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.mqtt.MqtUtils; import com.sincere.att.vo.AttendanceInfoBean; import com.sincere.att.vo.CheckOrderVo; 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.ApiImplicitParam; import io.swagger.annotations.ApiImplicitParams; 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.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.*; import java.util.concurrent.atomic.AtomicReference; /** * 所有的设备请求都会在url参数里携带SN,这是设备序列号(serial number的缩写),每个设备唯一标识 */ @RestController @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> cmdMap = new HashMap<>(); private static Map 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 = "GetDeviceCmd", method = RequestMethod.GET) @ApiOperation(value = "查询待处理指令") @ApiImplicitParams({@ApiImplicitParam(name = "schoolId", value = "学校id"), @ApiImplicitParam(name = "deviceId", value = "设备id")}) public String GetDeviceCmd(@RequestParam("schoolId") String schoolId, @RequestParam("deviceId") String deviceId) { try { if(schoolId=="1221") { } if(StringUtils.isNotBlank(deviceId)){ List cmds = cmdMap.get(deviceId); if (cmds != null && cmds.size() > 0) { return cmds.toString(); } return "cmd is empty"; } else{ return "device not is null"; } } catch (Exception e) { return e.getMessage(); } } //C:${CmdID}:Check 检查并传送新数据 @RequestMapping(value = "GetLatestData", method = RequestMethod.GET) @ApiOperation(value = "检查并上传新数据") @ApiImplicitParams({@ApiImplicitParam(name = "schoolId", value = "学校id"), @ApiImplicitParam(name = "deviceId", value = "设备id")}) public void GetLatestData(@RequestParam("schoolId") String schoolId, @RequestParam("deviceId") String deviceId) { SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyyMMddHHmmss"); String date=simpleDateFormat.format(new Date()); List order = new ArrayList<>(); CheckOrderVo vo = new CheckOrderVo(); vo.setStudentName(deviceId+date); int number = 1; try { number = cmdOrderMap.get(deviceId); } catch (Exception e) { } number++; cmdOrderMap.put(deviceId, number); if (!order.contains(vo.toString())) { order.add(vo.toString()); } cmdMap.put(deviceId, order); } @RequestMapping(value = "sendSingleUser", method = RequestMethod.GET) @ApiOperation(value = "下发单个用户") @ApiImplicitParams({@ApiImplicitParam(name = "schoolId", value = "学校id"), @ApiImplicitParam(name = "deviceId", value = "设备id"), @ApiImplicitParam(name = "studentId", value = "学生id")}) public void sendSingleUser(@RequestParam("schoolId") String schoolId, @RequestParam("deviceId") String deviceId, @RequestParam("studentId") int studentId) { // String result1 = HttpClientUtils.httpGet2("http://campus.myjxt.com/api/EasyN/GetStudentDetail?studentid="+studentId+"&schoolId="+schoolId); JSONObject result = HttpClientUtils.httpGet("http://campus.myjxt.com/api/EasyN/GetStudentDetail?studentid="+studentId+"&schoolId="+schoolId); JSONObject array = (JSONObject) result.get("data"); List order = new ArrayList<>(); UserOrderVo vo = new UserOrderVo(); vo.setStudentId((Integer) array.get("studentId")); vo.setStudentName((String) array.get("studentName")); int number = 1; try { number = cmdOrderMap.get(deviceId); } catch (Exception e) { } vo.setNumber(number); number++; cmdOrderMap.put(deviceId, number); if (vo.getStudentId() != 0) { // if (vo.getStudentId() == 72196){ //todo:测试专用 if (!order.contains(vo.toString())) { order.add(vo.toString()); } // } } cmdMap.put(deviceId, order); } @RequestMapping(value = "sendSingleFinger", method = RequestMethod.GET) public void sendSingleFinger(@RequestParam("StudentId") int StudentId,@RequestParam(value = "deviceId") String deviceId) { List order = new ArrayList<>(); // 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(deviceId); } catch (Exception e) { } vo.setNumber(number); vo.setOrder(xaFeign.selectFinger((Integer) StudentId)); number++; cmdOrderMap.put(deviceId, number); if (StringUtils.isNotBlank(vo.getOrder())) { order.add(vo.toString()); } //} cmdMap.put(deviceId, order); //} } @RequestMapping(value = "sendUser", method = RequestMethod.GET) public void sendUser(@RequestParam("roomId") 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 attendanceList = scFeign.selectRoomAttendance(roomId); for (String attendance : attendanceList) { List order = new ArrayList<>(); 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) { // if (vo.getStudentId() == 72196){ //todo:测试专用 if (!order.contains(vo.toString())) { order.add(vo.toString()); } // } } } cmdMap.put(attendance, order); } } @RequestMapping(value = "sendFinger", method = RequestMethod.GET) public void sendFinger(@RequestParam("roomId") int roomId,@RequestParam(value = "deviceId",required = false) String deviceId) { 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 attendanceList = scFeign.selectRoomAttendance(roomId); for (String attendance : attendanceList) { if(StringUtils.isNotBlank(deviceId)&&!attendance.contains(deviceId)) continue; List order = new ArrayList<>(); 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 { System.out.println("设备上电:" + SN); if (cmdMap.get(SN) == null) { System.out.println("设备上线:" + SN); cmdMap.put(SN, new ArrayList<>()); cmdOrderMap.put(SN, 10000); } 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"); //System.out.println(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date())+"设备心跳:" + SN); List cmds = cmdMap.get(SN); // if (null != cmds && cmds.size() > 10) // cmds = cmds.subList(0, 10); if (cmds == null) {//等于空说明从来没加载过,如果初始化加载过了,此时应该不为Null 只是size为0 System.out.println("设备上线:" + SN); cmds = new ArrayList<>(); cmdMap.put(SN, cmds); cmdOrderMap.put(SN, 10000); } 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()); // System.out.println("返回数据成功:" + SN + "---学生数量:" + cmds.size()); } 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 //ID=10000&Return=-10&CMD=DATA 指纹下发返回return=-10,表示指纹机没有这个用户数据 List cmdList = cmdMap.get(SN); String[] returnList = data.split("\n"); if (returnList != null && returnList.length > 0 && cmdList != null && cmdList.size() > 0) { System.out.println("----returnList:" + returnList.length); for (String message : returnList) { System.out.println("----returnList:"+ SN + "," + message); 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 it = cmdList.iterator(); while (((Iterator) it).hasNext()) { String b = it.next(); if (b.contains("C:" + number)) { it.remove(); System.out.println("----设备接收数据"+(Integer.parseInt(result)==0?"成功":"--失败--")+":" + SN + "----number:" + number); } } if(message.contains("CMD=DATA")) { } if(message.contains("CMD=CHECK")) { } //} } } 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])); if (StringUtils.isNotBlank(cardNo)) { String cardNo10 = new BigInteger(cardNo, 16).toString(); //考勤日志 SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); String info = String.format("", simpleDateFormat.format(new Date()), SN, cardNo10, 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) { if ( Integer.parseInt(jsonObject.get("data").toString()) == 0) { /** * 签到成功发送数据到看板 add by 2020-11-17 */ sendMQMessage(SN,cardNo); Log_kaoInfo.info("出入寝签到成功:" + SN + " 卡号:" + cardNo); } else { Log_kaoInfo.info("出入寝签到失败:" + SN + " 卡号:" + cardNo + " result1:" + jsonObject.toJSONString()); } } else { System.out.println(list[0]+":card is "+cardNo); } } if ("OPERLOG".equals(table)) { //操作日志 if (data.substring(0, 3).contains("FP")) { String[] finger = data.split("FP "); for (int j = 0; j < finger.length; j++) { String fingerInfo = finger[j]; if(org.springframework.util.StringUtils.isEmpty(fingerInfo)) continue; //添加指纹 String studentId = fingerInfo .substring(fingerInfo .indexOf("=") + 1, fingerInfo .indexOf("\t", fingerInfo .indexOf("="))); // String order = data.substring(3); String ret= xaFeign.selectFinger(Integer.parseInt(studentId)); if(!org.springframework.util.StringUtils.isEmpty(ret)) continue; //String order = data; FingerDto fingerDto = new FingerDto(); fingerDto.setOrderMsg(fingerInfo); fingerDto.setStudentId(Integer.valueOf(studentId)); fingerDto.setCreateTime(new Date()); xaFeign.insertFinger(fingerDto); } } } try { response.getWriter().write("OK"); } catch (IOException e) { e.printStackTrace(); } } public void sendMQMessage(String deviceId,String cardNum) { //获取寝室关联的场景id String placeId = scFeign.selectPlaceAttendance(deviceId); if (null != placeId) { //关联的显示看板设备 List kanbanIds = scFeign.selectRoomAttendance(Integer.parseInt(placeId)); for (int i = 0; i < kanbanIds.size(); i++) { String kanbanId = kanbanIds.get(i); String data = "{\"cmd\":\"" + 34 + "\",\"clientId\":\"" + kanbanId + "\",\"data\":{\"cardNum\":\"" + cardNum+"}}"; MqtUtils.getInstance().sendMsg(kanbanId, data); } } else { String schoolId = scFeign.getSchoolIdWidthCardNum(cardNum); if(org.springframework.util.StringUtils.isEmpty(schoolId)||Integer.parseInt(schoolId) <=0)return; List clintIds = scFeign.getClintIds(schoolId); for (int i = 0; i < clintIds.size(); i++) { String clintId = clintIds.get(i); String data = "{\"cmd\":\"" + 34 + "\",\"clientId\":\"" + clintId + "\",\"data\":{\"cardNum\":\"" + cardNum + "}}"; MqtUtils.getInstance().sendMsg(clintId, data); } } } public static void main(String[] args) { /*JSONObject object = new JSONObject(); object.put("pageIndex",1); object.put("roomId","13299"); object.put("pageSize",9999); JSONObject result = HttpClientUtils.httpPostJson("http://campus.myjxt.com/api/Room/GetListPageRoom",object.toJSONString()); JSONObject data = result.getJSONObject("data"); JSONArray roomList = data.getJSONArray("roomList"); for (int i = 0; i < roomList.size(); i++) { String name = roomList.getJSONObject(i).getString("name"); String studentId = roomList.getJSONObject(i).getString("studentid"); System.out.println(name+","+studentId); }*/ String cardNo = "FF013E0F"; String SN = "A4JS174260624"; String cardNo10 = new BigInteger(cardNo, 16).toString(); //考勤日志 SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); String info = String.format("", simpleDateFormat.format(new Date()), SN, cardNo10, DateUtils.date2String(new Date(), DateUtils.format2), "-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()); } } /** * 设备通电以后连接到服务器,需要返回的初始化参数 * * @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(); } }