Compare commits
4 Commits
dev_new_co
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| 33f8ce0b92 | |||
| 13acda2ddb | |||
| 3f156fe447 | |||
| 921a4b9c54 |
105
.idea/workspace.xml
generated
105
.idea/workspace.xml
generated
@@ -6,14 +6,21 @@
|
|||||||
<component name="ChangeListManager">
|
<component name="ChangeListManager">
|
||||||
<list default="true" id="84ac1b15-3cfa-4375-9957-45b7b581d04e" name="Changes" comment="# commit">
|
<list default="true" id="84ac1b15-3cfa-4375-9957-45b7b581d04e" name="Changes" comment="# commit">
|
||||||
<change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
|
<change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
|
||||||
<change beforePath="$PROJECT_DIR$/maibu-common/src/main/java/com/maibu/core/business/device/NettyDevice.java" beforeDir="false" afterPath="$PROJECT_DIR$/maibu-common/src/main/java/com/maibu/core/business/device/NettyDevice.java" afterDir="false" />
|
<change beforePath="$PROJECT_DIR$/maibu-admin/src/main/resources/application-dev.yml" beforeDir="false" afterPath="$PROJECT_DIR$/maibu-admin/src/main/resources/application-dev.yml" afterDir="false" />
|
||||||
<change beforePath="$PROJECT_DIR$/maibu-common/src/main/java/com/maibu/memory/DeviceSessionManager.java" beforeDir="false" afterPath="$PROJECT_DIR$/maibu-common/src/main/java/com/maibu/memory/DeviceSessionManager.java" afterDir="false" />
|
<change beforePath="$PROJECT_DIR$/maibu-common/src/main/java/com/maibu/core/business/Device.java" beforeDir="false" afterPath="$PROJECT_DIR$/maibu-common/src/main/java/com/maibu/core/business/Device.java" afterDir="false" />
|
||||||
<change beforePath="$PROJECT_DIR$/maibu-netty-server/src/main/java/com/maibu/dto/DeviceBindDTO.java" beforeDir="false" afterPath="$PROJECT_DIR$/maibu-netty-server/src/main/java/com/maibu/dto/DeviceBindDTO.java" afterDir="false" />
|
<change beforePath="$PROJECT_DIR$/maibu-external/src/main/java/com/maibu/uav/controller/UAVController.java" beforeDir="false" afterPath="$PROJECT_DIR$/maibu-external/src/main/java/com/maibu/uav/controller/UAVController.java" afterDir="false" />
|
||||||
<change beforePath="$PROJECT_DIR$/maibu-netty-server/src/main/java/com/maibu/netty/handler/CommandForwardHandler.java" beforeDir="false" afterPath="$PROJECT_DIR$/maibu-netty-server/src/main/java/com/maibu/netty/handler/CommandForwardHandler.java" afterDir="false" />
|
<change beforePath="$PROJECT_DIR$/maibu-external/src/main/java/com/maibu/uav/dto/UavDeviceStateResponseDetailDTO.java" beforeDir="false" afterPath="$PROJECT_DIR$/maibu-external/src/main/java/com/maibu/uav/dto/UavDeviceStateResponseDetailDTO.java" afterDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/maibu-external/src/main/java/com/maibu/uav/service/UAVService.java" beforeDir="false" afterPath="$PROJECT_DIR$/maibu-external/src/main/java/com/maibu/uav/service/UAVService.java" afterDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/maibu-framework/src/main/java/com/maibu/config/SecurityConfig.java" beforeDir="false" afterPath="$PROJECT_DIR$/maibu-framework/src/main/java/com/maibu/config/SecurityConfig.java" afterDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/maibu-netty-server/src/main/java/com/maibu/netty/NettyServer.java" beforeDir="false" afterPath="$PROJECT_DIR$/maibu-netty-server/src/main/java/com/maibu/netty/NettyServer.java" afterDir="false" />
|
||||||
<change beforePath="$PROJECT_DIR$/maibu-netty-server/src/main/java/com/maibu/netty/handler/DeviceConnectHandler.java" beforeDir="false" afterPath="$PROJECT_DIR$/maibu-netty-server/src/main/java/com/maibu/netty/handler/DeviceConnectHandler.java" afterDir="false" />
|
<change beforePath="$PROJECT_DIR$/maibu-netty-server/src/main/java/com/maibu/netty/handler/DeviceConnectHandler.java" beforeDir="false" afterPath="$PROJECT_DIR$/maibu-netty-server/src/main/java/com/maibu/netty/handler/DeviceConnectHandler.java" afterDir="false" />
|
||||||
<change beforePath="$PROJECT_DIR$/maibu-netty-server/src/main/java/com/maibu/service/TransferDeviceService.java" beforeDir="false" afterPath="$PROJECT_DIR$/maibu-netty-server/src/main/java/com/maibu/service/TransferDeviceService.java" afterDir="false" />
|
<change beforePath="$PROJECT_DIR$/maibu-netty-server/src/main/java/com/maibu/netty/handler/HeaderFooterDecoder.java" beforeDir="false" afterPath="$PROJECT_DIR$/maibu-netty-server/src/main/java/com/maibu/netty/handler/HeaderFooterDecoder.java" afterDir="false" />
|
||||||
<change beforePath="$PROJECT_DIR$/maibu-web-middleware/src/main/java/com/maibu/dto/NettySwitchDeviceDTO.java" beforeDir="false" afterPath="$PROJECT_DIR$/maibu-web-middleware/src/main/java/com/maibu/dto/NettySwitchDeviceDTO.java" afterDir="false" />
|
<change beforePath="$PROJECT_DIR$/maibu-netty-server/src/main/java/com/maibu/netty/handler/HexEncoder.java" beforeDir="false" afterPath="$PROJECT_DIR$/maibu-netty-server/src/main/java/com/maibu/netty/handler/HexEncoder.java" afterDir="false" />
|
||||||
<change beforePath="$PROJECT_DIR$/maibu-web-middleware/src/main/java/com/maibu/netty/handler/ClientHandler.java" beforeDir="false" afterPath="$PROJECT_DIR$/maibu-web-middleware/src/main/java/com/maibu/netty/handler/ClientHandler.java" afterDir="false" />
|
<change beforePath="$PROJECT_DIR$/maibu-service/maibu-iot-service/src/main/java/com/maibu/controller/DeviceController.java" beforeDir="false" afterPath="$PROJECT_DIR$/maibu-service/maibu-iot-service/src/main/java/com/maibu/controller/DeviceController.java" afterDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/maibu-service/maibu-iot-service/src/main/java/com/maibu/service/IDeviceService.java" beforeDir="false" afterPath="$PROJECT_DIR$/maibu-service/maibu-iot-service/src/main/java/com/maibu/service/IDeviceService.java" afterDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/maibu-service/maibu-iot-service/src/main/java/com/maibu/service/impl/DeviceServiceImpl.java" beforeDir="false" afterPath="$PROJECT_DIR$/maibu-service/maibu-iot-service/src/main/java/com/maibu/service/impl/DeviceServiceImpl.java" afterDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/maibu-service/maibu-iot-service/src/main/resources/mapper/iot/DeviceMapper.xml" beforeDir="false" afterPath="$PROJECT_DIR$/maibu-service/maibu-iot-service/src/main/resources/mapper/iot/DeviceMapper.xml" afterDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/maibu-web-middleware/src/main/java/com/maibu/common/MiddleConstant.java" beforeDir="false" afterPath="$PROJECT_DIR$/maibu-web-middleware/src/main/java/com/maibu/common/MiddleConstant.java" afterDir="false" />
|
||||||
</list>
|
</list>
|
||||||
<option name="SHOW_DIALOG" value="false" />
|
<option name="SHOW_DIALOG" value="false" />
|
||||||
<option name="HIGHLIGHT_CONFLICTS" value="true" />
|
<option name="HIGHLIGHT_CONFLICTS" value="true" />
|
||||||
@@ -33,11 +40,6 @@
|
|||||||
</option>
|
</option>
|
||||||
</component>
|
</component>
|
||||||
<component name="Git.Settings">
|
<component name="Git.Settings">
|
||||||
<option name="RECENT_BRANCH_BY_REPOSITORY">
|
|
||||||
<map>
|
|
||||||
<entry key="$PROJECT_DIR$" value="main" />
|
|
||||||
</map>
|
|
||||||
</option>
|
|
||||||
<option name="RECENT_GIT_ROOT_PATH" value="$PROJECT_DIR$" />
|
<option name="RECENT_GIT_ROOT_PATH" value="$PROJECT_DIR$" />
|
||||||
</component>
|
</component>
|
||||||
<component name="HttpClientEndpointsTabState">
|
<component name="HttpClientEndpointsTabState">
|
||||||
@@ -77,40 +79,40 @@
|
|||||||
<option name="hideEmptyMiddlePackages" value="true" />
|
<option name="hideEmptyMiddlePackages" value="true" />
|
||||||
<option name="showLibraryContents" value="true" />
|
<option name="showLibraryContents" value="true" />
|
||||||
</component>
|
</component>
|
||||||
<component name="PropertiesComponent"><![CDATA[{
|
<component name="PropertiesComponent">{
|
||||||
"keyToString": {
|
"keyToString": {
|
||||||
"ASKED_SHARE_PROJECT_CONFIGURATION_FILES": "true",
|
"ASKED_SHARE_PROJECT_CONFIGURATION_FILES": "true",
|
||||||
"Application.test.executor": "Debug",
|
"Application.test.executor": "Debug",
|
||||||
"HTTP Request.MiddlePlatformApplication | #1.executor": "Run",
|
"HTTP Request.MiddlePlatformApplication | #1.executor": "Run",
|
||||||
"HTTP Request.MiddlePlatformApplication | #2.executor": "Run",
|
"HTTP Request.MiddlePlatformApplication | #2.executor": "Run",
|
||||||
"HTTP Request.MiddlePlatformApplication | #3.executor": "Run",
|
"HTTP Request.MiddlePlatformApplication | #3.executor": "Run",
|
||||||
"Maven.MiddlePlatform [clean].executor": "Run",
|
"Maven.MiddlePlatform [clean].executor": "Run",
|
||||||
"Maven.MiddlePlatform [install].executor": "Run",
|
"Maven.MiddlePlatform [install].executor": "Run",
|
||||||
"Maven.maibu-netty-server [clean].executor": "Run",
|
"Maven.maibu-netty-server [clean].executor": "Run",
|
||||||
"ModuleVcsDetector.initialDetectionPerformed": "true",
|
"ModuleVcsDetector.initialDetectionPerformed": "true",
|
||||||
"RequestMappingsPanelOrder0": "0",
|
"RequestMappingsPanelOrder0": "0",
|
||||||
"RequestMappingsPanelOrder1": "1",
|
"RequestMappingsPanelOrder1": "1",
|
||||||
"RequestMappingsPanelWidth0": "75",
|
"RequestMappingsPanelWidth0": "75",
|
||||||
"RequestMappingsPanelWidth1": "75",
|
"RequestMappingsPanelWidth1": "75",
|
||||||
"RunOnceActivity.MCP Project settings loaded": "true",
|
"RunOnceActivity.MCP Project settings loaded": "true",
|
||||||
"RunOnceActivity.ShowReadmeOnStart": "true",
|
"RunOnceActivity.ShowReadmeOnStart": "true",
|
||||||
"RunOnceActivity.TerminalTabsStorage.copyFrom.TerminalArrangementManager.252": "true",
|
"RunOnceActivity.TerminalTabsStorage.copyFrom.TerminalArrangementManager.252": "true",
|
||||||
"RunOnceActivity.git.unshallow": "true",
|
"RunOnceActivity.git.unshallow": "true",
|
||||||
"RunOnceActivity.typescript.service.memoryLimit.init": "true",
|
"RunOnceActivity.typescript.service.memoryLimit.init": "true",
|
||||||
"Spring Boot.MiddlePlatformApplication.executor": "Debug",
|
"Spring Boot.MiddlePlatformApplication.executor": "Debug",
|
||||||
"git-widget-placeholder": "dev__control",
|
"git-widget-placeholder": "main",
|
||||||
"kotlin-language-version-configured": "true",
|
"kotlin-language-version-configured": "true",
|
||||||
"last_opened_file_path": "/home/maibu/Test/MiddlePlatform/maibu-external/src/main/java/com/maibu/uav",
|
"last_opened_file_path": "/home/maibu/Test/MiddlePlatform/maibu-external/src/main/java/com/maibu/uav",
|
||||||
"node.js.detected.package.eslint": "true",
|
"node.js.detected.package.eslint": "true",
|
||||||
"node.js.detected.package.tslint": "true",
|
"node.js.detected.package.tslint": "true",
|
||||||
"node.js.selected.package.eslint": "(autodetect)",
|
"node.js.selected.package.eslint": "(autodetect)",
|
||||||
"node.js.selected.package.tslint": "(autodetect)",
|
"node.js.selected.package.tslint": "(autodetect)",
|
||||||
"nodejs_package_manager_path": "npm",
|
"nodejs_package_manager_path": "npm",
|
||||||
"onboarding.tips.debug.path": "D:/code/MiddlePlatform/maibu-service/maibu-system-service/src/main/java/com/maibu/Main.java",
|
"onboarding.tips.debug.path": "D:/code/MiddlePlatform/maibu-service/maibu-system-service/src/main/java/com/maibu/Main.java",
|
||||||
"settings.editor.selected.configurable": "project.propVCSSupport.CommitDialog",
|
"settings.editor.selected.configurable": "project.propVCSSupport.CommitDialog",
|
||||||
"vue.rearranger.settings.migration": "true"
|
"vue.rearranger.settings.migration": "true"
|
||||||
}
|
}
|
||||||
}]]></component>
|
}</component>
|
||||||
<component name="RdControllerToolWindowsLayoutState" isNewUi="true">
|
<component name="RdControllerToolWindowsLayoutState" isNewUi="true">
|
||||||
<layout>
|
<layout>
|
||||||
<window_info id="Bookmarks" side_tool="true" />
|
<window_info id="Bookmarks" side_tool="true" />
|
||||||
@@ -188,6 +190,17 @@
|
|||||||
<configuration name="MiddlePlatformApplication | #3" type="HttpClient.HttpRequestRunConfigurationType" factoryName="HTTP Request" temporary="true" nameIsGenerated="true" path="$APPLICATION_CONFIG_DIR$/scratches/MiddlePlatformApplication.http" executionIdentifier="#3" index="3" runType="Run single request">
|
<configuration name="MiddlePlatformApplication | #3" type="HttpClient.HttpRequestRunConfigurationType" factoryName="HTTP Request" temporary="true" nameIsGenerated="true" path="$APPLICATION_CONFIG_DIR$/scratches/MiddlePlatformApplication.http" executionIdentifier="#3" index="3" runType="Run single request">
|
||||||
<method v="2" />
|
<method v="2" />
|
||||||
</configuration>
|
</configuration>
|
||||||
|
<configuration default="true" type="JetRunConfigurationType">
|
||||||
|
<module name="maibu-iot-service" />
|
||||||
|
<method v="2">
|
||||||
|
<option name="Make" enabled="true" />
|
||||||
|
</method>
|
||||||
|
</configuration>
|
||||||
|
<configuration default="true" type="KotlinStandaloneScriptRunConfigurationType">
|
||||||
|
<module name="maibu-iot-service" />
|
||||||
|
<option name="filePath" />
|
||||||
|
<method v="2" />
|
||||||
|
</configuration>
|
||||||
<configuration name="MiddlePlatformApplication" type="SpringBootApplicationConfigurationType" factoryName="Spring Boot" temporary="true" nameIsGenerated="true">
|
<configuration name="MiddlePlatformApplication" type="SpringBootApplicationConfigurationType" factoryName="Spring Boot" temporary="true" nameIsGenerated="true">
|
||||||
<option name="FRAME_DEACTIVATION_UPDATE_POLICY" value="UpdateClassesAndResources" />
|
<option name="FRAME_DEACTIVATION_UPDATE_POLICY" value="UpdateClassesAndResources" />
|
||||||
<module name="maibu-admin" />
|
<module name="maibu-admin" />
|
||||||
@@ -712,7 +725,7 @@
|
|||||||
<line-breakpoint enabled="true" type="java-method">
|
<line-breakpoint enabled="true" type="java-method">
|
||||||
<url>file://$PROJECT_DIR$/maibu-service/maibu-iot-service/src/main/java/com/maibu/controller/IOTWorkOrderController.java</url>
|
<url>file://$PROJECT_DIR$/maibu-service/maibu-iot-service/src/main/java/com/maibu/controller/IOTWorkOrderController.java</url>
|
||||||
<line>58</line>
|
<line>58</line>
|
||||||
<properties class="com.maibu.controller.IOTWorkOrderController" method="list">
|
<properties class="com.maibu.controller.IOTWorkOrderController" method="edit">
|
||||||
<option name="EMULATED" value="true" />
|
<option name="EMULATED" value="true" />
|
||||||
<option name="WATCH_EXIT" value="false" />
|
<option name="WATCH_EXIT" value="false" />
|
||||||
</properties>
|
</properties>
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ spring:
|
|||||||
datasource:
|
datasource:
|
||||||
type: com.alibaba.druid.pool.DruidDataSource
|
type: com.alibaba.druid.pool.DruidDataSource
|
||||||
driver-class-name: com.mysql.cj.jdbc.Driver
|
driver-class-name: com.mysql.cj.jdbc.Driver
|
||||||
url: jdbc:mysql://1.95.137.212:3306/maibu?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
|
url: jdbc:mysql://localhost:3306/maibu?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
|
||||||
username: satabot
|
username: satabot
|
||||||
password: satabot
|
password: satabot
|
||||||
|
|
||||||
@@ -31,7 +31,7 @@ spring:
|
|||||||
mqtt:
|
mqtt:
|
||||||
username: maibu # 账号
|
username: maibu # 账号
|
||||||
password: jsmbzn520 # 密码
|
password: jsmbzn520 # 密码
|
||||||
host-url: tcp://1.95.137.212:1883 # mqtt连接tcp地址
|
host-url: tcp://localhost:1883 # mqtt连接tcp地址
|
||||||
client-id: maibu-mqtt-client # 客户端Id,不能相同,采用随机数 ${random.value}
|
client-id: maibu-mqtt-client # 客户端Id,不能相同,采用随机数 ${random.value}
|
||||||
default-topic: test # 默认主题
|
default-topic: test # 默认主题
|
||||||
timeout: 30 # 超时时间
|
timeout: 30 # 超时时间
|
||||||
|
|||||||
@@ -97,16 +97,6 @@ public class DeviceTask {
|
|||||||
return builder(FastBeeConstant.TASK.DEVICE_ERROR_MONITOR);
|
return builder(FastBeeConstant.TASK.DEVICE_ERROR_MONITOR);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Bean(FastBeeConstant.TASK.DEVICE_HEARTBEAT_MONITOR)
|
|
||||||
public Executor deviceHeartBeatMonitor() {
|
|
||||||
return builder(FastBeeConstant.TASK.DEVICE_HEARTBEAT_MONITOR);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Bean(FastBeeConstant.TASK.MAP_MESSAGE_PUSH)
|
|
||||||
public Executor mapMessagePush() {
|
|
||||||
return builder(FastBeeConstant.TASK.MAP_MESSAGE_PUSH);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Bean(FastBeeConstant.TASK.DEVICE_TASK_HANDLER)
|
@Bean(FastBeeConstant.TASK.DEVICE_TASK_HANDLER)
|
||||||
public Executor deviceTaskHandler() {
|
public Executor deviceTaskHandler() {
|
||||||
return builder(FastBeeConstant.TASK.DEVICE_TASK_HANDLER);
|
return builder(FastBeeConstant.TASK.DEVICE_TASK_HANDLER);
|
||||||
|
|||||||
@@ -21,11 +21,7 @@ public class Constant {
|
|||||||
|
|
||||||
public static final AttributeKey<String> ATT_SITE_ID = AttributeKey.valueOf("siteId");
|
public static final AttributeKey<String> ATT_SITE_ID = AttributeKey.valueOf("siteId");
|
||||||
|
|
||||||
public static final String WheelGainCoefficients = "WheelGainCoefficients";
|
public static final String WheelGainCoefficients = "WheelGainCoefficients";
|
||||||
|
|
||||||
public static final String mqttClientPrefix = "common-device-client-";
|
public static final String mqttClientPrefix = "common-device-client-";
|
||||||
|
|
||||||
public static final String mqttHandleKey = "hostHandle";
|
|
||||||
|
|
||||||
public static final Long hostOfflineInterval = 10000L; //单位毫秒
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -100,18 +100,6 @@ public interface FastBeeConstant {
|
|||||||
* 设备错误
|
* 设备错误
|
||||||
*/
|
*/
|
||||||
String DEVICE_ERROR_MONITOR = "deviceErrorMonitor";
|
String DEVICE_ERROR_MONITOR = "deviceErrorMonitor";
|
||||||
|
|
||||||
/**
|
|
||||||
* 设备错误
|
|
||||||
*/
|
|
||||||
String DEVICE_HEARTBEAT_MONITOR = "deviceHeartBeatMonitor";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 设备错误
|
|
||||||
*/
|
|
||||||
String MAP_MESSAGE_PUSH = "mapMessagePush";
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 设备任务处理线程
|
* 设备任务处理线程
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -13,8 +13,6 @@ import com.fasterxml.jackson.annotation.JsonFormat;
|
|||||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||||
import com.maibu.annotation.Excel;
|
import com.maibu.annotation.Excel;
|
||||||
import com.maibu.core.domain.BaseDO;
|
import com.maibu.core.domain.BaseDO;
|
||||||
import com.maibu.core.host.LocationMessage;
|
|
||||||
import com.maibu.core.host.VehicleMessage;
|
|
||||||
import com.maibu.influxdb.MowerRealTimeData;
|
import com.maibu.influxdb.MowerRealTimeData;
|
||||||
|
|
||||||
import io.swagger.annotations.ApiModel;
|
import io.swagger.annotations.ApiModel;
|
||||||
@@ -74,6 +72,7 @@ public class Device extends BaseDO {
|
|||||||
@Excel(name = "产品名称")
|
@Excel(name = "产品名称")
|
||||||
private String productName;
|
private String productName;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 租户名称
|
* 租户名称
|
||||||
*/
|
*/
|
||||||
@@ -86,7 +85,8 @@ public class Device extends BaseDO {
|
|||||||
*/
|
*/
|
||||||
@ApiModelProperty("固件版本")
|
@ApiModelProperty("固件版本")
|
||||||
@Excel(name = "固件版本")
|
@Excel(name = "固件版本")
|
||||||
private String firmwareVersion;
|
private BigDecimal firmwareVersion;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* WIFI固件版本
|
* WIFI固件版本
|
||||||
@@ -95,6 +95,7 @@ public class Device extends BaseDO {
|
|||||||
@Excel(name = "HTTP推送固件版本")
|
@Excel(name = "HTTP推送固件版本")
|
||||||
private BigDecimal wirelessVersion;
|
private BigDecimal wirelessVersion;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 设备状态(1-未激活,2-禁用,3-在线,4-离线)
|
* 设备状态(1-未激活,2-禁用,3-在线,4-离线)
|
||||||
*/
|
*/
|
||||||
@@ -105,12 +106,12 @@ public class Device extends BaseDO {
|
|||||||
/**
|
/**
|
||||||
* 设备在线状态(1-在线,2-离线)
|
* 设备在线状态(1-在线,2-离线)
|
||||||
*/
|
*/
|
||||||
@ApiModelProperty("设备状态(1-在线,0-离线)")
|
@ApiModelProperty("设备状态(1-在线,2-离线)")
|
||||||
@Excel(name = "设备在线状态")
|
@Excel(name = "设备在线状态")
|
||||||
private Integer onlineStatus;
|
private Integer onlineStatus;
|
||||||
|
|
||||||
@TableField(exist = false)
|
@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])
|
* wifi信号强度(信号极好4格[-55— 0],信号好3格[-70— -55],信号一般2格[-85— -70],信号差1格[-100— -85])
|
||||||
@@ -193,6 +194,7 @@ public class Device extends BaseDO {
|
|||||||
@ApiModelProperty("设备摘要")
|
@ApiModelProperty("设备摘要")
|
||||||
private String summary;
|
private String summary;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 是否是模拟设备
|
* 是否是模拟设备
|
||||||
*/
|
*/
|
||||||
@@ -204,12 +206,12 @@ public class Device extends BaseDO {
|
|||||||
@ApiModelProperty("子设备地址")
|
@ApiModelProperty("子设备地址")
|
||||||
private Integer slaveId;
|
private Integer slaveId;
|
||||||
|
|
||||||
|
|
||||||
@TableField(updateStrategy = FieldStrategy.IGNORED)
|
@TableField(updateStrategy = FieldStrategy.IGNORED)
|
||||||
private Long siteId;
|
private Long siteId;
|
||||||
|
|
||||||
@TableField(updateStrategy = FieldStrategy.IGNORED)
|
@TableField(updateStrategy = FieldStrategy.IGNORED)
|
||||||
private Long orgId;
|
private Long orgId;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 租户ID
|
* 租户ID
|
||||||
*/
|
*/
|
||||||
@@ -218,6 +220,7 @@ public class Device extends BaseDO {
|
|||||||
@TableField(updateStrategy = FieldStrategy.IGNORED)
|
@TableField(updateStrategy = FieldStrategy.IGNORED)
|
||||||
private Long tenantId;
|
private Long tenantId;
|
||||||
|
|
||||||
|
|
||||||
@TableField(exist = false)
|
@TableField(exist = false)
|
||||||
private DeviceRunningStatusHistory lastRunningStatus;
|
private DeviceRunningStatusHistory lastRunningStatus;
|
||||||
|
|
||||||
@@ -225,19 +228,12 @@ public class Device extends BaseDO {
|
|||||||
private MowerRealTimeData lastMowerRealTimeData;
|
private MowerRealTimeData lastMowerRealTimeData;
|
||||||
|
|
||||||
@TableField(exist = false)
|
@TableField(exist = false)
|
||||||
private Map<Integer, Integer> statusStatistics;
|
private Map<Integer,Integer> statusStatistics;
|
||||||
|
|
||||||
@TableField(exist = false)
|
@TableField(exist = false)
|
||||||
private DeviceRunParam runParam;
|
private DeviceRunParam runParam;
|
||||||
|
|
||||||
private Boolean hasRegistered;
|
|
||||||
|
|
||||||
private Boolean hasHost;
|
private boolean hasRegistered = false;
|
||||||
|
|
||||||
@TableField(exist = false)
|
|
||||||
private LocationMessage locationMessage;
|
|
||||||
|
|
||||||
@TableField(exist = false)
|
|
||||||
private VehicleMessage vehicleMessage;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,14 +1,18 @@
|
|||||||
package com.maibu.core.business;
|
package com.maibu.core.business;
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.annotation.IdType;
|
import com.baomidou.mybatisplus.annotation.IdType;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableField;
|
||||||
import com.baomidou.mybatisplus.annotation.TableId;
|
import com.baomidou.mybatisplus.annotation.TableId;
|
||||||
import com.baomidou.mybatisplus.annotation.TableName;
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||||
import com.maibu.core.domain.BaseDO;
|
import com.maibu.core.domain.BaseDO;
|
||||||
|
import com.maibu.core.enums.ConnectType;
|
||||||
|
import io.swagger.annotations.ApiModel;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.EqualsAndHashCode;
|
import lombok.EqualsAndHashCode;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
|
||||||
@EqualsAndHashCode(callSuper = true)
|
@EqualsAndHashCode(callSuper = true)
|
||||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||||
|
|||||||
@@ -1,17 +1,17 @@
|
|||||||
package com.maibu.core.business;
|
package com.maibu.core.business;
|
||||||
|
|
||||||
import java.time.LocalDateTime;
|
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.annotation.IdType;
|
import com.baomidou.mybatisplus.annotation.IdType;
|
||||||
import com.baomidou.mybatisplus.annotation.TableField;
|
import com.baomidou.mybatisplus.annotation.TableField;
|
||||||
import com.baomidou.mybatisplus.annotation.TableId;
|
import com.baomidou.mybatisplus.annotation.TableId;
|
||||||
import com.baomidou.mybatisplus.annotation.TableName;
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
|
import com.maibu.core.domain.BaseDO;
|
||||||
import com.maibu.core.domain.OrgBaseDO;
|
import com.maibu.core.domain.OrgBaseDO;
|
||||||
import com.maibu.core.enums.DeviceTaskStaus;
|
import com.maibu.core.enums.DeviceTaskStaus;
|
||||||
|
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.EqualsAndHashCode;
|
import lombok.EqualsAndHashCode;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
|
||||||
@EqualsAndHashCode(callSuper = true)
|
@EqualsAndHashCode(callSuper = true)
|
||||||
@Data
|
@Data
|
||||||
@TableName("iot_device_task")
|
@TableName("iot_device_task")
|
||||||
@@ -39,7 +39,4 @@ public class DevicePlanTask extends OrgBaseDO {
|
|||||||
|
|
||||||
private LocalDateTime canExecuteTime; // 这个时间之前都不能执行
|
private LocalDateTime canExecuteTime; // 这个时间之前都不能执行
|
||||||
|
|
||||||
@TableField(exist = false)
|
|
||||||
private volatile boolean taskAccepted = false; //任务被上位机接收
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,8 +4,6 @@ import com.baomidou.mybatisplus.annotation.IdType;
|
|||||||
import com.baomidou.mybatisplus.annotation.TableField;
|
import com.baomidou.mybatisplus.annotation.TableField;
|
||||||
import com.baomidou.mybatisplus.annotation.TableId;
|
import com.baomidou.mybatisplus.annotation.TableId;
|
||||||
import com.baomidou.mybatisplus.annotation.TableName;
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler;
|
|
||||||
import com.maibu.annotation.Excel;
|
|
||||||
import com.maibu.constant.CommandConstant;
|
import com.maibu.constant.CommandConstant;
|
||||||
import com.maibu.core.domain.BaseDO;
|
import com.maibu.core.domain.BaseDO;
|
||||||
|
|
||||||
@@ -15,7 +13,6 @@ import lombok.EqualsAndHashCode;
|
|||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
import java.nio.ByteOrder;
|
import java.nio.ByteOrder;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
@EqualsAndHashCode(callSuper = true)
|
@EqualsAndHashCode(callSuper = true)
|
||||||
@Data
|
@Data
|
||||||
@@ -25,7 +22,7 @@ public class DeviceRunParam extends BaseDO {
|
|||||||
@TableId(type = IdType.AUTO)
|
@TableId(type = IdType.AUTO)
|
||||||
private Long id;
|
private Long id;
|
||||||
|
|
||||||
// private String deviceId;
|
private String deviceId;
|
||||||
|
|
||||||
private Long siteId;
|
private Long siteId;
|
||||||
|
|
||||||
@@ -33,40 +30,6 @@ public class DeviceRunParam extends BaseDO {
|
|||||||
|
|
||||||
private Integer runSpeed; //不下发到设备自己用
|
private Integer runSpeed; //不下发到设备自己用
|
||||||
|
|
||||||
@Excel(name = "设备序列号", cellType = Excel.ColumnType.STRING, prompt = "设备序列号")
|
|
||||||
private String deviceId;//设备序列号
|
|
||||||
|
|
||||||
@Excel(name = "产品型号", cellType = Excel.ColumnType.STRING, prompt = "产品型号")
|
|
||||||
private String productModel;//产品型号
|
|
||||||
|
|
||||||
@Excel(name = "设备类型", cellType = Excel.ColumnType.STRING, prompt = "设备类型")
|
|
||||||
private String deviceType;//设备类型:mower-割草机器人
|
|
||||||
|
|
||||||
@Excel(name = "RTK模式", cellType = Excel.ColumnType.STRING, prompt = "RTK模式")
|
|
||||||
private String rtkMode;//RTK模式:network-4G网络差分
|
|
||||||
|
|
||||||
@Excel(name = "摄像头数量", cellType = Excel.ColumnType.STRING, prompt = "摄像头数量")
|
|
||||||
private Integer cameraNum;//摄像头数量
|
|
||||||
|
|
||||||
@Excel(name = "动力类型", cellType = Excel.ColumnType.STRING, prompt = "动力类型")
|
|
||||||
private String powerType;//动力类型:hybrid-混动
|
|
||||||
|
|
||||||
@Excel(name = "车轮类型", cellType = Excel.ColumnType.STRING, prompt = "车轮类型")
|
|
||||||
private String wheelType;//车轮类型:track-履带式
|
|
||||||
|
|
||||||
@Excel(name = "发动机类型", cellType = Excel.ColumnType.STRING, prompt = "发动机类型")
|
|
||||||
private String engineType;//发动机类型:honda-本田发动机
|
|
||||||
|
|
||||||
@Excel(name = "是否搭载上位机",cellType = Excel.ColumnType.NUMERIC)
|
|
||||||
private Integer hasHost = 1;//是否搭载上位机
|
|
||||||
|
|
||||||
@Excel(name = "设备能力列表")
|
|
||||||
@TableField(exist = false)
|
|
||||||
private String capabilities;
|
|
||||||
|
|
||||||
@TableField(typeHandler = JacksonTypeHandler.class)
|
|
||||||
private List<String> capabilityList;//设备能力列表:heartbeat-上报心跳/location-上报位置/vehicle_status-上报整机状态/task_control-任务控制/single_point-单点作业/coverage-全覆盖割草作业/path_upload-作业路径上传
|
|
||||||
|
|
||||||
|
|
||||||
@TableField(exist = false)
|
@TableField(exist = false)
|
||||||
public byte header1;
|
public byte header1;
|
||||||
@@ -154,6 +117,112 @@ public class DeviceRunParam extends BaseDO {
|
|||||||
return buffer.array();
|
return buffer.array();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// public static byte[] toWriteBytes(DeviceRunParam p) {
|
||||||
|
//
|
||||||
|
// ByteBuffer buffer = ByteBuffer.allocate(178);
|
||||||
|
// buffer.order(ByteOrder.LITTLE_ENDIAN);
|
||||||
|
//
|
||||||
|
// // 包头
|
||||||
|
// buffer.put((byte) 0xAB);
|
||||||
|
// buffer.put((byte) 0xAA);
|
||||||
|
//
|
||||||
|
// // 指令
|
||||||
|
// buffer.put(CommandConstant.writeConfig);
|
||||||
|
//
|
||||||
|
// // UID固化标志
|
||||||
|
// buffer.put(p.getChipUidSign());
|
||||||
|
//
|
||||||
|
// // UID
|
||||||
|
// putFixedString(buffer, p.getChipUid(), 45);
|
||||||
|
//
|
||||||
|
// // Byte68
|
||||||
|
// byte remote = 0;
|
||||||
|
// remote |= (p.getKnifeMotorMode() & 0x03);
|
||||||
|
// remote |= (p.getWalkMotorMode() & 0x03) << 2;
|
||||||
|
// remote |= (p.getLeftMotorReverse() & 0x01) << 4;
|
||||||
|
// remote |= (p.getRightMotorReverse() & 0x01) << 5;
|
||||||
|
// remote |= (p.getSwapChannel() & 0x01) << 6;
|
||||||
|
// remote |= (p.getUse4G() & 0x01) << 7;
|
||||||
|
// buffer.put(remote);
|
||||||
|
//
|
||||||
|
// // 69~72
|
||||||
|
// buffer.putShort((short) p.getForwardSpeedLimit());
|
||||||
|
// buffer.putShort((short) p.getTurnSpeedLimit());
|
||||||
|
//
|
||||||
|
// //73
|
||||||
|
// byte b73 = 0;
|
||||||
|
// b73 |= (p.getKnifePolarity() & 1);
|
||||||
|
// b73 |= (p.getFanPolarity() & 1) << 1;
|
||||||
|
// b73 |= (p.getThrottlePolarity() & 1) << 2;
|
||||||
|
// b73 |= (p.getLiftProtectTime() & 0x0F) << 3;
|
||||||
|
// b73 |= (p.getDualRtk() & 1) << 7;
|
||||||
|
// buffer.put(b73);
|
||||||
|
//
|
||||||
|
// //74
|
||||||
|
// byte b74 = 0;
|
||||||
|
// b74 |= (p.getKnifeChannel() & 0x0F);
|
||||||
|
// b74 |= (p.getFanChannel() & 0x0F) << 4;
|
||||||
|
// buffer.put(b74);
|
||||||
|
//
|
||||||
|
// //75
|
||||||
|
// byte b75 = 0;
|
||||||
|
// b75 |= (p.getThrottleChannel() & 0x0F);
|
||||||
|
// b75 |= (p.getRemoteType() & 0x07) << 4;
|
||||||
|
// if (p.isRelayBoard()) {
|
||||||
|
// b75 |= 1 << 7;
|
||||||
|
// }
|
||||||
|
// buffer.put(b75);
|
||||||
|
//
|
||||||
|
// //76
|
||||||
|
// byte b76 = 0;
|
||||||
|
// b76 |= (p.getLiftChannel() & 0x0F);
|
||||||
|
// b76 |= (p.getChassisChannel() & 0x0F) << 4;
|
||||||
|
// buffer.put(b76);
|
||||||
|
//
|
||||||
|
// //77
|
||||||
|
// byte b77 = 0;
|
||||||
|
// b77 |= (p.getArmChannel() & 0x0F);
|
||||||
|
// b77 |= (p.getFuelPumpChannel() & 0x0F) << 4;
|
||||||
|
// buffer.put(b77);
|
||||||
|
//
|
||||||
|
// //wifi
|
||||||
|
// putFixedString(buffer, p.getWifiName(), 20);
|
||||||
|
// putFixedString(buffer, p.getWifiPassword(), 20);
|
||||||
|
//
|
||||||
|
// //118
|
||||||
|
// byte b118 = 0;
|
||||||
|
// b118 |= (p.getBatteryType() & 0x03);
|
||||||
|
// b118 |= (p.getDriveType() & 0x03) << 2;
|
||||||
|
// buffer.put(b118);
|
||||||
|
//
|
||||||
|
// //119~158 float
|
||||||
|
// buffer.putFloat(p.getGearRatio());
|
||||||
|
// buffer.putFloat(p.getRobotLength());
|
||||||
|
// buffer.putFloat(p.getRobotWidth());
|
||||||
|
// buffer.putFloat(p.getRobotHeight());
|
||||||
|
// buffer.putFloat(p.getKnifeWidth());
|
||||||
|
// buffer.putFloat(p.getTyreSize());
|
||||||
|
// buffer.putFloat(p.getLeftForwardGain());
|
||||||
|
// buffer.putFloat(p.getLeftBackwardGain());
|
||||||
|
// buffer.putFloat(p.getRightForwardGain());
|
||||||
|
// buffer.putFloat(p.getRightBackwardGain());
|
||||||
|
//
|
||||||
|
// //159~173
|
||||||
|
// putFixedString(buffer, p.getFirmwareVersion(), 15);
|
||||||
|
//
|
||||||
|
// //CRC
|
||||||
|
//
|
||||||
|
// / / byte[] bytes = buffer.array();
|
||||||
|
// / / int crc = CRC16Util.crc16(bytes, 0, 174);
|
||||||
|
// buffer.putShort((short) 0);
|
||||||
|
//
|
||||||
|
// //Tail
|
||||||
|
// buffer.put((byte) 0xAA);
|
||||||
|
// buffer.put((byte) 0xAB);
|
||||||
|
//
|
||||||
|
// return buffer.array();
|
||||||
|
// }
|
||||||
|
|
||||||
public byte[] toWriteBytes() {
|
public byte[] toWriteBytes() {
|
||||||
// 如果没有原始数据,使用静态方法重新构建
|
// 如果没有原始数据,使用静态方法重新构建
|
||||||
if (originalData == null || originalData.length < 178) {
|
if (originalData == null || originalData.length < 178) {
|
||||||
|
|||||||
@@ -20,8 +20,6 @@ public class WorkRecord extends OrgBaseDO {
|
|||||||
private String workName;
|
private String workName;
|
||||||
private Long userId;
|
private Long userId;
|
||||||
|
|
||||||
private String mode;//导航任务模式 single_point|coverage
|
|
||||||
|
|
||||||
// private String jsonData;
|
// private String jsonData;
|
||||||
|
|
||||||
@TableField(typeHandler = JacksonTypeHandler.class)
|
@TableField(typeHandler = JacksonTypeHandler.class)
|
||||||
|
|||||||
@@ -1,37 +1,35 @@
|
|||||||
package com.maibu.core.business.device;
|
package com.maibu.core.business.device;
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
|
||||||
import com.maibu.core.business.*;
|
|
||||||
import com.maibu.core.business.path.LatAndLngEntity;
|
|
||||||
import com.maibu.core.business.path.RoutePlanSendEntity;
|
|
||||||
import com.maibu.core.enums.ConnectorType;
|
|
||||||
import com.maibu.core.enums.DeviceTaskStaus;
|
|
||||||
import com.maibu.core.host.HostWorkRecordCreateDTO;
|
|
||||||
import com.maibu.core.host.MutiPointEntity;
|
|
||||||
import com.maibu.core.host.PointEntity;
|
|
||||||
import com.maibu.core.ota.DeviceOtaFirmware;
|
|
||||||
import com.maibu.mapper.DevicePlanTaskMapper;
|
|
||||||
import com.maibu.mapper.WorkRecordMapper;
|
|
||||||
import com.maibu.memory.GlobalMemory;
|
|
||||||
import com.maibu.memory.SiteMemory;
|
|
||||||
import com.maibu.mqtt.MqttTopic;
|
|
||||||
import com.maibu.utils.StringUtils;
|
|
||||||
import com.maibu.utils.json.JsonUtils;
|
|
||||||
import com.maibu.utils.spring.SpringUtils;
|
|
||||||
import io.netty.buffer.Unpooled;
|
|
||||||
import lombok.Data;
|
|
||||||
import lombok.EqualsAndHashCode;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
import org.eclipse.paho.client.mqttv3.MqttException;
|
|
||||||
|
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
import java.nio.ByteOrder;
|
import java.nio.ByteOrder;
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
import java.util.*;
|
import java.util.LinkedList;
|
||||||
import java.util.concurrent.ScheduledExecutorService;
|
import java.util.Queue;
|
||||||
import java.util.concurrent.ScheduledFuture;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
import com.maibu.utils.json.JsonUtils;
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
import org.springframework.util.CollectionUtils;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||||
|
import com.maibu.core.business.Device;
|
||||||
|
import com.maibu.core.business.DevicePlanTask;
|
||||||
|
import com.maibu.core.business.DeviceRunParam;
|
||||||
|
import com.maibu.core.business.DeviceRunStatistics;
|
||||||
|
import com.maibu.core.business.PlanPath;
|
||||||
|
import com.maibu.core.business.WorkRecord;
|
||||||
|
import com.maibu.core.business.path.LatAndLngEntity;
|
||||||
|
import com.maibu.core.business.path.RoutePlanSendEntity;
|
||||||
|
import com.maibu.core.enums.ConnectorType;
|
||||||
|
import com.maibu.core.enums.DeviceTaskStaus;
|
||||||
|
import com.maibu.mapper.DevicePlanTaskMapper;
|
||||||
|
import com.maibu.mapper.WorkRecordMapper;
|
||||||
|
import com.maibu.memory.GlobalMemory;
|
||||||
|
import com.maibu.memory.SiteMemory;
|
||||||
|
import com.maibu.utils.spring.SpringUtils;
|
||||||
|
|
||||||
|
import io.netty.buffer.Unpooled;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
@Slf4j
|
@Slf4j
|
||||||
@EqualsAndHashCode(callSuper = true)
|
@EqualsAndHashCode(callSuper = true)
|
||||||
@@ -60,8 +58,8 @@ public class NettyDevice extends Connector {
|
|||||||
// todo 注册的时候更新 siteId
|
// todo 注册的时候更新 siteId
|
||||||
private Device device;
|
private Device device;
|
||||||
|
|
||||||
// todo 当前登录的账号的token 以token为控制的权限
|
//todo 假如设置一个当前控制的token
|
||||||
private String token;
|
private String currentControlToken;
|
||||||
|
|
||||||
@JsonIgnore
|
@JsonIgnore
|
||||||
private DevicePlanTaskMapper devicePlanTaskMapper = SpringUtils.getBean(DevicePlanTaskMapper.class);
|
private DevicePlanTaskMapper devicePlanTaskMapper = SpringUtils.getBean(DevicePlanTaskMapper.class);
|
||||||
@@ -69,11 +67,6 @@ public class NettyDevice extends Connector {
|
|||||||
@JsonIgnore
|
@JsonIgnore
|
||||||
private WorkRecordMapper workRecordMapper = SpringUtils.getBean(WorkRecordMapper.class);
|
private WorkRecordMapper workRecordMapper = SpringUtils.getBean(WorkRecordMapper.class);
|
||||||
|
|
||||||
@JsonIgnore
|
|
||||||
private ScheduledExecutorService executor = SpringUtils.getBean("scheduledExecutorService");
|
|
||||||
|
|
||||||
private static final String mqttClientId = "maibu-mqtt-client";
|
|
||||||
|
|
||||||
public NettyDevice(String connectorId) {
|
public NettyDevice(String connectorId) {
|
||||||
super(connectorId);
|
super(connectorId);
|
||||||
this.deviceType = ConnectorType.MASTER; // 默认上位机角色
|
this.deviceType = ConnectorType.MASTER; // 默认上位机角色
|
||||||
@@ -84,10 +77,6 @@ public class NettyDevice extends Connector {
|
|||||||
this.deviceType = deviceType;
|
this.deviceType = deviceType;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void status(Integer onlineStatus) {
|
|
||||||
this.onlineStatus = onlineStatus;
|
|
||||||
}
|
|
||||||
|
|
||||||
// todo 如何确定命令已收到?
|
// todo 如何确定命令已收到?
|
||||||
public void sendNextPoint() {
|
public void sendNextPoint() {
|
||||||
if (task.getTaskStaus().equals(DeviceTaskStaus.PAUSE))
|
if (task.getTaskStaus().equals(DeviceTaskStaus.PAUSE))
|
||||||
@@ -120,14 +109,13 @@ public class NettyDevice extends Connector {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public synchronized Long finishTask() {
|
public synchronized Long finishTask() {
|
||||||
// sendPathCommand((byte) 0x01, (short) 0, 0.00d, 0.00d, (short) 0);
|
sendPathCommand((byte) 0x01, (short) 0, 0.00d, 0.00d, (short) 0);
|
||||||
long finishId = task.getId();
|
long finishId = task.getId();
|
||||||
task.setTaskStaus(DeviceTaskStaus.FINISH);
|
task.setTaskStaus(DeviceTaskStaus.FINISH);
|
||||||
task.setFinishTime(LocalDateTime.now());
|
task.setFinishTime(LocalDateTime.now());
|
||||||
devicePlanTaskMapper.saveOrUpdate(task);
|
devicePlanTaskMapper.saveOrUpdate(task);
|
||||||
SiteMemory siteMemory = GlobalMemory.getSiteMemory(task.getOrgId(), task.getSiteId());
|
SiteMemory siteMemory = GlobalMemory.getSiteMemory(task.getOrgId(), task.getSiteId());
|
||||||
siteMemory.removeDevicePlanExecute(task.getDeviceId());
|
siteMemory.removeDevicePlanExecute(task.getDeviceId());
|
||||||
GlobalMemory.taskPathMap.remove(task.getId());
|
|
||||||
task = null;
|
task = null;
|
||||||
currentTaskId = null;
|
currentTaskId = null;
|
||||||
currentPoint = null;
|
currentPoint = null;
|
||||||
@@ -136,59 +124,15 @@ public class NettyDevice extends Connector {
|
|||||||
return finishId;
|
return finishId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public synchronized boolean cancelTask() {
|
||||||
public synchronized boolean cancelingTask() throws MqttException {
|
|
||||||
if (task != null) {
|
|
||||||
WorkRecord workRecord = workRecordMapper.selectById(task.getRouteId());
|
|
||||||
if (workRecord != null) {
|
|
||||||
HostWorkRecordCreateDTO dto = new HostWorkRecordCreateDTO();
|
|
||||||
dto.setAction("cancel");
|
|
||||||
dto.setCommand_id(task.getId() + "_" + System.currentTimeMillis());
|
|
||||||
dto.setTask_id(String.valueOf(task.getId()));
|
|
||||||
dto.setSn(task.getDeviceId());
|
|
||||||
dto.setMode(workRecord.getMode());
|
|
||||||
dto.setTimestamp(System.currentTimeMillis());
|
|
||||||
dto.setMessage_id(task.getId() + "_" + System.currentTimeMillis());
|
|
||||||
dto.setProtocol_version("1.4");
|
|
||||||
|
|
||||||
GlobalMemory.customMqttDeviceMonitor.publish(mqttClientId,
|
|
||||||
String.format(MqttTopic.MOWER_TASK_ROUTE_SET, task.getDeviceId()),
|
|
||||||
JsonUtils.toJsonString(dto));
|
|
||||||
task.setTaskStaus(DeviceTaskStaus.CANCELING);
|
|
||||||
task.setUpdateTime(LocalDateTime.now());
|
|
||||||
devicePlanTaskMapper.saveOrUpdate(task);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public synchronized boolean canceledTask() {
|
|
||||||
if (task != null) {
|
if (task != null) {
|
||||||
|
sendPathCommand((byte) 0x01, (short) 0, 0.00d, 0.00d, (short) 0);
|
||||||
task.setTaskStaus(DeviceTaskStaus.CANCELED);
|
task.setTaskStaus(DeviceTaskStaus.CANCELED);
|
||||||
task.setUpdateTime(LocalDateTime.now());
|
task.setUpdateTime(LocalDateTime.now());
|
||||||
devicePlanTaskMapper.saveOrUpdate(task);
|
devicePlanTaskMapper.saveOrUpdate(task);
|
||||||
SiteMemory siteMemory = GlobalMemory.getSiteMemory(task.getOrgId(), task.getSiteId());
|
SiteMemory siteMemory = GlobalMemory.getSiteMemory(task.getOrgId(), task.getSiteId());
|
||||||
siteMemory.removeDevicePlanPrepare(task);
|
siteMemory.removeDevicePlanPrepare(task);
|
||||||
siteMemory.removeDevicePlanExecute(task.getDeviceId());
|
siteMemory.removeDevicePlanExecute(task.getDeviceId());
|
||||||
GlobalMemory.taskPathMap.remove(task.getId());
|
|
||||||
task = null;
|
|
||||||
currentTaskId = null;
|
|
||||||
currentPoint = null;
|
|
||||||
locationQueue.clear();
|
|
||||||
executingTask = false;
|
|
||||||
}
|
|
||||||
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;
|
task = null;
|
||||||
currentTaskId = null;
|
currentTaskId = null;
|
||||||
currentPoint = null;
|
currentPoint = null;
|
||||||
@@ -212,9 +156,8 @@ public class NettyDevice extends Connector {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 配置左右轮增益系数
|
//配置左右轮增益系数
|
||||||
public void sendWheelGainCoefficientsCommand(double leftForwardGain, double leftBackwardGain,
|
public void sendWheelGainCoefficientsCommand(double leftForwardGain, double leftBackwardGain, double rightForwardGain, double rightBackwardGain) {
|
||||||
double rightForwardGain, double rightBackwardGain) {
|
|
||||||
ByteBuffer buffer = ByteBuffer.allocate(39);
|
ByteBuffer buffer = ByteBuffer.allocate(39);
|
||||||
buffer.order(ByteOrder.LITTLE_ENDIAN);
|
buffer.order(ByteOrder.LITTLE_ENDIAN);
|
||||||
|
|
||||||
@@ -246,6 +189,7 @@ public class NettyDevice extends Connector {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void readConfigCommand() {
|
public void readConfigCommand() {
|
||||||
byte[] bytes = DeviceRunParam.toReadBytes();
|
byte[] bytes = DeviceRunParam.toReadBytes();
|
||||||
log.debug("下发读取配置的报文:{}", toHexString(bytes));
|
log.debug("下发读取配置的报文:{}", toHexString(bytes));
|
||||||
@@ -294,128 +238,28 @@ public class NettyDevice extends Connector {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void startTask() {
|
public void startTask() {
|
||||||
try {
|
try {
|
||||||
if (executingTask)
|
if (executingTask)
|
||||||
return;
|
return;
|
||||||
executingTask = true;
|
|
||||||
if (task != null) {
|
if (task != null) {
|
||||||
// startTime 在启动前记录
|
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());
|
task.setStartTime(LocalDateTime.now());
|
||||||
|
|
||||||
AtomicInteger count = new AtomicInteger(0);
|
|
||||||
ScheduledFuture<?>[] futureHolder = new ScheduledFuture<?>[1];
|
|
||||||
futureHolder[0] = executor.scheduleWithFixedDelay(() -> {
|
|
||||||
int current = count.incrementAndGet();
|
|
||||||
try {
|
|
||||||
if (task.isTaskAccepted()) {
|
|
||||||
// 成功,停止后续执行
|
|
||||||
futureHolder[0].cancel(false);
|
|
||||||
log.info("任务执行成功,停止重试,执行次数={}", current);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
sendNavigationCommand();
|
|
||||||
// 达到最大次数
|
|
||||||
if (current >= 10) {
|
|
||||||
futureHolder[0].cancel(false);
|
|
||||||
log.warn("任务执行达到最大次数,停止执行");
|
|
||||||
executingTask = false;
|
|
||||||
task.setTaskStaus(DeviceTaskStaus.FAILED);
|
|
||||||
devicePlanTaskMapper.saveOrUpdate(task);
|
|
||||||
task = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
} catch (Exception e) {
|
|
||||||
log.error("任务执行异常,次数={}", current, e);
|
|
||||||
|
|
||||||
// 异常是否算一次,可以根据你的业务决定
|
|
||||||
if (current >= 10) {
|
|
||||||
futureHolder[0].cancel(false);
|
|
||||||
}
|
|
||||||
executingTask = false;
|
|
||||||
task.setTaskStaus(DeviceTaskStaus.FAILED);
|
|
||||||
devicePlanTaskMapper.saveOrUpdate(task);
|
|
||||||
task = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
}, 0, 5, TimeUnit.SECONDS);
|
|
||||||
}
|
}
|
||||||
|
executingTask = true;
|
||||||
|
sendNextPoint();
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.error("发送开始任务:error {} ", e.getMessage());
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void sendNavigationCommand() throws MqttException {
|
|
||||||
|
|
||||||
log.debug("发送开始任务 taskStatus:{},routeId:{}", task.getTaskStaus(), task.getRouteId());
|
|
||||||
if (!task.getTaskStaus().equals(DeviceTaskStaus.EXECUTING))
|
|
||||||
return;
|
|
||||||
|
|
||||||
WorkRecord workRecord = workRecordMapper.selectById(task.getRouteId());
|
|
||||||
log.debug("发送开始任务 workRecord {}", workRecord);
|
|
||||||
if (workRecord != null) {
|
|
||||||
HostWorkRecordCreateDTO dto = new HostWorkRecordCreateDTO();
|
|
||||||
dto.setAction("start");
|
|
||||||
dto.setCommand_id(task.getId() + "_" + System.currentTimeMillis());
|
|
||||||
dto.setTask_id(String.valueOf(task.getId()));
|
|
||||||
dto.setSn(task.getDeviceId());
|
|
||||||
dto.setMode(workRecord.getMode());
|
|
||||||
dto.setTimestamp(System.currentTimeMillis());
|
|
||||||
dto.setMessage_id(task.getId() + "_" + System.currentTimeMillis());
|
|
||||||
dto.setProtocol_version("1.4");
|
|
||||||
|
|
||||||
PointEntity point = new PointEntity();
|
|
||||||
if (!StringUtils.isEmpty(workRecord.getMode())) {
|
|
||||||
if (workRecord.getMode().equals("single_point")) {
|
|
||||||
point.setLongitude(workRecord.getJsonData().getPath().get(0).getLng());
|
|
||||||
point.setLatitude(workRecord.getJsonData().getPath().get(0).getLat());
|
|
||||||
}
|
|
||||||
if (workRecord.getMode().equals("coverage")) {
|
|
||||||
List<MutiPointEntity> boundary_points = new ArrayList<>();
|
|
||||||
// workRecord.getJsonData().getPath().forEach(x -> {
|
|
||||||
// MutiPointEntity mutiPoint = new MutiPointEntity();
|
|
||||||
// mutiPoint.setLongitude(x.getLng());
|
|
||||||
// mutiPoint.setLatitude(x.getLat());
|
|
||||||
// mutiPoint.setIndex();
|
|
||||||
// boundary_points.add(mutiPoint);
|
|
||||||
// });
|
|
||||||
List<LatAndLngEntity> path = workRecord.getJsonData().getPath();
|
|
||||||
|
|
||||||
for (int i = 0; i < path.size(); i++) {
|
|
||||||
LatAndLngEntity x = path.get(i);
|
|
||||||
|
|
||||||
MutiPointEntity mutiPoint = new MutiPointEntity();
|
|
||||||
mutiPoint.setLongitude(x.getLng());
|
|
||||||
mutiPoint.setLatitude(x.getLat());
|
|
||||||
mutiPoint.setIndex(i);
|
|
||||||
boundary_points.add(mutiPoint);
|
|
||||||
}
|
|
||||||
point.setBoundary_points(boundary_points);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
dto.setData(point);
|
|
||||||
GlobalMemory.customMqttDeviceMonitor.publish(mqttClientId,
|
|
||||||
String.format(MqttTopic.MOWER_TASK_ROUTE_SET, task.getDeviceId()),
|
|
||||||
JsonUtils.toJsonString(dto));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void upgrade(String deviceId, DeviceOtaFirmware firmware) throws MqttException {
|
|
||||||
Map<String, Object> payload = new HashMap<>();
|
|
||||||
payload.put("action", "ota_upgrade");
|
|
||||||
payload.put("version", firmware.getVersion());
|
|
||||||
payload.put("file_url", firmware.getFileUrl());
|
|
||||||
payload.put("firmware_id", firmware.getId());
|
|
||||||
payload.put("sn", deviceId);
|
|
||||||
payload.put("timestamp", System.currentTimeMillis());
|
|
||||||
payload.put("message_id", firmware.getId() + "_" + System.currentTimeMillis());
|
|
||||||
|
|
||||||
GlobalMemory.customMqttDeviceMonitor.publish(
|
|
||||||
mqttClientId,
|
|
||||||
String.format(MqttTopic.MOWER_OTA_UPGRADE_SET, deviceId),
|
|
||||||
JsonUtils.toJsonString(payload)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,18 +0,0 @@
|
|||||||
package com.maibu.core.business.dto;
|
|
||||||
|
|
||||||
import lombok.Data;
|
|
||||||
|
|
||||||
@Data
|
|
||||||
public class DeviceMapPushDTO {
|
|
||||||
private String id;
|
|
||||||
private double lat;
|
|
||||||
private double lng;
|
|
||||||
private double y; //yaw
|
|
||||||
private String f; //fix_status
|
|
||||||
private double a; //altitude
|
|
||||||
private String s;//status 运行状态
|
|
||||||
private Long t; //taskId 任务id
|
|
||||||
private double b; //电量
|
|
||||||
private boolean ha = false;//hasAlarm 有无告警
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -20,8 +20,4 @@ public class DeviceTaskCommandDTO {
|
|||||||
|
|
||||||
private Long taskId;
|
private Long taskId;
|
||||||
|
|
||||||
private Long regionId;
|
|
||||||
|
|
||||||
private boolean forceCancel = false; //强制取消 不等回复
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,12 +0,0 @@
|
|||||||
package com.maibu.core.business.dto;
|
|
||||||
|
|
||||||
import com.maibu.core.enums.MesType;
|
|
||||||
import lombok.Data;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
@Data
|
|
||||||
public class WebMapMessageDTO {
|
|
||||||
private List<DeviceMapPushDTO> data;
|
|
||||||
private MesType type;
|
|
||||||
}
|
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
package com.maibu.core.business.dto;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import com.maibu.core.business.path.LatAndLngEntity;
|
|
||||||
import com.maibu.core.enums.MesType;
|
|
||||||
|
|
||||||
import lombok.Data;
|
|
||||||
|
|
||||||
@Data
|
|
||||||
public class WebRouteStatusMessageDTO {
|
|
||||||
private List<LatAndLngEntity> data;
|
|
||||||
private String deviceId;
|
|
||||||
private Long taskId;
|
|
||||||
private MesType type;
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
package com.maibu.core.business.inter;
|
||||||
|
|
||||||
|
public interface DeviceWebSocketInterace {
|
||||||
|
|
||||||
|
void sendWebsoketMes(String key, String data);
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
package com.maibu.core.business.inter;
|
|
||||||
|
|
||||||
public interface DeviceWebSocketInterface {
|
|
||||||
|
|
||||||
void sendWebsocketMes(String key, String data);
|
|
||||||
|
|
||||||
|
|
||||||
void sendMapWebsocketMes(Long siteId,String data);
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -14,19 +14,10 @@ public class WebsocketMesDispather {
|
|||||||
private ApplicationContext applicationContext;
|
private ApplicationContext applicationContext;
|
||||||
|
|
||||||
public void dispather(String key, String data) {
|
public void dispather(String key, String data) {
|
||||||
Map<String, DeviceWebSocketInterface> beanMap = applicationContext.getBeansOfType(DeviceWebSocketInterface.class);
|
Map<String, DeviceWebSocketInterace> beanMap = applicationContext.getBeansOfType(DeviceWebSocketInterace.class);
|
||||||
// 遍历
|
// 遍历
|
||||||
beanMap.values().forEach(x -> {
|
beanMap.values().forEach(x -> {
|
||||||
x.sendWebsocketMes(key, data);
|
x.sendWebsoketMes(key, data);
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public void mapMessageDispather(Long siteId, String data) {
|
|
||||||
Map<String, DeviceWebSocketInterface> beanMap = applicationContext.getBeansOfType(DeviceWebSocketInterface.class);
|
|
||||||
// 遍历
|
|
||||||
beanMap.values().forEach(x -> {
|
|
||||||
x.sendMapWebsocketMes(siteId, data);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,15 +1,14 @@
|
|||||||
package com.maibu.core.domain.entity;
|
package com.maibu.core.domain.entity;
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.annotation.IdType;
|
import com.baomidou.mybatisplus.annotation.IdType;
|
||||||
import com.baomidou.mybatisplus.annotation.TableId;
|
import com.baomidou.mybatisplus.annotation.TableId;
|
||||||
import com.baomidou.mybatisplus.annotation.TableName;
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
import com.maibu.core.domain.BaseDO;
|
import com.maibu.core.domain.BaseDO;
|
||||||
|
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.EqualsAndHashCode;
|
import lombok.EqualsAndHashCode;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
|
||||||
@EqualsAndHashCode(callSuper = true)
|
@EqualsAndHashCode(callSuper = true)
|
||||||
@Data
|
@Data
|
||||||
@TableName(value = "sys_region")
|
@TableName(value = "sys_region")
|
||||||
@@ -30,6 +29,4 @@ public class SysRegion extends BaseDO {
|
|||||||
|
|
||||||
private Integer status;
|
private Integer status;
|
||||||
|
|
||||||
private Long bindRoute;// 绑定的线路id
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -43,6 +43,4 @@ public class SysSite extends BaseDO {
|
|||||||
|
|
||||||
private boolean dingTalkOrderPush = false;// 工单是否推送
|
private boolean dingTalkOrderPush = false;// 工单是否推送
|
||||||
|
|
||||||
private String siteMapName; // geoserver 地图名称
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -48,12 +48,6 @@ public class LoginUser implements UserDetails {
|
|||||||
*/
|
*/
|
||||||
private String token;
|
private String token;
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 用户唯一标识 用户控制设备
|
|
||||||
*/
|
|
||||||
private String realToken;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 登录时间
|
* 登录时间
|
||||||
*/
|
*/
|
||||||
@@ -114,7 +108,7 @@ public class LoginUser implements UserDetails {
|
|||||||
this.permissions = permissions;
|
this.permissions = permissions;
|
||||||
}
|
}
|
||||||
|
|
||||||
public LoginUser(Long userId, Long deptId, Long orgId, Long siteId, Long roleId, String language, SysUser user, Set<String> permissions) {
|
public LoginUser(Long userId, Long deptId, Long orgId, Long siteId, Long roleId,String language, SysUser user, Set<String> permissions) {
|
||||||
this.userId = userId;
|
this.userId = userId;
|
||||||
this.deptId = deptId;
|
this.deptId = deptId;
|
||||||
this.orgId = orgId;
|
this.orgId = orgId;
|
||||||
|
|||||||
@@ -7,13 +7,12 @@ import lombok.Getter;
|
|||||||
@AllArgsConstructor
|
@AllArgsConstructor
|
||||||
public enum DeviceTaskStaus {
|
public enum DeviceTaskStaus {
|
||||||
|
|
||||||
NEW("NEW", "新建"),
|
NEW("NEW","新建"),
|
||||||
EXECUTING("EXECUTING", "执行中"),
|
EXECUTING("EXECUTING","执行中"),
|
||||||
PAUSE("PAUSE", "暂停中"),
|
PAUSE("PAUSE","暂停中"),
|
||||||
CANCELED("CANCELED", "已取消"),
|
CANCELED("CANCELED","已取消"),
|
||||||
CANCELING("CANCELING", "取消中"),
|
FINISH("FINISH","执行成功"),
|
||||||
FINISH("FINISH", "执行成功"),
|
FAILED("FAILED","执行失败");
|
||||||
FAILED("FAILED", "执行失败");
|
|
||||||
|
|
||||||
|
|
||||||
private final String code;
|
private final String code;
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ package com.maibu.core.enums;
|
|||||||
public enum MesType {
|
public enum MesType {
|
||||||
AUTH, // 登录连接权限web->be
|
AUTH, // 登录连接权限web->be
|
||||||
deviceInfo, // 设备状态 be->web
|
deviceInfo, // 设备状态 be->web
|
||||||
locationInfo,
|
|
||||||
path, // 路径下发 web->be
|
path, // 路径下发 web->be
|
||||||
have_logged_in, // 消息
|
have_logged_in, // 消息
|
||||||
device_status_changed, // 上下线状态变化
|
device_status_changed, // 上下线状态变化
|
||||||
@@ -14,7 +13,5 @@ public enum MesType {
|
|||||||
remoteControl,
|
remoteControl,
|
||||||
detectionReport, // 障碍物消息
|
detectionReport, // 障碍物消息
|
||||||
switchPermission, // 切换控制申请
|
switchPermission, // 切换控制申请
|
||||||
switchResult,// 切换结果
|
switchResult;// 切换结果
|
||||||
route_post,// 路径规划 点位推送
|
|
||||||
mapPush;
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,18 +0,0 @@
|
|||||||
package com.maibu.core.enums;
|
|
||||||
|
|
||||||
import lombok.AllArgsConstructor;
|
|
||||||
import lombok.Getter;
|
|
||||||
|
|
||||||
@Getter
|
|
||||||
@AllArgsConstructor
|
|
||||||
public enum OtaOperate {
|
|
||||||
|
|
||||||
upload("upload", "上传"),
|
|
||||||
upgrade("upgrade", "升级"),
|
|
||||||
rollback("rollback", "回滚"),
|
|
||||||
reboot("reboot", "重启");
|
|
||||||
|
|
||||||
private final String name;
|
|
||||||
private final String value;
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
package com.maibu.core.host;
|
|
||||||
|
|
||||||
import lombok.Data;
|
|
||||||
import lombok.EqualsAndHashCode;
|
|
||||||
|
|
||||||
@EqualsAndHashCode(callSuper = true)
|
|
||||||
@Data
|
|
||||||
public class HeartBeatDTO extends HostBase {
|
|
||||||
private String status;
|
|
||||||
|
|
||||||
private Long sysTimestamp; //服务器的时间
|
|
||||||
}
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
package com.maibu.core.host;
|
|
||||||
|
|
||||||
import lombok.Data;
|
|
||||||
|
|
||||||
@Data
|
|
||||||
public class HostBase {
|
|
||||||
|
|
||||||
private String protocol_version;
|
|
||||||
private String message_id;
|
|
||||||
private String sn;
|
|
||||||
private Long timestamp; //上位机的时间
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
package com.maibu.core.host;
|
|
||||||
|
|
||||||
|
|
||||||
import lombok.Data;
|
|
||||||
import lombok.EqualsAndHashCode;
|
|
||||||
|
|
||||||
@EqualsAndHashCode(callSuper = true)
|
|
||||||
@Data
|
|
||||||
public class HostLocationRelTimeDTO extends HostBase {
|
|
||||||
|
|
||||||
private LocationMessage data;
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
package com.maibu.core.host;
|
|
||||||
|
|
||||||
|
|
||||||
import lombok.Data;
|
|
||||||
import lombok.EqualsAndHashCode;
|
|
||||||
|
|
||||||
@EqualsAndHashCode(callSuper = true)
|
|
||||||
@Data
|
|
||||||
public class HostNavigationReplyDTO extends HostBase {
|
|
||||||
|
|
||||||
private String task_id; //任务唯一编号
|
|
||||||
private String command_id;//指令唯一编号
|
|
||||||
private boolean accepted;//是否接收
|
|
||||||
private String code;//任务动作 OK|INVALID|BUSY|ERROR
|
|
||||||
|
|
||||||
private String message;
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
package com.maibu.core.host;
|
|
||||||
|
|
||||||
|
|
||||||
import lombok.Data;
|
|
||||||
import lombok.EqualsAndHashCode;
|
|
||||||
|
|
||||||
@EqualsAndHashCode(callSuper = true)
|
|
||||||
@Data
|
|
||||||
public class HostTaskStatusDTO extends HostBase{
|
|
||||||
|
|
||||||
private String task_id; //任务唯一编号
|
|
||||||
private String command_id;//指令唯一编号
|
|
||||||
private String mode;//导航任务模式 single_point|coverage
|
|
||||||
private String status;//任务动作 accepted|running|paused|completed|cancelled|failed
|
|
||||||
|
|
||||||
private HostTaskStatusDetailDTO data;
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
package com.maibu.core.host;
|
|
||||||
|
|
||||||
|
|
||||||
import lombok.Data;
|
|
||||||
|
|
||||||
@Data
|
|
||||||
public class HostTaskStatusDetailDTO {
|
|
||||||
private float progress;
|
|
||||||
private String error_code;
|
|
||||||
private String error_message;
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
package com.maibu.core.host;
|
|
||||||
|
|
||||||
|
|
||||||
import lombok.Data;
|
|
||||||
import lombok.EqualsAndHashCode;
|
|
||||||
|
|
||||||
@EqualsAndHashCode(callSuper = true)
|
|
||||||
@Data
|
|
||||||
public class HostVehicleRelTimeDTO extends HostBase {
|
|
||||||
|
|
||||||
private VehicleMessage data;
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,20 +0,0 @@
|
|||||||
package com.maibu.core.host;
|
|
||||||
|
|
||||||
|
|
||||||
import lombok.Data;
|
|
||||||
import lombok.EqualsAndHashCode;
|
|
||||||
|
|
||||||
@EqualsAndHashCode(callSuper = true)
|
|
||||||
@Data
|
|
||||||
public class HostWorkRecordCreateDTO extends HostBase {
|
|
||||||
|
|
||||||
private String task_id; //任务唯一编号
|
|
||||||
private String command_id;//指令唯一编号
|
|
||||||
private String mode;//导航任务模式 single_point|coverage
|
|
||||||
private String action;//任务动作 start/pause/resume/cancel
|
|
||||||
// private String frame_id; //WGS84
|
|
||||||
|
|
||||||
private PointEntity data;
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,27 +0,0 @@
|
|||||||
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
|
|
||||||
@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 String fix_status;
|
|
||||||
private double altitude;
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
package com.maibu.core.host;
|
|
||||||
|
|
||||||
import lombok.Data;
|
|
||||||
|
|
||||||
@Data
|
|
||||||
public class MutiPointEntity {
|
|
||||||
|
|
||||||
private int index;
|
|
||||||
private double latitude;
|
|
||||||
private double longitude;
|
|
||||||
private double yaw;//目标航向,正北0°、顺时针正、0-360°
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,20 +0,0 @@
|
|||||||
package com.maibu.core.host;
|
|
||||||
|
|
||||||
import lombok.Data;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
@Data
|
|
||||||
public class PointEntity {
|
|
||||||
|
|
||||||
private double latitude;
|
|
||||||
private double longitude;
|
|
||||||
private double yaw;//目标航向,正北0°、顺时针正、0-360°
|
|
||||||
|
|
||||||
private List<MutiPointEntity> boundary_points;
|
|
||||||
|
|
||||||
private double cell_size;//覆盖分辨率,单位m
|
|
||||||
|
|
||||||
private double angle;//覆盖作业方向,单位度
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
package com.maibu.core.host;
|
|
||||||
|
|
||||||
import lombok.Data;
|
|
||||||
|
|
||||||
@Data
|
|
||||||
public class VehicleMessage {
|
|
||||||
|
|
||||||
private double speed;
|
|
||||||
private double battery_percentage;// 电量
|
|
||||||
private double battery_voltage;// 电压
|
|
||||||
private String motion;// moving|stopped|blocked
|
|
||||||
private boolean emergency_stop; // 急停状态
|
|
||||||
|
|
||||||
private double distance; // 里程数
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
package com.maibu.core.mq.message;
|
||||||
|
|
||||||
|
import com.maibu.core.ota.OtaPackageCode;
|
||||||
|
import com.maibu.core.protocol.Message;
|
||||||
|
import com.maibu.core.protocol.modbus.ModbusCode;
|
||||||
|
import io.netty.buffer.ByteBuf;
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 消息解析model
|
||||||
|
* @author gsb
|
||||||
|
* @date 2022/10/10 15:53
|
||||||
|
*/
|
||||||
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
@Data
|
||||||
|
@Builder
|
||||||
|
public class DeviceData extends Message {
|
||||||
|
|
||||||
|
/*topic*/
|
||||||
|
private String topicName;
|
||||||
|
|
||||||
|
/*设备编号*/
|
||||||
|
private String serialNumber;
|
||||||
|
|
||||||
|
/*原数据*/
|
||||||
|
private byte[] data;
|
||||||
|
|
||||||
|
private ByteBuf buf;
|
||||||
|
|
||||||
|
private Object body;
|
||||||
|
/*MQTT OR 其他*/
|
||||||
|
private int type;
|
||||||
|
/*Modbus*/
|
||||||
|
private ModbusCode code;
|
||||||
|
/**产品id*/
|
||||||
|
private Long productId;
|
||||||
|
|
||||||
|
private OtaPackageCode netModbusCode;
|
||||||
|
|
||||||
|
private int bitCount;
|
||||||
|
}
|
||||||
@@ -0,0 +1,59 @@
|
|||||||
|
package com.maibu.core.mq.message;
|
||||||
|
|
||||||
|
import com.maibu.core.protocol.modbus.ModbusCode;
|
||||||
|
import com.maibu.enums.ServerType;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设备下发指令model
|
||||||
|
*
|
||||||
|
* @author gsb
|
||||||
|
* @date 2022/10/10 16:18
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@Builder
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
public class DeviceDownMessage {
|
||||||
|
|
||||||
|
private String messageId;
|
||||||
|
/**
|
||||||
|
* 时间戳,单位毫秒
|
||||||
|
*/
|
||||||
|
private Long timestamp;
|
||||||
|
/**
|
||||||
|
* 消息体
|
||||||
|
*/
|
||||||
|
private Object body;
|
||||||
|
/*下发的指令,服务调用的时候就是服务标识符*/
|
||||||
|
private String identifier;
|
||||||
|
/*产品id*/
|
||||||
|
private Long productId;
|
||||||
|
/**
|
||||||
|
* 设备编码
|
||||||
|
*/
|
||||||
|
private String serialNumber;
|
||||||
|
/**
|
||||||
|
* 从机编号
|
||||||
|
*/
|
||||||
|
private Integer slaveId;
|
||||||
|
private ModbusCode code;
|
||||||
|
private String protocolCode;
|
||||||
|
|
||||||
|
private List<PropRead> values;
|
||||||
|
private String topic;
|
||||||
|
private String subCode;
|
||||||
|
private ServerType serverType;
|
||||||
|
|
||||||
|
public DeviceDownMessage(List<PropRead> values, String topic, String subCode,String transport) {
|
||||||
|
this.values = values;
|
||||||
|
this.topic = topic;
|
||||||
|
this.subCode = subCode;
|
||||||
|
this.serverType = ServerType.explain(transport);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
package com.maibu.core.mq.message;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 平台下发指令数据model
|
||||||
|
* @author bill
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class DeviceFunctionMessage {
|
||||||
|
|
||||||
|
/*流水号,兼容modbus标准协议没有消息流水号*/
|
||||||
|
private String seqNo;
|
||||||
|
/*平台时间*/
|
||||||
|
private Long pfTimestamp;
|
||||||
|
/*下发的消息体*/
|
||||||
|
private Object body;
|
||||||
|
/*下发的指令物模型标识符*/
|
||||||
|
private String identifier;
|
||||||
|
/*下发的数据寄存器地址*/
|
||||||
|
private String hexAddress;
|
||||||
|
/*产品ID*/
|
||||||
|
private Long productId;
|
||||||
|
/*设备编号*/
|
||||||
|
private String serialNumber;
|
||||||
|
/*网关设备编号*/
|
||||||
|
private String protocolCode;
|
||||||
|
|
||||||
|
/*是否有子设备 0-否,1-是*/
|
||||||
|
private Integer hasSub;
|
||||||
|
/*子设备从机编号 例如 02 编号从机。通过主机集控下发的指定从机编号*/
|
||||||
|
private String subDeviceCode;
|
||||||
|
}
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
package com.maibu.core.mq.message;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设备消息
|
||||||
|
* @author bill
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||||
|
public class DeviceMessage {
|
||||||
|
|
||||||
|
/** 下发的数据*/
|
||||||
|
private Object message;
|
||||||
|
|
||||||
|
/** 下发的topic*/
|
||||||
|
private String topicName;
|
||||||
|
|
||||||
|
/** 设备编号*/
|
||||||
|
private String serialNumber;
|
||||||
|
|
||||||
|
private String dataType;
|
||||||
|
|
||||||
|
/** 时间 */
|
||||||
|
@JsonFormat(pattern ="yyyy-MM-dd HH:mm:ss:SSS")
|
||||||
|
private Date time;
|
||||||
|
}
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
package com.maibu.core.mq.message;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 指令下发组将的model
|
||||||
|
* @author bill
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class FunctionCallBackBo {
|
||||||
|
|
||||||
|
/*下发的数据*/
|
||||||
|
private byte[] message;
|
||||||
|
|
||||||
|
/*MQTt-下发的topic*/
|
||||||
|
private String topicName;
|
||||||
|
|
||||||
|
/*设备编号*/
|
||||||
|
private String serialNumber;
|
||||||
|
/**
|
||||||
|
* 原数据包
|
||||||
|
*/
|
||||||
|
private String sources;
|
||||||
|
}
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
package com.maibu.core.mq.message;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 指令下发组将的model
|
||||||
|
* @author bill
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class InstructionsMessage {
|
||||||
|
|
||||||
|
/*下发的数据*/
|
||||||
|
private byte[] message;
|
||||||
|
|
||||||
|
/*MQTt-下发的topic*/
|
||||||
|
private String topicName;
|
||||||
|
|
||||||
|
/*设备编号*/
|
||||||
|
private String serialNumber;
|
||||||
|
}
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
package com.maibu.core.mq.message;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author gsb
|
||||||
|
* @date 2024/6/20 10:53
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class ModbusPollMsg {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 下发指令
|
||||||
|
*/
|
||||||
|
private List<String> commandList;
|
||||||
|
/**
|
||||||
|
* 服务端类型
|
||||||
|
*/
|
||||||
|
private Integer serverType;
|
||||||
|
/**
|
||||||
|
* 产品id
|
||||||
|
*/
|
||||||
|
private Long productId;
|
||||||
|
/**
|
||||||
|
* 设备编码
|
||||||
|
*/
|
||||||
|
private String serialNumber;
|
||||||
|
|
||||||
|
private String transport;
|
||||||
|
}
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
package com.maibu.core.mq.message;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author bill
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class MqttBo {
|
||||||
|
|
||||||
|
/*主题*/
|
||||||
|
private String topic;
|
||||||
|
/*数据*/
|
||||||
|
private String data;
|
||||||
|
/*消息质量*/
|
||||||
|
private int qos = 1;
|
||||||
|
/*发送方向*/
|
||||||
|
private String direction;
|
||||||
|
/*时间*/
|
||||||
|
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
|
||||||
|
private Date ts;
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
package com.maibu.core.mq.message;
|
||||||
|
|
||||||
|
import com.maibu.core.protocol.modbus.ModbusCode;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author gsb
|
||||||
|
* @date 2022/12/9 10:15
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class PropRead {
|
||||||
|
|
||||||
|
/**设备编号*/
|
||||||
|
private String serialNumber;
|
||||||
|
/**寄存器起始地址*/
|
||||||
|
private int address;
|
||||||
|
/**
|
||||||
|
* 读取寄存器个数
|
||||||
|
*/
|
||||||
|
private int count;
|
||||||
|
/**数据结果长度计算值*/
|
||||||
|
private int length;
|
||||||
|
/**
|
||||||
|
* 从机地址
|
||||||
|
*/
|
||||||
|
private int slaveId;
|
||||||
|
/**
|
||||||
|
* 读取个数
|
||||||
|
*/
|
||||||
|
private int quantity;
|
||||||
|
/**
|
||||||
|
* 数据
|
||||||
|
*/
|
||||||
|
private String data;
|
||||||
|
/**
|
||||||
|
* 功能码
|
||||||
|
*/
|
||||||
|
private ModbusCode code;
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
package com.maibu.core.mq.message;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 协议bean
|
||||||
|
* @author gsb
|
||||||
|
* @date 2022/10/25 14:54
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class ProtocolDto {
|
||||||
|
|
||||||
|
/**协议编号*/
|
||||||
|
private String code;
|
||||||
|
private String name;
|
||||||
|
/*外部协议url*/
|
||||||
|
private String protocolUrl;
|
||||||
|
private String description;
|
||||||
|
/**协议类型 协议类型 0:系统协议 1:jar,2.js,3.c*/
|
||||||
|
private Integer protocolType;
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
package com.maibu.core.mq.message;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 网关子设备model
|
||||||
|
* @author gsb
|
||||||
|
* @date 2022/10/10 10:18
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class SubDeviceMessage {
|
||||||
|
/*子设备编号或编码*/
|
||||||
|
private String serialNumber;
|
||||||
|
/*数据*/
|
||||||
|
private byte[] data;
|
||||||
|
/*消息id*/
|
||||||
|
private String messageId;
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
package com.maibu.core.mq.ota;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* OTA升级回复model
|
||||||
|
* @author gsb
|
||||||
|
* @date 2022/10/24 17:20
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@JsonInclude(JsonInclude.Include.NON_EMPTY)
|
||||||
|
public class OtaReplyMessage {
|
||||||
|
|
||||||
|
private Long taskId;
|
||||||
|
private BigDecimal version;
|
||||||
|
private int status;
|
||||||
|
private int progress;
|
||||||
|
}
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
package com.maibu.core.mq.ota;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* OTA远程升级
|
||||||
|
* @author gsb
|
||||||
|
* @date 2022/10/10 10:22
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@Builder
|
||||||
|
@JsonInclude(JsonInclude.Include.NON_EMPTY)
|
||||||
|
public class OtaUpgradeBo {
|
||||||
|
|
||||||
|
// 设备编码
|
||||||
|
private String serialNumber;
|
||||||
|
// 升级任务ID
|
||||||
|
private Long taskId;
|
||||||
|
// 消息内容
|
||||||
|
private byte[] msg;
|
||||||
|
// 设备状态
|
||||||
|
private int status;
|
||||||
|
// topic
|
||||||
|
private String topicName;
|
||||||
|
// 固件包版本
|
||||||
|
private BigDecimal version;
|
||||||
|
// 固件包http地址
|
||||||
|
private String url;
|
||||||
|
// 固件包分包传输大小
|
||||||
|
private int packageSize;
|
||||||
|
// 固件包传输偏移量
|
||||||
|
private int offset;
|
||||||
|
// 升级进度
|
||||||
|
private int progress;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,63 @@
|
|||||||
|
package com.maibu.core.mq.ota;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||||
|
import com.maibu.utils.DateUtils;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.concurrent.Delayed;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ota升级发送,实现Delayed延时接口
|
||||||
|
*
|
||||||
|
* @author bill
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class OtaUpgradeDelayTask implements Delayed {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 固件id
|
||||||
|
*/
|
||||||
|
private Long firmwareId;
|
||||||
|
/**
|
||||||
|
* 1:指定产品 2:指定设备
|
||||||
|
*/
|
||||||
|
private Long upgradeType;
|
||||||
|
|
||||||
|
private List<String> devices;
|
||||||
|
/**
|
||||||
|
* 任务id
|
||||||
|
*/
|
||||||
|
private Long taskId;
|
||||||
|
/**
|
||||||
|
* 开始升级时间
|
||||||
|
*/
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
|
||||||
|
private Date startTime;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置延迟执行时间 开始升级时间 -当前时间
|
||||||
|
*
|
||||||
|
* @param unit
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public long getDelay(TimeUnit unit) {
|
||||||
|
return startTime.getTime() - DateUtils.getTimestamp();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int compareTo(Delayed o) {
|
||||||
|
OtaUpgradeDelayTask delayTask = (OtaUpgradeDelayTask) o;
|
||||||
|
//比较
|
||||||
|
long diff = this.startTime.getTime() - delayTask.startTime.getTime();
|
||||||
|
if (diff <= 0) {
|
||||||
|
return -1;
|
||||||
|
} else {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,36 +0,0 @@
|
|||||||
package com.maibu.core.ota;
|
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.annotation.IdType;
|
|
||||||
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 lombok.Data;
|
|
||||||
import lombok.EqualsAndHashCode;
|
|
||||||
|
|
||||||
|
|
||||||
@EqualsAndHashCode(callSuper = true)
|
|
||||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
|
||||||
@Data
|
|
||||||
@TableName("iot_ota_firmware")
|
|
||||||
public class DeviceOtaFirmware extends BaseDO {
|
|
||||||
private static final long serialVersionUID = 1L;
|
|
||||||
|
|
||||||
@TableId(type = IdType.AUTO)
|
|
||||||
private Long id;
|
|
||||||
|
|
||||||
private String version; //版本号
|
|
||||||
|
|
||||||
private String fileName; //文件名
|
|
||||||
|
|
||||||
private String minioObjectName; //服务器文件名
|
|
||||||
|
|
||||||
private String fileUrl; //存放地址
|
|
||||||
|
|
||||||
private String deviceType;
|
|
||||||
|
|
||||||
private String fileSize;
|
|
||||||
|
|
||||||
private String description;
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,37 +0,0 @@
|
|||||||
package com.maibu.core.ota;
|
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.annotation.IdType;
|
|
||||||
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.OtaOperate;
|
|
||||||
|
|
||||||
import lombok.Data;
|
|
||||||
import lombok.EqualsAndHashCode;
|
|
||||||
|
|
||||||
@EqualsAndHashCode(callSuper = true)
|
|
||||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
|
||||||
@Data
|
|
||||||
@TableName(value = "iot_ota_operate_record", autoResultMap = true)
|
|
||||||
public class DeviceOtaOperateRecord extends BaseDO {
|
|
||||||
private static final long serialVersionUID = 1L;
|
|
||||||
|
|
||||||
@TableId(type = IdType.AUTO)
|
|
||||||
private Long id;
|
|
||||||
|
|
||||||
private OtaOperate operateType; // 操作类型
|
|
||||||
|
|
||||||
private String fileName; // 名称
|
|
||||||
|
|
||||||
private Long firmwareId; // id
|
|
||||||
|
|
||||||
private String deviceId; // 名称
|
|
||||||
|
|
||||||
private String deviceType;
|
|
||||||
|
|
||||||
private String preVersion;
|
|
||||||
|
|
||||||
private String nowVersion;
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,45 @@
|
|||||||
|
package com.maibu.core.ota;
|
||||||
|
|
||||||
|
import com.maibu.exception.ServiceException;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@AllArgsConstructor
|
||||||
|
public enum OtaPackageCode {
|
||||||
|
|
||||||
|
OTA_01("查询产品工装号",(byte) 0x01),
|
||||||
|
OTA_0A("OTA升级启动",(byte) 0x0A),
|
||||||
|
OTA_0B("OTA升级包传输",(byte) 0x0B)
|
||||||
|
;
|
||||||
|
|
||||||
|
private String desc;
|
||||||
|
private byte code;
|
||||||
|
|
||||||
|
public static OtaPackageCode getInstance(int code) {
|
||||||
|
switch ((byte)code) {
|
||||||
|
case 0x01:
|
||||||
|
return OTA_01;
|
||||||
|
case 0x0A:
|
||||||
|
return OTA_0A;
|
||||||
|
case 0x0B:
|
||||||
|
return OTA_0B;
|
||||||
|
default:
|
||||||
|
throw new ServiceException("功能码[" + code + "],未定义");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getDes(int code){
|
||||||
|
switch ((byte)code) {
|
||||||
|
case 0x01:
|
||||||
|
return OTA_01.desc;
|
||||||
|
case 0x0A:
|
||||||
|
return OTA_0A.desc;
|
||||||
|
case 0x0B:
|
||||||
|
return OTA_0B.desc;
|
||||||
|
default:
|
||||||
|
return "UNKOWN";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
package com.maibu.enums;
|
|
||||||
|
|
||||||
import lombok.AllArgsConstructor;
|
|
||||||
import lombok.Getter;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 设备回调状态
|
|
||||||
*
|
|
||||||
* @author bill
|
|
||||||
*/
|
|
||||||
@Getter
|
|
||||||
@AllArgsConstructor
|
|
||||||
public enum DeviceStatusEnum {
|
|
||||||
|
|
||||||
working("1", "工作中"),
|
|
||||||
idle("2", "空闲中"),
|
|
||||||
offline("3", "离线"),
|
|
||||||
charging("4", "充电中"),
|
|
||||||
error("5", "故障");
|
|
||||||
|
|
||||||
String code;
|
|
||||||
String message;
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -6,6 +6,8 @@ import java.util.List;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import org.springframework.util.CollectionUtils;
|
||||||
|
|
||||||
import com.influxdb.query.FluxRecord;
|
import com.influxdb.query.FluxRecord;
|
||||||
import com.influxdb.query.FluxTable;
|
import com.influxdb.query.FluxTable;
|
||||||
import com.maibu.influxdb.inter.InfluxField;
|
import com.maibu.influxdb.inter.InfluxField;
|
||||||
|
|||||||
@@ -1,11 +0,0 @@
|
|||||||
package com.maibu.mapper;
|
|
||||||
|
|
||||||
import com.maibu.core.ota.DeviceOtaFirmware;
|
|
||||||
import com.maibu.mybatis.mapper.BaseMapperX;
|
|
||||||
import org.springframework.stereotype.Repository;
|
|
||||||
|
|
||||||
|
|
||||||
@Repository
|
|
||||||
public interface DeviceOtaFirmwareMapper extends BaseMapperX<DeviceOtaFirmware> {
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
package com.maibu.mapper;
|
|
||||||
|
|
||||||
import com.maibu.core.ota.DeviceOtaOperateRecord;
|
|
||||||
import com.maibu.mybatis.mapper.BaseMapperX;
|
|
||||||
import org.springframework.stereotype.Repository;
|
|
||||||
|
|
||||||
|
|
||||||
@Repository
|
|
||||||
public interface DeviceOtaOperateRecordMapper extends BaseMapperX<DeviceOtaOperateRecord> {
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
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<LocationMessage> {
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,16 +1,13 @@
|
|||||||
package com.maibu.memory;
|
package com.maibu.memory;
|
||||||
|
|
||||||
|
|
||||||
import cn.hutool.core.util.ObjectUtil;
|
import cn.hutool.core.util.ObjectUtil;
|
||||||
import com.maibu.core.business.device.Connector;
|
import com.maibu.core.business.device.Connector;
|
||||||
import com.maibu.core.business.device.NettyDevice;
|
import com.maibu.core.business.device.NettyDevice;
|
||||||
import com.maibu.core.enums.ConnectorStatus;
|
import com.maibu.core.enums.ConnectorStatus;
|
||||||
import com.maibu.core.enums.ConnectorType;
|
import com.maibu.core.enums.ConnectorType;
|
||||||
import com.maibu.utils.json.JsonUtils;
|
|
||||||
|
|
||||||
import io.netty.channel.Channel;
|
import io.netty.channel.Channel;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
@@ -27,22 +24,19 @@ import java.util.stream.Collectors;
|
|||||||
*/
|
*/
|
||||||
@Component
|
@Component
|
||||||
@Data
|
@Data
|
||||||
@Slf4j
|
|
||||||
public class DeviceSessionManager {
|
public class DeviceSessionManager {
|
||||||
|
|
||||||
private static final Logger logger = LoggerFactory.getLogger(DeviceSessionManager.class);
|
private static final Logger logger = LoggerFactory.getLogger(DeviceSessionManager.class);
|
||||||
// 设备ID -> 设备对象(业务实体)
|
// 设备ID -> 设备对象(业务实体)
|
||||||
private final ConcurrentHashMap<String, NettyDevice> deviceMap = new ConcurrentHashMap<>();
|
private final ConcurrentHashMap<String, NettyDevice> deviceMap = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
// 当前设备的控制权在哪 登录的账号 deviceId(下位机) -> token key 唯一保证一个deviceId 只有一个控制权
|
|
||||||
private final ConcurrentHashMap<String, String> controllerMap = new ConcurrentHashMap<>();
|
|
||||||
|
|
||||||
// 设备ID -> Channel(通信通道)
|
// 设备ID -> Channel(通信通道)
|
||||||
private final ConcurrentHashMap<String, Channel> channelMap = new ConcurrentHashMap<>();
|
private final ConcurrentHashMap<String, Channel> channelMap = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
// Channel -> 设备ID(反查)
|
// Channel -> 设备ID(反查)
|
||||||
private final ConcurrentHashMap<Channel, String> channelToDeviceIdMap = new ConcurrentHashMap<>();
|
private final ConcurrentHashMap<Channel, String> channelToDeviceIdMap = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
|
|
||||||
public void clearChannelToDeviceIdMap(String deviceId) {
|
public void clearChannelToDeviceIdMap(String deviceId) {
|
||||||
if (StringUtils.isEmpty(deviceId) || CollectionUtils.isEmpty(channelToDeviceIdMap)) {
|
if (StringUtils.isEmpty(deviceId) || CollectionUtils.isEmpty(channelToDeviceIdMap)) {
|
||||||
return;
|
return;
|
||||||
@@ -70,6 +64,7 @@ public class DeviceSessionManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 注册设备连接(设备上线)
|
* 注册设备连接(设备上线)
|
||||||
*
|
*
|
||||||
@@ -77,8 +72,7 @@ public class DeviceSessionManager {
|
|||||||
* @param channel 通信通道
|
* @param channel 通信通道
|
||||||
* @param deviceType 设备类型(MASTER/SLAVE)
|
* @param deviceType 设备类型(MASTER/SLAVE)
|
||||||
*/
|
*/
|
||||||
public void registerDevice(String deviceId, Channel channel, ConnectorType deviceType, ConnectorStatus status,
|
public void registerDevice(String deviceId, Channel channel, ConnectorType deviceType, ConnectorStatus status, String slaveId) {
|
||||||
String slaveId) {
|
|
||||||
NettyDevice nettyDevice = deviceMap.computeIfAbsent(deviceId, id -> new NettyDevice(id, deviceType));
|
NettyDevice nettyDevice = deviceMap.computeIfAbsent(deviceId, id -> new NettyDevice(id, deviceType));
|
||||||
nettyDevice.setChannel(channel);
|
nettyDevice.setChannel(channel);
|
||||||
nettyDevice.setConnectorStatus(status); // 默认上线即ACTIVE
|
nettyDevice.setConnectorStatus(status); // 默认上线即ACTIVE
|
||||||
@@ -90,20 +84,6 @@ public class DeviceSessionManager {
|
|||||||
System.out.println("Registered device: " + deviceId + " type: " + deviceType);
|
System.out.println("Registered device: " + deviceId + " type: " + deviceType);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 注册下位机设备
|
|
||||||
*
|
|
||||||
* @param deviceId 设备ID
|
|
||||||
*/
|
|
||||||
public void registerSlaveDevice(String deviceId, ConnectorStatus status, String slaveId) {
|
|
||||||
NettyDevice nettyDevice = deviceMap.computeIfAbsent(deviceId, id -> new NettyDevice(id, ConnectorType.SLAVE));
|
|
||||||
nettyDevice.setConnectorStatus(status); // 默认上线即ACTIVE
|
|
||||||
nettyDevice.setCurrentSlaveId(slaveId);
|
|
||||||
nettyDevice.setLatestLoginTime(System.currentTimeMillis());
|
|
||||||
deviceMap.put(deviceId, nettyDevice);
|
|
||||||
logger.debug("Registered slave device:{},type:{}", deviceId, ConnectorType.SLAVE);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 上位机绑定下位机,建立双向绑定关系
|
* 上位机绑定下位机,建立双向绑定关系
|
||||||
*
|
*
|
||||||
@@ -112,8 +92,7 @@ public class DeviceSessionManager {
|
|||||||
*/
|
*/
|
||||||
public void bindConnector(String masterId, String slaveId) {
|
public void bindConnector(String masterId, String slaveId) {
|
||||||
NettyDevice master = deviceMap.get(masterId);
|
NettyDevice master = deviceMap.get(masterId);
|
||||||
if (master == null)
|
if (master == null) return;
|
||||||
return;
|
|
||||||
NettyDevice slave = deviceMap.computeIfAbsent(slaveId, id -> new NettyDevice(id, ConnectorType.SLAVE));
|
NettyDevice slave = deviceMap.computeIfAbsent(slaveId, id -> new NettyDevice(id, ConnectorType.SLAVE));
|
||||||
master.addConnectedDevice(slave);
|
master.addConnectedDevice(slave);
|
||||||
System.out.println("Bind connectors for master " + masterId + " and slave " + slaveId);
|
System.out.println("Bind connectors for master " + masterId + " and slave " + slaveId);
|
||||||
@@ -126,62 +105,6 @@ public class DeviceSessionManager {
|
|||||||
return deviceMap.get(deviceId);
|
return deviceMap.get(deviceId);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取有控制权的 客户端
|
|
||||||
*/
|
|
||||||
public String getMaster(String deviceId) {
|
|
||||||
return controllerMap.get(deviceId);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取客户端当前 控制的设备
|
|
||||||
*/
|
|
||||||
public String getControl(String token) {
|
|
||||||
for (String key : controllerMap.keySet()) {
|
|
||||||
if (controllerMap.get(key).equals(token)) {
|
|
||||||
return controllerMap.get(token);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void lock(String deviceId, String token) {
|
|
||||||
if (!StringUtils.isEmpty(deviceId) && !StringUtils.isEmpty(token)) {
|
|
||||||
controllerMap.put(deviceId, token);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean unLock(String token) {
|
|
||||||
if (!StringUtils.isEmpty(token)) {
|
|
||||||
Iterator<String> iterator = controllerMap.keySet().iterator();
|
|
||||||
while (iterator.hasNext()) {
|
|
||||||
String key = iterator.next();
|
|
||||||
if (controllerMap.get(key).equals(token)) {
|
|
||||||
iterator.remove();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean unLock(String deviceId, String token, boolean force) {
|
|
||||||
if (!StringUtils.isEmpty(deviceId)) {
|
|
||||||
if (force) {
|
|
||||||
controllerMap.remove(deviceId);
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
String nowToken = controllerMap.get(deviceId);
|
|
||||||
if (!StringUtils.isEmpty(token) && nowToken.equals(token)) {
|
|
||||||
controllerMap.remove(deviceId);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// 模糊匹配
|
// 模糊匹配
|
||||||
public List<NettyDevice> getDevicesLike(String query) {
|
public List<NettyDevice> getDevicesLike(String query) {
|
||||||
return deviceMap.values().stream()
|
return deviceMap.values().stream()
|
||||||
@@ -189,31 +112,32 @@ public class DeviceSessionManager {
|
|||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public List<NettyDevice> getSlaveControl(String slaveId) {
|
public List<NettyDevice> getSlaveControl(String slaveId) {
|
||||||
// 获取所有连接的主机 且是active状态的
|
// 获取所有连接的主机 且是active状态的
|
||||||
return deviceMap.values().stream()
|
return deviceMap.values().stream()
|
||||||
.filter(device -> Objects.equals(device.getCurrentSlaveId(), slaveId)
|
.filter(device -> ObjectUtil.equals(device.getCurrentSlaveId(), slaveId)
|
||||||
&& ConnectorStatus.ACTIVE.equals(device.getConnectorStatus()))
|
&& ConnectorStatus.ACTIVE.equals(device.getConnectorStatus()))
|
||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public List<NettyDevice> getAllSlaveControl(String slaveId) {
|
public List<NettyDevice> getAllSlaveControl(String slaveId) {
|
||||||
// 获取所有连接的主机 不区分状态
|
// 获取所有连接的主机 不区分状态
|
||||||
return deviceMap.values().stream()
|
return deviceMap.values().stream()
|
||||||
.filter(device -> !StringUtils.isEmpty(device.getCurrentSlaveId())
|
.filter(device -> ObjectUtil.equals(device.getCurrentSlaveId(), slaveId))
|
||||||
&& Objects.equals(device.getCurrentSlaveId(), slaveId)
|
|
||||||
&& device.getDeviceType().equals(ConnectorType.MASTER))
|
|
||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
}
|
}
|
||||||
|
|
||||||
public NettyDevice getCurrentControl(String slaveId) {
|
public NettyDevice getCurrentControl(String slaveId) {
|
||||||
// 获取所有连接的主机 不区分状态
|
// 获取所有连接的主机 不区分状态
|
||||||
return deviceMap.values().stream()
|
return deviceMap.values().stream()
|
||||||
.filter(device -> Objects.equals(device.getCurrentSlaveId(), slaveId)
|
.filter(device -> ObjectUtil.equals(device.getCurrentSlaveId(), slaveId)
|
||||||
&& ConnectorStatus.ACTIVE.equals(device.getConnectorStatus()))
|
&& ConnectorStatus.ACTIVE.equals(device.getConnectorStatus()))
|
||||||
.findFirst().orElse(null);
|
.findFirst().orElse(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// 模糊匹配
|
/// 模糊匹配
|
||||||
public NettyDevice getUserControl(String userName) {
|
public NettyDevice getUserControl(String userName) {
|
||||||
return deviceMap.values().stream()
|
return deviceMap.values().stream()
|
||||||
@@ -222,6 +146,7 @@ public class DeviceSessionManager {
|
|||||||
.findFirst().orElse(null);
|
.findFirst().orElse(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 根据设备ID获取Channel
|
* 根据设备ID获取Channel
|
||||||
*/
|
*/
|
||||||
@@ -236,6 +161,7 @@ public class DeviceSessionManager {
|
|||||||
return channelToDeviceIdMap.get(channel);
|
return channelToDeviceIdMap.get(channel);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 根据从机查控制的主机
|
* 根据从机查控制的主机
|
||||||
*/
|
*/
|
||||||
@@ -248,8 +174,7 @@ public class DeviceSessionManager {
|
|||||||
* 根据从机查所有主机
|
* 根据从机查所有主机
|
||||||
*/
|
*/
|
||||||
public List<NettyDevice> getMastersBySlaveId(String slaveId) {
|
public List<NettyDevice> getMastersBySlaveId(String slaveId) {
|
||||||
return deviceMap.values().stream().filter(x -> Objects.equals(x.getCurrentSlaveId(), slaveId))
|
return deviceMap.values().stream().filter(x -> Objects.equals(x.getCurrentSlaveId(), slaveId)).collect(Collectors.toList());
|
||||||
.collect(Collectors.toList());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -257,25 +182,18 @@ public class DeviceSessionManager {
|
|||||||
*/
|
*/
|
||||||
public void removeDevice(String deviceId) {
|
public void removeDevice(String deviceId) {
|
||||||
NettyDevice nettyDevice = deviceMap.remove(deviceId);
|
NettyDevice nettyDevice = deviceMap.remove(deviceId);
|
||||||
// Channel channel = channelMap.remove(deviceId);
|
// Channel channel = channelMap.remove(deviceId);
|
||||||
clearChannelToDeviceIdMap(deviceId);
|
clearChannelToDeviceIdMap(deviceId);
|
||||||
// if (channel != null) {
|
// if (channel != null) {
|
||||||
// channelToDeviceIdMap.remove(channel);
|
// channelToDeviceIdMap.remove(channel);
|
||||||
// channel.close();
|
// channel.close();
|
||||||
// }
|
// }
|
||||||
if (nettyDevice != null) {
|
if (nettyDevice != null) {
|
||||||
// 仅当设备是上位机时,才解绑绑定关系
|
// 仅当设备是上位机时,才解绑绑定关系
|
||||||
if (nettyDevice.getDeviceType() == ConnectorType.MASTER) {
|
if (nettyDevice.getDeviceType() == ConnectorType.MASTER) {
|
||||||
for (Connector connected : new HashSet<>(nettyDevice.getConnectedConnectors())) {
|
for (Connector connected : new HashSet<>(nettyDevice.getConnectedConnectors())) {
|
||||||
nettyDevice.removeConnectedDevice(connected);
|
nettyDevice.removeConnectedDevice(connected);
|
||||||
}
|
}
|
||||||
// 清理channel和状态
|
|
||||||
nettyDevice.setChannel(null);
|
|
||||||
Channel channel = channelMap.remove(deviceId);
|
|
||||||
if (channel != null) {
|
|
||||||
channelToDeviceIdMap.remove(channel);
|
|
||||||
channel.close();
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
// 如果是下位机,则保留绑定关系,只清理channel和状态
|
// 如果是下位机,则保留绑定关系,只清理channel和状态
|
||||||
nettyDevice.setChannel(null);
|
nettyDevice.setChannel(null);
|
||||||
@@ -288,6 +206,7 @@ public class DeviceSessionManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 判断设备是否在线
|
* 判断设备是否在线
|
||||||
*/
|
*/
|
||||||
@@ -312,23 +231,5 @@ public class DeviceSessionManager {
|
|||||||
return nettyDevice != null && nettyDevice.canReceive();
|
return nettyDevice != null && nettyDevice.canReceive();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取客户端当前 控制的设备
|
|
||||||
*/
|
|
||||||
public String getDeviceByTaskId(Long taskId) {
|
|
||||||
if (taskId == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
log.debug("sendMessage deviceMap:{},taskId={}", JsonUtils.toJsonString(deviceMap), taskId);
|
|
||||||
for (String key : deviceMap.keySet()) {
|
|
||||||
NettyDevice nettyDevice = deviceMap.get(key);
|
|
||||||
log.debug("sendMessage currentTaskId:{},equal {}", JsonUtils.toJsonString(nettyDevice.getCurrentTaskId()),
|
|
||||||
Objects.equals(nettyDevice.getCurrentTaskId(), taskId));
|
|
||||||
if (nettyDevice != null && Objects.equals(nettyDevice.getCurrentTaskId(), taskId)) {
|
|
||||||
return nettyDevice.getConnectorId();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,16 +1,17 @@
|
|||||||
package com.maibu.memory;
|
package com.maibu.memory;
|
||||||
|
|
||||||
import com.maibu.constant.Constant;
|
|
||||||
import com.maibu.core.business.Device;
|
import com.maibu.core.business.Device;
|
||||||
import com.maibu.core.business.IoTCommonDevice;
|
import com.maibu.core.business.IoTCommonDevice;
|
||||||
import com.maibu.core.business.path.LatAndLngEntity;
|
|
||||||
import com.maibu.influxdb.util.InfluxDBUtil;
|
import com.maibu.influxdb.util.InfluxDBUtil;
|
||||||
import com.maibu.mqtt.*;
|
import com.maibu.mqtt.MqttClientUtil;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
import org.springframework.util.CollectionUtils;
|
import org.springframework.util.CollectionUtils;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
@Component
|
@Component
|
||||||
@@ -25,13 +26,10 @@ public class GlobalMemory {
|
|||||||
// key:orgId - siteId
|
// key:orgId - siteId
|
||||||
public static ConcurrentHashMap<Long, Map<Long, SiteMemory>> orgAttrs = new ConcurrentHashMap<>();
|
public static ConcurrentHashMap<Long, Map<Long, SiteMemory>> orgAttrs = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
public static ConcurrentHashMap<Long, List<LatAndLngEntity>> taskPathMap = new ConcurrentHashMap<>();
|
|
||||||
|
|
||||||
public static InfluxDBUtil influxDBUtil;
|
public static InfluxDBUtil influxDBUtil;
|
||||||
|
|
||||||
// public static MqttClientUtil mqttClientUtil;
|
public static MqttClientUtil mqttClientUtil;
|
||||||
|
|
||||||
public static CustomMqttDeviceMonitor customMqttDeviceMonitor = null; //这里面包含了 连我们自己的mqtt 和外部的一些设备,自己的用clientId 是固定的
|
|
||||||
|
|
||||||
|
|
||||||
public static SiteMemory getSiteMemory(Long orgId, Long siteId) {
|
public static SiteMemory getSiteMemory(Long orgId, Long siteId) {
|
||||||
@@ -54,7 +52,7 @@ public class GlobalMemory {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 新增场站内存
|
* 新增场站内存
|
||||||
*
|
*
|
||||||
* @param orgId
|
* @param orgId
|
||||||
* @param siteId
|
* @param siteId
|
||||||
* @param siteMemory
|
* @param siteMemory
|
||||||
@@ -74,7 +72,7 @@ public class GlobalMemory {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 删除
|
* 删除
|
||||||
*
|
*
|
||||||
* @param orgId
|
* @param orgId
|
||||||
* @param siteId
|
* @param siteId
|
||||||
*/
|
*/
|
||||||
@@ -87,36 +85,4 @@ public class GlobalMemory {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void initMqttDeviceMonitor(String mqttHostUrl, String mqttClientId, String mqttUsername, String mqttPassword) {
|
|
||||||
if (customMqttDeviceMonitor == null) {
|
|
||||||
// 1. 创建 MQTT 监控器和消息处理器
|
|
||||||
customMqttDeviceMonitor = new CustomMqttDeviceMonitor();
|
|
||||||
// customMqttDeviceMonitor.registerHandler(new GenericPropertyMessageHandler());
|
|
||||||
customMqttDeviceMonitor.registerHandler(new HostMessageHandler()); //专门处理上位机的
|
|
||||||
// customMqttDeviceMonitor.registerHandler(new ActionMessageHandler());
|
|
||||||
|
|
||||||
//单独注册 对接上位机的
|
|
||||||
// 注册设备到 MQTT 监控器
|
|
||||||
CustomMqttDeviceConfig deviceConfig = new CustomMqttDeviceConfig();
|
|
||||||
deviceConfig.setDeviceKey(mqttClientId);
|
|
||||||
deviceConfig.setBrokerUrl(mqttHostUrl);
|
|
||||||
deviceConfig.setClientId(mqttClientId);
|
|
||||||
deviceConfig.setUsername(mqttUsername);
|
|
||||||
deviceConfig.setPassword(mqttPassword);
|
|
||||||
//TODO 添加所有需要订阅的
|
|
||||||
deviceConfig.setSubscribeTopics(Arrays.asList(
|
|
||||||
MqttTopic.MOWER_HEARTBEAT,//心跳
|
|
||||||
MqttTopic.MOWER_WILDCARD_LOCATION,//位置 经纬度
|
|
||||||
MqttTopic.MOWER_WILDCARD_TASK_ROUTE, //路径回复
|
|
||||||
MqttTopic.MOWER_WILDCARD_TASK_STATUS,//任务状态
|
|
||||||
MqttTopic.MOWER_WILDCARD_ERROR,//错误
|
|
||||||
MqttTopic.MOWER_WILDCARD_REALTIME, //状态消息
|
|
||||||
MqttTopic.MOWER_WILDCARD_TASK_TARGET_REPLY, //路径规划下发回复
|
|
||||||
MqttTopic.MOWER_OTA_RESULT_POST
|
|
||||||
));
|
|
||||||
deviceConfig.setHandlerType(Constant.mqttHandleKey); //唯一的 用于处理上位机mqtt的
|
|
||||||
customMqttDeviceMonitor.registerDevice(deviceConfig);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ import java.util.Objects;
|
|||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
import com.maibu.core.business.*;
|
import com.maibu.core.business.*;
|
||||||
import com.maibu.core.business.dto.DeviceMapPushDTO;
|
|
||||||
import com.maibu.mqtt.CustomMqttDeviceMonitor;
|
import com.maibu.mqtt.CustomMqttDeviceMonitor;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.eclipse.paho.client.mqttv3.MqttClient;
|
import org.eclipse.paho.client.mqttv3.MqttClient;
|
||||||
@@ -31,6 +30,8 @@ public class SiteMemory {
|
|||||||
|
|
||||||
public SysSite sysSite;
|
public SysSite sysSite;
|
||||||
|
|
||||||
|
public CustomMqttDeviceMonitor CustomMqttDeviceMonitor;
|
||||||
|
|
||||||
public static final ConcurrentHashMap<String, MqttClient> mqttClientMap = new ConcurrentHashMap<>();
|
public static final ConcurrentHashMap<String, MqttClient> mqttClientMap = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
public static final ConcurrentHashMap<Long, OrderModel> orderModelMap = new ConcurrentHashMap<>();
|
public static final ConcurrentHashMap<Long, OrderModel> orderModelMap = new ConcurrentHashMap<>();
|
||||||
@@ -54,42 +55,6 @@ public class SiteMemory {
|
|||||||
// key deviceId execute
|
// key deviceId execute
|
||||||
public static ConcurrentHashMap<String, DevicePlanTask> devicePlanTaskExecuteMap = new ConcurrentHashMap<>();
|
public static ConcurrentHashMap<String, DevicePlanTask> devicePlanTaskExecuteMap = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
// 记录 设备上线后的运行数据 下线后清除并保存到数据库
|
|
||||||
public static ConcurrentHashMap<String, DeviceRunStatistics> deviceRunStatisticsMap = new ConcurrentHashMap<>();
|
|
||||||
|
|
||||||
public static ConcurrentHashMap<String, DeviceMapPushDTO> deviceMapPushMap = new ConcurrentHashMap<>();
|
|
||||||
|
|
||||||
public Map<String, DeviceMapPushDTO> getAllDeviceMapPush() {
|
|
||||||
return deviceMapPushMap;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void saveMapPushDTO(String deviceId, DeviceMapPushDTO dto) {
|
|
||||||
deviceMapPushMap.put(deviceId, dto);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void removeMapPushDTO(String deviceId) {
|
|
||||||
deviceMapPushMap.remove(deviceId);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void saveRunStatistics(DeviceRunStatistics deviceRunStatistics) {
|
|
||||||
if (deviceRunStatistics != null && !StringUtils.isEmpty(deviceRunStatistics.getDeviceId())) {
|
|
||||||
deviceRunStatisticsMap.put(deviceRunStatistics.getDeviceId(), deviceRunStatistics);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public DeviceRunStatistics getRunStatistics(String deviceId) {
|
|
||||||
if (!StringUtils.isEmpty(deviceId)) {
|
|
||||||
return deviceRunStatisticsMap.get(deviceId);
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void removeRunStatistics(String deviceId) {
|
|
||||||
if (!StringUtils.isEmpty(deviceId)) {
|
|
||||||
deviceRunStatisticsMap.remove(deviceId);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void saveDevice(Device device) {
|
public static void saveDevice(Device device) {
|
||||||
deviceMap.put(device.getSerialNumber(), device);
|
deviceMap.put(device.getSerialNumber(), device);
|
||||||
}
|
}
|
||||||
@@ -172,6 +137,7 @@ public class SiteMemory {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void saveDeviceRunParam(DeviceRunParam deviceRunParam) {
|
public void saveDeviceRunParam(DeviceRunParam deviceRunParam) {
|
||||||
deviceRunParamMap.put(deviceRunParam.getDeviceId(), deviceRunParam);
|
deviceRunParamMap.put(deviceRunParam.getDeviceId(), deviceRunParam);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,24 +1,17 @@
|
|||||||
package com.maibu.mqtt;
|
package com.maibu.mqtt;
|
||||||
|
|
||||||
import com.maibu.core.host.HeartBeatDTO;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.eclipse.paho.client.mqttv3.*;
|
import org.eclipse.paho.client.mqttv3.*;
|
||||||
import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence;
|
import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
import javax.annotation.PreDestroy;
|
import javax.annotation.PreDestroy;
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.concurrent.Executors;
|
import java.util.concurrent.Executors;
|
||||||
import java.util.concurrent.LinkedBlockingQueue;
|
|
||||||
import java.util.concurrent.ScheduledExecutorService;
|
import java.util.concurrent.ScheduledExecutorService;
|
||||||
import java.util.concurrent.ThreadFactory;
|
|
||||||
import java.util.concurrent.ThreadPoolExecutor;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 自定义外部设备 MQTT 订阅管理器
|
* 自定义外部设备 MQTT 订阅管理器
|
||||||
@@ -73,24 +66,6 @@ public class CustomMqttDeviceMonitor {
|
|||||||
*/
|
*/
|
||||||
private ScheduledExecutorService scheduler;
|
private ScheduledExecutorService scheduler;
|
||||||
|
|
||||||
private final ConcurrentHashMap<String, HeartBeatDTO> hearBeatMap = new ConcurrentHashMap<>();
|
|
||||||
|
|
||||||
private final ThreadPoolExecutor messageExecutor = new ThreadPoolExecutor(
|
|
||||||
4, 8, 30L, TimeUnit.SECONDS,
|
|
||||||
new LinkedBlockingQueue<>(256),
|
|
||||||
new ThreadFactory() {
|
|
||||||
private final AtomicInteger counter = new AtomicInteger(1);
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Thread newThread(Runnable r) {
|
|
||||||
Thread t = new Thread(r, "mqtt-message-worker-" + counter.getAndIncrement());
|
|
||||||
t.setDaemon(true);
|
|
||||||
return t;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
new ThreadPoolExecutor.CallerRunsPolicy()
|
|
||||||
);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 巡检间隔(秒)
|
* 巡检间隔(秒)
|
||||||
*/
|
*/
|
||||||
@@ -99,7 +74,7 @@ public class CustomMqttDeviceMonitor {
|
|||||||
// ==================== 消息处理器管理 ====================
|
// ==================== 消息处理器管理 ====================
|
||||||
|
|
||||||
|
|
||||||
public CustomMqttMessageHandler getMessageHandler(String key) {
|
public CustomMqttMessageHandler getMessageHandler(String key){
|
||||||
return handlerMap.get(key);
|
return handlerMap.get(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -177,25 +152,6 @@ public class CustomMqttDeviceMonitor {
|
|||||||
return client != null && client.isConnected();
|
return client != null && client.isConnected();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 保存心跳
|
|
||||||
*/
|
|
||||||
public void saveHeartBeat(String sn, HeartBeatDTO dto) {
|
|
||||||
hearBeatMap.put(sn, dto);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取心跳
|
|
||||||
*/
|
|
||||||
public HeartBeatDTO getHeartBeat(String sn) {
|
|
||||||
return hearBeatMap.get(sn);
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<HeartBeatDTO> getAllHeartBeat() {
|
|
||||||
return new ArrayList<>(hearBeatMap.values());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// ==================== 连接管理 ====================
|
// ==================== 连接管理 ====================
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -224,7 +180,6 @@ public class CustomMqttDeviceMonitor {
|
|||||||
if (scheduler != null) {
|
if (scheduler != null) {
|
||||||
scheduler.shutdown();
|
scheduler.shutdown();
|
||||||
}
|
}
|
||||||
messageExecutor.shutdown();
|
|
||||||
clientMap.keySet().forEach(this::disconnectDevice);
|
clientMap.keySet().forEach(this::disconnectDevice);
|
||||||
log.info("CustomMqttDeviceMonitor 已停止");
|
log.info("CustomMqttDeviceMonitor 已停止");
|
||||||
}
|
}
|
||||||
@@ -271,7 +226,7 @@ public class CustomMqttDeviceMonitor {
|
|||||||
public void messageArrived(String topic, MqttMessage message) {
|
public void messageArrived(String topic, MqttMessage message) {
|
||||||
String payload = new String(message.getPayload());
|
String payload = new String(message.getPayload());
|
||||||
log.debug("收到消息: deviceKey={}, topic={}, payload={}", deviceKey, topic, payload);
|
log.debug("收到消息: deviceKey={}, topic={}, payload={}", deviceKey, topic, payload);
|
||||||
messageExecutor.submit(() -> dispatchMessage(deviceKey, topic, payload, config));
|
dispatchMessage(deviceKey, topic, payload, config);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -418,7 +373,6 @@ public class CustomMqttDeviceMonitor {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 向指定设备发布消息(指定 QoS)
|
* 向指定设备发布消息(指定 QoS)
|
||||||
* 异步投递到线程池执行,避免阻塞 MQTT 回调线程
|
|
||||||
*/
|
*/
|
||||||
public void publish(String deviceKey, String topic, String payload, int qos) throws MqttException {
|
public void publish(String deviceKey, String topic, String payload, int qos) throws MqttException {
|
||||||
MqttClient client = clientMap.get(deviceKey);
|
MqttClient client = clientMap.get(deviceKey);
|
||||||
@@ -429,7 +383,7 @@ public class CustomMqttDeviceMonitor {
|
|||||||
MqttMessage message = new MqttMessage(payload.getBytes());
|
MqttMessage message = new MqttMessage(payload.getBytes());
|
||||||
message.setQos(qos);
|
message.setQos(qos);
|
||||||
client.publish(topic, message);
|
client.publish(topic, message);
|
||||||
log.debug("发布消息: deviceKey={}, topic={},payload:{}", deviceKey, topic, payload);
|
log.debug("发布消息: deviceKey={}, topic={}", deviceKey, topic);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -1,526 +0,0 @@
|
|||||||
package com.maibu.mqtt;
|
|
||||||
|
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
|
||||||
import com.maibu.constant.Constant;
|
|
||||||
import com.maibu.constant.NettyCacheKey;
|
|
||||||
import com.maibu.core.business.DeviceRunStatistics;
|
|
||||||
import com.maibu.core.business.device.DeviceStatusDetail;
|
|
||||||
import com.maibu.core.business.device.NettyDevice;
|
|
||||||
import com.maibu.core.business.dto.DeviceMapPushDTO;
|
|
||||||
import com.maibu.core.business.dto.WebDeviceTaskStatusMessageDTO;
|
|
||||||
import com.maibu.core.business.dto.WebStatusMessageDTO;
|
|
||||||
import com.maibu.core.business.inter.WebsocketMesDispather;
|
|
||||||
import com.maibu.core.enums.DeviceTaskStaus;
|
|
||||||
import com.maibu.core.enums.MesType;
|
|
||||||
import com.maibu.core.host.*;
|
|
||||||
import com.maibu.core.redis.RedisCache;
|
|
||||||
import com.maibu.enums.DeviceStatusEnum;
|
|
||||||
import com.maibu.memory.DeviceSessionManager;
|
|
||||||
import com.maibu.memory.GlobalMemory;
|
|
||||||
import com.maibu.memory.SiteMemory;
|
|
||||||
import com.maibu.utils.StringUtils;
|
|
||||||
import com.maibu.utils.json.JsonUtils;
|
|
||||||
import com.maibu.utils.spring.SpringUtils;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
import org.eclipse.paho.client.mqttv3.MqttException;
|
|
||||||
import org.springframework.util.CollectionUtils;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* mqtt相关的 上位机处理器
|
|
||||||
*/
|
|
||||||
@Slf4j
|
|
||||||
public class HostMessageHandler implements CustomMqttMessageHandler {
|
|
||||||
|
|
||||||
private final DeviceSessionManager deviceSessionManager = SpringUtils.getBean(DeviceSessionManager.class);
|
|
||||||
|
|
||||||
private final WebsocketMesDispather websocketMesDispather = SpringUtils.getBean(WebsocketMesDispather.class);
|
|
||||||
|
|
||||||
private final String mqttClientId = "maibu-mqtt-client";
|
|
||||||
|
|
||||||
private final RedisCache redisCache = SpringUtils.getBean(RedisCache.class);
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getHandlerType() {
|
|
||||||
return Constant.mqttHandleKey;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean supports(String handlerType) {
|
|
||||||
return Constant.mqttHandleKey.equals(handlerType);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 处理 MQTT 消息
|
|
||||||
*
|
|
||||||
* <p>
|
|
||||||
* 通配符订阅场景下,deviceKey 为配置中的固定标识(如 "host-monitor"),
|
|
||||||
* 真正的设备 ID 需从 topic 中解析,通过 {@link #extractDeviceId(String)} 获取。
|
|
||||||
* </p>
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void handleMessage(String deviceKey, String topic, String payload, CustomMqttDeviceConfig config) {
|
|
||||||
try {
|
|
||||||
String deviceId = extractDeviceId(topic);
|
|
||||||
if (deviceId == null) {
|
|
||||||
log.warn("无法从topic解析deviceId: {}", topic);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
String action = extractAction(topic);
|
|
||||||
if (action == null) {
|
|
||||||
log.debug("未识别的topic: {}", topic);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (action) {
|
|
||||||
case "location_post":
|
|
||||||
handleLocationPost(deviceId, topic, payload);
|
|
||||||
break;
|
|
||||||
case "realtime_post":
|
|
||||||
handleRealtimePost(deviceId, topic, payload);
|
|
||||||
break;
|
|
||||||
case "heartbeat_post":
|
|
||||||
handleHeartbeatPost(deviceId, topic, payload);
|
|
||||||
break;
|
|
||||||
case "error_post":
|
|
||||||
handleErrorPost(deviceId, topic, payload);
|
|
||||||
break;
|
|
||||||
// case "route_post":
|
|
||||||
// case "point_post":
|
|
||||||
// handleTaskPost(deviceId, topic, payload, action);
|
|
||||||
// break;
|
|
||||||
case "task_status_post":
|
|
||||||
handleTaskPost(deviceId, topic, payload, action);
|
|
||||||
break;
|
|
||||||
case "config_reply":
|
|
||||||
handleConfigReply(deviceId, topic, payload);
|
|
||||||
break;
|
|
||||||
case "control_reply":
|
|
||||||
handleControlReply(deviceId, topic, payload);
|
|
||||||
break;
|
|
||||||
case "route_reply":
|
|
||||||
handleRouteReply(deviceId, topic, payload);
|
|
||||||
break;
|
|
||||||
case "upgrade_reply":
|
|
||||||
handleUpgradeReply(deviceId, topic, payload);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
log.debug("割草机消息: deviceId={}, topic={}, action={}", deviceId, topic, action);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
log.error("消息处理异常: topic={}, error={}", topic, e.getMessage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 定位信息 经纬度
|
|
||||||
*/
|
|
||||||
private void handleLocationPost(String deviceId, String topic, String payload) {
|
|
||||||
try {
|
|
||||||
log.debug("【位置数据】deviceId={}, payload={}", deviceId, payload);
|
|
||||||
HostLocationRelTimeDTO locationRelTimeDTO = JsonUtils.parseObject(payload, HostLocationRelTimeDTO.class);
|
|
||||||
if (locationRelTimeDTO != null) {
|
|
||||||
WebStatusMessageDTO dto = createWebDeviceLocationMessage(locationRelTimeDTO, deviceId);
|
|
||||||
List<NettyDevice> controlMasters = deviceSessionManager
|
|
||||||
.getAllSlaveControl(deviceId);
|
|
||||||
if (!CollectionUtils.isEmpty(controlMasters)) {
|
|
||||||
for (NettyDevice x : controlMasters) {
|
|
||||||
try {
|
|
||||||
websocketMesDispather.dispather(x.getConnectorId(), JsonUtils.toJsonString(dto));
|
|
||||||
} catch (Exception e) {
|
|
||||||
log.error("位置数据websocket推送失败: connectorId={}, error={}", x.getConnectorId(),
|
|
||||||
e.getMessage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// todo 推送实时位置和状态消息到外部
|
|
||||||
// todo 记录到内存 开线程池队列 逐一转发
|
|
||||||
// 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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public WebStatusMessageDTO createWebDeviceLocationMessage(HostLocationRelTimeDTO locationRelTimeDTO,
|
|
||||||
String deviceId) {
|
|
||||||
WebStatusMessageDTO webStatusMessageDTO = new WebStatusMessageDTO();
|
|
||||||
List<DeviceStatusDetail> transferData = new ArrayList<>();
|
|
||||||
|
|
||||||
DeviceStatusDetail d = new DeviceStatusDetail();
|
|
||||||
d.setName("deviceId");
|
|
||||||
d.setValue(deviceId);
|
|
||||||
d.setUnit("");
|
|
||||||
transferData.add(d);
|
|
||||||
|
|
||||||
DeviceStatusDetail lat = new DeviceStatusDetail();
|
|
||||||
lat.setName("latitude");
|
|
||||||
lat.setValue(String.valueOf(locationRelTimeDTO.getData().getLatitude()));
|
|
||||||
lat.setUnit("");
|
|
||||||
transferData.add(lat);
|
|
||||||
|
|
||||||
DeviceStatusDetail lng = new DeviceStatusDetail();
|
|
||||||
lng.setName("longitude");
|
|
||||||
lng.setValue(String.valueOf(locationRelTimeDTO.getData().getLongitude()));
|
|
||||||
lng.setUnit("");
|
|
||||||
transferData.add(lng);
|
|
||||||
|
|
||||||
DeviceStatusDetail yaw = new DeviceStatusDetail();
|
|
||||||
yaw.setName("yaw");
|
|
||||||
yaw.setValue(String.valueOf(locationRelTimeDTO.getData().getYaw()));
|
|
||||||
yaw.setUnit("");
|
|
||||||
transferData.add(yaw);
|
|
||||||
|
|
||||||
DeviceStatusDetail fix_status = new DeviceStatusDetail();
|
|
||||||
fix_status.setName("fix_status");
|
|
||||||
fix_status.setValue(String.valueOf(locationRelTimeDTO.getData().getFix_status()));
|
|
||||||
fix_status.setUnit("");
|
|
||||||
transferData.add(fix_status);
|
|
||||||
|
|
||||||
DeviceStatusDetail altitude = new DeviceStatusDetail();
|
|
||||||
altitude.setName("altitude");
|
|
||||||
altitude.setValue(String.valueOf(locationRelTimeDTO.getData().getAltitude()));
|
|
||||||
altitude.setUnit("");
|
|
||||||
transferData.add(altitude);
|
|
||||||
|
|
||||||
DeviceStatusDetail status = new DeviceStatusDetail();
|
|
||||||
status.setName("status");
|
|
||||||
|
|
||||||
NettyDevice nettyDevice = deviceSessionManager.getDevice(deviceId);
|
|
||||||
// todo error故障
|
|
||||||
if (nettyDevice != null) {
|
|
||||||
if (nettyDevice.getOnlineStatus() == 0) {
|
|
||||||
status.setValue(DeviceStatusEnum.offline.getCode());
|
|
||||||
} else {
|
|
||||||
if (nettyDevice.getTask() != null && nettyDevice.getTask().isTaskAccepted()) {
|
|
||||||
status.setValue(DeviceStatusEnum.working.getCode());
|
|
||||||
} else {
|
|
||||||
status.setValue(DeviceStatusEnum.idle.getCode());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
status.setValue(DeviceStatusEnum.offline.getCode());
|
|
||||||
}
|
|
||||||
status.setUnit("");
|
|
||||||
transferData.add(status);
|
|
||||||
|
|
||||||
webStatusMessageDTO.setData(transferData);
|
|
||||||
webStatusMessageDTO.setType(MesType.locationInfo);
|
|
||||||
|
|
||||||
if (nettyDevice != null && nettyDevice.getDevice() != null) {
|
|
||||||
Long siteId = nettyDevice.getDevice().getSiteId();
|
|
||||||
Long orgId = nettyDevice.getDevice().getOrgId();
|
|
||||||
SiteMemory siteMemory = GlobalMemory.getSiteMemory(orgId, siteId);
|
|
||||||
if (siteMemory != null) {
|
|
||||||
DeviceMapPushDTO dto = new DeviceMapPushDTO();
|
|
||||||
dto.setA(Double.parseDouble(altitude.getValue()));
|
|
||||||
dto.setId(deviceId);
|
|
||||||
// dto.setB();
|
|
||||||
// dto.setHa();
|
|
||||||
dto.setF(fix_status.getValue());
|
|
||||||
dto.setS(status.getValue());
|
|
||||||
dto.setLat(Double.parseDouble(lat.getValue()));
|
|
||||||
dto.setLng(Double.parseDouble(lng.getValue()));
|
|
||||||
dto.setT(nettyDevice.getCurrentTaskId());
|
|
||||||
dto.setY(Double.parseDouble(yaw.getValue()));
|
|
||||||
siteMemory.saveMapPushDTO(deviceId, dto);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return webStatusMessageDTO;
|
|
||||||
}
|
|
||||||
|
|
||||||
public WebStatusMessageDTO createWebDeviceRealtimeMessage(HostVehicleRelTimeDTO vehicleRelTimeDTO) {
|
|
||||||
// todo 状态消息
|
|
||||||
|
|
||||||
WebStatusMessageDTO webStatusMessageDTO = new WebStatusMessageDTO();
|
|
||||||
List<DeviceStatusDetail> transferData = new ArrayList<>();
|
|
||||||
DeviceStatusDetail voltage = new DeviceStatusDetail();
|
|
||||||
voltage.setName("voltage");
|
|
||||||
voltage.setValue(String.valueOf(vehicleRelTimeDTO.getData().getBattery_voltage()));
|
|
||||||
voltage.setUnit("");
|
|
||||||
|
|
||||||
transferData.add(voltage);
|
|
||||||
|
|
||||||
DeviceStatusDetail speed = new DeviceStatusDetail();
|
|
||||||
speed.setName("speed");
|
|
||||||
speed.setValue(String.valueOf(vehicleRelTimeDTO.getData().getSpeed()));
|
|
||||||
speed.setUnit("");
|
|
||||||
transferData.add(speed);
|
|
||||||
|
|
||||||
DeviceStatusDetail motion = new DeviceStatusDetail();
|
|
||||||
motion.setName("motion");
|
|
||||||
motion.setValue(String.valueOf(vehicleRelTimeDTO.getData().getMotion()));
|
|
||||||
motion.setUnit("");
|
|
||||||
transferData.add(motion);
|
|
||||||
|
|
||||||
DeviceStatusDetail percentage = new DeviceStatusDetail();
|
|
||||||
percentage.setName("percentage");
|
|
||||||
percentage.setValue(String.valueOf(vehicleRelTimeDTO.getData().getBattery_percentage()));
|
|
||||||
percentage.setUnit("");
|
|
||||||
transferData.add(percentage);
|
|
||||||
|
|
||||||
webStatusMessageDTO.setData(transferData);
|
|
||||||
webStatusMessageDTO.setType(MesType.deviceInfo);
|
|
||||||
return webStatusMessageDTO;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 上位机数据
|
|
||||||
*/
|
|
||||||
private void handleRealtimePost(String deviceId, String topic, String payload) {
|
|
||||||
log.debug("【实时数据】deviceId={}, payload={}", deviceId, payload);
|
|
||||||
try {
|
|
||||||
HostVehicleRelTimeDTO vehicleRelTimeDTO = JsonUtils.parseObject(payload, HostVehicleRelTimeDTO.class);
|
|
||||||
if (vehicleRelTimeDTO != null) {
|
|
||||||
|
|
||||||
// todo 更新里程数 里程数 * 割幅0.8
|
|
||||||
vehicleRelTimeDTO.getData().getDistance();
|
|
||||||
NettyDevice nettyDevice = deviceSessionManager.getDevice(deviceId);
|
|
||||||
if (nettyDevice != null) {
|
|
||||||
Long orgId = nettyDevice.getDevice().getOrgId();
|
|
||||||
Long siteId = nettyDevice.getDevice().getSiteId();
|
|
||||||
SiteMemory siteMemory = GlobalMemory.getSiteMemory(orgId, siteId);
|
|
||||||
if (siteMemory != null) {
|
|
||||||
DeviceRunStatistics deviceRunStatistics = siteMemory.getRunStatistics(deviceId);
|
|
||||||
if (deviceRunStatistics == null) {
|
|
||||||
deviceRunStatistics = new DeviceRunStatistics();
|
|
||||||
}
|
|
||||||
deviceRunStatistics.setDeviceId(deviceId);
|
|
||||||
deviceRunStatistics.setDistance(vehicleRelTimeDTO.getData().getDistance());
|
|
||||||
deviceRunStatistics.setWorkArea(vehicleRelTimeDTO.getData().getDistance() * 0.8);
|
|
||||||
siteMemory.saveRunStatistics(deviceRunStatistics);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
WebStatusMessageDTO dto = createWebDeviceRealtimeMessage(vehicleRelTimeDTO);
|
|
||||||
List<NettyDevice> controlMasters = deviceSessionManager
|
|
||||||
.getAllSlaveControl(deviceId);
|
|
||||||
if (!CollectionUtils.isEmpty(controlMasters)) {
|
|
||||||
for (NettyDevice x : controlMasters) {
|
|
||||||
try {
|
|
||||||
websocketMesDispather.dispather(x.getConnectorId(), JsonUtils.toJsonString(dto));
|
|
||||||
} catch (Exception e) {
|
|
||||||
log.error("实时数据websocket推送失败: connectorId={}, error={}", x.getConnectorId(),
|
|
||||||
e.getMessage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
log.error("实时消息解析失败: deviceId={}, payload={}, error={}", deviceId, payload, e.getMessage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 处理心跳
|
|
||||||
* topic: mower/{deviceId}/event/heartbeat/post
|
|
||||||
*/
|
|
||||||
private void handleHeartbeatPost(String deviceId, String topic, String payload) {
|
|
||||||
log.debug("【心跳】payload={}", payload);
|
|
||||||
// 心跳处理
|
|
||||||
HeartBeatDTO beatDTO = JsonUtils.parseObject(payload, HeartBeatDTO.class);
|
|
||||||
if (beatDTO != null) {
|
|
||||||
beatDTO.setSysTimestamp(System.currentTimeMillis());
|
|
||||||
GlobalMemory.customMqttDeviceMonitor.saveHeartBeat(beatDTO.getSn(), beatDTO);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 处理错误告警
|
|
||||||
* topic: mower/{deviceId}/event/error/post
|
|
||||||
*/
|
|
||||||
private void handleErrorPost(String deviceId, String topic, String payload) {
|
|
||||||
log.warn("【错误告警】deviceId={}, payload={}", deviceId, payload);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 处理任务相关上报
|
|
||||||
*/
|
|
||||||
private void handleTaskPost(String deviceId, String topic, String payload, String action) {
|
|
||||||
log.info("【任务上报】deviceId={}, action={}, payload={}", deviceId, action, payload);
|
|
||||||
|
|
||||||
HostTaskStatusDTO dto = JsonUtils.parseObject(payload, HostTaskStatusDTO.class);
|
|
||||||
if (dto != null && !StringUtils.isEmpty(dto.getStatus())) {
|
|
||||||
NettyDevice nettyDevice = deviceSessionManager.getDevice(deviceId);
|
|
||||||
if ("completed".equals(dto.getStatus())) {
|
|
||||||
Long taskId = nettyDevice.finishTask();
|
|
||||||
|
|
||||||
WebDeviceTaskStatusMessageDTO sendDto = new WebDeviceTaskStatusMessageDTO();
|
|
||||||
sendDto.setDeviceId(deviceId);
|
|
||||||
sendDto.setTaskId(taskId);
|
|
||||||
sendDto.setStatus(DeviceTaskStaus.FINISH.toString());
|
|
||||||
sendDto.setType(MesType.device_task_change);
|
|
||||||
|
|
||||||
List<NettyDevice> controlMasters = deviceSessionManager
|
|
||||||
.getAllSlaveControl(deviceId);
|
|
||||||
if (!CollectionUtils.isEmpty(controlMasters)) {
|
|
||||||
for (NettyDevice x : controlMasters) {
|
|
||||||
try {
|
|
||||||
websocketMesDispather.dispather(x.getConnectorId(), JsonUtils.toJsonString(sendDto));
|
|
||||||
} catch (Exception e) {
|
|
||||||
log.error("实时数据websocket推送失败: connectorId={}, error={}", x.getConnectorId(),
|
|
||||||
e.getMessage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// todo 推送实时位置和状态消息到外部
|
|
||||||
try {
|
|
||||||
GlobalMemory.customMqttDeviceMonitor.publish(mqttClientId,
|
|
||||||
String.format(MqttTopic.DEVICE_TASK_STATUS_TOPIC, taskId),
|
|
||||||
JsonUtils.toJsonString(sendDto));
|
|
||||||
} catch (MqttException e) {
|
|
||||||
// TODO Auto-generated catch block
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
if ("cancelled".equals(dto.getStatus())) {
|
|
||||||
nettyDevice.canceledTask();
|
|
||||||
}
|
|
||||||
// if("paused".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();
|
|
||||||
// }
|
|
||||||
// if("running".equals(dto.getStatus())){
|
|
||||||
// NettyDevice nettyDevice = deviceSessionManager.getDevice(deviceId);
|
|
||||||
// nettyDevice.finishTask();
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 处理配置响应
|
|
||||||
*/
|
|
||||||
private void handleConfigReply(String deviceId, String topic, String payload) {
|
|
||||||
log.debug("【配置响应】deviceId={}, payload={}", deviceId, payload);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 处理控制指令响应
|
|
||||||
*/
|
|
||||||
private void handleControlReply(String deviceId, String topic, String payload) {
|
|
||||||
log.debug("【控制响应】deviceId={}, payload={}", deviceId, payload);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 处理控制指令响应
|
|
||||||
*/
|
|
||||||
private void handleRouteReply(String deviceId, String topic, String payload) {
|
|
||||||
log.debug("【路径任务下发响应】deviceId={}, payload={}", deviceId, payload);
|
|
||||||
|
|
||||||
// todo 更新任务接收状态
|
|
||||||
HostNavigationReplyDTO replyDTO = JsonUtils.parseObject(payload, HostNavigationReplyDTO.class);
|
|
||||||
NettyDevice device = deviceSessionManager.getDevice(deviceId);
|
|
||||||
if (replyDTO.isAccepted()) {
|
|
||||||
if (device != null && device.getTask() != null
|
|
||||||
&& String.valueOf(device.getTask().getId()).equals(replyDTO.getTask_id())) {
|
|
||||||
device.getTask().setTaskAccepted(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 处理控制指令响应
|
|
||||||
*/
|
|
||||||
private void handleUpgradeReply(String deviceId, String topic, String payload) {
|
|
||||||
// log.debug("【路径任务下发响应】deviceId={}, payload={}", deviceId, payload);
|
|
||||||
//
|
|
||||||
// // todo 更新任务接收状态
|
|
||||||
// HostNavigationReplyDTO replyDTO = JsonUtils.parseObject(payload, HostNavigationReplyDTO.class);
|
|
||||||
// NettyDevice device = deviceSessionManager.getDevice(deviceId);
|
|
||||||
// if (replyDTO.isAccepted()) {
|
|
||||||
// if (device != null && device.getTask() != null
|
|
||||||
// && String.valueOf(device.getTask().getId()).equals(replyDTO.getTask_id())) {
|
|
||||||
// device.getTask().setTaskAccepted(true);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 从 Topic 中解析 deviceId
|
|
||||||
* Topic 格式:mower/{deviceId}/...
|
|
||||||
*/
|
|
||||||
private String extractDeviceId(String topic) {
|
|
||||||
if (topic == null || topic.isEmpty()) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
String[] parts = topic.split("/");
|
|
||||||
if (parts.length < 2 || !"mower".equals(parts[0])) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return parts[1];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 从 Topic 中提取动作标识
|
|
||||||
* 将 mower/{deviceId}/xxx/yyy/post 转为 xxx_yyy_post 形式
|
|
||||||
*/
|
|
||||||
private String extractAction(String topic) {
|
|
||||||
String[] parts = topic.split("/");
|
|
||||||
if (parts.length < 3 || !"mower".equals(parts[0])) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
StringBuilder path = new StringBuilder();
|
|
||||||
for (int i = 2; i < parts.length; i++) {
|
|
||||||
if (i > 2)
|
|
||||||
path.append("/");
|
|
||||||
path.append(parts[i]);
|
|
||||||
}
|
|
||||||
String remaining = path.toString();
|
|
||||||
|
|
||||||
if (remaining.equals("property/location/post"))
|
|
||||||
return "location_post";
|
|
||||||
if (remaining.equals("property/realtime/post"))
|
|
||||||
return "realtime_post";
|
|
||||||
if (remaining.equals("event/heartbeat/post"))
|
|
||||||
return "heartbeat_post";
|
|
||||||
if (remaining.equals("event/error/post"))
|
|
||||||
return "error_post";
|
|
||||||
// if (remaining.equals("task/route/post")) return "route_post";
|
|
||||||
// if (remaining.equals("task/point/post")) return "point_post";
|
|
||||||
if (remaining.equals("task/status/post"))
|
|
||||||
return "task_status_post";
|
|
||||||
if (remaining.equals("action/config/reply"))
|
|
||||||
return "config_reply";
|
|
||||||
if (remaining.equals("action/control/reply"))
|
|
||||||
return "control_reply";
|
|
||||||
if (remaining.equals("task/target/reply"))
|
|
||||||
return "route_reply";
|
|
||||||
if (remaining.equals("/ota/result/post"))
|
|
||||||
return "upgrade_reply";
|
|
||||||
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onConnectionLost(String deviceKey, Throwable cause) {
|
|
||||||
log.warn("主机监控连接断开: deviceKey={}, reason={}", deviceKey, cause.getMessage());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onSubscribed(String deviceKey, String topic) {
|
|
||||||
log.info("主机监控订阅主题: deviceKey={}, topic={}", deviceKey, topic);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,18 +1,16 @@
|
|||||||
package com.maibu.mqtt;
|
package com.maibu.mqtt;
|
||||||
|
|
||||||
|
|
||||||
public class MqttTopic {
|
public class MqttTopic {
|
||||||
|
|
||||||
/** 通用设备主题,建议使用 MOWER_* 系列主题 */
|
/** @deprecated 通用设备主题,建议使用 MOWER_* 系列主题 */
|
||||||
public static final String DEVICE_STATUS_TOPIC = "device/%s/realTimeMessage";
|
public static final String DEVICE_STATUS_TOPIC = "device/%s/realTimeMessage";
|
||||||
|
/** @deprecated 通用设备主题,建议使用 MOWER_* 系列主题 */
|
||||||
public static final String DEVICE_LOCATION_TOPIC = "device/%s/locationMessage";
|
|
||||||
/** 通用设备主题,建议使用 MOWER_* 系列主题 */
|
|
||||||
public static final String DEVICE_TASK_STATUS_TOPIC = "task/%s/status";
|
public static final String DEVICE_TASK_STATUS_TOPIC = "task/%s/status";
|
||||||
/** 通用设备主题,建议使用 MOWER_* 系列主题 */
|
/** @deprecated 通用设备主题,建议使用 MOWER_* 系列主题 */
|
||||||
public static final String DEVICE_TASK_ARRIVE_TOPIC = "task/%s/arrive";
|
public static final String DEVICE_TASK_ARRIVE_TOPIC = "task/%s/arrive";
|
||||||
/** 通用设备主题,建议使用 MOWER_* 系列主题 */
|
/** @deprecated 通用设备主题,建议使用 MOWER_* 系列主题 */
|
||||||
public static final String DEVICE_ERROR_PUSH_TOPIC = "device/%s/error";
|
public static final String DEVICE_ERROR_PUSH_TOPIC = "device/%s/error";
|
||||||
public static final String DEVICE_ROUTE_PUSH_TOPIC = "device/%s/route/post";
|
|
||||||
|
|
||||||
/** 产品标识:割草机 */
|
/** 产品标识:割草机 */
|
||||||
public static final String MOWER_PRODUCT = "mower";
|
public static final String MOWER_PRODUCT = "mower";
|
||||||
@@ -20,12 +18,12 @@ public class MqttTopic {
|
|||||||
// ==================== 设备连接与状态 ====================
|
// ==================== 设备连接与状态 ====================
|
||||||
/** 设备上线/下线事件上报(设备->平台),对应 TCP 0x03 connect */
|
/** 设备上线/下线事件上报(设备->平台),对应 TCP 0x03 connect */
|
||||||
public static final String MOWER_STATUS_POST = "mower/%s/event/status/post";
|
public static final String MOWER_STATUS_POST = "mower/%s/event/status/post";
|
||||||
|
/** 状态变更确认回复(平台->设备) */
|
||||||
|
// public static final String MOWER_STATUS_REPLY = "mower/%s/event/status/reply";
|
||||||
|
|
||||||
// ==================== 实时运行数据 ====================
|
// ==================== 实时运行数据 ====================
|
||||||
/** 实时运行数据上报:电压/速度/温度/位置等(设备->平台),对应 TCP 0x02 status */
|
/** 实时运行数据上报:电压/速度/温度/位置等(设备->平台),对应 TCP 0x02 status */
|
||||||
public static final String MOWER_REALTIME_POST = "mower/%s/property/realtime/post";
|
public static final String MOWER_REALTIME_POST = "mower/%s/property/realtime/post";
|
||||||
/** GPS 位置数据上报:经纬度、速度、航向等(设备->平台) */
|
|
||||||
public static final String MOWER_LOCATION_POST = "mower/%s/property/location/post";
|
|
||||||
|
|
||||||
// ==================== 心跳保活 ====================
|
// ==================== 心跳保活 ====================
|
||||||
/** 设备心跳上报(设备->平台),对应 TCP 0xFF heartbeat */
|
/** 设备心跳上报(设备->平台),对应 TCP 0xFF heartbeat */
|
||||||
@@ -45,61 +43,58 @@ public class MqttTopic {
|
|||||||
/** 远程控制指令下发:前进/后退/转向/割草等(平台->设备),对应 TCP 0x00 remoteControl */
|
/** 远程控制指令下发:前进/后退/转向/割草等(平台->设备),对应 TCP 0x00 remoteControl */
|
||||||
public static final String MOWER_CONTROL_SET = "mower/%s/action/control/set";
|
public static final String MOWER_CONTROL_SET = "mower/%s/action/control/set";
|
||||||
|
|
||||||
|
// /** 控制指令响应(设备->平台) */
|
||||||
|
// public static final String MOWER_CONTROL_REPLY = "mower/%s/action/control/reply";
|
||||||
|
|
||||||
// ==================== 任务管理 ====================
|
// ==================== 任务管理 ====================
|
||||||
/** 路径规划下发(平台->设备),对应 TCP 0x01 path */
|
/** 路径规划下发(平台->设备),对应 TCP 0x01 path */
|
||||||
// public static final String MOWER_TASK_ROUTE_SET = "mower/%s/task/route/set";
|
public static final String MOWER_TASK_ROUTE_SET = "mower/%s/task/route/set";
|
||||||
// public static final String MOWER_TASK_ROUTE_POST =
|
public static final String MOWER_TASK_ROUTE_POST = "mower/%s/task/route/post";
|
||||||
// "mower/%s/task/route/post";
|
|
||||||
|
|
||||||
public static final String MOWER_TASK_ROUTE_SET = "mower/%s/task/target/set";
|
|
||||||
|
|
||||||
/** 启动任务执行(平台->设备),对应 TCP 0x12 interaction */
|
/** 启动任务执行(平台->设备),对应 TCP 0x12 interaction */
|
||||||
public static final String MOWER_TASK_STATUS_SET = "mower/%s/task/status/set";
|
public static final String MOWER_TASK_STATUS_SET = "mower/%s/task/status/set";
|
||||||
|
// /** 暂停任务(平台->设备) */
|
||||||
|
// public static final String MOWER_TASK_PAUSE_SET = "mower/%s/task/pause/set";
|
||||||
|
// /** 继续任务(平台->设备) */
|
||||||
|
// public static final String MOWER_TASK_RESUME_SET = "mower/%s/task/resume/set";
|
||||||
|
// /** 取消任务(平台->设备) */
|
||||||
|
// public static final String MOWER_TASK_CANCEL_SET = "mower/%s/task/cancel/set";
|
||||||
|
// /** 到达路径点上报(设备->平台) */
|
||||||
public static final String MOWER_TASK_POINT_POST = "mower/%s/task/point/post";
|
public static final String MOWER_TASK_POINT_POST = "mower/%s/task/point/post";
|
||||||
/** 任务状态变更上报:执行中/暂停/完成等(设备->平台) */
|
/** 任务状态变更上报:执行中/暂停/完成等(设备->平台) */
|
||||||
public static final String MOWER_TASK_STATUS_POST = "mower/%s/task/status/post";
|
public static final String MOWER_TASK_STATUS_POST = "mower/%s/task/status/post";
|
||||||
|
/** 任务完成上报(设备->平台) */
|
||||||
|
public static final String MOWER_TASK_FINISH_POST = "mower/%s/task/finish/post";
|
||||||
|
|
||||||
// ==================== 错误告警 ====================
|
// ==================== 错误告警 ====================
|
||||||
/** 设备错误告警上报:电机故障/传感器异常等(设备->平台) */
|
/** 设备错误告警上报:电机故障/传感器异常等(设备->平台) */
|
||||||
public static final String MOWER_ERROR_POST = "mower/%s/event/error/post";
|
public static final String MOWER_ERROR_POST = "mower/%s/event/error/post";
|
||||||
|
|
||||||
// ==================== OTA 固件升级 ====================
|
// ==================== OTA 固件升级 ====================
|
||||||
/** 下发 OTA 升级指令(平台->设备) */
|
// /** 下发 OTA 升级指令(平台->设备) */
|
||||||
public static final String MOWER_OTA_UPGRADE_SET = "mower/%s/ota/upgrade/set";
|
// public static final String MOWER_OTA_UPGRADE_SET = "mower/%s/ota/upgrade/set";
|
||||||
/** OTA 升级进度上报(设备->平台) */
|
// /** OTA 升级进度上报(设备->平台) */
|
||||||
public static final String MOWER_OTA_PROGRESS_POST = "mower/+/ota/progress/post";
|
// public static final String MOWER_OTA_PROGRESS_POST = "mower/%s/ota/progress/post";
|
||||||
/** OTA 升级结果上报(设备->平台) */
|
// /** OTA 升级结果上报(设备->平台) */
|
||||||
public static final String MOWER_OTA_RESULT_POST = "mower/+/ota/result/post";
|
// public static final String MOWER_OTA_RESULT_POST = "mower/%s/ota/result/post";
|
||||||
|
|
||||||
// ==================== 设备信息 ====================
|
// ==================== 设备信息 ====================
|
||||||
// /** 查询设备信息(平台->设备) */
|
// /** 查询设备信息(平台->设备) */
|
||||||
// public static final String MOWER_INFO_DEVICE_GET =
|
// public static final String MOWER_INFO_DEVICE_GET = "mower/%s/info/device/get";
|
||||||
// "mower/%s/info/device/get";
|
// /** 设备信息响应(设备->平台) */
|
||||||
// /** 设备信息响应(设备->平台) */
|
// public static final String MOWER_INFO_DEVICE_REPLY = "mower/%s/info/device/reply";
|
||||||
// public static final String MOWER_INFO_DEVICE_REPLY =
|
|
||||||
// "mower/%s/info/device/reply";
|
|
||||||
/** 设备版本信息上报(设备->平台) */
|
/** 设备版本信息上报(设备->平台) */
|
||||||
// public static final String MOWER_INFO_VERSION_POST =
|
// public static final String MOWER_INFO_VERSION_POST = "mower/%s/info/version/post";
|
||||||
// "mower/%s/info/version/post";
|
|
||||||
|
|
||||||
// ==================== 通配符订阅 ====================
|
// ==================== 通配符订阅 ====================
|
||||||
/** 订阅所有设备的状态变更事件 */
|
/** 订阅所有设备的状态变更事件 */
|
||||||
public static final String MOWER_WILDCARD_STATUS = "mower/+/event/status/post";
|
public static final String MOWER_WILDCARD_STATUS = "mower/+/event/status/post";
|
||||||
/** 订阅所有设备的实时运行数据 */
|
/** 订阅所有设备的实时运行数据 */
|
||||||
public static final String MOWER_WILDCARD_REALTIME = "mower/+/property/realtime/post";
|
public static final String MOWER_WILDCARD_REALTIME = "mower/+/property/realtime/post";
|
||||||
/** 上位机的额外消息 */
|
|
||||||
public static final String MOWER_WILDCARD_LOCATION = "mower/+/property/location/post";
|
|
||||||
/** 订阅所有设备的错误告警 */
|
/** 订阅所有设备的错误告警 */
|
||||||
public static final String MOWER_WILDCARD_ERROR = "mower/+/event/error/post";
|
public static final String MOWER_WILDCARD_ERROR = "mower/+/event/error/post";
|
||||||
/** 订阅所有设备的任务状态变更 */
|
/** 订阅所有设备的任务状态变更 */
|
||||||
public static final String MOWER_WILDCARD_TASK_STATUS = "mower/+/task/status/post";
|
public static final String MOWER_WILDCARD_TASK_STATUS = "mower/+/task/status/post";
|
||||||
|
|
||||||
public static final String MOWER_WILDCARD_TASK_ROUTE = "mower/+/task/route/post";
|
|
||||||
|
|
||||||
public static final String MOWER_WILDCARD_TASK_TARGET_REPLY = "mower/+/task/target/reply";
|
|
||||||
|
|
||||||
public static final String MOWER_HEARTBEAT = "mower/+/event/heartbeat/post";
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 格式化 Topic 模板,将 %s 替换为设备ID
|
* 格式化 Topic 模板,将 %s 替换为设备ID
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
package com.maibu.utils;
|
package com.maibu.utils;
|
||||||
|
|
||||||
import io.minio.*;
|
import io.minio.BucketExistsArgs;
|
||||||
|
import io.minio.MakeBucketArgs;
|
||||||
|
import io.minio.MinioClient;
|
||||||
|
import io.minio.PutObjectArgs;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
@@ -41,15 +44,6 @@ public class MinioUtil {
|
|||||||
// 拼接 public URL
|
// 拼接 public URL
|
||||||
return endpoint + "/" + defaultBucket + "/" + objectName;
|
return endpoint + "/" + defaultBucket + "/" + objectName;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void deleteFile(String objectName) throws Exception {
|
|
||||||
minioClient.removeObject(
|
|
||||||
RemoveObjectArgs.builder()
|
|
||||||
.bucket(defaultBucket)
|
|
||||||
.object(objectName)
|
|
||||||
.build()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -29,7 +29,6 @@ import org.springframework.util.CollectionUtils;
|
|||||||
import org.springframework.web.multipart.MultipartFile;
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
|
|
||||||
import javax.annotation.PostConstruct;
|
import javax.annotation.PostConstruct;
|
||||||
import javax.annotation.PreDestroy;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.security.InvalidKeyException;
|
import java.security.InvalidKeyException;
|
||||||
@@ -59,9 +58,6 @@ public class UAVService {
|
|||||||
@Autowired
|
@Autowired
|
||||||
private RedisCache redisCache;
|
private RedisCache redisCache;
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private ScheduledExecutorService executor;
|
|
||||||
|
|
||||||
|
|
||||||
public static final Map<String, Long> latestActiveTime = new ConcurrentHashMap<>();
|
public static final Map<String, Long> latestActiveTime = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
@@ -673,6 +669,7 @@ public class UAVService {
|
|||||||
|
|
||||||
@PostConstruct
|
@PostConstruct
|
||||||
public void heartbeatMonitor() {
|
public void heartbeatMonitor() {
|
||||||
|
ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor();
|
||||||
executor.scheduleWithFixedDelay(() -> {
|
executor.scheduleWithFixedDelay(() -> {
|
||||||
try {
|
try {
|
||||||
Long nowTime = System.currentTimeMillis();
|
Long nowTime = System.currentTimeMillis();
|
||||||
@@ -824,5 +821,4 @@ public class UAVService {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -116,7 +116,7 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter {
|
|||||||
// 过滤请求
|
// 过滤请求
|
||||||
.authorizeRequests()
|
.authorizeRequests()
|
||||||
// 对于登录login 注册register 验证码captchaImage 允许匿名访问
|
// 对于登录login 注册register 验证码captchaImage 允许匿名访问
|
||||||
.antMatchers("/iot/host/upload-path-csv","/api/thermal/**","/iotDA/device/**", "/websocket/allMemory", "/iot/UAV/**", "/iot/api/**", "/iot/device/userDevice", "/external/sms/sendAliSmsCode", "/login", "/register", "/captchaImage", "/iot/tool/register", "/iot/tool/ntp",
|
.antMatchers("/api/thermal/**","/iotDA/device/**", "/websocket/allMemory", "/iot/UAV/**", "/iot/api/**", "/iot/device/userDevice", "/external/sms/sendAliSmsCode", "/login", "/register", "/captchaImage", "/iot/tool/register", "/iot/tool/ntp",
|
||||||
"/iot/tool/mqtt/auth", "/iot/workRecord/**", "/iot/tool/mqtt/authv5", "/iot/tool/mqtt/webhook", "/iot/tool/mqtt/webhookv5", "/auth/**/**",
|
"/iot/tool/mqtt/auth", "/iot/workRecord/**", "/iot/tool/mqtt/authv5", "/iot/tool/mqtt/webhook", "/iot/tool/mqtt/webhookv5", "/auth/**/**",
|
||||||
"/wechat/mobileLogin", "/wechat/miniLogin", "/wechat/wxBind/callback").permitAll()
|
"/wechat/mobileLogin", "/wechat/miniLogin", "/wechat/wxBind/callback").permitAll()
|
||||||
.antMatchers("/zlmhook/**").permitAll()
|
.antMatchers("/zlmhook/**").permitAll()
|
||||||
|
|||||||
@@ -170,9 +170,8 @@ public class TokenService {
|
|||||||
|
|
||||||
Map<String, Object> claims = new HashMap<>();
|
Map<String, Object> claims = new HashMap<>();
|
||||||
claims.put(Constants.LOGIN_USER_KEY, token);
|
claims.put(Constants.LOGIN_USER_KEY, token);
|
||||||
String realToken = createToken(claims);
|
return createToken(claims);
|
||||||
loginUser.setRealToken(realToken);
|
|
||||||
return realToken;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public int addToken(SysUser user, SysClient sysClient) {
|
public int addToken(SysUser user, SysClient sysClient) {
|
||||||
|
|||||||
@@ -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.DeviceMessage;
|
||||||
import com.huaweicloud.sdk.iot.device.client.requests.ServiceProperty;
|
import com.huaweicloud.sdk.iot.device.client.requests.ServiceProperty;
|
||||||
import com.huaweicloud.sdk.iot.device.transport.ActionListener;
|
import com.huaweicloud.sdk.iot.device.transport.ActionListener;
|
||||||
import com.maibu.constant.NettyCacheKey;
|
import com.maibu.common.NettyCacheKey;
|
||||||
import com.maibu.core.business.DeviceRunningStatusHistory;
|
import com.maibu.core.business.DeviceRunningStatusHistory;
|
||||||
import com.maibu.core.business.DeviceStatusRecordDTO;
|
import com.maibu.core.business.DeviceStatusRecordDTO;
|
||||||
import com.maibu.core.redis.RedisCache;
|
import com.maibu.core.redis.RedisCache;
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
package com.maibu.constant;
|
package com.maibu.common;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
public class NettyCacheKey {
|
public class NettyCacheKey {
|
||||||
|
|
||||||
public static final String deviceRunningStatusKey = "running_status:";
|
public static final String deviceRunningStatusKey = "running_status:";
|
||||||
|
|
||||||
public static final String latestPositonKey = "latest_position:";
|
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -3,7 +3,6 @@ package com.maibu.controller;
|
|||||||
import java.time.LocalDate;
|
import java.time.LocalDate;
|
||||||
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.eclipse.paho.client.mqttv3.MqttException;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.format.annotation.DateTimeFormat;
|
import org.springframework.format.annotation.DateTimeFormat;
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
@@ -46,10 +45,10 @@ public class DeviceTaskController extends BaseController {
|
|||||||
|
|
||||||
@GetMapping("/getSiteDevicePlan")
|
@GetMapping("/getSiteDevicePlan")
|
||||||
public AjaxResult getSiteDevicePlan(@RequestParam Long siteId,
|
public AjaxResult getSiteDevicePlan(@RequestParam Long siteId,
|
||||||
@RequestParam(required = false) @DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate startTime,
|
@RequestParam(required = false) @DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate startTime,
|
||||||
@RequestParam(required = false) @DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate endTime,
|
@RequestParam(required = false) @DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate endTime,
|
||||||
@RequestParam(required = false) String deviceId,
|
@RequestParam(required = false) String deviceId,
|
||||||
@RequestParam(required = false) DeviceTaskStaus taskStaus) {
|
@RequestParam(required = false) DeviceTaskStaus taskStaus) {
|
||||||
return AjaxResult.success(deviceTaskService.getSiteDevicePlan(siteId, startTime, endTime, deviceId, taskStaus));
|
return AjaxResult.success(deviceTaskService.getSiteDevicePlan(siteId, startTime, endTime, deviceId, taskStaus));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -86,6 +85,7 @@ public class DeviceTaskController extends BaseController {
|
|||||||
return AjaxResult.success(deviceTaskService.concurrentDevicePlanTask(deviceId));
|
return AjaxResult.success(deviceTaskService.concurrentDevicePlanTask(deviceId));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@GetMapping("/workStatistics")
|
@GetMapping("/workStatistics")
|
||||||
public AjaxResult workStatistics(@RequestParam Long userId) {
|
public AjaxResult workStatistics(@RequestParam Long userId) {
|
||||||
return AjaxResult.success(deviceTaskService.workStatistics(userId));
|
return AjaxResult.success(deviceTaskService.workStatistics(userId));
|
||||||
@@ -93,13 +93,13 @@ public class DeviceTaskController extends BaseController {
|
|||||||
|
|
||||||
@PostMapping("/deviceTaskPool")
|
@PostMapping("/deviceTaskPool")
|
||||||
public TableDataInfo deviceTaskPool(@RequestBody DeviceTaskQueryDTO dto) {
|
public TableDataInfo deviceTaskPool(@RequestBody DeviceTaskQueryDTO dto) {
|
||||||
startPostPage(dto.getPageNum(), dto.getPageSize());
|
startPostPage(dto.getPageNum(),dto.getPageSize());
|
||||||
return getDataTable(deviceTaskService.deviceTaskPool(dto));
|
return getDataTable(deviceTaskService.deviceTaskPool(dto));
|
||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping("/getSiteDeviceTaskHistory")
|
@PostMapping("/getSiteDeviceTaskHistory")
|
||||||
public TableDataInfo getSiteDeviceTaskHistory(@RequestBody DeviceTaskQueryDTO dto) {
|
public TableDataInfo getSiteDeviceTaskHistory(@RequestBody DeviceTaskQueryDTO dto) {
|
||||||
startPostPage(dto.getPageNum(), dto.getPageSize());
|
startPostPage(dto.getPageNum(),dto.getPageSize());
|
||||||
return getDataTable(deviceTaskService.getSiteDeviceTaskHistory(dto));
|
return getDataTable(deviceTaskService.getSiteDeviceTaskHistory(dto));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -124,38 +124,13 @@ public class DeviceTaskController extends BaseController {
|
|||||||
return AjaxResult.success(deviceTaskService.createDeviceTask(dto, getLoginUser().getUsername()));
|
return AjaxResult.success(deviceTaskService.createDeviceTask(dto, getLoginUser().getUsername()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping("/createRegionDeviceTask")
|
|
||||||
public AjaxResult createRegionDeviceTask(@RequestBody DeviceTaskCommandDTO dto) {
|
|
||||||
String deviceId = dto.getDeviceId();
|
|
||||||
Long siteId = dto.getSiteId();
|
|
||||||
Long orgId = dto.getOrgId();
|
|
||||||
Long regionId = dto.getRegionId();
|
|
||||||
if (StringUtils.isEmpty(deviceId)) {
|
|
||||||
return AjaxResult.error("deviceId为空!");
|
|
||||||
}
|
|
||||||
if (siteId == null) {
|
|
||||||
return AjaxResult.error("siteId为空!");
|
|
||||||
}
|
|
||||||
if (orgId == null) {
|
|
||||||
return AjaxResult.error("orgId为空!");
|
|
||||||
}
|
|
||||||
if (regionId == null) {
|
|
||||||
return AjaxResult.error("regionId为空!");
|
|
||||||
}
|
|
||||||
SiteMemory siteMemory = GlobalMemory.getSiteMemory(orgId, siteId);
|
|
||||||
if (siteMemory.hasTask(deviceId)) {
|
|
||||||
return AjaxResult.error("当前设备存在任务!");
|
|
||||||
}
|
|
||||||
return AjaxResult.success(deviceTaskService.createRegionDeviceTask(dto, getLoginUser().getUsername()));
|
|
||||||
}
|
|
||||||
|
|
||||||
@PostMapping("/cancelTask")
|
@PostMapping("/cancelTask")
|
||||||
public AjaxResult cancelTask(@RequestBody DeviceTaskCommandDTO dto) throws MqttException {
|
public AjaxResult cancelTask(@RequestBody DeviceTaskCommandDTO dto) {
|
||||||
String deviceId = dto.getDeviceId();
|
String deviceId = dto.getDeviceId();
|
||||||
if (StringUtils.isEmpty(deviceId) && dto.getTaskId() == null) {
|
if (StringUtils.isEmpty(deviceId) && dto.getTaskId() == null) {
|
||||||
return AjaxResult.error("deviceId或taskId为空!");
|
return AjaxResult.error("deviceId或taskId为空!");
|
||||||
}
|
}
|
||||||
return AjaxResult.success(deviceTaskService.cancelTask(dto));
|
return AjaxResult.success(deviceTaskService.cancelTask(dto, getUsername()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping("/pauseTask")
|
@PostMapping("/pauseTask")
|
||||||
@@ -176,4 +151,5 @@ public class DeviceTaskController extends BaseController {
|
|||||||
return AjaxResult.success(deviceTaskService.recoveryTask(dto, getUsername()));
|
return AjaxResult.success(deviceTaskService.recoveryTask(dto, getUsername()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -66,7 +66,11 @@ public class TransferDeviceController extends BaseController {
|
|||||||
if (StringUtils.isEmpty(bindDTO.getPlatform())) {
|
if (StringUtils.isEmpty(bindDTO.getPlatform())) {
|
||||||
return AjaxResult.error("平台为空!");
|
return AjaxResult.error("平台为空!");
|
||||||
}
|
}
|
||||||
return AjaxResult.success(transferDeviceService.switchDevice(bindDTO));
|
LoginUser user = getLoginUser();
|
||||||
|
if (user == null) {
|
||||||
|
return AjaxResult.error("当前token用户不存在!");
|
||||||
|
}
|
||||||
|
return AjaxResult.success(transferDeviceService.switchDevice(bindDTO, user));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -83,7 +87,8 @@ public class TransferDeviceController extends BaseController {
|
|||||||
if (StringUtils.isEmpty(bindDTO.getPlatform())) {
|
if (StringUtils.isEmpty(bindDTO.getPlatform())) {
|
||||||
return AjaxResult.error("平台为空!");
|
return AjaxResult.error("平台为空!");
|
||||||
}
|
}
|
||||||
return AjaxResult.success(transferDeviceService.remoteControl(bindDTO));
|
LoginUser user = getLoginUser();
|
||||||
|
return AjaxResult.success(transferDeviceService.remoteControl(bindDTO, user));
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
logger.error("获取设备控制权出错", e);
|
logger.error("获取设备控制权出错", e);
|
||||||
return AjaxResult.error();
|
return AjaxResult.error();
|
||||||
@@ -117,7 +122,8 @@ public class TransferDeviceController extends BaseController {
|
|||||||
if (StringUtils.isEmpty(bindDTO.getPlatform())) {
|
if (StringUtils.isEmpty(bindDTO.getPlatform())) {
|
||||||
return AjaxResult.error("平台为空!");
|
return AjaxResult.error("平台为空!");
|
||||||
}
|
}
|
||||||
transferDeviceService.releaseControl(bindDTO);
|
LoginUser user = getLoginUser();
|
||||||
|
transferDeviceService.releaseControl(bindDTO, user);
|
||||||
return AjaxResult.success();
|
return AjaxResult.success();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,6 +24,4 @@ public class DeviceBindDTO {
|
|||||||
|
|
||||||
private Integer type; // releaseControl 1 完全释放 2 释放控制权 可监听数据
|
private Integer type; // releaseControl 1 完全释放 2 释放控制权 可监听数据
|
||||||
|
|
||||||
private String token;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
package com.maibu.core.business.dto;
|
package com.maibu.dto;
|
||||||
|
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
@@ -39,12 +39,6 @@ public class InitThread implements ApplicationRunner {
|
|||||||
@Resource(name = FastBeeConstant.TASK.DEVICE_ERROR_MONITOR)
|
@Resource(name = FastBeeConstant.TASK.DEVICE_ERROR_MONITOR)
|
||||||
private Executor deviceErrorMonitorExecutor;
|
private Executor deviceErrorMonitorExecutor;
|
||||||
|
|
||||||
@Resource(name = FastBeeConstant.TASK.DEVICE_HEARTBEAT_MONITOR)
|
|
||||||
private Executor deviceHeartBeatMonitorExecutor;
|
|
||||||
|
|
||||||
@Resource(name = FastBeeConstant.TASK.MAP_MESSAGE_PUSH)
|
|
||||||
private Executor mapMessagePushExecutor;
|
|
||||||
|
|
||||||
@Resource(name = FastBeeConstant.TASK.COMMON_DEVICE_MONITOR)
|
@Resource(name = FastBeeConstant.TASK.COMMON_DEVICE_MONITOR)
|
||||||
private Executor commonDeviceMonitorExecutor;
|
private Executor commonDeviceMonitorExecutor;
|
||||||
|
|
||||||
@@ -127,19 +121,8 @@ public class InitThread implements ApplicationRunner {
|
|||||||
private void init() throws MqttException {
|
private void init() throws MqttException {
|
||||||
// 初始化InfluxDBUtil
|
// 初始化InfluxDBUtil
|
||||||
GlobalMemory.influxDBUtil = new InfluxDBUtil(influxDBUrl, influxDBToken, influxDBOrg, influxDBBucket);
|
GlobalMemory.influxDBUtil = new InfluxDBUtil(influxDBUrl, influxDBToken, influxDBOrg, influxDBBucket);
|
||||||
|
// 初始化MqttClientUtil
|
||||||
GlobalMemory.initMqttDeviceMonitor(mqttHostUrl, mqttClientId, mqttUsername, mqttPassword);
|
GlobalMemory.mqttClientUtil = new MqttClientUtil(mqttHostUrl, mqttClientId, mqttUsername, mqttPassword);
|
||||||
|
|
||||||
// 地图监控推送
|
|
||||||
mapMessagePushExecutor.execute(() -> {
|
|
||||||
deviceThreadService.mapMessagePush();
|
|
||||||
});
|
|
||||||
|
|
||||||
// 上位机设备心跳监控
|
|
||||||
deviceHeartBeatMonitorExecutor.execute(() -> {
|
|
||||||
deviceThreadService.heartBeatMonitor();
|
|
||||||
});
|
|
||||||
|
|
||||||
// 设备错误监听线程
|
// 设备错误监听线程
|
||||||
deviceErrorMonitorExecutor.execute(() -> {
|
deviceErrorMonitorExecutor.execute(() -> {
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -4,13 +4,10 @@ import java.util.List;
|
|||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import com.maibu.memory.DeviceSessionManager;
|
import com.maibu.memory.DeviceSessionManager;
|
||||||
import com.maibu.memory.GlobalMemory;
|
|
||||||
import com.maibu.mqtt.MqttTopic;
|
|
||||||
import org.apache.commons.codec.binary.Hex;
|
import org.apache.commons.codec.binary.Hex;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
import org.springframework.util.CollectionUtils;
|
import org.springframework.util.CollectionUtils;
|
||||||
|
|
||||||
@@ -35,9 +32,6 @@ public class CommandForwardHandler extends SimpleChannelInboundHandler<String> {
|
|||||||
@Autowired
|
@Autowired
|
||||||
private DeviceSessionManager deviceSessionManager;
|
private DeviceSessionManager deviceSessionManager;
|
||||||
|
|
||||||
@Value("${mqtt.client-id}")
|
|
||||||
private String mqttClientId;
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void channelRead0(ChannelHandlerContext ctx, String msg) throws Exception {
|
protected void channelRead0(ChannelHandlerContext ctx, String msg) throws Exception {
|
||||||
Channel currentChannel = ctx.channel();
|
Channel currentChannel = ctx.channel();
|
||||||
@@ -84,14 +78,11 @@ public class CommandForwardHandler extends SimpleChannelInboundHandler<String> {
|
|||||||
logger.debug("发送拒绝master:{},消息到达的slave设备:{},处于禁止接收状态", senderDeviceId, target.getConnectorId());
|
logger.debug("发送拒绝master:{},消息到达的slave设备:{},处于禁止接收状态", senderDeviceId, target.getConnectorId());
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
// todo 向上位机发送控制消息
|
Channel targetChannel = target.getChannel();
|
||||||
|
if (targetChannel != null && targetChannel.isActive()) {
|
||||||
GlobalMemory.customMqttDeviceMonitor.publish(mqttClientId, String.format(MqttTopic.MOWER_CONTROL_SET, target.getConnectorId()), msg);
|
targetChannel.writeAndFlush(msg);
|
||||||
// Channel targetChannel = target.getChannel();
|
logger.debug("从master:{},向slave:{}, 转发消息:{}", senderDeviceId, target.getConnectorId(), msg);
|
||||||
// if (targetChannel != null && targetChannel.isActive()) {
|
}
|
||||||
// targetChannel.writeAndFlush(msg);
|
|
||||||
// logger.debug("从master:{},向slave:{}, 转发消息:{}", senderDeviceId, target.getConnectorId(), msg);
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
} else if (ConnectorType.SLAVE.equals(senderNettyDevice.getDeviceType())) {
|
} else if (ConnectorType.SLAVE.equals(senderNettyDevice.getDeviceType())) {
|
||||||
List<NettyDevice> masters = deviceSessionManager.getMastersBySlaveId(senderDeviceId);
|
List<NettyDevice> masters = deviceSessionManager.getMastersBySlaveId(senderDeviceId);
|
||||||
|
|||||||
@@ -13,17 +13,18 @@ import com.maibu.constant.Constant;
|
|||||||
import com.maibu.core.business.DeviceRunParam;
|
import com.maibu.core.business.DeviceRunParam;
|
||||||
import com.maibu.mapper.DeviceRunParamMapper;
|
import com.maibu.mapper.DeviceRunParamMapper;
|
||||||
import com.maibu.memory.DeviceSessionManager;
|
import com.maibu.memory.DeviceSessionManager;
|
||||||
|
import com.maibu.memory.SiteMemory;
|
||||||
import org.apache.commons.codec.binary.Hex;
|
import org.apache.commons.codec.binary.Hex;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.eclipse.paho.client.mqttv3.MqttException;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
import org.springframework.util.CollectionUtils;
|
import org.springframework.util.CollectionUtils;
|
||||||
|
|
||||||
import com.maibu.constant.CommandConstant;
|
import com.maibu.constant.CommandConstant;
|
||||||
import com.maibu.constant.NettyCacheKey;
|
import com.maibu.common.NettyCacheKey;
|
||||||
import com.maibu.core.business.DeviceRunStatistics;
|
import com.maibu.core.business.DeviceRunStatistics;
|
||||||
import com.maibu.core.business.DeviceRunningStatusHistory;
|
import com.maibu.core.business.DeviceRunningStatusHistory;
|
||||||
import com.maibu.core.business.DeviceStatusRecordDTO;
|
import com.maibu.core.business.DeviceStatusRecordDTO;
|
||||||
@@ -32,7 +33,7 @@ import com.maibu.core.business.device.NettyDevice;
|
|||||||
import com.maibu.core.business.inter.WebsocketMesDispather;
|
import com.maibu.core.business.inter.WebsocketMesDispather;
|
||||||
import com.maibu.core.enums.MesType;
|
import com.maibu.core.enums.MesType;
|
||||||
import com.maibu.core.redis.RedisCache;
|
import com.maibu.core.redis.RedisCache;
|
||||||
import com.maibu.core.business.dto.WebStatusMessageDTO;
|
import com.maibu.dto.WebStatusMessageDTO;
|
||||||
import com.maibu.influxdb.MowerRealTimeData;
|
import com.maibu.influxdb.MowerRealTimeData;
|
||||||
import com.maibu.influxdb.util.InfluxSqlBuilder;
|
import com.maibu.influxdb.util.InfluxSqlBuilder;
|
||||||
import com.maibu.memory.GlobalMemory;
|
import com.maibu.memory.GlobalMemory;
|
||||||
@@ -62,9 +63,6 @@ public class DataToDataBaseHandler extends SimpleChannelInboundHandler<String> {
|
|||||||
@Autowired
|
@Autowired
|
||||||
private DeviceRunParamMapper deviceRunParamMapper;
|
private DeviceRunParamMapper deviceRunParamMapper;
|
||||||
|
|
||||||
@Value("${mqtt.client-id}")
|
|
||||||
private String mqttClientId;
|
|
||||||
|
|
||||||
private static final Long recordInterval = 5000L; // 5秒记录一次
|
private static final Long recordInterval = 5000L; // 5秒记录一次
|
||||||
|
|
||||||
// private static final Long pushInterval = 500L; // 0.5秒推送一次
|
// private static final Long pushInterval = 500L; // 0.5秒推送一次
|
||||||
@@ -98,9 +96,13 @@ public class DataToDataBaseHandler extends SimpleChannelInboundHandler<String> {
|
|||||||
String deviceStatus = new String(bytes, 2, bytes.length - 4, StandardCharsets.UTF_8).trim();
|
String deviceStatus = new String(bytes, 2, bytes.length - 4, StandardCharsets.UTF_8).trim();
|
||||||
String[] split = deviceStatus.split(",");
|
String[] split = deviceStatus.split(",");
|
||||||
WebStatusMessageDTO dto = createWebDeviceStatusMessage(split);
|
WebStatusMessageDTO dto = createWebDeviceStatusMessage(split);
|
||||||
GlobalMemory.customMqttDeviceMonitor.publish(mqttClientId,
|
try {
|
||||||
String.format(MqttTopic.DEVICE_STATUS_TOPIC, deviceID),
|
GlobalMemory.mqttClientUtil.publish(
|
||||||
JsonUtils.toJsonString(dto));
|
String.format(MqttTopic.DEVICE_STATUS_TOPIC, deviceID),
|
||||||
|
JsonUtils.toJsonString(dto));
|
||||||
|
} catch (MqttException e) {
|
||||||
|
logger.error("发送实时状态数据错误: {}", e.getMessage());
|
||||||
|
}
|
||||||
List<NettyDevice> controlMasters = deviceSessionManager
|
List<NettyDevice> controlMasters = deviceSessionManager
|
||||||
.getAllSlaveControl(deviceID);
|
.getAllSlaveControl(deviceID);
|
||||||
if (!CollectionUtils.isEmpty(controlMasters)) {
|
if (!CollectionUtils.isEmpty(controlMasters)) {
|
||||||
@@ -134,15 +136,19 @@ public class DataToDataBaseHandler extends SimpleChannelInboundHandler<String> {
|
|||||||
latestStatus.setDeviceId(deviceID);
|
latestStatus.setDeviceId(deviceID);
|
||||||
} else {
|
} else {
|
||||||
latestStatus = nettyDevice.getLatestStatus();
|
latestStatus = nettyDevice.getLatestStatus();
|
||||||
|
// 使用Duration.between计算两个时间点之间的持续时间
|
||||||
|
Duration duration = Duration.between(latestStatus.getStartTime(), LocalDateTime.now());
|
||||||
|
long minutes = duration.toMinutes();
|
||||||
|
latestStatus.setTime(minutes);
|
||||||
}
|
}
|
||||||
latestStatus.setWorkArea(Double.valueOf(workArea));
|
latestStatus.setWorkArea(Double.valueOf(workArea));
|
||||||
latestStatus.setDistance(Double.valueOf(workArea) / 0.8);
|
|
||||||
nettyDevice.setLatestStatus(latestStatus);
|
nettyDevice.setLatestStatus(latestStatus);
|
||||||
}
|
}
|
||||||
} else if (bytes[2] == CommandConstant.readConfig) {
|
} else if (bytes[2] == CommandConstant.readConfig) {
|
||||||
DeviceRunParam runParam = DeviceRunParam.fromBytes(bytes);
|
DeviceRunParam runParam = DeviceRunParam.fromBytes(bytes);
|
||||||
logger.debug("收到返回的设备运行参数: {}", JsonUtils.toJsonString(runParam));
|
logger.debug("收到返回的设备运行参数: {}", JsonUtils.toJsonString(runParam));
|
||||||
CompletableFuture<DeviceRunParam> future = ctx.channel().attr(Constant.READ_CONFIG_KEY).get();
|
CompletableFuture<DeviceRunParam> future =
|
||||||
|
ctx.channel().attr(Constant.READ_CONFIG_KEY).get();
|
||||||
if (future != null) {
|
if (future != null) {
|
||||||
future.complete(runParam);
|
future.complete(runParam);
|
||||||
ctx.channel().attr(Constant.READ_CONFIG_KEY).set(null);
|
ctx.channel().attr(Constant.READ_CONFIG_KEY).set(null);
|
||||||
@@ -154,6 +160,7 @@ public class DataToDataBaseHandler extends SimpleChannelInboundHandler<String> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public WebStatusMessageDTO createWebDeviceStatusMessage(String[] split) {
|
public WebStatusMessageDTO createWebDeviceStatusMessage(String[] split) {
|
||||||
WebStatusMessageDTO webStatusMessageDTO = new WebStatusMessageDTO();
|
WebStatusMessageDTO webStatusMessageDTO = new WebStatusMessageDTO();
|
||||||
List<DeviceStatusDetail> transferData = transferStatusData(split);
|
List<DeviceStatusDetail> transferData = transferStatusData(split);
|
||||||
|
|||||||
@@ -8,23 +8,23 @@ import java.util.concurrent.ConcurrentHashMap;
|
|||||||
|
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
|
|
||||||
|
import com.maibu.memory.DeviceSessionManager;
|
||||||
import org.apache.commons.codec.binary.Hex;
|
import org.apache.commons.codec.binary.Hex;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.eclipse.paho.client.mqttv3.MqttException;
|
import org.eclipse.paho.client.mqttv3.MqttException;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
import org.springframework.util.CollectionUtils;
|
import org.springframework.util.CollectionUtils;
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
|
||||||
import com.maibu.constant.CommandConstant;
|
import com.maibu.constant.CommandConstant;
|
||||||
import com.maibu.constant.Constant;
|
import com.maibu.constant.Constant;
|
||||||
import com.maibu.core.business.Device;
|
import com.maibu.core.business.Device;
|
||||||
import com.maibu.core.business.DeviceRunStatistics;
|
|
||||||
import com.maibu.core.business.device.NettyDevice;
|
import com.maibu.core.business.device.NettyDevice;
|
||||||
import com.maibu.core.business.inter.WebsocketMesDispather;
|
import com.maibu.core.business.inter.WebsocketMesDispather;
|
||||||
|
import com.maibu.core.domain.entity.SysUser;
|
||||||
|
import com.maibu.core.domain.entity.UserClient;
|
||||||
import com.maibu.core.enums.CommandRequestType;
|
import com.maibu.core.enums.CommandRequestType;
|
||||||
import com.maibu.core.enums.ConnectionCloseReason;
|
import com.maibu.core.enums.ConnectionCloseReason;
|
||||||
import com.maibu.core.enums.ConnectorStatus;
|
import com.maibu.core.enums.ConnectorStatus;
|
||||||
@@ -33,12 +33,12 @@ import com.maibu.core.enums.DeviceStatus;
|
|||||||
import com.maibu.core.enums.DeviceTaskStaus;
|
import com.maibu.core.enums.DeviceTaskStaus;
|
||||||
import com.maibu.core.enums.MesType;
|
import com.maibu.core.enums.MesType;
|
||||||
import com.maibu.core.enums.RespondCode;
|
import com.maibu.core.enums.RespondCode;
|
||||||
|
import com.maibu.dto.DeviceLoginResponseDTO;
|
||||||
import com.maibu.dto.DeviceRequestDTO;
|
import com.maibu.dto.DeviceRequestDTO;
|
||||||
import com.maibu.dto.DeviceRespondDTO;
|
import com.maibu.dto.DeviceRespondDTO;
|
||||||
import com.maibu.dto.DeviceStatusChangeDTO;
|
import com.maibu.dto.DeviceStatusChangeDTO;
|
||||||
import com.maibu.dto.DeviceTaskStatusMessageDTO;
|
import com.maibu.dto.DeviceTaskStatusMessageDTO;
|
||||||
import com.maibu.mapper.DeviceRunStatisticsMapper;
|
import com.maibu.mapper.DeviceRunStatisticsMapper;
|
||||||
import com.maibu.memory.DeviceSessionManager;
|
|
||||||
import com.maibu.memory.GlobalMemory;
|
import com.maibu.memory.GlobalMemory;
|
||||||
import com.maibu.mqtt.MqttTopic;
|
import com.maibu.mqtt.MqttTopic;
|
||||||
import com.maibu.service.IDeviceService;
|
import com.maibu.service.IDeviceService;
|
||||||
@@ -73,15 +73,15 @@ public class DeviceConnectHandler extends SimpleChannelInboundHandler<String> {
|
|||||||
@Autowired
|
@Autowired
|
||||||
private IDeviceService deviceService;
|
private IDeviceService deviceService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private ISysUserService userService;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private DeviceRunStatisticsMapper deviceRunStatisticsMapper;
|
private DeviceRunStatisticsMapper deviceRunStatisticsMapper;
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
private WebsocketMesDispather websocketMesDispather;
|
private WebsocketMesDispather websocketMesDispather;
|
||||||
|
|
||||||
@Value("${mqtt.client-id}")
|
|
||||||
private String mqttClientId;
|
|
||||||
|
|
||||||
public DeviceConnectHandler(DeviceSessionManager sessionManager) {
|
public DeviceConnectHandler(DeviceSessionManager sessionManager) {
|
||||||
this.sessionManager = sessionManager;
|
this.sessionManager = sessionManager;
|
||||||
}
|
}
|
||||||
@@ -115,8 +115,6 @@ public class DeviceConnectHandler extends SimpleChannelInboundHandler<String> {
|
|||||||
logger.info("{}: 设备断开 status: {}", deviceId, ConnectorStatus.DISABLED);
|
logger.info("{}: 设备断开 status: {}", deviceId, ConnectorStatus.DISABLED);
|
||||||
// updateLogoutSingle(deviceId);
|
// updateLogoutSingle(deviceId);
|
||||||
// todo 自动切换到其他?
|
// todo 自动切换到其他?
|
||||||
|
|
||||||
sessionManager.unLock(deviceId);
|
|
||||||
}
|
}
|
||||||
if (nettyDevice != null && nettyDevice.getDeviceType() == ConnectorType.SLAVE) {
|
if (nettyDevice != null && nettyDevice.getDeviceType() == ConnectorType.SLAVE) {
|
||||||
nettyDevice.setOnlineStatus(0);
|
nettyDevice.setOnlineStatus(0);
|
||||||
@@ -145,24 +143,8 @@ public class DeviceConnectHandler extends SimpleChannelInboundHandler<String> {
|
|||||||
// todo 更新历史作业消息
|
// todo 更新历史作业消息
|
||||||
}
|
}
|
||||||
if (nettyDevice.getLatestStatus() != null) {
|
if (nettyDevice.getLatestStatus() != null) {
|
||||||
|
nettyDevice.getLatestStatus().setEndTime(LocalDateTime.now());
|
||||||
LambdaQueryWrapper<DeviceRunStatistics> queryWrapper = new LambdaQueryWrapper<>();
|
deviceRunStatisticsMapper.insert(nettyDevice.getLatestStatus());
|
||||||
queryWrapper.eq(DeviceRunStatistics::getDeviceId, deviceId);
|
|
||||||
DeviceRunStatistics existing = deviceRunStatisticsMapper
|
|
||||||
.selectOne(queryWrapper);
|
|
||||||
if (existing != null) {
|
|
||||||
nettyDevice.getLatestStatus().setId(existing.getId());
|
|
||||||
nettyDevice.getLatestStatus().setDistance(
|
|
||||||
existing.getDistance() + nettyDevice.getLatestStatus().getDistance());
|
|
||||||
nettyDevice.getLatestStatus().setWorkArea(
|
|
||||||
existing.getWorkArea() + nettyDevice.getLatestStatus().getWorkArea());
|
|
||||||
long time = System.currentTimeMillis() - nettyDevice.getLatestLoginTime();
|
|
||||||
nettyDevice.getLatestStatus().setTime(existing.getTime() + time / (1000 * 60)); // 累加时长,单位为分钟
|
|
||||||
} else {
|
|
||||||
long time = System.currentTimeMillis() - nettyDevice.getLatestLoginTime();
|
|
||||||
nettyDevice.getLatestStatus().setTime(time / (1000 * 60)); // 累加时长,单位为分钟
|
|
||||||
}
|
|
||||||
deviceRunStatisticsMapper.saveOrUpdate(nettyDevice.getLatestStatus());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
sessionManager.removeDevice(deviceId);
|
sessionManager.removeDevice(deviceId);
|
||||||
@@ -173,7 +155,7 @@ public class DeviceConnectHandler extends SimpleChannelInboundHandler<String> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void channelRead0(ChannelHandlerContext ctx, String msg) {
|
protected void channelRead0(ChannelHandlerContext ctx, String msg) throws Exception {
|
||||||
try {
|
try {
|
||||||
byte[] bytes = Hex.decodeHex(msg.toCharArray());
|
byte[] bytes = Hex.decodeHex(msg.toCharArray());
|
||||||
|
|
||||||
@@ -199,13 +181,86 @@ public class DeviceConnectHandler extends SimpleChannelInboundHandler<String> {
|
|||||||
logger.info("上位机连接 sessionId: {}", sessionId);
|
logger.info("上位机连接 sessionId: {}", sessionId);
|
||||||
logger.info("上位机连接 userName: {}", userName);
|
logger.info("上位机连接 userName: {}", userName);
|
||||||
logger.info("上位机连接 type: {}", parts[1]);
|
logger.info("上位机连接 type: {}", parts[1]);
|
||||||
|
SysUser sysUser = userService.selectUserByUserName(userName);
|
||||||
|
if (sysUser != null) {
|
||||||
|
sysUserClientService.insertUserClient(sysUser.getUserId(), userName, deviceId, "", 0);
|
||||||
|
}
|
||||||
|
// 如果 当前角色存在sessionId同时和当前的穿过来不同则下发剔除指令
|
||||||
|
boolean t = false;
|
||||||
|
if (StringUtils.isEmpty(sessionId) || sysUser == null) {
|
||||||
|
t = true;
|
||||||
|
}
|
||||||
|
if (sysUser != null && !StringUtils.isEmpty(sessionId)
|
||||||
|
&& !StringUtils.isEmpty(sysUser.getSessionId())) {
|
||||||
|
if (!sysUser.getSessionId().equals(sessionId)) {
|
||||||
|
t = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (t) {
|
||||||
|
// 发送已登录状态到客户端
|
||||||
|
if ("web".equals(parts[1])) {
|
||||||
|
NettyDevice device = sessionManager.getDevice(deviceId);
|
||||||
|
logger.info("web 上位机连接重连: {}", JsonUtils.toJsonString(device));
|
||||||
|
if (device != null && !StringUtils.isEmpty(device.getCurrentSlaveId())) {
|
||||||
|
logger.info("上位机连接重连: {}", deviceId);
|
||||||
|
} else {
|
||||||
|
// 判断是否账号在控制空 如果在控制设置账号为非active
|
||||||
|
List<UserClient> userClients = sysUserClientService
|
||||||
|
.selectUserClientByUserName(userName);
|
||||||
|
ConnectorStatus status = ConnectorStatus.ACTIVE;
|
||||||
|
logger.info("web 上位机连接重连2: {}", JsonUtils.toJsonString(userClients));
|
||||||
|
UserClient nowClient = null;
|
||||||
|
if (!CollectionUtils.isEmpty(userClients)) {
|
||||||
|
long count = userClients.stream().filter(
|
||||||
|
x -> x.getIsAlive() == 1 && !deviceId.equals(x.getClientName()))
|
||||||
|
.count();
|
||||||
|
if (count > 0) {
|
||||||
|
status = ConnectorStatus.RECEIVER;
|
||||||
|
}
|
||||||
|
nowClient = userClients.stream().filter(
|
||||||
|
x -> x.getIsAlive() == 1 && deviceId.equals(x.getClientName()))
|
||||||
|
.findFirst().orElse(null);
|
||||||
|
}
|
||||||
|
logger.info("web 上位机连接重连3: {}", JsonUtils.toJsonString(status));
|
||||||
|
if (!ConnectorStatus.ACTIVE.equals(status)) {
|
||||||
|
handleMasterConnect(ctx, deviceId, null, status);
|
||||||
|
} else {
|
||||||
|
logger.info("web 上位机连接重连4: {}", JsonUtils.toJsonString(nowClient));
|
||||||
|
if (nowClient != null) {
|
||||||
|
handleMasterConnect(ctx, deviceId, nowClient.getDeviceName(), status);
|
||||||
|
} else {
|
||||||
|
handleMasterConnect(ctx, deviceId, null, status);
|
||||||
|
}
|
||||||
|
|
||||||
NettyDevice masterDevice = sessionManager.getDevice(sessionId);
|
}
|
||||||
if (masterDevice == null) {
|
}
|
||||||
// sessionManager.getControl(sessionId);
|
} else {
|
||||||
handleMasterConnect(ctx, sessionId, null, ConnectorStatus.ACTIVE);
|
DeviceLoginResponseDTO responseDTO = new DeviceLoginResponseDTO();
|
||||||
|
responseDTO.setRespond(RespondCode.have_logged_in);
|
||||||
|
ByteBuf buf = ctx.alloc().buffer();
|
||||||
|
CommandUtils.buildCommand(buf, responseDTO, CommandConstant.interaction);
|
||||||
|
ctx.channel().writeAndFlush(buf);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
ctx.channel().attr(Constant.ATT_DEVICE_ID).set(sessionId);
|
// 判断是否账号在控制空 如果在控制设置账号为非active
|
||||||
|
List<UserClient> userClients = sysUserClientService
|
||||||
|
.selectUserClientByUserName(userName);
|
||||||
|
ConnectorStatus status = ConnectorStatus.ACTIVE;
|
||||||
|
if (!CollectionUtils.isEmpty(userClients)) {
|
||||||
|
long count = userClients.stream()
|
||||||
|
.filter(x -> x.getIsAlive() == 1 && !deviceId.equals(x.getClientName()))
|
||||||
|
.count();
|
||||||
|
if (count > 0) {
|
||||||
|
status = ConnectorStatus.RECEIVER;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
logger.info("上位机上线:{}", status);
|
||||||
|
// if (ConnectorStatus.ACTIVE.equals(status)) {
|
||||||
|
// //todo 设置当前控制的token
|
||||||
|
// sysUser.setSessionId(sessionId);
|
||||||
|
// userService.updateUserProfile(sysUser);
|
||||||
|
// }
|
||||||
|
handleMasterConnect(ctx, deviceId, null, status);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -220,17 +275,15 @@ public class DeviceConnectHandler extends SimpleChannelInboundHandler<String> {
|
|||||||
device.setDeviceName(data);
|
device.setDeviceName(data);
|
||||||
device.setProductId(-1L);
|
device.setProductId(-1L);
|
||||||
device.setTenantId(-1L);
|
device.setTenantId(-1L);
|
||||||
device.setFirmwareVersion("1.0");
|
device.setFirmwareVersion(BigDecimal.valueOf(1.0));
|
||||||
device.setProductName("割草机产品MC700");
|
device.setProductName("割草机产品MC700");
|
||||||
device.setCreateTime(LocalDateTime.now());
|
device.setCreateTime(LocalDateTime.now());
|
||||||
device.setUpdateTime(LocalDateTime.now());
|
device.setUpdateTime(LocalDateTime.now());
|
||||||
device.setHasHost(false);
|
|
||||||
deviceService.insertDeviceBySelf(device);
|
deviceService.insertDeviceBySelf(device);
|
||||||
} else {
|
} else {
|
||||||
device.setStatus(3);
|
device.setStatus(3);
|
||||||
device.setOnlineStatus(DeviceStatus.online.getType());
|
device.setOnlineStatus(DeviceStatus.online.getType());
|
||||||
device.setUpdateTime(LocalDateTime.now());
|
device.setUpdateTime(LocalDateTime.now());
|
||||||
device.setHasHost(false);
|
|
||||||
deviceService.updateDeviceBySelf(device);
|
deviceService.updateDeviceBySelf(device);
|
||||||
}
|
}
|
||||||
NettyDevice slaveDevice = sessionManager.getDevice(data);
|
NettyDevice slaveDevice = sessionManager.getDevice(data);
|
||||||
@@ -238,24 +291,23 @@ public class DeviceConnectHandler extends SimpleChannelInboundHandler<String> {
|
|||||||
slaveDevice.setOnlineStatus(1);
|
slaveDevice.setOnlineStatus(1);
|
||||||
slaveDevice.setDevice(device);
|
slaveDevice.setDevice(device);
|
||||||
}
|
}
|
||||||
// // 推送json 找到设备绑定的主机进行推送
|
// 推送json 找到设备绑定的主机进行推送
|
||||||
// List<NettyDevice> controlMasters =
|
List<NettyDevice> controlMasters = sessionManager.getAllSlaveControl(device.getSerialNumber());
|
||||||
// sessionManager.getAllSlaveControl(device.getSerialNumber());
|
if (!CollectionUtils.isEmpty(controlMasters)) {
|
||||||
// if (!CollectionUtils.isEmpty(controlMasters)) {
|
controlMasters.forEach(x -> {
|
||||||
// controlMasters.forEach(x -> {
|
DeviceStatusChangeDTO changeDTO = new DeviceStatusChangeDTO();
|
||||||
// DeviceStatusChangeDTO changeDTO = new DeviceStatusChangeDTO();
|
changeDTO.setDeviceId(data);
|
||||||
// changeDTO.setDeviceId(data);
|
changeDTO.setStatus(DeviceStatus.online.getCode());
|
||||||
// changeDTO.setStatus(DeviceStatus.online.getCode());
|
changeDTO.setEvent(RespondCode.device_status_changed);
|
||||||
// changeDTO.setEvent(RespondCode.device_status_changed);
|
ByteBuf buf = ctx.alloc().buffer();
|
||||||
// ByteBuf buf = ctx.alloc().buffer();
|
CommandUtils.buildCommand(buf, changeDTO, CommandConstant.interaction);
|
||||||
// CommandUtils.buildCommand(buf, changeDTO, CommandConstant.interaction);
|
String content = buf.toString(CharsetUtil.UTF_8);
|
||||||
// String content = buf.toString(CharsetUtil.UTF_8);
|
logger.info("推送下位机登录状态消息:{}", content);
|
||||||
// logger.info("推送下位机登录状态消息:{}", content);
|
if (x.getChannel() != null && x.getChannel().isActive()) {
|
||||||
// if (x.getChannel() != null && x.getChannel().isActive()) {
|
x.getChannel().writeAndFlush(buf);
|
||||||
// x.getChannel().writeAndFlush(buf);
|
}
|
||||||
// }
|
});
|
||||||
// });
|
}
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (cmdType == CommandConstant.interaction) {
|
} else if (cmdType == CommandConstant.interaction) {
|
||||||
@@ -302,7 +354,7 @@ public class DeviceConnectHandler extends SimpleChannelInboundHandler<String> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void pushFinishData(NettyDevice device, String deviceId) throws MqttException {
|
public void pushFinishData(NettyDevice device, String deviceId) {
|
||||||
Long taskId = device.finishTask();
|
Long taskId = device.finishTask();
|
||||||
// todo 推送信息给前端
|
// todo 推送信息给前端
|
||||||
DeviceTaskStatusMessageDTO changeDTO = new DeviceTaskStatusMessageDTO();
|
DeviceTaskStatusMessageDTO changeDTO = new DeviceTaskStatusMessageDTO();
|
||||||
@@ -311,9 +363,12 @@ public class DeviceConnectHandler extends SimpleChannelInboundHandler<String> {
|
|||||||
changeDTO.setType(MesType.device_task_change);
|
changeDTO.setType(MesType.device_task_change);
|
||||||
changeDTO.setTaskId(taskId);
|
changeDTO.setTaskId(taskId);
|
||||||
|
|
||||||
GlobalMemory.customMqttDeviceMonitor.publish(mqttClientId,
|
try {
|
||||||
String.format(MqttTopic.DEVICE_TASK_STATUS_TOPIC, taskId),
|
GlobalMemory.mqttClientUtil.publish(String.format(MqttTopic.DEVICE_TASK_STATUS_TOPIC, taskId),
|
||||||
JsonUtils.toJsonString(changeDTO));
|
JsonUtils.toJsonString(changeDTO));
|
||||||
|
} catch (MqttException e) {
|
||||||
|
logger.error("任务完成状态推送失败 task:{},device:{}error:{}", taskId, deviceId, e.getMessage());
|
||||||
|
}
|
||||||
List<NettyDevice> controlMasters = sessionManager
|
List<NettyDevice> controlMasters = sessionManager
|
||||||
.getAllSlaveControl(deviceId);
|
.getAllSlaveControl(deviceId);
|
||||||
if (!CollectionUtils.isEmpty(controlMasters)) {
|
if (!CollectionUtils.isEmpty(controlMasters)) {
|
||||||
@@ -327,7 +382,7 @@ public class DeviceConnectHandler extends SimpleChannelInboundHandler<String> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void pushArriveData(NettyDevice device, String deviceId) throws MqttException {
|
public void pushArriveData(NettyDevice device, String deviceId) {
|
||||||
Long taskId = device.getTask() == null ? null : device.getTask().getId();
|
Long taskId = device.getTask() == null ? null : device.getTask().getId();
|
||||||
// todo 推送信息给前端
|
// todo 推送信息给前端
|
||||||
DeviceTaskStatusMessageDTO reportDTO = new DeviceTaskStatusMessageDTO();
|
DeviceTaskStatusMessageDTO reportDTO = new DeviceTaskStatusMessageDTO();
|
||||||
@@ -335,9 +390,13 @@ public class DeviceConnectHandler extends SimpleChannelInboundHandler<String> {
|
|||||||
reportDTO.setTaskId(taskId);
|
reportDTO.setTaskId(taskId);
|
||||||
reportDTO.setEntity(device.getCurrentPoint());
|
reportDTO.setEntity(device.getCurrentPoint());
|
||||||
reportDTO.setType(MesType.device_task_arrive_point);
|
reportDTO.setType(MesType.device_task_arrive_point);
|
||||||
GlobalMemory.customMqttDeviceMonitor.publish(mqttClientId,
|
try {
|
||||||
String.format(MqttTopic.DEVICE_TASK_ARRIVE_TOPIC, taskId),
|
|
||||||
JsonUtils.toJsonString(reportDTO));
|
GlobalMemory.mqttClientUtil.publish(String.format(MqttTopic.DEVICE_TASK_ARRIVE_TOPIC, taskId),
|
||||||
|
JsonUtils.toJsonString(reportDTO));
|
||||||
|
} catch (MqttException e) {
|
||||||
|
logger.error("任务点位到达推送失败 task:{},device:{}error:{}", taskId, deviceId, e.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
List<NettyDevice> controlMasters = sessionManager
|
List<NettyDevice> controlMasters = sessionManager
|
||||||
.getAllSlaveControl(deviceId);
|
.getAllSlaveControl(deviceId);
|
||||||
@@ -369,20 +428,17 @@ public class DeviceConnectHandler extends SimpleChannelInboundHandler<String> {
|
|||||||
logger.info("12指令切换权限,c:{}", c.getConnectorId());
|
logger.info("12指令切换权限,c:{}", c.getConnectorId());
|
||||||
if (!c.getConnectorId().equals(masterId)) {
|
if (!c.getConnectorId().equals(masterId)) {
|
||||||
// c.setCurrentSlaveId(null);
|
// c.setCurrentSlaveId(null);
|
||||||
// c.removeConnectedDevice(slaveDevice);
|
c.removeConnectedDevice(slaveDevice);
|
||||||
c.setConnectorStatus(ConnectorStatus.RECEIVER);
|
c.setConnectorStatus(ConnectorStatus.RECEIVER);
|
||||||
sessionManager.unLock(c.getConnectorId());
|
sysUserClientService.updateAliveStatus(c.getConnectorId(), slaveId, 2);
|
||||||
// sysUserClientService.updateAliveStatus(c.getConnectorId(), slaveId, 2);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
logger.info("12指令解析,切换权限,slaveId:{},masterId :{}", slaveId, masterId);
|
logger.info("12指令解析,切换权限,slaveId:{},masterId :{}", slaveId, masterId);
|
||||||
sessionManager.lock(slaveId, masterId);
|
|
||||||
masterDevice.setCurrentSlaveId(slaveId);
|
masterDevice.setCurrentSlaveId(slaveId);
|
||||||
masterDevice.setConnectorStatus(ConnectorStatus.ACTIVE);
|
masterDevice.setConnectorStatus(ConnectorStatus.ACTIVE);
|
||||||
masterDevice.addConnectedDevice(slaveDevice);
|
masterDevice.addConnectedDevice(slaveDevice);
|
||||||
// sysUserClientService.updateAliveStatus(masterDevice.getConnectorId(),
|
sysUserClientService.updateAliveStatus(masterDevice.getConnectorId(), slaveId, 1);
|
||||||
// slaveId, 1);
|
|
||||||
} else {
|
} else {
|
||||||
logger.info("权限切换请求被拒绝");
|
logger.info("权限切换请求被拒绝");
|
||||||
}
|
}
|
||||||
@@ -413,122 +469,69 @@ public class DeviceConnectHandler extends SimpleChannelInboundHandler<String> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// /**
|
|
||||||
// * 找到当前设备控制的主机 转发控制请求
|
|
||||||
// */
|
|
||||||
// private void handlePermissionRequest(DeviceRequestDTO requestDTO, byte[]
|
|
||||||
// bytes, ChannelHandlerContext ctx) {
|
|
||||||
// logger.info("转发控制请求 :{}", JsonUtils.toJsonString(requestDTO));
|
|
||||||
// String slaveId = requestDTO.getDeviceId();
|
|
||||||
// List<NettyDevice> controlList = sessionManager.getSlaveControl(slaveId);
|
|
||||||
// String masterId = requestDTO.getUserId() + ":" + requestDTO.getPlatform();
|
|
||||||
// logger.info("转发控制请求 controlList :{}", JsonUtils.toJsonString(controlList));
|
|
||||||
// if (!CollectionUtils.isEmpty(controlList)) {
|
|
||||||
// // 如果当前设备有控制
|
|
||||||
// logger.info("转发控制请求 发送报文");
|
|
||||||
// NettyDevice controlDevice = controlList.get(0);
|
|
||||||
// if (controlDevice != null && controlDevice.getChannel() != null &&
|
|
||||||
// controlDevice.getChannel().isActive()) {
|
|
||||||
// controlDevice.getChannel().writeAndFlush(Unpooled.wrappedBuffer(bytes));
|
|
||||||
// logger.info("转发控制请求 发送报文结束 deviceId :{}", controlDevice.getConnectorId());
|
|
||||||
// controlRequestMap.put(masterId, slaveId);
|
|
||||||
// logger.info("转发控制请求 controlRequestMap:{}",
|
|
||||||
// JsonUtils.toJsonString(controlRequestMap));
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// } else {
|
|
||||||
// // 判断直接给权限 还是 判断是否有该账号其他端的的控制有权限
|
|
||||||
// NettyDevice activeDevice =
|
|
||||||
// sessionManager.getUserControl(requestDTO.getUserId());
|
|
||||||
// boolean sendMes = true;
|
|
||||||
// if (activeDevice == null) {
|
|
||||||
// sendMes = false;
|
|
||||||
// } else {
|
|
||||||
// if (activeDevice.getConnectorId().equals(masterId)) {
|
|
||||||
// sendMes = false;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// if (sendMes) {
|
|
||||||
// if (activeDevice.getChannel() != null &&
|
|
||||||
// activeDevice.getChannel().isActive()) {
|
|
||||||
// activeDevice.getChannel().writeAndFlush(Unpooled.wrappedBuffer(bytes));
|
|
||||||
// logger.info("转发控制请求2 发送报文结束 deviceId :{}", activeDevice.getConnectorId());
|
|
||||||
// controlRequestMap.put(masterId, slaveId);
|
|
||||||
// logger.info("转发控制请求2 controlRequestMap:{}",
|
|
||||||
// JsonUtils.toJsonString(controlRequestMap));
|
|
||||||
// }
|
|
||||||
// } else {
|
|
||||||
// NettyDevice masterDevice = sessionManager.getDevice(masterId);
|
|
||||||
// if (masterDevice != null) {
|
|
||||||
// NettyDevice slaveDevice = sessionManager.getDevice(slaveId);
|
|
||||||
// masterDevice.setCurrentSlaveId(slaveId);
|
|
||||||
// masterDevice.setConnectorStatus(ConnectorStatus.ACTIVE);
|
|
||||||
// masterDevice.addConnectedDevice(slaveDevice);
|
|
||||||
//
|
|
||||||
// sysUserClientService.updateAliveStatus(masterDevice.getConnectorId(),
|
|
||||||
// slaveId, 1);
|
|
||||||
// if (masterDevice.getChannel() != null &&
|
|
||||||
// masterDevice.getChannel().isActive()) {
|
|
||||||
// DeviceRequestDTO reDto = new DeviceRequestDTO();
|
|
||||||
// reDto.setPlatform(requestDTO.getPlatform());
|
|
||||||
// DeviceRespondDTO respond = new DeviceRespondDTO();
|
|
||||||
// respond.setSwitchResult(true);
|
|
||||||
// respond.setHolder("you");
|
|
||||||
// respond.setDeviceId(slaveId);
|
|
||||||
// reDto.setRespond(respond);
|
|
||||||
// ByteBuf buf = ctx.alloc().buffer();
|
|
||||||
// CommandUtils.buildCommand(buf, reDto, CommandConstant.interaction);
|
|
||||||
// String content = buf.toString(CharsetUtil.UTF_8);
|
|
||||||
// masterDevice.getChannel().writeAndFlush(buf);
|
|
||||||
// logger.info("转发控制请求设置当前控制2 发送报文:{} deviceId :{}", content, masterId);
|
|
||||||
// }
|
|
||||||
// } else {
|
|
||||||
//
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 找到当前设备控制的主机 转发控制请求
|
* 找到当前设备控制的主机 转发控制请求
|
||||||
*/
|
*/
|
||||||
private void handlePermissionRequest(DeviceRequestDTO requestDTO, byte[] bytes, ChannelHandlerContext ctx) {
|
private void handlePermissionRequest(DeviceRequestDTO requestDTO, byte[] bytes, ChannelHandlerContext ctx) {
|
||||||
logger.info("转发控制请求 :{}", JsonUtils.toJsonString(requestDTO));
|
logger.info("转发控制请求 :{}", JsonUtils.toJsonString(requestDTO));
|
||||||
String slaveId = requestDTO.getDeviceId();
|
String slaveId = requestDTO.getDeviceId();
|
||||||
String token = requestDTO.getToken();
|
List<NettyDevice> controlList = sessionManager.getSlaveControl(slaveId);
|
||||||
String master = sessionManager.getMaster(slaveId);
|
String masterId = requestDTO.getUserId() + ":" + requestDTO.getPlatform();
|
||||||
if (!StringUtils.isEmpty(master)) {
|
logger.info("转发控制请求 controlList :{}", JsonUtils.toJsonString(controlList));
|
||||||
|
if (!CollectionUtils.isEmpty(controlList)) {
|
||||||
// 如果当前设备有控制
|
// 如果当前设备有控制
|
||||||
logger.info("转发控制请求 发送报文");
|
logger.info("转发控制请求 发送报文");
|
||||||
NettyDevice controlDevice = sessionManager.getDevice(master);
|
NettyDevice controlDevice = controlList.get(0);
|
||||||
if (controlDevice != null && controlDevice.getChannel() != null && controlDevice.getChannel().isActive()) {
|
if (controlDevice != null && controlDevice.getChannel() != null && controlDevice.getChannel().isActive()) {
|
||||||
controlDevice.getChannel().writeAndFlush(Unpooled.wrappedBuffer(bytes));
|
controlDevice.getChannel().writeAndFlush(Unpooled.wrappedBuffer(bytes));
|
||||||
logger.info("转发控制请求 发送报文结束 deviceId :{}", controlDevice.getConnectorId());
|
logger.info("转发控制请求 发送报文结束 deviceId :{}", controlDevice.getConnectorId());
|
||||||
controlRequestMap.put(token, slaveId);
|
controlRequestMap.put(masterId, slaveId);
|
||||||
logger.info("转发控制请求 controlRequestMap:{}", JsonUtils.toJsonString(controlRequestMap));
|
logger.info("转发控制请求 controlRequestMap:{}", JsonUtils.toJsonString(controlRequestMap));
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
NettyDevice masterDevice = sessionManager.getDevice(token);
|
|
||||||
if (masterDevice != null) {
|
|
||||||
NettyDevice slaveDevice = sessionManager.getDevice(slaveId);
|
|
||||||
masterDevice.setCurrentSlaveId(slaveId);
|
|
||||||
masterDevice.setConnectorStatus(ConnectorStatus.ACTIVE);
|
|
||||||
masterDevice.addConnectedDevice(slaveDevice);
|
|
||||||
sessionManager.lock(slaveId, token);
|
|
||||||
|
|
||||||
if (masterDevice.getChannel() != null && masterDevice.getChannel().isActive()) {
|
} else {
|
||||||
DeviceRequestDTO reDto = new DeviceRequestDTO();
|
// 判断直接给权限 还是 判断是否有该账号其他端的的控制有权限
|
||||||
reDto.setPlatform(requestDTO.getPlatform());
|
NettyDevice activeDevice = sessionManager.getUserControl(requestDTO.getUserId());
|
||||||
DeviceRespondDTO respond = new DeviceRespondDTO();
|
boolean sendMes = true;
|
||||||
respond.setSwitchResult(true);
|
if (activeDevice == null) {
|
||||||
respond.setHolder("you");
|
sendMes = false;
|
||||||
respond.setDeviceId(slaveId);
|
} else {
|
||||||
reDto.setRespond(respond);
|
if (activeDevice.getConnectorId().equals(masterId)) {
|
||||||
ByteBuf buf = ctx.alloc().buffer();
|
sendMes = false;
|
||||||
CommandUtils.buildCommand(buf, reDto, CommandConstant.interaction);
|
}
|
||||||
String content = buf.toString(CharsetUtil.UTF_8);
|
}
|
||||||
masterDevice.getChannel().writeAndFlush(buf);
|
if (sendMes) {
|
||||||
logger.info("转发控制请求设置当前控制2 发送报文:{} deviceId :{}", content, token);
|
if (activeDevice.getChannel() != null && activeDevice.getChannel().isActive()) {
|
||||||
|
activeDevice.getChannel().writeAndFlush(Unpooled.wrappedBuffer(bytes));
|
||||||
|
logger.info("转发控制请求2 发送报文结束 deviceId :{}", activeDevice.getConnectorId());
|
||||||
|
controlRequestMap.put(masterId, slaveId);
|
||||||
|
logger.info("转发控制请求2 controlRequestMap:{}", JsonUtils.toJsonString(controlRequestMap));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
NettyDevice masterDevice = sessionManager.getDevice(masterId);
|
||||||
|
if (masterDevice != null) {
|
||||||
|
NettyDevice slaveDevice = sessionManager.getDevice(slaveId);
|
||||||
|
masterDevice.setCurrentSlaveId(slaveId);
|
||||||
|
masterDevice.setConnectorStatus(ConnectorStatus.ACTIVE);
|
||||||
|
masterDevice.addConnectedDevice(slaveDevice);
|
||||||
|
|
||||||
|
sysUserClientService.updateAliveStatus(masterDevice.getConnectorId(), slaveId, 1);
|
||||||
|
if (masterDevice.getChannel() != null && masterDevice.getChannel().isActive()) {
|
||||||
|
DeviceRequestDTO reDto = new DeviceRequestDTO();
|
||||||
|
reDto.setPlatform(requestDTO.getPlatform());
|
||||||
|
DeviceRespondDTO respond = new DeviceRespondDTO();
|
||||||
|
respond.setSwitchResult(true);
|
||||||
|
respond.setHolder("you");
|
||||||
|
respond.setDeviceId(slaveId);
|
||||||
|
reDto.setRespond(respond);
|
||||||
|
ByteBuf buf = ctx.alloc().buffer();
|
||||||
|
CommandUtils.buildCommand(buf, reDto, CommandConstant.interaction);
|
||||||
|
String content = buf.toString(CharsetUtil.UTF_8);
|
||||||
|
masterDevice.getChannel().writeAndFlush(buf);
|
||||||
|
logger.info("转发控制请求设置当前控制2 发送报文:{} deviceId :{}", content, masterId);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -540,7 +543,7 @@ public class DeviceConnectHandler extends SimpleChannelInboundHandler<String> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void handleMasterConnect(ChannelHandlerContext ctx, String masterId, String slaveId,
|
private void handleMasterConnect(ChannelHandlerContext ctx, String masterId, String slaveId,
|
||||||
ConnectorStatus status) {
|
ConnectorStatus status) {
|
||||||
ctx.channel().attr(Constant.ATT_DEVICE_ID).set(masterId);
|
ctx.channel().attr(Constant.ATT_DEVICE_ID).set(masterId);
|
||||||
sessionManager.registerDevice(masterId, ctx.channel(), ConnectorType.MASTER, status, slaveId);
|
sessionManager.registerDevice(masterId, ctx.channel(), ConnectorType.MASTER, status, slaveId);
|
||||||
// sessionManager.bindConnector(masterId, slaveId);
|
// sessionManager.bindConnector(masterId, slaveId);
|
||||||
|
|||||||
@@ -31,8 +31,6 @@ public class HeartbeatHandler extends ChannelInboundHandlerAdapter {
|
|||||||
|
|
||||||
private static final Logger logger = LoggerFactory.getLogger(HeartbeatHandler.class);
|
private static final Logger logger = LoggerFactory.getLogger(HeartbeatHandler.class);
|
||||||
|
|
||||||
private static final long DEVICE_REGISTER_TIMEOUT_MS = 10_000; // 10秒注册超时
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void channelActive(ChannelHandlerContext ctx) throws Exception {
|
public void channelActive(ChannelHandlerContext ctx) throws Exception {
|
||||||
// 连接建立后启动定时任务,主动发心跳
|
// 连接建立后启动定时任务,主动发心跳
|
||||||
@@ -41,7 +39,6 @@ public class HeartbeatHandler extends ChannelInboundHandlerAdapter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void scheduleHeartbeat(ChannelHandlerContext ctx) {
|
private void scheduleHeartbeat(ChannelHandlerContext ctx) {
|
||||||
final long startTime = System.currentTimeMillis();
|
|
||||||
ctx.executor().scheduleAtFixedRate(() -> {
|
ctx.executor().scheduleAtFixedRate(() -> {
|
||||||
try {
|
try {
|
||||||
if (ctx.channel().isActive()) {
|
if (ctx.channel().isActive()) {
|
||||||
@@ -50,12 +47,6 @@ public class HeartbeatHandler extends ChannelInboundHandlerAdapter {
|
|||||||
ByteBuf heartbeat = Unpooled.wrappedBuffer(HEARTBEAT_PACKET);
|
ByteBuf heartbeat = Unpooled.wrappedBuffer(HEARTBEAT_PACKET);
|
||||||
ctx.writeAndFlush(heartbeat);
|
ctx.writeAndFlush(heartbeat);
|
||||||
logger.debug("发送心跳包给客户端:{},deviceId:{}", ctx.channel().remoteAddress(), deviceId);
|
logger.debug("发送心跳包给客户端:{},deviceId:{}", ctx.channel().remoteAddress(), deviceId);
|
||||||
} else {
|
|
||||||
long elapsed = System.currentTimeMillis() - startTime;
|
|
||||||
if (elapsed > DEVICE_REGISTER_TIMEOUT_MS) {
|
|
||||||
logger.warn("设备超过{}ms未注册,断开连接:{}", DEVICE_REGISTER_TIMEOUT_MS, ctx.channel().remoteAddress());
|
|
||||||
ctx.close();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
@@ -64,24 +55,6 @@ public class HeartbeatHandler extends ChannelInboundHandlerAdapter {
|
|||||||
}, 0, HEARTBEAT_INTERVAL, TimeUnit.SECONDS);
|
}, 0, HEARTBEAT_INTERVAL, TimeUnit.SECONDS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// private void scheduleHeartbeat(ChannelHandlerContext ctx) {
|
|
||||||
// ctx.executor().scheduleAtFixedRate(() -> {
|
|
||||||
// try {
|
|
||||||
// if (ctx.channel().isActive()) {
|
|
||||||
// String deviceId = ctx.channel().attr(Constant.ATT_DEVICE_ID).get();
|
|
||||||
// if (!StringUtils.isEmpty(deviceId)) {
|
|
||||||
// ByteBuf heartbeat = Unpooled.wrappedBuffer(HEARTBEAT_PACKET);
|
|
||||||
// ctx.writeAndFlush(heartbeat);
|
|
||||||
// logger.debug("发送心跳包给客户端:{},deviceId:{}", ctx.channel().remoteAddress(), deviceId);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// } catch (Exception e) {
|
|
||||||
// logger.error("heartbeat error", e);
|
|
||||||
// }
|
|
||||||
// }, 0, HEARTBEAT_INTERVAL, TimeUnit.SECONDS);
|
|
||||||
// }
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
|
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
|
||||||
if (msg instanceof ByteBuf) {
|
if (msg instanceof ByteBuf) {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
package com.maibu.scheduled;
|
package com.maibu.scheduled;
|
||||||
|
|
||||||
import com.maibu.constant.NettyCacheKey;
|
import com.maibu.common.NettyCacheKey;
|
||||||
import com.maibu.core.business.DevicePlan;
|
import com.maibu.core.business.DevicePlan;
|
||||||
import com.maibu.core.business.DeviceRunParam;
|
import com.maibu.core.business.DeviceRunParam;
|
||||||
import com.maibu.core.business.DeviceStatusRecordDTO;
|
import com.maibu.core.business.DeviceStatusRecordDTO;
|
||||||
|
|||||||
@@ -19,7 +19,6 @@ import org.springframework.beans.factory.annotation.Autowired;
|
|||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.util.CollectionUtils;
|
import org.springframework.util.CollectionUtils;
|
||||||
|
|
||||||
import javax.annotation.PreDestroy;
|
|
||||||
import java.time.DayOfWeek;
|
import java.time.DayOfWeek;
|
||||||
import java.time.LocalDate;
|
import java.time.LocalDate;
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
@@ -45,12 +44,13 @@ public class DevicePlanTaskMonitorService {
|
|||||||
@Autowired
|
@Autowired
|
||||||
private WorkRecordMapper workRecordMapper;
|
private WorkRecordMapper workRecordMapper;
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private ScheduledExecutorService executor;
|
|
||||||
/**
|
/**
|
||||||
* 计划迟的任务生成机器执行任务
|
* 计划迟的任务生成机器执行任务
|
||||||
*/
|
*/
|
||||||
public void generatePlanTask() throws InterruptedException {
|
public void generatePlanTask() throws InterruptedException {
|
||||||
|
|
||||||
|
ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor();
|
||||||
executor.scheduleWithFixedDelay(() -> {
|
executor.scheduleWithFixedDelay(() -> {
|
||||||
try {
|
try {
|
||||||
Map<String, List<DevicePlan>> planMap = SiteMemory.devicePlanMap;
|
Map<String, List<DevicePlan>> planMap = SiteMemory.devicePlanMap;
|
||||||
@@ -204,6 +204,7 @@ public class DevicePlanTaskMonitorService {
|
|||||||
|
|
||||||
public void doLoop() throws InterruptedException {
|
public void doLoop() throws InterruptedException {
|
||||||
//prepare 进执行execute的逻辑
|
//prepare 进执行execute的逻辑
|
||||||
|
ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor();
|
||||||
executor.scheduleWithFixedDelay(() -> {
|
executor.scheduleWithFixedDelay(() -> {
|
||||||
try {
|
try {
|
||||||
List<SiteMemory> list = GlobalMemory.getAllSiteMemory();
|
List<SiteMemory> list = GlobalMemory.getAllSiteMemory();
|
||||||
@@ -214,11 +215,11 @@ public class DevicePlanTaskMonitorService {
|
|||||||
planMap.keySet().forEach(key -> {
|
planMap.keySet().forEach(key -> {
|
||||||
NettyDevice device = deviceSessionManager.getDevice(key);
|
NettyDevice device = deviceSessionManager.getDevice(key);
|
||||||
//判断是否能进execute
|
//判断是否能进execute
|
||||||
if (device != null && device.getTask() == null && device.getOnlineStatus() != null && device.getOnlineStatus() == 1) {
|
if (device != null && device.getCurrentTaskId() == null && device.getOnlineStatus() != null && device.getOnlineStatus() == 1) {
|
||||||
List<DevicePlanTask> tasks = planMap.get(key);
|
List<DevicePlanTask> tasks = planMap.get(key);
|
||||||
if (!CollectionUtils.isEmpty(tasks)) {
|
if (!CollectionUtils.isEmpty(tasks)) {
|
||||||
tasks.removeIf(Objects::isNull);
|
tasks.removeIf(Objects::isNull);
|
||||||
tasks.sort(
|
tasks.sort(
|
||||||
Comparator.comparing(
|
Comparator.comparing(
|
||||||
DevicePlanTask::getStartTime,
|
DevicePlanTask::getStartTime,
|
||||||
Comparator.nullsLast(Comparator.naturalOrder())
|
Comparator.nullsLast(Comparator.naturalOrder())
|
||||||
@@ -229,9 +230,9 @@ public class DevicePlanTaskMonitorService {
|
|||||||
String deviceId = devicePlanTask.getDeviceId();
|
String deviceId = devicePlanTask.getDeviceId();
|
||||||
if (!StringUtils.isEmpty(deviceId) && deviceId.equals(key)) {
|
if (!StringUtils.isEmpty(deviceId) && deviceId.equals(key)) {
|
||||||
devicePlanTask.setTaskStaus(DeviceTaskStaus.EXECUTING);
|
devicePlanTask.setTaskStaus(DeviceTaskStaus.EXECUTING);
|
||||||
|
siteMemory.addDevicePlanExecute(devicePlanTask);
|
||||||
device.setCurrentTaskId(devicePlanTask.getId());
|
device.setCurrentTaskId(devicePlanTask.getId());
|
||||||
device.setTask(devicePlanTask);
|
device.setTask(devicePlanTask);
|
||||||
siteMemory.addDevicePlanExecute(devicePlanTask);
|
|
||||||
siteMemory.removeDevicePlanPrepare(devicePlanTask);
|
siteMemory.removeDevicePlanPrepare(devicePlanTask);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -249,6 +250,7 @@ public class DevicePlanTaskMonitorService {
|
|||||||
|
|
||||||
public void doExecute() {
|
public void doExecute() {
|
||||||
//prepare 进执行execute的逻辑
|
//prepare 进执行execute的逻辑
|
||||||
|
ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor();
|
||||||
executor.scheduleWithFixedDelay(() -> {
|
executor.scheduleWithFixedDelay(() -> {
|
||||||
try {
|
try {
|
||||||
List<SiteMemory> list = GlobalMemory.getAllSiteMemory();
|
List<SiteMemory> list = GlobalMemory.getAllSiteMemory();
|
||||||
@@ -268,4 +270,5 @@ public class DevicePlanTaskMonitorService {
|
|||||||
}
|
}
|
||||||
}, 0, 1000, TimeUnit.MILLISECONDS);
|
}, 0, 1000, TimeUnit.MILLISECONDS);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,7 +11,6 @@ import java.util.stream.Collectors;
|
|||||||
|
|
||||||
import com.maibu.memory.DeviceSessionManager;
|
import com.maibu.memory.DeviceSessionManager;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.eclipse.paho.client.mqttv3.MqttException;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.util.CollectionUtils;
|
import org.springframework.util.CollectionUtils;
|
||||||
@@ -24,7 +23,6 @@ import com.maibu.core.business.DeviceTaskPlanRule;
|
|||||||
import com.maibu.core.business.WorkRecord;
|
import com.maibu.core.business.WorkRecord;
|
||||||
import com.maibu.core.business.device.NettyDevice;
|
import com.maibu.core.business.device.NettyDevice;
|
||||||
import com.maibu.core.business.dto.DeviceTaskCommandDTO;
|
import com.maibu.core.business.dto.DeviceTaskCommandDTO;
|
||||||
import com.maibu.core.domain.entity.SysRegion;
|
|
||||||
import com.maibu.core.domain.entity.SysSite;
|
import com.maibu.core.domain.entity.SysSite;
|
||||||
import com.maibu.core.domain.model.LoginUser;
|
import com.maibu.core.domain.model.LoginUser;
|
||||||
import com.maibu.core.enums.DeviceTaskStaus;
|
import com.maibu.core.enums.DeviceTaskStaus;
|
||||||
@@ -35,7 +33,6 @@ import com.maibu.dto.DeviceWorkStatisticsDTO;
|
|||||||
import com.maibu.mapper.DeviceMapper;
|
import com.maibu.mapper.DeviceMapper;
|
||||||
import com.maibu.mapper.DevicePlanMapper;
|
import com.maibu.mapper.DevicePlanMapper;
|
||||||
import com.maibu.mapper.DevicePlanTaskMapper;
|
import com.maibu.mapper.DevicePlanTaskMapper;
|
||||||
import com.maibu.mapper.SysRegionMapper;
|
|
||||||
import com.maibu.mapper.SysSiteMapper;
|
import com.maibu.mapper.SysSiteMapper;
|
||||||
import com.maibu.mapper.WorkRecordMapper;
|
import com.maibu.mapper.WorkRecordMapper;
|
||||||
import com.maibu.memory.GlobalMemory;
|
import com.maibu.memory.GlobalMemory;
|
||||||
@@ -65,9 +62,6 @@ public class DeviceTaskService {
|
|||||||
@Autowired
|
@Autowired
|
||||||
private SysSiteMapper sysSiteMapper;
|
private SysSiteMapper sysSiteMapper;
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private SysRegionMapper sysRegionMapper;
|
|
||||||
|
|
||||||
public int insertOrUpdate(DevicePlan devicePlan, LoginUser loginUser) {
|
public int insertOrUpdate(DevicePlan devicePlan, LoginUser loginUser) {
|
||||||
Long id = devicePlan.getId();
|
Long id = devicePlan.getId();
|
||||||
SiteMemory siteMemory = GlobalMemory.getSiteMemory(devicePlan.getOrgId(), devicePlan.getSiteId());
|
SiteMemory siteMemory = GlobalMemory.getSiteMemory(devicePlan.getOrgId(), devicePlan.getSiteId());
|
||||||
@@ -453,9 +447,9 @@ public class DeviceTaskService {
|
|||||||
x.setTaskStausTranslate(taskStaus.getDescription());
|
x.setTaskStausTranslate(taskStaus.getDescription());
|
||||||
});
|
});
|
||||||
list.sort(
|
list.sort(
|
||||||
Comparator.comparing(DevicePlanTask::getCreateTime,
|
Comparator.comparing(DevicePlanTask::getFinishTime,
|
||||||
Comparator.nullsLast(Comparator.reverseOrder()))
|
Comparator.nullsLast(Comparator.reverseOrder()))
|
||||||
.thenComparing(DevicePlanTask::getFinishTime,
|
.thenComparing(DevicePlanTask::getCreateTime,
|
||||||
Comparator.nullsLast(Comparator.reverseOrder())));
|
Comparator.nullsLast(Comparator.reverseOrder())));
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
@@ -482,36 +476,7 @@ public class DeviceTaskService {
|
|||||||
return task.getId();
|
return task.getId();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Long createRegionDeviceTask(DeviceTaskCommandDTO dto, String username) {
|
public boolean cancelTask(DeviceTaskCommandDTO dto, String username) {
|
||||||
LambdaQueryWrapper<SysRegion> queryWrapper = new LambdaQueryWrapper<>();
|
|
||||||
queryWrapper.eq(SysRegion::getId, dto.getRegionId());
|
|
||||||
SysRegion region = sysRegionMapper.selectOne(queryWrapper);
|
|
||||||
|
|
||||||
if (region == null || region.getBindRoute() == null) {
|
|
||||||
throw new RuntimeException("区域未绑定线路!");
|
|
||||||
}
|
|
||||||
DevicePlanTask task = new DevicePlanTask();
|
|
||||||
task.setRouteId(region.getBindRoute());
|
|
||||||
task.setOrgId(dto.getOrgId());
|
|
||||||
task.setSiteId(dto.getSiteId());
|
|
||||||
task.setTaskStaus(DeviceTaskStaus.NEW);
|
|
||||||
task.setDeviceId(dto.getDeviceId());
|
|
||||||
task.setCreateBy(username);
|
|
||||||
task.setCreateTime(LocalDateTime.now());
|
|
||||||
task.setStartTime(dto.getStartTime());
|
|
||||||
devicePlanTaskMapper.saveOrUpdate(task);
|
|
||||||
if (dto.getOrgId() == null) {
|
|
||||||
SysSite site = sysSiteMapper.selectById(dto.getSiteId());
|
|
||||||
if (site != null) {
|
|
||||||
dto.setOrgId(site.getOrgId());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
SiteMemory siteMemory = GlobalMemory.getSiteMemory(task.getOrgId(), task.getSiteId());
|
|
||||||
siteMemory.addDevicePlanPrepare(task);
|
|
||||||
return task.getId();
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean cancelTask(DeviceTaskCommandDTO dto) throws MqttException {
|
|
||||||
String deviceId = dto.getDeviceId();
|
String deviceId = dto.getDeviceId();
|
||||||
DevicePlanTask devicePlanTask = null;
|
DevicePlanTask devicePlanTask = null;
|
||||||
if (StringUtils.isEmpty(dto.getDeviceId())) {
|
if (StringUtils.isEmpty(dto.getDeviceId())) {
|
||||||
@@ -523,11 +488,7 @@ public class DeviceTaskService {
|
|||||||
}
|
}
|
||||||
NettyDevice device = deviceSessionManager.getDevice(deviceId);
|
NettyDevice device = deviceSessionManager.getDevice(deviceId);
|
||||||
if (device != null && device.getTask() != null) {
|
if (device != null && device.getTask() != null) {
|
||||||
if (dto.isForceCancel()) {
|
return device.cancelTask();
|
||||||
return device.canceledTask();
|
|
||||||
} else {
|
|
||||||
return device.cancelingTask();
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
if (devicePlanTask != null) {
|
if (devicePlanTask != null) {
|
||||||
devicePlanTask.setTaskStaus(DeviceTaskStaus.CANCELED);
|
devicePlanTask.setTaskStaus(DeviceTaskStaus.CANCELED);
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ package com.maibu.service;
|
|||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
import java.math.BigDecimal;
|
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
@@ -10,18 +9,15 @@ import java.util.Comparator;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
import java.util.concurrent.Executors;
|
||||||
import java.util.concurrent.ScheduledExecutorService;
|
import java.util.concurrent.ScheduledExecutorService;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import com.maibu.core.business.dto.DeviceMapPushDTO;
|
import com.maibu.memory.DeviceSessionManager;
|
||||||
import com.maibu.core.business.dto.WebMapMessageDTO;
|
|
||||||
import com.maibu.core.enums.*;
|
|
||||||
import com.maibu.utils.json.JsonUtils;
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.checkerframework.checker.units.qual.s;
|
import org.eclipse.paho.client.mqttv3.MqttException;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
|
||||||
import org.springframework.core.io.Resource;
|
import org.springframework.core.io.Resource;
|
||||||
import org.springframework.core.io.ResourceLoader;
|
import org.springframework.core.io.ResourceLoader;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
@@ -29,24 +25,19 @@ import org.springframework.util.CollectionUtils;
|
|||||||
|
|
||||||
import com.alibaba.fastjson2.JSON;
|
import com.alibaba.fastjson2.JSON;
|
||||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||||
import com.maibu.constant.Constant;
|
import com.maibu.common.NettyCacheKey;
|
||||||
import com.maibu.constant.NettyCacheKey;
|
|
||||||
import com.maibu.core.business.Device;
|
|
||||||
import com.maibu.core.business.DeviceRunStatistics;
|
|
||||||
import com.maibu.core.business.DeviceRunningStatusHistory;
|
import com.maibu.core.business.DeviceRunningStatusHistory;
|
||||||
import com.maibu.core.business.DeviceStatusRecordDTO;
|
import com.maibu.core.business.DeviceStatusRecordDTO;
|
||||||
import com.maibu.core.business.ErrorIdentificationStandard;
|
import com.maibu.core.business.ErrorIdentificationStandard;
|
||||||
import com.maibu.core.business.alarm_center.AlarmMessage;
|
import com.maibu.core.business.alarm_center.AlarmMessage;
|
||||||
import com.maibu.core.business.device.NettyDevice;
|
import com.maibu.core.business.device.NettyDevice;
|
||||||
import com.maibu.core.business.inter.WebsocketMesDispather;
|
import com.maibu.core.business.inter.WebsocketMesDispather;
|
||||||
import com.maibu.core.host.HeartBeatDTO;
|
import com.maibu.core.enums.CompareEnum;
|
||||||
import com.maibu.core.host.LocationMessage;
|
import com.maibu.core.enums.ErrorSource;
|
||||||
|
import com.maibu.core.enums.RespondCode;
|
||||||
import com.maibu.core.redis.RedisCache;
|
import com.maibu.core.redis.RedisCache;
|
||||||
import com.maibu.dto.DeviceErrorPushDTO;
|
import com.maibu.dto.DeviceErrorPushDTO;
|
||||||
import com.maibu.mapper.DeviceRunStatisticsMapper;
|
|
||||||
import com.maibu.mapper.ErrorIdentificationStandardMapper;
|
import com.maibu.mapper.ErrorIdentificationStandardMapper;
|
||||||
import com.maibu.mapper.HostLocationMapper;
|
|
||||||
import com.maibu.memory.DeviceSessionManager;
|
|
||||||
import com.maibu.memory.GlobalMemory;
|
import com.maibu.memory.GlobalMemory;
|
||||||
import com.maibu.memory.SiteMemory;
|
import com.maibu.memory.SiteMemory;
|
||||||
import com.maibu.mqtt.MqttTopic;
|
import com.maibu.mqtt.MqttTopic;
|
||||||
@@ -78,26 +69,13 @@ public class DeviceThreadService {
|
|||||||
@Autowired
|
@Autowired
|
||||||
private AlertPushService alertPushService;
|
private AlertPushService alertPushService;
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private IDeviceService deviceService;
|
|
||||||
|
|
||||||
@Value("${mqtt.client-id}")
|
|
||||||
private String mqttClientId;
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private ScheduledExecutorService executor;
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private HostLocationMapper hostLocationMapper;
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private DeviceRunStatisticsMapper deviceRunStatisticsMapper;
|
|
||||||
|
|
||||||
public void deviceErrorMonitor() throws InterruptedException, IOException {
|
public void deviceErrorMonitor() throws InterruptedException, IOException {
|
||||||
initStandard();
|
initStandard();
|
||||||
|
|
||||||
// TODO fix 后续是否分多个线程 一个site一个线程
|
// TODO fix 后续是否分多个线程 一个site一个线程
|
||||||
// 有还需要更新接受故障方式。
|
// 有还需要更新接受故障方式。
|
||||||
|
|
||||||
|
ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor();
|
||||||
executor.scheduleWithFixedDelay(() -> {
|
executor.scheduleWithFixedDelay(() -> {
|
||||||
try {
|
try {
|
||||||
String key = NettyCacheKey.deviceRunningStatusKey;
|
String key = NettyCacheKey.deviceRunningStatusKey;
|
||||||
@@ -114,7 +92,7 @@ public class DeviceThreadService {
|
|||||||
String[] parts = k.split(":");
|
String[] parts = k.split(":");
|
||||||
String deviceId = parts[1];
|
String deviceId = parts[1];
|
||||||
NettyDevice slaveDevice = sessionManager.getDevice(deviceId);
|
NettyDevice slaveDevice = sessionManager.getDevice(deviceId);
|
||||||
if (slaveDevice != null && slaveDevice.getOnlineStatus() == 1) {
|
if (slaveDevice != null && slaveDevice.isOnline()) {
|
||||||
Long siteId = slaveDevice.getDevice().getSiteId();
|
Long siteId = slaveDevice.getDevice().getSiteId();
|
||||||
Long orgId = slaveDevice.getDevice().getOrgId();
|
Long orgId = slaveDevice.getDevice().getOrgId();
|
||||||
log.debug("compare siteId:{},orgId:{}", siteId, orgId);
|
log.debug("compare siteId:{},orgId:{}", siteId, orgId);
|
||||||
@@ -206,10 +184,7 @@ public class DeviceThreadService {
|
|||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
try {
|
try {
|
||||||
GlobalMemory.customMqttDeviceMonitor.publish(mqttClientId,
|
GlobalMemory.mqttClientUtil.publish(String.format(MqttTopic.DEVICE_ERROR_PUSH_TOPIC, deviceId), dto);
|
||||||
String.format(MqttTopic.DEVICE_ERROR_PUSH_TOPIC, deviceId), dto);
|
|
||||||
// GlobalMemory.mqttClientUtil.publish(String.format(MqttTopic.DEVICE_ERROR_PUSH_TOPIC,
|
|
||||||
// deviceId), dto);
|
|
||||||
List<NettyDevice> controlMasters = sessionManager.getAllSlaveControl(deviceId);
|
List<NettyDevice> controlMasters = sessionManager.getAllSlaveControl(deviceId);
|
||||||
if (!CollectionUtils.isEmpty(controlMasters)) {
|
if (!CollectionUtils.isEmpty(controlMasters)) {
|
||||||
controlMasters.forEach(x -> {
|
controlMasters.forEach(x -> {
|
||||||
@@ -217,13 +192,13 @@ public class DeviceThreadService {
|
|||||||
log.info("推送错误信息 device:{},content:{}", deviceId, dto);
|
log.info("推送错误信息 device:{},content:{}", deviceId, dto);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (MqttException e) {
|
||||||
log.error("推送错误信息失败 device:{}error:{}", deviceId, e.getMessage());
|
log.error("推送错误信息失败 device:{}error:{}", deviceId, e.getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<AlarmMessage> compareErrorStandard(Long siteId, Long orgId, DeviceRunningStatusHistory history,
|
public List<AlarmMessage> compareErrorStandard(Long siteId, Long orgId, DeviceRunningStatusHistory history,
|
||||||
List<ErrorIdentificationStandard> standards) {
|
List<ErrorIdentificationStandard> standards) {
|
||||||
if (history == null || CollectionUtils.isEmpty(standards))
|
if (history == null || CollectionUtils.isEmpty(standards))
|
||||||
return null;
|
return null;
|
||||||
List<AlarmMessage> list = new ArrayList<>();
|
List<AlarmMessage> list = new ArrayList<>();
|
||||||
@@ -232,8 +207,7 @@ public class DeviceThreadService {
|
|||||||
String compareValues = standard.getCompareValues();
|
String compareValues = standard.getCompareValues();
|
||||||
CompareEnum compareType = standard.getCompareType();
|
CompareEnum compareType = standard.getCompareType();
|
||||||
String targetValue = knownClassFieldFinding(fieldName, history);
|
String targetValue = knownClassFieldFinding(fieldName, history);
|
||||||
log.debug("compare2 compareType:{} compareValues:{},targetValue:{}", compareType, compareValues,
|
log.debug("compare2 compareType:{} compareValues:{},targetValue:{}", compareType, compareValues, targetValue);
|
||||||
targetValue);
|
|
||||||
if (!StringUtils.isEmpty(compareValues) && !StringUtils.isEmpty(targetValue)) {
|
if (!StringUtils.isEmpty(compareValues) && !StringUtils.isEmpty(targetValue)) {
|
||||||
boolean result = CompareUtils.compare(compareType, targetValue, compareValues);
|
boolean result = CompareUtils.compare(compareType, targetValue, compareValues);
|
||||||
log.debug("compare3 result:{}", result);
|
log.debug("compare3 result:{}", result);
|
||||||
@@ -274,154 +248,4 @@ public class DeviceThreadService {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 监控心跳
|
|
||||||
*/
|
|
||||||
public void heartBeatMonitor() {
|
|
||||||
executor.scheduleWithFixedDelay(() -> {
|
|
||||||
try {
|
|
||||||
Long nowTime = System.currentTimeMillis();
|
|
||||||
List<HeartBeatDTO> heartBeatDTOS = GlobalMemory.customMqttDeviceMonitor.getAllHeartBeat();
|
|
||||||
if (!CollectionUtils.isEmpty(heartBeatDTOS)) {
|
|
||||||
heartBeatDTOS.forEach(x -> {
|
|
||||||
if (x == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
String deviceId = x.getSn();
|
|
||||||
Long lastActiveTime = x.getSysTimestamp();
|
|
||||||
NettyDevice nettyDevice = sessionManager.getDevice(x.getSn());
|
|
||||||
|
|
||||||
if (lastActiveTime == null) {
|
|
||||||
log.error("设备心跳时间为空,deviceId={}", deviceId);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (nowTime - lastActiveTime >= Constant.hostOfflineInterval) {
|
|
||||||
// 超时了判断离线
|
|
||||||
if (nettyDevice != null) {
|
|
||||||
nettyDevice.status(DeviceStatus.offline.getType());
|
|
||||||
// todo 推送设备离线
|
|
||||||
String key = NettyCacheKey.latestPositonKey + deviceId;
|
|
||||||
// 保存一下最新一次的数据到 数据库
|
|
||||||
LocationMessage locationMessage = redisCache.getCacheObject(key);
|
|
||||||
if (locationMessage != null) {
|
|
||||||
LambdaQueryWrapper<LocationMessage> queryWrapper = new LambdaQueryWrapper<>();
|
|
||||||
queryWrapper.eq(LocationMessage::getDeviceId, deviceId);
|
|
||||||
LocationMessage existing = hostLocationMapper.selectOne(queryWrapper);
|
|
||||||
if (existing != null) {
|
|
||||||
locationMessage.setId(existing.getId());
|
|
||||||
}
|
|
||||||
hostLocationMapper.saveOrUpdate(locationMessage);
|
|
||||||
}
|
|
||||||
Device device = deviceService.selectDeviceBySerialNumber(deviceId);
|
|
||||||
if (device != null) {
|
|
||||||
device.setOnlineStatus(DeviceStatus.offline.getType());
|
|
||||||
device.setUpdateTime(LocalDateTime.now());
|
|
||||||
deviceService.updateDeviceBySelf(device);
|
|
||||||
}
|
|
||||||
|
|
||||||
Long orgId = nettyDevice.getDevice().getOrgId();
|
|
||||||
Long siteId = nettyDevice.getDevice().getSiteId();
|
|
||||||
SiteMemory siteMemory = GlobalMemory.getSiteMemory(orgId, siteId);
|
|
||||||
if (siteMemory != null) {
|
|
||||||
DeviceRunStatistics deviceRunStatistics = siteMemory.getRunStatistics(deviceId);
|
|
||||||
if (deviceRunStatistics != null) {
|
|
||||||
LambdaQueryWrapper<DeviceRunStatistics> queryWrapper = new LambdaQueryWrapper<>();
|
|
||||||
queryWrapper.eq(DeviceRunStatistics::getDeviceId, deviceId);
|
|
||||||
DeviceRunStatistics existing = deviceRunStatisticsMapper
|
|
||||||
.selectOne(queryWrapper);
|
|
||||||
if (existing != null) {
|
|
||||||
deviceRunStatistics.setId(existing.getId());
|
|
||||||
deviceRunStatistics.setDistance(
|
|
||||||
existing.getDistance() + deviceRunStatistics.getDistance());
|
|
||||||
deviceRunStatistics.setWorkArea(
|
|
||||||
existing.getWorkArea() + deviceRunStatistics.getWorkArea());
|
|
||||||
long time = System.currentTimeMillis() - nettyDevice.getLatestLoginTime();
|
|
||||||
deviceRunStatistics.setTime(existing.getTime() + time / (1000 * 60)); // 累加时长,单位为分钟
|
|
||||||
} else {
|
|
||||||
long time = System.currentTimeMillis() - nettyDevice.getLatestLoginTime();
|
|
||||||
deviceRunStatistics.setTime(time / (1000 * 60)); // 累加时长,单位为分钟
|
|
||||||
}
|
|
||||||
deviceRunStatisticsMapper.saveOrUpdate(deviceRunStatistics);
|
|
||||||
}
|
|
||||||
// todo 删除实时消息推送里面的数据
|
|
||||||
siteMemory.removeMapPushDTO(deviceId);
|
|
||||||
}
|
|
||||||
|
|
||||||
sessionManager.removeDevice(deviceId);
|
|
||||||
// TODO 统计总里程、总作业面积
|
|
||||||
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
Device device = deviceService.selectDeviceBySerialNumber(deviceId);
|
|
||||||
if (device == null) {
|
|
||||||
device = new Device();
|
|
||||||
device.setStatus(3);
|
|
||||||
device.setOnlineStatus(DeviceStatus.online.getType());
|
|
||||||
device.setSerialNumber(deviceId);
|
|
||||||
device.setDeviceName(deviceId);
|
|
||||||
device.setProductId(-1L);
|
|
||||||
device.setTenantId(-1L);
|
|
||||||
device.setFirmwareVersion("1.0");
|
|
||||||
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());
|
|
||||||
device.setHasHost(true);
|
|
||||||
deviceService.updateDeviceBySelf(device);
|
|
||||||
}
|
|
||||||
if (nettyDevice == null) {
|
|
||||||
sessionManager.registerSlaveDevice(deviceId, ConnectorStatus.ACTIVE, null);
|
|
||||||
NettyDevice slaveDevice = sessionManager.getDevice(deviceId);
|
|
||||||
if (slaveDevice != null) {
|
|
||||||
slaveDevice.setOnlineStatus(1);
|
|
||||||
slaveDevice.setDevice(device);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// todo 推送设备上线
|
|
||||||
nettyDevice.status(1);
|
|
||||||
nettyDevice.setDevice(device);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
log.error("执行监测心跳线程错误", e);
|
|
||||||
}
|
|
||||||
}, 0, 500, TimeUnit.MILLISECONDS);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 监控心跳
|
|
||||||
*/
|
|
||||||
public void mapMessagePush() {
|
|
||||||
executor.scheduleWithFixedDelay(() -> {
|
|
||||||
try {
|
|
||||||
List<SiteMemory> list = GlobalMemory.getAllSiteMemory();
|
|
||||||
if (!CollectionUtils.isEmpty(list)) {
|
|
||||||
list.forEach(x -> {
|
|
||||||
Map<String, DeviceMapPushDTO> map = x.getAllDeviceMapPush();
|
|
||||||
List<DeviceMapPushDTO> pushList = new ArrayList<>(map.values());
|
|
||||||
WebMapMessageDTO dto = new WebMapMessageDTO();
|
|
||||||
dto.setData(pushList);
|
|
||||||
dto.setType(MesType.mapPush);
|
|
||||||
try {
|
|
||||||
websocketMesDispather.mapMessageDispather(x.getSiteId(),
|
|
||||||
JsonUtils.toJsonString(dto));
|
|
||||||
} catch (Exception e) {
|
|
||||||
log.error("实时地图数据websocket推送失败: siteId={}, error={}", x.getSiteId(),
|
|
||||||
e.getMessage(), e);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
log.error("执行监测心跳线程错误:{}", e.getMessage());
|
|
||||||
}
|
|
||||||
}, 0, 100, TimeUnit.MILLISECONDS);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,12 +7,10 @@ import com.maibu.core.domain.AjaxResult;
|
|||||||
import com.maibu.core.domain.entity.UserClient;
|
import com.maibu.core.domain.entity.UserClient;
|
||||||
import com.maibu.core.domain.model.LoginUser;
|
import com.maibu.core.domain.model.LoginUser;
|
||||||
import com.maibu.core.enums.ConnectorStatus;
|
import com.maibu.core.enums.ConnectorStatus;
|
||||||
import com.maibu.exception.ServiceException;
|
|
||||||
import com.maibu.mapper.DeviceMapper;
|
import com.maibu.mapper.DeviceMapper;
|
||||||
import com.maibu.mapper.SysUserClientMapper;
|
import com.maibu.mapper.SysUserClientMapper;
|
||||||
import com.maibu.memory.DeviceSessionManager;
|
import com.maibu.memory.DeviceSessionManager;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.util.CollectionUtils;
|
import org.springframework.util.CollectionUtils;
|
||||||
@@ -22,7 +20,6 @@ import java.time.LocalDateTime;
|
|||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
@Service
|
@Service
|
||||||
@Slf4j
|
@Slf4j
|
||||||
@@ -158,111 +155,62 @@ public class TransferDeviceService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// public synchronized boolean switchDevice(DeviceBindDTO bindDTO, LoginUser user) {
|
public synchronized boolean switchDevice(DeviceBindDTO bindDTO, LoginUser user) {
|
||||||
// try {
|
|
||||||
// String slaveId = bindDTO.getDeviceId();
|
|
||||||
// String platform = bindDTO.getPlatform();
|
|
||||||
// String userName = user.getUsername();
|
|
||||||
// String masterId = userName + ":" + platform;
|
|
||||||
// //todo 判断是否有权限 正在控制才能切
|
|
||||||
// //todo 离线没有控制权的怎么切
|
|
||||||
// log.info("switchDevice:{}", masterId);
|
|
||||||
// NettyDevice deviceMaster = sessionManager.getDevice(masterId);
|
|
||||||
// log.info("deviceMaster:{}", deviceMaster);
|
|
||||||
// if (deviceMaster != null) {
|
|
||||||
// log.info("ConnectorStatus:{}", deviceMaster.getConnectorStatus());
|
|
||||||
// if (ConnectorStatus.RECEIVER.equals(deviceMaster.getConnectorStatus())) {
|
|
||||||
// //当前账号没有控制则可以切换为控制?
|
|
||||||
// NettyDevice activeDevice = sessionManager.getUserControl(userName);
|
|
||||||
// deviceMaster.getConnectedConnectors().clear();
|
|
||||||
// if (activeDevice == null) {
|
|
||||||
// log.info("bindConnector ACTIVE :{}", masterId);
|
|
||||||
// sessionManager.bindConnector(masterId, slaveId);
|
|
||||||
// deviceMaster.setConnectorStatus(ConnectorStatus.ACTIVE);
|
|
||||||
// deviceMaster.setCurrentSlaveId(slaveId);
|
|
||||||
// sysUserClientService.updateAliveStatus(masterId, slaveId, 1);
|
|
||||||
// } else {
|
|
||||||
// log.info("bindConnector RECEIVER :{}", masterId);
|
|
||||||
// sessionManager.bindConnector(masterId, slaveId);
|
|
||||||
// deviceMaster.setConnectorStatus(ConnectorStatus.RECEIVER);
|
|
||||||
// deviceMaster.setCurrentSlaveId(slaveId);
|
|
||||||
// sysUserClientService.updateAliveStatus(masterId, slaveId, 2);
|
|
||||||
// }
|
|
||||||
// } else {
|
|
||||||
// //从关联其他设备切换到 当前禁言 假如有控制且不是当前更新为2
|
|
||||||
// List<NettyDevice> controls = sessionManager.getSlaveControl(slaveId);
|
|
||||||
// if (CollectionUtils.isEmpty(controls)) {
|
|
||||||
// deviceMaster.getConnectedConnectors().clear();
|
|
||||||
// log.info("bindConnector 1:{}", masterId);
|
|
||||||
// sessionManager.bindConnector(masterId, slaveId);
|
|
||||||
// deviceMaster.setConnectorStatus(ConnectorStatus.ACTIVE);
|
|
||||||
// deviceMaster.setCurrentSlaveId(slaveId);
|
|
||||||
// sysUserClientService.updateAliveStatus(masterId, slaveId, 1);
|
|
||||||
// } else {
|
|
||||||
// NettyDevice controlDevice = controls.get(0);
|
|
||||||
// if (!masterId.equals(controlDevice.getConnectorId())) {
|
|
||||||
// //当前的设备有控制 的主机
|
|
||||||
// deviceMaster.getConnectedConnectors().clear();
|
|
||||||
// log.info("bindConnector RECEIVER 2:{}", masterId);
|
|
||||||
// sessionManager.bindConnector(masterId, slaveId);
|
|
||||||
// deviceMaster.setConnectorStatus(ConnectorStatus.RECEIVER);
|
|
||||||
// deviceMaster.setCurrentSlaveId(slaveId);
|
|
||||||
// sysUserClientService.updateAliveStatus(masterId, slaveId, 2);
|
|
||||||
// }
|
|
||||||
// //当前 切当前不做操作
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// return true;
|
|
||||||
// }
|
|
||||||
// } catch (Exception e) {
|
|
||||||
// log.error("切换设备失败: {}", e.getMessage(), e);
|
|
||||||
// }
|
|
||||||
// return false;
|
|
||||||
// }
|
|
||||||
|
|
||||||
public synchronized boolean switchDevice(DeviceBindDTO bindDTO) {
|
|
||||||
try {
|
try {
|
||||||
String slaveId = bindDTO.getDeviceId();
|
String slaveId = bindDTO.getDeviceId();
|
||||||
// String platform = bindDTO.getPlatform();
|
String platform = bindDTO.getPlatform();
|
||||||
// String userName = user.getUsername();
|
String userName = user.getUsername();
|
||||||
|
String masterId = userName + ":" + platform;
|
||||||
// String masterId = userName + ":" + platform;
|
//todo 判断是否有权限 正在控制才能切
|
||||||
|
//todo 离线没有控制权的怎么切
|
||||||
|
log.info("switchDevice:{}", masterId);
|
||||||
String token = bindDTO.getToken();
|
NettyDevice deviceMaster = sessionManager.getDevice(masterId);
|
||||||
|
log.info("deviceMaster:{}", deviceMaster);
|
||||||
log.info("switchDevice slaveId:{},token:{}", slaveId, token);
|
if (deviceMaster != null) {
|
||||||
NettyDevice deviceMaster = sessionManager.getDevice(token);
|
log.info("ConnectorStatus:{}", deviceMaster.getConnectorStatus());
|
||||||
log.info("switchDevice deviceMaster:{}", deviceMaster);
|
if (ConnectorStatus.RECEIVER.equals(deviceMaster.getConnectorStatus())) {
|
||||||
if (deviceMaster == null) {
|
//当前账号没有控制则可以切换为控制?
|
||||||
throw new ServiceException("功能码当前账号未发送登录请求,不在线");
|
NettyDevice activeDevice = sessionManager.getUserControl(userName);
|
||||||
}
|
|
||||||
|
|
||||||
List<NettyDevice> controls = sessionManager.getAllSlaveControl(slaveId);
|
|
||||||
if (CollectionUtils.isEmpty(controls)) {
|
|
||||||
deviceMaster.getConnectedConnectors().clear();
|
|
||||||
sessionManager.bindConnector(token, slaveId);
|
|
||||||
deviceMaster.setConnectorStatus(ConnectorStatus.ACTIVE);
|
|
||||||
deviceMaster.setCurrentSlaveId(slaveId);
|
|
||||||
sessionManager.lock(slaveId, token);
|
|
||||||
log.info("switchDevice bindConnector slaveId:{},token:{}", slaveId, token);
|
|
||||||
} else {
|
|
||||||
List<String> connectorIds = controls.stream().map(NettyDevice::getConnectorId).collect(Collectors.toList());
|
|
||||||
if (!connectorIds.contains(token)) {
|
|
||||||
//当前的设备有控制 的主机
|
|
||||||
deviceMaster.getConnectedConnectors().clear();
|
deviceMaster.getConnectedConnectors().clear();
|
||||||
sessionManager.bindConnector(token, slaveId);
|
if (activeDevice == null) {
|
||||||
deviceMaster.setConnectorStatus(ConnectorStatus.RECEIVER);
|
log.info("bindConnector ACTIVE :{}", masterId);
|
||||||
deviceMaster.setCurrentSlaveId(slaveId);
|
sessionManager.bindConnector(masterId, slaveId);
|
||||||
log.info("switchDevice bindConnector RECEIVER :{}", token);
|
deviceMaster.setConnectorStatus(ConnectorStatus.ACTIVE);
|
||||||
|
deviceMaster.setCurrentSlaveId(slaveId);
|
||||||
|
sysUserClientService.updateAliveStatus(masterId, slaveId, 1);
|
||||||
|
} else {
|
||||||
|
log.info("bindConnector RECEIVER :{}", masterId);
|
||||||
|
sessionManager.bindConnector(masterId, slaveId);
|
||||||
|
deviceMaster.setConnectorStatus(ConnectorStatus.RECEIVER);
|
||||||
|
deviceMaster.setCurrentSlaveId(slaveId);
|
||||||
|
sysUserClientService.updateAliveStatus(masterId, slaveId, 2);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
deviceMaster.setConnectorStatus(ConnectorStatus.ACTIVE);
|
//从关联其他设备切换到 当前禁言 假如有控制且不是当前更新为2
|
||||||
deviceMaster.setCurrentSlaveId(slaveId);
|
List<NettyDevice> controls = sessionManager.getSlaveControl(slaveId);
|
||||||
sessionManager.lock(slaveId, token);
|
if (CollectionUtils.isEmpty(controls)) {
|
||||||
|
deviceMaster.getConnectedConnectors().clear();
|
||||||
|
log.info("bindConnector 1:{}", masterId);
|
||||||
|
sessionManager.bindConnector(masterId, slaveId);
|
||||||
|
deviceMaster.setConnectorStatus(ConnectorStatus.ACTIVE);
|
||||||
|
deviceMaster.setCurrentSlaveId(slaveId);
|
||||||
|
sysUserClientService.updateAliveStatus(masterId, slaveId, 1);
|
||||||
|
} else {
|
||||||
|
NettyDevice controlDevice = controls.get(0);
|
||||||
|
if (!masterId.equals(controlDevice.getConnectorId())) {
|
||||||
|
//当前的设备有控制 的主机
|
||||||
|
deviceMaster.getConnectedConnectors().clear();
|
||||||
|
log.info("bindConnector RECEIVER 2:{}", masterId);
|
||||||
|
sessionManager.bindConnector(masterId, slaveId);
|
||||||
|
deviceMaster.setConnectorStatus(ConnectorStatus.RECEIVER);
|
||||||
|
deviceMaster.setCurrentSlaveId(slaveId);
|
||||||
|
sysUserClientService.updateAliveStatus(masterId, slaveId, 2);
|
||||||
|
}
|
||||||
|
//当前 切当前不做操作
|
||||||
|
}
|
||||||
}
|
}
|
||||||
//当前 切当前不做操作
|
return true;
|
||||||
}
|
}
|
||||||
return true;
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.error("切换设备失败: {}", e.getMessage(), e);
|
log.error("切换设备失败: {}", e.getMessage(), e);
|
||||||
}
|
}
|
||||||
@@ -270,18 +218,53 @@ public class TransferDeviceService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public DeviceControlDTO remoteControl(DeviceBindDTO bindDTO) {
|
public DeviceControlDTO remoteControl(DeviceBindDTO bindDTO, LoginUser user) {
|
||||||
try {
|
try {
|
||||||
String token = bindDTO.getToken();
|
String slaveId = bindDTO.getDeviceId();
|
||||||
String masterToken = sessionManager.getMaster(bindDTO.getDeviceId());
|
String platform = bindDTO.getPlatform();
|
||||||
|
String userName = user.getUsername();
|
||||||
|
String masterId = userName + ":" + platform;
|
||||||
DeviceControlDTO dto = new DeviceControlDTO();
|
DeviceControlDTO dto = new DeviceControlDTO();
|
||||||
if (!StringUtils.isEmpty(token) && token.equals(masterToken)) {
|
NettyDevice deviceMaster = sessionManager.getDevice(masterId);
|
||||||
dto.setRemoteControl(true);
|
log.info("remoteControl deviceMaster:{}", masterId);
|
||||||
dto.setOwner("you");
|
|
||||||
|
// //TODO 拓展当前控制不是同一个账号
|
||||||
|
// NettyDevice currentDevice = sessionManager.getCurrentControl(slaveId);
|
||||||
|
// if(currentDevice != null){
|
||||||
|
// if(currentDevice.getConnectorId().equals(masterId)){
|
||||||
|
// dto.setRemoteControl(true);
|
||||||
|
// dto.setOwner(platform);
|
||||||
|
// }else{
|
||||||
|
// dto.setRemoteControl(false);
|
||||||
|
// dto.setOwner(currentDevice.getConnectorId());
|
||||||
|
// }
|
||||||
|
// }else{
|
||||||
|
// dto.setRemoteControl(false);
|
||||||
|
// dto.setOwner(null);
|
||||||
|
// dto.setReason("occupied");
|
||||||
|
// }
|
||||||
|
|
||||||
|
if (deviceMaster != null) {
|
||||||
|
if (ConnectorStatus.ACTIVE.equals(deviceMaster.getConnectorStatus())) {
|
||||||
|
dto.setRemoteControl(true);
|
||||||
|
dto.setOwner(platform);
|
||||||
|
} else {
|
||||||
|
dto.setRemoteControl(false);
|
||||||
|
dto.setReason("occupied");
|
||||||
|
NettyDevice activeDevice = sessionManager.getUserControl(userName);
|
||||||
|
if (activeDevice != null) {
|
||||||
|
String[] l = activeDevice.getConnectorId().split(":");
|
||||||
|
dto.setOwner(l[1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
dto.setRemoteControl(false);
|
dto.setRemoteControl(false);
|
||||||
dto.setReason("occupied");
|
dto.setReason("not exist");
|
||||||
dto.setOwner(masterToken);
|
NettyDevice activeDevice = sessionManager.getUserControl(userName);
|
||||||
|
if (activeDevice != null) {
|
||||||
|
String[] l = activeDevice.getConnectorId().split(":");
|
||||||
|
dto.setOwner(l[1]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return dto;
|
return dto;
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
@@ -333,7 +316,7 @@ public class TransferDeviceService {
|
|||||||
}
|
}
|
||||||
masterDevice.setCurrentSlaveId(slaveId);
|
masterDevice.setCurrentSlaveId(slaveId);
|
||||||
masterDevice.setConnectorStatus(ConnectorStatus.ACTIVE);
|
masterDevice.setConnectorStatus(ConnectorStatus.ACTIVE);
|
||||||
// sysUserClientService.updateAliveStatus(masterDevice.getConnectorId(), slaveId, 1);
|
sysUserClientService.updateAliveStatus(masterDevice.getConnectorId(), slaveId, 1);
|
||||||
|
|
||||||
dto.setSwitchControl(true);
|
dto.setSwitchControl(true);
|
||||||
dto.setHolder(platform);
|
dto.setHolder(platform);
|
||||||
@@ -344,20 +327,23 @@ public class TransferDeviceService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void releaseControl(DeviceBindDTO bindDTO) {
|
public void releaseControl(DeviceBindDTO bindDTO, LoginUser user) {
|
||||||
try {
|
try {
|
||||||
|
String platform = bindDTO.getPlatform();
|
||||||
|
String userName = user.getUsername();
|
||||||
|
String masterId = userName + ":" + platform;
|
||||||
Integer type = bindDTO.getType();
|
Integer type = bindDTO.getType();
|
||||||
String masterId = sessionManager.getMaster(bindDTO.getDeviceId());
|
NettyDevice deviceMaster = sessionManager.getDevice(masterId);
|
||||||
if (type != null && !StringUtils.isEmpty(masterId)) {
|
if (deviceMaster != null && type!=null) {
|
||||||
NettyDevice device = sessionManager.getDevice(masterId);
|
if(type == 1){
|
||||||
if (type == 1) {
|
sysUserClientService.updateAliveStatus(masterId, "", 0);
|
||||||
device.setCurrentSlaveId(null);
|
deviceMaster.setCurrentSlaveId(null);
|
||||||
device.getConnectedConnectors().clear();
|
deviceMaster.getConnectedConnectors().clear();
|
||||||
} else if (type == 2) {
|
} else if (type == 2) {
|
||||||
device.setConnectorStatus(ConnectorStatus.RECEIVER);
|
deviceMaster.setConnectorStatus(ConnectorStatus.RECEIVER);
|
||||||
|
sysUserClientService.updateAliveStatus(masterId, deviceMaster.getCurrentSlaveId(), 2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
sessionManager.unLock(bindDTO.getDeviceId(), bindDTO.getToken(), false);
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.error(e.getMessage());
|
log.error(e.getMessage());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import com.maibu.core.controller.BaseController;
|
|||||||
import com.maibu.core.domain.AjaxResult;
|
import com.maibu.core.domain.AjaxResult;
|
||||||
import com.maibu.core.page.TableDataInfo;
|
import com.maibu.core.page.TableDataInfo;
|
||||||
import com.maibu.dto.DeviceParamAuthDTO;
|
import com.maibu.dto.DeviceParamAuthDTO;
|
||||||
|
import com.maibu.dto.DeviceRunningStatisticsQueryDTO;
|
||||||
import com.maibu.enums.BusinessType;
|
import com.maibu.enums.BusinessType;
|
||||||
import com.maibu.mapper.DeviceRunStatisticsMapper;
|
import com.maibu.mapper.DeviceRunStatisticsMapper;
|
||||||
import com.maibu.mybatis.LambdaQueryWrapperX;
|
import com.maibu.mybatis.LambdaQueryWrapperX;
|
||||||
@@ -272,14 +273,6 @@ public class DeviceController extends BaseController {
|
|||||||
return getDataTable(deviceService.getSiteList(getLoginUser(), device));
|
return getDataTable(deviceService.getSiteList(getLoginUser(), device));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 查询设备列表 分配页面
|
|
||||||
*/
|
|
||||||
@GetMapping("/getDeviceBySpiltCode")
|
|
||||||
public AjaxResult getDeviceBySpiltCode(@RequestParam String code) {
|
|
||||||
return AjaxResult.success(deviceService.getDeviceBySpiltCode(code));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 查询设备列表 分配页面
|
* 查询设备列表 分配页面
|
||||||
*/
|
*/
|
||||||
@@ -289,6 +282,14 @@ public class DeviceController extends BaseController {
|
|||||||
return getDataTable(deviceService.getDeviceList(getLoginUser(), device));
|
return getDataTable(deviceService.getDeviceList(getLoginUser(), device));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询设备列表 分配页面
|
||||||
|
*/
|
||||||
|
@GetMapping("/getDeviceBySpiltCode")
|
||||||
|
public AjaxResult getDeviceBySpiltCode(@RequestParam String code) {
|
||||||
|
return AjaxResult.success(deviceService.getDeviceBySpiltCode(code));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 设备授权修改
|
* 设备授权修改
|
||||||
*/
|
*/
|
||||||
@@ -297,6 +298,14 @@ public class DeviceController extends BaseController {
|
|||||||
return AjaxResult.success(deviceService.paramModifyAuth(dto));
|
return AjaxResult.success(deviceService.paramModifyAuth(dto));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查看当前设备有没授权修改参数
|
||||||
|
*/
|
||||||
|
@PostMapping("/runningHistoryStatistics")
|
||||||
|
public AjaxResult runningHistoryStatistics(@RequestBody DeviceRunningStatisticsQueryDTO dto) {
|
||||||
|
return AjaxResult.success(deviceService.runningHistoryStatistics(dto));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 查看当前设备有没授权修改参数
|
* 查看当前设备有没授权修改参数
|
||||||
*/
|
*/
|
||||||
@@ -305,5 +314,4 @@ public class DeviceController extends BaseController {
|
|||||||
return AjaxResult.success(deviceService.hasPermission(deviceId));
|
return AjaxResult.success(deviceService.hasPermission(deviceId));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,129 +0,0 @@
|
|||||||
package com.maibu.controller;
|
|
||||||
|
|
||||||
import com.maibu.core.controller.BaseController;
|
|
||||||
import com.maibu.core.domain.AjaxResult;
|
|
||||||
import com.maibu.core.domain.R;
|
|
||||||
import com.maibu.core.enums.OtaOperate;
|
|
||||||
import com.maibu.core.ota.DeviceOtaFirmware;
|
|
||||||
import com.maibu.core.ota.DeviceOtaOperateRecord;
|
|
||||||
import com.maibu.core.page.TableDataInfo;
|
|
||||||
import com.maibu.dto.BaseQueryDTO;
|
|
||||||
import com.maibu.dto.DeviceOtaOperateDTO;
|
|
||||||
import com.maibu.service.impl.DeviceOtaService;
|
|
||||||
import com.maibu.utils.MinioUtil;
|
|
||||||
import io.swagger.annotations.Api;
|
|
||||||
import io.swagger.annotations.ApiOperation;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.web.bind.annotation.*;
|
|
||||||
import org.springframework.web.multipart.MultipartFile;
|
|
||||||
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.time.LocalDateTime;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
@Api(tags = "OTA固件管理")
|
|
||||||
@RestController
|
|
||||||
@RequestMapping("/iot/deviceOta")
|
|
||||||
public class DeviceOtaController extends BaseController {
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private DeviceOtaService service;
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private MinioUtil minioUtil;
|
|
||||||
|
|
||||||
// ==================== 固件管理 ====================
|
|
||||||
|
|
||||||
@ApiOperation("新增或修改固件")
|
|
||||||
@PostMapping("/firmware/save")
|
|
||||||
public R saveFirmware(
|
|
||||||
@RequestPart("file") MultipartFile file, // 接收上传的图片
|
|
||||||
@RequestPart("firmware") DeviceOtaFirmware firmware // 接收表单里的 JSON 对象
|
|
||||||
) {
|
|
||||||
|
|
||||||
try (InputStream inputStream = file.getInputStream()) {
|
|
||||||
|
|
||||||
String fileName = "ota/firmware/" + firmware.getVersion();
|
|
||||||
|
|
||||||
// 上传到 MinIO
|
|
||||||
minioUtil.uploadFile(fileName, inputStream, "application/octet-stream");
|
|
||||||
|
|
||||||
// 获取访问 URL
|
|
||||||
String url = minioUtil.getPublicUrl(fileName);
|
|
||||||
System.out.println("固件上传成功,访问地址: " + url);
|
|
||||||
|
|
||||||
// 这里可以把 URL 存到 workRecord 里
|
|
||||||
firmware.setMinioObjectName(fileName);
|
|
||||||
firmware.setFileUrl(url);
|
|
||||||
boolean b = service.saveFirmware(firmware, file.getSize());
|
|
||||||
DeviceOtaOperateRecord record = new DeviceOtaOperateRecord();
|
|
||||||
record.setFileName(firmware.getVersion());
|
|
||||||
record.setFirmwareId(firmware.getId());
|
|
||||||
record.setOperateType(OtaOperate.upload);
|
|
||||||
record.setCreateBy(getUsername());
|
|
||||||
record.setCreateTime(LocalDateTime.now());
|
|
||||||
service.saveOperateRecord(record);
|
|
||||||
return !b ? R.fail("新增失败") : R.ok("新增成功");
|
|
||||||
} catch (Exception e) {
|
|
||||||
return R.fail("新增失败: " + e.getMessage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@ApiOperation("固件分页列表")
|
|
||||||
@PostMapping("/firmware/list")
|
|
||||||
public TableDataInfo listFirmware() {
|
|
||||||
startPage();
|
|
||||||
return getDataTable(service.listFirmware());
|
|
||||||
}
|
|
||||||
|
|
||||||
@ApiOperation("根据ID查询固件")
|
|
||||||
@GetMapping("/firmware/detail")
|
|
||||||
public AjaxResult selectFirmwareById(@RequestParam Long id) {
|
|
||||||
return AjaxResult.success(service.selectFirmwareById(id));
|
|
||||||
}
|
|
||||||
|
|
||||||
@ApiOperation("更新固件")
|
|
||||||
@PostMapping("/firmware/upgrade")
|
|
||||||
public AjaxResult upgrade(@RequestBody DeviceOtaOperateDTO dto) {
|
|
||||||
return service.upgrade(dto);
|
|
||||||
}
|
|
||||||
|
|
||||||
@ApiOperation("批量删除固件")
|
|
||||||
@PostMapping("/firmware/delete")
|
|
||||||
public AjaxResult deleteFirmware(@RequestBody List<Long> ids) {
|
|
||||||
return AjaxResult.success(service.deleteFirmware(ids));
|
|
||||||
}
|
|
||||||
|
|
||||||
// ==================== 操作记录管理 ====================
|
|
||||||
|
|
||||||
@ApiOperation("新增或修改操作记录")
|
|
||||||
@PostMapping("/record/save")
|
|
||||||
public AjaxResult saveOperateRecord(@RequestBody DeviceOtaOperateRecord record) {
|
|
||||||
return AjaxResult.success(service.saveOperateRecord(record));
|
|
||||||
}
|
|
||||||
|
|
||||||
@ApiOperation("操作记录分页列表")
|
|
||||||
@PostMapping("/record/list")
|
|
||||||
public TableDataInfo listOperateRecord(@RequestBody BaseQueryDTO dto) {
|
|
||||||
startPage();
|
|
||||||
return getDataTable(service.listOperateRecord(dto));
|
|
||||||
}
|
|
||||||
|
|
||||||
@ApiOperation("根据ID查询操作记录")
|
|
||||||
@GetMapping("/record/detail")
|
|
||||||
public AjaxResult selectOperateRecordById(@RequestParam Long id) {
|
|
||||||
return AjaxResult.success(service.selectOperateRecordById(id));
|
|
||||||
}
|
|
||||||
|
|
||||||
@GetMapping("/record/selectListByDeviceId")
|
|
||||||
public AjaxResult selectListByDeviceId(@RequestParam String deviceId) {
|
|
||||||
return AjaxResult.success(service.selectListByDeviceId(deviceId));
|
|
||||||
}
|
|
||||||
|
|
||||||
@ApiOperation("批量删除操作记录")
|
|
||||||
@PostMapping("/record/delete")
|
|
||||||
public AjaxResult deleteOperateRecord(@RequestBody List<Long> ids) {
|
|
||||||
return AjaxResult.success(service.deleteOperateRecord(ids));
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,19 +1,23 @@
|
|||||||
package com.maibu.controller;
|
package com.maibu.controller;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.concurrent.ExecutionException;
|
||||||
|
import java.util.concurrent.TimeoutException;
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
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.RequestParam;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
import com.maibu.core.business.DeviceRunParam;
|
import com.maibu.core.business.DeviceRunParam;
|
||||||
import com.maibu.core.controller.BaseController;
|
import com.maibu.core.controller.BaseController;
|
||||||
import com.maibu.core.domain.AjaxResult;
|
import com.maibu.core.domain.AjaxResult;
|
||||||
import com.maibu.core.page.TableDataInfo;
|
import com.maibu.core.page.TableDataInfo;
|
||||||
import com.maibu.dto.BaseQueryDTO;
|
import com.maibu.dto.BaseQueryDTO;
|
||||||
import com.maibu.service.impl.DeviceRunParamService;
|
import com.maibu.service.impl.DeviceRunParamService;
|
||||||
import com.maibu.utils.poi.ExcelUtil;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.web.bind.annotation.*;
|
|
||||||
import org.springframework.web.multipart.MultipartFile;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.concurrent.ExecutionException;
|
|
||||||
import java.util.concurrent.TimeoutException;
|
|
||||||
|
|
||||||
@RestController
|
@RestController
|
||||||
@RequestMapping("/iot/deviceRunParam")
|
@RequestMapping("/iot/deviceRunParam")
|
||||||
@@ -43,12 +47,5 @@ public class DeviceRunParamController extends BaseController {
|
|||||||
public AjaxResult delete(@RequestBody List<Long> ids) {
|
public AjaxResult delete(@RequestBody List<Long> ids) {
|
||||||
return AjaxResult.success(service.delete(ids));
|
return AjaxResult.success(service.delete(ids));
|
||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping("/importData")
|
|
||||||
public AjaxResult importData(MultipartFile file) throws Exception {
|
|
||||||
ExcelUtil<DeviceRunParam> util = new ExcelUtil<DeviceRunParam>(DeviceRunParam.class);
|
|
||||||
List<DeviceRunParam> paramList = util.importExcel(file.getInputStream());
|
|
||||||
boolean message = service.importParam(paramList);
|
|
||||||
return success(message);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,248 +0,0 @@
|
|||||||
package com.maibu.controller;
|
|
||||||
|
|
||||||
import java.io.BufferedReader;
|
|
||||||
import java.io.InputStreamReader;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.zip.GZIPInputStream;
|
|
||||||
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
|
||||||
import org.springframework.http.MediaType;
|
|
||||||
import org.springframework.util.CollectionUtils;
|
|
||||||
import org.springframework.web.bind.annotation.PostMapping;
|
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
|
||||||
import org.springframework.web.bind.annotation.RequestParam;
|
|
||||||
import org.springframework.web.bind.annotation.RequestPart;
|
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
|
||||||
import org.springframework.web.multipart.MultipartFile;
|
|
||||||
|
|
||||||
import com.maibu.core.business.device.NettyDevice;
|
|
||||||
import com.maibu.core.business.dto.WebRouteStatusMessageDTO;
|
|
||||||
import com.maibu.core.business.inter.WebsocketMesDispather;
|
|
||||||
import com.maibu.core.business.path.LatAndLngEntity;
|
|
||||||
import com.maibu.core.controller.BaseController;
|
|
||||||
import com.maibu.core.domain.R;
|
|
||||||
import com.maibu.core.enums.MesType;
|
|
||||||
import com.maibu.memory.DeviceSessionManager;
|
|
||||||
import com.maibu.memory.GlobalMemory;
|
|
||||||
import com.maibu.mqtt.MqttTopic;
|
|
||||||
import com.maibu.service.impl.HostComputerService;
|
|
||||||
import com.maibu.utils.json.JsonUtils;
|
|
||||||
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
|
|
||||||
@Slf4j
|
|
||||||
@RestController
|
|
||||||
@RequestMapping("/iot/host")
|
|
||||||
public class HostComputerController extends BaseController {
|
|
||||||
|
|
||||||
private static final int BATCH_SIZE = 5000;
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private HostComputerService hostComputerService;
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private WebsocketMesDispather websocketMesDispather;
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private DeviceSessionManager deviceSessionManager;
|
|
||||||
|
|
||||||
@Value("${mqtt.client-id}")
|
|
||||||
private String mqttClientId;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 上传 csv.gz 轨迹文件并解析为 LatAndLngEntity 列表(分批处理,每批 BATCH_SIZE 条)
|
|
||||||
*
|
|
||||||
* <p>
|
|
||||||
* CSV 格式:第 1 列=cell_index,第 2 列=x(lat),第 3 列=y(lng)
|
|
||||||
* </p>
|
|
||||||
*
|
|
||||||
* @param file csv.gz 压缩文件
|
|
||||||
* @param taskId 任务ID
|
|
||||||
* @return 解析后的完整轨迹数据
|
|
||||||
*/
|
|
||||||
@PostMapping(value = "/upload-path-csv", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
|
|
||||||
public R uploadCsv(
|
|
||||||
@RequestPart("file") MultipartFile file,
|
|
||||||
@RequestParam("taskId") Long taskId) {
|
|
||||||
if (file == null || file.isEmpty()) {
|
|
||||||
return R.fail("文件不能为空");
|
|
||||||
}
|
|
||||||
if (taskId == null) {
|
|
||||||
return R.fail("taskId 不能为空");
|
|
||||||
}
|
|
||||||
|
|
||||||
String originalFilename = file.getOriginalFilename();
|
|
||||||
if (originalFilename == null || !originalFilename.toLowerCase().endsWith(".csv.gz")) {
|
|
||||||
return R.fail("只支持 .csv.gz 格式文件");
|
|
||||||
}
|
|
||||||
|
|
||||||
log.info("收到 csv.gz 文件: taskId={}, fileName={}, size={}", taskId, originalFilename, file.getSize());
|
|
||||||
|
|
||||||
List<LatAndLngEntity> allPath = new ArrayList<>();
|
|
||||||
List<LatAndLngEntity> batch = new ArrayList<>(BATCH_SIZE);
|
|
||||||
int batchIndex = 0;
|
|
||||||
|
|
||||||
try (GZIPInputStream gzipInputStream = new GZIPInputStream(file.getInputStream());
|
|
||||||
BufferedReader reader = new BufferedReader(new InputStreamReader(gzipInputStream))) {
|
|
||||||
|
|
||||||
String line;
|
|
||||||
int lineNum = 0;
|
|
||||||
|
|
||||||
while ((line = reader.readLine()) != null) {
|
|
||||||
lineNum++;
|
|
||||||
if (line.trim().isEmpty()) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
String[] values = line.split(",");
|
|
||||||
|
|
||||||
if (lineNum < 4) {
|
|
||||||
log.info("CSV 表头: {}", Arrays.toString(values));
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (values.length < 3) {
|
|
||||||
log.warn("第 {} 行列数不足3列,跳过: {}", lineNum, line);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
LatAndLngEntity entity = parseLatLng(values);
|
|
||||||
if (entity != null) {
|
|
||||||
batch.add(entity);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (batch.size() >= BATCH_SIZE) {
|
|
||||||
batchIndex++;
|
|
||||||
processBatch(taskId, batch, batchIndex);
|
|
||||||
allPath.addAll(batch);
|
|
||||||
batch.clear();
|
|
||||||
log.info("csv 解析进度: taskId={}, 第 {} 批({}条), 累计 {} 条",
|
|
||||||
taskId, batchIndex, BATCH_SIZE, allPath.size());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!batch.isEmpty()) {
|
|
||||||
batchIndex++;
|
|
||||||
processBatch(taskId, batch, batchIndex);
|
|
||||||
allPath.addAll(batch);
|
|
||||||
batch.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
log.info("csv 解析完成: taskId={}, 共 {} 个轨迹点, 分 {} 批处理", taskId, allPath.size(), batchIndex);
|
|
||||||
|
|
||||||
GlobalMemory.taskPathMap.put(taskId, allPath);
|
|
||||||
sendMessage(taskId, allPath);
|
|
||||||
// TODO 推送数据到前端
|
|
||||||
|
|
||||||
return R.ok();
|
|
||||||
|
|
||||||
} catch (Exception e) {
|
|
||||||
log.error("csv.gz 解析失败: taskId={}, error={}", taskId, e.getMessage(), e);
|
|
||||||
return R.fail("文件解析失败: " + e.getMessage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 定位信息 经纬度
|
|
||||||
*/
|
|
||||||
private void sendMessage(Long taskId, List<LatAndLngEntity> data) {
|
|
||||||
try {
|
|
||||||
WebRouteStatusMessageDTO dto = new WebRouteStatusMessageDTO();
|
|
||||||
String deviceId = deviceSessionManager.getDeviceByTaskId(taskId);
|
|
||||||
log.debug("sendMessage: taskId={}, deviceId={}", taskId, deviceId);
|
|
||||||
List<NettyDevice> controlMasters = deviceSessionManager
|
|
||||||
.getAllSlaveControl(deviceId);
|
|
||||||
log.debug("sendMessage: controlMasters={}", JsonUtils.toJsonString(controlMasters));
|
|
||||||
dto.setData(data);
|
|
||||||
dto.setDeviceId(deviceId);
|
|
||||||
dto.setTaskId(taskId);
|
|
||||||
dto.setType(MesType.route_post);
|
|
||||||
if (!CollectionUtils.isEmpty(controlMasters)) {
|
|
||||||
for (NettyDevice x : controlMasters) {
|
|
||||||
try {
|
|
||||||
websocketMesDispather.dispather(x.getConnectorId(), JsonUtils.toJsonString(dto));
|
|
||||||
log.info("sendMessage推送成功: connectorId={}, taskId={}", x.getConnectorId(), taskId);
|
|
||||||
} catch (Exception e) {
|
|
||||||
log.error("sendMessage推送失败: connectorId={}, error={}", x.getConnectorId(),
|
|
||||||
e.getMessage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
GlobalMemory.customMqttDeviceMonitor.publish(mqttClientId,
|
|
||||||
String.format(MqttTopic.DEVICE_ROUTE_PUSH_TOPIC, deviceId),
|
|
||||||
JsonUtils.toJsonString(dto));
|
|
||||||
|
|
||||||
} catch (Exception e) {
|
|
||||||
log.error("sendMessage失败: taskId={}", taskId, e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 从 CSV 行解析 LatAndLngEntity
|
|
||||||
* 第 3 列(x) → lat,第 4 列(y) → lng
|
|
||||||
*/
|
|
||||||
private LatAndLngEntity parseLatLng(String[] values) {
|
|
||||||
try {
|
|
||||||
String xStr = values[2].trim();
|
|
||||||
String yStr = values[3].trim();
|
|
||||||
|
|
||||||
if (xStr.isEmpty() || yStr.isEmpty()) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
LatAndLngEntity entity = new LatAndLngEntity();
|
|
||||||
entity.setLat(Double.parseDouble(xStr));
|
|
||||||
entity.setLng(Double.parseDouble(yStr));
|
|
||||||
return entity;
|
|
||||||
} catch (NumberFormatException e) {
|
|
||||||
log.warn("解析轨迹点失败: values={}, error={}", Arrays.toString(values), e.getMessage());
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 分批处理轨迹数据
|
|
||||||
*
|
|
||||||
* <p>
|
|
||||||
* 每批 BATCH_SIZE 条数据触发一次,可用于:
|
|
||||||
* </p>
|
|
||||||
* <ul>
|
|
||||||
* <li>批量入库(insertBatch)</li>
|
|
||||||
* <li>发布 MQTT 消息到上位机</li>
|
|
||||||
* <li>数据校验/统计</li>
|
|
||||||
* </ul>
|
|
||||||
*
|
|
||||||
* @param taskId 任务ID
|
|
||||||
* @param path 当前批次的轨迹点列表
|
|
||||||
* @param batchIndex 批次序号(从 1 开始)
|
|
||||||
*/
|
|
||||||
protected void processBatch(Long taskId, List<LatAndLngEntity> path, int batchIndex) {
|
|
||||||
if (path == null || path.isEmpty()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
int size = path.size();
|
|
||||||
double minLat = Double.MAX_VALUE, maxLat = -Double.MAX_VALUE;
|
|
||||||
double minLng = Double.MAX_VALUE, maxLng = -Double.MAX_VALUE;
|
|
||||||
|
|
||||||
for (LatAndLngEntity p : path) {
|
|
||||||
if (p.getLat() < minLat)
|
|
||||||
minLat = p.getLat();
|
|
||||||
if (p.getLat() > maxLat)
|
|
||||||
maxLat = p.getLat();
|
|
||||||
if (p.getLng() < minLng)
|
|
||||||
minLng = p.getLng();
|
|
||||||
if (p.getLng() > maxLng)
|
|
||||||
maxLng = p.getLng();
|
|
||||||
}
|
|
||||||
|
|
||||||
log.info("【第 {} 批处理】taskId={}, 本批 {} 条, lat范围=[{}, {}], lng范围=[{}, {}]",
|
|
||||||
batchIndex, taskId, size,
|
|
||||||
String.format("%.6f", minLat), String.format("%.6f", maxLat),
|
|
||||||
String.format("%.6f", minLng), String.format("%.6f", maxLng));
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,20 +1,26 @@
|
|||||||
package com.maibu.controller;
|
package com.maibu.controller;
|
||||||
|
|
||||||
import com.maibu.core.business.WorkRecord;
|
|
||||||
import com.maibu.core.controller.BaseController;
|
|
||||||
import com.maibu.core.domain.AjaxResult;
|
|
||||||
import com.maibu.core.domain.R;
|
|
||||||
import com.maibu.memory.GlobalMemory;
|
|
||||||
import com.maibu.service.impl.WorkRecordService;
|
|
||||||
import com.maibu.utils.MinioUtil;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.http.MediaType;
|
|
||||||
import org.springframework.web.bind.annotation.*;
|
|
||||||
import org.springframework.web.multipart.MultipartFile;
|
|
||||||
|
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.http.MediaType;
|
||||||
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
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.RequestParam;
|
||||||
|
import org.springframework.web.bind.annotation.RequestPart;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
|
|
||||||
|
import com.maibu.core.business.WorkRecord;
|
||||||
|
import com.maibu.core.business.path.LatAndLngEntity;
|
||||||
|
import com.maibu.core.controller.BaseController;
|
||||||
|
import com.maibu.core.domain.R;
|
||||||
|
import com.maibu.service.impl.WorkRecordService;
|
||||||
|
import com.maibu.utils.MinioUtil;
|
||||||
|
|
||||||
@RestController
|
@RestController
|
||||||
@RequestMapping("/iot/workRecord")
|
@RequestMapping("/iot/workRecord")
|
||||||
public class WorkRecordController extends BaseController {
|
public class WorkRecordController extends BaseController {
|
||||||
@@ -32,11 +38,9 @@ public class WorkRecordController extends BaseController {
|
|||||||
) {
|
) {
|
||||||
int i = -1;
|
int i = -1;
|
||||||
|
|
||||||
// WorkRecord workRecordObj = JsonUtils.parseObject(workRecord,
|
// WorkRecord workRecordObj = JsonUtils.parseObject(workRecord, WorkRecord.class);
|
||||||
// WorkRecord.class);
|
|
||||||
|
|
||||||
WorkRecord workRecord1 = workRecordService.selectWorkRecordByWorkNameAndSiteId(workRecord.getWorkName(),
|
WorkRecord workRecord1 = workRecordService.selectWorkRecordByWorkNameAndSiteId(workRecord.getWorkName(), workRecord.getSiteId());
|
||||||
workRecord.getSiteId());
|
|
||||||
if (workRecord1 != null) {
|
if (workRecord1 != null) {
|
||||||
return R.fail("该任务已存在");
|
return R.fail("该任务已存在");
|
||||||
}
|
}
|
||||||
@@ -102,13 +106,8 @@ public class WorkRecordController extends BaseController {
|
|||||||
|
|
||||||
@GetMapping("/selectByTaskId")
|
@GetMapping("/selectByTaskId")
|
||||||
public R selectByTaskId(@RequestParam Long taskId) {
|
public R selectByTaskId(@RequestParam Long taskId) {
|
||||||
WorkRecord workRecord = workRecordService.selectByTaskId(taskId);
|
List<LatAndLngEntity> path = workRecordService.selectByTaskId(taskId);
|
||||||
return R.ok(workRecord);
|
return R.ok(path);
|
||||||
}
|
|
||||||
|
|
||||||
@GetMapping("getTaskPath")
|
|
||||||
public AjaxResult getTaskPath(@RequestParam Long taskId) {
|
|
||||||
return AjaxResult.success(GlobalMemory.taskPathMap.get(taskId));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,15 +0,0 @@
|
|||||||
package com.maibu.dto;
|
|
||||||
|
|
||||||
|
|
||||||
import com.maibu.core.enums.OtaOperate;
|
|
||||||
import lombok.Data;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
@Data
|
|
||||||
public class DeviceOtaOperateDTO {
|
|
||||||
|
|
||||||
private OtaOperate operateType;
|
|
||||||
private Long firmwareId;
|
|
||||||
private List<String> deviceModels;
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
package com.maibu.dto;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||||
|
import lombok.Data;
|
||||||
|
import org.springframework.format.annotation.DateTimeFormat;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class DeviceRunningStatisticsQueryDTO {
|
||||||
|
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
|
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
|
private LocalDateTime startTime;
|
||||||
|
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
|
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
|
private LocalDateTime endTime;
|
||||||
|
|
||||||
|
private String deviceId;
|
||||||
|
}
|
||||||
@@ -16,6 +16,7 @@ import java.util.List;
|
|||||||
@Repository
|
@Repository
|
||||||
public interface DeviceMapper extends BaseMapperX<Device> {
|
public interface DeviceMapper extends BaseMapperX<Device> {
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 根据设备编号查询设备
|
* 根据设备编号查询设备
|
||||||
*
|
*
|
||||||
@@ -24,6 +25,7 @@ public interface DeviceMapper extends BaseMapperX<Device> {
|
|||||||
*/
|
*/
|
||||||
public Device selectDeviceBySerialNumber(String serialNumber);
|
public Device selectDeviceBySerialNumber(String serialNumber);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 查询设备列表
|
* 查询设备列表
|
||||||
*
|
*
|
||||||
@@ -32,6 +34,7 @@ public interface DeviceMapper extends BaseMapperX<Device> {
|
|||||||
*/
|
*/
|
||||||
public List<Device> selectDeviceList(Device device);
|
public List<Device> selectDeviceList(Device device);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 根据产品ID查询产品下所有设备的编号
|
* 根据产品ID查询产品下所有设备的编号
|
||||||
*
|
*
|
||||||
@@ -63,6 +66,7 @@ public interface DeviceMapper extends BaseMapperX<Device> {
|
|||||||
*/
|
*/
|
||||||
public int updateDevice(Device device);
|
public int updateDevice(Device device);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 重置设备状态
|
* 重置设备状态
|
||||||
*
|
*
|
||||||
@@ -70,6 +74,7 @@ public interface DeviceMapper extends BaseMapperX<Device> {
|
|||||||
*/
|
*/
|
||||||
public int resetDeviceStatus(String deviceNum);
|
public int resetDeviceStatus(String deviceNum);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 根据产品ID获取产品下所有编号
|
* 根据产品ID获取产品下所有编号
|
||||||
*
|
*
|
||||||
@@ -86,6 +91,6 @@ public interface DeviceMapper extends BaseMapperX<Device> {
|
|||||||
*/
|
*/
|
||||||
public List<String> selectSerialNumbersByProductId(@Param("productId") Long productId);
|
public List<String> selectSerialNumbersByProductId(@Param("productId") Long productId);
|
||||||
|
|
||||||
public Device selectDeviceBySpiltCode(@Param("code") String code);
|
|
||||||
|
|
||||||
|
public Device selectDeviceBySpiltCode(@Param("code") String code);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,12 @@
|
|||||||
package com.maibu.service;
|
package com.maibu.service;
|
||||||
|
|
||||||
import com.maibu.core.business.Device;
|
import com.maibu.core.business.Device;
|
||||||
|
import com.maibu.core.business.DeviceRunningStatusHistory;
|
||||||
import com.maibu.core.business.dto.DeviceBindDTO;
|
import com.maibu.core.business.dto.DeviceBindDTO;
|
||||||
import com.maibu.core.domain.AjaxResult;
|
import com.maibu.core.domain.AjaxResult;
|
||||||
import com.maibu.core.domain.model.LoginUser;
|
import com.maibu.core.domain.model.LoginUser;
|
||||||
import com.maibu.dto.DeviceParamAuthDTO;
|
import com.maibu.dto.DeviceParamAuthDTO;
|
||||||
|
import com.maibu.dto.DeviceRunningStatisticsQueryDTO;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@@ -16,8 +18,10 @@ import java.util.List;
|
|||||||
*/
|
*/
|
||||||
public interface IDeviceService {
|
public interface IDeviceService {
|
||||||
|
|
||||||
|
|
||||||
public AjaxResult updateDeviceBySelf(Device device);
|
public AjaxResult updateDeviceBySelf(Device device);
|
||||||
|
|
||||||
|
|
||||||
public Device insertDeviceBySelf(Device device);
|
public Device insertDeviceBySelf(Device device);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -28,6 +32,7 @@ public interface IDeviceService {
|
|||||||
*/
|
*/
|
||||||
public Device selectDeviceBySerialNumber(String serialNumber);
|
public Device selectDeviceBySerialNumber(String serialNumber);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 查询设备列表
|
* 查询设备列表
|
||||||
*
|
*
|
||||||
@@ -36,6 +41,7 @@ public interface IDeviceService {
|
|||||||
*/
|
*/
|
||||||
public List<Device> selectDeviceList(Device device);
|
public List<Device> selectDeviceList(Device device);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 根据产品ID查询产品下所有设备的编号
|
* 根据产品ID查询产品下所有设备的编号
|
||||||
*
|
*
|
||||||
@@ -51,6 +57,7 @@ public interface IDeviceService {
|
|||||||
*/
|
*/
|
||||||
public int selectDeviceCountByProductId(Long productId);
|
public int selectDeviceCountByProductId(Long productId);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 重置设备状态
|
* 重置设备状态
|
||||||
*
|
*
|
||||||
@@ -58,6 +65,7 @@ public interface IDeviceService {
|
|||||||
*/
|
*/
|
||||||
public int resetDeviceStatus(String deviceNum);
|
public int resetDeviceStatus(String deviceNum);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 根据产品ID获取产品下所有编号
|
* 根据产品ID获取产品下所有编号
|
||||||
*
|
*
|
||||||
@@ -66,6 +74,7 @@ public interface IDeviceService {
|
|||||||
*/
|
*/
|
||||||
public String[] getDeviceNumsByProductId(Long productId);
|
public String[] getDeviceNumsByProductId(Long productId);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 查询产品下所有设备,返回设备编号
|
* 查询产品下所有设备,返回设备编号
|
||||||
*
|
*
|
||||||
@@ -74,10 +83,13 @@ public interface IDeviceService {
|
|||||||
*/
|
*/
|
||||||
public List<String> selectSerialNumbersByProductId(Long productId);
|
public List<String> selectSerialNumbersByProductId(Long productId);
|
||||||
|
|
||||||
|
|
||||||
public boolean bind(DeviceBindDTO bindDTO, String username);
|
public boolean bind(DeviceBindDTO bindDTO, String username);
|
||||||
|
|
||||||
|
|
||||||
public boolean unbind(DeviceBindDTO bindDTO, String username);
|
public boolean unbind(DeviceBindDTO bindDTO, String username);
|
||||||
|
|
||||||
|
|
||||||
public List<Device> getSiteList(LoginUser loginUser, Device device);
|
public List<Device> getSiteList(LoginUser loginUser, Device device);
|
||||||
|
|
||||||
public List<Device> getDeviceList(LoginUser loginUser, Device device);
|
public List<Device> getDeviceList(LoginUser loginUser, Device device);
|
||||||
@@ -88,4 +100,6 @@ public interface IDeviceService {
|
|||||||
|
|
||||||
public boolean hasPermission(String deviceId);
|
public boolean hasPermission(String deviceId);
|
||||||
|
|
||||||
|
public List<DeviceRunningStatusHistory> runningHistoryStatistics(DeviceRunningStatisticsQueryDTO dto);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,7 +13,6 @@ import com.maibu.core.enums.AlarmType;
|
|||||||
import com.maibu.core.redis.RedisCache;
|
import com.maibu.core.redis.RedisCache;
|
||||||
import org.eclipse.paho.client.mqttv3.MqttException;
|
import org.eclipse.paho.client.mqttv3.MqttException;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||||
@@ -52,10 +51,6 @@ public class AlarmServiceImpl extends ServiceImpl<AlarmMapper, Alarm> implements
|
|||||||
@Autowired
|
@Autowired
|
||||||
private RedisCache redisCache;
|
private RedisCache redisCache;
|
||||||
|
|
||||||
@Value("${mqtt.client-id}")
|
|
||||||
private String mqttClientId;
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<Alarm> selectAlarmPage(AlarmQueryDTO queryDTO) {
|
public List<Alarm> selectAlarmPage(AlarmQueryDTO queryDTO) {
|
||||||
// validateQueryParams(queryDTO);
|
// validateQueryParams(queryDTO);
|
||||||
@@ -412,8 +407,7 @@ public class AlarmServiceImpl extends ServiceImpl<AlarmMapper, Alarm> implements
|
|||||||
|
|
||||||
public void pushErrorMessage(String deviceId, String dto) {
|
public void pushErrorMessage(String deviceId, String dto) {
|
||||||
try {
|
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.mqttClientUtil.publish(String.format(MqttTopic.DEVICE_ERROR_PUSH_TOPIC, deviceId), dto);
|
|
||||||
// List<NettyDevice> controlMasters =
|
// List<NettyDevice> controlMasters =
|
||||||
// sessionManager.getAllSlaveControl(deviceId);
|
// sessionManager.getAllSlaveControl(deviceId);
|
||||||
// if (!CollectionUtils.isEmpty(controlMasters)) {
|
// if (!CollectionUtils.isEmpty(controlMasters)) {
|
||||||
|
|||||||
@@ -1,204 +0,0 @@
|
|||||||
package com.maibu.service.impl;
|
|
||||||
|
|
||||||
import java.time.LocalDateTime;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
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.core.business.Device;
|
|
||||||
import com.maibu.core.business.device.NettyDevice;
|
|
||||||
import com.maibu.core.domain.AjaxResult;
|
|
||||||
import com.maibu.core.ota.DeviceOtaFirmware;
|
|
||||||
import com.maibu.core.ota.DeviceOtaOperateRecord;
|
|
||||||
import com.maibu.dto.BaseQueryDTO;
|
|
||||||
import com.maibu.dto.DeviceOtaOperateDTO;
|
|
||||||
import com.maibu.mapper.DeviceOtaFirmwareMapper;
|
|
||||||
import com.maibu.mapper.DeviceOtaOperateRecordMapper;
|
|
||||||
import com.maibu.memory.DeviceSessionManager;
|
|
||||||
import com.maibu.service.IDeviceService;
|
|
||||||
import com.maibu.utils.MinioUtil;
|
|
||||||
import com.maibu.utils.SecurityUtils;
|
|
||||||
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
|
|
||||||
@Service
|
|
||||||
@Slf4j
|
|
||||||
public class DeviceOtaService {
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private DeviceOtaFirmwareMapper deviceOtaFirmwareMapper;
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private DeviceOtaOperateRecordMapper deviceOtaOperateRecordMapper;
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private MinioUtil minioUtil;
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private DeviceSessionManager deviceSessionManager;
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private IDeviceService deviceService;
|
|
||||||
|
|
||||||
private static final int BATCH_SIZE = 5;
|
|
||||||
|
|
||||||
public boolean saveFirmware(DeviceOtaFirmware firmware, Long fileSize) {
|
|
||||||
|
|
||||||
firmware.setCreateTime(LocalDateTime.now());
|
|
||||||
firmware.setCreateBy(SecurityUtils.getUsername());
|
|
||||||
firmware.setFileSize(formatFileSize(fileSize));
|
|
||||||
|
|
||||||
return deviceOtaFirmwareMapper.saveOrUpdate(firmware);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static String formatFileSize(long size) {
|
|
||||||
if (size < 1024) {
|
|
||||||
return size + " B";
|
|
||||||
}
|
|
||||||
|
|
||||||
double kb = size / 1024.0;
|
|
||||||
if (kb < 1024) {
|
|
||||||
return String.format("%.2f KB", kb);
|
|
||||||
}
|
|
||||||
|
|
||||||
double mb = kb / 1024.0;
|
|
||||||
if (mb < 1024) {
|
|
||||||
return String.format("%.2f MB", mb);
|
|
||||||
}
|
|
||||||
|
|
||||||
double gb = mb / 1024.0;
|
|
||||||
return String.format("%.2f GB", gb);
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<DeviceOtaFirmware> listFirmware() {
|
|
||||||
LambdaQueryWrapper<DeviceOtaFirmware> queryWrapper = new LambdaQueryWrapper<>();
|
|
||||||
queryWrapper.orderByDesc(DeviceOtaFirmware::getCreateTime);
|
|
||||||
return deviceOtaFirmwareMapper.selectList(queryWrapper);
|
|
||||||
}
|
|
||||||
|
|
||||||
public DeviceOtaFirmware selectFirmwareById(Long id) {
|
|
||||||
return deviceOtaFirmwareMapper.selectById(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
public AjaxResult upgrade(DeviceOtaOperateDTO dto) {
|
|
||||||
if (dto.getFirmwareId() == null) {
|
|
||||||
return AjaxResult.error("固件ID不能为空");
|
|
||||||
}
|
|
||||||
if (CollectionUtils.isEmpty(dto.getDeviceModels())) {
|
|
||||||
return AjaxResult.error("请选择要升级的设备");
|
|
||||||
}
|
|
||||||
|
|
||||||
DeviceOtaFirmware firmware = deviceOtaFirmwareMapper.selectById(dto.getFirmwareId());
|
|
||||||
if (firmware == null) {
|
|
||||||
return AjaxResult.error("固件不存在");
|
|
||||||
}
|
|
||||||
|
|
||||||
List<DeviceOtaOperateRecord> records = new ArrayList<>();
|
|
||||||
|
|
||||||
int totalDevices = dto.getDeviceModels().size();
|
|
||||||
int successCount = 0;
|
|
||||||
int offlineCount = 0;
|
|
||||||
|
|
||||||
for (int i = 0; i < totalDevices; i += BATCH_SIZE) {
|
|
||||||
List<String> batch = dto.getDeviceModels().subList(i, Math.min(i + BATCH_SIZE, totalDevices));
|
|
||||||
log.info("OTA 灰度升级 第 {} 批, 本批设备数: {}", (i / BATCH_SIZE) + 1, batch.size());
|
|
||||||
|
|
||||||
for (String deviceId : batch) {
|
|
||||||
NettyDevice device = deviceSessionManager.getDevice(deviceId);
|
|
||||||
if (device == null || device.getOnlineStatus() == 0) {
|
|
||||||
log.warn("设备 {} 离线,跳过升级", deviceId);
|
|
||||||
offlineCount++;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
device.upgrade(deviceId, firmware);
|
|
||||||
|
|
||||||
Device updatedDevice = device.getDevice();
|
|
||||||
|
|
||||||
DeviceOtaOperateRecord record = new DeviceOtaOperateRecord();
|
|
||||||
record.setOperateType(dto.getOperateType());
|
|
||||||
record.setFirmwareId(firmware.getId());
|
|
||||||
record.setFileName(firmware.getFileName());
|
|
||||||
record.setDeviceType(firmware.getDeviceType());
|
|
||||||
record.setCreateTime(LocalDateTime.now());
|
|
||||||
record.setCreateBy(SecurityUtils.getUsername());
|
|
||||||
record.setDeviceId(deviceId);
|
|
||||||
record.setPreVersion(updatedDevice.getFirmwareVersion());
|
|
||||||
record.setNowVersion(firmware.getVersion());
|
|
||||||
records.add(record);
|
|
||||||
|
|
||||||
updatedDevice.setFirmwareVersion(firmware.getVersion());
|
|
||||||
deviceService.updateDeviceBySelf(updatedDevice);
|
|
||||||
|
|
||||||
successCount++;
|
|
||||||
log.info("OTA 升级指令已下发: deviceId={}, version={}", deviceId, firmware.getVersion());
|
|
||||||
} catch (Exception e) {
|
|
||||||
log.error("OTA 升级指令下发失败: deviceId={}", deviceId, e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
deviceOtaOperateRecordMapper.saveOrUpdateBatch(records);
|
|
||||||
|
|
||||||
String msg = String.format("升级指令下发完成: 成功=%d, 离线=%d, 总计=%d",
|
|
||||||
successCount, offlineCount, totalDevices);
|
|
||||||
log.info(msg);
|
|
||||||
return AjaxResult.success(msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
public int deleteFirmware(List<Long> ids) {
|
|
||||||
if (CollectionUtils.isEmpty(ids)) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
List<DeviceOtaFirmware> list = deviceOtaFirmwareMapper.selectBatchIds(ids);
|
|
||||||
if (!CollectionUtils.isEmpty(list)) {
|
|
||||||
list.forEach(l -> {
|
|
||||||
try {
|
|
||||||
minioUtil.deleteFile(l.getMinioObjectName());
|
|
||||||
} catch (Exception e) {
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
return deviceOtaFirmwareMapper.deleteBatchIds(ids);
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean saveOperateRecord(DeviceOtaOperateRecord record) {
|
|
||||||
return deviceOtaOperateRecordMapper.saveOrUpdate(record);
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<DeviceOtaOperateRecord> listOperateRecord(BaseQueryDTO dto) {
|
|
||||||
LambdaQueryWrapper<DeviceOtaOperateRecord> queryWrapper = new LambdaQueryWrapper<>();
|
|
||||||
if (dto != null) {
|
|
||||||
if (!StringUtils.isEmpty(dto.getDeviceId())) {
|
|
||||||
queryWrapper.eq(DeviceOtaOperateRecord::getDeviceType, dto.getDeviceId());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
queryWrapper.orderByDesc(DeviceOtaOperateRecord::getCreateTime);
|
|
||||||
return deviceOtaOperateRecordMapper.selectList(queryWrapper);
|
|
||||||
}
|
|
||||||
|
|
||||||
public DeviceOtaOperateRecord selectOperateRecordById(Long id) {
|
|
||||||
return deviceOtaOperateRecordMapper.selectById(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<DeviceOtaOperateRecord> selectListByDeviceId(String deviceId) {
|
|
||||||
LambdaQueryWrapper<DeviceOtaOperateRecord> wrapper = new LambdaQueryWrapper<>();
|
|
||||||
wrapper.eq(DeviceOtaOperateRecord::getDeviceId, deviceId);
|
|
||||||
return deviceOtaOperateRecordMapper.selectList(wrapper);
|
|
||||||
}
|
|
||||||
|
|
||||||
public int deleteOperateRecord(List<Long> ids) {
|
|
||||||
if (CollectionUtils.isEmpty(ids)) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return deviceOtaOperateRecordMapper.deleteBatchIds(ids);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,21 +1,5 @@
|
|||||||
package com.maibu.service.impl;
|
package com.maibu.service.impl;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.concurrent.CompletableFuture;
|
|
||||||
import java.util.concurrent.ExecutionException;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
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.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||||
import com.maibu.constant.Constant;
|
import com.maibu.constant.Constant;
|
||||||
import com.maibu.core.business.DeviceRunParam;
|
import com.maibu.core.business.DeviceRunParam;
|
||||||
@@ -26,8 +10,17 @@ import com.maibu.mapper.DeviceRunParamMapper;
|
|||||||
import com.maibu.memory.DeviceSessionManager;
|
import com.maibu.memory.DeviceSessionManager;
|
||||||
import com.maibu.memory.GlobalMemory;
|
import com.maibu.memory.GlobalMemory;
|
||||||
import com.maibu.memory.SiteMemory;
|
import com.maibu.memory.SiteMemory;
|
||||||
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
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.List;
|
||||||
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
import java.util.concurrent.ExecutionException;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
import java.util.concurrent.TimeoutException;
|
||||||
|
|
||||||
@Service
|
@Service
|
||||||
@Slf4j
|
@Slf4j
|
||||||
@@ -39,8 +32,7 @@ public class DeviceRunParamService {
|
|||||||
@Autowired
|
@Autowired
|
||||||
private DeviceSessionManager sessionManager;
|
private DeviceSessionManager sessionManager;
|
||||||
|
|
||||||
public boolean save(DeviceRunParam deviceRunParam)
|
public boolean save(DeviceRunParam deviceRunParam) throws ExecutionException, InterruptedException, TimeoutException {
|
||||||
throws ExecutionException, InterruptedException, TimeoutException {
|
|
||||||
|
|
||||||
NettyDevice nettyDevice = sessionManager.getDevice(deviceRunParam.getDeviceId());
|
NettyDevice nettyDevice = sessionManager.getDevice(deviceRunParam.getDeviceId());
|
||||||
if (nettyDevice == null || !nettyDevice.getChannel().isActive()) {
|
if (nettyDevice == null || !nettyDevice.getChannel().isActive()) {
|
||||||
@@ -95,73 +87,30 @@ public class DeviceRunParamService {
|
|||||||
return deviceRunParamMapper.selectList(queryWrapper);
|
return deviceRunParamMapper.selectList(queryWrapper);
|
||||||
}
|
}
|
||||||
|
|
||||||
// public DeviceRunParam selectByDeviceId(String deviceId)
|
public DeviceRunParam selectByDeviceId(String deviceId) throws ExecutionException, InterruptedException, TimeoutException {
|
||||||
// throws ExecutionException, InterruptedException, TimeoutException {
|
NettyDevice nettyDevice = sessionManager.getDevice(deviceId);
|
||||||
|
CompletableFuture<DeviceRunParam> 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);
|
||||||
|
|
||||||
// NettyDevice nettyDevice = sessionManager.getDevice(deviceId);
|
LambdaQueryWrapper<DeviceRunParam> queryWrapper = new LambdaQueryWrapper<>();
|
||||||
// CompletableFuture<DeviceRunParam> future = new CompletableFuture<>();
|
if (!StringUtils.isEmpty(deviceId)) {
|
||||||
// if (nettyDevice != null && nettyDevice.getChannel() != null &&
|
queryWrapper.eq(DeviceRunParam::getDeviceId, deviceId);
|
||||||
// nettyDevice.getChannel().isActive()) {
|
|
||||||
// nettyDevice.getChannel().attr(Constant.READ_CONFIG_KEY).set(future);
|
|
||||||
// try {
|
|
||||||
// nettyDevice.readConfigCommand();
|
|
||||||
// DeviceRunParam param = future.get(5, TimeUnit.SECONDS);
|
|
||||||
|
|
||||||
// LambdaQueryWrapper<DeviceRunParam> 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<DeviceRunParam> 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<DeviceRunParam> 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<DeviceRunParam> 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;
|
return null;
|
||||||
@@ -181,56 +130,5 @@ public class DeviceRunParamService {
|
|||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean importParam(List<DeviceRunParam> params) {
|
|
||||||
try {
|
|
||||||
if (!CollectionUtils.isEmpty(params)) {
|
|
||||||
|
|
||||||
List<String> snList = params.stream().map(DeviceRunParam::getDeviceId).collect(Collectors.toList());
|
|
||||||
|
|
||||||
if (!CollectionUtils.isEmpty(snList)) {
|
|
||||||
LambdaQueryWrapper<DeviceRunParam> queryWrapper = new LambdaQueryWrapper<>();
|
|
||||||
queryWrapper.in(DeviceRunParam::getDeviceId, snList);
|
|
||||||
List<DeviceRunParam> oldList = deviceRunParamMapper.selectList(queryWrapper);
|
|
||||||
Map<String, DeviceRunParam> map = oldList.stream()
|
|
||||||
.collect(Collectors.toMap(
|
|
||||||
DeviceRunParam::getDeviceId,
|
|
||||||
Function.identity()));
|
|
||||||
List<DeviceRunParam> saveList = new ArrayList<>();
|
|
||||||
params.forEach(x -> {
|
|
||||||
if (StringUtils.isEmpty(x.getDeviceId()))
|
|
||||||
return;
|
|
||||||
DeviceRunParam deviceRunParam = null;
|
|
||||||
if (!CollectionUtils.isEmpty(map)) {
|
|
||||||
deviceRunParam = map.get(x.getDeviceId());
|
|
||||||
}
|
|
||||||
if (!StringUtils.isEmpty(x.getCapabilities())) {
|
|
||||||
List<String> list = Arrays.stream(x.getCapabilities().split(","))
|
|
||||||
.map(String::trim)
|
|
||||||
.collect(Collectors.toList());
|
|
||||||
x.setCapabilityList(list);
|
|
||||||
}
|
|
||||||
if (deviceRunParam != null) {
|
|
||||||
deviceRunParam.setCapabilityList(x.getCapabilityList());
|
|
||||||
deviceRunParam.setProductModel(x.getProductModel());
|
|
||||||
deviceRunParam.setRtkMode(x.getRtkMode());
|
|
||||||
deviceRunParam.setDeviceType(x.getDeviceType());
|
|
||||||
deviceRunParam.setPowerType(x.getPowerType());
|
|
||||||
deviceRunParam.setCameraNum(x.getCameraNum());
|
|
||||||
deviceRunParam.setWheelType(x.getWheelType());
|
|
||||||
deviceRunParam.setEngineType(x.getEngineType());
|
|
||||||
deviceRunParam.setHasHost(x.getHasHost());
|
|
||||||
saveList.add(deviceRunParam);
|
|
||||||
} else {
|
|
||||||
saveList.add(x);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return deviceRunParamMapper.saveOrUpdateBatch(saveList);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
} catch (Exception e) {
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -8,11 +8,13 @@ import java.util.List;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
import java.util.function.Function;
|
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
|
|
||||||
|
import com.maibu.constant.CacheConstants;
|
||||||
|
import com.maibu.dto.DeviceParamAuthDTO;
|
||||||
|
import com.maibu.dto.DeviceRunningStatisticsQueryDTO;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
@@ -21,8 +23,8 @@ import org.springframework.stereotype.Service;
|
|||||||
import org.springframework.util.CollectionUtils;
|
import org.springframework.util.CollectionUtils;
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||||
import com.maibu.constant.CacheConstants;
|
import com.influxdb.query.FluxRecord;
|
||||||
import com.maibu.constant.NettyCacheKey;
|
import com.influxdb.query.FluxTable;
|
||||||
import com.maibu.core.business.Device;
|
import com.maibu.core.business.Device;
|
||||||
import com.maibu.core.business.DevicePlan;
|
import com.maibu.core.business.DevicePlan;
|
||||||
import com.maibu.core.business.DeviceRunningStatusHistory;
|
import com.maibu.core.business.DeviceRunningStatusHistory;
|
||||||
@@ -33,13 +35,13 @@ import com.maibu.core.domain.entity.SysRole;
|
|||||||
import com.maibu.core.domain.entity.SysSite;
|
import com.maibu.core.domain.entity.SysSite;
|
||||||
import com.maibu.core.domain.model.LoginUser;
|
import com.maibu.core.domain.model.LoginUser;
|
||||||
import com.maibu.core.enums.DeviceTaskStaus;
|
import com.maibu.core.enums.DeviceTaskStaus;
|
||||||
import com.maibu.core.host.LocationMessage;
|
|
||||||
import com.maibu.core.redis.RedisCache;
|
import com.maibu.core.redis.RedisCache;
|
||||||
import com.maibu.dto.DeviceParamAuthDTO;
|
import com.maibu.influxdb.MowerRealTimeData;
|
||||||
|
import com.maibu.influxdb.util.InfluxSqlBuilder;
|
||||||
|
import com.maibu.influxdb.util.LambdaUtils;
|
||||||
import com.maibu.mapper.DeviceMapper;
|
import com.maibu.mapper.DeviceMapper;
|
||||||
import com.maibu.mapper.DevicePlanMapper;
|
import com.maibu.mapper.DevicePlanMapper;
|
||||||
import com.maibu.mapper.DeviceStatusHistoryMapper;
|
import com.maibu.mapper.DeviceStatusHistoryMapper;
|
||||||
import com.maibu.mapper.HostLocationMapper;
|
|
||||||
import com.maibu.mapper.SysSiteMapper;
|
import com.maibu.mapper.SysSiteMapper;
|
||||||
import com.maibu.memory.GlobalMemory;
|
import com.maibu.memory.GlobalMemory;
|
||||||
import com.maibu.memory.SiteMemory;
|
import com.maibu.memory.SiteMemory;
|
||||||
@@ -74,9 +76,6 @@ public class DeviceServiceImpl implements IDeviceService {
|
|||||||
@Autowired
|
@Autowired
|
||||||
private SysSiteMapper sysSiteMapper;
|
private SysSiteMapper sysSiteMapper;
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private HostLocationMapper hostLocationMapper;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 根据设备编号查询设备
|
* 根据设备编号查询设备
|
||||||
*
|
*
|
||||||
@@ -149,13 +148,6 @@ public class DeviceServiceImpl implements IDeviceService {
|
|||||||
Map<String, List<DeviceRunningStatusHistory>> statusMap = allStatusList.stream()
|
Map<String, List<DeviceRunningStatusHistory>> statusMap = allStatusList.stream()
|
||||||
.collect(Collectors.groupingBy(DeviceRunningStatusHistory::getDeviceId));
|
.collect(Collectors.groupingBy(DeviceRunningStatusHistory::getDeviceId));
|
||||||
|
|
||||||
LambdaQueryWrapper<LocationMessage> query = new LambdaQueryWrapper<>();
|
|
||||||
query.in(LocationMessage::getDeviceId, ids);
|
|
||||||
|
|
||||||
List<LocationMessage> hostLocations = hostLocationMapper.selectList(query);
|
|
||||||
Map<String, LocationMessage> locationMap = hostLocations.stream()
|
|
||||||
.collect(Collectors.toMap(LocationMessage::getDeviceId, Function.identity()));
|
|
||||||
|
|
||||||
deviceList.forEach(x -> {
|
deviceList.forEach(x -> {
|
||||||
Integer s = x.getOnlineStatus() == null ? 0 : x.getOnlineStatus();
|
Integer s = x.getOnlineStatus() == null ? 0 : x.getOnlineStatus();
|
||||||
if (0 == s) {
|
if (0 == s) {
|
||||||
@@ -192,13 +184,6 @@ public class DeviceServiceImpl implements IDeviceService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
x.setLastRunningStatus(lastRunningStatus);
|
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));
|
deviceList.sort(Comparator.comparing(Device::getFeStatus));
|
||||||
}
|
}
|
||||||
@@ -328,24 +313,13 @@ public class DeviceServiceImpl implements IDeviceService {
|
|||||||
if (!CollectionUtils.isEmpty(deviceList)) {
|
if (!CollectionUtils.isEmpty(deviceList)) {
|
||||||
List<String> ids = deviceList.stream().map(Device::getDeviceName).collect(Collectors.toList());
|
List<String> ids = deviceList.stream().map(Device::getDeviceName).collect(Collectors.toList());
|
||||||
List<DeviceRunningStatusHistory> allStatusList = deviceStatusHistoryMapper.selectLatestByDeviceIds(ids);
|
List<DeviceRunningStatusHistory> allStatusList = deviceStatusHistoryMapper.selectLatestByDeviceIds(ids);
|
||||||
// 有上位机的
|
|
||||||
LambdaQueryWrapper<LocationMessage> query = new LambdaQueryWrapper<>();
|
|
||||||
query.in(LocationMessage::getDeviceId, ids);
|
|
||||||
List<LocationMessage> hostLocations = hostLocationMapper.selectList(query);
|
|
||||||
Map<String, LocationMessage> locationMap = hostLocations.stream()
|
|
||||||
.collect(Collectors.toMap(LocationMessage::getDeviceId, Function.identity()));
|
|
||||||
|
|
||||||
for (Device x : deviceList) {
|
for (Device x : deviceList) {
|
||||||
if (siteMemory.hasTask(x.getSerialNumber())) {
|
if (siteMemory.hasTask(x.getSerialNumber())) {
|
||||||
work += 1;
|
work += 1;
|
||||||
x.setFeStatus(1);
|
x.setFeStatus(1);
|
||||||
} else {
|
} else {
|
||||||
free += 1;
|
free += 1;
|
||||||
if (x.getOnlineStatus() == null || x.getOnlineStatus() == 0) {
|
x.setFeStatus(2);
|
||||||
x.setFeStatus(3);
|
|
||||||
} else {
|
|
||||||
x.setFeStatus(2);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
String key = "running_status:" + x.getDeviceName();
|
String key = "running_status:" + x.getDeviceName();
|
||||||
DeviceStatusRecordDTO recordDTO = redisCache.getCacheObject(key);
|
DeviceStatusRecordDTO recordDTO = redisCache.getCacheObject(key);
|
||||||
@@ -371,27 +345,16 @@ public class DeviceServiceImpl implements IDeviceService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
x.setLastRunningStatus(lastRunningStatus);
|
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);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
statusStatistics.put(0, work);
|
statusStatistics.put(0, work);
|
||||||
statusStatistics.put(1, free);
|
statusStatistics.put(1, free);
|
||||||
deviceList.forEach(y -> {
|
deviceList.forEach(y -> {
|
||||||
y.setStatusStatistics(statusStatistics);
|
y.setStatusStatistics(statusStatistics);
|
||||||
});
|
});
|
||||||
|
deviceList.sort(Comparator.comparing(Device::getFeStatus));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!CollectionUtils.isEmpty(deviceList)) {
|
|
||||||
deviceList.sort(Comparator.comparing(Device::getFeStatus));
|
|
||||||
}
|
|
||||||
return deviceList;
|
return deviceList;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -420,6 +383,12 @@ public class DeviceServiceImpl implements IDeviceService {
|
|||||||
return deviceList;
|
return deviceList;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Device getDeviceBySpiltCode(String code) {
|
||||||
|
return deviceMapper.selectDeviceBySpiltCode(code);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean paramModifyAuth(DeviceParamAuthDTO dto) {
|
public boolean paramModifyAuth(DeviceParamAuthDTO dto) {
|
||||||
if (dto != null && !StringUtils.isEmpty(dto.getDeviceId())) {
|
if (dto != null && !StringUtils.isEmpty(dto.getDeviceId())) {
|
||||||
@@ -441,8 +410,31 @@ public class DeviceServiceImpl implements IDeviceService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Device getDeviceBySpiltCode(String code) {
|
public List<DeviceRunningStatusHistory> runningHistoryStatistics(DeviceRunningStatisticsQueryDTO dto) {
|
||||||
return deviceMapper.selectDeviceBySpiltCode(code);
|
LambdaQueryWrapper<DeviceRunningStatusHistory> queryWrapper = new LambdaQueryWrapper<>();
|
||||||
|
if (dto != null && !StringUtils.isEmpty(dto.getDeviceId())) {
|
||||||
|
queryWrapper.eq(DeviceRunningStatusHistory::getDeviceId, dto.getDeviceId());
|
||||||
|
}
|
||||||
|
if (dto != null && dto.getStartTime() != null && dto.getEndTime() != null) {
|
||||||
|
queryWrapper.ge(DeviceRunningStatusHistory::getCreateTime, dto.getStartTime());
|
||||||
|
queryWrapper.le(DeviceRunningStatusHistory::getCreateTime, dto.getEndTime());
|
||||||
|
}
|
||||||
|
List<DeviceRunningStatusHistory> list = deviceStatusHistoryMapper.selectList(queryWrapper);
|
||||||
|
|
||||||
|
String key = "running_status:" + dto.getDeviceId();
|
||||||
|
DeviceStatusRecordDTO recordDTO = redisCache.getCacheObject(key);
|
||||||
|
List<DeviceRunningStatusHistory> cacheList;
|
||||||
|
if (recordDTO != null) {
|
||||||
|
cacheList = recordDTO.getHistories();
|
||||||
|
if (!CollectionUtils.isEmpty(list)) {
|
||||||
|
if (!CollectionUtils.isEmpty(cacheList)) {
|
||||||
|
list.addAll(cacheList);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return cacheList;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,18 +0,0 @@
|
|||||||
package com.maibu.service.impl;
|
|
||||||
|
|
||||||
import com.maibu.core.business.WorkRecord;
|
|
||||||
import com.maibu.memory.GlobalMemory;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.stereotype.Service;
|
|
||||||
|
|
||||||
@Service
|
|
||||||
@Slf4j
|
|
||||||
public class HostComputerService {
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private WorkRecordService workRecordService;
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -3,13 +3,13 @@ package com.maibu.service.impl;
|
|||||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||||
import com.maibu.core.business.DevicePlanTask;
|
import com.maibu.core.business.DevicePlanTask;
|
||||||
import com.maibu.core.business.WorkRecord;
|
import com.maibu.core.business.WorkRecord;
|
||||||
|
import com.maibu.core.business.path.LatAndLngEntity;
|
||||||
import com.maibu.mapper.DevicePlanTaskMapper;
|
import com.maibu.mapper.DevicePlanTaskMapper;
|
||||||
import com.maibu.mapper.WorkRecordMapper;
|
import com.maibu.mapper.WorkRecordMapper;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.util.CollectionUtils;
|
import org.springframework.util.CollectionUtils;
|
||||||
|
|
||||||
import java.util.Comparator;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@Service
|
@Service
|
||||||
@@ -64,7 +64,6 @@ public class WorkRecordService {
|
|||||||
list.forEach(workRecord -> {
|
list.forEach(workRecord -> {
|
||||||
workRecord.setJsonData(null);
|
workRecord.setJsonData(null);
|
||||||
});
|
});
|
||||||
list.sort(Comparator.comparing(WorkRecord::getId).reversed());
|
|
||||||
}
|
}
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
@@ -73,13 +72,16 @@ public class WorkRecordService {
|
|||||||
return workRecordMapper.selectById(id);
|
return workRecordMapper.selectById(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
public WorkRecord selectByTaskId(Long taskId) {
|
public List<LatAndLngEntity> selectByTaskId(Long taskId) {
|
||||||
DevicePlanTask devicePlanTask = devicePlanTaskMapper.selectById(taskId); // 先查询设备任务,确认任务存在
|
DevicePlanTask devicePlanTask = devicePlanTaskMapper.selectById(taskId); // 先查询设备任务,确认任务存在
|
||||||
if (devicePlanTask == null) {
|
if (devicePlanTask == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
Long routeId = devicePlanTask.getRouteId(); // 获取任务关联的路线ID
|
Long routeId = devicePlanTask.getRouteId(); // 获取任务关联的路线ID
|
||||||
WorkRecord workRecord = workRecordMapper.selectById(routeId); // 查询路线ID对应的工作记录
|
WorkRecord workRecord = workRecordMapper.selectById(routeId); // 查询路线ID对应的工作记录
|
||||||
return workRecord; // 如果没有找到对应的工作记录或路线数据,返回 null
|
if (workRecord != null && workRecord.getJsonData() != null) {
|
||||||
|
return workRecord.getJsonData().getPath(); // 返回路线数据
|
||||||
|
}
|
||||||
|
return null; // 如果没有找到对应的工作记录或路线数据,返回 null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -39,14 +39,10 @@
|
|||||||
<result property="guid" column="guid"/>
|
<result property="guid" column="guid"/>
|
||||||
<result property="protocolCode" column="protocol_code"/>
|
<result property="protocolCode" column="protocol_code"/>
|
||||||
<result property="onlineStatus" column="online_status"/>
|
<result property="onlineStatus" column="online_status"/>
|
||||||
<result property="hasHost" column="has_host"/>
|
|
||||||
<result property="hasRegistered" column="has_registered"/>
|
|
||||||
</resultMap>
|
</resultMap>
|
||||||
|
|
||||||
<sql id="selectDeviceVo">
|
<sql id="selectDeviceVo">
|
||||||
select d.online_status,
|
select d.online_status,
|
||||||
d.has_host,
|
|
||||||
d.has_registered,
|
|
||||||
d.device_alias,
|
d.device_alias,
|
||||||
d.device_id,
|
d.device_id,
|
||||||
d.org_id,
|
d.org_id,
|
||||||
@@ -149,8 +145,6 @@
|
|||||||
and d.active_time between #{params.beginActiveTime} and #{params.endActiveTime}
|
and d.active_time between #{params.beginActiveTime} and #{params.endActiveTime}
|
||||||
</if>
|
</if>
|
||||||
<if test="onlineStatus != null ">and d.online_status = #{onlineStatus}</if>
|
<if test="onlineStatus != null ">and d.online_status = #{onlineStatus}</if>
|
||||||
<if test="hasHost != null ">and d.has_host = #{hasHost}</if>
|
|
||||||
<if test="hasRegistered != null ">and d.has_registered = #{hasRegistered}</if>
|
|
||||||
</where>
|
</where>
|
||||||
order by d.create_time desc
|
order by d.create_time desc
|
||||||
</select>
|
</select>
|
||||||
@@ -267,6 +261,11 @@
|
|||||||
where serial_number = #{serialNumber}
|
where serial_number = #{serialNumber}
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
|
<select id="selectDeviceBySpiltCode" parameterType="String" resultMap="DeviceResult">
|
||||||
|
<include refid="selectDeviceVo"/>
|
||||||
|
where device_name like concat('%', #{code}, '%')
|
||||||
|
</select>
|
||||||
|
|
||||||
<select id="selectDeviceCountBySerialNumber" parameterType="String" resultType="int">
|
<select id="selectDeviceCountBySerialNumber" parameterType="String" resultType="int">
|
||||||
select count(device_id)
|
select count(device_id)
|
||||||
from iot_device
|
from iot_device
|
||||||
@@ -308,8 +307,6 @@
|
|||||||
<if test="onlineStatus != null">online_status,</if>
|
<if test="onlineStatus != null">online_status,</if>
|
||||||
<if test="orgId != null">org_id,</if>
|
<if test="orgId != null">org_id,</if>
|
||||||
<if test="siteId != null">site_id,</if>
|
<if test="siteId != null">site_id,</if>
|
||||||
<if test="hasHost != null">has_host,</if>
|
|
||||||
<if test="hasRegistered != null">has_registered,</if>
|
|
||||||
</trim>
|
</trim>
|
||||||
<trim prefix="values (" suffix=")" suffixOverrides=",">
|
<trim prefix="values (" suffix=")" suffixOverrides=",">
|
||||||
<if test="deviceName != null and deviceName != ''">#{deviceName},</if>
|
<if test="deviceName != null and deviceName != ''">#{deviceName},</if>
|
||||||
@@ -343,8 +340,6 @@
|
|||||||
<if test="onlineStatus != null">#{onlineStatus},</if>
|
<if test="onlineStatus != null">#{onlineStatus},</if>
|
||||||
<if test="orgId != null">#{orgId},</if>
|
<if test="orgId != null">#{orgId},</if>
|
||||||
<if test="siteId != null">#{siteId},</if>
|
<if test="siteId != null">#{siteId},</if>
|
||||||
<if test="hasHost != null">#{hasHost},</if>
|
|
||||||
<if test="hasRegistered != null">#{hasRegistered},</if>
|
|
||||||
</trim>
|
</trim>
|
||||||
</insert>
|
</insert>
|
||||||
|
|
||||||
@@ -405,8 +400,6 @@
|
|||||||
<if test="onlineStatus != null">online_status = #{onlineStatus},</if>
|
<if test="onlineStatus != null">online_status = #{onlineStatus},</if>
|
||||||
<if test="orgId != null">org_id = #{orgId},</if>
|
<if test="orgId != null">org_id = #{orgId},</if>
|
||||||
<if test="siteId != null">site_id = #{siteId},</if>
|
<if test="siteId != null">site_id = #{siteId},</if>
|
||||||
<if test="hasHost != null">has_host = #{hasHost},</if>
|
|
||||||
<if test="hasRegistered != null">has_registered = #{hasRegistered},</if>
|
|
||||||
</trim>
|
</trim>
|
||||||
where device_id = #{deviceId}
|
where device_id = #{deviceId}
|
||||||
</update>
|
</update>
|
||||||
@@ -504,9 +497,4 @@
|
|||||||
#{deviceId}
|
#{deviceId}
|
||||||
</foreach>
|
</foreach>
|
||||||
</update>
|
</update>
|
||||||
|
|
||||||
<select id="selectDeviceBySpiltCode" parameterType="String" resultMap="DeviceResult">
|
|
||||||
<include refid="selectDeviceVo"/>
|
|
||||||
where device_name like concat('%', #{code}, '%')
|
|
||||||
</select>
|
|
||||||
</mapper>
|
</mapper>
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user