package com.ruoyi.web.controller.hk;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.ruoyi.common.config.RuoYiConfig;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.file.FileUploadUtils;
import com.ruoyi.system.service.ISysNoticeService;
import com.sun.jna.Pointer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.text.SimpleDateFormat;
import java.util.Date;

@Component
public class AlarmDataParse {

    @Autowired
    private ISysNoticeService sysNoticeService;

    public static AlarmDataParse alarmDataParse;

    @PostConstruct
    public void init() {
        alarmDataParse = this;
        alarmDataParse.sysNoticeService = this.sysNoticeService;
    }

    public static void alarmDataHandle(int lCommand, HCNetSDK.NET_DVR_ALARMER pAlarmer, Pointer pAlarmInfo, int dwBufLen, Pointer pUser) {
/*        SysNotice sysNotice = new SysNotice();
        sysNotice.setNoticeTitle("1");
        sysNotice.setNoticeContent("1");
        sysNotice.setNoticeType("1");
        alarmDataParse.sysNoticeService.insertNotice(sysNotice);*/
        System.out.println("报警事件类型： lCommand:" + Integer.toHexString(lCommand));
        String sAlarmInfo = new String(pAlarmer.sDeviceIP).trim();
        //lCommand是传的报警类型
        switch (lCommand) {
            case HCNetSDK.COMM_ISAPI_ALARM: //ISAPI协议报警信息
                HCNetSDK.NET_DVR_ALARM_ISAPI_INFO struEventISAPI = new HCNetSDK.NET_DVR_ALARM_ISAPI_INFO();
                struEventISAPI.write();
                Pointer pEventISAPI = struEventISAPI.getPointer();
                pEventISAPI.write(0, pAlarmInfo.getByteArray(0, struEventISAPI.size()), 0, struEventISAPI.size());
                struEventISAPI.read();
                //报警数据类型：0- invalid，1- xml，2- json
                sAlarmInfo = "报警设备IP：" + sAlarmInfo + "：ISAPI协议报警信息, 数据格式:" + struEventISAPI.byDataType +
                        ", 图片个数:" + struEventISAPI.byPicturesNumber;
                System.out.println(sAlarmInfo);
                SimpleDateFormat sf1 = new SimpleDateFormat("yyyyMMddHHmmss");
                String curTime = sf1.format(new Date());
                //报警数据打印
                HCNetSDK.BYTE_ARRAY m_strISAPIData = new HCNetSDK.BYTE_ARRAY(struEventISAPI.dwAlarmDataLen);
                m_strISAPIData.write();
                Pointer pPlateInfo = m_strISAPIData.getPointer();
                pPlateInfo.write(0, struEventISAPI.pAlarmData.getByteArray(0, m_strISAPIData.size()), 0, m_strISAPIData.size());
                m_strISAPIData.read();
                //报警结果
                /*    {
                 *//*req, object, 事件内容, range:[,], desc:*//*
                "ipAddress": "172.6.64.7",
                    *//*req, string, 报警设备IPv4地址, const:, range:[,], enum:[], format:ipv4, mediaType:, pattern:, unit:, RAP:, desc:*//*
                    "ipv6Address": "null",
                    *//*opt, string, 报警设备IPv6地址, const:, range:[,], enum:[], format:ipv6, mediaType:, pattern:, unit:, RAP:, desc:*//*
                    "portNo": 80,
                    *//*opt, integer, 报警设备端口号, const:, enum:[], range:[1,65535], multipleOf:, step:, unit:, desc:*//*
                    "protocol": "HTTP",
                    *//*opt, string, 协议类型, const:, range:[0,64], enum:[], format:, mediaType:, pattern:, unit:, RAP:, desc:[HTTP#HTTP,HTTPS#HTTPS,EHome#EHome,OTAP#OTAP], 该字段无实际意义*//*
                    "macAddress": "01:17:24:45:D9:F4",
                    *//*opt, string, MAC地址, const:, range:[1,32], enum:[], format:, mediaType:, pattern:, unit:, RAP:, desc:*//*
                    "channelID": 1,
                    *//*req, integer, 触发报警的设备通道号, const:, enum:[], range:[1,65535], multipleOf:, step:, unit:, desc:触发的视频通道号（1、    在SDK透传ISAPI协议的时候，上传的是 私有协议对应的视频通道号；（2、    在萤石透传ISAPI协议的时候，上传的是 萤石协议对应的视频通道号；（3、    在ISUP透传ISAPI协议的时候，上传的是 ISUP协议对应的视频通道号；*//*
                    "channelName": "ABC",
                    *//*opt, string, 通道名称（监控点名称）, const:, range:[0,64], enum:[], format:, mediaType:, pattern:, unit:, RAP:, desc:与/ISAPI/Streaming/channels/<channelID>的<channelName>一致*//*
                    "dateTime": "2004-05-03T17:30:08+08:00",
                    *//*req, string, 报警触发时间, const:, range:[,], enum:[], format:date-time, mediaType:, pattern:, unit:, RAP:, desc:*//*
                    "activePostCount": 1,
                    *//*opt, integer, 同一个报警已经上传的次数, const:, enum:[], range:[1,2147483647], multipleOf:, step:, unit:, desc:事件触发频次脉冲事件 定义：事件持续触发（按照设备的检测频率），例如：移动侦测。瞬时事件 定义：区分目标，一个目标触发一次，例如：目标抓拍activePostCount  在脉冲事件 类型触发的时候，用于区分是否是同一触发源触发的事件。例如：移动侦测，按照设备检测频率会一直上传；如果触发源发生了变化，这个时候计数就可以重新开始了。这个可以作为事件触发频次的方式来集成；*//*
                    "eventType": "DialIndicatorReading",
                    *//*req, string, 事件类型, const:, range:[1,64], enum:[], format:, mediaType:, pattern:, unit:, RAP:, desc:表计识别*//*
                    "eventState": "active",
                    *//*req, string, 事件状态, const:, range:[,], enum:[active#有效事件, inactive#无效事件], format:, mediaType:, pattern:, unit:, RAP:, desc:针对持续性事件active – 表示有效事件（开始 或者 无过程状态也使用该字段）；inactive – 表示无效事件（结束）；remark:在心跳类型下，该字段赋值（表示心跳数据,10s上传一次）；*//*
                    "eventDescription": "DialIndicatorReading",
                    *//*req, string, 事件描述, const:, range:[1,128], enum:[], format:, mediaType:, pattern:, unit:, RAP:, desc:表计识别*//*
                    "deviceID": "test0123",
                    *//*opt, string, 设备ID, const:, range:[1,64], enum:[], format:, mediaType:, pattern:, unit:, RAP:, desc:ISUP协议接入时，deviceID为设备注册的ISUP设备ID；OTAP协议本地接入时，deviceID为设备注册的OTAP设备ID；OTAP萤石接入时，deviceID为设备注册萤石云的9位短序列号。*//*
                    "deviceUUID": "12345",
                    *//*opt, string, 设备编号,, const:, range:[1,128], enum:[], format:, mediaType:, pattern:, unit:, RAP:, desc:设备唯一标识，可通过协议/ISAPI/System/deviceInfo中的<deviceID>字段进行获取（部分设备支持配置deviceID参数）*//*
                    "isDataRetransmission": true,
                    *//*opt, boolean, 重传数据标记, const:, desc:由于网络异常等因素;导致的实时检测的数据上传失败;后设备异常因素恢复后重新上传当时的采集分析数据*//*
                    "UUID": "079f23cd-0988-459f-96f5-fa1c507dd07c",
                    *//*opt, string, 上传事件唯一标识, const:, range:[0,64], enum:[], format:, mediaType:, pattern:, unit:, RAP:, desc:*//*
                    "DialIndicatorReading":{
                *//*opt, object, 事件内容, range:[,], desc:*//*
                "sceneID": 1,
                        *//*ro, opt, integer, 场景ID, const:, enum:[], range:[1,16], multipleOf:, step:, unit:, desc:*//*
                        "ruleID": 1,
                        *//*ro, opt, integer, 规则ID, const:, enum:[], range:[1,16], multipleOf:, step:, unit:, desc:*//*
                        "tagSetID": "test",
                        *//*ro, opt, string, 标定集ID, const:, range:[1,64], enum:[], format:, mediaType:, pattern:, unit:, RAP:, desc:由平台维护，唯一表示一个标定集,desc:非标定分析任务不会返回*//*
                        "presetID": 1,
                        *//*ro, opt, integer, 预置点ID, const:, enum:[], range:[1,256], multipleOf:, step:, unit:, desc:*//*
                        "pictureID": "test",
                        *//*opt, string, 图片ID, const:, range:[1,32], enum:[], format:, mediaType:, pattern:, unit:, RAP:, desc:和提交通用图片分析任务时下发图片时附加的图片id对应,用于标识下发通用图片任务的图片*//*
                        "resultType": "dialIndicatorReading",
                        *//*ro, req, string, 分析结果类型, const:, range:[,], enum:[dialIndicatorReading#读表（正常状态）, dialIndicatorDefect#缺陷表（异常）], format:, mediaType:, pattern:, unit:, RAP:, desc:*//*
                        "alarmLevel": "general",
                        *//*opt, string, 告警等级, const:, range:[,], enum:[normal#正常, general#一般告警, serious#严重告警, emergency#危急告警], format:, mediaType:, pattern:, unit:, RAP:, desc:*//*
                        "dialIndicatorReading":{
                    *//*ro, opt, object, 读表类事件信息, range:[,], desc:*//*
                    "dialIndicatorAnalysisType": "tagged",
                            *//*opt, string, 表计读数分析类型, const:, range:[,], enum:[tagged#标定模式, unTagged#非标定模式], format:, mediaType:, pattern:, unit:, RAP:, desc:*//*
                            "dialIndicatorStatus": "success",
                            *//*opt, string, 读数状态, const:, range:[,], enum:[success#成功, failed#整张图失败], format:, mediaType:, pattern:, unit:, RAP:, desc:成功可能部分成功也可能全部成功,会返回读数信息。失败是整张图失败，不会返回读数信息（dialIndicatorNums,dialIndicatorParams）,没有该字段默认成功*//*
                            "readingFailedReason": 1,
                            *//*opt, integer, 读数失败原因, const:, enum:[0#未知, 1#标定异常, 2#相机偏转, 3#图像质量不佳, 5#未标定, 6#标定参数异常, 7#算法处理超时, 8#算法处理异常], range:[,], multipleOf:, step:, unit:, dependency:(dialIndicatorStatus,eq,failed), desc:当读数失败的时候返回*//*
                            "dialIndicatorNums": 1,
                            *//*ro, opt, integer, 表个数, const:, enum:[], range:[0,16], multipleOf:, step:, unit:, desc:*//*
                            "dialIndicatorParams":[
                    *//*ro, opt, array, 表信息列表, range:[0,16], uniqueItems:, desc:*//*
                    {
                        *//*opt, object, 表信息, range:[,], desc:*//*
                        "dialIndicatorID": 1,
                            *//*ro, opt, integer, 表ID, const:, enum:[], range:[1,120], multipleOf:, step:, unit:, desc:由于老设备这个参数的生成逻辑是按1，2，3递增的顺序生成的标识，而且考虑到删除表计后添加新的表计会覆盖被删除的标识，而且范围受限，所以不能作为表的标识，用32位UUID的meterID代替*//*
                            "meterID": "test",
                            *//*ro, opt, string, 表计ID, const:, range:[1,64], enum:[], format:, mediaType:, pattern:, unit:, RAP:, desc:表的标识,当手动下发添加表计的时候，由web生成（非用户填写），当自动标定的时候，由设备生成，最终算法库进行解析，作为表计的标识，建议使用UUID作为标识防止重复。平台可以通过查询表计识别事件中的meterID进行表计校验（是否为标定的表计，并且是否被删除）*//*
                            "meterName": "test",
                            *//*ro, opt, string, 表计名称, const:, range:[1,64], enum:[], format:, mediaType:, pattern:, unit:, RAP:, desc:*//*
                            "readingParams":{
                        *//*ro, opt, object, 读数表参数, range:[,], desc:*//*
                        "readingNums": 2,
                                *//*ro, opt, integer, 读数个数, const:, enum:[], range:[0,16], multipleOf:, step:, unit:, desc:*//*
                                "readingInfo":[
                        *//*ro, opt, array, 读数信息列表, range:[0,16], uniqueItems:, desc:*//*
                        {
                            *//*opt, object, 读数信息, range:[,], desc:*//*
                            "readingType": "pointer",
                                *//*ro, opt, string, 表类型, const:, range:[,], enum:[pointer#指针类, number#数字类, status#状态类, level#液位类], format:, mediaType:, pattern:, unit:, RAP:, desc:*//*
                                "targetRegion":[
                            *//*ro, opt, array, 目标区域, range:[4,10], uniqueItems:, desc:4~10边形,左下角坐标原点*//*
                            {
                                *//*req, object, 目标区域, range:[,], desc:*//*
                                "x": 0.12,
                                    *//*ro, req, number, x坐标, const:, enum:[], range:[0,1], multipleOf:, step:, unit:, desc:*//*
                                    "y": 0.12
                                *//*ro, req, number, y坐标, const:, enum:[], range:[0,1], multipleOf:, step:, unit:, desc:*//*
                            }
                                ],
                            "ROIRegion":[
                            *//*ro, opt, array, 感兴趣区域, range:[4,10], uniqueItems:, desc:4~10边形,左下角坐标原点*//*
                            {
                                *//*req, object, 感兴趣区域坐标, range:[,], desc:*//*
                                "x": 0.12,
                                    *//*ro, req, number, x坐标, const:, enum:[], range:[0,1], multipleOf:, step:, unit:, desc:*//*
                                    "y": 0.12
                                *//*ro, req, number, y坐标, const:, enum:[], range:[0,1], multipleOf:, step:, unit:, desc:*//*
                            }
                                ],
                            "readingResult": "test",
                                *//*ro, opt, string, 当前读数值, const:, range:[0,16], enum:[], format:, mediaType:, pattern:, unit:, RAP:, desc:readingType为指针类,数字类,液位类时该字段有效*//*
                                "readingConfidence": 80,
                                *//*ro, opt, integer, 读数置信度, const:, enum:[], range:[1,100], multipleOf:, step:, unit:, desc:*//*
                                "regionConfidence": 80,
                                *//*ro, opt, integer, 区域置信度, const:, enum:[], range:[1,100], multipleOf:, step:, unit:, desc:*//*
                                "statusResult": 1,
                                *//*ro, opt, integer, 状态表状态, const:, enum:[0#红灯亮, 1#红灯灭, 2#黄灯亮, 3#黄灯灭, 4#蓝灯亮, 5#蓝灯灭, 6#绿灯亮, 7#绿灯灭, 8#白灯亮, 9#白灯灭, 10#旋钮向左, 11#旋钮向左上, 12#旋钮向上, 13#旋钮向右上, 14#旋钮向右, 15#旋钮向右下, 16#旋钮向下, 17#旋钮向左下, 18#空开向上, 19#空开向下, 20#压板开, 21#压板合, 22#硅胶筒变色, 23#硅胶筒未变色, 24#字符分, 25#字符合, 26#字符0, 27#字符1, 28#字符ON, 29#字符OFF, 30#字符已储能, 31#字符未储能, 32#断路器分, 33#断路器合, 34#断路器0, 35#断路器1, 36#断路器ON, 37#断路器OFF, 38#断路器已储能, 39#断路器未储能, 40#刀闸开, 41#刀闸关, 42#开集类型关, 43#开集类别开, -1#需要解析classifiedStatusResult状态], range:[,], multipleOf:, step:, unit:, desc:状态表的情况下，为了兼容老平台，设备必须返回该字段，如果枚举中没有对应的状态，需将其置为-1。平台为了兼容老设备，平台也需要先解析这个字段，这个字段为-1，则应该解析下面拆分的状态（pilotLampState,eightPositionSelectorKnobState等）。readingType为状态类时有效*//*
                                "classifiedStatusResult":{
                            *//*opt, object, 分类后的状态结果, range:[,], dependency:(statusResult,eq,44), desc:*//*
                            "pilotLampState": "0",
                                    *//*ro, opt, string, 指示灯当前读数值, const:, range:[,], enum:[0#亮, 1#灭, 2#红灯亮, 3#红灯灭, 4#黄灯亮, 5#黄灯灭, 6#蓝灯亮, 7#蓝灯灭, 8#绿灯亮, 9#绿灯灭, 10#白灯亮, 11#白灯灭, 100#亮横向, 101#亮竖向, 102#红灯亮横向, 103#红灯亮竖向, 104#黄灯亮横向, 105#黄灯亮竖向, 106#蓝灯亮横向, 107#蓝灯亮竖向, 108#绿灯亮横向, 109#绿灯亮竖向, 110#白灯亮横向, 111#白灯亮竖向], format:, mediaType:, pattern:, unit:, RAP:, desc:*//*
                                    "eightPositionSelectorKnobState": "0",
                                    *//*ro, opt, string, 8朝向旋钮当前读数值, const:, range:[,], enum:[0#旋钮向左, 1#旋钮向左上, 2#旋钮向上, 3#旋钮向右上, 4#旋钮向右, 5#旋钮向右下, 6#旋钮向下, 7#旋钮向左下], format:, mediaType:, pattern:, unit:, RAP:, desc:*//*
                                    "airSwitchCircuitBreakerState": "0",
                                    *//*ro, opt, string, 空开当前读数值, const:, range:[,], enum:[0#空开向下, 1#空开向上], format:, mediaType:, pattern:, unit:, RAP:, desc:*//*
                                    "relayProtectionControllerState": "0",
                                    *//*ro, opt, string, 压板当前读数值, const:, range:[,], enum:[0#压板开, 1#压板合], format:, mediaType:, pattern:, unit:, RAP:, desc:*//*
                                    "silicaGelBreatherState": "0",
                                    *//*ro, opt, string, 硅胶筒当前读数值, const:, range:[,], enum:[0#硅胶筒未变色, 1#硅胶筒变色], format:, mediaType:, pattern:, unit:, RAP:, desc:*//*
                                    "charactersState": "0",
                                    *//*ro, opt, string, 字符当前读数值, const:, range:[,], enum:[0#字符分, 1#字符合, 2#字符0, 3#字符1, 4#字符OFF, 5#字符ON, 6#字符未储能, 7#字符已储能], format:, mediaType:, pattern:, unit:, RAP:, desc:*//*
                                    "circuitBreakerState": "0",
                                    *//*ro, opt, string, 断路器当前读数值, const:, range:[,], enum:[0#断路器分, 1#断路器合, 2#断路器0, 3#断路器1, 4#断路器OFF, 5#断路器ON, 6#断路器未储能, 7#断路器已储能], format:, mediaType:, pattern:, unit:, RAP:, desc:*//*
                                    "knifeSwitchState": "0",
                                    *//*ro, opt, string, 刀闸当前读数值, const:, range:[,], enum:[0#刀闸开（分）, 1#刀闸关（合）], format:, mediaType:, pattern:, unit:, RAP:, desc:*//*
                                    "openSetTypeState": "0"
                            *//*ro, opt, string, 开集类型当前读数值, const:, range:[,], enum:[0#开集类型开, 1#开集类别关], format:, mediaType:, pattern:, unit:, RAP:, desc:*//*
                        },
                            "mapName": "undefined",
                                *//*opt, string, 映射名称, const:, range:[1,128], enum:[], format:, mediaType:, pattern:, unit:, RAP:, desc:由报警结果全局映射或部分映射配置,设备上报时按映射规则将状态转为对应的映射名称*//*
                                "readingFailedReason": 1,
                                *//*opt, integer, 读数失败原因, const:, enum:[0#未知, 1#标定异常, 2#相机偏转, 3#图像质量不佳], range:[,], multipleOf:, step:, unit:, desc:当读数失败的时候返回,不能输出读数*//*
                                "readingWarningInfo": 1
                            *//*opt, integer, 读数警告提示, const:, enum:[0#未知, 1#标定异常, 2#相机偏转, 3#图像质量不佳], range:[,], multipleOf:, step:, unit:, desc:算法针对角度变化会有一定的修正,能输出读数,希望通过该信息提示用户相机发生偏转等信息*//*
                        }
                        ]
                    }
                    }
            ]
                },
                "dialIndicatorDefect":{
                    *//*ro, opt, object, 缺陷表事件信息, range:[,], desc:*//*
                    "dialIndicatorNums": 0,
                            *//*ro, opt, integer, 缺陷表个数, const:, enum:[], range:[0,32], multipleOf:, step:, unit:, desc:*//*
                            "dialIndicatorParams":[
                    *//*ro, opt, array, 缺陷表信息列表, range:[0,16], uniqueItems:, desc:*//*
                    {
                        *//*opt, object, 缺陷表信息, range:[,], desc:*//*
                        "defectMainType": 1,
                            *//*ro, opt, integer, 实体类型, const:, enum:[1#表盘, 2#表计外壳, 3#硅胶筒, 4#呼吸器, 5#绝缘子, 6#变电箱体, 7#盖板, 8#压板, 9#人体, 10#头部, 11#鸟巢, 12#烟体, 13#挂空悬浮物, 14#地面油污], range:[,], multipleOf:, step:, unit:, desc:*//*
                            "targetRegion":[
                        *//*ro, opt, array, 目标区域, range:[4,10], uniqueItems:, desc:4~10边形,左下角坐标原点*//*
                        {
                            *//*req, object, 目标区域, range:[,], desc:*//*
                            "x": 0.12,
                                *//*ro, req, number, x坐标, const:, enum:[], range:[0,1], multipleOf:, step:, unit:, desc:*//*
                                "y": 0.12
                            *//*ro, req, number, y坐标, const:, enum:[], range:[0,1], multipleOf:, step:, unit:, desc:*//*
                        }
                    ],
                        "defectNums": 2,
                            *//*ro, opt, integer, 缺陷个数, const:, enum:[], range:[0,16], multipleOf:, step:, unit:, desc:*//*
                            "defectInfo":[
                        *//*ro, opt, array, 缺陷信息列表, range:[0,16], uniqueItems:, desc:*//*
                        {
                            *//*opt, object, 缺陷信息, range:[,], desc:*//*
                            "defectType": 1,
                                *//*ro, opt, integer, int, const:, enum:[0#默认值, 1#表盘正常, 2#表盘模糊, 3#表盘破损, 4#表盘读数异常, 5#表计外壳正常, 6#表计外壳破损, 7#硅胶缺陷类型：硅胶筒正常, 8#表计外壳正常（和5重复）以5为标准, 9#硅胶变色, 10#呼吸器缺陷类型：呼吸器油封油位正常, 11#呼吸器油封油位异常, 12#绝缘子缺陷类型：绝缘子正常, 13#绝缘子异常, 14#变电箱体缺陷类型：变电箱体闭合正常, 15#变电箱体闭合异常, 16#盖板正常, 17#盖板破损, 18#压板缺陷类型：压板开, 19#压板合, 20#人体缺陷类型：穿工装, 21#未穿工装, 22#头部缺陷类型：戴安全帽, 23#未戴安全帽, 24#硅胶筒破损, 25#鸟巢, 26#烟体, 27#挂空悬浮物, 28#地面油污, 29#呼吸器油封破损, 30#导线断股, 31#电容器本体鼓肚, 32#膨胀器冲顶, 33#设备烟火, 34#部件表面油污], range:[,], multipleOf:, step:, unit:, desc:*//*
                                "confidence": 80
                            *//*ro, opt, integer, 检测置信度, const:, enum:[], range:[1,100], multipleOf:, step:, unit:, desc:*//*
                        }
                    ]
                    }
            ]
                },
                "dialIndicatorPicPath":{
                    *//*opt, object, 表计检测图片文件存储信息, range:[,], desc:*//*
                    "resourcesContentType": "binary",
                            *//*req, string, 资源传输类型, const:, range:[,], enum:[url#url方式传输, binary#二进制方式传输, base64#base64编码的图片], format:, mediaType:, pattern:, unit:, RAP:, desc:资源传输类型,当设备返回的报警报文中带有额外资源（比如图片）时,该节点必须返回。使用URI从设备下载文件的时候，需要进行认证，认证方式和登录设备的方式保持一致。如果该URI的参数中有token(?token=)可以直接请求，除token以外的其他方式，认证方式为登录设备的方式。设备返回URI中的IP和Port，仅代表设备直连网络下可以被访问，建议集成方基于设备网络部署，替换URI中的IP和Port。如果返回的URI的前缀为“/pic”,代表为武汉云存储的URI，设备自定义的URI不使用该前缀。*//*
                            "resourcesContent": "",
                            *//*req, string, 资源标识ID, const:, range:[0,262000], enum:[], format:, mediaType:, pattern:, unit:, RAP:, desc:当设备返回的报警报文中带有额外资源（比如图片）时,该节点必须返回;当resourcesContentType为binary时,该节点与图片的Content-ID严格对应;当resourcesContentType为url时,该节点填写具体的url; 当resourcesContentType 为base64时，表示经过base64编码后的数据*//*
                            "pictureResolution":{
                        *//*opt, object, 图片资源的分辨率, range:[,], desc:归一化坐标转换成实际分辨率时依赖此节点。*//*
                        "height": 1,
                                *//*req, integer, 分辨率高, const:, enum:[], range:[1,65535], multipleOf:, step:, unit:px, desc:*//*
                                "width": 1
                        *//*req, integer, 分辨率框, const:, enum:[], range:[1,65535], multipleOf:, step:, unit:px, desc:*//*
                    }
                },
                "isResultOverlay": false
                *//*ro, opt, boolean, 是否叠加信息已显示在图片上, const:, desc:对应/ISAPI/Intelligent/dialIndicatorReading/DialIndicatorReadingResultOverlay?format=json,开启表计识别结果叠加后并不会直接显示在图片上，还需要平台自己处理或算法库处理后才能显示在图片上，有该字段表示字体信息已叠加在图片上，不需要进一步处理*//*
            }
            }*/
                String result = new String(m_strISAPIData.byValue).trim() + "\n";

                JSONObject jsonObject = JSON.parseObject(result);
                Object ipAddress = jsonObject.get("ipAddress");

                //打印报警数据
                System.out.println(new String(m_strISAPIData.byValue).trim() + "\n");
                //图片数据保存
                for (int i = 0; i < struEventISAPI.byPicturesNumber; i++) {
                    HCNetSDK.NET_DVR_ALARM_ISAPI_PICDATA struPicData = new HCNetSDK.NET_DVR_ALARM_ISAPI_PICDATA();
                    struPicData.write();
                    Pointer pPicData = struPicData.getPointer();
                    pPicData.write(0, struEventISAPI.pPicPackData.getByteArray(i * struPicData.size(), struPicData.size()), 0, struPicData.size());
                    struPicData.read();
                    FileOutputStream fout;
                    try {
                        // 上传文件路径
                        String filePath = RuoYiConfig.getUploadPath();
                        //图片名称
                        String filename = new String(pAlarmer.sDeviceIP).trim() + "_" + curTime +
                                "_ISAPIPic_" + i + "_" + new String(struPicData.szFilename).trim();
                        //图片名称进行编码
                        filename = StringUtils.format("{}/{}.{}", DateUtils.datePath(),
                                filename, "jpg");
                        //路径不存在则生成
                        FileUploadUtils.getAbsoluteFile(filePath, filename);
                        //最终生成的文件名称
                        String fileName = filePath + File.separator + filename;
                        fout = new FileOutputStream(fileName);
                        System.out.println("图片路径" + filename);
                        //将字节写入文件
                        long offset = 0;
                        ByteBuffer buffers = struPicData.pPicData.getByteBuffer(offset, struPicData.dwPicLen);
                        byte[] bytes = new byte[struPicData.dwPicLen];
                        buffers.rewind();
                        buffers.get(bytes);
                        fout.write(bytes);
                        fout.close();
                    } catch (FileNotFoundException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    } catch (IOException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }
                break;
            case HCNetSDK.COMM_VCA_ALARM:  // 智能检测通用报警(Json或者XML数据结构)
                sAlarmInfo = new String(pAlarmer.sDeviceIP);
                //报警数据类型：0- invalid，1- xml，2- json
                sAlarmInfo = "报警设备IP：" + sAlarmInfo;
                System.out.println(sAlarmInfo);

                SimpleDateFormat sf0 = new SimpleDateFormat("yyyyMMddHHmmss");
                String curTime0 = sf0.format(new Date());
                FileOutputStream Data;
                String jsonfile = "../pic" + new String(pAlarmer.sDeviceIP).trim() + curTime0 + "_VCA_ALARM_" + ".json";
                try {
                    Data = new FileOutputStream(jsonfile);
                    //将字节写入文件
                    ByteBuffer dataBuffer = pAlarmInfo.getByteBuffer(0, dwBufLen);
                    byte[] dataByte = new byte[dwBufLen];
                    dataBuffer.rewind();
                    dataBuffer.get(dataByte);
                    Data.write(dataByte);
                    Data.close();
                } catch (FileNotFoundException e) {
                    e.printStackTrace();
                } catch (IOException e) {
                    e.printStackTrace();
                }
                break;
            default:
                System.out.println("报警类型" + Integer.toHexString(lCommand));
                break;
        }
    }
}
