MyTask.java 18.9 KB
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 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457
package com.example.dahua;

import com.example.dahua.bean.*;
import com.example.dahua.dao.UserDao;
import com.example.dahua.lib.NetSDKLib;
import com.example.dahua.lib.ToolKits;
import com.example.dahua.lib.Utils;
import com.example.dahua.module.AutoRegisterModule;
import com.example.dahua.module.GateModule;
import com.example.dahua.module.LoginModule;
import com.example.dahua.service.AttendanceService;
import com.example.dahua.utils.DateUtils;
import com.example.dahua.utils.FileUtils;
import com.example.dahua.xiananDao.SearchMapper;
import com.example.dahua.xiananDao.SendRecordDao;
import com.sun.jna.Pointer;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.List;

@Component
@Slf4j
public class MyTask implements ApplicationRunner {

    // 主动注册监听回调
    private ServiceCB servicCallback = new ServiceCB();

    // 设备断线通知回调
    private DisConnect disConnect = new DisConnect();

    // 网络连接恢复
    private HaveReConnect haveReConnect = new HaveReConnect();

    //设备登录账号
    public static String strUser = "admin";

    //设备登密码
    public static String password = "q12345678";

    //在线设备信息集合
    private List<DeviceInfoBean> deviceInfoBeans = new ArrayList<>();

    //存放登录句柄
    public static Map<String, NetSDKLib.LLong> lLongMap = new HashMap<>();

    @Autowired
    SendRecordDao sendRecordDao;

    @Autowired
    SearchMapper searchMapper;

    @Autowired
    UserDao userDao;

    public boolean isHasNewDevice = false;//判断是否有新设备上线

    @Override
    public void run(ApplicationArguments args) throws Exception {
//        121.40.109.21
        // 打开工程,初始化
        LoginModule.init(disConnect, haveReConnect);
        //自注册
        autoRegister();

//        System.out.println(" sendRecordDao:"+sendRecordDao.getSenSuccess());
    }


    /**
     * 设备自注册
     */
    private void autoRegister() {

        /**
         * 开启监听服务
         */

        System.out.println("new Utils().getHostAddress():"+new Utils().getHostAddress());
        AutoRegisterModule.startServer(new Utils().getHostAddress(), 9500, servicCallback);

    }

    // 设备断线回调: 通过 CLIENT_Init 设置该回调函数,当设备出现断线时,SDK会调用该函数
    private class DisConnect implements NetSDKLib.fDisConnect {
        public void invoke(NetSDKLib.LLong m_hLoginHandle, String pchDVRIP, int nDVRPort, Pointer dwUser) {
            System.out.printf("Device[%s] Port[%d] DisConnect!\n", pchDVRIP, nDVRPort);
            String deviceId = getDeviceId(pchDVRIP, nDVRPort);
            if (!StringUtils.isEmpty(deviceId)) {
                attendanceService.updateConnectStateWithDevid(0, deviceId);
                GateModule.stopRealLoadPic(lLongMap.get(deviceId));
                lLongMap.remove(deviceId);
//                devMap.remove(deviceId);
                removeDevice(deviceId);
                isHasNewDevice = true;
            }
//            AutoRegisterModule.logout()
            // 断线提示
        }
    }

    // 网络连接恢复,设备重连成功回调
    // 通过 CLIENT_SetAutoReconnect 设置该回调函数,当已断线的设备重连成功时,SDK会调用该函数
    private class HaveReConnect implements NetSDKLib.fHaveReConnect {
        public void invoke(NetSDKLib.LLong m_hLoginHandle, String pchDVRIP, int nDVRPort, Pointer dwUser) {
            // 重连提示
            String deviceId = getDeviceId(pchDVRIP, nDVRPort);
            System.out.printf("ReConnect Device[%s] IP[%S] Port[%d]\n", deviceId,pchDVRIP, nDVRPort);
            if (!StringUtils.isEmpty(deviceId)) {
                attendanceService.updateConnectStateWithDevid(1, deviceId);
//                devMap.put(deviceId,"");
                DeviceInfoBean deviceInfoBean = new DeviceInfoBean();
                deviceInfoBean.setDevcieId(deviceId);
                deviceInfoBean.setDeviceIp(pchDVRIP);
                deviceInfoBean.setDevicePort(nDVRPort);
                deviceInfoBean.setLoginHandle(m_hLoginHandle);
                deviceInfoBean.setPassword(password);
                deviceInfoBean.setUsername(strUser);
                deviceInfoBeans.add(deviceInfoBean);
                lLongMap.put(deviceId, m_hLoginHandle);
                isHasNewDevice = true;
            }
        }
    }

    /**
     * 根据ip和port获取设备id
     *
     * @param pchDVRIP
     * @param nDVRPort
     * @return
     */
    private String getDeviceId(String pchDVRIP, int nDVRPort) {
        for (DeviceInfoBean deviceInfoBean :
                deviceInfoBeans) {
            if (pchDVRIP.equals(deviceInfoBean.getDeviceIp()) && nDVRPort == deviceInfoBean.getDevicePort()) {
                return deviceInfoBean.getDevcieId();
            }
        }
        return "";
    }

    /**
     * 移除设备
     *
     * @param deviceId
     */
    private void removeDevice(String deviceId) {

        DeviceInfoBean deviceInfoBean = null;


        for (DeviceInfoBean dev :
                deviceInfoBeans) {
            if (dev.getDevcieId().equals(deviceId)) deviceInfoBean = dev;
        }

        if (null != deviceInfoBean) deviceInfoBeans.remove(deviceInfoBean);
    }


    @Autowired
    private AttendanceService attendanceService;//设备控制服务

    /**
     * 侦听服务器回调函数
     */
    public class ServiceCB implements NetSDKLib.fServiceCallBack {
        @Override
        public int invoke(NetSDKLib.LLong lHandle, final String pIp, final int wPort,
                          int lCommand, Pointer pParam1, int dwParamLen,
                          Pointer dwUserData) {

            // 将 pParam 转化为序列号
            byte[] buffer1 = new byte[dwParamLen];
            pParam1.read(0, buffer1, 0, dwParamLen);
            //设备id
            String deviceId = "";
            try {
                deviceId = new String(buffer1, "GBK").trim();
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
            System.out.printf("Register Device Info [Device address %s][port %s][DeviceID %s] \n", pIp, wPort, deviceId);
            switch (lCommand) {
                case NetSDKLib.EM_LISTEN_TYPE.NET_DVR_DISCONNECT: {  // 验证期间设备断线回调
                    System.out.println("EM_LISTEN_TYPE:验证期间设备断线回调");

                    break;
                }
                case NetSDKLib.EM_LISTEN_TYPE.NET_DVR_SERIAL_RETURN: { // 设备注册携带序列号
                    System.out.println("EM_LISTEN_TYPE:设备注册携带序列号");
                    /**
                     * 主动注册调用的登录接口,获取登录句柄
                     */
                    NetSDKLib.LLong loginHandleLong = AutoRegisterModule.login(pIp, wPort, strUser, password, deviceId);
//                    FileUtils.getInstance().writeLogs("设备注册:"+deviceId+" 登录句柄:"+loginHandleLong,FileUtils.devices);
                    if (loginHandleLong.longValue() != 0) {
                        lLongMap.put(deviceId, loginHandleLong);
                        isHasNewDevice = true;
                        String inTime = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date());
                        if (deviceId.startsWith("ytj")){
                            attendanceService.insert(deviceId, "29", pIp, wPort + "", inTime, "-1", "1");
                        }else {
                            attendanceService.insert(deviceId, "22", pIp, wPort + "", inTime, "-1", "1");
                        }
                        DeviceInfoBean deviceInfoBean = new DeviceInfoBean();
                        deviceInfoBean.setDevcieId(deviceId);
                        deviceInfoBean.setDeviceIp(pIp);
                        deviceInfoBean.setDevicePort(wPort);
                        deviceInfoBean.setLoginHandle(loginHandleLong);
                        deviceInfoBeans.add(deviceInfoBean);

                    } else {
//                        System.err.println(String.format("Login Failed[Device IP %s] [Port %s][DeviceID %s] %s", pIp,
//                                wPort, deviceId));
                    }
                    break;
                }
                default:
                    break;
            }

            return 1;
        }
    }

    public synchronized void reloadPic() {
        isHasNewDevice = false;
        if (null != deviceInfoBeans && deviceInfoBeans.size() > 0) {
            for (DeviceInfoBean dev :
                    deviceInfoBeans) {
                if (lLongMap.get(dev.getDevcieId()).intValue() > 0) {
                    NetSDKLib.LLong lLong = GateModule.realLoadPic2(0, analyzerCallback, lLongMap.get(dev.getDevcieId()),dev.getDevcieId());
//                    System.out.println("监听成功:"+dev.getDevcieId());
//                    if (lLong.intValue() != -1) {
//                        //deviceInfoBeans.remove(dev);
//                    }
                }

            }
        }
    }


    //智能订阅
    private AnalyzerDataCB analyzerCallback = new AnalyzerDataCB();

    private class AnalyzerDataCB implements NetSDKLib.fAnalyzerDataCallBack {
        private BufferedImage gateBufferedImage = null;

        public int invoke(NetSDKLib.LLong lAnalyzerHandle, int dwAlarmType,
                          Pointer pAlarmInfo, Pointer pBuffer, int dwBufSize,
                          Pointer dwUser, int nSequence, Pointer reserved) {
            if (lAnalyzerHandle.longValue() == 0 || pAlarmInfo == null) {
                return -1;
            }

            byte[] bufferBytes = new byte[dwBufSize];

            pBuffer.read(0, bufferBytes, 0, dwBufSize);


            File path = new File(".\\FaceRecoder");
            if (!path.exists()) {
                path.mkdir();
            }

            //设备ID获取
            NetSDKLib.NET_DEVICEINFO_Ex deviceInfo = new NetSDKLib.NET_DEVICEINFO_Ex();
            ToolKits.GetPointerData(dwUser, deviceInfo);

            String szSn = new String(deviceInfo.sSerialNumber).trim();

            ///< 门禁事件
            if (dwAlarmType == NetSDKLib.EVENT_IVS_ACCESS_CTL) {
                NetSDKLib.DEV_EVENT_ACCESS_CTL_INFO msg = new NetSDKLib.DEV_EVENT_ACCESS_CTL_INFO();
                ToolKits.GetPointerData(pAlarmInfo, msg);
                //卡号
                String card = new String(msg.szCardNo).trim();

                System.out.println("sda:" + card + " 抓拍照片存储地址:");

                try {
                    if (!StringUtils.isEmpty(card)) {
                        // 保存图片,获取图片缓存
                        // 图片服务器路径
                        String snapPicPath = path + "\\" + System.currentTimeMillis() + ".png";  // 保存图片地址
                        byte[] buffer = pBuffer.getByteArray(0, dwBufSize);
                        ByteArrayInputStream byteArrInputGlobal = new ByteArrayInputStream(buffer);
                        gateBufferedImage = ImageIO.read(byteArrInputGlobal);
                        if (gateBufferedImage != null) {
                            ImageIO.write(gateBufferedImage, "png", new File(snapPicPath));
                        }
                        //卡号取反(大写)
                        card = cardNo(card);
                        //根据卡号获取卡身份信息
                        CardBean cardBean = userDao.getCards(card);
                        String time = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date());
                        snapPicPath = snapPicPath.replaceFirst("\\.", "http://121.40.109.21:8991");
                        snapPicPath = snapPicPath.replace("FaceRecoder", "image");
                        if (null != cardBean && cardBean.getType() == 0) {
                            //老师人脸信息,保存人脸记录表
                            TeacherBean teacherBean = userDao.getTeacherWithId(cardBean.getUser_id());
                            sendRecordDao.addFaceRecoder(szSn, teacherBean.getUser_id(), teacherBean.getName(), snapPicPath, 1, time, card,"");
                        } else if (null != cardBean && cardBean.getType() == 2) {
                            //学生人脸信息,保存人脸记录表
                            UserInfoBean userInfoBean = userDao.getStudentWithid(cardBean.getUser_id());
                            sendRecordDao.addFaceRecoder(szSn, userInfoBean.getUser_id(), userInfoBean.getName(), snapPicPath, 1, time, card,"");
                        }

                        // TODO 考勤记录
                        //刷卡结果,1表示成功, 0表示失败
                        int status = msg.bStatus;
                        //门禁事件类型:1进2出
                        int eventType = msg.emEventType;
                        //刷卡时间
                        String eventTime = msg.UTC.toStringTime();
                        //保存考勤记录
                        kaoQinRecord(status,eventType,card,szSn,eventTime,snapPicPath);
                    }

                } catch (IOException e2) {
                    e2.printStackTrace();
                }

                // 图片以及门禁信息界面显示
//                EventQueue eventQueue = Toolkit.getDefaultToolkit().getSystemEventQueue();
//                if (eventQueue != null) {
//                    eventQueue.postEvent( new GateFrame.AccessEvent(target,
//                            gateBufferedImage,
//                            msg));
//                }
            }

            return 0;
        }
    }


    /**
     * 卡号两两取反
     *
     * @param cardDex
     * @return
     */
    public String cardNo(String cardDex) {

        String cardR = "";
        int length = cardDex.length();
        if (length != 8) {
            System.out.println("卡号格式不正确:" + cardDex);
            return cardDex;
        }
        while (length > 0) {
            length -= 2;
            cardR += cardDex.substring(length, length + 2);
        }

        return cardR;

    }

    /**
     * 大华设备考勤记录
     * @param status
     * @param eventType
     * @param cardNo
     * @param deviceId
     * @param eventTime
     * @param imageUrl
     */
    public void kaoQinRecord(int status,int eventType,String cardNo,String deviceId,String eventTime,String imageUrl) {
        if (status == 1) {
            //有效刷卡调考勤存储过程
            CheckIn checkIn = new CheckIn();
            checkIn.setDeviceId(deviceId);
            checkIn.setCardNo(cardNo);
            checkIn.setFunNo(8);
            checkIn.setFlag(eventType == 2 ? 1 : 0);
            checkIn.setCheckTime(eventTime);
            searchMapper.checkIn(checkIn);
            if (checkIn.getIsSuccess() == 1) {
                //考勤成功
                String content = "考勤成功!,设备:" + deviceId + "卡号:" + cardNo + "方向:" + (eventType == 1 ? "进门" : "出门") + "______" + eventTime;
                //记录学生考勤签到记录
                FileUtils.getInstance().writeLogs(content, FileUtils.qiandaoSuccess);
            } else {
                //考勤失败
                String content = "考勤失败!,设备:" + deviceId + "卡号:" + cardNo + "---" + checkIn.getOut();
                //记录学生考勤签到记录
                FileUtils.getInstance().writeLogs(content, FileUtils.qiandaoErr);
            }
        } else {
            //判断是否请假
            String studentNum = userDao.checkLeave(cardNo);
            if (org.apache.commons.lang.StringUtils.isNotBlank(studentNum)) {
                //短信信息
                Message mobileMessage = userDao.selectByParentMobile(cardNo);
                if (mobileMessage.getSchoolId() == 4) {
                    //才发送短信
                    ShortMsg shortMsg = new ShortMsg();
                    String tableSuffix = DateUtils.date2String(new Date(), DateUtils.format);
                    shortMsg.setTableName("smsNew" + tableSuffix);
                    shortMsg.setSchoolId(mobileMessage.getSchoolId());
                    shortMsg.setMobile(mobileMessage.getParentMobile());
                    if (eventType == 2) {
                        //出门
                        shortMsg.setMsg(mobileMessage.getName() + "家长您好,你的孩子于" + DateUtils.date2String(new Date(), DateUtils.format2) + "请假后出校,请知晓;");
                    } else {
                        shortMsg.setMsg(mobileMessage.getName() + "家长您好,你的孩子于" + DateUtils.date2String(new Date(), DateUtils.format2) + "请假后进校,请知晓;");
                    }
                    userDao.insertMessage(shortMsg.getTableName(),shortMsg.getSchoolId()+"",shortMsg.getMobile(),shortMsg.getMsg());
                }
            } else {
                //若即不成功,也不是请假,则按刷卡异常处理
                User user = userDao.selectUserByCardNum(cardNo).get(0);
                if(user ==null ){
                    System.out.println("卡号"+cardNo+"没找到对应学生或老师");
                }
                int deviceType;
                if (deviceId.startsWith("ytj")){
                    deviceType = 29;
                }else {
                    deviceType = 22;
                }
                //失败记录
                SendRecordBean sendRecordBean = new SendRecordBean();
                sendRecordBean.setSchoolId(user.getSchoolId());
                sendRecordBean.setSchoolName(userDao.getSchoolName(String.valueOf(user.getSchoolId())));
                sendRecordBean.setTime(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
                sendRecordBean.setUserType(2);
                sendRecordBean.setNum(cardNo);
                sendRecordBean.setName(user.getName());
                sendRecordBean.setImgPath(imageUrl);
                sendRecordBean.setCustomerid(String.valueOf(user.getStudentId()));
                sendRecordBean.setFailType(8);
                sendRecordBean.setFailContent("人脸认证失败");
                sendRecordBean.setDeviceID(deviceId);
                sendRecordDao.addFaceFail(sendRecordBean.getCustomerid(), sendRecordBean.getDeviceID(), sendRecordBean.getNum(), sendRecordBean.getName(), sendRecordBean.getTime(),
                        sendRecordBean.getSchoolName(), sendRecordBean.getImgPath(), sendRecordBean.getSchoolId(), sendRecordBean.getFailContent(), sendRecordBean.getFailType(), sendRecordBean.getUserType(), deviceType);
            }
        }
    }
}