AttPushController.java 13.9 KB
package com.sincere.att.controller;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.sincere.att.feign.ScFeign;
import com.sincere.att.feign.XaFeign;
import com.sincere.att.logs.LogName;
import com.sincere.att.logs.LoggerUtils;
import com.sincere.att.vo.AttendanceInfoBean;
import com.sincere.att.vo.FingerOrderVo;
import com.sincere.att.vo.UserOrderVo;
import com.sincere.common.dto.smartCampus.SZ_AttendanceDto;
import com.sincere.common.dto.xiaoan.FingerDto;
import com.sincere.common.util.DateUtils;
import com.sincere.common.util.HttpClientUtils;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.math.BigInteger;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * 所有的设备请求都会在url参数里携带SN,这是设备序列号(serial number的缩写),每个设备唯一标识
 */
@Controller
@RequestMapping("/iclock")
public class AttPushController {
    private static final Logger Log_orderFail = LoggerUtils.Logger(LogName.orderFail);
    private static final Logger Log_orderSuccess = LoggerUtils.Logger(LogName.orderSuccess);
    private static final Logger Log_kaoInfo = LoggerUtils.Logger(LogName.kaoInfo);

    private static Map<String, List<String>> cmdMap = new HashMap<>();
    private static Map<String, Integer> cmdOrderMap = new HashMap<>();

    private static String pwd = "22222222-6faf-48uh-a5a9-447ec68bfe2f";
    private static String account = "yueqingzhijiao";


    @Autowired
    ScFeign scFeign;

    @Autowired
    XaFeign xaFeign;

    @RequestMapping(value = "sendUser/{roomId}", method = RequestMethod.GET)
    public void sendUser(@PathVariable int roomId) {
        JSONObject object = new JSONObject();
        object.put("PageIndex", 1);
        object.put("roomId", roomId);
        object.put("pageSize", 9999);
        JSONObject result = HttpClientUtils.httpPostJson("http://campus.myjxt.com/api/Room/GetListPageRoom", object.toJSONString());
        JSONArray array = (JSONArray) ((JSONObject) result.get("data")).get("roomList");
        List<String> order = new ArrayList<>();
        List<String> attendanceList = scFeign.selectRoomAttendance(roomId);
        for (String attendance : attendanceList) {
            for (int i = 0; i < array.size(); i++) {
                JSONObject student = (JSONObject) array.get(i);
                UserOrderVo vo = new UserOrderVo();
                vo.setStudentId((Integer) student.get("studentid"));
                vo.setStudentName((String) student.get("name"));
                int number = 1;
                try {
                    number = cmdOrderMap.get(attendance);
                } catch (Exception e) {

                }
                vo.setNumber(number);
                number++;
                cmdOrderMap.put(attendance, number);
                if (vo.getStudentId() != 0) {
                    order.add(vo.toString());
                }
            }
            cmdMap.put(attendance, order);
        }
    }

    @RequestMapping(value = "sendFinger/{roomId}", method = RequestMethod.GET)
    public void sendFinger(@PathVariable int roomId) {
        JSONObject object = new JSONObject();
        object.put("PageIndex", 1);
        object.put("roomId", roomId);
        object.put("pageSize", 9999);
        JSONObject result = HttpClientUtils.httpPostJson("http://campus.myjxt.com/api/Room/GetListPageRoom", object.toJSONString());
        JSONArray array = (JSONArray) ((JSONObject) result.get("data")).get("roomList");
        List<String> order = new ArrayList<>();
        List<String> attendanceList = scFeign.selectRoomAttendance(roomId);
        for (String attendance : attendanceList) {
            for (int i = 0; i < array.size(); i++) {
                JSONObject student = (JSONObject) array.get(i);
                FingerOrderVo vo = new FingerOrderVo();
                int number = 1;
                try {
                    number = cmdOrderMap.get(attendance);
                } catch (Exception e) {

                }
                vo.setNumber(number);
                vo.setOrder(xaFeign.selectFinger((Integer) student.get("studentid")));
                number++;
                cmdOrderMap.put(attendance, number);
                if (StringUtils.isNotBlank(vo.getOrder())) {
                    order.add(vo.toString());
                }
            }
            cmdMap.put(attendance, order);
        }
    }

    /**
     * 1,设备通完电以后第一个发送到后台的请求
     * 格式为 /iclock/cdata?options=all&language=xxxx&pushver=xxxx
     */
    @RequestMapping(value = "/cdata", params = {"options", "language", "pushver"}, method = RequestMethod.GET)
    public void init(String SN, String options, String language, String pushver, HttpServletRequest request,
                     @RequestParam(required = false) String PushOptionsFlag, HttpServletResponse response) {
        try {
            if (cmdMap.get(SN) == null) {
                cmdMap.put(SN, new ArrayList<>());
                cmdOrderMap.put(SN, 1);
            }
            if (scFeign.selectAttendaceWithId(SN) == null) {
                SZ_AttendanceDto attendanceDto = new SZ_AttendanceDto();
                attendanceDto.setClint_id(SN);
                attendanceDto.setClint_type("24");
                attendanceDto.setIp(request.getRemoteAddr());
                attendanceDto.setPort(request.getRemotePort());
                attendanceDto.setIntime(DateUtils.date2String(new Date(), DateUtils.format2));
                attendanceDto.setSchool_id("-1");
                attendanceDto.setState(1);
                scFeign.insertAttendance(attendanceDto);
            } else {
                scFeign.updateAttendance(SN);
            }
            String initOptions = initOptions(SN, PushOptionsFlag);
            response.getWriter().write(initOptions);//返回成功以后设备会发送心跳请求
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 2,心跳请求,会从服务器拿到命令返回   给设备
     */
    @RequestMapping("/getrequest")
    public void heartBeat(String SN, HttpServletResponse response) {
        scFeign.updateAttendance(SN);
        StringBuffer sb = new StringBuffer("OK");
        List<String> cmds = cmdMap.get(SN);
        if (cmds == null) {//等于空说明从来没加载过,如果初始化加载过了,此时应该不为Null 只是size为0
            cmds = new ArrayList<>();
            cmdMap.put(SN, cmds);
            cmdOrderMap.put(SN, 1);
        }
        if (cmds != null && cmds.size() > 0) {
            sb.setLength(0);//如果有命令就不返回OK了
            cmds.stream().forEach(cmd -> sb.append(cmd).append("\r\n\r\n"));

        }
        try {
            response.setCharacterEncoding("gbk");
            response.getWriter().write(sb.toString());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }


    /**
     * 3,候补心跳请求,正常情况下设备不发此请求,有大量数据上传的时候,不发上面的心跳,发这个请求,
     * 这个请求,服务器只能返回OK,不可以返回命令
     */
    @RequestMapping("/ping")
    public void ping(HttpServletResponse response) {
        System.out.println("考勤机心跳请求大量进来了......ping" + new SimpleDateFormat("HH:mm:ss").format(new Date()));
        try {
            response.getWriter().write("OK");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 4,设备端处理完命令以后会发送该请求,告诉服务器命令的处理结果
     */
    @RequestMapping("/devicecmd")
    public void handleCmd(String SN, @RequestBody String data, HttpServletResponse response) {
        //判断data  清空map
        List<String> cmdList = cmdMap.get(SN);
        String[] returnList = data.split("\n");
        if (returnList.length > 0 && cmdList.size() > 0) {
            for (String message : returnList) {
                String number = message.substring(message.indexOf("=") + 1, message.indexOf("&"));
                String result = message.substring(message.indexOf("=", message.indexOf("&")) + 1, message.indexOf("&", message.indexOf("&") + 1));
                if (result.equals("0")) {
                    Iterator<String> it = cmdList.iterator();
                    while (((Iterator) it).hasNext()) {
                        String b = it.next();
                        if (b.contains("C:" + number)) {
                            Log_orderSuccess.info("指令成功==========" + b);
                            it.remove();
                        }
                    }
                }
            }
        }
        try {
            response.getWriter().write("OK");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }


    /**
     * 5 考勤数据上报
     */
    @RequestMapping(value = "/cdata")
    public void handleRtData(HttpServletRequest request, HttpServletResponse response, String SN, String table) throws UnsupportedEncodingException {
        request.setCharacterEncoding("gbk");
        String data = "";
        ByteArrayOutputStream bos = null;
        byte[] b = new byte[1024];
        try {
            InputStream is = request.getInputStream();
            bos = new ByteArrayOutputStream();
            int len = 0;
            while ((len = is.read(b)) != -1) {
                bos.write(b, 0, len);
            }
            data = new String(bos.toByteArray(), "gbk");
        } catch (IOException e) {
            e.printStackTrace();
        }
        if ("ATTLOG".equals(table)) {
            String[] list = data.split("\t");
            String cardNo = scFeign.selectStudentNumByStudentId(Integer.valueOf(list[0]));
            cardNo = new BigInteger(cardNo, 16).toString();
            //考勤日志
            SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            String info = String.format("<AttendanceInfo submitTime=\"%s\"><Info device=\"%s\" card=\"%s\" operTime=\"%s\" direc=\"%s\"></Info></AttendanceInfo>",
                    simpleDateFormat.format(new Date()), SN, cardNo, list[1], "-1");
            AttendanceInfoBean attendanceInfoBean = new AttendanceInfoBean();
            attendanceInfoBean.setInfo(info);
            attendanceInfoBean.setIsControl(0);
            attendanceInfoBean.setPwd(pwd);
            attendanceInfoBean.setUsername(account);

            String jsonResult = JSON.toJSONString(attendanceInfoBean);
            String urlHXY = "http://campus.myjxt.com/api/XiaoAnCommon/SendHXY";
            JSONObject jsonObject = HttpClientUtils.httpPostJson(urlHXY, jsonResult);
            if ((int) jsonObject.get("status") == 1) {
                Log_kaoInfo.info("出入寝签到成功:" + SN + " 卡号:" + cardNo);
            } else {
                Log_orderFail.info("出入寝签到失败:" + SN + " 卡号:" + cardNo + " result1:" + jsonObject.toJSONString());
            }
        }
        if ("OPERLOG".equals(table)) {
            //操作日志
            if (data.substring(0, 3).contains("FP")) {
                //添加指纹
                String studentId = data.substring(data.indexOf("=") + 1, data.indexOf("\t", data.indexOf("=")));
                String order = data.substring(3);
                FingerDto fingerDto = new FingerDto();
                fingerDto.setOrderMsg(order);
                fingerDto.setStudentId(Integer.valueOf(studentId));
                fingerDto.setCreateTime(new Date());
                xaFeign.insertFinger(fingerDto);
            }
        }
        try {
            response.getWriter().write("OK");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 设备通电以后连接到服务器,需要返回的初始化参数
     *
     * @param sn
     * @param PushOptionsFlag
     * @return
     */
    private String initOptions(String sn, String PushOptionsFlag) {
        StringBuffer devOptions = new StringBuffer();
        devOptions.append("GET OPTION FROM: " + sn);
        // + "\nStamp=" + devInfo.devInfoJson.getString("Stamp")
        devOptions.append("\nATTLOGStamp=0");
        devOptions.append("\nOPERLOGStamp=0");
        devOptions.append("\nBIODATAStamp=0");
        devOptions.append("\nATTPHOTOStamp=0");
        devOptions.append("\nErrorDelay=10");//断网重连
        devOptions.append("\nDelay=5");//心跳间隔
        devOptions.append("\nTimeZone=8");//时区
        devOptions.append("\nRealtime=1");//实时上传
        devOptions.append("\nServerVer=3.0.1");//这个必须填写
//        1 考勤记录
//        2 操作日志
//        3 考勤照片
//        4 登记新指纹
//        5 登记新用户
//        6 指纹图片
//        7 修改用户信息
//        8 修改指纹
//        9 新登记人脸
//        10 用户照片
//        11 工作号码
//        12 比对照片
        devOptions.append("\nTransFlag=111111111111");//  1-12二进制位 分别代表以上含义
        System.out.println("PushOptionsFlag=============" + PushOptionsFlag);
        if (PushOptionsFlag != null && PushOptionsFlag.equals("1")) {
            // 支持参数单独获取的才要把需要获取的参数回传给设备 modifeid by max 20170926
            devOptions.append("\nPushOptions=RegDeviceType,FingerFunOn,FaceFunOn,FPVersion,FaceVersion,NetworkType,HardwareId3,HardwareId5,HardwareId56,LicenseStatus3,LicenseStatus5,LicenseStatus56");
        }
        devOptions.append("\n");
        return devOptions.toString();
    }
}