|
@@ -0,0 +1,365 @@
|
|
|
+package com.huimv.input.server;
|
|
|
+
|
|
|
+import cn.hutool.core.util.ObjectUtil;
|
|
|
+import com.alibaba.fastjson.JSONArray;
|
|
|
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
|
|
+import com.huimv.input.entity.*;
|
|
|
+import com.huimv.input.mapper.*;
|
|
|
+import com.huimv.input.utils.ModBusUtils;
|
|
|
+import io.netty.buffer.ByteBuf;
|
|
|
+import io.netty.buffer.Unpooled;
|
|
|
+import io.netty.channel.*;
|
|
|
+import lombok.extern.slf4j.Slf4j;
|
|
|
+import org.springframework.beans.factory.annotation.Autowired;
|
|
|
+import org.springframework.stereotype.Component;
|
|
|
+import org.springframework.transaction.annotation.Transactional;
|
|
|
+
|
|
|
+import java.io.IOException;
|
|
|
+import java.math.BigDecimal;
|
|
|
+import java.text.ParseException;
|
|
|
+import java.text.SimpleDateFormat;
|
|
|
+import java.util.*;
|
|
|
+import java.util.regex.Matcher;
|
|
|
+import java.util.regex.Pattern;
|
|
|
+
|
|
|
+
|
|
|
+/**
|
|
|
+ * @Project : huimv.shiwan
|
|
|
+ * @Package : com.huimv.biosafety.uface.controller
|
|
|
+ * @Description : TODO
|
|
|
+ * @Version : 1.0
|
|
|
+ * @Author : ZhuoNing
|
|
|
+ * @Create : 2020-12-25
|
|
|
+ **/
|
|
|
+@ChannelHandler.Sharable
|
|
|
+@Component
|
|
|
+@Slf4j
|
|
|
+public class EnvInputServerHandler extends ChannelInboundHandlerAdapter {
|
|
|
+ private StringBuilder askTextSb = null;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private RawDataMapper rawDataMapper;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private EnvRegularCallEggMapper envRegularCallEggMapper;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private EnvRegularCallFeedingMapper envRegularCallFeedingMapper;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private EnvDeviceMapper envDeviceMapper;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private BaseDuckInfoMapper baseDuckInfoMapper;
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ //
|
|
|
+ public void appendClientAsk(String text) {
|
|
|
+ if (this.askTextSb == null) {
|
|
|
+ askTextSb = new StringBuilder();
|
|
|
+ }
|
|
|
+ askTextSb.append(text);
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
|
|
|
+ ByteBuf byteBuf = (ByteBuf) msg;
|
|
|
+
|
|
|
+ byte[] bytes = new byte[byteBuf.readableBytes()];
|
|
|
+ byteBuf.readBytes(bytes);
|
|
|
+ String str = ModBusUtils.bytes2HexString(bytes);
|
|
|
+ ctx.writeAndFlush("10001");
|
|
|
+ System.out.println("收到的数据:"+str);
|
|
|
+ saveWeight(str,bytes);
|
|
|
+ System.out.println("保存成功");
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ public synchronized void saveWeight(String str, byte[] bytes) {
|
|
|
+ String[] s = str.split(" ");
|
|
|
+ String hexId = s[5] + s[4] + s[3] + s[2] ;
|
|
|
+ System.out.println("十六进制id"+hexId);
|
|
|
+ int decId = Integer.parseInt(hexId, 16);
|
|
|
+ System.out.println("十进制id"+decId);
|
|
|
+ long l = System.currentTimeMillis();
|
|
|
+
|
|
|
+ String bat = s[8] + s[7] ;
|
|
|
+
|
|
|
+ //获取上次一次数据
|
|
|
+ RawData lastRawData = rawDataMapper.selectOne(new QueryWrapper<RawData>().eq("device_code", decId).orderByDesc("id").last("limit 1"));
|
|
|
+ BigDecimal lastWeight = new BigDecimal(0);
|
|
|
+ if (ObjectUtil.isNotEmpty(lastRawData)){
|
|
|
+ lastWeight = lastRawData.getLastWeight();
|
|
|
+ }
|
|
|
+ int sLength = s.length;
|
|
|
+ //保存原始数据
|
|
|
+ RawData rawData = new RawData();
|
|
|
+ rawData.setDeviceCode(decId+"");
|
|
|
+ rawData.setData(str);
|
|
|
+ rawData.setCreateTime(new Date(l));
|
|
|
+ rawData.setLastWeight(new BigDecimal(Integer.parseInt(s[sLength -2]+s[sLength-3], 16)));
|
|
|
+ rawDataMapper.insert(rawData);
|
|
|
+ //获取设备
|
|
|
+ EnvDevice envDevice = envDeviceMapper.selectOne(new QueryWrapper<EnvDevice>().eq("device_code", decId).eq("device_type", 3));
|
|
|
+ if (ObjectUtil.isEmpty(envDevice)){
|
|
|
+ System.out.println("固定电子称不存在,数据抛弃");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ //获取鸭子
|
|
|
+ Integer unitId = envDevice.getUnitId();
|
|
|
+ BaseDuckInfo baseDuckInfo = baseDuckInfoMapper.selectOne(new QueryWrapper<BaseDuckInfo>().eq("unit_id", unitId).eq("is_cage", 0));
|
|
|
+ if (ObjectUtil.isEmpty(baseDuckInfo)){
|
|
|
+ System.out.println("该位置不存在鸭子,数据抛弃");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ try {
|
|
|
+
|
|
|
+ //循环获取体重
|
|
|
+ for (int i = 0; i < 60; i++) {
|
|
|
+ //当时时间
|
|
|
+ Date thenTime = new Date(l - ((60-i)*10000));
|
|
|
+ //
|
|
|
+ String str1 = s[i * 2 + 11] + s[i * 2 + 10];
|
|
|
+ BigDecimal weight = new BigDecimal(Integer.parseInt(str1,16));
|
|
|
+ BigDecimal subtract = weight.subtract(lastWeight);
|
|
|
+ int compare = subtract.compareTo(new BigDecimal(1500));
|
|
|
+ System.out.println(subtract +"------>"+weight+"----------->"+lastWeight);
|
|
|
+ EnvRegularCallFeeding envRegularCallFeeding = new EnvRegularCallFeeding();
|
|
|
+ envRegularCallFeeding.setBattery(new BigDecimal(Integer.parseInt(bat, 16)).divide(new BigDecimal(10), 1, BigDecimal.ROUND_HALF_UP).toString());
|
|
|
+ envRegularCallFeeding.setCallDate(thenTime);
|
|
|
+ envRegularCallFeeding.setCallCode(decId+"");
|
|
|
+ envRegularCallFeeding.setCallName(envDevice.getDeviceName());
|
|
|
+ envRegularCallFeeding.setDuckId(baseDuckInfo.getId());
|
|
|
+ envRegularCallFeeding.setDuckNum(baseDuckInfo.getDuckNum());
|
|
|
+ envRegularCallFeeding.setFarmId(baseDuckInfo.getFarmId());
|
|
|
+ envRegularCallFeeding.setUnitId(baseDuckInfo.getUnitId());
|
|
|
+ envRegularCallFeeding.setUnitName(baseDuckInfo.getUnitName());
|
|
|
+ if (weight.compareTo(new BigDecimal(0) )==0){
|
|
|
+ envRegularCallFeeding.setDuckFeedingOriginal((new BigDecimal(0)));
|
|
|
+ }else {
|
|
|
+ envRegularCallFeeding.setDuckFeedingOriginal(weight.divide(new BigDecimal(10), 1, BigDecimal.ROUND_HALF_UP) );
|
|
|
+ }
|
|
|
+ if (subtract.compareTo(new BigDecimal(0) )==0){
|
|
|
+ envRegularCallFeeding.setDuckWeight((new BigDecimal(0)));
|
|
|
+ }else {
|
|
|
+ envRegularCallFeeding.setDuckWeight(subtract.divide(new BigDecimal(10), 1, BigDecimal.ROUND_HALF_UP) );
|
|
|
+ }
|
|
|
+
|
|
|
+ //加料
|
|
|
+ if (compare>0){
|
|
|
+ envRegularCallFeeding.setEventType(1);
|
|
|
+ envRegularCallFeedingMapper.insert(envRegularCallFeeding);
|
|
|
+ lastWeight =weight;
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ int compare50 = subtract.compareTo(new BigDecimal(300));
|
|
|
+ //下蛋
|
|
|
+ if (compare50>0){
|
|
|
+ EnvRegularCallEgg envRegularCallEgg = new EnvRegularCallEgg();
|
|
|
+ envRegularCallEgg.setBattery(bat);
|
|
|
+ envRegularCallEgg.setCallDate(thenTime);
|
|
|
+ envRegularCallEgg.setCallCode(decId+"");
|
|
|
+ envRegularCallEgg.setCallName(envDevice.getDeviceName());
|
|
|
+ envRegularCallEgg.setDuckId(baseDuckInfo.getId());
|
|
|
+ envRegularCallEgg.setDuckNum(baseDuckInfo.getDuckNum());
|
|
|
+ envRegularCallEgg.setFarmId(baseDuckInfo.getFarmId());
|
|
|
+ envRegularCallEgg.setUnitId(baseDuckInfo.getUnitId());
|
|
|
+ envRegularCallEgg.setUnitName(baseDuckInfo.getUnitName());
|
|
|
+ envRegularCallEgg.setEggNum(1);
|
|
|
+ if (weight.compareTo(new BigDecimal(0) )==0){
|
|
|
+ envRegularCallEgg.setDuckFeedingOriginal((new BigDecimal(0)));
|
|
|
+ }else {
|
|
|
+ envRegularCallEgg.setDuckFeedingOriginal(weight.divide(new BigDecimal(10), 1, BigDecimal.ROUND_HALF_UP) );
|
|
|
+ }
|
|
|
+ if (subtract.compareTo(new BigDecimal(0) )==0){
|
|
|
+ envRegularCallEgg.setDuckWeight((new BigDecimal(0)));
|
|
|
+ }else {
|
|
|
+ envRegularCallEgg.setDuckWeight(subtract.divide(new BigDecimal(10), 1, BigDecimal.ROUND_HALF_UP) );
|
|
|
+ }
|
|
|
+ envRegularCallEggMapper.insert(envRegularCallEgg);
|
|
|
+ lastWeight =weight;
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ int compare0 = subtract.compareTo(new BigDecimal(0));
|
|
|
+ //吃料
|
|
|
+ if (compare0<=0){
|
|
|
+ if (subtract.compareTo(new BigDecimal(0) )==0){
|
|
|
+ envRegularCallFeeding.setDuckWeight((new BigDecimal(0)));
|
|
|
+ }else {
|
|
|
+ envRegularCallFeeding.setDuckWeight(subtract.subtract(subtract.multiply(new BigDecimal(2))).divide(new BigDecimal(10), 1, BigDecimal.ROUND_HALF_UP));
|
|
|
+ }
|
|
|
+ envRegularCallFeeding.setEventType(0);
|
|
|
+ envRegularCallFeedingMapper.insert(envRegularCallFeeding);
|
|
|
+ lastWeight =weight;
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ //其它
|
|
|
+ envRegularCallFeeding.setEventType(2);
|
|
|
+ envRegularCallFeedingMapper.insert(envRegularCallFeeding);
|
|
|
+ }
|
|
|
+ }catch (Exception e){
|
|
|
+ System.out.println(e);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
|
|
|
+
|
|
|
+// if (true){
|
|
|
+// ctx.writeAndFlush(Unpooled.copiedBuffer(new byte[]{1, 2, 3}));
|
|
|
+// }
|
|
|
+
|
|
|
+// if (askTextSb.toString().indexOf("end") != -1) {
|
|
|
+// // {处理客户端消息}
|
|
|
+
|
|
|
+
|
|
|
+// handleClientAskCmd(askTextSb.toString(), ctx);
|
|
|
+// //清空重置;
|
|
|
+// askTextSb.delete(0, askTextSb.length());
|
|
|
+// }
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
|
|
|
+ if (cause.getMessage().indexOf("Connection reset") != -1) {
|
|
|
+ log.info("相关采集器设备正在重启:" + cause.toString());
|
|
|
+ }
|
|
|
+// cause.printStackTrace();
|
|
|
+ ctx.close();
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * @Method : handleClientAskCmd
|
|
|
+ * @Description : 处理请求小心
|
|
|
+ * @Params : [clientAskText, ctx]
|
|
|
+ * @Return : void
|
|
|
+ * @Author : ZhuoNing
|
|
|
+ * @Date : 2022/3/28
|
|
|
+ * @Time : 17:36
|
|
|
+ */
|
|
|
+ private void handleClientAskCmd(String clientAskText, ChannelHandlerContext ctx) throws ParseException, IOException {
|
|
|
+ clientAskText = clientAskText.replaceAll("\r", "").replaceAll("\n", "");
|
|
|
+ //{处理非正常命令}
|
|
|
+// int countPlus = regexUtil.countPlus(clientAskText);
|
|
|
+// if (countPlus < 4) {
|
|
|
+// System.out.println("当前数据为不完整数据,故丢弃.>>" + clientAskText);
|
|
|
+// } else {
|
|
|
+ //--处理客户端请求数据
|
|
|
+ //{拆分粘包数据}
|
|
|
+ JSONArray askJa = parseAskCmdPackage(clientAskText);
|
|
|
+ for (int a = 0; a < askJa.size(); a++) {
|
|
|
+ String askText = askJa.getString(a);
|
|
|
+ //{处理请求命令}
|
|
|
+ askCmdActuator(askText, ctx);
|
|
|
+ }
|
|
|
+// }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * @Method : askCmdActuator
|
|
|
+ * @Description :
|
|
|
+ * @Params : [askText, ctx]
|
|
|
+ * @Return : void
|
|
|
+ * @Author : ZhuoNing
|
|
|
+ * @Date : 2022/3/23
|
|
|
+ * @Time : 18:08
|
|
|
+ */
|
|
|
+ private void askCmdActuator(String askText, ChannelHandlerContext ctx) throws ParseException, IOException {
|
|
|
+ System.out.println("======>接收设备请求:" + askText);
|
|
|
+ String[] dataArray = askText.split("\\+");
|
|
|
+ String cmdHeader = dataArray[0];
|
|
|
+ if (!cmdHeader.trim().equalsIgnoreCase("hm")) {
|
|
|
+ log.info("当前命令是非hm命令[" + askText + "]");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ //芯片id/设备编码
|
|
|
+ String idCode = dataArray[1];
|
|
|
+ String cmd = dataArray[2];
|
|
|
+ Map map = new HashMap();
|
|
|
+ map.put("askText", askText);
|
|
|
+ switch (cmd) {
|
|
|
+ case "1":
|
|
|
+ //获取远程设备编码
|
|
|
+ getDeviceCode(askText, idCode, ctx);
|
|
|
+ break;
|
|
|
+ case "2":
|
|
|
+ //同步时间
|
|
|
+ getServerTime(askText, idCode, ctx);
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ System.out.println("==>未知命令");
|
|
|
+ log.error(">>当前数据为非法数据-未知命令>>" + askText);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ //时间同步请求
|
|
|
+ private void getServerTime(String askText, String deviceCode, ChannelHandlerContext ctx) throws ParseException {
|
|
|
+ System.out.println("==>时间同步请求:" + askText);
|
|
|
+// if (!cmdProService.isEffectiveDevice(deviceCode)) {
|
|
|
+// System.out.println("##时间同步请求-未注册设备 idCode=" + deviceCode);
|
|
|
+// return;
|
|
|
+// }
|
|
|
+ String answerText = "hm+2+" + "+0+4+end";
|
|
|
+// log.info(">>时间同步请求-应答数据>>" + answerText);
|
|
|
+ answerCmd(answerText, ctx);
|
|
|
+ }
|
|
|
+
|
|
|
+ //获取远程设备编码
|
|
|
+ private void getDeviceCode(String askText, String idCode, ChannelHandlerContext ctx) {
|
|
|
+ System.out.println("==>获取远程设备编码请求:" + askText.trim());
|
|
|
+ //{读取设备编码}
|
|
|
+// String deviceCode = cmdProService.getDeviceCodeByChipId(idCode);
|
|
|
+// log.info("获取远程设备编码请求,芯片id>>" + idCode + " ,deviceCode>>" + deviceCode);
|
|
|
+// if (deviceCode == null) {
|
|
|
+// log.error("该设备未注册,已舍弃请求.");
|
|
|
+// return;
|
|
|
+// }
|
|
|
+// String answerText = "hm+1+0+" + deviceCode + "+123+8+end";
|
|
|
+// log.info("<<获取远程设备编码请求-应答数据:" + answerText);
|
|
|
+ //{应答指令}
|
|
|
+// answerCmd(answerText, ctx);
|
|
|
+ }
|
|
|
+
|
|
|
+ //应答
|
|
|
+ public void answerCmd(String answerText, ChannelHandlerContext ctx) {
|
|
|
+ ctx.writeAndFlush(Unpooled.copiedBuffer(answerText.getBytes()));
|
|
|
+ }
|
|
|
+
|
|
|
+ //检查无效耳标
|
|
|
+ public boolean checkValidEarmark(String earmark) {
|
|
|
+ if (earmark.trim().equalsIgnoreCase("ffffffffffffffff") || earmark.trim().equalsIgnoreCase("0000000000000000")) {
|
|
|
+ return true;
|
|
|
+ } else {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ //拆分粘包数据
|
|
|
+ public JSONArray parseAskCmdPackage(String text) {
|
|
|
+ String key = "end";
|
|
|
+ Pattern pattern = Pattern.compile(key);
|
|
|
+ Matcher matcher = pattern.matcher(text);
|
|
|
+ int count = 0;
|
|
|
+ while (matcher.find()) {
|
|
|
+ count++;
|
|
|
+ }
|
|
|
+ JSONArray dataJa = new JSONArray();
|
|
|
+ if (count == 1) {
|
|
|
+ dataJa.add(text);
|
|
|
+ } else {
|
|
|
+ for (int a = 0; a < count; a++) {
|
|
|
+ int p1 = text.indexOf("end");
|
|
|
+ dataJa.add(text.substring(0, p1 + 3));
|
|
|
+ text = text.substring(p1 + 3, text.length());
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return dataJa;
|
|
|
+ }
|
|
|
+}
|