UserHandler.java 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483
  1. package com.js.kbt.socket;
  2. import java.math.BigDecimal;
  3. import java.text.ParseException;
  4. import java.text.SimpleDateFormat;
  5. import java.util.Date;
  6. import java.util.List;
  7. import javax.annotation.Resource;
  8. import org.apache.log4j.Logger;
  9. import org.springframework.stereotype.Service;
  10. import com.alibaba.fastjson.JSONObject;
  11. import com.js.kbt.mapper.MouldDownPacketMapper;
  12. import com.js.kbt.mapper.MouldHistoryMapper;
  13. import com.js.kbt.mapper.MouldHistoryTimeMapper;
  14. import com.js.kbt.mapper.MouldHodingMapper;
  15. import com.js.kbt.mapper.TbFactoryMapper;
  16. import com.js.kbt.mapper.TbMouldEquipmentMapper;
  17. import com.js.kbt.mapper.TbMouldMapper;
  18. import com.js.kbt.mapper.TimeCalibrationRecordMapper;
  19. import com.js.kbt.model.MouldDownPacket;
  20. import com.js.kbt.model.MouldDownPacketExample;
  21. import com.js.kbt.model.MouldHistory;
  22. import com.js.kbt.model.MouldHistoryTime;
  23. import com.js.kbt.model.MouldHistoryTimeExample;
  24. import com.js.kbt.model.TbMould;
  25. import com.js.kbt.model.TbMouldEquipment;
  26. import com.js.kbt.model.TbMouldEquipmentExample;
  27. import com.js.kbt.model.TbMouldExample;
  28. import com.js.kbt.model.TimeCalibrationRecord;
  29. import io.netty.buffer.ByteBuf;
  30. import io.netty.buffer.Unpooled;
  31. import io.netty.channel.ChannelHandlerContext;
  32. import io.netty.channel.SimpleChannelInboundHandler;
  33. import io.netty.handler.timeout.IdleState;
  34. import io.netty.handler.timeout.IdleStateEvent;
  35. @Service("userHandler")
  36. public class UserHandler extends SimpleChannelInboundHandler<String> {
  37. private static final Logger logger = Logger.getLogger(UserHandler.class);
  38. private ChannelHandlerContext ctx;
  39. @Resource
  40. private MouldHistoryMapper mouldHistoryMapper;
  41. @Resource
  42. private MouldHistoryTimeMapper mouldHistoryTimeMapper;
  43. @Resource
  44. private TbMouldMapper tbMouldMapper;
  45. @Resource
  46. private TbMouldEquipmentMapper tbMouldEquipmentMapper;
  47. @Resource
  48. private TbFactoryMapper tbFactoryMapper;
  49. @Resource
  50. private MouldHodingMapper mouldHodingMapper;
  51. @Resource
  52. private MouldDownPacketMapper mouldDownPacketMapper;
  53. @Resource
  54. private TimeCalibrationRecordMapper timeCalibrationRecordMapper;
  55. @Override
  56. protected void channelRead0(ChannelHandlerContext arg0, String arg1) {
  57. String pack = "FAAF0007001e781e50003C37D5";
  58. //校准时间
  59. timeCalibration();
  60. System.out.println("收到===" + arg1 + "\n");
  61. String equipmentNo = processMsg(arg1);
  62. //以下是配置下行数据
  63. // sendPackage(equipmentNo);
  64. }
  65. private String processMsg(String input) {
  66. String ret = "FA AF 00 07 02 1e 78 1e 50 00 3C";
  67. ret.replaceAll(" ", "");
  68. logger.info("=====接收到======" + input);
  69. if (!input.startsWith("FAAF")) {
  70. logger.info("非云模盒消息,不处理");
  71. return ret;
  72. }
  73. MouldHistory item = new MouldHistory();
  74. // 抽取手机号码4-5(预留)丢包情况硬件会上报状态01,服务器判断02时候下发printall
  75. String mobilePart = input.substring(4 * 2, 5 * 2);
  76. System.out.println("原始mobile=" + mobilePart);
  77. String mobile = getStringFromHexStr(mobilePart);
  78. System.out.println("手机号码为" + mobile);
  79. item.setSim(mobile);
  80. // 获取设备编码15-24
  81. String deviceNumPart = input.substring(5 * 2, 25 * 2);
  82. String deviceNum = getStringFromHexStr(deviceNumPart);
  83. System.out.println("设备No=" + deviceNum);
  84. item.setEquipmentNo(deviceNum);
  85. // 软件版本号25
  86. String version = input.substring(25 * 2, 26 * 2);
  87. System.out.println("软件版本号=" + version);
  88. item.setVersion(version);
  89. String status = input.substring(26 * 2, 27 * 2);
  90. System.out.println("工作状态=" + status);
  91. MouldDownPacketExample pExp = new MouldDownPacketExample();
  92. pExp.createCriteria().andEquipmentNoEqualTo(deviceNum);
  93. List<MouldDownPacket> packetList = mouldDownPacketMapper.selectByExample(pExp);
  94. if(packetList.size()>0){
  95. MouldDownPacket packet = packetList.get(0);
  96. if(!("0"+packet.getIsUse()).equals(status)){
  97. logger.info("开始下发数据包==>"+packet.getPacketStr());
  98. sendMsg(packet.getPacketStr());
  99. }
  100. logger.info("判断是否开启或关闭已结束==>");
  101. }
  102. item.setStatus(Integer.decode("0x" + status).toString());
  103. // 经度27-37
  104. String longitude = getStringFromHexStr(input.substring(27 * 2, 38 * 2));
  105. System.out.println("经度=" + longitude);
  106. item.setLng(longitude);
  107. // 38-47纬度以 N 开头
  108. String latitude = getStringFromHexStr(input.substring(38 * 2, 48 * 2));
  109. System.out.println("纬度=" + latitude);
  110. item.setLat(latitude);
  111. System.out.println("==lac" + reverseParseHex(input.substring(48 * 2, 50 * 2)));
  112. System.out.println("==ci" + reverseParseHex(input.substring(50 * 2, 52 * 2)));
  113. item.setGprsLac("" + reverseParseHex(input.substring(48 * 2, 50 * 2)));
  114. item.setGprsCi("" + reverseParseHex(input.substring(50 * 2, 52 * 2)));
  115. item.setWifiBbsid(input.substring(52 * 2, 58 * 2));
  116. String temp = "0x" + input.substring(58 * 2, 59 * 2);
  117. System.out.println(temp);
  118. int i = Integer.decode(temp);
  119. System.out.println(i);
  120. item.setTemperature(i);
  121. item.setBattery(Integer.decode("0x" + input.substring(59 * 2, 60 * 2)));
  122. item.setSig2g(Integer.decode("0x" + input.substring(60 * 2, 61 * 2)));
  123. item.setSigNb(Integer.decode("0x" + input.substring(61 * 2, 62 * 2)));
  124. item.setSigWifi(Integer.decode("0x" + input.substring(62 * 2, 63 * 2)));
  125. item.setExt0("" + Integer.decode("0x" + input.substring(63 * 2, 64 * 2)));
  126. item.setAlarm(Integer.decode("0x" + input.substring(64 * 2, 65 * 2)));
  127. String str = input.substring(65 * 2, 69 * 2);
  128. item.setRunCnt(reverseParseHex(str));
  129. // 根据基站lac和ci获取经纬度
  130. String api = "http://api.cellocation.com:81/cell/?mcc=460&mnc=0&lac=" + item.getGprsLac() + "&ci="
  131. + item.getGprsCi() + "&output=json";
  132. String resp = com.js.kbt.util.HttpRequest.sendGet(api, null);
  133. JSONObject json = JSONObject.parseObject(resp);
  134. if (json.getInteger("errcode") == 0) {
  135. item.setLng(json.getDouble("lon") + "");
  136. item.setLat(json.getDouble("lat") + "");
  137. } else {
  138. logger.error("调用基站解析平台出错: " + resp);
  139. }
  140. String crcStr = input.substring(input.length() - 4);
  141. item.setCrcCode("" + reverseParseHex(crcStr));
  142. // 存入数据库
  143. mouldHistoryMapper.insertSelective(item);
  144. // 模具开合记录
  145. int cnt = item.getRunCnt();
  146. int start = 69;
  147. logger.info("累计开合模次数=" + cnt);
  148. int end = input.length() - 4; // 最后2位 0xXX,0xXX ,是CRC校验位
  149. logger.info("时间信息==" + input.substring(start * 2, end));
  150. if (end - start * 2 >= 24) {// 时间最少6位,1位显示0x00,开合算两个时间,所以是6*2*2=24
  151. // 本次运行周期内的开合模次数
  152. int periodCnt = (end - start * 2) / 24;
  153. logger.info("本次开合模次数==" + periodCnt);
  154. for (int pos = 0; pos < periodCnt; pos++) {
  155. // 合模时间
  156. MouldHistoryTime time = new MouldHistoryTime();
  157. time.setHistoryId(item.getId());
  158. time.setEquipmentNo(item.getEquipmentNo());
  159. time.setSeq(pos + 1);
  160. Date closeTime = parseDate(input, start, pos, 0);
  161. time.setCloseTime(closeTime);
  162. // 开模时间
  163. Date openTime = parseDate(input, start, pos, 6);
  164. time.setOpenTime(openTime);
  165. int timeCost = (int) (openTime.getTime() - closeTime.getTime());
  166. time.setTimeCost(timeCost);
  167. mouldHistoryTimeMapper.insertSelective(time);
  168. logger.info("mouldHistory数据添加完毕");
  169. }
  170. } else {
  171. logger.info("本次开合模次数==0");
  172. }
  173. // 统计该模盒的平均开合周期
  174. MouldHistoryTimeExample exp = new MouldHistoryTimeExample();
  175. exp.createCriteria().andEquipmentNoEqualTo(item.getEquipmentNo());
  176. List<MouldHistoryTime> list = mouldHistoryTimeMapper.selectByExample(exp);
  177. int avgTime = 0;
  178. int totalTime = 0;
  179. for (MouldHistoryTime t : list) {
  180. totalTime += t.getTimeCost();
  181. }
  182. if (list.size() == 0) {
  183. avgTime = 0;
  184. } else {
  185. avgTime = totalTime / list.size();
  186. }
  187. handleModLogic(item, avgTime);
  188. //判断预留字节的
  189. if("02".equals(mobilePart)){
  190. //丢包数据已占满缓存,调用读取命令
  191. sendMsg("#PRINTFALL;");
  192. return deviceNum;
  193. }
  194. //返回设备编号
  195. return deviceNum;
  196. }
  197. public void sendPackage(String equipmentNo){
  198. if(equipmentNo.indexOf("FAAF") != -1){
  199. logger.info("非法云模盒编号,不作下发处理");
  200. return;
  201. }
  202. MouldDownPacketExample exp = new MouldDownPacketExample();
  203. exp.createCriteria().andEquipmentNoEqualTo(equipmentNo);
  204. List<MouldDownPacket> list = mouldDownPacketMapper.selectByExample(exp);
  205. if(list.size()>0){
  206. MouldDownPacket packet = list.get(0);
  207. if(0==packet.getIsUse()){
  208. logger.info("开始下发数据包==>"+packet.getPacketStr());
  209. sendMsg(packet.getPacketStr());
  210. }
  211. }
  212. }
  213. public void timeCalibration(){
  214. Integer count = timeCalibrationRecordMapper.selectCountByToday();
  215. if(count==0){
  216. Date date = new Date();
  217. SimpleDateFormat sdf = new SimpleDateFormat("yy-MM-dd,HH:mm:ss");
  218. String dateStr = sdf.format(date);
  219. dateStr = "#TIME="+dateStr+";";
  220. //#TIME=18-03-06,15:31:48;
  221. logger.info("校准系统模块时间==>"+dateStr);
  222. sendMsg(dateStr);
  223. TimeCalibrationRecord timeCalibrationRecord = new TimeCalibrationRecord();
  224. timeCalibrationRecordMapper.insertSelective(timeCalibrationRecord);
  225. }
  226. }
  227. private void handleModLogic(MouldHistory item, int avgTime) {
  228. TbMouldEquipmentExample meqExp = new TbMouldEquipmentExample();
  229. meqExp.createCriteria().andEquipmentNoEqualTo(item.getEquipmentNo());
  230. if (tbMouldEquipmentMapper.countByExample(meqExp) > 0) {
  231. TbMouldEquipment me = tbMouldEquipmentMapper.selectByExample(meqExp).get(0);
  232. me.setHillNumber(item.getBattery() + "%");
  233. if (item.getLng() != null) {
  234. me.setLng(Double.parseDouble(item.getLng()));
  235. me.setLat(Double.parseDouble(item.getLat()));
  236. }
  237. me.setTemperature(item.getTemperature());
  238. tbMouldEquipmentMapper.updateByPrimaryKeySelective(me);
  239. TbMouldExample tExp = new TbMouldExample();
  240. tExp.setOrderByClause("id desc limit 1");
  241. tExp.createCriteria().andEquipmentIdEqualTo(me.getId());
  242. if (tbMouldMapper.countByExample(tExp) > 0) {
  243. TbMould tm = tbMouldMapper.selectByExample(tExp).get(0);
  244. tm.setState(item.getStatus());
  245. //云模盒运行次数+模具的历史运行次数
  246. tm.setRunTimes(item.getRunCnt()+tm.getHistoryRunTimes());
  247. // 处理每模平均周期(单位秒)
  248. BigDecimal bd = new BigDecimal(avgTime * 1.00 / 1000);
  249. tm.setOcCycle(bd);
  250. tbMouldMapper.updateByPrimaryKeySelective(tm);
  251. // 处理报警
  252. if (item.getAlarm() > 0) {
  253. /**
  254. * 无报警 0; 低电量报警 1; 温度过热 2; 安装被拆 8。
  255. */
  256. logger.info("设备报警啦:" + item.getAlarm());
  257. }
  258. }
  259. }
  260. }
  261. /**
  262. * 低位在前的16进制解析
  263. *
  264. * @param rHex
  265. * @return
  266. */
  267. public static int reverseParseHex(String rHex) {
  268. int size = rHex.length() / 2;
  269. StringBuilder sb = new StringBuilder();
  270. for (int i = 0; i < size; i++) {
  271. sb.append(rHex.substring((size - i - 1) * 2, (size - i) * 2));
  272. }
  273. String str = sb.toString();
  274. return Integer.parseInt(str, 16);
  275. }
  276. private static Date parseDate(String input, int start, int pos, int dateStartPos) {
  277. String year = input.substring((start + pos * 6 + dateStartPos) * 2, (start + pos * 6 + 1 + dateStartPos) * 2);
  278. String month = input.substring((start + pos * 6 + 1 + dateStartPos) * 2,
  279. (start + pos * 6 + 2 + dateStartPos) * 2);
  280. String day = input.substring((start + pos * 6 + 2 + dateStartPos) * 2,
  281. (start + pos * 6 + 3 + dateStartPos) * 2);
  282. String hh = input.substring((start + pos * 6 + 3 + dateStartPos) * 2, (start + pos * 6 + 4 + dateStartPos) * 2);
  283. String mm = input.substring((start + pos * 6 + 4 + dateStartPos) * 2, (start + pos * 6 + 5 + dateStartPos) * 2);
  284. String ss = input.substring((start + pos * 6 + 5 + dateStartPos) * 2, (start + pos * 6 + 6 + dateStartPos) * 2);
  285. StringBuilder sb = new StringBuilder();
  286. int yearInt = Integer.parseInt(year, 16);
  287. if (yearInt == 0) {
  288. sb.append("2019-01-01");
  289. } else {
  290. sb.append(yearInt < 100 ? "20" : "2");
  291. sb.append(yearInt).append("-");
  292. int monthInt = Integer.parseInt(month, 16);
  293. sb.append(monthInt < 10 ? "0" : "").append(monthInt).append("-");
  294. int dayInt = Integer.parseInt(day, 16);
  295. sb.append(dayInt < 10 ? "0" : "").append(dayInt);
  296. }
  297. Date parseDate = null;
  298. try {
  299. parseDate = new SimpleDateFormat("yyyy-MM-dd").parse(sb.toString());
  300. parseDate.setHours(Integer.parseInt(hh, 16));
  301. parseDate.setMinutes(Integer.parseInt(mm, 16));
  302. parseDate.setSeconds(Integer.parseInt(ss, 16));
  303. } catch (ParseException e) {
  304. e.printStackTrace();
  305. }
  306. return parseDate;
  307. }
  308. private String getStringFromHexStr(String hexStr) {
  309. StringBuilder sb = new StringBuilder();
  310. for (int i = 0; i < hexStr.length() / 2; i++) {
  311. String str = "0x" + hexStr.substring(i * 2, i * 2 + 2);
  312. int intVal = Integer.decode(str).intValue();
  313. char c = (char) intVal;
  314. sb.append(c);
  315. }
  316. return sb.toString();
  317. }
  318. public void close() {
  319. ctx.close();
  320. }
  321. public void sendMsg(String hexString) {
  322. System.out.println("发送消息==" + hexString);
  323. byte[] buffer = hexStrToBinaryStr(hexString);
  324. ByteBuf bf = Unpooled.buffer(hexString.length() / 2);
  325. bf.writeBytes(buffer);
  326. ctx.writeAndFlush(bf);
  327. // ctx.close();
  328. }
  329. /**
  330. * channel被激活时调用
  331. */
  332. @Override
  333. public void channelActive(ChannelHandlerContext ctx) {
  334. // TODO Auto-generated method stub
  335. this.ctx = ctx;
  336. System.out.println("==========Active=========" + ctx.channel().localAddress().toString() + ", connection num="
  337. + HelloServer.deviceMap.size());
  338. }
  339. @Override
  340. public void channelInactive(ChannelHandlerContext ctx) throws Exception {
  341. super.channelInactive(ctx);
  342. System.out.println("==========Inactive=========");
  343. }
  344. @Override
  345. public void handlerRemoved(ChannelHandlerContext ctx) throws Exception {
  346. // TODO Auto-generated method stub
  347. super.handlerRemoved(ctx);
  348. System.out.println("[YunSu]handlerRemoved=掉线了===");
  349. }
  350. @Override
  351. public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
  352. // TODO Auto-generated method stub
  353. super.exceptionCaught(ctx, cause);
  354. System.out.println("我捕捉到异常信息了");
  355. }
  356. @Override
  357. public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
  358. if (evt instanceof IdleStateEvent) {
  359. IdleStateEvent event = (IdleStateEvent) evt;
  360. if (event.state().equals(IdleState.READER_IDLE)) {
  361. } else if (event.state().equals(IdleState.WRITER_IDLE)) {
  362. // System.out.println("WRITER_IDLE=="+userInfo.getWxName());
  363. // logger.debug(ctx.channel().remoteAddress().toString()+
  364. // "WRITER_IDLE");
  365. // 超时关闭channel
  366. // ctx.close();
  367. } else if (event.state().equals(IdleState.ALL_IDLE)) {
  368. // 发送心跳
  369. ctx.channel().writeAndFlush("$&_".toString());
  370. }
  371. }
  372. // super.userEventTriggered(ctx, evt);
  373. }
  374. /**
  375. * 将十六进制的字符串转换成字节数组
  376. *
  377. * @param hexString
  378. * @return
  379. */
  380. public static byte[] hexStrToBinaryStr(String hexString) {
  381. if (hexString == null || "".contentEquals(hexString)) {
  382. return null;
  383. }
  384. hexString = hexString.replaceAll(" ", "");
  385. int len = hexString.length();
  386. int index = 0;
  387. byte[] bytes = new byte[len / 2];
  388. while (index < len) {
  389. String sub = hexString.substring(index, index + 2);
  390. bytes[index / 2] = (byte) Integer.parseInt(sub, 16);
  391. index += 2;
  392. }
  393. return bytes;
  394. }
  395. /**
  396. * 将字节数组转换成十六进制的字符串
  397. *
  398. * @return
  399. */
  400. public static String BinaryToHexString(byte[] bytes) {
  401. String hexStr = "0123456789ABCDEF";
  402. String result = "";
  403. String hex = "";
  404. for (byte b : bytes) {
  405. hex = String.valueOf(hexStr.charAt((b & 0xF0) >> 4));
  406. hex += String.valueOf(hexStr.charAt(b & 0x0F));
  407. result += hex + " ";
  408. }
  409. return result;
  410. }
  411. public static void main(String[] args) {
  412. // String str = "1F51";
  413. String input = "FAAF530000000000000000000000003137333030303239343310010000000000000000000000000000000000000000001F51E85F00000000000045004A54000100110000001308160F171F1308160F2D188FCA";
  414. // String temp = "0x"+str;
  415. // int i = Integer.decode(temp);
  416. // System.out.println(i);
  417. // int p = reverseParseHex(str);
  418. // System.out.println(p);
  419. // int start = 69;
  420. // System.out.println(str.substring(69*2));
  421. // Date d = parseDate(str, start, 0, 0);
  422. // System.out.println(d.toGMTString());
  423. int start = 69;
  424. int end = input.length() - 4; // 最后2位 0xXX,0xXX ,是CRC校验位
  425. logger.info("时间信息==" + input.substring(start * 2, end));
  426. if (end - start * 2 >= 24) {// 时间最少6位,1位显示0x00,开合算两个时间,所以是6*2*2=24
  427. // 本次运行周期内的开合模次数
  428. int periodCnt = (end - start * 2) / 24;
  429. logger.info("本次开合模次数==" + periodCnt);
  430. for (int pos = 0; pos < periodCnt; pos++) {
  431. // 合模时间
  432. MouldHistoryTime time = new MouldHistoryTime();
  433. time.setSeq(pos + 1);
  434. Date closeTime = parseDate(input, start, pos, 0);
  435. System.out.println(closeTime);
  436. time.setCloseTime(closeTime);
  437. // 开模时间
  438. Date openTime = parseDate(input, start, pos, 6);
  439. time.setOpenTime(openTime);
  440. System.out.println(openTime);
  441. int timeCost = (int) (openTime.getTime() - closeTime.getTime());
  442. time.setTimeCost(timeCost);
  443. }
  444. } else {
  445. logger.info("本次开合模次数==0");
  446. }
  447. }
  448. }