

package com.ruoyi.alarm;



import com.ruoyi.Common.osSelect;
import com.ruoyi.hksdk.HCNetSDK;
import com.sun.jna.Native;
import com.sun.jna.Pointer;
import org.springframework.boot.CommandLineRunner;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;

@Component
public class Alarm implements CommandLineRunner {

    static HCNetSDK hCNetSDK = null;
    static int lUserID = -1;//用户句柄 实现对设备登录
    static int lAlarmHandle =-1;//报警布防句柄
    static int lAlarmHandle_V50 = -1; //v50报警布防句柄
    static int lListenHandle = -1;//报警监听句柄
    static FMSGCallBack_V31 fMSFCallBack_V31 = null;
    static FMSGCallBack fMSFCallBack=null;


    /**
     * 动态库加载
     *
     * @return
     */
    private static boolean createSDKInstance() {
        if (hCNetSDK == null) {
            synchronized (HCNetSDK.class) {
                String strDllPath = "";
                try {
                    if (osSelect.isWindows())
                        //win系统加载库路径
                        strDllPath = System.getProperty("user.dir") + "\\ruoyi-admin\\lib\\HCNetSDK.dll";
                    else if (osSelect.isLinux())
                        //Linux系统加载库路径
                        strDllPath = System.getProperty("user.dir") + "/lib/libhcnetsdk.so";
                    hCNetSDK = (HCNetSDK) Native.loadLibrary(strDllPath, HCNetSDK.class);
                } catch (Exception ex) {
                    System.out.println("loadLibrary: " + strDllPath + " Error: " + ex.getMessage());
                    return false;
                }
            }
        }
        return true;
    }

    @Async
    @Override
    public void run(String... args) throws Exception {
        if (hCNetSDK == null) {
            if (!createSDKInstance()) {
                System.out.println("Load SDK fail");
                return;
            }
        }
        //linux系统建议调用以下接口加载组件库
        if (osSelect.isLinux()) {
            HCNetSDK.BYTE_ARRAY ptrByteArray1 = new HCNetSDK.BYTE_ARRAY(256);
            HCNetSDK.BYTE_ARRAY ptrByteArray2 = new HCNetSDK.BYTE_ARRAY(256);
            //这里是库的绝对路径，请根据实际情况修改，注意改路径必须有访问权限
            String strPath1 = System.getProperty("user.dir") + "/lib/libcrypto.so.1.0.0";
            String strPath2 = System.getProperty("user.dir") + "/lib/libssl.so";

            System.arraycopy(strPath1.getBytes(), 0, ptrByteArray1.byValue, 0, strPath1.length());
            ptrByteArray1.write();
            hCNetSDK.NET_DVR_SetSDKInitCfg(3, ptrByteArray1.getPointer());

            System.arraycopy(strPath2.getBytes(), 0, ptrByteArray2.byValue, 0, strPath2.length());
            ptrByteArray2.write();
            hCNetSDK.NET_DVR_SetSDKInitCfg(4, ptrByteArray2.getPointer());

            String strPathCom = System.getProperty("user.dir") + "/lib/";
            HCNetSDK.NET_DVR_LOCAL_SDK_PATH struComPath = new HCNetSDK.NET_DVR_LOCAL_SDK_PATH();
            System.arraycopy(strPathCom.getBytes(), 0, struComPath.sPath, 0, strPathCom.length());
            struComPath.write();
            hCNetSDK.NET_DVR_SetSDKInitCfg(2, struComPath.getPointer());
        }

        /**初始化*/
        hCNetSDK.NET_DVR_Init();
        /**加载日志*/
        hCNetSDK.NET_DVR_SetLogToFile(3, "./sdklog", false);
        //设置报警回调函数
        if (fMSFCallBack_V31 == null) {
            fMSFCallBack_V31 = new FMSGCallBack_V31();
            Pointer pUser = null;
            if (!hCNetSDK.NET_DVR_SetDVRMessageCallBack_V31(fMSFCallBack_V31, pUser)) {
                System.out.println("设置回调函数失败!");
                return;
            } else {
                //hCNetSDK.NET_DVR_SetDVRMessageCallBack_V50(HCNetSDK.COMM_ALARM_PDC,new FMSGCallBack_V31(),null );
                System.out.println("设置回调函数成功!");
            }
        }
        /** 设备上传的报警信息是COMM_VCA_ALARM(0x4993)类型，
         在SDK初始化之后增加调用NET_DVR_SetSDKLocalCfg(enumType为NET_DVR_LOCAL_CFG_TYPE_GENERAL)设置通用参数NET_DVR_LOCAL_GENERAL_CFG的byAlarmJsonPictureSeparate为1，
         将Json数据和图片数据分离上传，这样设置之后，报警布防回调函数里面接收到的报警信息类型为COMM_ISAPI_ALARM(0x6009)，
         报警信息结构体为NET_DVR_ALARM_ISAPI_INFO（与设备无关，SDK封装的数据结构），更便于解析。*/

        HCNetSDK.NET_DVR_LOCAL_GENERAL_CFG struNET_DVR_LOCAL_GENERAL_CFG = new HCNetSDK.NET_DVR_LOCAL_GENERAL_CFG();
        struNET_DVR_LOCAL_GENERAL_CFG.byAlarmJsonPictureSeparate = 1;   //设置JSON透传报警数据和图片分离
        struNET_DVR_LOCAL_GENERAL_CFG.write();
        Pointer pStrNET_DVR_LOCAL_GENERAL_CFG = struNET_DVR_LOCAL_GENERAL_CFG.getPointer();
        hCNetSDK.NET_DVR_SetSDKLocalCfg(17, pStrNET_DVR_LOCAL_GENERAL_CFG);

        int userId = login_V40( "60.171.161.56", (short) 9800, "admin", "zxy@7000");  //登录设备
        System.out.println("设备通道号"+userId);

        Alarm.setAlarm();//报警布防，和报警监听二选一即可

//        Alarm.startListen("10.16.36.108",(short)7200);//报警监听，不需要登陆设备

        //等待过程中，如果设备上传报警信息，在报警回调函数里面接收和处理报警信息
        /*Timer timer = new Timer();// 实例化Timer类
        timer.schedule(new TimerTask() {
            public void run() {
                //撤销布防上传通道
                if (! hCNetSDK.NET_DVR_CloseAlarmChan_V30(lAlarmHandle))
                {
                    System.out.println("! hCNetSDK.NET_DVR_CloseAlarmChan_V31(lAlarmHandle)\n"+ hCNetSDK.NET_DVR_GetLastError() +"\n" +hCNetSDK.NET_DVR_GetErrorMsg(null) );
                    hCNetSDK.NET_DVR_Logout(lUserID);
                    hCNetSDK. NET_DVR_Cleanup();
                    return;
                }

                //注销用户
                hCNetSDK.NET_DVR_Logout(lUserID);
                //释放SDK资源
                hCNetSDK.NET_DVR_Cleanup();
                this.cancel();
                System.gc();//主动回收垃圾
            }
        }, 2 * 60 * 1000 );// 这里毫秒*/

        /*System.out.println("1111111");
        while (true) {
            //这里加入控制台输入控制，是为了保持连接状态，当输入Y表示布防结束
            System.out.print("请选择是否撤出布防(Y/N)：\n");
            Scanner input = new Scanner(System.in);
            String str = input.next();
            if (str.equals("Y")) {
                break;
            }
        }
        Alarm.logout();
        //释放SDK
        hCNetSDK.NET_DVR_Cleanup();
        return;*/
    }




    /**
     * @param args
     */
   /* public static void main(String[] args) throws InterruptedException {

        if (hCNetSDK == null) {
            if (!createSDKInstance()) {
                System.out.println("Load SDK fail");
                return;
            }
        }
        //linux系统建议调用以下接口加载组件库
        if (osSelect.isLinux()) {
            HCNetSDK.BYTE_ARRAY ptrByteArray1 = new HCNetSDK.BYTE_ARRAY(256);
            HCNetSDK.BYTE_ARRAY ptrByteArray2 = new HCNetSDK.BYTE_ARRAY(256);
            //这里是库的绝对路径，请根据实际情况修改，注意改路径必须有访问权限
            String strPath1 = System.getProperty("user.dir") + "/lib/libcrypto.so.1.1";
            String strPath2 = System.getProperty("user.dir") + "/lib/libssl.so.1.1";

            System.arraycopy(strPath1.getBytes(), 0, ptrByteArray1.byValue, 0, strPath1.length());
            ptrByteArray1.write();
            hCNetSDK.NET_DVR_SetSDKInitCfg(3, ptrByteArray1.getPointer());

            System.arraycopy(strPath2.getBytes(), 0, ptrByteArray2.byValue, 0, strPath2.length());
            ptrByteArray2.write();
            hCNetSDK.NET_DVR_SetSDKInitCfg(4, ptrByteArray2.getPointer());

            String strPathCom = System.getProperty("user.dir") + "/lib/";
            HCNetSDK.NET_DVR_LOCAL_SDK_PATH struComPath = new HCNetSDK.NET_DVR_LOCAL_SDK_PATH();
            System.arraycopy(strPathCom.getBytes(), 0, struComPath.sPath, 0, strPathCom.length());
            struComPath.write();
            hCNetSDK.NET_DVR_SetSDKInitCfg(2, struComPath.getPointer());
        }

        *//**初始化*//*
        hCNetSDK.NET_DVR_Init();
        *//**加载日志*//*
        hCNetSDK.NET_DVR_SetLogToFile(3, "./sdklog", false);
        //设置报警回调函数
        if (fMSFCallBack_V31 == null) {
            fMSFCallBack_V31 = new FMSGCallBack_V31();
            Pointer pUser = null;
            if (!hCNetSDK.NET_DVR_SetDVRMessageCallBack_V31(fMSFCallBack_V31, pUser)) {
                System.out.println("设置回调函数失败!");
                return;
            } else {
                //hCNetSDK.NET_DVR_SetDVRMessageCallBack_V50(HCNetSDK.COMM_ALARM_PDC,new FMSGCallBack_V31(),null );
                System.out.println("设置回调函数成功!");
            }
        }
        *//** 设备上传的报警信息是COMM_VCA_ALARM(0x4993)类型，
         在SDK初始化之后增加调用NET_DVR_SetSDKLocalCfg(enumType为NET_DVR_LOCAL_CFG_TYPE_GENERAL)设置通用参数NET_DVR_LOCAL_GENERAL_CFG的byAlarmJsonPictureSeparate为1，
         将Json数据和图片数据分离上传，这样设置之后，报警布防回调函数里面接收到的报警信息类型为COMM_ISAPI_ALARM(0x6009)，
         报警信息结构体为NET_DVR_ALARM_ISAPI_INFO（与设备无关，SDK封装的数据结构），更便于解析。*//*

        HCNetSDK.NET_DVR_LOCAL_GENERAL_CFG struNET_DVR_LOCAL_GENERAL_CFG = new HCNetSDK.NET_DVR_LOCAL_GENERAL_CFG();
        struNET_DVR_LOCAL_GENERAL_CFG.byAlarmJsonPictureSeparate = 1;   //设置JSON透传报警数据和图片分离
        struNET_DVR_LOCAL_GENERAL_CFG.write();
        Pointer pStrNET_DVR_LOCAL_GENERAL_CFG = struNET_DVR_LOCAL_GENERAL_CFG.getPointer();
        hCNetSDK.NET_DVR_SetSDKLocalCfg(17, pStrNET_DVR_LOCAL_GENERAL_CFG);

        Alarm.login_V40( "114.99.127.243", (short) 1048, "admin", "lsly168S+");  //登录设备

        Alarm.setAlarm();//报警布防，和报警监听二选一即可

//        Alarm.startListen("10.16.36.108",(short)7200);//报警监听，不需要登陆设备

        //等待过程中，如果设备上传报警信息，在报警回调函数里面接收和处理报警信息
        *//*Timer timer = new Timer();// 实例化Timer类
        timer.schedule(new TimerTask() {
            public void run() {
                //撤销布防上传通道
                if (! hCNetSDK.NET_DVR_CloseAlarmChan_V30(lAlarmHandle))
                {
                    System.out.println("! hCNetSDK.NET_DVR_CloseAlarmChan_V31(lAlarmHandle)\n"+ hCNetSDK.NET_DVR_GetLastError() +"\n" +hCNetSDK.NET_DVR_GetErrorMsg(null) );
                    hCNetSDK.NET_DVR_Logout(lUserID);
                    hCNetSDK. NET_DVR_Cleanup();
                    return;
                }

                //注销用户
                hCNetSDK.NET_DVR_Logout(lUserID);
                //释放SDK资源
                hCNetSDK.NET_DVR_Cleanup();
                this.cancel();
                System.gc();//主动回收垃圾
            }
        }, 2 * 60 * 1000 );// 这里毫秒*//*

        System.out.println("1111111");
        while (true) {
            //这里加入控制台输入控制，是为了保持连接状态，当输入Y表示布防结束
            System.out.print("请选择是否撤出布防(Y/N)：\n");
            Scanner input = new Scanner(System.in);
            String str = input.next();
            if (str.equals("Y")) {
                break;
            }
        }
        Alarm.logout();
        //释放SDK
        hCNetSDK.NET_DVR_Cleanup();
        return;
    }*/


    /**
     * 设备登录V40 与V30功能一致
     * @param ip   设备IP
     * @param port SDK端口，默认设备的8000端口
     * @param user 设备用户名
     * @param psw  设备密码
     */
    public static int login_V40(String ip, short port, String user, String psw) {
        //注册
        HCNetSDK.NET_DVR_USER_LOGIN_INFO m_strLoginInfo = new HCNetSDK.NET_DVR_USER_LOGIN_INFO();//设备登录信息
        HCNetSDK.NET_DVR_DEVICEINFO_V40 m_strDeviceInfo = new HCNetSDK.NET_DVR_DEVICEINFO_V40();//设备信息

        String m_sDeviceIP = ip;//设备ip地址
        m_strLoginInfo.sDeviceAddress = new byte[HCNetSDK.NET_DVR_DEV_ADDRESS_MAX_LEN];
        System.arraycopy(m_sDeviceIP.getBytes(), 0, m_strLoginInfo.sDeviceAddress, 0, m_sDeviceIP.length());

        String m_sUsername = user;//设备用户名
        m_strLoginInfo.sUserName = new byte[HCNetSDK.NET_DVR_LOGIN_USERNAME_MAX_LEN];
        System.arraycopy(m_sUsername.getBytes(), 0, m_strLoginInfo.sUserName, 0, m_sUsername.length());

        String m_sPassword = psw;//设备密码
        m_strLoginInfo.sPassword = new byte[HCNetSDK.NET_DVR_LOGIN_PASSWD_MAX_LEN];
        System.arraycopy(m_sPassword.getBytes(), 0, m_strLoginInfo.sPassword, 0, m_sPassword.length());

        m_strLoginInfo.wPort = port;
        m_strLoginInfo.bUseAsynLogin = false; //是否异步登录：0- 否，1- 是
        m_strLoginInfo.byLoginMode=0;  //ISAPI登录
        m_strLoginInfo.write();

        lUserID = hCNetSDK.NET_DVR_Login_V40(m_strLoginInfo, m_strDeviceInfo);
        if (lUserID== -1) {
            System.out.println("登录失败，错误码为" + hCNetSDK.NET_DVR_GetLastError());
            return lUserID;
        } else {
            System.out.println(ip + ":设备登录成功！");
            return lUserID;
        }
    }

    /**
     * 控制道闸
     *  boolean a=HCNetSDK.NET_DVR_RemoteControl(tdh, 3128,  name, cfg.size());
     */
    public static boolean controlsDz(int lUserID, int dwCommand, Pointer lpInBuffer, int dwInBufferSize){
        return hCNetSDK.NET_DVR_RemoteControl(lUserID, dwCommand,  lpInBuffer, dwInBufferSize);
    }


    /**
     * 控制门禁
     *  boolean a=HCNetSDK.NET_DVR_RemoteControl(tdh, 3128,  name, cfg.size());
     */
    public static boolean controlGateway(int lUserID, int dwCommand,  int dwInBufferSize){
        return hCNetSDK.NET_DVR_ControlGateway(lUserID, dwCommand,  dwInBufferSize);
    }

    /**
     * 控制道闸失败
     *
     */
    public static int controlsDzError(){
        return hCNetSDK.NET_DVR_GetLastError();
    }

    /**
     * 注销用户
     *
     */
    public static boolean logout(int lUserID){
        return hCNetSDK.NET_DVR_Logout(lUserID);
    }

    /**
     * 释放SDK资源
     *
     */
    public static boolean cleanup(){
        return hCNetSDK.NET_DVR_Cleanup();
    }

    /**
     * 设备登录V30
     *
     * @param ip   设备IP
     * @param port SDK端口，默认设备的8000端口
     * @param user 设备用户名
     * @param psw  设备密码
     */
    public static void login_V30(String ip, short port, String user, String psw) {
        HCNetSDK.NET_DVR_DEVICEINFO_V30 m_strDeviceInfo = new HCNetSDK.NET_DVR_DEVICEINFO_V30();
        lUserID = hCNetSDK.NET_DVR_Login_V30(ip, port, user, psw, m_strDeviceInfo);
        System.out.println("UsID:" + lUserID);
        if ((lUserID == -1) || (lUserID == 0xFFFFFFFF)) {
            System.out.println("登录失败，错误码为" + hCNetSDK.NET_DVR_GetLastError());
            return;
        } else {
            System.out.println(ip + ":设备登录成功！");
            return;
        }
    }

    /**
     * 报警布防接口
     *
     * @param
     */
    public static void setAlarm() {
        if (lAlarmHandle < 0)//尚未布防,需要布防
        {
            //报警布防参数设置
            HCNetSDK.NET_DVR_SETUPALARM_PARAM m_strAlarmInfo = new HCNetSDK.NET_DVR_SETUPALARM_PARAM();
            m_strAlarmInfo.dwSize = m_strAlarmInfo.size();
            m_strAlarmInfo.byLevel = 1;  //布防等级
            m_strAlarmInfo.byAlarmInfoType = 1;   // 智能交通报警信息上传类型：0- 老报警信息（NET_DVR_PLATE_RESULT），1- 新报警信息(NET_ITS_PLATE_RESULT)
            m_strAlarmInfo.byDeployType = 0;   //布防类型：0-客户端布防，1-实时布防
            m_strAlarmInfo.write();
            lAlarmHandle= hCNetSDK.NET_DVR_SetupAlarmChan_V41(lUserID, m_strAlarmInfo);
            System.out.println("lAlarmHandle: " + lAlarmHandle);
            if (lAlarmHandle == -1) {
                System.out.println("布防失败，错误码为" + hCNetSDK.NET_DVR_GetLastError());
                return;
            } else {
                System.out.println("布防成功");

            }
        } else {

            System.out.println("设备已经布防，请先撤防！");
        }
        return;

    }


    /**
     * 报警布防V50接口，功能和V41一致
     *
     * @param
     */
    public static void setAlarm_V50() {

        if (lAlarmHandle_V50 < 0)//尚未布防,需要布防
        {
            //报警布防参数设置
            HCNetSDK.NET_DVR_SETUPALARM_PARAM_V50 m_strAlarmInfo = new HCNetSDK.NET_DVR_SETUPALARM_PARAM_V50();
            m_strAlarmInfo.dwSize = m_strAlarmInfo.size();
            m_strAlarmInfo.byLevel = 1;  //布防等级
            m_strAlarmInfo.byAlarmInfoType = 1;   // 智能交通报警信息上传类型：0- 老报警信息（NET_DVR_PLATE_RESULT），1- 新报警信息(NET_ITS_PLATE_RESULT)
            m_strAlarmInfo.byDeployType = 1;   //布防类型 0：客户端布防 1：实时布防
            m_strAlarmInfo.write();
            lAlarmHandle = hCNetSDK.NET_DVR_SetupAlarmChan_V50(lUserID, m_strAlarmInfo, Pointer.NULL, 0);
            System.out.println("lAlarmHandle: " + lAlarmHandle);
            if (lAlarmHandle== -1) {
                System.out.println("布防失败，错误码为" + hCNetSDK.NET_DVR_GetLastError());
                return;
            } else {
                System.out.println("布防成功");

            }

        } else {

            System.out.println("设备已经布防，请先撤防！");
        }
        return;

    }


    /**
     * 开启监听
     *
     * @param ip   监听IP
     * @param port 监听端口
     */
    public static void startListen(String ip, short port) {
        if (fMSFCallBack == null) {
            fMSFCallBack = new FMSGCallBack();
        }
        lListenHandle = hCNetSDK.NET_DVR_StartListen_V30(ip, port,  fMSFCallBack, null);
        if (lListenHandle == -1) {
            System.out.println("监听失败" + hCNetSDK.NET_DVR_GetLastError());
            return;
        } else {
            System.out.println("监听成功");
        }
    }

    /**
     * 设备撤防，设备注销
     *
     * @param
     */
    public static void logout() {

        if (lAlarmHandle > -1) {
            if (hCNetSDK.NET_DVR_CloseAlarmChan(lAlarmHandle)) {
                System.out.println("撤防成功");
            }
        }
        if (lListenHandle > -1) {
            if (hCNetSDK.NET_DVR_StopListen_V30(lListenHandle)) {
                System.out.println("停止监听成功");
            }
        }
        if (lUserID>-1)
        {
            if (hCNetSDK.NET_DVR_Logout(lUserID)) {
                System.out.println("注销成功");
            }
        }



        return;
    }



}
