Просмотр исходного кода

feat:青萍设备预警进行微信公众号提醒

陈长荣 5 месяцев назад
Родитель
Сommit
753b3362c9

+ 44 - 7
snowy-plugin/snowy-plugin-coldchain/src/main/java/vip/xiaonuo/coldchain/modular/qp/config/QpPush.java → snowy-plugin/snowy-plugin-coldchain/src/main/java/vip/xiaonuo/coldchain/modular/qp/config/QpApi.java

@@ -15,15 +15,12 @@ import org.springframework.stereotype.Component;
 import vip.xiaonuo.coldchain.modular.qp.vo.QpAlertConfigVo;
 import vip.xiaonuo.common.cache.CommonCacheOperator;
 
-import java.util.Arrays;
-import java.util.Base64;
-import java.util.Collections;
-import java.util.List;
+import java.util.*;
 
 @Slf4j
 @Component
 @RequiredArgsConstructor
-public class QpPush {
+public class QpApi {
 
     private final CommonCacheOperator cacheOperator;
     private final QpConfig qpConfig;
@@ -175,7 +172,7 @@ public class QpPush {
     /**
      * 保存或更新报警配置
      *
-     * @param mac      mac地址
+     * @param mac       mac地址
      * @param configVos 报警配置
      */
     public void saveConfig(String mac, List<QpAlertConfigVo> configVos) {
@@ -193,7 +190,47 @@ public class QpPush {
             //调用接口暂停一会
             try {
                 Thread.sleep(200);
-            } catch (InterruptedException ignored) {}
+            } catch (InterruptedException ignored) {
+            }
+        }
+    }
+
+    /**
+     * 获取设备列表
+     */
+    public JSONObject getDevices() {
+        String accessToken = getAccessToken();
+        try (HttpResponse response = HttpUtil.createGet("https://apis.cleargrass.com/v1/apis/devices?timestamp=" + System.currentTimeMillis())
+                .bearerAuth(accessToken)
+                .execute()) {
+            String body = response.body();
+            log.info("查询青萍设备列表: {}", body);
+            return JSON.parseObject(body);
         }
     }
+
+    /**
+     * 获取设备数据
+     *
+     * @param mac mac地址
+     * @return {"battery":{"value":70},"humidity":{"value":22.2},"pressure":{"value":103.29},"temperature":{"value":20.8},"timestamp":{"value":1574565267}}
+     */
+    public JSONObject getDeviceData(String mac) {
+        Assert.notBlank(mac, "mac不能为空");
+        JSONObject devices = getDevices();
+        if (devices.getInteger("total") < 1) {
+            return new JSONObject();
+        }
+
+        JSONArray deviceArray = devices.getJSONArray("devices");
+        Optional<JSONObject> opt = deviceArray.stream()
+                .map(x -> (JSONObject) x)
+                .filter(x -> mac.equals(x.getJSONObject("info").getString("mac")))
+                .findFirst();
+        if (opt.isEmpty()) {
+            return new JSONObject();
+        }
+
+        return opt.get().getJSONObject("data");
+    }
 }

+ 15 - 13
snowy-plugin/snowy-plugin-coldchain/src/main/java/vip/xiaonuo/coldchain/modular/qp/controller/QPController.java

@@ -1,24 +1,16 @@
 package vip.xiaonuo.coldchain.modular.qp.controller;
 
-import cn.hutool.json.JSONArray;
-import cn.hutool.json.JSONObject;
-import cn.hutool.json.JSONUtil;
-import com.github.jfcloud.influxdb.service.JfcloudInfluxDBService;
 import jakarta.annotation.Resource;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.web.bind.annotation.PostMapping;
 import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RestController;
-import vip.xiaonuo.coldchain.core.bean.influxdb.SensorData;
 import vip.xiaonuo.coldchain.modular.qp.service.QPService;
 import vip.xiaonuo.common.pojo.CommonResult;
 
-import java.text.SimpleDateFormat;
-import java.util.Date;
-import java.util.List;
-import java.util.Map;
-
 @RestController
+@RequestMapping("qp")
 @Slf4j
 public class QPController {
 
@@ -26,9 +18,19 @@ public class QPController {
     private QPService qpService;
 
 
-    @PostMapping("qp/save")
-    public CommonResult<String> save(@RequestBody Map<String,Object> map) {
-        qpService.save(map);
+    @PostMapping("/save")
+    public CommonResult<String> save(@RequestBody String param) {
+        qpService.save(param);
+        return CommonResult.ok();
+    }
+
+
+    /**
+     * 事件推送
+     */
+    @PostMapping("/event")
+    public CommonResult<String> triggerEvent(@RequestBody String param) {
+        qpService.triggerEvent(param);
         return CommonResult.ok();
     }
 }

+ 9 - 31
snowy-plugin/snowy-plugin-coldchain/src/main/java/vip/xiaonuo/coldchain/modular/qp/listener/QpListener.java

@@ -2,17 +2,14 @@ package vip.xiaonuo.coldchain.modular.qp.listener;
 
 import cn.hutool.core.util.StrUtil;
 import cn.hutool.json.JSONArray;
-import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.stereotype.Component;
-import vip.xiaonuo.coldchain.modular.monitordevice.entity.MonitorDevice;
 import vip.xiaonuo.coldchain.modular.monitordevice.service.MonitorDeviceService;
 import vip.xiaonuo.coldchain.modular.monitortargetregion.entity.MonitorTargetRegion;
 import vip.xiaonuo.coldchain.modular.monitortargetregion.enums.MonitorTargetRegionEvent;
-import vip.xiaonuo.coldchain.modular.qp.config.QpPush;
+import vip.xiaonuo.coldchain.modular.qp.config.QpApi;
 import vip.xiaonuo.coldchain.modular.qp.vo.QpAlertConfigVo;
-import vip.xiaonuo.common.enums.CommonDeleteFlagEnum;
 import vip.xiaonuo.common.listener.CommonDataChangeListener;
 import vip.xiaonuo.dev.modular.config.service.DevConfigService;
 
@@ -25,7 +22,7 @@ import java.util.stream.Stream;
 @RequiredArgsConstructor
 public class QpListener implements CommonDataChangeListener {
 
-    private final QpPush qpPush;
+    private final QpApi qpApi;
     private final DevConfigService devConfigService;
     private final MonitorDeviceService monitorDeviceService;
 
@@ -51,41 +48,22 @@ public class QpListener implements CommonDataChangeListener {
             return;
         }
 
-        List<MonitorTargetRegion> monitorTargetRegionList = jsonArray.toList(MonitorTargetRegion.class);
-        if (monitorTargetRegionList.isEmpty()) {
-            return;
-        }
-
-        Set<String> deviceIdSet = monitorTargetRegionList.stream()
-                .map(MonitorTargetRegion::getMonitorDeviceId)
-                .filter(Objects::nonNull)
-                .collect(Collectors.toSet());
-        if (deviceIdSet.isEmpty()) {
-            return;
-        }
-
         //获取青萍的设备型号
         String qingpingType = devConfigService.getValueByKey("qingping_type");
-        if (qingpingType == null) {
-            return;
-        }
         Set<String> qpDeviceType = Stream.of(qingpingType.split(",")).filter(StrUtil::isNotBlank).collect(Collectors.toSet());
 
-        //获取设备型号
-        List<MonitorDevice> qpDeviceList = monitorDeviceService.list(new LambdaQueryWrapper<>(MonitorDevice.class)
-                .in(MonitorDevice::getId, deviceIdSet)
-                .in(MonitorDevice::getModelName, qpDeviceType)
-                .eq(MonitorDevice::getDeleteFlag, CommonDeleteFlagEnum.NOT_DELETE));
-        if (qpDeviceList.isEmpty()) {
+        List<MonitorTargetRegion> monitorTargetRegionList = jsonArray.toList(MonitorTargetRegion.class)
+                .stream()
+                .filter(x -> qpDeviceType.contains(x.getModelName()))
+                .toList();
+        if (monitorTargetRegionList.isEmpty()) {
             return;
         }
 
         //监测点配置更新中的青萍设备
         Map<String, List<QpAlertConfigVo>> qpAlertConfigMap = new LinkedHashMap<>();
-        Map<String, String> qpDeviceMac = qpDeviceList.stream().collect(Collectors.toMap(MonitorDevice::getId, MonitorDevice::getDeviceCode));
-        monitorTargetRegionList = monitorTargetRegionList.stream().filter(x -> qpDeviceMac.containsKey(x.getMonitorDeviceId())).toList();
         for (MonitorTargetRegion region : monitorTargetRegionList) {
-            String mac = qpDeviceMac.get(region.getMonitorDeviceId());
+            String mac = region.getSensorCode();
             if (!qpAlertConfigMap.containsKey(mac)) {
                 qpAlertConfigMap.put(mac, new ArrayList<>());
             }
@@ -139,7 +117,7 @@ public class QpListener implements CommonDataChangeListener {
             }
         }
 
-        qpAlertConfigMap.forEach(qpPush::saveConfig);
+        qpAlertConfigMap.forEach(qpApi::saveConfig);
     }
 
     @Override

+ 4 - 3
snowy-plugin/snowy-plugin-coldchain/src/main/java/vip/xiaonuo/coldchain/modular/qp/service/QPService.java

@@ -1,7 +1,8 @@
 package vip.xiaonuo.coldchain.modular.qp.service;
 
-import java.util.Map;
-
 public interface QPService {
-    void save(Map<String, Object> map);
+
+    void save(String param);
+
+    void triggerEvent(String param);
 }

+ 78 - 5
snowy-plugin/snowy-plugin-coldchain/src/main/java/vip/xiaonuo/coldchain/modular/qp/service/impl/QPServiceImpl.java

@@ -1,29 +1,48 @@
 package vip.xiaonuo.coldchain.modular.qp.service.impl;
 
+import cn.hutool.core.util.StrUtil;
 import cn.hutool.json.JSONArray;
 import cn.hutool.json.JSONObject;
 import cn.hutool.json.JSONUtil;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.github.jfcloud.influxdb.service.JfcloudInfluxDBService;
 import jakarta.annotation.Resource;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.context.ApplicationEventPublisher;
 import org.springframework.stereotype.Service;
 import vip.xiaonuo.coldchain.core.bean.influxdb.SensorData;
+import vip.xiaonuo.coldchain.core.event.SensorDataEvent;
+import vip.xiaonuo.coldchain.modular.monitortargetregion.entity.MonitorTargetRegion;
+import vip.xiaonuo.coldchain.modular.monitortargetregion.service.MonitorTargetRegionService;
+import vip.xiaonuo.coldchain.modular.qp.config.QpApi;
 import vip.xiaonuo.coldchain.modular.qp.service.QPService;
+import vip.xiaonuo.coldchain.modular.qp.vo.QpAlertConfigVo;
+import vip.xiaonuo.common.enums.CommonDeleteFlagEnum;
 
-import java.text.SimpleDateFormat;
-import java.util.Date;
 import java.util.List;
-import java.util.Map;
 
+@Slf4j
 @Service
 public class QPServiceImpl implements QPService {
 
     @Resource
     private JfcloudInfluxDBService jfcloudInfluxDBService;
 
+    @Resource
+    private ApplicationEventPublisher applicationEventPublisher;
+
+    @Resource
+    private QpApi qpApi;
+
+    @Resource
+    private MonitorTargetRegionService monitorTargetRegionService;
+
     @Override
-    public void save(Map<String, Object> map) {
+    public void save(String param) {
+        log.info("青萍设备数据接收:{}", param);
+
         SensorData sensorData = new SensorData();
-        JSONObject mapJson = JSONUtil.parseObj(JSONUtil.toJsonStr(map));
+        JSONObject mapJson = JSONUtil.parseObj(param);
         JSONObject payloadJson = mapJson.getJSONObject("payload");
         JSONObject infoJson = payloadJson.getJSONObject("info");
         sensorData.setDeviceId(infoJson.getStr("mac"));
@@ -63,4 +82,58 @@ public class QPServiceImpl implements QPService {
 
         jfcloudInfluxDBService.writePojo(sensorData);
     }
+
+    @Override
+    public void triggerEvent(String param) {
+        log.info("青萍设备事件接收 :{}", param);
+
+        JSONObject paramObj = JSONUtil.parseObj(param);
+        JSONObject payloadObj = paramObj.getJSONObject("payload");
+        String mac = payloadObj.getByPath("info.mac", String.class);
+
+        //根据mac查询deviceId
+        MonitorTargetRegion region = monitorTargetRegionService.getOne(new LambdaQueryWrapper<>(MonitorTargetRegion.class)
+                .eq(MonitorTargetRegion::getSensorCode, mac)
+                .eq(MonitorTargetRegion::getDeleteFlag, CommonDeleteFlagEnum.NOT_DELETE)
+                .last("limit 1"));
+
+        JSONArray events = payloadObj.getJSONArray("events");
+        for (int i = 0; i < events.size(); i++) {
+            JSONObject event = events.getJSONObject(i);
+            //触发提醒
+            if (!"alert".equals(event.getStr("action"))) {
+                continue;
+            }
+
+            QpAlertConfigVo alertConfig = event.get("alert_config", QpAlertConfigVo.class);
+            SensorData sensorData = new SensorData();
+            sensorData.setModelName(mac);
+            sensorData.setDeviceId(mac);
+            sensorData.setRoads(region.getSensorRoute());
+
+            if (alertConfig.getMetric_name().equals("temperature")) {
+                log.info("青萍设备温度预警 mac={}", mac);
+                sensorData.setTemperature(event.getByPath("data.temperature.value", Float.class));
+            } else if (alertConfig.getMetric_name().equals("humidity")) {
+                log.info("青萍设备湿度预警 mac={}", mac);
+                sensorData.setHumidity(event.getByPath("data.humidity.value", Float.class));
+            } else if (alertConfig.getMetric_name().equals("co2")) {
+                log.info("青萍设备二氧化碳预警 mac={}", mac);
+                String co2Str = event.getByPath("data.co2.value", String.class);
+                if (StrUtil.isEmpty(co2Str)) {
+                    //没有二氧化碳的数据,查询设备列表获取
+                    com.alibaba.fastjson.JSONObject jsonObject = qpApi.getDeviceData(mac);
+                    co2Str = jsonObject.getJSONObject("co2").getString("value");
+                }
+                sensorData.setCo2(Float.parseFloat(co2Str));
+            }
+
+            log.info("青萍设备发送提醒 mac={} sensorData={}", mac, JSONUtil.toJsonStr(sensorData));
+            try {
+                applicationEventPublisher.publishEvent(new SensorDataEvent(this, sensorData));
+            } catch (Exception e) {
+                log.error("保存传感器数据失败: {}", sensorData, e);
+            }
+        }
+    }
 }