From 4ee3f6be908d34b341d3582a16ec490b35a92e38 Mon Sep 17 00:00:00 2001 From: rqian <1206436827@qq.com> Date: Wed, 9 Sep 2026 09:01:54 +0800 Subject: [PATCH] =?UTF-8?q?#=E4=BC=98=E5=8C=96=E6=9B=B4=E6=96=B0=20?= =?UTF-8?q?=E8=BF=9E=E6=8E=A5=E4=B8=8A=E4=BD=8D=E6=9C=BA=E7=9B=B8=E5=85=B3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/maibu/constant}/NettyCacheKey.java | 6 +- .../java/com/maibu/core/business/Device.java | 22 +-- .../business/DeviceModelPropertyMapping.java | 6 +- .../maibu/core/business/DeviceRunParam.java | 2 +- .../core/business/device/NettyDevice.java | 59 +++---- .../com/maibu/core/host/LocationMessage.java | 16 +- .../com/maibu/influxdb/MowerRealTimeData.java | 2 - .../com/maibu/mapper/HostLocationMapper.java | 14 ++ .../maibu/memory/DeviceSessionManager.java | 7 + .../com/maibu/mqtt/HostMessageHandler.java | 26 +-- .../java/com/maibu/utils/IoTDAMqttClient.java | 2 +- .../netty/handler/DataToDataBaseHandler.java | 2 +- .../com/maibu/scheduled/ScheduledTask.java | 2 +- .../maibu/service/DeviceThreadService.java | 152 +++++++++++------- .../controller/HostComputerController.java | 1 + .../controller/WorkRecordController.java | 10 +- .../service/impl/DeviceRunParamService.java | 131 ++++++++++----- .../maibu/service/impl/DeviceServiceImpl.java | 34 +++- .../maibu/service/impl/WorkRecordService.java | 9 +- .../resources/mapper/iot/DeviceMapper.xml | 12 ++ .../service/impl/IotDeviceCommonService.java | 33 ++-- 21 files changed, 330 insertions(+), 218 deletions(-) rename {maibu-netty-server/src/main/java/com/maibu/common => maibu-common/src/main/java/com/maibu/constant}/NettyCacheKey.java (52%) create mode 100644 maibu-common/src/main/java/com/maibu/mapper/HostLocationMapper.java diff --git a/maibu-netty-server/src/main/java/com/maibu/common/NettyCacheKey.java b/maibu-common/src/main/java/com/maibu/constant/NettyCacheKey.java similarity index 52% rename from maibu-netty-server/src/main/java/com/maibu/common/NettyCacheKey.java rename to maibu-common/src/main/java/com/maibu/constant/NettyCacheKey.java index 05540c1..6673423 100644 --- a/maibu-netty-server/src/main/java/com/maibu/common/NettyCacheKey.java +++ b/maibu-common/src/main/java/com/maibu/constant/NettyCacheKey.java @@ -1,9 +1,9 @@ -package com.maibu.common; - -import lombok.Data; +package com.maibu.constant; public class NettyCacheKey { public static final String deviceRunningStatusKey = "running_status:"; + public static final String latestPositonKey = "latest_position:"; + } diff --git a/maibu-common/src/main/java/com/maibu/core/business/Device.java b/maibu-common/src/main/java/com/maibu/core/business/Device.java index 957539c..37de3f1 100644 --- a/maibu-common/src/main/java/com/maibu/core/business/Device.java +++ b/maibu-common/src/main/java/com/maibu/core/business/Device.java @@ -13,6 +13,8 @@ import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.annotation.JsonInclude; import com.maibu.annotation.Excel; import com.maibu.core.domain.BaseDO; +import com.maibu.core.host.LocationMessage; +import com.maibu.core.host.VehicleMessage; import com.maibu.influxdb.MowerRealTimeData; import io.swagger.annotations.ApiModel; @@ -72,7 +74,6 @@ public class Device extends BaseDO { @Excel(name = "产品名称") private String productName; - /** * 租户名称 */ @@ -87,7 +88,6 @@ public class Device extends BaseDO { @Excel(name = "固件版本") private BigDecimal firmwareVersion; - /** * WIFI固件版本 */ @@ -95,7 +95,6 @@ public class Device extends BaseDO { @Excel(name = "HTTP推送固件版本") private BigDecimal wirelessVersion; - /** * 设备状态(1-未激活,2-禁用,3-在线,4-离线) */ @@ -111,7 +110,7 @@ public class Device extends BaseDO { private Integer onlineStatus; @TableField(exist = false) - private Integer feStatus; //前端大屏显示 1任务中/2空闲 + private Integer feStatus; // 前端大屏显示 1任务中/2空闲 /** * wifi信号强度(信号极好4格[-55— 0],信号好3格[-70— -55],信号一般2格[-85— -70],信号差1格[-100— -85]) @@ -194,7 +193,6 @@ public class Device extends BaseDO { @ApiModelProperty("设备摘要") private String summary; - /** * 是否是模拟设备 */ @@ -206,12 +204,12 @@ public class Device extends BaseDO { @ApiModelProperty("子设备地址") private Integer slaveId; - @TableField(updateStrategy = FieldStrategy.IGNORED) private Long siteId; @TableField(updateStrategy = FieldStrategy.IGNORED) private Long orgId; + /** * 租户ID */ @@ -220,7 +218,6 @@ public class Device extends BaseDO { @TableField(updateStrategy = FieldStrategy.IGNORED) private Long tenantId; - @TableField(exist = false) private DeviceRunningStatusHistory lastRunningStatus; @@ -228,12 +225,19 @@ public class Device extends BaseDO { private MowerRealTimeData lastMowerRealTimeData; @TableField(exist = false) - private Map statusStatistics; + private Map statusStatistics; @TableField(exist = false) private DeviceRunParam runParam; - private boolean hasRegistered = false; + private boolean hasHost = false; + + @TableField(exist = false) + private LocationMessage locationMessage; + + @TableField(exist = false) + private VehicleMessage vehicleMessage; + } diff --git a/maibu-common/src/main/java/com/maibu/core/business/DeviceModelPropertyMapping.java b/maibu-common/src/main/java/com/maibu/core/business/DeviceModelPropertyMapping.java index ccb725c..6524769 100644 --- a/maibu-common/src/main/java/com/maibu/core/business/DeviceModelPropertyMapping.java +++ b/maibu-common/src/main/java/com/maibu/core/business/DeviceModelPropertyMapping.java @@ -1,18 +1,14 @@ package com.maibu.core.business; import com.baomidou.mybatisplus.annotation.IdType; -import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; import com.fasterxml.jackson.annotation.JsonInclude; import com.maibu.core.domain.BaseDO; -import com.maibu.core.enums.ConnectType; -import io.swagger.annotations.ApiModel; + import lombok.Data; import lombok.EqualsAndHashCode; -import java.util.List; - @EqualsAndHashCode(callSuper = true) @JsonInclude(JsonInclude.Include.NON_NULL) diff --git a/maibu-common/src/main/java/com/maibu/core/business/DeviceRunParam.java b/maibu-common/src/main/java/com/maibu/core/business/DeviceRunParam.java index 8049650..5f3e381 100644 --- a/maibu-common/src/main/java/com/maibu/core/business/DeviceRunParam.java +++ b/maibu-common/src/main/java/com/maibu/core/business/DeviceRunParam.java @@ -58,7 +58,7 @@ public class DeviceRunParam extends BaseDO { private String engineType;//发动机类型:honda-本田发动机 @Excel(name = "是否搭载上位机",cellType = Excel.ColumnType.NUMERIC) - private Integer hasHost;//是否搭载上位机 + private Integer hasHost = 1;//是否搭载上位机 @Excel(name = "设备能力列表") @TableField(exist = false) diff --git a/maibu-common/src/main/java/com/maibu/core/business/device/NettyDevice.java b/maibu-common/src/main/java/com/maibu/core/business/device/NettyDevice.java index 5297ad4..662a8e5 100644 --- a/maibu-common/src/main/java/com/maibu/core/business/device/NettyDevice.java +++ b/maibu-common/src/main/java/com/maibu/core/business/device/NettyDevice.java @@ -138,24 +138,6 @@ public class NettyDevice extends Connector { return finishId; } - // public synchronized boolean cancelTask() { - // if (task != null) { - // sendPathCommand((byte) 0x01, (short) 0, 0.00d, 0.00d, (short) 0); - // task.setTaskStaus(DeviceTaskStaus.CANCELED); - // task.setUpdateTime(LocalDateTime.now()); - // devicePlanTaskMapper.saveOrUpdate(task); - // SiteMemory siteMemory = GlobalMemory.getSiteMemory(task.getOrgId(), - // task.getSiteId()); - // siteMemory.removeDevicePlanPrepare(task); - // siteMemory.removeDevicePlanExecute(task.getDeviceId()); - // task = null; - // currentTaskId = null; - // currentPoint = null; - // locationQueue.clear(); - // executingTask = false; - // } - // return true; - // } public synchronized boolean cancelingTask() throws MqttException { if (task != null) { @@ -200,6 +182,24 @@ public class NettyDevice extends Connector { return true; } + public synchronized boolean failedTask() { + if (task != null) { + task.setTaskStaus(DeviceTaskStaus.FAILED); + task.setUpdateTime(LocalDateTime.now()); + devicePlanTaskMapper.saveOrUpdate(task); + SiteMemory siteMemory = GlobalMemory.getSiteMemory(task.getOrgId(), task.getSiteId()); + siteMemory.removeDevicePlanPrepare(task); + siteMemory.removeDevicePlanExecute(task.getDeviceId()); + GlobalMemory.taskPathMap.remove(task.getId()); + task = null; + currentTaskId = null; + currentPoint = null; + locationQueue.clear(); + executingTask = false; + } + return true; + } + public void sendPathCommand(byte commandType, short pointCounts, double lat, double lng, short speed) { RoutePlanSendEntity routePlanSendEntity = new RoutePlanSendEntity(); routePlanSendEntity.setCommandType(commandType); @@ -296,29 +296,6 @@ public class NettyDevice extends Connector { } } - // public void startTask() { - // try { - // if (executingTask) - // return; - // if (task != null) { - // Long routeId = task.getRouteId(); - // WorkRecord workRecord = workRecordMapper.selectById(routeId); - // if (workRecord != null) { - // PlanPath planPath = workRecord.getJsonData(); - // if (planPath != null && !CollectionUtils.isEmpty(planPath.getPath())) { - // planPath.getPath().forEach(x -> { - // locationQueue.offer(x); - // }); - // } - // } - // task.setStartTime(LocalDateTime.now()); - // } - // executingTask = true; - // sendNextPoint(); - // } catch (Exception e) { - // throw new RuntimeException(e); - // } - // } public void startTask() { try { diff --git a/maibu-common/src/main/java/com/maibu/core/host/LocationMessage.java b/maibu-common/src/main/java/com/maibu/core/host/LocationMessage.java index 986c0e5..4904cbc 100644 --- a/maibu-common/src/main/java/com/maibu/core/host/LocationMessage.java +++ b/maibu-common/src/main/java/com/maibu/core/host/LocationMessage.java @@ -1,14 +1,26 @@ package com.maibu.core.host; +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.maibu.core.domain.OrgNoUserDO; import lombok.Data; +import lombok.EqualsAndHashCode; @Data -public class LocationMessage { +@EqualsAndHashCode(callSuper = true) +@TableName("iot_host_location_message") +public class LocationMessage extends OrgNoUserDO { + + @TableId(type = IdType.AUTO) + private Long id; + + private String deviceId; private double latitude; private double longitude; - private double yaw;//目标航向,正北0°、顺时针正、0-360° + private double yaw;// 目标航向,正北0°、顺时针正、0-360° private String fix_status; private double altitude; diff --git a/maibu-common/src/main/java/com/maibu/influxdb/MowerRealTimeData.java b/maibu-common/src/main/java/com/maibu/influxdb/MowerRealTimeData.java index 91c790e..2a9f97e 100644 --- a/maibu-common/src/main/java/com/maibu/influxdb/MowerRealTimeData.java +++ b/maibu-common/src/main/java/com/maibu/influxdb/MowerRealTimeData.java @@ -6,8 +6,6 @@ import java.util.List; import java.util.Map; import java.util.stream.Collectors; -import org.springframework.util.CollectionUtils; - import com.influxdb.query.FluxRecord; import com.influxdb.query.FluxTable; import com.maibu.influxdb.inter.InfluxField; diff --git a/maibu-common/src/main/java/com/maibu/mapper/HostLocationMapper.java b/maibu-common/src/main/java/com/maibu/mapper/HostLocationMapper.java new file mode 100644 index 0000000..54dbaed --- /dev/null +++ b/maibu-common/src/main/java/com/maibu/mapper/HostLocationMapper.java @@ -0,0 +1,14 @@ +package com.maibu.mapper; + +import org.springframework.stereotype.Repository; + +import com.maibu.core.host.LocationMessage; +import com.maibu.mybatis.mapper.BaseMapperX; + +/** + * 设备历史状态 + */ +@Repository +public interface HostLocationMapper extends BaseMapperX { + +} diff --git a/maibu-common/src/main/java/com/maibu/memory/DeviceSessionManager.java b/maibu-common/src/main/java/com/maibu/memory/DeviceSessionManager.java index 64b3ef4..f6d8b66 100644 --- a/maibu-common/src/main/java/com/maibu/memory/DeviceSessionManager.java +++ b/maibu-common/src/main/java/com/maibu/memory/DeviceSessionManager.java @@ -262,6 +262,13 @@ public class DeviceSessionManager { for (Connector connected : new HashSet<>(nettyDevice.getConnectedConnectors())) { nettyDevice.removeConnectedDevice(connected); } + // 清理channel和状态 + nettyDevice.setChannel(null); + Channel channel = channelMap.remove(deviceId); + if (channel != null) { + channelToDeviceIdMap.remove(channel); + channel.close(); + } } else { // 如果是下位机,则保留绑定关系,只清理channel和状态 nettyDevice.setChannel(null); diff --git a/maibu-common/src/main/java/com/maibu/mqtt/HostMessageHandler.java b/maibu-common/src/main/java/com/maibu/mqtt/HostMessageHandler.java index d1e1d94..e63afc2 100644 --- a/maibu-common/src/main/java/com/maibu/mqtt/HostMessageHandler.java +++ b/maibu-common/src/main/java/com/maibu/mqtt/HostMessageHandler.java @@ -3,17 +3,20 @@ package com.maibu.mqtt; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.maibu.constant.Constant; +import com.maibu.constant.NettyCacheKey; import com.maibu.core.business.device.DeviceStatusDetail; import com.maibu.core.business.device.NettyDevice; import com.maibu.core.business.dto.WebStatusMessageDTO; import com.maibu.core.business.inter.WebsocketMesDispather; import com.maibu.core.enums.MesType; import com.maibu.core.host.*; +import com.maibu.core.redis.RedisCache; import com.maibu.memory.DeviceSessionManager; import com.maibu.memory.GlobalMemory; import com.maibu.utils.StringUtils; import com.maibu.utils.json.JsonUtils; import com.maibu.utils.spring.SpringUtils; + import lombok.extern.slf4j.Slf4j; import org.springframework.util.CollectionUtils; @@ -34,6 +37,8 @@ public class HostMessageHandler implements CustomMqttMessageHandler { private final String mqttClientId = "maibu-mqtt-client"; + private final RedisCache redisCache = SpringUtils.getBean(RedisCache.class); + @Override public String getHandlerType() { return Constant.mqttHandleKey; @@ -131,6 +136,12 @@ public class HostMessageHandler implements CustomMqttMessageHandler { // GlobalMemory.customMqttDeviceMonitor.publish(mqttClientId, // String.format(MqttTopic.DEVICE_LOCATION_TOPIC, deviceId), // JsonUtils.toJsonString(dto)); + // todo 保存到内存 + String key = NettyCacheKey.latestPositonKey + deviceId; + LocationMessage locationMessage = locationRelTimeDTO.getData(); + locationMessage.setDeviceId(deviceId); + redisCache.setCacheObject(key, locationMessage); + } } catch (Exception e) { log.error("位置消息解析失败: deviceId={}, payload={}, error={}", deviceId, payload, e.getMessage()); @@ -242,14 +253,6 @@ public class HostMessageHandler implements CustomMqttMessageHandler { } } - /** - * 处理状态变更事件 - * topic: mower/{deviceId}/event/status/post - */ - private void handleStatusPost(String deviceId, String topic, String payload) { - log.info("【状态变更】deviceId={}, payload={}", deviceId, payload); - } - /** * 处理心跳 * topic: mower/{deviceId}/event/heartbeat/post @@ -291,10 +294,9 @@ public class HostMessageHandler implements CustomMqttMessageHandler { // NettyDevice nettyDevice = deviceSessionManager.getDevice(deviceId); // nettyDevice.finishTask(); // } - // if("failed".equals(dto.getStatus())){ - // NettyDevice nettyDevice = deviceSessionManager.getDevice(deviceId); - // nettyDevice.finishTask(); - // } + if ("failed".equals(dto.getStatus())) { + nettyDevice.failedTask(); + } // if("accepted".equals(dto.getStatus())){ // NettyDevice nettyDevice = deviceSessionManager.getDevice(deviceId); // nettyDevice.finishTask(); diff --git a/maibu-iotDA/src/main/java/com/maibu/utils/IoTDAMqttClient.java b/maibu-iotDA/src/main/java/com/maibu/utils/IoTDAMqttClient.java index b652c12..75fe491 100644 --- a/maibu-iotDA/src/main/java/com/maibu/utils/IoTDAMqttClient.java +++ b/maibu-iotDA/src/main/java/com/maibu/utils/IoTDAMqttClient.java @@ -6,7 +6,7 @@ import com.huaweicloud.sdk.iot.device.client.requests.CommandRsp; import com.huaweicloud.sdk.iot.device.client.requests.DeviceMessage; import com.huaweicloud.sdk.iot.device.client.requests.ServiceProperty; import com.huaweicloud.sdk.iot.device.transport.ActionListener; -import com.maibu.common.NettyCacheKey; +import com.maibu.constant.NettyCacheKey; import com.maibu.core.business.DeviceRunningStatusHistory; import com.maibu.core.business.DeviceStatusRecordDTO; import com.maibu.core.redis.RedisCache; diff --git a/maibu-netty-server/src/main/java/com/maibu/netty/handler/DataToDataBaseHandler.java b/maibu-netty-server/src/main/java/com/maibu/netty/handler/DataToDataBaseHandler.java index 75a00bc..dc1f9aa 100644 --- a/maibu-netty-server/src/main/java/com/maibu/netty/handler/DataToDataBaseHandler.java +++ b/maibu-netty-server/src/main/java/com/maibu/netty/handler/DataToDataBaseHandler.java @@ -23,7 +23,7 @@ import org.springframework.stereotype.Component; import org.springframework.util.CollectionUtils; import com.maibu.constant.CommandConstant; -import com.maibu.common.NettyCacheKey; +import com.maibu.constant.NettyCacheKey; import com.maibu.core.business.DeviceRunStatistics; import com.maibu.core.business.DeviceRunningStatusHistory; import com.maibu.core.business.DeviceStatusRecordDTO; diff --git a/maibu-netty-server/src/main/java/com/maibu/scheduled/ScheduledTask.java b/maibu-netty-server/src/main/java/com/maibu/scheduled/ScheduledTask.java index 8ede101..47a4a8f 100644 --- a/maibu-netty-server/src/main/java/com/maibu/scheduled/ScheduledTask.java +++ b/maibu-netty-server/src/main/java/com/maibu/scheduled/ScheduledTask.java @@ -1,6 +1,6 @@ package com.maibu.scheduled; -import com.maibu.common.NettyCacheKey; +import com.maibu.constant.NettyCacheKey; import com.maibu.core.business.DevicePlan; import com.maibu.core.business.DeviceRunParam; import com.maibu.core.business.DeviceStatusRecordDTO; diff --git a/maibu-netty-server/src/main/java/com/maibu/service/DeviceThreadService.java b/maibu-netty-server/src/main/java/com/maibu/service/DeviceThreadService.java index b8187f5..5062213 100644 --- a/maibu-netty-server/src/main/java/com/maibu/service/DeviceThreadService.java +++ b/maibu-netty-server/src/main/java/com/maibu/service/DeviceThreadService.java @@ -1,29 +1,19 @@ package com.maibu.service; -import cn.hutool.core.io.IORuntimeException; -import cn.hutool.core.io.IoUtil; -import com.alibaba.fastjson2.JSON; -import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; -import com.maibu.common.NettyCacheKey; -import com.maibu.constant.Constant; -import com.maibu.core.business.Device; -import com.maibu.core.business.DeviceRunningStatusHistory; -import com.maibu.core.business.DeviceStatusRecordDTO; -import com.maibu.core.business.ErrorIdentificationStandard; -import com.maibu.core.business.alarm_center.AlarmMessage; -import com.maibu.core.business.device.NettyDevice; -import com.maibu.core.business.inter.WebsocketMesDispather; -import com.maibu.core.enums.*; -import com.maibu.core.host.HeartBeatDTO; -import com.maibu.core.redis.RedisCache; -import com.maibu.dto.DeviceErrorPushDTO; -import com.maibu.mapper.ErrorIdentificationStandardMapper; -import com.maibu.memory.DeviceSessionManager; -import com.maibu.memory.GlobalMemory; -import com.maibu.memory.SiteMemory; -import com.maibu.mqtt.MqttTopic; -import com.maibu.utils.CompareUtils; -import lombok.extern.slf4j.Slf4j; +import java.io.IOException; +import java.lang.reflect.Field; +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Comparator; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; +import java.util.stream.Collectors; + import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; @@ -32,17 +22,37 @@ import org.springframework.core.io.ResourceLoader; import org.springframework.stereotype.Service; import org.springframework.util.CollectionUtils; -import javax.annotation.PreDestroy; -import java.io.IOException; -import java.lang.reflect.Field; -import java.math.BigDecimal; -import java.time.LocalDateTime; -import java.util.*; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.Executors; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.TimeUnit; -import java.util.stream.Collectors; +import com.alibaba.fastjson2.JSON; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.maibu.constant.Constant; +import com.maibu.constant.NettyCacheKey; +import com.maibu.core.business.Device; +import com.maibu.core.business.DeviceRunningStatusHistory; +import com.maibu.core.business.DeviceStatusRecordDTO; +import com.maibu.core.business.ErrorIdentificationStandard; +import com.maibu.core.business.alarm_center.AlarmMessage; +import com.maibu.core.business.device.NettyDevice; +import com.maibu.core.business.inter.WebsocketMesDispather; +import com.maibu.core.enums.CompareEnum; +import com.maibu.core.enums.ConnectorStatus; +import com.maibu.core.enums.DeviceStatus; +import com.maibu.core.enums.ErrorSource; +import com.maibu.core.enums.RespondCode; +import com.maibu.core.host.HeartBeatDTO; +import com.maibu.core.host.LocationMessage; +import com.maibu.core.redis.RedisCache; +import com.maibu.dto.DeviceErrorPushDTO; +import com.maibu.mapper.ErrorIdentificationStandardMapper; +import com.maibu.mapper.HostLocationMapper; +import com.maibu.memory.DeviceSessionManager; +import com.maibu.memory.GlobalMemory; +import com.maibu.memory.SiteMemory; +import com.maibu.mqtt.MqttTopic; +import com.maibu.utils.CompareUtils; + +import cn.hutool.core.io.IORuntimeException; +import cn.hutool.core.io.IoUtil; +import lombok.extern.slf4j.Slf4j; @Slf4j @Service @@ -75,10 +85,13 @@ public class DeviceThreadService { @Autowired private ScheduledExecutorService executor; + @Autowired + private HostLocationMapper hostLocationMapper; + public void deviceErrorMonitor() throws InterruptedException, IOException { initStandard(); - // TODO fix 后续是否分多个线程 一个site一个线程 + // TODO fix 后续是否分多个线程 一个site一个线程 // 有还需要更新接受故障方式。 executor.scheduleWithFixedDelay(() -> { try { @@ -188,8 +201,10 @@ public class DeviceThreadService { // } // } try { - GlobalMemory.customMqttDeviceMonitor.publish(mqttClientId, String.format(MqttTopic.DEVICE_ERROR_PUSH_TOPIC, deviceId), dto); -// GlobalMemory.mqttClientUtil.publish(String.format(MqttTopic.DEVICE_ERROR_PUSH_TOPIC, deviceId), dto); + GlobalMemory.customMqttDeviceMonitor.publish(mqttClientId, + String.format(MqttTopic.DEVICE_ERROR_PUSH_TOPIC, deviceId), dto); + // GlobalMemory.mqttClientUtil.publish(String.format(MqttTopic.DEVICE_ERROR_PUSH_TOPIC, + // deviceId), dto); List controlMasters = sessionManager.getAllSlaveControl(deviceId); if (!CollectionUtils.isEmpty(controlMasters)) { controlMasters.forEach(x -> { @@ -203,7 +218,7 @@ public class DeviceThreadService { } public List compareErrorStandard(Long siteId, Long orgId, DeviceRunningStatusHistory history, - List standards) { + List standards) { if (history == null || CollectionUtils.isEmpty(standards)) return null; List list = new ArrayList<>(); @@ -212,7 +227,8 @@ public class DeviceThreadService { String compareValues = standard.getCompareValues(); CompareEnum compareType = standard.getCompareType(); String targetValue = knownClassFieldFinding(fieldName, history); - log.debug("compare2 compareType:{} compareValues:{},targetValue:{}", compareType, compareValues, targetValue); + log.debug("compare2 compareType:{} compareValues:{},targetValue:{}", compareType, compareValues, + targetValue); if (!StringUtils.isEmpty(compareValues) && !StringUtils.isEmpty(targetValue)) { boolean result = CompareUtils.compare(compareType, targetValue, compareValues); log.debug("compare3 result:{}", result); @@ -253,7 +269,6 @@ public class DeviceThreadService { return null; } - /** * 监控心跳 */ @@ -268,10 +283,22 @@ public class DeviceThreadService { Long lastActiveTime = x.getSysTimestamp(); NettyDevice nettyDevice = sessionManager.getDevice(x.getSn()); if (nowTime - lastActiveTime >= Constant.hostOfflineInterval) { - //超时了判断离线 + // 超时了判断离线 if (nettyDevice != null) { - nettyDevice.status(0); - //todo 推送设备离线 + nettyDevice.status(DeviceStatus.offline.getType()); + // todo 推送设备离线 + String key = NettyCacheKey.latestPositonKey + deviceId; + // 保存一下最新一次的数据到 数据库 + LocationMessage locationMessage = redisCache.getCacheObject(key); + if (locationMessage != null) { + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + queryWrapper.eq(LocationMessage::getDeviceId, deviceId); + LocationMessage existing = hostLocationMapper.selectOne(queryWrapper); + if (existing != null) { + locationMessage.setId(existing.getId()); + } + hostLocationMapper.saveOrUpdate(locationMessage); + } } } else { if (nettyDevice == null) { @@ -289,31 +316,36 @@ public class DeviceThreadService { device.setProductName("割草机产品MC700"); device.setCreateTime(LocalDateTime.now()); device.setUpdateTime(LocalDateTime.now()); + device.setHasHost(true); deviceService.insertDeviceBySelf(device); } else { device.setStatus(3); device.setOnlineStatus(DeviceStatus.online.getType()); device.setUpdateTime(LocalDateTime.now()); + if (!device.isHasHost()) { + device.setHasHost(true); + } deviceService.updateDeviceBySelf(device); } // 推送json 找到设备绑定的主机进行推送 -// List controlMasters = sessionManager.getAllSlaveControl(device.getSerialNumber()); -// if (!CollectionUtils.isEmpty(controlMasters)) { -// controlMasters.forEach(x -> { -// DeviceStatusChangeDTO changeDTO = new DeviceStatusChangeDTO(); -// changeDTO.setDeviceId(data); -// changeDTO.setStatus(DeviceStatus.online.getCode()); -// changeDTO.setEvent(RespondCode.device_status_changed); -// ByteBuf buf = ctx.alloc().buffer(); -// CommandUtils.buildCommand(buf, changeDTO, CommandConstant.interaction); -// String content = buf.toString(CharsetUtil.UTF_8); -// logger.info("推送下位机登录状态消息:{}", content); -// if (x.getChannel() != null && x.getChannel().isActive()) { -// x.getChannel().writeAndFlush(buf); -// } -// }); + // List controlMasters = + // sessionManager.getAllSlaveControl(device.getSerialNumber()); + // if (!CollectionUtils.isEmpty(controlMasters)) { + // controlMasters.forEach(x -> { + // DeviceStatusChangeDTO changeDTO = new DeviceStatusChangeDTO(); + // changeDTO.setDeviceId(data); + // changeDTO.setStatus(DeviceStatus.online.getCode()); + // changeDTO.setEvent(RespondCode.device_status_changed); + // ByteBuf buf = ctx.alloc().buffer(); + // CommandUtils.buildCommand(buf, changeDTO, CommandConstant.interaction); + // String content = buf.toString(CharsetUtil.UTF_8); + // logger.info("推送下位机登录状态消息:{}", content); + // if (x.getChannel() != null && x.getChannel().isActive()) { + // x.getChannel().writeAndFlush(buf); + // } + // }); } else { - //todo 推送设备上线 + // todo 推送设备上线 nettyDevice.status(1); } } diff --git a/maibu-service/maibu-iot-service/src/main/java/com/maibu/controller/HostComputerController.java b/maibu-service/maibu-iot-service/src/main/java/com/maibu/controller/HostComputerController.java index aab6e07..7ece34c 100644 --- a/maibu-service/maibu-iot-service/src/main/java/com/maibu/controller/HostComputerController.java +++ b/maibu-service/maibu-iot-service/src/main/java/com/maibu/controller/HostComputerController.java @@ -162,6 +162,7 @@ public class HostComputerController extends BaseController { for (NettyDevice x : controlMasters) { try { websocketMesDispather.dispather(x.getConnectorId(), JsonUtils.toJsonString(dto)); + log.info("位置数据websocket推送成功: connectorId={}, taskId={}", x.getConnectorId(), taskId); } catch (Exception e) { log.error("位置数据websocket推送失败: connectorId={}, error={}", x.getConnectorId(), e.getMessage()); diff --git a/maibu-service/maibu-iot-service/src/main/java/com/maibu/controller/WorkRecordController.java b/maibu-service/maibu-iot-service/src/main/java/com/maibu/controller/WorkRecordController.java index a144ab3..3d105f2 100644 --- a/maibu-service/maibu-iot-service/src/main/java/com/maibu/controller/WorkRecordController.java +++ b/maibu-service/maibu-iot-service/src/main/java/com/maibu/controller/WorkRecordController.java @@ -40,9 +40,11 @@ public class WorkRecordController extends BaseController { ) { int i = -1; - // WorkRecord workRecordObj = JsonUtils.parseObject(workRecord, WorkRecord.class); + // WorkRecord workRecordObj = JsonUtils.parseObject(workRecord, + // WorkRecord.class); - WorkRecord workRecord1 = workRecordService.selectWorkRecordByWorkNameAndSiteId(workRecord.getWorkName(), workRecord.getSiteId()); + WorkRecord workRecord1 = workRecordService.selectWorkRecordByWorkNameAndSiteId(workRecord.getWorkName(), + workRecord.getSiteId()); if (workRecord1 != null) { return R.fail("该任务已存在"); } @@ -108,8 +110,8 @@ public class WorkRecordController extends BaseController { @GetMapping("/selectByTaskId") public R selectByTaskId(@RequestParam Long taskId) { - List path = workRecordService.selectByTaskId(taskId); - return R.ok(path); + WorkRecord workRecord = workRecordService.selectByTaskId(taskId); + return R.ok(workRecord); } @GetMapping("getTaskPath") diff --git a/maibu-service/maibu-iot-service/src/main/java/com/maibu/service/impl/DeviceRunParamService.java b/maibu-service/maibu-iot-service/src/main/java/com/maibu/service/impl/DeviceRunParamService.java index 3e85a90..db49be8 100644 --- a/maibu-service/maibu-iot-service/src/main/java/com/maibu/service/impl/DeviceRunParamService.java +++ b/maibu-service/maibu-iot-service/src/main/java/com/maibu/service/impl/DeviceRunParamService.java @@ -1,22 +1,5 @@ package com.maibu.service.impl; -import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; -import com.maibu.annotation.Excel; -import com.maibu.constant.Constant; -import com.maibu.core.business.DeviceRunParam; -import com.maibu.core.business.device.NettyDevice; -import com.maibu.dto.BaseQueryDTO; -import com.maibu.exception.ServiceException; -import com.maibu.mapper.DeviceRunParamMapper; -import com.maibu.memory.DeviceSessionManager; -import com.maibu.memory.GlobalMemory; -import com.maibu.memory.SiteMemory; -import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.StringUtils; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; -import org.springframework.util.CollectionUtils; - import java.util.ArrayList; import java.util.Arrays; import java.util.List; @@ -28,6 +11,24 @@ import java.util.concurrent.TimeoutException; import java.util.function.Function; import java.util.stream.Collectors; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.util.CollectionUtils; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.maibu.constant.Constant; +import com.maibu.core.business.DeviceRunParam; +import com.maibu.core.business.device.NettyDevice; +import com.maibu.dto.BaseQueryDTO; +import com.maibu.exception.ServiceException; +import com.maibu.mapper.DeviceRunParamMapper; +import com.maibu.memory.DeviceSessionManager; +import com.maibu.memory.GlobalMemory; +import com.maibu.memory.SiteMemory; + +import lombok.extern.slf4j.Slf4j; + @Service @Slf4j public class DeviceRunParamService { @@ -38,7 +39,8 @@ public class DeviceRunParamService { @Autowired private DeviceSessionManager sessionManager; - public boolean save(DeviceRunParam deviceRunParam) throws ExecutionException, InterruptedException, TimeoutException { + public boolean save(DeviceRunParam deviceRunParam) + throws ExecutionException, InterruptedException, TimeoutException { NettyDevice nettyDevice = sessionManager.getDevice(deviceRunParam.getDeviceId()); if (nettyDevice == null || !nettyDevice.getChannel().isActive()) { @@ -93,30 +95,73 @@ public class DeviceRunParamService { return deviceRunParamMapper.selectList(queryWrapper); } - public DeviceRunParam selectByDeviceId(String deviceId) throws ExecutionException, InterruptedException, TimeoutException { - NettyDevice nettyDevice = sessionManager.getDevice(deviceId); - CompletableFuture future = new CompletableFuture<>(); - if (nettyDevice != null && nettyDevice.getChannel() != null && nettyDevice.getChannel().isActive()) { - nettyDevice.getChannel().attr(Constant.READ_CONFIG_KEY).set(future); - try { - nettyDevice.readConfigCommand(); - DeviceRunParam param = future.get(5, TimeUnit.SECONDS); + // public DeviceRunParam selectByDeviceId(String deviceId) + // throws ExecutionException, InterruptedException, TimeoutException { - LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); - if (!StringUtils.isEmpty(deviceId)) { - queryWrapper.eq(DeviceRunParam::getDeviceId, deviceId); + // NettyDevice nettyDevice = sessionManager.getDevice(deviceId); + // CompletableFuture future = new CompletableFuture<>(); + // if (nettyDevice != null && nettyDevice.getChannel() != null && + // nettyDevice.getChannel().isActive()) { + // nettyDevice.getChannel().attr(Constant.READ_CONFIG_KEY).set(future); + // try { + // nettyDevice.readConfigCommand(); + // DeviceRunParam param = future.get(5, TimeUnit.SECONDS); + + // LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + // if (!StringUtils.isEmpty(deviceId)) { + // queryWrapper.eq(DeviceRunParam::getDeviceId, deviceId); + // } + // DeviceRunParam result = deviceRunParamMapper.selectOne(queryWrapper); + // if (result != null) { + // param.setId(result.getId()); + // param.setDeviceId(result.getDeviceId()); + // param.setRunSpeed(result.getRunSpeed()); + // param.setOrgId(nettyDevice.getDevice().getOrgId()); + // param.setSiteId(nettyDevice.getDevice().getSiteId()); + // } + // return param; + // } finally { + // nettyDevice.getChannel().attr(Constant.READ_CONFIG_KEY).set(null); + // } + // } + // return null; + // } + + public DeviceRunParam selectByDeviceId(String deviceId) + throws ExecutionException, InterruptedException, TimeoutException { + + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + if (!StringUtils.isEmpty(deviceId)) { + queryWrapper.eq(DeviceRunParam::getDeviceId, deviceId); + } + DeviceRunParam result = deviceRunParamMapper.selectOne(queryWrapper); + if (result != null && result.getHasHost() != null && result.getHasHost() == 1) { + return result; + } else { + NettyDevice nettyDevice = sessionManager.getDevice(deviceId); + CompletableFuture future = new CompletableFuture<>(); + if (nettyDevice != null && nettyDevice.getChannel() != null && nettyDevice.getChannel().isActive()) { + nettyDevice.getChannel().attr(Constant.READ_CONFIG_KEY).set(future); + try { + nettyDevice.readConfigCommand(); + DeviceRunParam param = future.get(5, TimeUnit.SECONDS); + + // LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + // if (!StringUtils.isEmpty(deviceId)) { + // queryWrapper.eq(DeviceRunParam::getDeviceId, deviceId); + // } + // DeviceRunParam result = deviceRunParamMapper.selectOne(queryWrapper); + if (result != null) { + param.setId(result.getId()); + param.setDeviceId(result.getDeviceId()); + param.setRunSpeed(result.getRunSpeed()); + param.setOrgId(nettyDevice.getDevice().getOrgId()); + param.setSiteId(nettyDevice.getDevice().getSiteId()); + } + return param; + } finally { + nettyDevice.getChannel().attr(Constant.READ_CONFIG_KEY).set(null); } - DeviceRunParam result = deviceRunParamMapper.selectOne(queryWrapper); - if (result != null) { - param.setId(result.getId()); - param.setDeviceId(result.getDeviceId()); - param.setRunSpeed(result.getRunSpeed()); - param.setOrgId(nettyDevice.getDevice().getOrgId()); - param.setSiteId(nettyDevice.getDevice().getSiteId()); - } - return param; - } finally { - nettyDevice.getChannel().attr(Constant.READ_CONFIG_KEY).set(null); } } return null; @@ -149,10 +194,11 @@ public class DeviceRunParamService { Map map = oldList.stream() .collect(Collectors.toMap( DeviceRunParam::getDeviceId, - Function.identity() - )); + Function.identity())); List saveList = new ArrayList<>(); params.forEach(x -> { + if (StringUtils.isEmpty(x.getDeviceId())) + return; DeviceRunParam deviceRunParam = null; if (!CollectionUtils.isEmpty(map)) { deviceRunParam = map.get(x.getDeviceId()); @@ -188,4 +234,3 @@ public class DeviceRunParamService { } } - \ No newline at end of file diff --git a/maibu-service/maibu-iot-service/src/main/java/com/maibu/service/impl/DeviceServiceImpl.java b/maibu-service/maibu-iot-service/src/main/java/com/maibu/service/impl/DeviceServiceImpl.java index 734b3e7..7f256a4 100644 --- a/maibu-service/maibu-iot-service/src/main/java/com/maibu/service/impl/DeviceServiceImpl.java +++ b/maibu-service/maibu-iot-service/src/main/java/com/maibu/service/impl/DeviceServiceImpl.java @@ -8,12 +8,11 @@ import java.util.List; import java.util.Map; import java.util.Set; import java.util.concurrent.TimeUnit; +import java.util.function.Function; import java.util.stream.Collectors; import javax.annotation.Resource; -import com.maibu.constant.CacheConstants; -import com.maibu.dto.DeviceParamAuthDTO; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -22,8 +21,8 @@ import org.springframework.stereotype.Service; import org.springframework.util.CollectionUtils; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; -import com.influxdb.query.FluxRecord; -import com.influxdb.query.FluxTable; +import com.maibu.constant.CacheConstants; +import com.maibu.constant.NettyCacheKey; import com.maibu.core.business.Device; import com.maibu.core.business.DevicePlan; import com.maibu.core.business.DeviceRunningStatusHistory; @@ -34,13 +33,13 @@ import com.maibu.core.domain.entity.SysRole; import com.maibu.core.domain.entity.SysSite; import com.maibu.core.domain.model.LoginUser; import com.maibu.core.enums.DeviceTaskStaus; +import com.maibu.core.host.LocationMessage; import com.maibu.core.redis.RedisCache; -import com.maibu.influxdb.MowerRealTimeData; -import com.maibu.influxdb.util.InfluxSqlBuilder; -import com.maibu.influxdb.util.LambdaUtils; +import com.maibu.dto.DeviceParamAuthDTO; import com.maibu.mapper.DeviceMapper; import com.maibu.mapper.DevicePlanMapper; import com.maibu.mapper.DeviceStatusHistoryMapper; +import com.maibu.mapper.HostLocationMapper; import com.maibu.mapper.SysSiteMapper; import com.maibu.memory.GlobalMemory; import com.maibu.memory.SiteMemory; @@ -75,6 +74,9 @@ public class DeviceServiceImpl implements IDeviceService { @Autowired private SysSiteMapper sysSiteMapper; + @Autowired + private HostLocationMapper hostLocationMapper; + /** * 根据设备编号查询设备 * @@ -147,6 +149,13 @@ public class DeviceServiceImpl implements IDeviceService { Map> statusMap = allStatusList.stream() .collect(Collectors.groupingBy(DeviceRunningStatusHistory::getDeviceId)); + LambdaQueryWrapper query = new LambdaQueryWrapper<>(); + query.in(LocationMessage::getDeviceId, ids); + + List hostLocations = hostLocationMapper.selectList(query); + Map locationMap = hostLocations.stream() + .collect(Collectors.toMap(LocationMessage::getDeviceId, Function.identity())); + deviceList.forEach(x -> { Integer s = x.getOnlineStatus() == null ? 0 : x.getOnlineStatus(); if (0 == s) { @@ -183,6 +192,13 @@ public class DeviceServiceImpl implements IDeviceService { } } x.setLastRunningStatus(lastRunningStatus); + + String locationKey = NettyCacheKey.latestPositonKey + x.getDeviceName(); + LocationMessage locationMessage = redisCache.getCacheObject(locationKey); + if (locationMessage == null) { + locationMessage = locationMap.get(x.getDeviceName()); + } + x.setLocationMessage(locationMessage); }); deviceList.sort(Comparator.comparing(Device::getFeStatus)); } @@ -353,7 +369,9 @@ public class DeviceServiceImpl implements IDeviceService { }); } } - deviceList.sort(Comparator.comparing(Device::getFeStatus)); + if (!CollectionUtils.isEmpty(deviceList)) { + deviceList.sort(Comparator.comparing(Device::getFeStatus)); + } return deviceList; } diff --git a/maibu-service/maibu-iot-service/src/main/java/com/maibu/service/impl/WorkRecordService.java b/maibu-service/maibu-iot-service/src/main/java/com/maibu/service/impl/WorkRecordService.java index 6e8db3b..2293e73 100644 --- a/maibu-service/maibu-iot-service/src/main/java/com/maibu/service/impl/WorkRecordService.java +++ b/maibu-service/maibu-iot-service/src/main/java/com/maibu/service/impl/WorkRecordService.java @@ -10,6 +10,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.util.CollectionUtils; +import java.util.Comparator; import java.util.List; @Service @@ -64,6 +65,7 @@ public class WorkRecordService { list.forEach(workRecord -> { workRecord.setJsonData(null); }); + list.sort(Comparator.comparing(WorkRecord::getId).reversed()); } return list; } @@ -72,16 +74,13 @@ public class WorkRecordService { return workRecordMapper.selectById(id); } - public List selectByTaskId(Long taskId) { + public WorkRecord selectByTaskId(Long taskId) { DevicePlanTask devicePlanTask = devicePlanTaskMapper.selectById(taskId); // 先查询设备任务,确认任务存在 if (devicePlanTask == null) { return null; } Long routeId = devicePlanTask.getRouteId(); // 获取任务关联的路线ID WorkRecord workRecord = workRecordMapper.selectById(routeId); // 查询路线ID对应的工作记录 - if (workRecord != null && workRecord.getJsonData() != null) { - return workRecord.getJsonData().getPath(); // 返回路线数据 - } - return null; // 如果没有找到对应的工作记录或路线数据,返回 null + return workRecord; // 如果没有找到对应的工作记录或路线数据,返回 null } } diff --git a/maibu-service/maibu-iot-service/src/main/resources/mapper/iot/DeviceMapper.xml b/maibu-service/maibu-iot-service/src/main/resources/mapper/iot/DeviceMapper.xml index 103d9f0..39f4be9 100644 --- a/maibu-service/maibu-iot-service/src/main/resources/mapper/iot/DeviceMapper.xml +++ b/maibu-service/maibu-iot-service/src/main/resources/mapper/iot/DeviceMapper.xml @@ -39,10 +39,14 @@ + + select d.online_status, + d.has_host, + d.has_registered, d.device_alias, d.device_id, d.org_id, @@ -145,6 +149,8 @@ and d.active_time between #{params.beginActiveTime} and #{params.endActiveTime} and d.online_status = #{onlineStatus} + and d.has_host = #{hasHost} + and d.has_registered = #{hasRegistered} order by d.create_time desc @@ -302,6 +308,8 @@ online_status, org_id, site_id, + has_host, + has_registered, #{deviceName}, @@ -335,6 +343,8 @@ #{onlineStatus}, #{orgId}, #{siteId}, + #{hasHost}, + #{hasRegistered}, @@ -395,6 +405,8 @@ online_status = #{onlineStatus}, org_id = #{orgId}, site_id = #{siteId}, + has_host = #{hasHost}, + has_registered = #{hasRegistered}, where device_id = #{deviceId} diff --git a/maibu-service/maibu-system-service/src/main/java/com/maibu/service/impl/IotDeviceCommonService.java b/maibu-service/maibu-system-service/src/main/java/com/maibu/service/impl/IotDeviceCommonService.java index 5556526..ad07f9a 100644 --- a/maibu-service/maibu-system-service/src/main/java/com/maibu/service/impl/IotDeviceCommonService.java +++ b/maibu-service/maibu-system-service/src/main/java/com/maibu/service/impl/IotDeviceCommonService.java @@ -44,7 +44,6 @@ import java.util.concurrent.TimeUnit; @Service public class IotDeviceCommonService { - @Autowired private IotDeviceCommonMapper iotDeviceCommonMapper; @@ -92,16 +91,13 @@ public class IotDeviceCommonService { device.setDelFlag(false); device.setCreateTime(LocalDateTime.now()); - log.info("设备 {} 已加入未注册缓存", deviceDTO.getSn()); } - public List getUnRegisterDevices() { return new ArrayList<>(GlobalMemory.unRegisterCommonDeviceMap.values()); } - public Page selectDevicePage(Page page, IoTCommonDevice device) { LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); @@ -123,7 +119,6 @@ public class IotDeviceCommonService { return iotDeviceCommonMapper.selectPage(page, wrapper); } - public IoTCommonDevice getBySn(String sn) { LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); wrapper.eq(IoTCommonDevice::getDeviceId, sn) @@ -131,7 +126,6 @@ public class IotDeviceCommonService { return iotDeviceCommonMapper.selectOne(wrapper); } - public void registerDevice(IoTCommonDevice device) { device.setHasRegister(true); device.setUpdateTime(LocalDateTime.now()); @@ -144,7 +138,6 @@ public class IotDeviceCommonService { GlobalMemory.unRegisterCommonDeviceMap.remove(device.getSn()); } - @Transactional(rollbackFor = Exception.class) public boolean updateDevice(DeviceConfigDTO deviceDTO) { // 1. 查询设备是否存在 @@ -181,7 +174,6 @@ public class IotDeviceCommonService { return iotDeviceCommonMapper.saveOrUpdate(device); } - /** * 设备连接测试(根据协议类型) */ @@ -201,12 +193,10 @@ public class IotDeviceCommonService { } } - public IoTCommonDevice getFromUnRegisterCache(String sn) { return GlobalMemory.unRegisterCommonDeviceMap.get(sn); } - public void updateUnRegisterCache(IoTCommonDevice device) { if (device.getDeviceId() == null) { throw new RuntimeException("设备 ID (SN) 不能为空"); @@ -216,14 +206,14 @@ public class IotDeviceCommonService { log.info("未注册设备 {} 缓存配置已更新", device.getDeviceId()); } - /** * MQTT 连接测试 */ private boolean testMqttConnection(String ip, Integer port, String username, String password) { try { // TODO: 使用 MQTT 客户端测试连接 - // MqttClient client = new MqttClient("tcp://" + ip + ":" + port, "test-" + UUID.randomUUID()); + // MqttClient client = new MqttClient("tcp://" + ip + ":" + port, "test-" + + // UUID.randomUUID()); // ... return true; // 暂时返回 true,后续接入真实 MQTT 库 } catch (Exception e) { @@ -258,14 +248,13 @@ public class IotDeviceCommonService { } } - public void removeByIds(List ids) { - if (CollectionUtils.isEmpty(ids)) return; + if (CollectionUtils.isEmpty(ids)) + return; iotDeviceCommonMapper.deleteBatchIds(ids); } - // 3. 按 productId 分组,缓存映射配置避免重复查询 public static Map> mappingCache = new ConcurrentHashMap<>(); @@ -300,7 +289,8 @@ public class IotDeviceCommonService { // 注册到处理器,用 productId 区分不同产品的映射 String handlerType = "property-" + productId; - GenericPropertyMessageHandler handler = (GenericPropertyMessageHandler) monitor.getMessageHandler(handlerType); + GenericPropertyMessageHandler handler = (GenericPropertyMessageHandler) monitor + .getMessageHandler(handlerType); handler.registerMappingConfig(handlerType, mappingConfig); // 获取产品信息 @@ -334,11 +324,14 @@ public class IotDeviceCommonService { /** * 根据数据库映射列表构建 PropertyMappingConfig * - *

将 {@link DeviceModelPropertyMapping} 转换为 {@link PropertyMappingConfig.FieldMapping}:

+ *

+ * 将 {@link DeviceModelPropertyMapping} 转换为 + * {@link PropertyMappingConfig.FieldMapping}: + *

*
    - *
  • sourceKey → FieldMapping.source(外部 JSON 中的字段名)
  • - *
  • standardKey → FieldMapping.target(统一后的内部属性名)
  • - *
  • dataType → FieldMapping.valueType(自动类型转换)
  • + *
  • sourceKey → FieldMapping.source(外部 JSON 中的字段名)
  • + *
  • standardKey → FieldMapping.target(统一后的内部属性名)
  • + *
  • dataType → FieldMapping.valueType(自动类型转换)
  • *
*/ private PropertyMappingConfig buildMappingConfig(List mappings) {