AttPushController.java 13.7 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 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();
    }
}