From 965b38158fad6a0f601b9299e1c231ee111d07d2 Mon Sep 17 00:00:00 2001 From: rqian <1206436827@qq.com> Date: Tue, 27 Oct 2026 17:08:27 +0800 Subject: [PATCH] #update --- .../system/SiteMapInfoController.java | 67 +++++++++++ .../system/SysRegionController.java | 35 ++---- .../java/com/maibu/config/DeviceTask.java | 5 + .../com/maibu/constant/FastBeeConstant.java | 73 ++++++------ .../maibu/core/business/DevicePlanTask.java | 9 +- .../com/maibu/core/business/WorkRecord.java | 9 +- .../core/business/device/NettyDevice.java | 83 +++++++------- .../core/business/dto/DeviceMapPushDTO.java | 2 + .../java/com/maibu/core/domain/BaseDO.java | 6 + .../maibu/core/domain/entity/SysRegion.java | 14 ++- .../com/maibu/core/domain/entity/SysSite.java | 25 +++-- .../com/maibu/core/domain/map/RestPoint.java | 16 +++ .../maibu/core/domain/map/SiteMapInfo.java | 31 +++++ .../core/domain/map/TempObstaclePoint.java | 16 +++ .../maibu/core/domain/rule/ActionConfig.java | 25 +++++ .../maibu/core/domain/rule/IotAutoRule.java | 64 +++++++++++ .../core/domain/rule/IotAutoRuleRecord.java | 63 +++++++++++ .../core/domain/rule/TriggerConditions.java | 28 +++++ .../java/com/maibu/core/enums/ActionType.java | 26 +++++ .../com/maibu/core/enums/DeviceScope.java | 22 ++++ .../java/com/maibu/core/enums/RouteType.java | 24 ++++ .../java/com/maibu/core/enums/RuleType.java | 18 +++ .../com/maibu/core/host/DetectionStamp.java | 10 ++ .../core/host/ObstacleDetectionData.java | 34 ++++++ .../com/maibu/core/host/ObstacleObject.java | 34 ++++++ .../com/maibu/core/host/ObstaclePostDTO.java | 13 +++ .../com/maibu/core/host/VehicleMessage.java | 2 + .../java/com/maibu/memory/SiteMemory.java | 40 ++++++- .../com/maibu/mqtt/HostMessageHandler.java | 51 +++++++++ .../main/java/com/maibu/mqtt/MqttTopic.java | 2 + .../com/maibu/utils/LongListTypeHandler.java | 40 +++++++ .../java/com/maibu/own/entity/WorkOrder.java | 8 +- .../controller/DeviceTaskController.java | 23 +++- .../main/java/com/maibu/init/InitThread.java | 80 +++++++++++-- .../com/maibu/service/DeviceTaskService.java | 102 +++++++++++++++-- .../maibu/service/DeviceThreadService.java | 106 ++++++++++++++++++ .../main/resources/workRecordTemplete.json | 8 ++ .../controller/IotAutoRuleController.java | 98 ++++++++++++++++ .../controller/WorkRecordController.java | 15 +++ .../maibu/dto/IotAutoRuleRecordQueryDTO.java | 17 +++ .../com/maibu/service/IotAutoRuleService.java | 82 ++++++++++++++ .../maibu/service/impl/WorkRecordService.java | 10 ++ .../com/maibu/mapper/IotAutoRuleMapper.java | 11 ++ .../maibu/mapper/IotAutoRuleRecordMapper.java | 12 ++ .../com/maibu/mapper/SiteMapInfoMapper.java | 14 +++ .../com/maibu/service/SiteMapInfoService.java | 44 ++++++++ .../com/maibu/service/SysRegionService.java | 17 +-- .../java/com/maibu/control/DiffSteer.java | 2 +- .../java/com/maibu/utils/ControlUtils.java | 4 +- .../com/maibu/websocket/WebsocketHandler.java | 50 +++++---- 50 files changed, 1416 insertions(+), 174 deletions(-) create mode 100644 maibu-admin/src/main/java/com/maibu/web/controller/system/SiteMapInfoController.java create mode 100644 maibu-common/src/main/java/com/maibu/core/domain/map/RestPoint.java create mode 100644 maibu-common/src/main/java/com/maibu/core/domain/map/SiteMapInfo.java create mode 100644 maibu-common/src/main/java/com/maibu/core/domain/map/TempObstaclePoint.java create mode 100644 maibu-common/src/main/java/com/maibu/core/domain/rule/ActionConfig.java create mode 100644 maibu-common/src/main/java/com/maibu/core/domain/rule/IotAutoRule.java create mode 100644 maibu-common/src/main/java/com/maibu/core/domain/rule/IotAutoRuleRecord.java create mode 100644 maibu-common/src/main/java/com/maibu/core/domain/rule/TriggerConditions.java create mode 100644 maibu-common/src/main/java/com/maibu/core/enums/ActionType.java create mode 100644 maibu-common/src/main/java/com/maibu/core/enums/DeviceScope.java create mode 100644 maibu-common/src/main/java/com/maibu/core/enums/RouteType.java create mode 100644 maibu-common/src/main/java/com/maibu/core/enums/RuleType.java create mode 100644 maibu-common/src/main/java/com/maibu/core/host/DetectionStamp.java create mode 100644 maibu-common/src/main/java/com/maibu/core/host/ObstacleDetectionData.java create mode 100644 maibu-common/src/main/java/com/maibu/core/host/ObstacleObject.java create mode 100644 maibu-common/src/main/java/com/maibu/core/host/ObstaclePostDTO.java create mode 100644 maibu-common/src/main/java/com/maibu/utils/LongListTypeHandler.java create mode 100644 maibu-netty-server/src/main/resources/workRecordTemplete.json create mode 100644 maibu-service/maibu-iot-service/src/main/java/com/maibu/controller/IotAutoRuleController.java create mode 100644 maibu-service/maibu-iot-service/src/main/java/com/maibu/dto/IotAutoRuleRecordQueryDTO.java create mode 100644 maibu-service/maibu-iot-service/src/main/java/com/maibu/service/IotAutoRuleService.java create mode 100644 maibu-service/maibu-system-service/src/main/java/com/maibu/mapper/IotAutoRuleMapper.java create mode 100644 maibu-service/maibu-system-service/src/main/java/com/maibu/mapper/IotAutoRuleRecordMapper.java create mode 100644 maibu-service/maibu-system-service/src/main/java/com/maibu/mapper/SiteMapInfoMapper.java create mode 100644 maibu-service/maibu-system-service/src/main/java/com/maibu/service/SiteMapInfoService.java diff --git a/maibu-admin/src/main/java/com/maibu/web/controller/system/SiteMapInfoController.java b/maibu-admin/src/main/java/com/maibu/web/controller/system/SiteMapInfoController.java new file mode 100644 index 0000000..4a82f88 --- /dev/null +++ b/maibu-admin/src/main/java/com/maibu/web/controller/system/SiteMapInfoController.java @@ -0,0 +1,67 @@ +package com.maibu.web.controller.system; + +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.controller.BaseController; +import com.maibu.core.domain.AjaxResult; +import com.maibu.core.domain.map.SiteMapInfo; +import com.maibu.service.SiteMapInfoService; + +/** + * 区域/场站 + * + * @author ruoyi + */ +@RestController +@RequestMapping("/system/siteMapInfo") +public class SiteMapInfoController extends BaseController { + @Autowired + private SiteMapInfoService siteMapInfoService; + + /** + * 新增或者修改组织 + */ + + @PostMapping("/save") + public AjaxResult save(@RequestBody SiteMapInfo siteMapInfo) { + try { + return AjaxResult.success(siteMapInfoService.save(siteMapInfo)); + } catch (Exception e) { + return AjaxResult.error("新增修改场站出错", e.getMessage()); + } + } + + + /** + * 查询场站详情 + */ + + @GetMapping("/selectById") + public AjaxResult selectById(@RequestParam Long id) { + try { + return AjaxResult.success(siteMapInfoService.selectById(id)); + } catch (Exception e) { + return AjaxResult.error("查询场站详情出错", e.getMessage()); + } + } + + /** + * 查询组织下所有的区域场站 + */ + + @GetMapping("/selectBySiteId") + public AjaxResult selectBySiteId(@RequestParam Long siteId) { + try { + return AjaxResult.success(siteMapInfoService.selectBySiteId(siteId)); + } catch (Exception e) { + return AjaxResult.error("查询组织下所有场站出错", e.getMessage()); + } + } + +} diff --git a/maibu-admin/src/main/java/com/maibu/web/controller/system/SysRegionController.java b/maibu-admin/src/main/java/com/maibu/web/controller/system/SysRegionController.java index 6458977..1b5dee5 100644 --- a/maibu-admin/src/main/java/com/maibu/web/controller/system/SysRegionController.java +++ b/maibu-admin/src/main/java/com/maibu/web/controller/system/SysRegionController.java @@ -1,16 +1,19 @@ package com.maibu.web.controller.system; +import java.util.List; + +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.controller.BaseController; import com.maibu.core.domain.AjaxResult; import com.maibu.core.domain.entity.SysRegion; -import com.maibu.core.domain.entity.SysSite; -import com.maibu.core.page.TableDataInfo; import com.maibu.service.SysRegionService; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.web.bind.annotation.*; - -import java.util.List; - /** * 区域/场站 @@ -23,20 +26,6 @@ public class SysRegionController extends BaseController { @Autowired private SysRegionService sysRegionService; - - /** - * 查询组织列表 - */ - @GetMapping("/list") - public TableDataInfo list(SysRegion region) { - try { - startPage(); - return getDataTable(sysRegionService.list(region)); - } catch (Exception e) { - throw new RuntimeException(e); - } - } - /** * 新增或者修改组织 */ @@ -81,9 +70,9 @@ public class SysRegionController extends BaseController { */ @GetMapping("/selectBySiteId") - public AjaxResult selectBySiteId(@RequestParam Long id) { + public AjaxResult selectBySiteId(@RequestParam Long siteId) { try { - return AjaxResult.success(sysRegionService.selectBySiteId(id)); + return AjaxResult.success(sysRegionService.selectBySiteId(siteId)); } catch (Exception e) { return AjaxResult.error("保存组织出错", e.getMessage()); } diff --git a/maibu-common/src/main/java/com/maibu/config/DeviceTask.java b/maibu-common/src/main/java/com/maibu/config/DeviceTask.java index 3e75d1c..53b0b63 100644 --- a/maibu-common/src/main/java/com/maibu/config/DeviceTask.java +++ b/maibu-common/src/main/java/com/maibu/config/DeviceTask.java @@ -102,6 +102,11 @@ public class DeviceTask { return builder(FastBeeConstant.TASK.DEVICE_HEARTBEAT_MONITOR); } + @Bean(FastBeeConstant.TASK.AUTO_RULE) + public Executor autoRule() { + return builder(FastBeeConstant.TASK.AUTO_RULE); + } + @Bean(FastBeeConstant.TASK.MAP_MESSAGE_PUSH) public Executor mapMessagePush() { return builder(FastBeeConstant.TASK.MAP_MESSAGE_PUSH); diff --git a/maibu-common/src/main/java/com/maibu/constant/FastBeeConstant.java b/maibu-common/src/main/java/com/maibu/constant/FastBeeConstant.java index 3e79804..b49b481 100644 --- a/maibu-common/src/main/java/com/maibu/constant/FastBeeConstant.java +++ b/maibu-common/src/main/java/com/maibu/constant/FastBeeConstant.java @@ -11,7 +11,6 @@ public interface FastBeeConstant { String UFT8 = "UTF-8"; String GB2312 = "GB2312"; - String MQTT = "mqtt"; String PORT = "port"; String ADAPTER = "adapter"; @@ -27,16 +26,16 @@ public interface FastBeeConstant { String WM_PREFIX = "server-"; String FAST_PHONE = "phone-"; - /*MQTT平台判定离线时间 keepAlive*1.5 */ + /* MQTT平台判定离线时间 keepAlive*1.5 */ Long DEVICE_PING_EXPIRED = 90000L; } interface CLIENT { - //加盐 + // 加盐 String TOKEN = "fastbee-smart!@#$123"; } - /*webSocket配置*/ + /* webSocket配置 */ interface WS { String HEART_BEAT = "heartbeat"; String HTTP_SERVER_CODEC = "httpServerCodec"; @@ -87,13 +86,13 @@ public interface FastBeeConstant { * 消息消费线程 */ String MESSAGE_CONSUME_TASK = "messageConsumeTask"; - /*内部消费线程publish*/ + /* 内部消费线程publish */ String MESSAGE_CONSUME_TASK_PUB = "messageConsumeTaskPub"; - /*内部消费线程Fetch*/ + /* 内部消费线程Fetch */ String MESSAGE_CONSUME_TASK_FETCH = "messageConsumeTaskFetch"; - /*OTA升级延迟队列*/ + /* OTA升级延迟队列 */ String DELAY_UPGRADE_TASK = "delayUpgradeTask"; - /*OTA升级线程池*/ + /* OTA升级线程池 */ String OTA_THREAD_POOL = "otaThreadPoolTaskExecutor"; /** @@ -111,6 +110,10 @@ public interface FastBeeConstant { */ String MAP_MESSAGE_PUSH = "mapMessagePush"; + /** + * 规则触发任务 + */ + String AUTO_RULE = "autoRule"; /** * 设备任务处理线程 @@ -128,67 +131,66 @@ public interface FastBeeConstant { String PREDIX = "/+/+"; - /*OTA消息回复*/ + /* OTA消息回复 */ String OTA_REPLY = "upgrade/reply"; } - /*集群,全局发布的消息类型*/ + /* 集群,全局发布的消息类型 */ interface CHANNEL { - /*设备状态*/ + /* 设备状态 */ String DEVICE_STATUS = "device_status"; - /*平台读取属性*/ + /* 平台读取属性 */ String PROP_READ = "prop_read"; - /*推送消息*/ + /* 推送消息 */ String PUBLISH = "publish"; - /*服务下发*/ + /* 服务下发 */ String FUNCTION_INVOKE = "function_invoke"; - /*事件*/ + /* 事件 */ String EVENT = "event"; - /*other*/ + /* other */ String OTHER = "other"; - /*Qos1 推送应答*/ + /* Qos1 推送应答 */ String PUBLISH_ACK = "publish_ack"; - /*Qos2 发布消息收到*/ + /* Qos2 发布消息收到 */ String PUB_REC = "pub_rec"; - /*Qos 发布消息释放*/ + /* Qos 发布消息释放 */ String PUB_REL = "pub_rel"; - /*Qos2 发布消息完成*/ + /* Qos2 发布消息完成 */ String PUB_COMP = "pub_comp"; String UPGRADE = "upgrade"; /*-------------------------ROCKETMQ-------------------------*/ String SUFFIX = "group"; - /*设备状态*/ + /* 设备状态 */ String DEVICE_STATUS_GROUP = DEVICE_STATUS + SUFFIX; String PROP_READ_GROUP = PROP_READ + SUFFIX; - /*服务下发*/ + /* 服务下发 */ String FUNCTION_INVOKE_GROUP = FUNCTION_INVOKE + SUFFIX; - /*推送消息*/ + /* 推送消息 */ String PUBLISH_GROUP = PUBLISH + SUFFIX; - /*Qos1 推送应答*/ + /* Qos1 推送应答 */ String PUBLISH_ACK_GROUP = PUBLISH_ACK + SUFFIX; - /*Qos2 发布消息收到*/ + /* Qos2 发布消息收到 */ String PUB_REC_GROUP = PUB_REC + SUFFIX; - /*Qos 发布消息释放*/ + /* Qos 发布消息释放 */ String PUB_REL_GROUP = PUB_REL + SUFFIX; - /*Qos2 发布消息完成*/ + /* Qos2 发布消息完成 */ String PUB_COMP_GROUP = PUB_COMP + SUFFIX; - /*OTA升级*/ + /* OTA升级 */ String UPGRADE_GROUP = UPGRADE + SUFFIX; } - /** * redisKey 定义 */ interface REDIS { - /*在线设备列表*/ + /* 在线设备列表 */ String DEVICE_ONLINE_LIST = "device:online:list"; - /*设备实时状态key*/ + /* 设备实时状态key */ String DEVICE_RUNTIME_DATA = "device:runtime:"; - /*通讯协议参数*/ + /* 通讯协议参数 */ String DEVICE_PROTOCOL_PARAM = "device:param:"; /** * 设备消息id缓存key @@ -227,11 +229,11 @@ public interface FastBeeConstant { */ String MESSAGE_RETAIN_TOTAL = "message:retain:total"; - /*发送消息数*/ + /* 发送消息数 */ String MESSAGE_SEND_TOTAL = "message:send:total"; - /*接收消息数*/ + /* 接收消息数 */ String MESSAGE_RECEIVE_TOTAL = "message:receive:total"; - /*连接次数*/ + /* 连接次数 */ String MESSAGE_CONNECT_TOTAL = "message:connect:total"; /** * 认证次数 @@ -316,7 +318,6 @@ public interface FastBeeConstant { String CH = "CH"; String ModbusTcp = "MODBUS-TCP"; - } interface URL { diff --git a/maibu-common/src/main/java/com/maibu/core/business/DevicePlanTask.java b/maibu-common/src/main/java/com/maibu/core/business/DevicePlanTask.java index e52d795..8dfe277 100644 --- a/maibu-common/src/main/java/com/maibu/core/business/DevicePlanTask.java +++ b/maibu-common/src/main/java/com/maibu/core/business/DevicePlanTask.java @@ -7,7 +7,9 @@ import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; import com.maibu.core.domain.OrgBaseDO; +import com.maibu.core.domain.map.RestPoint; import com.maibu.core.enums.DeviceTaskStaus; +import com.maibu.core.enums.RouteType; import lombok.Data; import lombok.EqualsAndHashCode; @@ -40,6 +42,11 @@ public class DevicePlanTask extends OrgBaseDO { private LocalDateTime canExecuteTime; // 这个时间之前都不能执行 @TableField(exist = false) - private volatile boolean taskAccepted = false; //任务被上位机接收 + private volatile boolean taskAccepted = false; // 任务被上位机接收 + + private RouteType routeType; + + @TableField(exist = false) + private RestPoint backTaskPoint; } diff --git a/maibu-common/src/main/java/com/maibu/core/business/WorkRecord.java b/maibu-common/src/main/java/com/maibu/core/business/WorkRecord.java index 687ce92..0ec967b 100644 --- a/maibu-common/src/main/java/com/maibu/core/business/WorkRecord.java +++ b/maibu-common/src/main/java/com/maibu/core/business/WorkRecord.java @@ -6,6 +6,7 @@ import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler; import com.maibu.core.domain.OrgBaseDO; +import com.maibu.core.enums.RouteType; import lombok.Data; import lombok.EqualsAndHashCode; @@ -20,12 +21,14 @@ public class WorkRecord extends OrgBaseDO { private String workName; private Long userId; - private String mode;//导航任务模式 single_point|coverage + private String mode;// 导航任务模式 single_point|coverage -// private String jsonData; + // private String jsonData; + + private RouteType routeType; @TableField(typeHandler = JacksonTypeHandler.class) - private PlanPath jsonData; //计划 + private PlanPath jsonData; // 计划 private String imgUrl; } diff --git a/maibu-common/src/main/java/com/maibu/core/business/device/NettyDevice.java b/maibu-common/src/main/java/com/maibu/core/business/device/NettyDevice.java index 11f808e..ce82bc5 100644 --- a/maibu-common/src/main/java/com/maibu/core/business/device/NettyDevice.java +++ b/maibu-common/src/main/java/com/maibu/core/business/device/NettyDevice.java @@ -7,6 +7,7 @@ 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.enums.RouteType; import com.maibu.core.host.HostWorkRecordCreateDTO; import com.maibu.core.host.MutiPointEntity; import com.maibu.core.host.PointEntity; @@ -247,22 +248,22 @@ public class NettyDevice extends Connector { } // public void readConfigCommand() { - // byte[] bytes = DeviceRunParam.toReadBytes(); - // log.debug("下发读取配置的报文:{}", toHexString(bytes)); - // if (this.getChannel() != null && this.getChannel().isActive()) { - // this.getChannel().writeAndFlush(Unpooled.wrappedBuffer(bytes)); - // } - // log.debug("下发读取配置的报文完成:{}", toHexString(bytes)); + // byte[] bytes = DeviceRunParam.toReadBytes(); + // log.debug("下发读取配置的报文:{}", toHexString(bytes)); + // if (this.getChannel() != null && this.getChannel().isActive()) { + // this.getChannel().writeAndFlush(Unpooled.wrappedBuffer(bytes)); + // } + // log.debug("下发读取配置的报文完成:{}", toHexString(bytes)); // } // public void writeConfigCommand(DeviceRunParam deviceRunParam) { - // log.debug("下发修改配置的属性:{}", JsonUtils.toJsonString(deviceRunParam)); - // byte[] bytes = deviceRunParam.toWriteBytes(); - // log.debug("下发修改配置的报文:{}", toHexString(bytes)); - // if (this.getChannel() != null && this.getChannel().isActive()) { - // this.getChannel().writeAndFlush(Unpooled.wrappedBuffer(bytes)); - // } - // log.debug("下发修改配置的报文完成:{}", toHexString(bytes)); + // log.debug("下发修改配置的属性:{}", JsonUtils.toJsonString(deviceRunParam)); + // byte[] bytes = deviceRunParam.toWriteBytes(); + // log.debug("下发修改配置的报文:{}", toHexString(bytes)); + // if (this.getChannel() != null && this.getChannel().isActive()) { + // this.getChannel().writeAndFlush(Unpooled.wrappedBuffer(bytes)); + // } + // log.debug("下发修改配置的报文完成:{}", toHexString(bytes)); // } // todo 优化 @@ -365,32 +366,38 @@ public class NettyDevice extends Connector { dto.setProtocol_version(Constant.protocol_version); 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 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 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); + //TODO 增加其他系统任务类型 写死的code + if (RouteType.BACK_TO_REST_POINT.equals(task.getRouteType())) { + point.setLongitude(task.getBackTaskPoint().getPosition().getLng()); + point.setLatitude(task.getBackTaskPoint().getPosition().getLat()); + } else { + 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 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 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); } - point.setBoundary_points(boundary_points); } } dto.setData(point); diff --git a/maibu-common/src/main/java/com/maibu/core/business/dto/DeviceMapPushDTO.java b/maibu-common/src/main/java/com/maibu/core/business/dto/DeviceMapPushDTO.java index 9ac2477..f1d8bcf 100644 --- a/maibu-common/src/main/java/com/maibu/core/business/dto/DeviceMapPushDTO.java +++ b/maibu-common/src/main/java/com/maibu/core/business/dto/DeviceMapPushDTO.java @@ -17,4 +17,6 @@ public class DeviceMapPushDTO { private String cm;// 控制模式 manual_remote|auto + private String ms; // 运动状态 moving|stopped|blocked + } diff --git a/maibu-common/src/main/java/com/maibu/core/domain/BaseDO.java b/maibu-common/src/main/java/com/maibu/core/domain/BaseDO.java index 7af55c9..92fa253 100644 --- a/maibu-common/src/main/java/com/maibu/core/domain/BaseDO.java +++ b/maibu-common/src/main/java/com/maibu/core/domain/BaseDO.java @@ -1,5 +1,6 @@ package com.maibu.core.domain; +import com.baomidou.mybatisplus.annotation.FieldFill; import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableLogic; import com.fasterxml.jackson.annotation.JsonFormat; @@ -14,6 +15,7 @@ import java.util.Map; /** * 基类,时间类型改为LocalDateTime + * * @author fastb * @date 2023-08-22 9:11 */ @@ -23,20 +25,24 @@ public class BaseDO implements Serializable { /** 创建者 */ @ApiModelProperty("创建者") + @TableField(fill = FieldFill.INSERT) private String createBy; /** 创建时间 */ @ApiModelProperty("创建时间") + @TableField(fill = FieldFill.INSERT) @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") private LocalDateTime createTime; /** 更新者 */ @ApiModelProperty("更新者") + @TableField(fill = FieldFill.INSERT_UPDATE) private String updateBy; /** 更新时间 */ @ApiModelProperty("更新时间") @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @TableField(fill = FieldFill.INSERT_UPDATE) private LocalDateTime updateTime; /** 逻辑删除 */ diff --git a/maibu-common/src/main/java/com/maibu/core/domain/entity/SysRegion.java b/maibu-common/src/main/java/com/maibu/core/domain/entity/SysRegion.java index 5239a94..8e65bbd 100644 --- a/maibu-common/src/main/java/com/maibu/core/domain/entity/SysRegion.java +++ b/maibu-common/src/main/java/com/maibu/core/domain/entity/SysRegion.java @@ -3,16 +3,20 @@ package com.maibu.core.domain.entity; import java.util.List; import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; +import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler; +import com.maibu.core.business.path.LatAndLngEntity; import com.maibu.core.domain.BaseDO; +import com.maibu.utils.LongListTypeHandler; import lombok.Data; import lombok.EqualsAndHashCode; @EqualsAndHashCode(callSuper = true) @Data -@TableName(value = "sys_region") +@TableName(value = "sys_region", autoResultMap = true) public class SysRegion extends BaseDO { @TableId(type = IdType.AUTO) @@ -28,8 +32,14 @@ public class SysRegion extends BaseDO { private String remark; + @TableField(typeHandler = JacksonTypeHandler.class) + private List scope; // 区域范围 + private Integer status; - private Long bindRoute;// 绑定的线路id + private Long defaultRoute;// 绑定的线路id + + @TableField(typeHandler = LongListTypeHandler.class) + private List bindRoutes;// 绑定的线路id } diff --git a/maibu-common/src/main/java/com/maibu/core/domain/entity/SysSite.java b/maibu-common/src/main/java/com/maibu/core/domain/entity/SysSite.java index f01b977..799c329 100644 --- a/maibu-common/src/main/java/com/maibu/core/domain/entity/SysSite.java +++ b/maibu-common/src/main/java/com/maibu/core/domain/entity/SysSite.java @@ -1,17 +1,20 @@ package com.maibu.core.domain.entity; -import com.baomidou.mybatisplus.annotation.IdType; -import com.baomidou.mybatisplus.annotation.TableId; -import com.baomidou.mybatisplus.annotation.TableName; -import com.maibu.core.domain.BaseDO; -import lombok.Data; -import lombok.EqualsAndHashCode; - import java.math.BigDecimal; +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.maibu.core.domain.BaseDO; +import com.maibu.core.domain.map.SiteMapInfo; + +import lombok.Data; +import lombok.EqualsAndHashCode; + @EqualsAndHashCode(callSuper = true) @Data -@TableName(value = "sys_site") +@TableName(value = "sys_site", autoResultMap = true) public class SysSite extends BaseDO { @TableId(type = IdType.AUTO) @@ -45,4 +48,10 @@ public class SysSite extends BaseDO { private String siteMapName; // geoserver 地图名称 + /** + * 场站相关的地图信息 比如停车点,充电点,临时不可走点 等等 待拓展 + */ + @TableField(exist = false) + private SiteMapInfo siteMapInfo; + } diff --git a/maibu-common/src/main/java/com/maibu/core/domain/map/RestPoint.java b/maibu-common/src/main/java/com/maibu/core/domain/map/RestPoint.java new file mode 100644 index 0000000..880ace0 --- /dev/null +++ b/maibu-common/src/main/java/com/maibu/core/domain/map/RestPoint.java @@ -0,0 +1,16 @@ +package com.maibu.core.domain.map; + +import com.maibu.core.business.path.LatAndLngEntity; + +import lombok.Data; + +@Data +public class RestPoint { + + private LatAndLngEntity position; + + private String bindDeviceId; + + private String alias; + +} diff --git a/maibu-common/src/main/java/com/maibu/core/domain/map/SiteMapInfo.java b/maibu-common/src/main/java/com/maibu/core/domain/map/SiteMapInfo.java new file mode 100644 index 0000000..c7526a2 --- /dev/null +++ b/maibu-common/src/main/java/com/maibu/core/domain/map/SiteMapInfo.java @@ -0,0 +1,31 @@ +package com.maibu.core.domain.map; + +import java.util.List; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler; +import com.maibu.core.domain.OrgNoUserDO; + +import lombok.Data; +import lombok.EqualsAndHashCode; + +@EqualsAndHashCode(callSuper = true) +@Data +@TableName(value = "sys_site_map_info", autoResultMap = true) +public class SiteMapInfo extends OrgNoUserDO { + + @TableId(type = IdType.AUTO) + private Long id; + + @TableField(typeHandler = JacksonTypeHandler.class) + private List restPoints; // 休息点 + + @TableField(typeHandler = JacksonTypeHandler.class) + private List tempObstaclePoints; // 临时不可走点 + + // todo 拓展 安全区 充电区? + +} diff --git a/maibu-common/src/main/java/com/maibu/core/domain/map/TempObstaclePoint.java b/maibu-common/src/main/java/com/maibu/core/domain/map/TempObstaclePoint.java new file mode 100644 index 0000000..58681d9 --- /dev/null +++ b/maibu-common/src/main/java/com/maibu/core/domain/map/TempObstaclePoint.java @@ -0,0 +1,16 @@ +package com.maibu.core.domain.map; + +import com.maibu.core.business.path.LatAndLngEntity; + +import lombok.Data; + +@Data +public class TempObstaclePoint { + + private LatAndLngEntity position; + + private Double radius; + + private String alias; + +} diff --git a/maibu-common/src/main/java/com/maibu/core/domain/rule/ActionConfig.java b/maibu-common/src/main/java/com/maibu/core/domain/rule/ActionConfig.java new file mode 100644 index 0000000..8b7528f --- /dev/null +++ b/maibu-common/src/main/java/com/maibu/core/domain/rule/ActionConfig.java @@ -0,0 +1,25 @@ +package com.maibu.core.domain.rule; + +import java.util.Map; + +import com.maibu.core.enums.ActionType; + +import lombok.Data; + +@Data + +public class ActionConfig { + + /** + * 触发任务类型 + */ + private ActionType actionType; + + /** + * 参数值 + */ + private Map args; + + private Long routeId; + +} diff --git a/maibu-common/src/main/java/com/maibu/core/domain/rule/IotAutoRule.java b/maibu-common/src/main/java/com/maibu/core/domain/rule/IotAutoRule.java new file mode 100644 index 0000000..a55617d --- /dev/null +++ b/maibu-common/src/main/java/com/maibu/core/domain/rule/IotAutoRule.java @@ -0,0 +1,64 @@ +package com.maibu.core.domain.rule; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler; +import com.maibu.core.domain.OrgNoUserDO; +import com.maibu.core.enums.DeviceScope; +import com.maibu.core.enums.RuleType; + +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * 自动化规则配置 + */ +@EqualsAndHashCode(callSuper = true) +@Data +@TableName(value = "iot_auto_rule", autoResultMap = true) +public class IotAutoRule extends OrgNoUserDO { + + /** + * 主键 + */ + @TableId(type = IdType.AUTO) + private Long id; + + /** + * 规则名称 + */ + private String ruleName; + + /** + * 规则类型,如 LOW_BATTERY_RETURN + */ + private RuleType ruleType; + + /** + * 适用设备、分组、全部 + */ + private DeviceScope deviceScope; + + /** + * 触发条件 + */ + @TableField(typeHandler = JacksonTypeHandler.class) + private TriggerConditions conditions; + + /** + * 执行动作及参数 + */ + @TableField(typeHandler = JacksonTypeHandler.class) + private ActionConfig actionConfig; + + /** + * 是否启用:0-禁用,1-启用 + */ + private Boolean enabled = false; + + // 是否强制执行 比如车子当前有任务 + private Boolean ForceExecute = false; + +} diff --git a/maibu-common/src/main/java/com/maibu/core/domain/rule/IotAutoRuleRecord.java b/maibu-common/src/main/java/com/maibu/core/domain/rule/IotAutoRuleRecord.java new file mode 100644 index 0000000..feff304 --- /dev/null +++ b/maibu-common/src/main/java/com/maibu/core/domain/rule/IotAutoRuleRecord.java @@ -0,0 +1,63 @@ +package com.maibu.core.domain.rule; + +import java.time.LocalDateTime; +import java.util.Date; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler; +import com.maibu.core.domain.OrgNoUserDO; +import com.maibu.core.enums.RuleType; + +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * 自动化规则触发记录 + */ +@EqualsAndHashCode(callSuper = true) +@Data +@TableName(value = "iot_auto_rule_record", autoResultMap = true) +public class IotAutoRuleRecord extends OrgNoUserDO { + + /** + * 主键 + */ + @TableId(type = IdType.AUTO) + private Long id; + + /** + * 规则 ID + */ + private Long ruleId; + + private RuleType ruleType; + + /** + * 触发设备 ID + */ + private String deviceId; + + /** + * 触发时的指标快照 + */ + @TableField(typeHandler = JacksonTypeHandler.class) + private Object triggerValue; + + /** + * 触发时间 + */ + private LocalDateTime triggerTime; + + /** + * 关联的返航任务 ID + */ + private String taskId; + + /** + * 执行失败原因 + */ + private String errorMessage; +} \ No newline at end of file diff --git a/maibu-common/src/main/java/com/maibu/core/domain/rule/TriggerConditions.java b/maibu-common/src/main/java/com/maibu/core/domain/rule/TriggerConditions.java new file mode 100644 index 0000000..db93d33 --- /dev/null +++ b/maibu-common/src/main/java/com/maibu/core/domain/rule/TriggerConditions.java @@ -0,0 +1,28 @@ +package com.maibu.core.domain.rule; + +import java.math.BigDecimal; + +import com.maibu.core.enums.CompareEnum; + +import lombok.Data; + +@Data + +public class TriggerConditions { + + /** + * 触发条件判断的字段key 电量 battery /temperature/offline_duration/voltage + */ + private String key; + + /** + * 比较运算符:GT、GTE、LT、LTE、EQ、NE + */ + private CompareEnum operator; + + /** + * 比较阈值 + */ + private String value; + +} diff --git a/maibu-common/src/main/java/com/maibu/core/enums/ActionType.java b/maibu-common/src/main/java/com/maibu/core/enums/ActionType.java new file mode 100644 index 0000000..7432820 --- /dev/null +++ b/maibu-common/src/main/java/com/maibu/core/enums/ActionType.java @@ -0,0 +1,26 @@ +package com.maibu.core.enums; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +@Getter +@AllArgsConstructor +public enum ActionType { + + AUTO_TASK("AUTO_TASK", "路径规划任务"), + + BACK_TO_REST("BACK_TO_REST", "回休息区"), + + SEND_COMMAND("SEND_COMMAND", "下发指令"), + + ALARM("ALARM", "告警"), + + WORK_ORDER("WORK_ORDER", "工单下发"); + + /** 订单类型值(存储在数据库中) */ + private final String value; + + /** 订单类型名称(用于前端显示) */ + private final String name; + +} diff --git a/maibu-common/src/main/java/com/maibu/core/enums/DeviceScope.java b/maibu-common/src/main/java/com/maibu/core/enums/DeviceScope.java new file mode 100644 index 0000000..a52f821 --- /dev/null +++ b/maibu-common/src/main/java/com/maibu/core/enums/DeviceScope.java @@ -0,0 +1,22 @@ +package com.maibu.core.enums; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +@Getter +@AllArgsConstructor +public enum DeviceScope { + + ALL("ALL", "所有设备"), + + GROUP("GROUP", "设备组"), + + SOME("SOME", "特定的"); + + /** 订单类型值(存储在数据库中) */ + private final String value; + + /** 订单类型名称(用于前端显示) */ + private final String name; + +} diff --git a/maibu-common/src/main/java/com/maibu/core/enums/RouteType.java b/maibu-common/src/main/java/com/maibu/core/enums/RouteType.java new file mode 100644 index 0000000..072e102 --- /dev/null +++ b/maibu-common/src/main/java/com/maibu/core/enums/RouteType.java @@ -0,0 +1,24 @@ +package com.maibu.core.enums; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +@Getter +@AllArgsConstructor +public enum RouteType { + + MOWING_TASK("MOWING_TASK", "割草任务"), + + INSPECTION_TASK("INSPECTION_TASK", "巡检任务"), + + BACK_TO_REST_POINT("BACK_TO_REST_POINT", "返航任务"), + + OTHER("OTHER", "其他类型"); + + /** 订单类型值(存储在数据库中) */ + private final String value; + + /** 订单类型名称(用于前端显示) */ + private final String name; + +} diff --git a/maibu-common/src/main/java/com/maibu/core/enums/RuleType.java b/maibu-common/src/main/java/com/maibu/core/enums/RuleType.java new file mode 100644 index 0000000..23b26af --- /dev/null +++ b/maibu-common/src/main/java/com/maibu/core/enums/RuleType.java @@ -0,0 +1,18 @@ +package com.maibu.core.enums; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +@Getter +@AllArgsConstructor +public enum RuleType { + + LOW_BATTERY_RETURN("LOW_BATTERY_RETURN", "低电量返航"); + + /** 错误来源值(存储在数据库中) */ + private final String value; + + /** 错误来源名称(用于前端显示) */ + private final String name; + +} diff --git a/maibu-common/src/main/java/com/maibu/core/host/DetectionStamp.java b/maibu-common/src/main/java/com/maibu/core/host/DetectionStamp.java new file mode 100644 index 0000000..222bc0e --- /dev/null +++ b/maibu-common/src/main/java/com/maibu/core/host/DetectionStamp.java @@ -0,0 +1,10 @@ +package com.maibu.core.host; + +import lombok.Data; + +@Data +public class DetectionStamp { + + private Long sec; + private Long nanosec; +} diff --git a/maibu-common/src/main/java/com/maibu/core/host/ObstacleDetectionData.java b/maibu-common/src/main/java/com/maibu/core/host/ObstacleDetectionData.java new file mode 100644 index 0000000..b5cd917 --- /dev/null +++ b/maibu-common/src/main/java/com/maibu/core/host/ObstacleDetectionData.java @@ -0,0 +1,34 @@ +package com.maibu.core.host; + +import java.util.List; + +import com.maibu.core.enums.MesType; + +import lombok.Data; + +@Data +public class ObstacleDetectionData { + + + private MesType mesType; + + /** + * 融合状态 + */ + private String fusion_status; + + /** + * 障碍物检测状态 + */ + private String obstacle_status; + + /** + * 检测目标数量 + */ + private Integer object_count; + + /** + * 检测目标列表 + */ + private List objects; +} diff --git a/maibu-common/src/main/java/com/maibu/core/host/ObstacleObject.java b/maibu-common/src/main/java/com/maibu/core/host/ObstacleObject.java new file mode 100644 index 0000000..6e24070 --- /dev/null +++ b/maibu-common/src/main/java/com/maibu/core/host/ObstacleObject.java @@ -0,0 +1,34 @@ +package com.maibu.core.host; + +import lombok.Data; + +@Data +public class ObstacleObject { + + private Integer class_id; + private String class_name; + private Double confidence; + + private Integer x1; + private Integer y1; + private Integer x2; + private Integer y2; + + private Double x; + private Double y; + private Double z; + + private Double distance; + private Double angle; + + private Double latitude; + private Double longitude; + + private Integer track_id; + + private Double size_x; + private Double size_y; + private Double size_z; + + private DetectionStamp det_stamp; +} diff --git a/maibu-common/src/main/java/com/maibu/core/host/ObstaclePostDTO.java b/maibu-common/src/main/java/com/maibu/core/host/ObstaclePostDTO.java new file mode 100644 index 0000000..c183394 --- /dev/null +++ b/maibu-common/src/main/java/com/maibu/core/host/ObstaclePostDTO.java @@ -0,0 +1,13 @@ +package com.maibu.core.host; + + +import lombok.Data; +import lombok.EqualsAndHashCode; + +@EqualsAndHashCode(callSuper = true) +@Data +public class ObstaclePostDTO extends HostBase { + + private ObstacleDetectionData fusion_obstacle; + +} diff --git a/maibu-common/src/main/java/com/maibu/core/host/VehicleMessage.java b/maibu-common/src/main/java/com/maibu/core/host/VehicleMessage.java index eaa00e7..0288169 100644 --- a/maibu-common/src/main/java/com/maibu/core/host/VehicleMessage.java +++ b/maibu-common/src/main/java/com/maibu/core/host/VehicleMessage.java @@ -5,6 +5,8 @@ import lombok.Data; @Data public class VehicleMessage { + private String deviceId; + private double battery_percentage;// 实时电量百分比 private double battery_voltage;// 实时电压 diff --git a/maibu-common/src/main/java/com/maibu/memory/SiteMemory.java b/maibu-common/src/main/java/com/maibu/memory/SiteMemory.java index 2516624..6dd2d45 100644 --- a/maibu-common/src/main/java/com/maibu/memory/SiteMemory.java +++ b/maibu-common/src/main/java/com/maibu/memory/SiteMemory.java @@ -6,16 +6,27 @@ import java.util.Map; import java.util.Objects; import java.util.concurrent.ConcurrentHashMap; -import com.maibu.core.business.*; -import com.maibu.core.business.dto.DeviceMapPushDTO; -import com.maibu.mqtt.CustomMqttDeviceMonitor; import org.apache.commons.lang3.StringUtils; import org.eclipse.paho.client.mqttv3.MqttClient; import org.springframework.stereotype.Component; import org.springframework.util.CollectionUtils; +import com.maibu.core.business.AlarmOrderConfig; +import com.maibu.core.business.Device; +import com.maibu.core.business.DeviceModel; +import com.maibu.core.business.DevicePlan; +import com.maibu.core.business.DevicePlanTask; +import com.maibu.core.business.DeviceRunParam; +import com.maibu.core.business.DeviceRunStatistics; +import com.maibu.core.business.ErrorIdentificationStandard; +import com.maibu.core.business.IoTCommonDevice; +import com.maibu.core.business.OrderModel; +import com.maibu.core.business.Product; +import com.maibu.core.business.dto.DeviceMapPushDTO; import com.maibu.core.domain.entity.SysSite; +import com.maibu.core.domain.rule.IotAutoRule; import com.maibu.core.enums.ErrorSource; +import com.maibu.core.enums.RuleType; import com.maibu.core.host.VehicleMessage; import lombok.Data; @@ -62,11 +73,34 @@ public class SiteMemory { public static ConcurrentHashMap vehicleMessageMap = new ConcurrentHashMap<>(); + public static ConcurrentHashMap iotAutoRuleMap = new ConcurrentHashMap<>(); + + public List getAllIotAutoRule() { + return new ArrayList<>(iotAutoRuleMap.values()); + } + + public IotAutoRule getIotAutoRule(RuleType ruleType) { + return iotAutoRuleMap.get(ruleType); + } + + public void saveIotAutoRule(RuleType ruleType, IotAutoRule iotAutoRule) { + iotAutoRuleMap.put(ruleType, iotAutoRule); + } + + public void removeIotAutoRule(RuleType ruleType) { + iotAutoRuleMap.remove(ruleType); + } + + public List getAllVehicleMessage() { + return new ArrayList<>(vehicleMessageMap.values()); + } + public VehicleMessage getVehicleMessage(String deviceId) { return vehicleMessageMap.get(deviceId); } public void saveVehicleMessage(String deviceId, VehicleMessage vehicleMessage) { + vehicleMessage.setDeviceId(deviceId); vehicleMessageMap.put(deviceId, vehicleMessage); } diff --git a/maibu-common/src/main/java/com/maibu/mqtt/HostMessageHandler.java b/maibu-common/src/main/java/com/maibu/mqtt/HostMessageHandler.java index 833ea31..404aa73 100644 --- a/maibu-common/src/main/java/com/maibu/mqtt/HostMessageHandler.java +++ b/maibu-common/src/main/java/com/maibu/mqtt/HostMessageHandler.java @@ -8,6 +8,7 @@ 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.WebMapMessageDTO; import com.maibu.core.business.dto.WebStatusMessageDTO; import com.maibu.core.business.inter.WebsocketMesDispather; import com.maibu.core.enums.DeviceTaskStaus; @@ -107,6 +108,10 @@ public class HostMessageHandler implements CustomMqttMessageHandler { case "upgrade_reply": handleUpgradeReply(deviceId, topic, payload); break; + case "obstacle_post": + handleObstaclePost(deviceId, topic, payload); + break; + default: log.debug("割草机消息: deviceId={}, topic={}, action={}", deviceId, topic, action); break; @@ -247,6 +252,7 @@ public class HostMessageHandler implements CustomMqttMessageHandler { VehicleMessage vehicleMessage = siteMemory.getVehicleMessage(deviceId); if (vehicleMessage != null) { dto.setCm(vehicleMessage.getControl_mode()); + dto.setMs(vehicleMessage.getMotion()); dto.setB(vehicleMessage.getBattery_percentage()); } siteMemory.saveMapPushDTO(deviceId, dto); @@ -634,6 +640,49 @@ public class HostMessageHandler implements CustomMqttMessageHandler { // } } + /** + * 处理控障碍物提示 + */ + private void handleObstaclePost(String deviceId, String topic, String payload) { + + log.debug("【障碍物提示】deviceId={}, payload={}", deviceId, payload); + + ObstacleDetectionData data = JsonUtils.parseObject(payload, ObstacleDetectionData.class); + + List controlMasters = deviceSessionManager + .getAllSlaveControl(deviceId); + data.setMesType(MesType.detectionReport); + if (!CollectionUtils.isEmpty(controlMasters)) { + + for (NettyDevice x : controlMasters) { + try { + websocketMesDispather.dispather(x.getConnectorId(), JsonUtils.toJsonString(data)); + } catch (Exception e) { + log.error("实时数据websocket推送失败: connectorId={}, error={}", x.getConnectorId(), + e.getMessage(), e); + } + } + } + try { + NettyDevice device = deviceSessionManager.getDevice(deviceId); + if (device != null && device.getDevice() != null) { + Long siteId = device.getDevice().getSiteId(); + websocketMesDispather.mapMessageDispather(siteId, + JsonUtils.toJsonString(data)); + } + } catch (Exception e) { + log.error("实时地图数据websocket推送失败: siteId={}, error={}", e); + } + try { + GlobalMemory.customMqttDeviceMonitor.publish(mqttClientId, + String.format(MqttTopic.DEVICE_OBSTACLE_PUSH_TOPIC, deviceId), + JsonUtils.toJsonString(data)); + } catch (MqttException e) { + log.error("实时数据websocket推送失败: deviceId={}, error={}", deviceId, e.getMessage(), e); + } + + } + /** * 从 Topic 中解析 deviceId * Topic 格式:mower/{deviceId}/... @@ -686,6 +735,8 @@ public class HostMessageHandler implements CustomMqttMessageHandler { return "route_reply"; if (remaining.equals("/ota/result/post")) return "upgrade_reply"; + if (remaining.equals("/perception/obstacle/post")) + return "obstacle_post"; return null; } diff --git a/maibu-common/src/main/java/com/maibu/mqtt/MqttTopic.java b/maibu-common/src/main/java/com/maibu/mqtt/MqttTopic.java index 4d2943f..8424a57 100644 --- a/maibu-common/src/main/java/com/maibu/mqtt/MqttTopic.java +++ b/maibu-common/src/main/java/com/maibu/mqtt/MqttTopic.java @@ -17,6 +17,8 @@ public class MqttTopic { public static final String DEVICE_ROUTE_PUSH_TOPIC = "device/%s/route/post"; public static final String DEVICE_STATUS_PUSH_TOPIC = "device/%s/status/change"; + // 障碍物信息 + public static final String DEVICE_OBSTACLE_PUSH_TOPIC = "device/%s/obstacle/post"; /** 产品标识:割草机 */ public static final String MOWER_PRODUCT = "mower"; diff --git a/maibu-common/src/main/java/com/maibu/utils/LongListTypeHandler.java b/maibu-common/src/main/java/com/maibu/utils/LongListTypeHandler.java new file mode 100644 index 0000000..ef3378e --- /dev/null +++ b/maibu-common/src/main/java/com/maibu/utils/LongListTypeHandler.java @@ -0,0 +1,40 @@ +package com.maibu.utils; + +import com.baomidou.mybatisplus.extension.handlers.AbstractJsonTypeHandler; +import com.fasterxml.jackson.databind.JavaType; +import com.fasterxml.jackson.databind.ObjectMapper; + +import java.io.IOException; +import java.util.List; + +public class LongListTypeHandler extends AbstractJsonTypeHandler> { + + private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper(); + + private static final JavaType LIST_TYPE = + OBJECT_MAPPER.getTypeFactory() + .constructCollectionType(List.class, Long.class); + + public LongListTypeHandler(Class type) { + // 兼容 MyBatis-Plus 通过反射传入字段类型的方式 + } + + @Override + protected List parse(String json) { + try { + return OBJECT_MAPPER.readValue(json, LIST_TYPE); + } catch (IOException e) { + throw new RuntimeException("bindRoutes JSON 解析失败", e); + } + } + + @Override + protected String toJson(List obj) { + try { + return OBJECT_MAPPER.writeValueAsString(obj); + } catch (IOException e) { + throw new RuntimeException("bindRoutes JSON 序列化失败", e); + } + } +} + diff --git a/maibu-external/src/main/java/com/maibu/own/entity/WorkOrder.java b/maibu-external/src/main/java/com/maibu/own/entity/WorkOrder.java index 20c12fc..d2b7ece 100644 --- a/maibu-external/src/main/java/com/maibu/own/entity/WorkOrder.java +++ b/maibu-external/src/main/java/com/maibu/own/entity/WorkOrder.java @@ -1,14 +1,14 @@ package com.maibu.own.entity; +import java.io.Serializable; +import java.time.LocalDateTime; + import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; + import lombok.Data; import lombok.NoArgsConstructor; -import org.springframework.data.annotation.Id; - -import java.io.Serializable; -import java.time.LocalDateTime; @Data @NoArgsConstructor diff --git a/maibu-netty-server/src/main/java/com/maibu/controller/DeviceTaskController.java b/maibu-netty-server/src/main/java/com/maibu/controller/DeviceTaskController.java index a1b2490..43dab3a 100644 --- a/maibu-netty-server/src/main/java/com/maibu/controller/DeviceTaskController.java +++ b/maibu-netty-server/src/main/java/com/maibu/controller/DeviceTaskController.java @@ -124,7 +124,7 @@ public class DeviceTaskController extends BaseController { return AjaxResult.success(deviceTaskService.createDeviceTask(dto, getLoginUser().getUsername())); } - @PostMapping("/createRegionDeviceTask") + @PostMapping("/createRegionDefaultTask") public AjaxResult createRegionDeviceTask(@RequestBody DeviceTaskCommandDTO dto) { String deviceId = dto.getDeviceId(); Long siteId = dto.getSiteId(); @@ -176,4 +176,25 @@ public class DeviceTaskController extends BaseController { return AjaxResult.success(deviceTaskService.recoveryTask(dto, getUsername())); } + @PostMapping("/backToRestPoint") + public AjaxResult backToRestPoint(@RequestBody DeviceTaskCommandDTO dto) { + String deviceId = dto.getDeviceId(); + Long siteId = dto.getSiteId(); + Long orgId = dto.getOrgId(); + if (StringUtils.isEmpty(deviceId)) { + return AjaxResult.error("deviceId为空!"); + } + if (siteId == null) { + return AjaxResult.error("siteId为空!"); + } + if (orgId == null) { + return AjaxResult.error("orgId为空!"); + } + SiteMemory siteMemory = GlobalMemory.getSiteMemory(orgId, siteId); + if (siteMemory.hasTask(deviceId)) { + return AjaxResult.error("当前设备存在任务!"); + } + return AjaxResult.success(deviceTaskService.backToRestPoint(dto, getLoginUser().getUsername())); + } + } diff --git a/maibu-netty-server/src/main/java/com/maibu/init/InitThread.java b/maibu-netty-server/src/main/java/com/maibu/init/InitThread.java index 02dfa23..2999657 100644 --- a/maibu-netty-server/src/main/java/com/maibu/init/InitThread.java +++ b/maibu-netty-server/src/main/java/com/maibu/init/InitThread.java @@ -5,14 +5,12 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; +import java.util.Objects; import java.util.concurrent.Executor; import java.util.stream.Collectors; import javax.annotation.Resource; -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.Value; import org.springframework.boot.ApplicationArguments; @@ -26,7 +24,6 @@ import com.alibaba.fastjson2.JSON; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.maibu.constant.FastBeeConstant; import com.maibu.core.business.AlarmOrderConfig; -import com.maibu.core.business.Device; import com.maibu.core.business.DeviceModel; import com.maibu.core.business.DevicePlan; import com.maibu.core.business.DevicePlanTask; @@ -35,9 +32,12 @@ import com.maibu.core.business.ErrorIdentificationStandard; import com.maibu.core.business.IoTCommonDevice; import com.maibu.core.business.OrderModel; import com.maibu.core.business.Product; +import com.maibu.core.business.WorkRecord; import com.maibu.core.domain.entity.SysParam; import com.maibu.core.domain.entity.SysSite; +import com.maibu.core.domain.map.SiteMapInfo; import com.maibu.core.enums.DeviceTaskStaus; +import com.maibu.core.enums.RouteType; import com.maibu.influxdb.util.InfluxDBUtil; import com.maibu.mapper.AlarmOrderConfigMapper; import com.maibu.mapper.DevicePlanMapper; @@ -47,9 +47,11 @@ import com.maibu.mapper.DeviceRunParamMapper; import com.maibu.mapper.ErrorIdentificationStandardMapper; import com.maibu.mapper.IotDeviceCommonMapper; import com.maibu.mapper.OrderModelMapper; +import com.maibu.mapper.SiteMapInfoMapper; import com.maibu.mapper.SysDeviceModelMapper; import com.maibu.mapper.SysParamMapper; import com.maibu.mapper.SysSiteMapper; +import com.maibu.mapper.WorkRecordMapper; import com.maibu.memory.GlobalMemory; import com.maibu.memory.SiteMemory; import com.maibu.mybatis.LambdaQueryWrapperX; @@ -57,7 +59,6 @@ import com.maibu.service.DevicePlanTaskMonitorService; import com.maibu.service.DeviceThreadService; import com.maibu.service.impl.IotDeviceCommonService; -import cn.hutool.core.io.IORuntimeException; import cn.hutool.core.io.IoUtil; import lombok.extern.slf4j.Slf4j; @@ -75,6 +76,9 @@ public class InitThread implements ApplicationRunner { @Resource(name = FastBeeConstant.TASK.MAP_MESSAGE_PUSH) private Executor mapMessagePushExecutor; + @Resource(name = FastBeeConstant.TASK.AUTO_RULE) + private Executor autoRuleExecutor; + @Resource(name = FastBeeConstant.TASK.COMMON_DEVICE_MONITOR) private Executor commonDeviceMonitorExecutor; @@ -96,6 +100,9 @@ public class InitThread implements ApplicationRunner { @Autowired private SysSiteMapper sysSiteMapper; + @Autowired + private SiteMapInfoMapper siteMapInfoMapper; + @Autowired private DeviceRunParamMapper deviceRunParamMapper; @@ -111,7 +118,7 @@ public class InitThread implements ApplicationRunner { @Autowired private ErrorIdentificationStandardMapper errorIdentificationStandardMapper; @Autowired - + private OrderModelMapper orderModelMapper; @Autowired private AlarmOrderConfigMapper alarmOrderConfigMapper; @@ -125,6 +132,9 @@ public class InitThread implements ApplicationRunner { @Autowired private SysParamMapper sysParamMapper; + @Autowired + private WorkRecordMapper workRecordMapper; + @Value("${influxdb.url}") private String influxDBUrl; @@ -162,14 +172,21 @@ public class InitThread implements ApplicationRunner { } private void init() throws Exception { - //初始化系统参数 + // 初始化系统参数 initSystemParam(); + initDefaultWorkRecord(); + // 初始化InfluxDBUtil GlobalMemory.influxDBUtil = new InfluxDBUtil(influxDBUrl, influxDBToken, influxDBOrg, influxDBBucket); GlobalMemory.initMqttDeviceMonitor(mqttHostUrl, mqttClientId, mqttUsername, mqttPassword); + // 规则触发线程 + autoRuleExecutor.execute(() -> { + deviceThreadService.autoRule(); + }); + // 地图监控推送 mapMessagePushExecutor.execute(() -> { deviceThreadService.mapMessagePush(); @@ -225,6 +242,19 @@ public class InitThread implements ApplicationRunner { }); } + // 场站的 地图配置信息 + List siteMapInfoList = siteMapInfoMapper.selectList(); + if (!CollectionUtils.isEmpty(siteMapInfoList)) { + siteMapInfoList.forEach(x -> { + Long orgId = x.getOrgId(); + Long siteId = x.getSiteId(); + SiteMemory siteMemory = GlobalMemory.getSiteMemory(orgId, siteId); + if (siteMemory != null) { + siteMemory.getSysSite().setSiteMapInfo(x); + } + }); + } + // 外部设备 List ioTCommonDeviceList = iotDeviceCommonMapper.selectList(); if (!CollectionUtils.isEmpty(ioTCommonDeviceList)) { @@ -391,4 +421,40 @@ public class InitThread implements ApplicationRunner { } } + + public void initDefaultWorkRecord() throws IOException { + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + List list = workRecordMapper.selectList(queryWrapper); + try { + // 读取resource目录下的dsystemParam.json文件 + org.springframework.core.io.Resource resource = resourceLoader + .getResource("classpath:workRecordTemplete.json"); + // 使用fastjson2转换为DeviceConfig对象 + String jsonContent; + jsonContent = IoUtil.readUtf8(resource.getInputStream()); + List records = JSON.parseArray(jsonContent, WorkRecord.class); + List saveList = new ArrayList<>(); + if (CollectionUtils.isEmpty(list)) { + saveList.addAll(records); + } else { + Map> map = list.stream() + .filter(Objects::nonNull) + .filter(workRecord -> workRecord.getRouteType() != null) + .collect(Collectors.groupingBy( + workRecord -> workRecord.getRouteType().toString())); + if (!CollectionUtils.isEmpty(records)) { + records.forEach(x -> { + if (!map.containsKey(x.getRouteType())) { + x.setUserId(1L); + saveList.add(x); + } + }); + } + } + workRecordMapper.saveOrUpdateBatch(saveList); + } catch (Exception e) { + log.error("初始化系统参数失败", e); + } + + } } diff --git a/maibu-netty-server/src/main/java/com/maibu/service/DeviceTaskService.java b/maibu-netty-server/src/main/java/com/maibu/service/DeviceTaskService.java index 86a643f..15e287c 100644 --- a/maibu-netty-server/src/main/java/com/maibu/service/DeviceTaskService.java +++ b/maibu-netty-server/src/main/java/com/maibu/service/DeviceTaskService.java @@ -17,6 +17,8 @@ import org.springframework.stereotype.Service; import org.springframework.util.CollectionUtils; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.ObjectMapper; import com.maibu.core.business.Device; import com.maibu.core.business.DevicePlan; import com.maibu.core.business.DevicePlanTask; @@ -26,20 +28,26 @@ import com.maibu.core.business.device.NettyDevice; 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.map.RestPoint; +import com.maibu.core.domain.map.SiteMapInfo; import com.maibu.core.domain.model.LoginUser; import com.maibu.core.enums.DeviceTaskStaus; +import com.maibu.core.enums.RouteType; import com.maibu.dto.DevicePlanStatisticsDTO; import com.maibu.dto.DevicePlanTaskStatisticsDTO; import com.maibu.dto.DeviceTaskQueryDTO; import com.maibu.dto.DeviceWorkStatisticsDTO; +import com.maibu.exception.ServiceException; import com.maibu.mapper.DeviceMapper; import com.maibu.mapper.DevicePlanMapper; import com.maibu.mapper.DevicePlanTaskMapper; +import com.maibu.mapper.SiteMapInfoMapper; import com.maibu.mapper.SysRegionMapper; import com.maibu.mapper.SysSiteMapper; import com.maibu.mapper.WorkRecordMapper; import com.maibu.memory.GlobalMemory; import com.maibu.memory.SiteMemory; +import com.maibu.utils.MessageUtils; import lombok.extern.slf4j.Slf4j; @@ -68,6 +76,8 @@ public class DeviceTaskService { @Autowired private SysRegionMapper sysRegionMapper; + private static final ObjectMapper objectMapper = new ObjectMapper(); + public int insertOrUpdate(DevicePlan devicePlan, LoginUser loginUser) { Long id = devicePlan.getId(); SiteMemory siteMemory = GlobalMemory.getSiteMemory(devicePlan.getOrgId(), devicePlan.getSiteId()); @@ -470,6 +480,12 @@ public class DeviceTaskService { task.setCreateTime(LocalDateTime.now()); task.setRouteId(dto.getRouteId()); task.setStartTime(dto.getStartTime()); + + WorkRecord workRecord = workRecordMapper.selectById(dto.getRouteId()); + if (workRecord != null) { + task.setRouteType(workRecord.getRouteType()); + } + devicePlanTaskMapper.saveOrUpdate(task); if (dto.getOrgId() == null) { SysSite site = sysSiteMapper.selectById(dto.getSiteId()); @@ -487,11 +503,22 @@ public class DeviceTaskService { queryWrapper.eq(SysRegion::getId, dto.getRegionId()); SysRegion region = sysRegionMapper.selectOne(queryWrapper); - if (region == null || region.getBindRoute() == null) { - throw new RuntimeException("区域未绑定线路!"); + if (region == null) { + throw new RuntimeException("区域未找到!"); + } + Long routeId = dto.getRouteId(); + if (routeId == null) { + routeId = region.getDefaultRoute(); + } + + if (dto.getOrgId() == null) { + SysSite site = sysSiteMapper.selectById(dto.getSiteId()); + if (site != null) { + dto.setOrgId(site.getOrgId()); + } } DevicePlanTask task = new DevicePlanTask(); - task.setRouteId(region.getBindRoute()); + task.setRouteId(routeId); task.setOrgId(dto.getOrgId()); task.setSiteId(dto.getSiteId()); task.setTaskStaus(DeviceTaskStaus.NEW); @@ -499,13 +526,14 @@ public class DeviceTaskService { 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()); - } + + WorkRecord workRecord = workRecordMapper.selectById(region.getDefaultRoute()); + if (workRecord != null) { + task.setRouteType(workRecord.getRouteType()); } + + devicePlanTaskMapper.saveOrUpdate(task); + SiteMemory siteMemory = GlobalMemory.getSiteMemory(task.getOrgId(), task.getSiteId()); siteMemory.addDevicePlanPrepare(task); return task.getId(); @@ -584,4 +612,60 @@ public class DeviceTaskService { return false; } + public Long backToRestPoint(DeviceTaskCommandDTO dto, String username) { + + if (dto.getOrgId() == null) { + SysSite site = sysSiteMapper.selectById(dto.getSiteId()); + if (site != null) { + dto.setOrgId(site.getOrgId()); + } + } + + SiteMemory siteMemory = GlobalMemory.getSiteMemory(dto.getOrgId(), dto.getSiteId()); + SiteMapInfo siteMapInfo; + if (siteMemory == null) { + throw new ServiceException(MessageUtils.message("任务下发出错!")); + } + + siteMapInfo = siteMemory.getSysSite().getSiteMapInfo(); + + if (siteMapInfo == null || CollectionUtils.isEmpty(siteMapInfo.getRestPoints())) { + throw new ServiceException(MessageUtils.message("当前机器未配置返回点!")); + } + + List restPoints = objectMapper.convertValue( + siteMapInfo.getRestPoints(), + new TypeReference>() { + }); + + RestPoint switchRestPoint = restPoints.stream() + .filter(x -> dto.getDeviceId().equals(x.getBindDeviceId())).findFirst().orElse(null); + + if (switchRestPoint == null) { + throw new ServiceException(MessageUtils.message("当前机器未配置返回点!")); + } + + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + queryWrapper.eq(WorkRecord::getRouteType, RouteType.BACK_TO_REST_POINT); + WorkRecord workRecord = workRecordMapper.selectOne(queryWrapper); + + DevicePlanTask task = new DevicePlanTask(); + + task.setRouteId(workRecord.getId()); + task.setRouteType(workRecord.getRouteType()); + + task.setBackTaskPoint(switchRestPoint); + 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); + + siteMemory.addDevicePlanPrepare(task); + return task.getId(); + } + } diff --git a/maibu-netty-server/src/main/java/com/maibu/service/DeviceThreadService.java b/maibu-netty-server/src/main/java/com/maibu/service/DeviceThreadService.java index 3c2f404..2f364f1 100644 --- a/maibu-netty-server/src/main/java/com/maibu/service/DeviceThreadService.java +++ b/maibu-netty-server/src/main/java/com/maibu/service/DeviceThreadService.java @@ -15,6 +15,7 @@ import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; import com.maibu.core.business.dto.DeviceMapPushDTO; +import com.maibu.core.business.dto.DeviceTaskCommandDTO; import com.maibu.core.business.dto.WebMapMessageDTO; import com.maibu.core.business.dto.WebOlineStatusMessageDTO; import com.maibu.core.enums.*; @@ -40,8 +41,13 @@ import com.maibu.core.business.ErrorIdentificationStandard; import com.maibu.core.business.alarm_center.AlarmMessage; import com.maibu.core.business.device.NettyDevice; import com.maibu.core.business.inter.WebsocketMesDispather; +import com.maibu.core.domain.AjaxResult; +import com.maibu.core.domain.rule.ActionConfig; +import com.maibu.core.domain.rule.IotAutoRule; +import com.maibu.core.domain.rule.TriggerConditions; import com.maibu.core.host.HeartBeatDTO; import com.maibu.core.host.LocationMessage; +import com.maibu.core.host.VehicleMessage; import com.maibu.core.redis.RedisCache; import com.maibu.dto.DeviceErrorPushDTO; import com.maibu.dto.DeviceTaskStatusMessageDTO; @@ -95,6 +101,9 @@ public class DeviceThreadService { @Autowired private DeviceRunStatisticsMapper deviceRunStatisticsMapper; + @Autowired + private DeviceTaskService deviceTaskService; + public void deviceErrorMonitor() throws InterruptedException, IOException { initStandard(); @@ -456,4 +465,101 @@ public class DeviceThreadService { }, 0, 100, TimeUnit.MILLISECONDS); } + /** + * 规则触发自动判断 + */ + public void autoRule() { + executor.scheduleWithFixedDelay(() -> { + try { + List list = GlobalMemory.getAllSiteMemory(); + if (!CollectionUtils.isEmpty(list)) { + list.forEach(x -> { + List rules = x.getAllIotAutoRule(); + if (!CollectionUtils.isEmpty(rules)) { + rules.forEach(rule -> { + // 根据不同的 类型区分处理方式 + handleAutoRule(rule, x); + }); + } + }); + } + } catch (Exception e) { + log.error("执行规则出发线程错误:{}", e.getMessage()); + } + }, 0, 500, TimeUnit.MILLISECONDS); + } + + public void handleAutoRule(IotAutoRule rule, SiteMemory siteMemory) { + + if (RuleType.LOW_BATTERY_RETURN.equals(rule.getRuleType())) { + TriggerConditions conditions = rule.getConditions(); + String key = conditions.getKey(); + CompareEnum compareType = conditions.getOperator(); + String compareValue = conditions.getValue(); + List vList = siteMemory.getAllVehicleMessage(); + if (!CollectionUtils.isEmpty(vList)) { + vList.forEach(x -> { + String deviceId = x.getDeviceId(); + String value = classFieldFinding(key, x); + boolean result = CompareUtils.compare(compareType, value, compareValue); + if (result) { + ActionConfig aConfig = rule.getActionConfig(); + if (aConfig != null && aConfig.getActionType() != null) { + ActionType actionType = aConfig.getActionType(); + if (ActionType.BACK_TO_REST.equals(actionType)) { + if (siteMemory.hasTask(deviceId)) { + return; + } + DeviceTaskCommandDTO dto = new DeviceTaskCommandDTO(); + dto.setDeviceId(deviceId); + dto.setOrgId(siteMemory.getSysSite().getOrgId()); + dto.setSiteId(siteMemory.getSysSite().getId()); + + deviceTaskService.backToRestPoint(dto, "system"); + } + if (ActionType.AUTO_TASK.equals(actionType)) { + if (siteMemory.hasTask(deviceId)) { + return; + } + Long routeId = aConfig.getRouteId(); + DeviceTaskCommandDTO dto = new DeviceTaskCommandDTO(); + dto.setDeviceId(deviceId); + dto.setOrgId(siteMemory.getSysSite().getOrgId()); + dto.setSiteId(siteMemory.getSysSite().getId()); + dto.setRouteId(routeId); + deviceTaskService.createDeviceTask(dto, "system"); + } + if (ActionType.ALARM.equals(actionType)) { + + } + if (ActionType.SEND_COMMAND.equals(actionType)) { + + } + if (ActionType.WORK_ORDER.equals(actionType)) { + + } + } + } + }); + } + + } + + } + + private static String classFieldFinding(String fieldName, VehicleMessage history) { + try { + // 1. 获取类的Class对象 + Class vehicleClass = VehicleMessage.class; + Field field = vehicleClass.getDeclaredField(fieldName); + field.setAccessible(true); + Object value = field.get(history); + return (String) value; + } catch (NoSuchFieldException | IllegalAccessException e) { + System.out.println("获取字段失败: " + e.getMessage()); + log.error("获取属性值失败:{}", e.getMessage()); + } + return null; + } + } diff --git a/maibu-netty-server/src/main/resources/workRecordTemplete.json b/maibu-netty-server/src/main/resources/workRecordTemplete.json new file mode 100644 index 0000000..8b2a756 --- /dev/null +++ b/maibu-netty-server/src/main/resources/workRecordTemplete.json @@ -0,0 +1,8 @@ +[ + { + "workName": "返航任务", + "jsonData": {}, + "mode": "single_point", + "routeType": "BACK_TO_REST_POINT" + } +] \ No newline at end of file diff --git a/maibu-service/maibu-iot-service/src/main/java/com/maibu/controller/IotAutoRuleController.java b/maibu-service/maibu-iot-service/src/main/java/com/maibu/controller/IotAutoRuleController.java new file mode 100644 index 0000000..43aa962 --- /dev/null +++ b/maibu-service/maibu-iot-service/src/main/java/com/maibu/controller/IotAutoRuleController.java @@ -0,0 +1,98 @@ +package com.maibu.controller; + +import java.util.List; + +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.controller.BaseController; +import com.maibu.core.domain.AjaxResult; +import com.maibu.core.domain.entity.SysMenu; +import com.maibu.core.domain.rule.IotAutoRule; +import com.maibu.core.domain.rule.IotAutoRuleRecord; +import com.maibu.core.page.TableDataInfo; +import com.maibu.dto.IotAutoRuleRecordQueryDTO; +import com.maibu.service.IotAutoRuleService; + +/** + * 区域/场站 + * + * @author ruoyi + */ +@RestController +@RequestMapping("/system/autoRule") +public class IotAutoRuleController extends BaseController { + @Autowired + private IotAutoRuleService iotAutoRuleService; + + /** + * 新增或者修改组织 + */ + + @PostMapping("/save") + public AjaxResult save(@RequestBody IotAutoRule iotAutoRule) { + try { + return AjaxResult.success(iotAutoRuleService.save(iotAutoRule)); + } catch (Exception e) { + return AjaxResult.error("新增修改场站出错", e.getMessage()); + } + } + + /** + * 查询场站详情 + */ + + @GetMapping("/selectById") + public AjaxResult selectById(@RequestParam Long id) { + try { + return AjaxResult.success(iotAutoRuleService.selectById(id)); + } catch (Exception e) { + return AjaxResult.error("查询场站详情出错", e.getMessage()); + } + } + + /** + * 查询组织下所有的规则 + */ + @GetMapping("/selectBySiteId") + public AjaxResult selectBySiteId(@RequestParam Long siteId) { + try { + return AjaxResult.success(iotAutoRuleService.selectBySiteId(siteId)); + } catch (Exception e) { + return AjaxResult.error("查询组织下所有场站出错", e.getMessage()); + } + } + + /** + * 查询组织下所有的规则 + */ + @PostMapping("/selectAllRecord") + public TableDataInfo selectAllRecord(@RequestBody IotAutoRuleRecordQueryDTO QueryDto) { + try { + startPage(); + List menus = iotAutoRuleService.selectAllRecord(QueryDto); + return getDataTable(menus); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + /** + * 删除组织 + */ + + @PostMapping("/delete") + public AjaxResult delete(@RequestBody List ids) { + try { + return AjaxResult.success(iotAutoRuleService.delete(ids)); + } catch (Exception e) { + return AjaxResult.error("保存组织出错", e.getMessage()); + } + } + +} diff --git a/maibu-service/maibu-iot-service/src/main/java/com/maibu/controller/WorkRecordController.java b/maibu-service/maibu-iot-service/src/main/java/com/maibu/controller/WorkRecordController.java index a526c55..a7c369e 100644 --- a/maibu-service/maibu-iot-service/src/main/java/com/maibu/controller/WorkRecordController.java +++ b/maibu-service/maibu-iot-service/src/main/java/com/maibu/controller/WorkRecordController.java @@ -4,6 +4,7 @@ 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.core.enums.RouteType; import com.maibu.memory.GlobalMemory; import com.maibu.service.impl.WorkRecordService; import com.maibu.utils.MinioUtil; @@ -35,6 +36,14 @@ public class WorkRecordController extends BaseController { // WorkRecord workRecordObj = JsonUtils.parseObject(workRecord, // WorkRecord.class); + if (workRecord == null || workRecord.getRouteType() == null) { + return R.fail("未选择规划类型"); + } + + if (RouteType.BACK_TO_REST_POINT.equals(workRecord.getRouteType())) { + return R.fail("无法添加返航任务类型的路径规划"); + } + WorkRecord workRecord1 = workRecordService.selectWorkRecordByWorkNameAndSiteId(workRecord.getWorkName(), workRecord.getSiteId()); if (workRecord1 != null) { @@ -100,6 +109,12 @@ public class WorkRecordController extends BaseController { return R.ok(workRecord); } + @PostMapping("/selectByIds") + public R selectByIds(@RequestBody List ids) { + List workRecords = workRecordService.selectByIds(ids); + return R.ok(workRecords); + } + @GetMapping("/selectByTaskId") public R selectByTaskId(@RequestParam Long taskId) { WorkRecord workRecord = workRecordService.selectByTaskId(taskId); diff --git a/maibu-service/maibu-iot-service/src/main/java/com/maibu/dto/IotAutoRuleRecordQueryDTO.java b/maibu-service/maibu-iot-service/src/main/java/com/maibu/dto/IotAutoRuleRecordQueryDTO.java new file mode 100644 index 0000000..f8d60a7 --- /dev/null +++ b/maibu-service/maibu-iot-service/src/main/java/com/maibu/dto/IotAutoRuleRecordQueryDTO.java @@ -0,0 +1,17 @@ +package com.maibu.dto; + +import com.maibu.core.domain.BaseEntity; +import com.maibu.core.enums.RuleType; + +import lombok.Data; + +@Data +public class IotAutoRuleRecordQueryDTO extends BaseEntity { + private RuleType ruleType; + + private Long ruleId; + + private String deviceId; + + private Long siteId; +} diff --git a/maibu-service/maibu-iot-service/src/main/java/com/maibu/service/IotAutoRuleService.java b/maibu-service/maibu-iot-service/src/main/java/com/maibu/service/IotAutoRuleService.java new file mode 100644 index 0000000..520b8b5 --- /dev/null +++ b/maibu-service/maibu-iot-service/src/main/java/com/maibu/service/IotAutoRuleService.java @@ -0,0 +1,82 @@ +package com.maibu.service; + +import java.util.List; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.maibu.core.domain.map.SiteMapInfo; +import com.maibu.core.domain.rule.IotAutoRule; +import com.maibu.core.domain.rule.IotAutoRuleRecord; +import com.maibu.dto.IotAutoRuleRecordQueryDTO; +import com.maibu.exception.ServiceException; +import com.maibu.mapper.IotAutoRuleMapper; +import com.maibu.mapper.IotAutoRuleRecordMapper; +import com.maibu.mapper.SiteMapInfoMapper; +import com.maibu.memory.GlobalMemory; +import com.maibu.memory.SiteMemory; + +import io.micrometer.core.instrument.util.StringUtils; + +@Service +public class IotAutoRuleService { + + @Autowired + private IotAutoRuleMapper iotAutoRuleMapper; + + @Autowired + private IotAutoRuleRecordMapper iotAutoRuleRecordMapper; + + public boolean save(IotAutoRule iotAutoRule) { + try { + boolean b = iotAutoRuleMapper.saveOrUpdate(iotAutoRule); + SiteMemory siteMemory = GlobalMemory.getSiteMemory(iotAutoRule.getOrgId(), iotAutoRule.getId()); + if (siteMemory != null && siteMemory.sysSite != null) { + siteMemory.saveIotAutoRule(iotAutoRule.getRuleType(), iotAutoRule); + return b; + } + } catch (Exception e) { + // TODO: handle exception + throw new ServiceException("地图信息保存失败"); + } + return false; + + } + + public IotAutoRule selectById(Long id) { + return iotAutoRuleMapper.selectById(id); + } + + public IotAutoRule selectBySiteId(Long siteId) { + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + queryWrapper.eq(IotAutoRule::getSiteId, siteId); + return iotAutoRuleMapper.selectOne(queryWrapper); + } + + public List selectAllRecord(IotAutoRuleRecordQueryDTO queryDto) { + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + + if (queryDto != null && queryDto.getRuleType() != null) { + queryWrapper.eq(IotAutoRuleRecord::getRuleType, queryDto.getRuleType()); + } + + if (queryDto != null && queryDto.getRuleId() != null) { + queryWrapper.eq(IotAutoRuleRecord::getRuleId, queryDto.getRuleId()); + } + + if (queryDto != null && !StringUtils.isEmpty(queryDto.getDeviceId())) { + queryWrapper.eq(IotAutoRuleRecord::getDeviceId, queryDto.getDeviceId()); + } + + if (queryDto != null && queryDto.getSiteId() != null) { + queryWrapper.eq(IotAutoRuleRecord::getSiteId, queryDto.getSiteId()); + } + + return iotAutoRuleRecordMapper.selectList(queryWrapper); + } + + public int delete(List ids) { + return iotAutoRuleRecordMapper.deleteBatchIds(ids); + } +} diff --git a/maibu-service/maibu-iot-service/src/main/java/com/maibu/service/impl/WorkRecordService.java b/maibu-service/maibu-iot-service/src/main/java/com/maibu/service/impl/WorkRecordService.java index 2bc2fe0..7c0d2fc 100644 --- a/maibu-service/maibu-iot-service/src/main/java/com/maibu/service/impl/WorkRecordService.java +++ b/maibu-service/maibu-iot-service/src/main/java/com/maibu/service/impl/WorkRecordService.java @@ -9,6 +9,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.util.CollectionUtils; +import java.util.ArrayList; import java.util.Comparator; import java.util.List; @@ -73,6 +74,15 @@ public class WorkRecordService { return workRecordMapper.selectById(id); } + public List selectByIds(List ids) { + if (!CollectionUtils.isEmpty(ids)) { + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + queryWrapper.in(WorkRecord::getId, ids); + return workRecordMapper.selectList(queryWrapper); + } + return new ArrayList<>(); + } + public WorkRecord selectByTaskId(Long taskId) { DevicePlanTask devicePlanTask = devicePlanTaskMapper.selectById(taskId); // 先查询设备任务,确认任务存在 if (devicePlanTask == null) { diff --git a/maibu-service/maibu-system-service/src/main/java/com/maibu/mapper/IotAutoRuleMapper.java b/maibu-service/maibu-system-service/src/main/java/com/maibu/mapper/IotAutoRuleMapper.java new file mode 100644 index 0000000..48cdec3 --- /dev/null +++ b/maibu-service/maibu-system-service/src/main/java/com/maibu/mapper/IotAutoRuleMapper.java @@ -0,0 +1,11 @@ +package com.maibu.mapper; + +import org.springframework.stereotype.Repository; + +import com.maibu.core.domain.rule.IotAutoRule; +import com.maibu.mybatis.mapper.BaseMapperX; + +@Repository +public interface IotAutoRuleMapper extends BaseMapperX { + +} diff --git a/maibu-service/maibu-system-service/src/main/java/com/maibu/mapper/IotAutoRuleRecordMapper.java b/maibu-service/maibu-system-service/src/main/java/com/maibu/mapper/IotAutoRuleRecordMapper.java new file mode 100644 index 0000000..73e6e5a --- /dev/null +++ b/maibu-service/maibu-system-service/src/main/java/com/maibu/mapper/IotAutoRuleRecordMapper.java @@ -0,0 +1,12 @@ +package com.maibu.mapper; + +import org.springframework.stereotype.Repository; + +import com.maibu.core.domain.rule.IotAutoRuleRecord; +import com.maibu.mybatis.mapper.BaseMapperX; + + +@Repository +public interface IotAutoRuleRecordMapper extends BaseMapperX { + +} diff --git a/maibu-service/maibu-system-service/src/main/java/com/maibu/mapper/SiteMapInfoMapper.java b/maibu-service/maibu-system-service/src/main/java/com/maibu/mapper/SiteMapInfoMapper.java new file mode 100644 index 0000000..c4a4660 --- /dev/null +++ b/maibu-service/maibu-system-service/src/main/java/com/maibu/mapper/SiteMapInfoMapper.java @@ -0,0 +1,14 @@ +package com.maibu.mapper; + +import org.springframework.stereotype.Repository; + +import com.maibu.core.domain.map.SiteMapInfo; +import com.maibu.mybatis.mapper.BaseMapperX; + +/** + * 设备历史状态 + */ +@Repository +public interface SiteMapInfoMapper extends BaseMapperX { + +} diff --git a/maibu-service/maibu-system-service/src/main/java/com/maibu/service/SiteMapInfoService.java b/maibu-service/maibu-system-service/src/main/java/com/maibu/service/SiteMapInfoService.java new file mode 100644 index 0000000..12b3c47 --- /dev/null +++ b/maibu-service/maibu-system-service/src/main/java/com/maibu/service/SiteMapInfoService.java @@ -0,0 +1,44 @@ +package com.maibu.service; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.maibu.core.domain.map.SiteMapInfo; +import com.maibu.exception.ServiceException; +import com.maibu.mapper.SiteMapInfoMapper; +import com.maibu.memory.GlobalMemory; +import com.maibu.memory.SiteMemory; + +@Service +public class SiteMapInfoService { + + @Autowired + private SiteMapInfoMapper siteMapInfoMapper; + + public boolean save(SiteMapInfo siteMapInfo) { + try { + boolean b = siteMapInfoMapper.saveOrUpdate(siteMapInfo); + SiteMemory siteMemory = GlobalMemory.getSiteMemory(siteMapInfo.getOrgId(), siteMapInfo.getId()); + if (siteMemory != null && siteMemory.sysSite != null) { + siteMemory.sysSite.setSiteMapInfo(siteMapInfo); + } + return b; + } catch (Exception e) { + // TODO: handle exception + throw new ServiceException("地图信息保存失败"); + } + + } + + public SiteMapInfo selectById(Long id) { + return siteMapInfoMapper.selectById(id); + } + + public SiteMapInfo selectBySiteId(Long siteId) { + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + queryWrapper.eq(SiteMapInfo::getSiteId, siteId); + return siteMapInfoMapper.selectOne(queryWrapper); + } + +} diff --git a/maibu-service/maibu-system-service/src/main/java/com/maibu/service/SysRegionService.java b/maibu-service/maibu-system-service/src/main/java/com/maibu/service/SysRegionService.java index 6e76e1e..5cd33ab 100644 --- a/maibu-service/maibu-system-service/src/main/java/com/maibu/service/SysRegionService.java +++ b/maibu-service/maibu-system-service/src/main/java/com/maibu/service/SysRegionService.java @@ -12,7 +12,6 @@ import java.util.ArrayList; import java.util.List; import java.util.stream.Collectors; - @Service public class SysRegionService { @@ -20,14 +19,6 @@ public class SysRegionService { private SysRegionMapper sysRegionMapper; - public List list(SysRegion region) { - LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); - if (region != null && !StringUtils.isEmpty(region.getRegionName())) { - queryWrapper.like(SysRegion::getRegionName, region.getRegionName()); - } - return sysRegionMapper.selectList(queryWrapper); - } - public boolean save(SysRegion org) { return sysRegionMapper.saveOrUpdate(org); } @@ -37,8 +28,8 @@ public class SysRegionService { } public void deleteAll(List ids) { - List regionIds = getIdsBySiteIds(ids); - if(!CollectionUtils.isEmpty(regionIds)){ + List regionIds = getIdsBySiteIds(ids); + if (!CollectionUtils.isEmpty(regionIds)) { delete(regionIds); } } @@ -47,9 +38,9 @@ public class SysRegionService { LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); queryWrapper.in(SysRegion::getSiteId, ids); List list = sysRegionMapper.selectList(queryWrapper); - if(!CollectionUtils.isEmpty(list)){ + if (!CollectionUtils.isEmpty(list)) { return list.stream().map(SysRegion::getId).collect(Collectors.toList()); - }else{ + } else { return new ArrayList<>(); } } diff --git a/maibu-web-middleware/src/main/java/com/maibu/control/DiffSteer.java b/maibu-web-middleware/src/main/java/com/maibu/control/DiffSteer.java index 9791c96..b9b8b12 100644 --- a/maibu-web-middleware/src/main/java/com/maibu/control/DiffSteer.java +++ b/maibu-web-middleware/src/main/java/com/maibu/control/DiffSteer.java @@ -2,7 +2,7 @@ package com.maibu.control; import lombok.Data; -@Data +@Data public class DiffSteer { public static final int Polarity_High = 0; // 0 diff --git a/maibu-web-middleware/src/main/java/com/maibu/utils/ControlUtils.java b/maibu-web-middleware/src/main/java/com/maibu/utils/ControlUtils.java index 321e80d..2e5a446 100644 --- a/maibu-web-middleware/src/main/java/com/maibu/utils/ControlUtils.java +++ b/maibu-web-middleware/src/main/java/com/maibu/utils/ControlUtils.java @@ -75,8 +75,8 @@ public class ControlUtils { // buffer.putShort(entity.getLeftWheelSpeed());//左轮速度 // buffer.putShort(entity.getRightWheelSpeed());//右轮速度 - buffer.putDouble(entity.getAngularSpeed());// 左轮速度 - buffer.putDouble(entity.getLinearSpeed());// 右轮速度 + buffer.putDouble(entity.getLinearSpeed());// + buffer.putDouble(entity.getAngularSpeed());// 右轮速度 buffer.put(entity.getChassisLiftFlag());// 底盘升降 buffer.put(entity.getMowerSpeedFlag());// 割刀加减速 diff --git a/maibu-web-middleware/src/main/java/com/maibu/websocket/WebsocketHandler.java b/maibu-web-middleware/src/main/java/com/maibu/websocket/WebsocketHandler.java index f315836..fe49a6e 100644 --- a/maibu-web-middleware/src/main/java/com/maibu/websocket/WebsocketHandler.java +++ b/maibu-web-middleware/src/main/java/com/maibu/websocket/WebsocketHandler.java @@ -1,19 +1,13 @@ package com.maibu.websocket; -import com.maibu.constant.CommandConstant; -import com.maibu.common.MiddleConstant; -import com.maibu.core.business.LawnMoverProtocolEntity; -import com.maibu.core.enums.CommandRequestType; -import com.maibu.core.enums.MesType; -import com.maibu.dto.*; -import com.maibu.memory.MiddleGlobalMemory; -import com.maibu.netty.NettyClient; -import com.maibu.utils.CommandUtils; -import com.maibu.utils.ControlUtils; -import com.maibu.utils.json.JsonUtils; -import com.maibu.utils.spring.SpringUtils; -import io.netty.buffer.ByteBuf; -import io.netty.buffer.Unpooled; +import java.net.InetSocketAddress; +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; + import org.apache.commons.lang3.StringUtils; import org.java_websocket.WebSocket; import org.java_websocket.handshake.ClientHandshake; @@ -21,14 +15,24 @@ import org.java_websocket.server.WebSocketServer; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.net.InetSocketAddress; -import java.util.Collection; -import java.util.List; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.Executors; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.TimeUnit; +import com.maibu.common.MiddleConstant; +import com.maibu.constant.CommandConstant; +import com.maibu.core.business.LawnMoverProtocolEntity; +import com.maibu.core.enums.CommandRequestType; +import com.maibu.core.enums.MesType; +import com.maibu.dto.DeviceRequestDTO; +import com.maibu.dto.DeviceRespondDTO; +import com.maibu.dto.RemoteData; +import com.maibu.dto.WebMessageBaseDTO; +import com.maibu.memory.MiddleGlobalMemory; +import com.maibu.netty.NettyClient; +import com.maibu.utils.CommandUtils; +import com.maibu.utils.ControlUtils; +import com.maibu.utils.json.JsonUtils; +import com.maibu.utils.spring.SpringUtils; + +import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; /** * WebSocket服务器实现类 @@ -110,7 +114,7 @@ public class WebsocketHandler extends WebSocketServer { List axes = remoteData.getAxes(); List buttons = remoteData.getButtons(); Double y = axes.get(1) * 1000 * -1; // 前后值反了 - Double x = axes.get(2) * 1000; + Double x = axes.get(2) * 1000 * -1; int intX = (int) x.doubleValue(); int intY = (int) y.doubleValue(); // todo 计算线速度和角速度 还需要根据车型来给线速度 角速度范围最大值