package com.js.kbt.socket; import java.math.BigDecimal; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; import java.util.List; import javax.annotation.Resource; import org.apache.log4j.Logger; import org.springframework.stereotype.Service; import com.alibaba.fastjson.JSONObject; import com.js.kbt.mapper.MouldDownPacketMapper; import com.js.kbt.mapper.MouldHistoryMapper; import com.js.kbt.mapper.MouldHistoryTimeMapper; import com.js.kbt.mapper.MouldHodingMapper; import com.js.kbt.mapper.TbFactoryMapper; import com.js.kbt.mapper.TbMouldEquipmentMapper; import com.js.kbt.mapper.TbMouldMapper; import com.js.kbt.mapper.TimeCalibrationRecordMapper; import com.js.kbt.model.MouldDownPacket; import com.js.kbt.model.MouldDownPacketExample; import com.js.kbt.model.MouldHistory; import com.js.kbt.model.MouldHistoryTime; import com.js.kbt.model.MouldHistoryTimeExample; import com.js.kbt.model.TbMould; import com.js.kbt.model.TbMouldEquipment; import com.js.kbt.model.TbMouldEquipmentExample; import com.js.kbt.model.TbMouldExample; import com.js.kbt.model.TimeCalibrationRecord; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.SimpleChannelInboundHandler; import io.netty.handler.timeout.IdleState; import io.netty.handler.timeout.IdleStateEvent; @Service("userHandler") public class UserHandler extends SimpleChannelInboundHandler { private static final Logger logger = Logger.getLogger(UserHandler.class); private ChannelHandlerContext ctx; @Resource private MouldHistoryMapper mouldHistoryMapper; @Resource private MouldHistoryTimeMapper mouldHistoryTimeMapper; @Resource private TbMouldMapper tbMouldMapper; @Resource private TbMouldEquipmentMapper tbMouldEquipmentMapper; @Resource private TbFactoryMapper tbFactoryMapper; @Resource private MouldHodingMapper mouldHodingMapper; @Resource private MouldDownPacketMapper mouldDownPacketMapper; @Resource private TimeCalibrationRecordMapper timeCalibrationRecordMapper; @Override protected void channelRead0(ChannelHandlerContext arg0, String arg1) { String pack = "FAAF0007001e781e50003C37D5"; //校准时间 timeCalibration(); System.out.println("收到===" + arg1 + "\n"); String equipmentNo = processMsg(arg1); //以下是配置下行数据 // sendPackage(equipmentNo); } private String processMsg(String input) { String ret = "FA AF 00 07 02 1e 78 1e 50 00 3C"; ret.replaceAll(" ", ""); logger.info("=====接收到======" + input); if (!input.startsWith("FAAF")) { logger.info("非云模盒消息,不处理"); return ret; } MouldHistory item = new MouldHistory(); // 抽取手机号码4-5(预留)丢包情况硬件会上报状态01,服务器判断02时候下发printall String mobilePart = input.substring(4 * 2, 5 * 2); System.out.println("原始mobile=" + mobilePart); String mobile = getStringFromHexStr(mobilePart); System.out.println("手机号码为" + mobile); item.setSim(mobile); // 获取设备编码15-24 String deviceNumPart = input.substring(5 * 2, 25 * 2); String deviceNum = getStringFromHexStr(deviceNumPart); System.out.println("设备No=" + deviceNum); item.setEquipmentNo(deviceNum); // 软件版本号25 String version = input.substring(25 * 2, 26 * 2); System.out.println("软件版本号=" + version); item.setVersion(version); String status = input.substring(26 * 2, 27 * 2); System.out.println("工作状态=" + status); MouldDownPacketExample pExp = new MouldDownPacketExample(); pExp.createCriteria().andEquipmentNoEqualTo(deviceNum); List packetList = mouldDownPacketMapper.selectByExample(pExp); if(packetList.size()>0){ MouldDownPacket packet = packetList.get(0); if(!("0"+packet.getIsUse()).equals(status)){ logger.info("开始下发数据包==>"+packet.getPacketStr()); sendMsg(packet.getPacketStr()); } logger.info("判断是否开启或关闭已结束==>"); } item.setStatus(Integer.decode("0x" + status).toString()); // 经度27-37 String longitude = getStringFromHexStr(input.substring(27 * 2, 38 * 2)); System.out.println("经度=" + longitude); item.setLng(longitude); // 38-47纬度以 N 开头 String latitude = getStringFromHexStr(input.substring(38 * 2, 48 * 2)); System.out.println("纬度=" + latitude); item.setLat(latitude); System.out.println("==lac" + reverseParseHex(input.substring(48 * 2, 50 * 2))); System.out.println("==ci" + reverseParseHex(input.substring(50 * 2, 52 * 2))); item.setGprsLac("" + reverseParseHex(input.substring(48 * 2, 50 * 2))); item.setGprsCi("" + reverseParseHex(input.substring(50 * 2, 52 * 2))); item.setWifiBbsid(input.substring(52 * 2, 58 * 2)); String temp = "0x" + input.substring(58 * 2, 59 * 2); System.out.println(temp); int i = Integer.decode(temp); System.out.println(i); item.setTemperature(i); item.setBattery(Integer.decode("0x" + input.substring(59 * 2, 60 * 2))); item.setSig2g(Integer.decode("0x" + input.substring(60 * 2, 61 * 2))); item.setSigNb(Integer.decode("0x" + input.substring(61 * 2, 62 * 2))); item.setSigWifi(Integer.decode("0x" + input.substring(62 * 2, 63 * 2))); item.setExt0("" + Integer.decode("0x" + input.substring(63 * 2, 64 * 2))); item.setAlarm(Integer.decode("0x" + input.substring(64 * 2, 65 * 2))); String str = input.substring(65 * 2, 69 * 2); item.setRunCnt(reverseParseHex(str)); // 根据基站lac和ci获取经纬度 String api = "http://api.cellocation.com:81/cell/?mcc=460&mnc=0&lac=" + item.getGprsLac() + "&ci=" + item.getGprsCi() + "&output=json"; String resp = com.js.kbt.util.HttpRequest.sendGet(api, null); JSONObject json = JSONObject.parseObject(resp); if (json.getInteger("errcode") == 0) { item.setLng(json.getDouble("lon") + ""); item.setLat(json.getDouble("lat") + ""); } else { logger.error("调用基站解析平台出错: " + resp); } String crcStr = input.substring(input.length() - 4); item.setCrcCode("" + reverseParseHex(crcStr)); // 存入数据库 mouldHistoryMapper.insertSelective(item); // 模具开合记录 int cnt = item.getRunCnt(); int start = 69; logger.info("累计开合模次数=" + cnt); int end = input.length() - 4; // 最后2位 0xXX,0xXX ,是CRC校验位 logger.info("时间信息==" + input.substring(start * 2, end)); if (end - start * 2 >= 24) {// 时间最少6位,1位显示0x00,开合算两个时间,所以是6*2*2=24 // 本次运行周期内的开合模次数 int periodCnt = (end - start * 2) / 24; logger.info("本次开合模次数==" + periodCnt); for (int pos = 0; pos < periodCnt; pos++) { // 合模时间 MouldHistoryTime time = new MouldHistoryTime(); time.setHistoryId(item.getId()); time.setEquipmentNo(item.getEquipmentNo()); time.setSeq(pos + 1); Date closeTime = parseDate(input, start, pos, 0); time.setCloseTime(closeTime); // 开模时间 Date openTime = parseDate(input, start, pos, 6); time.setOpenTime(openTime); int timeCost = (int) (openTime.getTime() - closeTime.getTime()); time.setTimeCost(timeCost); mouldHistoryTimeMapper.insertSelective(time); logger.info("mouldHistory数据添加完毕"); } } else { logger.info("本次开合模次数==0"); } // 统计该模盒的平均开合周期 MouldHistoryTimeExample exp = new MouldHistoryTimeExample(); exp.createCriteria().andEquipmentNoEqualTo(item.getEquipmentNo()); List list = mouldHistoryTimeMapper.selectByExample(exp); int avgTime = 0; int totalTime = 0; for (MouldHistoryTime t : list) { totalTime += t.getTimeCost(); } if (list.size() == 0) { avgTime = 0; } else { avgTime = totalTime / list.size(); } handleModLogic(item, avgTime); //判断预留字节的 if("02".equals(mobilePart)){ //丢包数据已占满缓存,调用读取命令 sendMsg("#PRINTFALL;"); return deviceNum; } //返回设备编号 return deviceNum; } public void sendPackage(String equipmentNo){ if(equipmentNo.indexOf("FAAF") != -1){ logger.info("非法云模盒编号,不作下发处理"); return; } MouldDownPacketExample exp = new MouldDownPacketExample(); exp.createCriteria().andEquipmentNoEqualTo(equipmentNo); List list = mouldDownPacketMapper.selectByExample(exp); if(list.size()>0){ MouldDownPacket packet = list.get(0); if(0==packet.getIsUse()){ logger.info("开始下发数据包==>"+packet.getPacketStr()); sendMsg(packet.getPacketStr()); } } } public void timeCalibration(){ Integer count = timeCalibrationRecordMapper.selectCountByToday(); if(count==0){ Date date = new Date(); SimpleDateFormat sdf = new SimpleDateFormat("yy-MM-dd,HH:mm:ss"); String dateStr = sdf.format(date); dateStr = "#TIME="+dateStr+";"; //#TIME=18-03-06,15:31:48; logger.info("校准系统模块时间==>"+dateStr); sendMsg(dateStr); TimeCalibrationRecord timeCalibrationRecord = new TimeCalibrationRecord(); timeCalibrationRecordMapper.insertSelective(timeCalibrationRecord); } } private void handleModLogic(MouldHistory item, int avgTime) { TbMouldEquipmentExample meqExp = new TbMouldEquipmentExample(); meqExp.createCriteria().andEquipmentNoEqualTo(item.getEquipmentNo()); if (tbMouldEquipmentMapper.countByExample(meqExp) > 0) { TbMouldEquipment me = tbMouldEquipmentMapper.selectByExample(meqExp).get(0); me.setHillNumber(item.getBattery() + "%"); if (item.getLng() != null) { me.setLng(Double.parseDouble(item.getLng())); me.setLat(Double.parseDouble(item.getLat())); } me.setTemperature(item.getTemperature()); tbMouldEquipmentMapper.updateByPrimaryKeySelective(me); TbMouldExample tExp = new TbMouldExample(); tExp.setOrderByClause("id desc limit 1"); tExp.createCriteria().andEquipmentIdEqualTo(me.getId()); if (tbMouldMapper.countByExample(tExp) > 0) { TbMould tm = tbMouldMapper.selectByExample(tExp).get(0); tm.setState(item.getStatus()); //云模盒运行次数+模具的历史运行次数 tm.setRunTimes(item.getRunCnt()+tm.getHistoryRunTimes()); // 处理每模平均周期(单位秒) BigDecimal bd = new BigDecimal(avgTime * 1.00 / 1000); tm.setOcCycle(bd); tbMouldMapper.updateByPrimaryKeySelective(tm); // 处理报警 if (item.getAlarm() > 0) { /** * 无报警 0; 低电量报警 1; 温度过热 2; 安装被拆 8。 */ logger.info("设备报警啦:" + item.getAlarm()); } } } } /** * 低位在前的16进制解析 * * @param rHex * @return */ public static int reverseParseHex(String rHex) { int size = rHex.length() / 2; StringBuilder sb = new StringBuilder(); for (int i = 0; i < size; i++) { sb.append(rHex.substring((size - i - 1) * 2, (size - i) * 2)); } String str = sb.toString(); return Integer.parseInt(str, 16); } private static Date parseDate(String input, int start, int pos, int dateStartPos) { String year = input.substring((start + pos * 6 + dateStartPos) * 2, (start + pos * 6 + 1 + dateStartPos) * 2); String month = input.substring((start + pos * 6 + 1 + dateStartPos) * 2, (start + pos * 6 + 2 + dateStartPos) * 2); String day = input.substring((start + pos * 6 + 2 + dateStartPos) * 2, (start + pos * 6 + 3 + dateStartPos) * 2); String hh = input.substring((start + pos * 6 + 3 + dateStartPos) * 2, (start + pos * 6 + 4 + dateStartPos) * 2); String mm = input.substring((start + pos * 6 + 4 + dateStartPos) * 2, (start + pos * 6 + 5 + dateStartPos) * 2); String ss = input.substring((start + pos * 6 + 5 + dateStartPos) * 2, (start + pos * 6 + 6 + dateStartPos) * 2); StringBuilder sb = new StringBuilder(); int yearInt = Integer.parseInt(year, 16); if (yearInt == 0) { sb.append("2019-01-01"); } else { sb.append(yearInt < 100 ? "20" : "2"); sb.append(yearInt).append("-"); int monthInt = Integer.parseInt(month, 16); sb.append(monthInt < 10 ? "0" : "").append(monthInt).append("-"); int dayInt = Integer.parseInt(day, 16); sb.append(dayInt < 10 ? "0" : "").append(dayInt); } Date parseDate = null; try { parseDate = new SimpleDateFormat("yyyy-MM-dd").parse(sb.toString()); parseDate.setHours(Integer.parseInt(hh, 16)); parseDate.setMinutes(Integer.parseInt(mm, 16)); parseDate.setSeconds(Integer.parseInt(ss, 16)); } catch (ParseException e) { e.printStackTrace(); } return parseDate; } private String getStringFromHexStr(String hexStr) { StringBuilder sb = new StringBuilder(); for (int i = 0; i < hexStr.length() / 2; i++) { String str = "0x" + hexStr.substring(i * 2, i * 2 + 2); int intVal = Integer.decode(str).intValue(); char c = (char) intVal; sb.append(c); } return sb.toString(); } public void close() { ctx.close(); } public void sendMsg(String hexString) { System.out.println("发送消息==" + hexString); byte[] buffer = hexStrToBinaryStr(hexString); ByteBuf bf = Unpooled.buffer(hexString.length() / 2); bf.writeBytes(buffer); ctx.writeAndFlush(bf); // ctx.close(); } /** * channel被激活时调用 */ @Override public void channelActive(ChannelHandlerContext ctx) { // TODO Auto-generated method stub this.ctx = ctx; System.out.println("==========Active=========" + ctx.channel().localAddress().toString() + ", connection num=" + HelloServer.deviceMap.size()); } @Override public void channelInactive(ChannelHandlerContext ctx) throws Exception { super.channelInactive(ctx); System.out.println("==========Inactive========="); } @Override public void handlerRemoved(ChannelHandlerContext ctx) throws Exception { // TODO Auto-generated method stub super.handlerRemoved(ctx); System.out.println("[YunSu]handlerRemoved=掉线了==="); } @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { // TODO Auto-generated method stub super.exceptionCaught(ctx, cause); System.out.println("我捕捉到异常信息了"); } @Override public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception { if (evt instanceof IdleStateEvent) { IdleStateEvent event = (IdleStateEvent) evt; if (event.state().equals(IdleState.READER_IDLE)) { } else if (event.state().equals(IdleState.WRITER_IDLE)) { // System.out.println("WRITER_IDLE=="+userInfo.getWxName()); // logger.debug(ctx.channel().remoteAddress().toString()+ // "WRITER_IDLE"); // 超时关闭channel // ctx.close(); } else if (event.state().equals(IdleState.ALL_IDLE)) { // 发送心跳 ctx.channel().writeAndFlush("$&_".toString()); } } // super.userEventTriggered(ctx, evt); } /** * 将十六进制的字符串转换成字节数组 * * @param hexString * @return */ public static byte[] hexStrToBinaryStr(String hexString) { if (hexString == null || "".contentEquals(hexString)) { return null; } hexString = hexString.replaceAll(" ", ""); int len = hexString.length(); int index = 0; byte[] bytes = new byte[len / 2]; while (index < len) { String sub = hexString.substring(index, index + 2); bytes[index / 2] = (byte) Integer.parseInt(sub, 16); index += 2; } return bytes; } /** * 将字节数组转换成十六进制的字符串 * * @return */ public static String BinaryToHexString(byte[] bytes) { String hexStr = "0123456789ABCDEF"; String result = ""; String hex = ""; for (byte b : bytes) { hex = String.valueOf(hexStr.charAt((b & 0xF0) >> 4)); hex += String.valueOf(hexStr.charAt(b & 0x0F)); result += hex + " "; } return result; } public static void main(String[] args) { // String str = "1F51"; String input = "FAAF530000000000000000000000003137333030303239343310010000000000000000000000000000000000000000001F51E85F00000000000045004A54000100110000001308160F171F1308160F2D188FCA"; // String temp = "0x"+str; // int i = Integer.decode(temp); // System.out.println(i); // int p = reverseParseHex(str); // System.out.println(p); // int start = 69; // System.out.println(str.substring(69*2)); // Date d = parseDate(str, start, 0, 0); // System.out.println(d.toGMTString()); int start = 69; int end = input.length() - 4; // 最后2位 0xXX,0xXX ,是CRC校验位 logger.info("时间信息==" + input.substring(start * 2, end)); if (end - start * 2 >= 24) {// 时间最少6位,1位显示0x00,开合算两个时间,所以是6*2*2=24 // 本次运行周期内的开合模次数 int periodCnt = (end - start * 2) / 24; logger.info("本次开合模次数==" + periodCnt); for (int pos = 0; pos < periodCnt; pos++) { // 合模时间 MouldHistoryTime time = new MouldHistoryTime(); time.setSeq(pos + 1); Date closeTime = parseDate(input, start, pos, 0); System.out.println(closeTime); time.setCloseTime(closeTime); // 开模时间 Date openTime = parseDate(input, start, pos, 6); time.setOpenTime(openTime); System.out.println(openTime); int timeCost = (int) (openTime.getTime() - closeTime.getTime()); time.setTimeCost(timeCost); } } else { logger.info("本次开合模次数==0"); } } }