Procházet zdrojové kódy

完成重建心跳和环境温度的流程和优化工作。

zhuoning před 3 roky
rodič
revize
d829265ff2
17 změnil soubory, kde provedl 2045 přidání a 0 odebrání
  1. 55 0
      huimv-eartag2-platform/huimv-eartag2-device/pom.xml
  2. 28 0
      huimv-eartag2-platform/huimv-eartag2-device/src/main/java/com/huimv/eartag2/device/HuimvEartag2DeviceApplication.java
  3. 65 0
      huimv-eartag2-platform/huimv-eartag2-device/src/main/java/com/huimv/eartag2/device/config/TopicRabbitMQConfig.java
  4. 179 0
      huimv-eartag2-platform/huimv-eartag2-device/src/main/java/com/huimv/eartag2/device/listener/DeviceListener.java
  5. 51 0
      huimv-eartag2-platform/huimv-eartag2-device/src/main/java/com/huimv/eartag2/device/producer/ProcessProducer.java
  6. 69 0
      huimv-eartag2-platform/huimv-eartag2-device/src/main/java/com/huimv/eartag2/device/service/ICacheService.java
  7. 24 0
      huimv-eartag2-platform/huimv-eartag2-device/src/main/java/com/huimv/eartag2/device/service/IDeviceService.java
  8. 16 0
      huimv-eartag2-platform/huimv-eartag2-device/src/main/java/com/huimv/eartag2/device/service/IEartagService.java
  9. 401 0
      huimv-eartag2-platform/huimv-eartag2-device/src/main/java/com/huimv/eartag2/device/service/impl/CacheServiceImpl.java
  10. 571 0
      huimv-eartag2-platform/huimv-eartag2-device/src/main/java/com/huimv/eartag2/device/service/impl/DeviceServiceImpl.java
  11. 169 0
      huimv-eartag2-platform/huimv-eartag2-device/src/main/java/com/huimv/eartag2/device/service/impl/EartagServiceImpl.java
  12. 20 0
      huimv-eartag2-platform/huimv-eartag2-device/src/main/java/com/huimv/eartag2/device/task/TestTask.java
  13. 12 0
      huimv-eartag2-platform/huimv-eartag2-device/src/main/java/com/huimv/eartag2/device/utils/BaseTemplete.java
  14. 187 0
      huimv-eartag2-platform/huimv-eartag2-device/src/main/java/com/huimv/eartag2/device/utils/DateUtil.java
  15. 90 0
      huimv-eartag2-platform/huimv-eartag2-device/src/main/java/com/huimv/eartag2/device/utils/MathUtil.java
  16. 107 0
      huimv-eartag2-platform/huimv-eartag2-device/src/main/resources/application-dev.yml
  17. 1 0
      huimv-eartag2-platform/huimv-eartag2-device/src/main/resources/application.properties

+ 55 - 0
huimv-eartag2-platform/huimv-eartag2-device/pom.xml

@@ -11,5 +11,60 @@
 
     <artifactId>huimv-eartag2-device</artifactId>
 
+    <dependencies>
+        <!-- 排除Tomcat容器 -->
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-web</artifactId>
+            <!-- 移除掉默认支持的 Tomcat -->
+            <exclusions>
+                <exclusion>
+                    <groupId>org.springframework.boot</groupId>
+                    <artifactId>spring-boot-starter-tomcat</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+        <!-- 添加 Undertow 容器 -->
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-undertow</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-test</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <!-- eartag2-common -->
+        <dependency>
+            <groupId>com.huimv</groupId>
+            <artifactId>huimv-eartag2-common</artifactId>
+            <version>0.0.1-SNAPSHOT</version>
+        </dependency>
+        <!--rabbitmq-->
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-amqp</artifactId>
+        </dependency>
+        <!-- actuator -->
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-actuator</artifactId>
+        </dependency>
+    </dependencies>
 
+    <build>
+        <plugins>
+            <!--  -->
+            <plugin>
+                <groupId>org.springframework.boot</groupId>
+                <artifactId>spring-boot-maven-plugin</artifactId>
+            </plugin>
+            <!--  -->
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-resources-plugin</artifactId>
+                <version>2.6</version>
+            </plugin>
+        </plugins>
+    </build>
 </project>

+ 28 - 0
huimv-eartag2-platform/huimv-eartag2-device/src/main/java/com/huimv/eartag2/device/HuimvEartag2DeviceApplication.java

@@ -0,0 +1,28 @@
+package com.huimv.eartag2.device;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.autoconfigure.domain.EntityScan;
+import org.springframework.context.annotation.ComponentScan;
+import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
+import org.springframework.scheduling.annotation.EnableScheduling;
+
+/**
+ * @Project : huimv.shiwan
+ * @Package : com.huimv.biosafety.uface.controller
+ * @Description : TODO
+ * @Version : 1.0
+ * @Author : ZhuoNing
+ * @Create : 2020-12-25
+ **/
+//@ComponentScan(basePackages = {"com.huimv.eartag2.common.utils"})
+@EntityScan(value = "com.huimv.eartag2.common.dao.entity")
+@EnableJpaRepositories(basePackages = "com.huimv.eartag2.common.dao.repo")
+//@ComponentScan(value="com.huimv.eartag2.common.service")
+@SpringBootApplication
+@EnableScheduling
+public class HuimvEartag2DeviceApplication {
+    public static void main(String[] args) {
+        SpringApplication.run(HuimvEartag2DeviceApplication.class, args);
+    }
+}

+ 65 - 0
huimv-eartag2-platform/huimv-eartag2-device/src/main/java/com/huimv/eartag2/device/config/TopicRabbitMQConfig.java

@@ -0,0 +1,65 @@
+package com.huimv.eartag2.device.config;
+
+import com.huimv.eartag2.common.mq.Const;
+import org.springframework.amqp.core.Binding;
+import org.springframework.amqp.core.BindingBuilder;
+import org.springframework.amqp.core.Queue;
+import org.springframework.amqp.core.TopicExchange;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+/**
+ * @Project : huimv.shiwan
+ * @Package : com.huimv.biosafety.uface.controller
+ * @Description : TODO
+ * @Version : 1.0
+ * @Author : ZhuoNing
+ * @Create : 2020-12-25
+ **/
+@Configuration
+public class TopicRabbitMQConfig {
+    //心跳
+    @Bean
+    public Queue heartbeatQueue() {
+        return new Queue(Const.QUEUE_DEVICE_HEARTBEAT);
+    }
+    //采集器温度
+    @Bean
+    public Queue deviceTempQueue() {
+        return new Queue(Const.QUEUE_DEVICE_TEMP);
+    }
+    //耳标数据
+    @Bean
+    public Queue eartagQueue() {
+        return new Queue(Const.QUEUE_EARTAG);
+    }
+
+    //采集器设备交换机
+//    @Bean
+    TopicExchange deviceExchange() {
+        return new TopicExchange(Const.EXCHANGE_DEVICE);
+    }
+
+    //耳标交换机
+//    @Bean
+    TopicExchange eartagExchange() {
+        return new TopicExchange(Const.EXCHANGE_EARTAG);
+    }
+
+    //设备交换机、心跳队列、心跳路由键绑定
+    @Bean
+    Binding bindingHeartbeatExchangeMessage() {
+        return BindingBuilder.bind(heartbeatQueue()).to(deviceExchange()).with(Const.ROUTING_KEY_DEVICE_HEARTBEAT);
+    }
+    //设备交换机、设备环境温度队列、设备环境路由键绑定
+    @Bean
+    Binding bindingDeviceTempExchangeMessage() {
+        return BindingBuilder.bind(deviceTempQueue()).to(deviceExchange()).with(Const.ROUTING_KEY_DEVICE_TEMP);
+    }
+    //耳标交换机、耳标队列、耳标路由键绑定
+    @Bean
+    Binding bindingEartagExchangeMessage() {
+        return BindingBuilder.bind(eartagQueue()).to(eartagExchange()).with(Const.ROUTING_KEY_EARTAG);
+    }
+
+}

+ 179 - 0
huimv-eartag2-platform/huimv-eartag2-device/src/main/java/com/huimv/eartag2/device/listener/DeviceListener.java

@@ -0,0 +1,179 @@
+package com.huimv.eartag2.device.listener;
+
+import com.alibaba.fastjson.JSONObject;
+import com.huimv.eartag2.common.mq.Const;
+import com.huimv.eartag2.common.utils.MathUtil;
+import com.huimv.eartag2.device.producer.ProcessProducer;
+import com.huimv.eartag2.device.service.IDeviceService;
+import com.huimv.eartag2.device.service.IEartagService;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.amqp.rabbit.annotation.RabbitHandler;
+import org.springframework.amqp.rabbit.annotation.RabbitListener;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import java.math.BigDecimal;
+import java.text.ParseException;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @Project : huimv.shiwan
+ * @Package : com.huimv.biosafety.uface.controller
+ * @Description : TODO
+ * @Version : 1.0
+ * @Author : ZhuoNing
+ * @Create : 2020-12-25
+ **/
+@Component
+@Slf4j
+public class DeviceListener {
+    @Autowired
+    private IDeviceService deviceService;
+    @Autowired
+    private IEartagService eartagService;
+    @Autowired
+    private ProcessProducer processProducer;
+
+    /**
+     * @Method      : processRawdata
+     * @Description : 
+     * @Params      : [RawMap]
+     * @Return      : void
+     * 
+     * @Author      : ZhuoNing
+     * @Date        : 2022/3/12       
+     * @Time        : 17:28
+     */
+    @RabbitListener(queues = Const.QUEUE_ASK_DEVICE)
+    @RabbitHandler
+    public void processRawdata(Map RawMap) throws ParseException {
+//        System.out.println("<<<<<<<<<<<<<<< RawMap>>"+RawMap.toString());
+        String askText = RawMap.get("askText").toString();
+//        System.out.println("askText>>"+askText);
+//        System.out.println(" >>>>>>>>>>>>>>>>>>>>>>>> 处理设备队列 >>>>>>>>>>>>>>>>>>>>>>>>");
+        //本模块主要执行保存以下4类数据:(其他注册数据,在线数据,状态数据等都是由其他模块工程执行处理-process2模块工程)
+        //--保存原始流水数据(原始流水表)
+        //--保存设备心跳流水数据(设备心跳流水表)
+        //--保存设备环境流水数据(设备温度流水表)
+        //--保存耳标流水数据(耳标流水表)
+
+        //处理请求报文//
+        Map askMap = handleAskText(askText);
+        System.out.println("## askMap>>"+askMap.toString());
+        String type = askMap.get("type").toString();
+        JSONObject dataJo = (JSONObject) askMap.get("data");
+        if(type.trim().equalsIgnoreCase("device-heartbeat")){
+            //--(1)处理心跳数据
+            //--保存设备心跳流水数据(MySQL)
+
+            //保存心跳流水数据
+//            deviceService.saveDeviceHeartbeat(dataJo);
+            //发送心跳数据到MQ
+//            processProducer.sendHeartbeat(dataJo);
+            System.out.println("处理心跳");
+            System.out.println("askText>>"+askText);
+            //{处理设备心跳数据}
+            deviceService.handleDeviceHeartbeat(dataJo);
+            /////////////////////////////////////////////////////////////////////////////////////////////////////////
+        }else if(type.trim().equalsIgnoreCase("device-temp")){
+            //--(2)处理环境数据
+            //--保存设备环境流水数据(MySQL)
+
+            //保存设备环境温度流水数据
+//            deviceService.saveDeviceTemp(dataJo);
+            //发送设备环境温度数据到MQ
+//            processProducer.sendDeviceTemp(dataJo);
+            System.out.println("处理环境温度");
+            System.out.println("askText>>"+askText);
+            //{处理设备环境温度数据}
+            deviceService.handleDeviceEnvtemp(dataJo);
+            /////////////////////////////////////////////////////////////////////////////////////////////////////////
+        }
+    }
+
+    /**
+     * @Method      : handleAskText
+     * @Description : 
+     * @Params      : [askText]
+     * @Return      : java.util.Map
+     * 
+     * @Author      : ZhuoNing
+     * @Date        : 2022/3/12       
+     * @Time        : 17:27
+     */
+    private Map handleAskText(String askText) {
+        Map outMap = new HashMap();
+        JSONObject dataJo = new JSONObject();
+        String type = "";
+        String[] dataArray = askText.split("\\+");
+        String cmdHeader = dataArray[0];
+        if (cmdHeader.trim().equalsIgnoreCase("hm")) {
+            //采集器原始数据
+            String device = dataArray[1];
+            String cmd = dataArray[2];
+            if (cmd.trim().equalsIgnoreCase("0")) {
+                //不需要处理
+            } else if (cmd.trim().equalsIgnoreCase("1")) {
+                //获取设备编码
+            } else if (cmd.trim().equalsIgnoreCase("2")) {
+                //获取服务器时间命令
+            } else if (cmd.trim().equalsIgnoreCase("3")) {
+                //心跳包命令
+                dataJo.put("device", device);
+                type = "device-heartbeat";
+            } else if (cmd.trim().equalsIgnoreCase("4")) {
+                //环境温度-设备、数值、上传时间
+                dataJo.put("device", dataArray[1]);
+                dataJo.put("temp", dataArray[4]);
+                dataJo.put("askTime", dataArray[5]);
+                type = "device-temp";
+            } else {
+                log.error("##当前数据为非法数据>>" + askText);
+            }
+        } else if (cmdHeader.trim().equalsIgnoreCase("zj")) {
+//            String device = dataArray[1];
+            //-- 耳标数据 --//
+            //计算耳标温度
+            Double earTemp = 0D;
+            String other = dataArray[9];
+            if (other != null && other.trim().length() > 0) {
+                String[] otherArray = other.split("#");
+                String resi = otherArray[2];
+                int resiInt = Integer.parseInt(resi);
+                if(resiInt != 0){
+                    Double temp = MathUtil.ln(resiInt);
+                    earTemp = new BigDecimal(temp).setScale(1, BigDecimal.ROUND_HALF_UP).doubleValue();
+                }
+            }
+            //计算运动量//
+            Integer act1Int = eartagService.countAct(dataArray[1], dataArray[6]);
+            //命令头
+            dataJo.put("cmdHeader", dataArray[0]);
+            //采集器id
+            dataJo.put("device", dataArray[1]);
+            //耳标号
+            dataJo.put("earmark", dataArray[2]);
+            //电池电量
+            dataJo.put("bat", dataArray[3]);
+            //耳标温度
+            dataJo.put("earTemp", dataArray[4]);
+            dataJo.put("earTemp1", earTemp);
+            //环境温度
+            dataJo.put("envTemp", dataArray[5]);
+            //运动量
+            dataJo.put("act", dataArray[6]);
+            dataJo.put("act1", act1Int);
+            //信号强度
+            dataJo.put("signal", dataArray[7]);
+            //采集时间
+            dataJo.put("askTime", dataArray[8]);
+            //预留字段
+            dataJo.put("other", dataArray[9]);
+            type = "eartag";
+        }
+        outMap.put("type",type);
+        outMap.put("data",dataJo);
+        return outMap;
+    }
+}

+ 51 - 0
huimv-eartag2-platform/huimv-eartag2-device/src/main/java/com/huimv/eartag2/device/producer/ProcessProducer.java

@@ -0,0 +1,51 @@
+package com.huimv.eartag2.device.producer;
+
+import com.alibaba.fastjson.JSONObject;
+import com.huimv.eartag2.common.mq.Const;
+import org.springframework.amqp.rabbit.core.RabbitTemplate;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @Project : huimv.shiwan
+ * @Package : com.huimv.biosafety.uface.controller
+ * @Description : TODO
+ * @Version : 1.0
+ * @Author : ZhuoNing
+ * @Create : 2020-12-25
+ **/
+@Component
+public class ProcessProducer {
+    @Autowired
+    RabbitTemplate rabbitTemplate;  //使用RabbitTemplate,这提供了接收/发送等等方法
+
+    //处理心跳数据
+    public String sendHeartbeat(JSONObject dataJo) {
+        Map map = new HashMap();
+        map.put("heartbeat",dataJo.toString());
+        rabbitTemplate.convertAndSend(Const.EXCHANGE_DEVICE, Const.ROUTING_KEY_DEVICE_HEARTBEAT, map);
+        System.out.println("处理心跳 >>"+dataJo);
+        return "ok";
+    }
+
+    //处理环境温度数据
+    public String sendDeviceTemp(JSONObject dataJo) {
+        Map map = new HashMap();
+        map.put("deviceTemp",dataJo);
+        rabbitTemplate.convertAndSend(Const.EXCHANGE_DEVICE, Const.ROUTING_KEY_DEVICE_TEMP, map);
+        System.out.println("处理环境温度 >>"+dataJo);
+        return "ok";
+    }
+
+    //处理耳标数据
+    public String sendEartag(JSONObject dataJo) {
+        Map map = new HashMap();
+        map.put("eartag",dataJo);
+        rabbitTemplate.convertAndSend(Const.EXCHANGE_EARTAG, Const.ROUTING_KEY_EARTAG, map);
+        System.out.println("处理耳标数据 >>"+dataJo);
+        return "ok";
+    }
+}

+ 69 - 0
huimv-eartag2-platform/huimv-eartag2-device/src/main/java/com/huimv/eartag2/device/service/ICacheService.java

@@ -0,0 +1,69 @@
+package com.huimv.eartag2.device.service;
+
+import com.huimv.eartag2.common.dao.entity.*;
+
+import java.text.ParseException;
+
+public interface ICacheService {
+    //证是否存在当天总状态数据
+    Boolean isExistTodayFarmAllStatus(String deviceCode) throws ParseException;
+
+    //
+    Object getFarmIdByDeviceCode(String deviceCode);
+
+    //
+    Object getCreateDateByFarmId(String farmId);
+
+    //
+    void putFarmAllStatusCache(String farmId, EartarFarmAllStatusEntity farmAllStatusEntity) throws ParseException;
+
+    //
+    void putAllFarmAllStatusCache(String farmId, EartarFarmAllStatusEntity farmAllStatusEntity) throws ParseException;
+
+    //
+    void flashAllStatusCache(String farmId, EartarFarmAllStatusEntity farmAllStatusEntity);
+
+    //判断是否在线状态
+    boolean isExistDeviceOnlineSet(String farmId, String deviceCode, String todayDateText);
+
+    //将deviceCode加入到在线缓存当中
+    void putDeviceToOnline(String farmId, String deviceCode, String todayDateText);
+
+    //
+    void putDeviceRegister(String deviceCode, EartagDeviceRegisterEntity deviceRegisterEntity);
+
+    //将设备数据保存到在线数据中
+    void putDeviceInOnline(String deviceOnlineHashKey, EartagDeviceOnlineEntity eartagDeviceOnlineEntity);
+
+    //
+    boolean isExistEartagOnlineSet(String farmId, String earmark, String todayDateText);
+
+
+    void putEartagToOnlineInSet(String farmId, String earmark, String todayDateText) throws ParseException;
+
+    //从缓存读取在线耳标数量
+    Integer getEartagOnlineTotalFromCache(String farmId, String todayDateText);
+
+    //更新耳标注册消息缓存
+    void putEartagRegister(String earmark, EartagEartagRegisterEntity eartagRegisterEntity);
+
+    //更新耳标在线统计
+    void putEartagOnlineCount(String earmark, EartagEartagOnlineEntity eartagOnlineEntity);
+
+    //读取设备总数
+    Integer getDeviceTotal(String farmId);
+
+    void putDeviceTotal(Integer total, String farmId);
+
+    //读取设备取消数量
+    Integer getDeviceCancel(String farmId);
+
+    //设置设备取消缓存
+    void putDeviceCancel(Integer total, String farmId);
+
+    //读取耳标总数
+    Integer getEartagTotal(String farmId);
+
+    //设置耳标总数缓存
+    void putEartagTotal(Integer total, String farmId);
+}

+ 24 - 0
huimv-eartag2-platform/huimv-eartag2-device/src/main/java/com/huimv/eartag2/device/service/IDeviceService.java

@@ -0,0 +1,24 @@
+package com.huimv.eartag2.device.service;
+
+import com.alibaba.fastjson.JSONObject;
+
+import java.text.ParseException;
+
+public interface IDeviceService {
+    //保存心跳数据
+    void saveDeviceHeartbeat(JSONObject dataJo);
+    //保存设备温度数据
+    void saveDeviceTemp(JSONObject dataJo);
+    //保存采集器上传的原始数据
+    void saveRawdata(String askText) throws ParseException;
+
+    //处理设备心跳数据
+    void handleDeviceHeartbeat(JSONObject dataJo) throws ParseException;
+
+    //处理设备环境温度数据
+    void handleDeviceEnvtemp(JSONObject dataJo) throws ParseException;
+
+    //根据设备编码获取牧场id
+    String getFarmIdByDeviceCode(String deviceCode);
+
+}

+ 16 - 0
huimv-eartag2-platform/huimv-eartag2-device/src/main/java/com/huimv/eartag2/device/service/IEartagService.java

@@ -0,0 +1,16 @@
+package com.huimv.eartag2.device.service;
+
+import com.alibaba.fastjson.JSONObject;
+
+public interface IEartagService {
+    //计算运动量
+    Integer countAct(String deviceCode, String nowAct);
+    //保存耳标数据
+    void saveEartag(JSONObject dataJo);
+
+    //
+    Integer getEartagRegTotalByFarmId(String farmId);
+
+    //
+    Integer getEartagOnelineTotal(String farmId, String todayDateText);
+}

+ 401 - 0
huimv-eartag2-platform/huimv-eartag2-device/src/main/java/com/huimv/eartag2/device/service/impl/CacheServiceImpl.java

@@ -0,0 +1,401 @@
+package com.huimv.eartag2.device.service.impl;
+
+import com.huimv.eartag2.common.dao.entity.*;
+import com.huimv.eartag2.common.dao.repo.EartagDeviceRegisterRepo;
+import com.huimv.eartag2.common.utils.BizConst;
+import com.huimv.eartag2.common.utils.DateUtil;
+import com.huimv.eartag2.device.service.ICacheService;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.stereotype.Service;
+
+import java.text.ParseException;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * @Project : huimv.shiwan
+ * @Package : com.huimv.biosafety.uface.controller
+ * @Description : TODO
+ * @Version : 1.0
+ * @Author : ZhuoNing
+ * @Create : 2020-12-25
+ **/
+@Service
+@Slf4j
+public class CacheServiceImpl implements ICacheService {
+    @Autowired
+    private RedisTemplate redisTemplate;
+    @Autowired
+    private EartagDeviceRegisterRepo eartagDeviceRegisterRepo;
+//    @Value("${redis.expire.eartag_online_set}")
+    private Integer eartagOnlineSetExpire=25;
+
+    @Override
+    public Boolean isExistTodayFarmAllStatus(String deviceCode) throws ParseException {
+        System.out.println("isExistTodayFarmAllStatus 2.deviceCode>>"+deviceCode);
+
+        //(1)从注册表缓存中(device_register_牧场id)取出牧场id,(2)如果缓存没有则从注册表(eartag_device_register)中查询00
+        //(1)
+        Object farmIdObj = redisTemplate.opsForHash().get(BizConst.DEVICE_REGISTER_PREFIX + deviceCode,"farmId");
+        System.out.println("2.farmIdObj>>"+farmIdObj);
+        String farmId = "";
+        if(farmIdObj != null){
+            farmId = farmIdObj.toString();
+        }else{
+            //(2)
+            EartagDeviceRegisterEntity eartagDeviceRegisterEntity = eartagDeviceRegisterRepo.getDeviceRegister(deviceCode);
+            System.out.println("2.eartagDeviceRegisterEntity>>"+eartagDeviceRegisterEntity.toString());
+            if(eartagDeviceRegisterEntity == null){
+                log.error("设备编号:"+deviceCode+",不存在.");
+                return null;
+            }
+            farmId = eartagDeviceRegisterEntity.getFarmId();
+        }
+        System.out.println("2.farmId>>"+farmId);
+        //从牧场总状态缓存中获取最近一次日期
+        Object createDateObj = redisTemplate.opsForHash().get(BizConst.FARM_ALL_STATUS_PREFIX + farmId,"createDate");
+        System.out.println("2.createDateObj>>"+createDateObj);
+        if(createDateObj == null){
+            //--总状态记录记录不存在
+            System.out.println("A.");
+            return false;
+        }else{
+            //
+            String createDate = createDateObj.toString();
+            System.out.println("缓存中上次操作日期 createDate>>"+createDate);
+            if(new DateUtil().getTodayDateText().trim().equalsIgnoreCase(createDate)){
+                //--当天记录存在,就返回true;
+                System.out.println("B.");
+                return true;
+            }else{
+                //--当天记录不存在,就返回false;
+                System.out.println("C.");
+                return false;
+            }
+        }
+    }
+
+    //# 读根据设备编码读取牧场id
+    @Override
+    public Object getFarmIdByDeviceCode(String deviceCode) {
+        Object farmIdObj = redisTemplate.opsForHash().get(BizConst.DEVICE_REGISTER_PREFIX + deviceCode,"farmId");
+        return farmIdObj;
+    }
+
+    @Override
+    public Object getCreateDateByFarmId(String farmId) {
+        return redisTemplate.opsForHash().get(BizConst.FARM_ALL_STATUS_PREFIX + farmId,"createDate");
+    }
+
+    @Override
+    public void putFarmAllStatusCache(String farmId, EartarFarmAllStatusEntity farmAllStatusEntity) throws ParseException {
+        DateUtil duObj = new DateUtil();
+        redisTemplate.opsForHash().put(BizConst.FARM_ALL_STATUS_PREFIX+farmId,"deviceOnline",farmAllStatusEntity.getDeviceOnline());
+        redisTemplate.opsForHash().put(BizConst.FARM_ALL_STATUS_PREFIX+farmId,"deviceOffline",farmAllStatusEntity.getDeviceOffline());
+        redisTemplate.opsForHash().put(BizConst.FARM_ALL_STATUS_PREFIX+farmId,"deviceRate",farmAllStatusEntity.getDeviceRate());
+        redisTemplate.opsForHash().put(BizConst.FARM_ALL_STATUS_PREFIX+farmId,"updateTime",duObj.formatDateTime(duObj.getTodayText()));
+    }
+
+    @Override
+    public void putAllFarmAllStatusCache(String farmId, EartarFarmAllStatusEntity farmAllStatusEntity) throws ParseException {
+        Map allStatusMap = new HashMap();
+//        allStatusMap.put("id",farmAllStatusEntity.getId());
+        allStatusMap.put("deviceTotal",farmAllStatusEntity.getDeviceTotal());
+        allStatusMap.put("deviceOnline",farmAllStatusEntity.getDeviceOnline());
+        allStatusMap.put("deviceOffline",farmAllStatusEntity.getDeviceOffline());
+        allStatusMap.put("deviceRate",farmAllStatusEntity.getDeviceRate());
+        allStatusMap.put("deviceCancel",farmAllStatusEntity.getDeviceCancel());
+        allStatusMap.put("eartagTotal",farmAllStatusEntity.getEartagTotal());
+        allStatusMap.put("eartagOnline",farmAllStatusEntity.getEartagOnline());
+        allStatusMap.put("farmId",farmId);
+//        allStatusMap.put("updateTime",duObj.formatDateTime(duObj.getTodayText()));
+//        allStatusMap.put("createDate",duObj.getTodayDate());
+        allStatusMap.put("updateTime",farmAllStatusEntity.getUpdateTime());
+        allStatusMap.put("createDate",farmAllStatusEntity.getCreateDate());
+
+//        System.out.println("allStatusMap>>"+allStatusMap.toString());
+        redisTemplate.opsForHash().putAll(BizConst.FARM_ALL_STATUS_PREFIX+farmId, allStatusMap);
+    }
+
+    @Override
+    public void flashAllStatusCache(String farmId, EartarFarmAllStatusEntity farmAllStatusEntity) {
+        Map allStatusMap = new HashMap();
+//        allStatusMap.put("id",farmAllStatusEntity.getId());
+        allStatusMap.put("deviceTotal",farmAllStatusEntity.getDeviceTotal());
+        allStatusMap.put("deviceOnline",farmAllStatusEntity.getDeviceOnline());
+        allStatusMap.put("deviceOffline",farmAllStatusEntity.getDeviceOffline());
+        allStatusMap.put("deviceRate",farmAllStatusEntity.getDeviceRate());
+        allStatusMap.put("deviceCancel",farmAllStatusEntity.getDeviceCancel());
+        allStatusMap.put("eartagTotal",farmAllStatusEntity.getEartagTotal());
+        allStatusMap.put("eartagOnline",farmAllStatusEntity.getEartagOnline());
+        allStatusMap.put("farmId",farmId);
+//        allStatusMap.put("updateTime",duObj.formatDateTime(duObj.getTodayText()));
+//        allStatusMap.put("createDate",duObj.getTodayDate());
+        allStatusMap.put("updateTime",farmAllStatusEntity.getUpdateTime());
+        allStatusMap.put("createDate",farmAllStatusEntity.getCreateDate());
+
+//        System.out.println("allStatusMap>>"+allStatusMap.toString());
+        redisTemplate.opsForHash().putAll(BizConst.FARM_ALL_STATUS_PREFIX+farmId, allStatusMap);
+    }
+
+    @Override
+    public boolean isExistDeviceOnlineSet(String farmId, String deviceCode, String todayDateText) {
+        String setKey = BizConst.SET_FARM_DEVICE_ONLINE_PREFIX + farmId+":"+todayDateText;
+        System.out.println("setKey>>"+setKey);
+        return redisTemplate.opsForSet().isMember(setKey, deviceCode);
+    }
+
+    /**
+     * @Method      : putDeviceCode
+     * @Description : 将新的设备编号加入到缓存当中;
+     * @Params      : [farmId, deviceCode]
+     * @Return      : void
+     *
+     * @Author      : ZhuoNing
+     * @Date        : 2022/3/1
+     * @Time        : 13:42
+     */
+    @Override
+    public void putDeviceToOnline(String farmId, String deviceCode, String todayDateText) {
+        String setKey = BizConst.SET_FARM_DEVICE_ONLINE_PREFIX + farmId+":"+todayDateText;
+        redisTemplate.opsForSet().add(setKey, deviceCode);
+        redisTemplate.expire(setKey,eartagOnlineSetExpire , TimeUnit.HOURS);
+    }
+
+    @Override
+    public void putDeviceRegister(String deviceCode, EartagDeviceRegisterEntity deviceRegisterEntity) {
+        //--更新redis中注册表数据
+        String deviceRegHashKey = BizConst.DEVICE_REGISTER_PREFIX + deviceCode;
+        //将Entity转为Map
+        Map registerMap = RegisterEntityToMap(deviceRegisterEntity);
+        redisTemplate.opsForHash().putAll(deviceRegHashKey, registerMap);
+    }
+
+    /**
+     * @Method      : putDeviceInOnline
+     * @Description : 将数据库中的在线数据更新对应的缓存数据中
+     * @Params      : [deviceOnlineHashKey, eartagDeviceOnlineEntity]
+     * @Return      : void
+     * 
+     * @Author      : ZhuoNing
+     * @Date        : 2022/3/1       
+     * @Time        : 16:07
+     */
+    @Override
+    public void putDeviceInOnline(String deviceCode, EartagDeviceOnlineEntity eartagDeviceOnlineEntity) {
+        Map map = new HashMap();
+//        map.put("id", eartagDeviceOnlineEntity.getId());
+        map.put("deviceCode", eartagDeviceOnlineEntity.getDeviceCode());
+        map.put("alias", eartagDeviceOnlineEntity.getAlias());
+        map.put("heartbeatTotal", eartagDeviceOnlineEntity.getHeartbeatTotal());
+        map.put("envtempTotal", eartagDeviceOnlineEntity.getEnvtempTotal());
+        map.put("eartagTotal", eartagDeviceOnlineEntity.getEartagTotal());
+        map.put("firstTime", eartagDeviceOnlineEntity.getFirstTime());
+        map.put("lastTime", eartagDeviceOnlineEntity.getLastTime());
+        map.put("lastEnvtemp", eartagDeviceOnlineEntity.getLastEnvtemp());
+        map.put("lastEartag", eartagDeviceOnlineEntity.getLastEartag());
+        map.put("addDate", eartagDeviceOnlineEntity.getAddDate());
+        map.put("farmId", eartagDeviceOnlineEntity.getFarmId());
+        //更新缓存
+        String deviceOnlineKey = BizConst.DEVICE_ONLINE_PREFIX + deviceCode;
+        redisTemplate.opsForHash().putAll(deviceOnlineKey, map);
+//        Map onlineMap = fromOnlineEntityToMap(newDeviceOnlineEntity);
+//        redisTemplate.opsForHash().putAll(deviceOnlineHashKey, onlineMap);
+    }
+
+    /**
+     * @Method      : isExistEartagOnlineStatus
+     * @Description : 
+     * @Params      : [farmId, earmark]
+     * @Return      : boolean
+     * 
+     * @Author      : ZhuoNing
+     * @Date        : 2022/3/1       
+     * @Time        : 21:18
+     */
+    @Override
+    public boolean isExistEartagOnlineSet(String farmId, String earmark, String todayDateText) {
+//        redisTemplate.opsForSet().add(BizConst.SET_FARM_DEVICE_ONLINE_PREFIX + farmId+"_"+todayDateText, earmark);
+        String setKey = BizConst.SET_FARM_EARMARK_ONLINE_PREFIX + farmId+"_"+todayDateText;
+        System.out.println("## eartag.setKey .isExistEartagOnlineSet >>"+setKey+",earmark>>"+earmark);
+        return redisTemplate.opsForSet().isMember(setKey, earmark);
+    }
+
+    @Override
+    public void putEartagToOnlineInSet(String farmId, String earmark, String todayDateText) throws ParseException {
+        String setKey = BizConst.SET_FARM_EARMARK_ONLINE_PREFIX + farmId+"_"+todayDateText;
+        System.out.println("## eartag.setKey .putEartagToOnlineInSet>>"+setKey+",earmark>>"+earmark);
+        redisTemplate.opsForSet().add(setKey, earmark);
+        redisTemplate.expire(setKey,eartagOnlineSetExpire , TimeUnit.HOURS);
+//        Set<String> resultSet = redisTemplate.opsForSet().members(setKey);
+//        System.out.println("## "+setKey+">>"+resultSet.size()+" >>"+resultSet);
+    }
+
+    /**
+     * @Method      : getEartagOnlineTotalFromCache
+     * @Description : 返回集合缓存的数量;
+     * @Params      : [farmId, todayDateText]
+     * @Return      : void
+     * 
+     * @Author      : ZhuoNing
+     * @Date        : 2022/3/3       
+     * @Time        : 10:55
+     */
+    @Override
+    public Integer getEartagOnlineTotalFromCache(String farmId, String todayDateText) {
+        String setKey = BizConst.SET_FARM_EARMARK_ONLINE_PREFIX + farmId+":"+todayDateText;
+        return redisTemplate.opsForSet().members(setKey).size();
+    }
+
+    /**
+     * @Method      : putEartagRegister
+     * @Description : 
+     * @Params      : [earmark, eartagRegisterEntity]
+     * @Return      : void
+     * 
+     * @Author      : ZhuoNing
+     * @Date        : 2022/3/3       
+     * @Time        : 15:29
+     */
+    @Override
+    public void putEartagRegister(String earmark, EartagEartagRegisterEntity eartagRegisterEntity) {
+        Map map = new HashMap();
+//        map.put("id", eartagRegisterEntity.getId());
+        map.put("earmark",eartagRegisterEntity.getEarmark());
+        map.put("firstTime",eartagRegisterEntity.getFirstTime());
+        map.put("lastTime",eartagRegisterEntity.getLastTime());
+        map.put("firstDevice",eartagRegisterEntity.getFirstDevice());
+        map.put("belongDevice",eartagRegisterEntity.getBelongDevice());
+        map.put("lastDevice",eartagRegisterEntity.getLastDevice());
+        map.put("registerTime",eartagRegisterEntity.getRegisterTime());
+        map.put("registerType",eartagRegisterEntity.getRegisterType());
+        map.put("remark",eartagRegisterEntity.getRemark());
+        map.put("farmId",eartagRegisterEntity.getFarmId());
+        map.put("activeStatus",eartagRegisterEntity.getActiveStatus());
+        map.put("activeTime",eartagRegisterEntity.getActiveTime());
+        map.put("liveStatus",eartagRegisterEntity.getLiveStatus());
+        //更新缓存
+        String earmarkOnlineKey = BizConst.EARTAG_REGISTER_PREFIX + earmark;
+        redisTemplate.opsForHash().putAll(earmarkOnlineKey, map);
+    }
+
+    /**
+     * @Method      : putEartagOnlineCount
+     * @Description : 
+     * @Params      : [earmark, eartagOnlineEntity]
+     * @Return      : void
+     * 
+     * @Author      : ZhuoNing
+     * @Date        : 2022/3/3       
+     * @Time        : 15:29
+     */
+    @Override
+    public void putEartagOnlineCount(String earmark, EartagEartagOnlineEntity eartagOnlineEntity) {
+        Map map = new HashMap();
+//        map.put("id", eartagRegisterEntity.getId());
+        map.put("earmark",eartagOnlineEntity.getEarmark());
+        map.put("total",eartagOnlineEntity.getTotal());
+        map.put("firstTime",eartagOnlineEntity.getFirstTime());
+        map.put("lastTime",eartagOnlineEntity.getLastTime());
+        map.put("envTemp",eartagOnlineEntity.getEnvTemp());
+        map.put("eartagTemp",eartagOnlineEntity.getEartagTemp());
+        map.put("addDate",eartagOnlineEntity.getAddDate());
+        map.put("farmId",eartagOnlineEntity.getFarmId());
+        //更新缓存
+        String earmarkOnlineKey = BizConst.EARTAG_ONLINE_PREFIX + earmark;
+        redisTemplate.opsForHash().putAll(earmarkOnlineKey, map);
+    }
+
+    @Override
+    public Integer getDeviceTotal(String farmId) {
+        String valueKey = BizConst.FARM_DEVICE_TOTAL_PREFIX+farmId;
+//        String value = (String) redisTemplate.opsForValue().get(valueKey);
+        Object obj = redisTemplate.opsForValue().get(valueKey);
+        if(obj == null){
+            return null;
+        }else{
+            return Integer.parseInt(String.valueOf(obj));
+        }
+    }
+
+    @Override
+    public void putDeviceTotal(Integer total, String farmId) {
+        String valueKey = BizConst.FARM_DEVICE_TOTAL_PREFIX+farmId;
+        redisTemplate.opsForValue().set(valueKey,total);
+    }
+
+    @Override
+    public Integer getDeviceCancel(String farmId) {
+        String valueKey = BizConst.FARM_DEVICE_CANCEL_PREFIX+farmId;
+//        String value = (String) redisTemplate.opsForValue().get(valueKey);
+        Object obj = redisTemplate.opsForValue().get(valueKey);
+        if(obj == null){
+            return null;
+        }else{
+            return Integer.parseInt(String.valueOf(obj));
+        }
+    }
+
+    @Override
+    public void putDeviceCancel(Integer total, String farmId) {
+        String valueKey = BizConst.FARM_DEVICE_CANCEL_PREFIX+farmId;
+        redisTemplate.opsForValue().set(valueKey,total);
+    }
+
+    @Override
+    public Integer getEartagTotal(String farmId) {
+        String valueKey = BizConst.FARM_EARTAG_TOTAL_PREFIX+farmId;
+        Object obj = redisTemplate.opsForValue().get(valueKey);
+        if(obj == null){
+            return null;
+        }else{
+            return Integer.parseInt(String.valueOf(obj));
+        }
+    }
+
+    @Override
+    public void putEartagTotal(Integer total, String farmId) {
+        String valueKey = BizConst.FARM_EARTAG_TOTAL_PREFIX+farmId;
+        redisTemplate.opsForValue().set(valueKey,total);
+    }
+
+    /**
+     * @Method : RegisterEntityToMap
+     * @Description :
+     * @Params : [deviceRegisterEntity]
+     * @Return : java.util.Map
+     * @Author : ZhuoNing
+     * @Date : 2022/2/21
+     * @Time : 14:03
+     */
+    private Map RegisterEntityToMap(EartagDeviceRegisterEntity deviceRegisterEntity) {
+        Map map = new HashMap();
+        map.put("Id", deviceRegisterEntity.getId());
+        map.put("deviceCode", deviceRegisterEntity.getDeviceCode());
+        map.put("farmId", deviceRegisterEntity.getFarmId());
+        map.put("farmName", deviceRegisterEntity.getFarmName());
+        map.put("typeF", deviceRegisterEntity.getTypeF());
+        map.put("stage", deviceRegisterEntity.getStage());
+        map.put("pigpenId", deviceRegisterEntity.getPigpenId());
+        map.put("unitId", deviceRegisterEntity.getUnitId());
+        map.put("registerTime", deviceRegisterEntity.getRegisterTime());
+        map.put("lastTime", deviceRegisterEntity.getLastTime());
+        map.put("activeStatus", deviceRegisterEntity.getActiveStatus());
+        map.put("activeTime", deviceRegisterEntity.getActiveTime());
+        map.put("deviceStatus", deviceRegisterEntity.getDeviceStatus());
+        map.put("deviceAlias", deviceRegisterEntity.getDeviceAlias());
+        map.put("location", deviceRegisterEntity.getLocation());
+        map.put("remark", deviceRegisterEntity.getRemark());
+        return map;
+    }
+
+    //#
+    public Object getValByKey(String hashKey,String key){
+        Object valueObj = redisTemplate.opsForHash().get(hashKey,key);
+        return valueObj;
+    }
+}

+ 571 - 0
huimv-eartag2-platform/huimv-eartag2-device/src/main/java/com/huimv/eartag2/device/service/impl/DeviceServiceImpl.java

@@ -0,0 +1,571 @@
+package com.huimv.eartag2.device.service.impl;
+
+import com.alibaba.fastjson.JSONObject;
+import com.huimv.eartag2.common.dao.entity.*;
+import com.huimv.eartag2.common.dao.repo.*;
+//import com.huimv.eartag2.process.service.IDeviceService;
+//import com.huimv.eartag2.process.utils.DateUtil;
+//import com.huimv.eartag2.process.utils.MathUtil;
+import com.huimv.eartag2.common.utils.BizConst;
+import com.huimv.eartag2.device.service.ICacheService;
+import com.huimv.eartag2.device.service.IDeviceService;
+import com.huimv.eartag2.device.service.IEartagService;
+import com.huimv.eartag2.device.utils.DateUtil;
+import com.huimv.eartag2.device.utils.MathUtil;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.math.BigDecimal;
+import java.sql.Timestamp;
+import java.text.ParseException;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @Project : huimv.shiwan
+ * @Package : com.huimv.biosafety.uface.controller
+ * @Description : TODO
+ * @Version : 1.0
+ * @Author : ZhuoNing
+ * @Create : 2020-12-25
+ **/
+@Service
+@Slf4j
+public class DeviceServiceImpl implements IDeviceService {
+    @Autowired
+    private MathUtil mathUtil;
+    @Autowired
+    private DateUtil dateUtil;
+    @Autowired
+    private EartagRawRepo rawRepo;
+    @Autowired
+    private EartagHeartbeatRepo heartbeatRepo;
+    @Autowired
+    private EartagEnvRepo envRepo;
+//    @Autowired
+//    private IDeviceService deviceService;
+    @Autowired
+    private ICacheService cacheService;
+    @Autowired
+    private EartagDeviceRegisterRepo deviceRegisterRepo;
+    @Autowired
+    private EartagDeviceOnlineRepo deviceOnlineRepo;
+    @Autowired
+    private EartarFarmAllStatusRepo eartagFarmAllStatusRepo;
+    @Autowired
+    private EartarFarmAllStatusRepo farmAllStatusRepo;
+    @Autowired
+    private IEartagService eartagService;
+    @Autowired
+    private EartagDeviceOnlineRepo eartagDeviceOnlineRepo;
+    @Autowired
+    private EartagEartagRegisterRepo eartagRegisterRepo;
+
+    /**
+     * @Method      : handleDeviceHeartbeat
+     * @Description : 处理设备心跳数据
+     * @Params      : [dataJo]
+     * @Return      : void
+     * 
+     * @Author      : ZhuoNing
+     * @Date        : 2022/3/12       
+     * @Time        : 19:16
+     */
+    @Override
+    public void handleDeviceHeartbeat(JSONObject dataJo) throws ParseException {
+        System.out.println("心跳数据 dataJo>>"+dataJo);
+        //逻辑处理:
+        //1、保存设备心跳流水数据;
+        //2、更新设备注册表(活动状态、活动更新时间,更新类型)
+        //3、更新在线统计表(心跳数,心跳最早上传时间,最后一次上传时间)
+        //4、更新总状态表表
+
+        //1、{保存设备心跳记录}
+        saveDeviceHeartbeat(dataJo);
+        //2、{更新设备注册表}
+//        updateDeviceRegister(dataJo);
+        //3、{更新在线统计表}
+//        updateDeviceOnline(dataJo);
+        //4、{更新总状态表}
+//        updateAllStatus(dataJo);
+        //--------------------------------------------------------------------------------------------
+        System.out.println("dataJo>"+dataJo);
+        String deviceCode = dataJo.getString("device");
+        //{获取牧场id}
+        String farmId = getFarmIdByDeviceCode(deviceCode);
+        System.out.println("## farmId>>"+farmId);
+        String todayDateText = new com.huimv.eartag2.common.utils.DateUtil().getTodayDateText();
+        java.sql.Date todayDate = new java.sql.Date(new java.util.Date().getTime());
+        Timestamp nowTimestamp = new Timestamp(new java.util.Date().getTime());
+
+        //Step1:更新设备注册表[设置活动状态为1,设置活动状态更新时间]
+        //Step2:更新在线统计[心跳数+1,心跳第一次上传时间,心跳最后一次时间],预先判断该数据是否存在,如果不存在要先添加记录,如果存在就修改数据
+
+        //# 更新设备注册表 #
+        updateDeviceRegister(farmId, deviceCode,nowTimestamp);
+        //# 更新在线统计 #
+        updateDeviceOnlineCount(farmId, deviceCode,todayDateText,nowTimestamp,todayDate);
+
+        //判断该设备编号是否存在缓存在线集合当中;
+        Boolean isExist = cacheService.isExistDeviceOnlineSet(farmId, deviceCode, todayDateText);
+        System.out.println("# 处理心跳 isExist >>"+isExist);
+        if (!isExist) {
+            System.out.println("## 心跳 2");
+            //# 更新总状态表 #
+            updateDeviceAllStatus(farmId, deviceCode,todayDateText,nowTimestamp,todayDate);
+
+            //# 将新设备编号加入在线缓存 #
+            cacheService.putDeviceToOnline(farmId, deviceCode,todayDateText);
+        }
+        //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+    }
+
+    //更新总状态
+    public void updateDeviceAllStatus(String farmId, String deviceCode, String todayDateText, Timestamp nowTimestamp, java.sql.Date todayDate) throws ParseException {
+        System.out.println("## 心跳 2.3");
+        //读取一条总状态记录;
+        EartarFarmAllStatusEntity farmAllStatusEntity = farmAllStatusRepo.getOneByFarmIdAndCreateDate(farmId,todayDateText);
+        if(farmAllStatusEntity == null){
+            System.out.println("## 心跳 2.3.1");
+            //总状态记录不存在;
+            //#创建一条新总状态记录;
+            //*计算设备在线数量、离线数量、在线率*
+            int deviceTotal = getDeviceTotalByFarmIdFromDeviceRegister(farmId);
+            int onlineNum = 1;
+            int offlineNum = deviceTotal-1;
+            BigDecimal reateBd= new BigDecimal(onlineNum).divide(new BigDecimal(deviceTotal),1,BigDecimal.ROUND_HALF_UP);
+            //*计算设备注销数量*
+            int cancelNum = getDeviceCancelTotalFromDeviceRegister(farmId);
+            //#计算耳标总数
+            int eartagTotal = eartagService.getEartagRegTotalByFarmId(farmId);
+            //计算耳标在线数量
+            int eartagOnlineTotal = eartagService.getEartagOnelineTotal(farmId,todayDateText);
+            //
+            EartarFarmAllStatusEntity newFarmAllStatusEntity = new EartarFarmAllStatusEntity();
+            newFarmAllStatusEntity.setDeviceTotal(deviceTotal);
+            newFarmAllStatusEntity.setDeviceOnline(onlineNum);
+            newFarmAllStatusEntity.setDeviceOffline(offlineNum);
+            newFarmAllStatusEntity.setDeviceRate(Float.parseFloat(reateBd.toString()));
+            newFarmAllStatusEntity.setDeviceCancel(cancelNum);
+            newFarmAllStatusEntity.setEartagTotal(eartagTotal);
+            newFarmAllStatusEntity.setEartagOnline(eartagOnlineTotal);
+            newFarmAllStatusEntity.setFarmId(farmId);
+            newFarmAllStatusEntity.setUpdateTime(nowTimestamp);
+            newFarmAllStatusEntity.setCreateDate(todayDate);
+            newFarmAllStatusEntity.setFarmId(farmId);
+            farmAllStatusRepo.saveAndFlush(newFarmAllStatusEntity);
+            //更新总状态表缓存
+            cacheService.putAllFarmAllStatusCache(farmId,newFarmAllStatusEntity);
+        }else{
+            System.out.println("## 心跳 2.3.2");
+            //总状态记录存在;
+            //#计算设备的在线、离线、在线率,更新时间
+            int onlineNum = farmAllStatusEntity.getDeviceOnline();
+            onlineNum++;
+            //
+            int total = getDeviceTotalByFarmIdFromDeviceRegister(farmId);
+            int offlineNum = 0;
+            if(total > onlineNum){
+                offlineNum = total - onlineNum;
+            }
+            farmAllStatusEntity.setDeviceTotal(total);
+            BigDecimal reateBd= new BigDecimal(onlineNum).divide(new BigDecimal(total),1,BigDecimal.ROUND_HALF_UP);
+            farmAllStatusEntity.setDeviceOnline(onlineNum);
+            farmAllStatusEntity.setDeviceOffline(offlineNum);
+            farmAllStatusEntity.setDeviceRate(Float.parseFloat(reateBd.toString()));
+            farmAllStatusEntity.setUpdateTime(nowTimestamp);
+            eartagFarmAllStatusRepo.saveAndFlush(farmAllStatusEntity);
+            //更新总状态表缓存
+            cacheService.putAllFarmAllStatusCache(farmId,farmAllStatusEntity);
+        }
+    }
+
+    //计算设备总数
+    public int getDeviceTotalByFarmIdFromDeviceRegister(String farmId){
+        //从缓存钟读取设备总数
+        Integer deviceTotal = cacheService.getDeviceTotal(farmId);
+        if(deviceTotal != null) {
+            return deviceTotal;
+        }else{
+            List<Object[]> deviceRegList = deviceRegisterRepo.getDeviceCountByFarmId(farmId);
+            Object[] deviceRegObj = (Object[]) deviceRegList.get(0);
+            Integer total = Integer.parseInt(deviceRegObj[0].toString());
+            //设置缓存
+            cacheService.putDeviceCancel(total,farmId);
+            //设备总数
+            return total;
+        }
+    }
+
+    //计算注销设备数量
+    private int getDeviceCancelTotalFromDeviceRegister(String farmId) {
+        //从缓存钟读取设备总数
+        Integer deviceCancel = cacheService.getDeviceCancel(farmId);
+        if(deviceCancel != null) {
+            return deviceCancel;
+        }else {
+            List<Object[]> deviceRegList = deviceRegisterRepo.getDeviceCountByFarmId(farmId);
+            Object[] deviceRegObj = (Object[]) deviceRegList.get(0);
+            Integer total = Integer.parseInt(deviceRegObj[0].toString());
+            //设置缓存
+            cacheService.putDeviceCancel(total,farmId);
+            //设备总数
+            return total;
+        }
+    }
+
+    //更新在线状态
+    public void updateDeviceOnlineCount(String farmId, String deviceCode, String todayDateText, Timestamp nowTimestamp, java.sql.Date todayDate) throws ParseException {
+        //# 先判断今天在线记录是否存在 #
+        //# 更新数据表 #
+        //# 更新缓存 #
+        System.out.println("## 心跳 1.2/2.2");
+        //
+        EartagDeviceOnlineEntity deviceOnlineEntity = deviceOnlineRepo.getDeviceOnline(deviceCode,todayDateText);
+        if(deviceOnlineEntity == null){
+            System.out.println("## 心跳 1.2.1/2.2.1");
+            //不存在;
+            EartagDeviceOnlineEntity newDeviceOnlineEntity = new EartagDeviceOnlineEntity();
+            newDeviceOnlineEntity.setDeviceCode(deviceCode);
+            newDeviceOnlineEntity.setHeartbeatTotal(1);
+            newDeviceOnlineEntity.setEnvtempTotal(0);
+            newDeviceOnlineEntity.setEartagTotal(0);
+            newDeviceOnlineEntity.setAddDate(todayDate);
+            newDeviceOnlineEntity.setHeartbeatFirstTime(nowTimestamp);
+            newDeviceOnlineEntity.setHeartbeatLastTime(nowTimestamp);
+            newDeviceOnlineEntity.setFarmId(farmId);
+            deviceOnlineRepo.saveAndFlush(newDeviceOnlineEntity);
+            //更新每天在线统计缓存
+            cacheService.putDeviceInOnline(deviceCode,newDeviceOnlineEntity);
+        }else{
+            System.out.println("## 心跳 1.2.2/2.2.2");
+            //存在;
+            int total = deviceOnlineEntity.getHeartbeatTotal();
+            deviceOnlineEntity.setHeartbeatTotal(++total);
+            deviceOnlineEntity.setHeartbeatLastTime(nowTimestamp);
+            deviceOnlineRepo.saveAndFlush(deviceOnlineEntity);
+            //更新每天在线统计缓存
+            cacheService.putDeviceInOnline(deviceCode,deviceOnlineEntity);
+        }
+
+        //--(优化思路) --//
+//        updateDeviceOnlineCount(deviceCode);
+
+    }
+
+    //更新设备注册表
+    private void updateDeviceRegister(String farmId, String deviceCode, Timestamp nowTimestamp) {
+        //--更新mysql
+        EartagDeviceRegisterEntity deviceRegisterEntity = deviceRegisterRepo.getDeviceRegister(deviceCode);
+        if (deviceRegisterEntity != null) {
+            //设备注册数据存在
+            deviceRegisterEntity.setActiveStatus(1);
+            deviceRegisterEntity.setActiveTime(new Timestamp(new Date().getTime()));
+            deviceRegisterRepo.saveAndFlush(deviceRegisterEntity);
+            //更新缓存中设备注册信息
+            cacheService.putDeviceRegister(deviceCode,deviceRegisterEntity);
+        }else{
+            //设备注册数据不存在
+            //新建设备注册记录
+            EartagDeviceRegisterEntity newDeviceRegisterEntity = new EartagDeviceRegisterEntity();
+            newDeviceRegisterEntity.setDeviceCode(deviceCode);
+            newDeviceRegisterEntity.setFarmId(farmId);
+            newDeviceRegisterEntity.setRegisterTime(nowTimestamp);
+            newDeviceRegisterEntity.setActiveStatus(1);
+            newDeviceRegisterEntity.setActiveTime(nowTimestamp);
+            newDeviceRegisterEntity.setDeviceStatus(1);
+            deviceRegisterRepo.saveAndFlush(newDeviceRegisterEntity);
+            //更新缓存中设备注册信息
+            cacheService.putDeviceRegister(deviceCode,newDeviceRegisterEntity);
+        }
+    }
+
+    /**
+     * @Method      : handleDeviceEnvtemp
+     * @Description : 处理设备环境温度数据
+     * @Params      : [dataJo]
+     * @Return      : void
+     * 
+     * @Author      : ZhuoNing
+     * @Date        : 2022/3/12       
+     * @Time        : 19:16
+     */
+    @Override
+    public void handleDeviceEnvtemp(JSONObject dataJo) throws ParseException {
+        System.out.println("环境数据 dataJo>>"+dataJo);
+        //逻辑处理:
+        //1、保存环境温度流水数据;
+        //2、更新设备注册表(活动状态、活动更新时间,更新类型)
+        //3、更新在线统计表(环境温度计数,环境温度最早上传时间,最新环境温度,环境温度最后一次上传时间)
+        //4、更新总状态表
+        //保存设备心跳记录
+//        saveDeviceHeartbeat(dataJo);
+        //{更新设备注册表}
+//        updateDeviceRegister(dataJo);
+        //{更新在线统计表}
+//        updateDeviceOnline(dataJo);
+        //{更新总状态表}
+//        updateAllStatus(dataJo);
+        //------------------------------------------------------------------------------------
+        String deviceCode = dataJo.getString("device");
+        String farmId = getFarmIdByDeviceCode(deviceCode);
+
+        String todayDateText = new com.huimv.eartag2.common.utils.DateUtil().getTodayDateText();
+        java.sql.Date todayDate = new java.sql.Date(new java.util.Date().getTime());
+        Timestamp nowTimestamp = new Timestamp(new java.util.Date().getTime());
+
+        //# 更新在线统计 #
+        updateDeviceOnlineWithEnvtemp(farmId, deviceCode);
+//            System.out.println("## ++++1");
+        //# 更新设备注册表 #
+        updateDeviceRegister(farmId, deviceCode,nowTimestamp);
+
+        //            //# 更新设备注册表 #
+//            updateDeviceRegister(farmId, deviceCode,nowTimestamp);
+//            //# 更新在线统计 #
+//            updateDeviceOnlineWithEnvtemp(farmId, deviceCode);
+
+        //判断该设备编号是否存在牧场缓存在线集合当中;
+        Boolean isExist = cacheService.isExistDeviceOnlineSet(farmId, deviceCode,todayDateText);
+        System.out.println("## 处理环境温度 isExist>>"+isExist);
+        if (!isExist) {
+            //Step1:更新总状态表[device_online+1,device_offline-1,device_rate],预先判断该数据是否存在,如果不存在要先添加记录,如果存在就修改数据
+            //Step2:更新设备注册表[active_status=1,active_time=当前时间]
+            //Step3:更新在线统计[],预先判断该数据是否存在,如果不存在要先添加记录,如果存在就修改数据
+            //Step4:将新设备编号加入缓存
+            System.out.println("## ----");
+            //# 更新总状态表 #
+            updateEnvtempOfDeviceAllStatus(farmId, deviceCode);
+            //# 将新设备编号加入在线缓存 #
+            cacheService.putDeviceToOnline(farmId, deviceCode, todayDateText);
+            System.out.println("## END");
+        }
+        //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+    }
+
+    public void updateEnvtempOfDeviceAllStatus(String farmId, String deviceCode) throws ParseException {
+//        System.out.println("## (A)");
+        String todayDateText = new com.huimv.eartag2.common.utils.DateUtil().getTodayDateText();
+        //
+        EartarFarmAllStatusEntity farmAllStatusEntity = eartagFarmAllStatusRepo.getOneByFarmIdAndCreateDate(farmId,todayDateText);
+        if(farmAllStatusEntity == null){
+//            System.out.println("## (A.1)");
+            //设备总状态表信息不存在
+            //创建设备状态记录并更新缓存cache()
+            createNewFarmAllStatus(farmId,deviceCode);
+            //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+        }else{
+//            System.out.println("## (A.2)");
+            //设备总状态表信息存在
+            //计算设备状态并更新缓存cache(在线数+1,离线数-1,计算设备在线率)
+            int onlineNum = farmAllStatusEntity.getDeviceOnline();
+            int offlineNum = farmAllStatusEntity.getDeviceOffline();
+            int total = farmAllStatusEntity.getDeviceTotal();
+            onlineNum++;
+            offlineNum--;
+            BigDecimal rateBd= new BigDecimal(onlineNum).divide(new BigDecimal(total),1,BigDecimal.ROUND_HALF_UP);
+            farmAllStatusEntity.setDeviceOnline(onlineNum);
+            farmAllStatusEntity.setDeviceOffline(offlineNum);
+            farmAllStatusEntity.setDeviceRate(Float.parseFloat(rateBd.toString()));
+            farmAllStatusEntity.setUpdateTime(new Timestamp(new Date().getTime()));
+            eartagFarmAllStatusRepo.saveAndFlush(farmAllStatusEntity);
+            //# 同步更新牧场总状态缓存相关字段 #
+            cacheService.flashAllStatusCache(farmId,farmAllStatusEntity);
+        }
+    }
+
+    //# 创建总状态记录 #
+    private void createNewFarmAllStatus(String farmId,String deviceCode) {
+        System.out.println("## (A.1.1)");
+        //# 计算处于工作状态的设备总数(设备注册表)
+        List<Object[]> deviceRegList = deviceRegisterRepo.getDeviceCountByFarmId(farmId);
+        Object[] deviceRegObj = (Object[]) deviceRegList.get(0);
+        //设备总数
+        int deviceTotal = 0;
+        deviceTotal = Integer.parseInt(deviceRegObj[0].toString());
+        System.out.println("## total>>"+deviceTotal);
+        if(deviceTotal == 0){
+            log.error("该牧场没有任何处于工作状态的采集器设备.");
+            System.out.println("## (A.1.1.1)");
+        }else{
+            System.out.println("## (A.1.1.2)");
+            //# 计算耳标总数(耳标注册表)
+            int eartagTotal = 0;
+            List<Object[]> eartagRegList = eartagRegisterRepo.getEartagCountByFarmId(farmId);
+            Object[] eartagRegObj = (Object[]) eartagRegList.get(0);
+            //处于工作状态的耳标总数
+            eartagTotal = Integer.parseInt(eartagRegObj[0].toString());
+
+            int onlineNum = 1;
+            int offlineNum = deviceTotal-1;
+            BigDecimal reateBd= new BigDecimal(onlineNum).divide(new BigDecimal(deviceTotal),1,BigDecimal.ROUND_HALF_UP);
+            //MySQL:farm_all_status
+            EartarFarmAllStatusEntity farmAllStatusEntity = new EartarFarmAllStatusEntity();
+            farmAllStatusEntity.setDeviceTotal(deviceTotal);
+            farmAllStatusEntity.setDeviceOnline(onlineNum);
+            farmAllStatusEntity.setDeviceOffline(offlineNum);
+            farmAllStatusEntity.setDeviceRate(Float.parseFloat(reateBd.toString()));
+            farmAllStatusEntity.setEartagTotal(eartagTotal);
+            farmAllStatusEntity.setEartagOnline(1);
+            farmAllStatusEntity.setUpdateTime(new Timestamp(new Date().getTime()));
+            farmAllStatusEntity.setCreateDate(new java.sql.Date(new Date().getTime()));
+            eartagFarmAllStatusRepo.saveAndFlush(farmAllStatusEntity);
+
+            //Redis Cache:farm_all_status_+farmId
+            cacheService.flashAllStatusCache(farmId,farmAllStatusEntity);
+        }
+    }
+
+    //更新在线统计
+    private void updateDeviceOnlineWithEnvtemp(String farmId, String deviceCode) throws ParseException {
+        System.out.println("## (1)/(C)");
+        //# 更新数据库
+        //# 更新在线缓存
+        String todayDateText = new com.huimv.eartag2.common.utils.DateUtil().getTodayDateText();
+//        System.out.println("1.todayDateText>>" + todayDateText);
+        //读取在线日期
+        EartagDeviceOnlineEntity eartagDeviceOnlineEntity = eartagDeviceOnlineRepo.getDeviceOnline(deviceCode, todayDateText);
+        String deviceOnlineHashKey = BizConst.DEVICE_ONLINE_PREFIX + deviceCode;
+        if (eartagDeviceOnlineEntity == null) {
+            //不存在设备在线统计
+            //创建设备在线统计并创建缓存
+            createNewDeviceOnline(farmId,deviceCode);
+        }else{
+            int envtempTotal = eartagDeviceOnlineEntity.getEnvtempTotal();
+//            System.out.println(">>>>>>>>>>> envtempTotal>>"+envtempTotal);
+            eartagDeviceOnlineEntity.setEnvtempTotal(++envtempTotal);
+            eartagDeviceOnlineEntity.setLastTime(new Timestamp(new Date().getTime()));
+//            System.out.println(">>>>>>>>>>> eartagDeviceOnlineEntity>>"+eartagDeviceOnlineEntity);
+            eartagDeviceOnlineRepo.saveAndFlush(eartagDeviceOnlineEntity);
+            //更新设备在线缓存数据
+            cacheService.putDeviceInOnline(deviceOnlineHashKey,eartagDeviceOnlineEntity);
+        }
+    }
+
+    //创建
+    private void createNewDeviceOnline(String farmId, String deviceCode) {
+//        System.out.println("## (1.1.1)");
+        EartagDeviceOnlineEntity newEartagDeviceOnlineEntity = new EartagDeviceOnlineEntity();
+        newEartagDeviceOnlineEntity.setDeviceCode(deviceCode);
+        newEartagDeviceOnlineEntity.setHeartbeatTotal(0);;
+        newEartagDeviceOnlineEntity.setEnvtempTotal(1);
+        newEartagDeviceOnlineEntity.setEartagTotal(0);
+        newEartagDeviceOnlineEntity.setAddDate(new java.sql.Date(new Date().getTime()));
+        newEartagDeviceOnlineEntity.setFarmId(farmId);
+        newEartagDeviceOnlineEntity.setEnvtempFirstTime(new Timestamp(new Date().getTime()));
+        newEartagDeviceOnlineEntity.setEnvtempLastTime(new Timestamp(new Date().getTime()));
+        eartagDeviceOnlineRepo.saveAndFlush(newEartagDeviceOnlineEntity);
+        //将新建的设备在线数据更新到设备在线缓存
+        cacheService.putDeviceInOnline(BizConst.DEVICE_ONLINE_PREFIX + deviceCode,newEartagDeviceOnlineEntity);
+    }
+
+    //更新总状态表
+//    private void updateAllStatus(JSONObject dataJo) {
+//    }
+
+    //更新在线统计表
+//    private void updateDeviceOnline(JSONObject dataJo) {
+//    }
+
+
+    @Override
+    public String getFarmIdByDeviceCode(String deviceCode) {
+        EartagDeviceRegisterEntity deviceRegisterEntity = deviceRegisterRepo.getDeviceRegister(deviceCode);
+        return deviceRegisterEntity.getFarmId();
+    }
+    /**
+     * @Method      : saveDeviceHeartbeat
+     * @Description : 保存设备心跳数据
+     * @Params      : [dataJo]
+     * @Return      : void
+     * 
+     * @Author      : ZhuoNing
+     * @Date        : 2022/2/15       
+     * @Time        : 14:39
+     */
+    @Override
+    public void saveDeviceHeartbeat(JSONObject dataJo) {
+        String deviceCode = dataJo.getString("device");
+        EartagHeartbeatEntity addHeartbeatEntity = new EartagHeartbeatEntity();
+        addHeartbeatEntity.setDeviceCode(deviceCode);
+        addHeartbeatEntity.setAddTime(new Timestamp(new Date().getTime()));
+        heartbeatRepo.saveAndFlush(addHeartbeatEntity);
+    }
+
+    /**
+     * @Method      : saveDeviceTemp
+     * @Description : 保存设备温度数据
+     * @Params      : [dataJo]
+     * @Return      : void
+     * 
+     * @Author      : ZhuoNing
+     * @Date        : 2022/2/15       
+     * @Time        : 14:39
+     */
+    @Override
+    public void saveDeviceTemp(JSONObject dataJo) {
+        String device = dataJo.getString("device");
+        String temp = dataJo.getString("temp");
+        EartagEnvEntity envEntity = new EartagEnvEntity();
+        envEntity.setDeviceCode(device);
+        envEntity.setTemp1(Integer.parseInt(temp));
+        envEntity.setTemp2(0F);
+        envEntity.setAddTime(new Timestamp(new Date().getTime()));
+        envRepo.saveAndFlush(envEntity);
+    }
+
+    /**
+     * @Method      : saveRawdata
+     * @Description : 保存原始数据
+     * @Params      : [askText]
+     * @Return      : void
+     *
+     * @Author      : ZhuoNing
+     * @Date        : 2022/2/9
+     * @Time        : 13:38
+     */
+    @Override
+    public void saveRawdata(String askText) throws ParseException {
+//        log.info("#开始解析Ask请求数据>>" + askText.trim().replace("\n", ""));
+        String[] dataArray = askText.split("\\+");
+        String cmdHeader = dataArray[0];
+        Map rawMap = new HashMap();
+        if (cmdHeader.trim().equalsIgnoreCase("hm")) {
+            //采集器原始数据
+            String device = dataArray[1];
+            String cmd = dataArray[2];
+            rawMap.put("cmdHeader", cmdHeader);
+            rawMap.put("device", device);
+            rawMap.put("cmd", cmd);
+            rawMap.put("ask", askText);
+        } else if (cmdHeader.trim().equalsIgnoreCase("zj")) {
+            //采集器原始数据
+            String device = dataArray[1];
+            rawMap.put("cmdHeader", cmdHeader);
+            rawMap.put("device", device);
+            rawMap.put("cmd", "");
+            rawMap.put("ask", askText);
+            rawMap.put("addTime", dateUtil.getTodayMissionText());
+        } else {
+            //采集器原始数据
+            String device = dataArray[1];
+            rawMap.put("cmdHeader", cmdHeader);
+            rawMap.put("device", device);
+            rawMap.put("cmd", "");
+            rawMap.put("ask", askText);
+        }
+        //保存原始数据
+        //类型、设备、命令、数据内容、日期
+        EartagRawEntity addRawEntity = new EartagRawEntity();
+        addRawEntity.setCmdHeader(rawMap.get("cmdHeader").toString());
+        addRawEntity.setDevice(rawMap.get("device").toString());
+        addRawEntity.setCmd(rawMap.get("cmd").toString());
+        addRawEntity.setAsk(rawMap.get("ask").toString());
+        addRawEntity.setAddTime(new Timestamp(new Date().getTime()));
+        rawRepo.saveAndFlush(addRawEntity);
+    }
+
+}

+ 169 - 0
huimv-eartag2-platform/huimv-eartag2-device/src/main/java/com/huimv/eartag2/device/service/impl/EartagServiceImpl.java

@@ -0,0 +1,169 @@
+package com.huimv.eartag2.device.service.impl;
+
+import com.alibaba.fastjson.JSONObject;
+import com.huimv.eartag2.common.dao.entity.EartagDataEntity;
+import com.huimv.eartag2.common.dao.repo.EartagDataRepo;
+//import com.huimv.eartag2.process.service.IEartagService;
+import com.huimv.eartag2.common.dao.repo.EartagEartagRegisterRepo;
+import com.huimv.eartag2.device.service.ICacheService;
+import com.huimv.eartag2.device.service.IEartagService;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.stereotype.Service;
+
+import java.sql.Timestamp;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @Project : huimv.shiwan
+ * @Package : com.huimv.biosafety.uface.controller
+ * @Description : TODO
+ * @Version : 1.0
+ * @Author : ZhuoNing
+ * @Create : 2020-12-25
+ **/
+@Service
+@Slf4j
+public class EartagServiceImpl implements IEartagService {
+    @Autowired
+    private RedisTemplate redisTemplate;
+    @Autowired
+    private EartagDataRepo eartagDataRepo;
+    @Autowired
+    private EartagEartagRegisterRepo eartagRegisterRepo;
+    @Autowired
+    private ICacheService cacheService;
+
+    //读取耳标注册数据
+    @Override
+    public Integer getEartagRegTotalByFarmId(String farmId){
+        //从缓存读取耳标总数
+        Integer eartagTotal = cacheService.getEartagTotal(farmId);
+        if(eartagTotal != null){
+            return eartagTotal;
+        }else{
+            List<Object[]> eartagRegList = eartagRegisterRepo.getEartagCountByFarmId(farmId);
+            Object[] eartagRegObj = (Object[]) eartagRegList.get(0);
+            Integer total = Integer.parseInt(eartagRegObj[0].toString());
+            //设置耳标总数缓存
+            cacheService.putEartagTotal(total,farmId);
+            //处于工作状态的耳标总数
+            return total;
+        }
+    }
+
+    @Override
+    public Integer getEartagOnelineTotal(String farmId, String todayDateText) {
+        return cacheService.getEartagOnlineTotalFromCache(farmId,todayDateText);
+    }
+
+    /**
+     * @Method : countAct
+     * @Description : 计算act数值
+     * @Params : [deviceCode, nowAct0]
+     * @Return : java.lang.Integer
+     * @Author : ZhuoNing
+     * @Date : 2022/1/18
+     * @Time : 15:25
+     */
+    @Override
+    public Integer countAct(String deviceCode, String nowAct) {
+        //读取hash
+        Object actObj = redisTemplate.opsForHash().get(deviceCode, "act");
+        if (actObj == null) {
+            //--初始化最新的redis记录
+            initRedisObj(deviceCode);
+            Object lastAct = redisTemplate.opsForHash().get(deviceCode, "act");
+            if (lastAct == null) {
+                log.error("#--- redis数据库有问题,请检查redis是否能正常连接 ---# ");
+                return 0;
+            }
+        }
+        Object lastAct = redisTemplate.opsForHash().get(deviceCode, "act");
+        Integer act1 = Integer.parseInt(nowAct) - Integer.parseInt(lastAct.toString());
+//        redisTemplate.opsForHash().put(deviceCode, "act1", act1);
+        return act1;
+    }
+
+    /**
+     * @Author      : ZhuoNing
+     * @Date        : 2022/2/9
+     * @Time        : 14:33
+     */
+    @Override
+    public void saveEartag(JSONObject eartagJo) {
+        EartagDataEntity dataEntity = new EartagDataEntity();
+        dataEntity.setCmdHeader(eartagJo.getString("cmdHeader"));
+        dataEntity.setDevice(eartagJo.getString("device"));
+        dataEntity.setEarmark(eartagJo.getString("earmark"));
+        dataEntity.setBat(Integer.parseInt(eartagJo.getString("bat")));
+        dataEntity.setEarTemp(Integer.parseInt(eartagJo.getString("earTemp")));
+        dataEntity.setEarTemp1(eartagJo.getFloat("earTemp1"));
+        dataEntity.setEnvTemp(Integer.parseInt(eartagJo.getString("envTemp")));
+        dataEntity.setEnvTemp1(Integer.parseInt(eartagJo.getString("envTemp")));
+        dataEntity.setAct(Integer.parseInt(eartagJo.getString("act")));
+        dataEntity.setAct1(Integer.parseInt(eartagJo.getString("act1")));
+        dataEntity.setSignal1(Integer.parseInt(eartagJo.getString("signal")));
+        dataEntity.setAskTime(getAskTime(eartagJo.getString("askTime")));
+        dataEntity.setOther(eartagJo.getString("other"));
+        dataEntity.setAddTime(new Timestamp(new Date().getTime()));
+        eartagDataRepo.saveAndFlush(dataEntity);
+
+        //最新的耳标数据覆盖老数据
+        Map<String, String> map = new HashMap<>();
+        map.put("cmdHeader", dataEntity.getCmdHeader());
+        map.put("device", dataEntity.getDevice());
+        map.put("earmark", dataEntity.getEarmark());
+        map.put("bat", dataEntity.getBat().toString());
+        map.put("earTemp", dataEntity.getEarTemp().toString());
+        map.put("earTemp1", dataEntity.getEarTemp1().toString());
+        map.put("envTemp", dataEntity.getEnvTemp().toString());
+        map.put("envTemp1", dataEntity.getEnvTemp1().toString());
+        map.put("act", dataEntity.getAct().toString());
+        map.put("act1", dataEntity.getAct1().toString());
+        map.put("signal1", dataEntity.getSignal1().toString());
+        map.put("askTime", dataEntity.getAskTime());
+        map.put("other", dataEntity.getOther());
+        map.put("addTime", dataEntity.getAddTime().toString());
+        //为hash结构设置多个键值对(hmset)
+        redisTemplate.opsForHash().putAll(dataEntity.getDevice(), map);
+    }
+
+    //
+    public String getAskTime(String askTime) {
+        String newAskTime = askTime.substring(0, 4) + "-" + askTime.substring(4, 6) + "-" + askTime.substring(6, 8) + " " + askTime.substring(8, 10) + ":" + askTime.substring(10, 12) + ":" + askTime.substring(12, 14);
+        return newAskTime;
+    }
+
+    /**
+     * 初始化redis最新记录
+     */
+    private void initRedisObj(String deviceCode) {
+        EartagDataEntity lastEartagDataEntity = eartagDataRepo.getLastEartagData(deviceCode);
+        if (lastEartagDataEntity != null) {
+            System.out.println("## lastEartagDataEntity.toString>>" + lastEartagDataEntity.toString());
+            //--从数据库读取最新记录并覆盖redis
+            Map<String, String> map = new HashMap<>();
+            map.put("cmdHeader", lastEartagDataEntity.getCmdHeader());
+            map.put("device", lastEartagDataEntity.getDevice());
+            map.put("earmark", lastEartagDataEntity.getEarmark());
+            map.put("bat", lastEartagDataEntity.getBat().toString());
+            map.put("earTemp", lastEartagDataEntity.getEarTemp().toString());
+            map.put("earTemp1", lastEartagDataEntity.getEarTemp1().toString());
+            map.put("envTemp", lastEartagDataEntity.getEnvTemp().toString());
+            map.put("envTemp1", lastEartagDataEntity.getEnvTemp1().toString());
+            map.put("act", lastEartagDataEntity.getAct().toString());
+            map.put("act1", lastEartagDataEntity.getAct1().toString());
+            map.put("signal1", lastEartagDataEntity.getSignal1().toString());
+            map.put("askTime", lastEartagDataEntity.getAskTime());
+            map.put("other", lastEartagDataEntity.getOther());
+            map.put("addTime", lastEartagDataEntity.getAddTime().toString());
+            //为hash结构设置多个键值对(hmset)
+            redisTemplate.opsForHash().putAll(deviceCode, map);
+        }
+    }
+}

+ 20 - 0
huimv-eartag2-platform/huimv-eartag2-device/src/main/java/com/huimv/eartag2/device/task/TestTask.java

@@ -0,0 +1,20 @@
+package com.huimv.eartag2.device.task;
+
+import org.springframework.stereotype.Component;
+
+/**
+ * @Project : huimv.shiwan
+ * @Package : com.huimv.biosafety.uface.controller
+ * @Description : TODO
+ * @Version : 1.0
+ * @Author : ZhuoNing
+ * @Create : 2020-12-25
+ **/
+@Component
+public class TestTask {
+
+//    @Scheduled(cron="0/5 * * * * ?")
+    public void test1(){
+        System.out.println("定时任务开启.");
+    }
+}

+ 12 - 0
huimv-eartag2-platform/huimv-eartag2-device/src/main/java/com/huimv/eartag2/device/utils/BaseTemplete.java

@@ -0,0 +1,12 @@
+package com.huimv.eartag2.device.utils;
+
+/**
+ * @Project : huimv.shiwan
+ * @Package : com.huimv.biosafety.uface.controller
+ * @Description : TODO
+ * @Version : 1.0
+ * @Author : ZhuoNing
+ * @Create : 2020-12-25
+ **/
+public class BaseTemplete {
+}

+ 187 - 0
huimv-eartag2-platform/huimv-eartag2-device/src/main/java/com/huimv/eartag2/device/utils/DateUtil.java

@@ -0,0 +1,187 @@
+package com.huimv.eartag2.device.utils;
+
+import cn.hutool.core.date.DateTime;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Component;
+
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.Date;
+
+/**
+ * @Project : huimv.shiwan
+ * @Package : com.huimv.biosafety.uface.controller
+ * @Description : TODO
+ * @Version : 1.0
+ * @Author : ZhuoNing
+ * @Create : 2020-12-25
+ **/
+@Component
+@Slf4j
+public class DateUtil {
+
+    //格式化日期(Long --> Date)
+    public String formatLongToDate(Long longDate){
+        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+        Date date= new Date(longDate);
+        return df.format(date);
+    }
+
+    //格式化本年
+    public String getThisYear(){
+        Calendar cal = Calendar.getInstance();
+        int year = cal.get(Calendar.YEAR);
+        return String.valueOf(year);
+    }
+
+    //格式化本月
+    public String getThisMonth(){
+        Calendar cal = Calendar.getInstance();
+        int month = cal.get(Calendar.MONTH) + 1;
+        if(String.valueOf(month).length()==1)
+        {
+            return "0"+String.valueOf(month);
+        }else{
+            return String.valueOf(month);
+        }
+    }
+
+    //格式化日期时间
+    public String formatDateTime(String dateText) throws ParseException {
+        if(dateText.indexOf("T") != -1){
+            dateText = dateText.replace("T"," ");
+        }
+        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+        Date date = sdf.parse(dateText);
+        return sdf.format(date);
+    }
+
+    public Date parseDateTime(String dateText) throws ParseException {
+        if(dateText.indexOf("T") != -1){
+            dateText = dateText.replace("T"," ");
+        }
+        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+        return sdf.parse(dateText);
+    }
+
+    public Long parseDateTimeLong(String dateText) throws ParseException {
+        if(dateText.indexOf("T") != -1){
+            dateText = dateText.replace("T"," ");
+        }
+        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+        Date date = sdf.parse(dateText);
+        return date.getTime();
+    }
+
+    //
+    public Date getTodayDate() throws ParseException {
+        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
+        return sdf.parse(sdf.format(new Date()));
+    }
+
+    public Date getTodayDatetime() throws ParseException {
+        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+        return sdf.parse(sdf.format(new Date()));
+    }
+
+    public String getTodayDateText() throws ParseException {
+        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
+        return sdf.format(new Date());
+    }
+
+    public String getTodayText() throws ParseException {
+        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+        return sdf.format(new Date());
+    }
+
+    public String getNowText() throws ParseException {
+        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
+        return sdf.format(new Date());
+    }
+
+    public String getTodayMissionText() throws ParseException {
+        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
+        return sdf.format(new Date());
+    }
+
+    public String getStartDateInThisMonth(){
+        DateTime date = cn.hutool.core.date.DateUtil.date();
+        return (cn.hutool.core.date.DateUtil.beginOfMonth(date) + "").substring(0, 10);
+    }
+
+    public String getEndDateInThisMonth(){
+        DateTime date = cn.hutool.core.date.DateUtil.date();
+        return (date + "").substring(0, 10);
+    }
+
+    /**
+     * 获取过去或者未来 任意天内的日期数组
+     * @param intervals      intervals天内
+     * @return              日期数组
+     */
+    public ArrayList<String> test(int intervals ) {
+        ArrayList<String> pastDaysList = new ArrayList<>();
+        ArrayList<String> fetureDaysList = new ArrayList<>();
+        for (int i = 0; i <intervals; i++) {
+            pastDaysList.add(getPastDate(i));
+            fetureDaysList.add(getFetureDate(i));
+        }
+        return pastDaysList;
+    }
+
+    /**
+     * 获取过去第几天的日期
+     *
+     * @param past
+     * @return
+     */
+    public String getPastDate(int past) {
+        Calendar calendar = Calendar.getInstance();
+        calendar.set(Calendar.DAY_OF_YEAR, calendar.get(Calendar.DAY_OF_YEAR) - past);
+        Date today = calendar.getTime();
+        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
+        String result = format.format(today);
+        return result;
+    }
+
+    /**
+     * 获取未来 第 past 天的日期
+     * @param past
+     * @return
+     */
+    public String getFetureDate(int past) {
+        Calendar calendar = Calendar.getInstance();
+        calendar.set(Calendar.DAY_OF_YEAR, calendar.get(Calendar.DAY_OF_YEAR) + past);
+        Date today = calendar.getTime();
+        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
+        String result = format.format(today);
+        return result;
+    }
+
+    //重新构建日期
+    public String rebuildDateTime(String text){
+        return text.substring(0,4)+"-"+text.substring(4,6)+"-"+text.substring(6,8)+" "+text.substring(8,10)+":"+text.substring(10,12)+":"+text.substring(12,14);
+    }
+
+    public static void main(String[] args){
+        DateUtil du = new DateUtil();
+        //
+        du.test1();
+    }
+
+    private void test1() {
+        String text = "20211201104300";
+//        String text = "1234567890abcd";
+        String date = text.substring(0,4)+"-"+text.substring(4,6)+"-"+text.substring(6,8)+" "+text.substring(8,10)+":"+text.substring(10,12)+":"+text.substring(12,14);
+        System.out.println("date="+date);
+    }
+
+    //获取long时间
+    public Long getNowLong(){
+        Calendar calendar = Calendar.getInstance();
+        calendar.set(calendar.get(Calendar.YEAR),calendar.get(Calendar.MONTH),calendar.get(Calendar.DAY_OF_MONTH)-1,0,0,0);
+        return calendar.getTime().getTime();
+    }
+}

+ 90 - 0
huimv-eartag2-platform/huimv-eartag2-device/src/main/java/com/huimv/eartag2/device/utils/MathUtil.java

@@ -0,0 +1,90 @@
+package com.huimv.eartag2.device.utils;
+
+import org.springframework.stereotype.Component;
+
+import java.text.DecimalFormat;
+import java.text.NumberFormat;
+
+/**
+ * @Project : huimv.shiwan
+ * @Package : com.huimv.biosafety.uface.controller
+ * @Description : TODO
+ * @Version : 1.0
+ * @Author : ZhuoNing
+ * @Create : 2020-12-25
+ **/
+@Component
+public class MathUtil {
+
+    public static double A = 0.00335396319311466;
+    public static double B = 0.000256376549039663;
+    public static double C = 0.00000248933580817244;
+    public static double D = 0.0000000753805242068686;
+    public static double E = -0.0000000204758173596178;
+
+    //保留一位小数
+    public static  double changeDouble(Double dou) {
+        NumberFormat nf = new DecimalFormat("0.0 ");
+        dou = Double.parseDouble(nf.format(dou));
+        return dou;
+    }
+
+    public static double ln(int rv) {
+        int R_REF = 10000;
+        double ln = Math.log((double) rv / R_REF);
+//        System.out.println("$$$$$$$$$ ln>>"+ln);
+        //保留一位小数
+        return changeDouble(1 / (A + B * ln + C * Math.pow(ln, 2) + D * Math.pow(ln, 3) + E * Math.pow(ln, 4)) - 273.15) + 0.001;
+    }
+
+    public String formatBit(float num, int bit) {
+        // 创建一个数值格式化对象
+        NumberFormat numberFormat = NumberFormat.getInstance();
+        // 设置精确到小数点后2位
+        numberFormat.setMaximumFractionDigits(bit);
+        return numberFormat.format(num);
+    }
+
+    public String formatBit(float num) {
+        return String.valueOf(num);
+    }
+
+    //计算比率
+    public String countRate(float num, int bit) {
+        // 创建一个数值格式化对象
+        NumberFormat numberFormat = NumberFormat.getInstance();
+        // 设置精确到小数点后2位
+        numberFormat.setMaximumFractionDigits(bit);
+        return numberFormat.format(num * 100);//所占百分比
+    }
+
+    //计算占比
+    public String countRate(float num, float total,int bit) {
+        // 创建一个数值格式化对象
+        NumberFormat numberFormat = NumberFormat.getInstance();
+        // 设置精确到小数点后2位
+        numberFormat.setMaximumFractionDigits(bit);
+        //所占百分比
+        return numberFormat.format((float)  num/ (float)total* 100);
+    }
+
+    //格式化
+    public String format(float num, int bit) {
+        // 创建一个数值格式化对象
+        NumberFormat numberFormat = NumberFormat.getInstance();
+        // 设置精确到小数点后2位
+        numberFormat.setMaximumFractionDigits(bit);
+        return numberFormat.format(num * 100);//所占百分比
+    }
+
+    //格式化
+    public String format(float num, float total,int bit) {
+        // 创建一个数值格式化对象
+        NumberFormat numberFormat = NumberFormat.getInstance();
+        // 设置精确到小数点后2位
+        numberFormat.setMaximumFractionDigits(bit);
+        //所占百分比
+        return numberFormat.format((float)  num/ (float)total* 100);
+    }
+
+}

+ 107 - 0
huimv-eartag2-platform/huimv-eartag2-device/src/main/resources/application-dev.yml

@@ -0,0 +1,107 @@
+server:
+  port: 8092
+spring:
+  application:
+    name: huimv-eartag2-process
+
+  datasource:
+    url: jdbc:mysql://192.168.1.7:3306/huimv-demo-eartag20?useUnicode=true&characterEncoding=UTF-8&useSSL=false&autoReconnect=true&serverTimezone=Asia/Shanghai
+    username: root
+    password: hm123456
+    driver-class-name: com.mysql.cj.jdbc.Driver
+  jpa:
+    show-sql: true
+    database: mysql
+    hibernate:
+      ddl-auto: update
+    database-platform: org.hibernate.dialect.MySQL5InnoDBDialect
+    open-in-view: true
+
+  #配置rabbitMq 服务器
+#  rabbitmq:
+#    host: 10.0.0.4
+#    port: 5672
+#    username: huimv
+#    password: hm123456
+#    #虚拟host 可以不设置,使用server默认host
+#    virtual-host: /
+  rabbitmq:
+    host: 192.168.1.170
+    port: 5672
+    username: admin
+    password: admin
+    #虚拟host 可以不设置,使用server默认host
+    virtual-host: /
+    listener:
+      simple:
+        acknowledge-mode: none  #消费端不需要确认
+
+  #redis
+  redis:
+    database: 0
+    host: 192.168.1.68
+    port: 6379
+    password: hm123456
+    timeout: 5000ms
+    jedis:
+      pool:
+        max-active: 20
+        max-wait: -1
+        max-idle: 10
+        min-idle: 0
+
+  #redis
+#  redis:
+#    database: 0
+#    host: 192.168.1.68
+#    port: 6379
+#    password: hm123456
+#    timeout: 5000ms
+#    jedis:
+#      pool:
+#        max-active: 20
+#        max-wait: -1
+#        max-idle: 10
+#        min-idle: 0
+#    lettuce:
+#      pool:
+#        max-active: 3
+#        min-idle: 2
+#        max-idle: 3
+#        max-wait: 1
+#      shutdown-timeout: 100
+
+#  data:
+#    redis:
+#      repositories:
+#        enabled: false
+
+  #是否缓存空值
+#  cache:
+#    redis:
+#      cache-null-values: false
+    #server:
+#  port: 9110
+#spring:
+#  application:
+#    name: huimv-hy-autoGetData
+#
+#  datasource:
+##    url: jdbc:mysql://47.98.175.112:3306/huimv_ql_farm_haiyan?useUnicode=true&characterEncoding=UTF-8&useSSL=false&autoReconnect=true&serverTimezone=Asia/Shanghai
+#    #    url: jdbc:mysql://36.22.189.214:3306/huimv_ql_farm?useUnicode=true&characterEncoding=UTF-8&useSSL=false&autoReconnect=true&serverTimezone=Asia/Shanghai
+#        url: jdbc:mysql://192.168.1.7:3306/huimv_ql_farm?useUnicode=true&characterEncoding=UTF-8&useSSL=false&autoReconnect=true&serverTimezone=Asia/Shanghai
+#    username: root
+#    password: hm123456
+#    driver-class-name: com.mysql.cj.jdbc.Driver
+#  jpa:
+#    properties:
+#      hibernate:
+#        enable_lazy_load_no_trans: true
+#    show-sql: true
+#    database: mysql
+#    hibernate:
+#      ddl-auto: update
+#    database-platform: org.hibernate.dialect.MySQL5InnoDBDialect
+#    open-in-view: true
+
+

+ 1 - 0
huimv-eartag2-platform/huimv-eartag2-device/src/main/resources/application.properties

@@ -0,0 +1 @@
+spring.profiles.active=dev