diff --git a/maibu-admin/src/main/java/com/maibu/web/controller/system/SysLoginController.java b/maibu-admin/src/main/java/com/maibu/web/controller/system/SysLoginController.java index b6af317..56554ec 100644 --- a/maibu-admin/src/main/java/com/maibu/web/controller/system/SysLoginController.java +++ b/maibu-admin/src/main/java/com/maibu/web/controller/system/SysLoginController.java @@ -11,7 +11,7 @@ import com.maibu.domain.AppPreferences; import com.maibu.core.business.device.NettyDevice; import com.maibu.enums.BusinessType; import com.maibu.enums.SourceType; -import com.maibu.manager.DeviceSessionManager; +import com.maibu.memory.DeviceSessionManager; import com.maibu.service.IAppPreferencesService; import com.maibu.service.ISysMenuService; import com.maibu.service.ISysUserService; diff --git a/maibu-admin/src/main/resources/application-dev.yml b/maibu-admin/src/main/resources/application-dev.yml index c51c9d8..e27acc1 100644 --- a/maibu-admin/src/main/resources/application-dev.yml +++ b/maibu-admin/src/main/resources/application-dev.yml @@ -4,8 +4,8 @@ spring: type: com.alibaba.druid.pool.DruidDataSource driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql://localhost:3306/maibu?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8 - username: fastbee - password: maibu520 + username: satabot + password: satabot # redis 配置 redis: diff --git a/maibu-common/src/main/java/com/maibu/constant/CommandConstant.java b/maibu-common/src/main/java/com/maibu/constant/CommandConstant.java new file mode 100644 index 0000000..97a1723 --- /dev/null +++ b/maibu-common/src/main/java/com/maibu/constant/CommandConstant.java @@ -0,0 +1,20 @@ +package com.maibu.constant; + +public class CommandConstant { + + public static byte remoteControl = (byte) 0x00; + + public static byte heartbeat = (byte) 0xff; + + public static byte path = (byte) 0x01; + + public static byte status = (byte) 0x02; + + public static byte connect = (byte) 0x03; + + public static byte interaction = (byte) 0x12; //主要用于推送状态消息等 + + public static byte readConfig = (byte) 0x05; //读取配置的参数 + + public static byte writeConfig = (byte) 0x06; //写配置参数 +} diff --git a/maibu-netty-server/src/main/java/com/maibu/common/Constant.java b/maibu-common/src/main/java/com/maibu/constant/Constant.java similarity index 60% rename from maibu-netty-server/src/main/java/com/maibu/common/Constant.java rename to maibu-common/src/main/java/com/maibu/constant/Constant.java index 81ce1c7..bcb95f9 100644 --- a/maibu-netty-server/src/main/java/com/maibu/common/Constant.java +++ b/maibu-common/src/main/java/com/maibu/constant/Constant.java @@ -1,17 +1,25 @@ -package com.maibu.common; +package com.maibu.constant; +import com.maibu.core.business.DeviceRunParam; import com.maibu.core.enums.ConnectionCloseReason; import io.netty.util.AttributeKey; import lombok.Data; +import java.util.concurrent.CompletableFuture; + @Data public class Constant { public static final AttributeKey ATT_DEVICE_ID = AttributeKey.valueOf("deviceId"); + public static final AttributeKey> READ_CONFIG_KEY = + AttributeKey.valueOf("READ_CONFIG"); + public static final AttributeKey ATT_CLOSE_REASON = AttributeKey.valueOf("closeReason"); public static final AttributeKey ATT_ORG_ID = AttributeKey.valueOf("orgId"); public static final AttributeKey ATT_SITE_ID = AttributeKey.valueOf("siteId"); + + public static final String WheelGainCoefficients = "WheelGainCoefficients"; } 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 287948c..fb83995 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 @@ -20,21 +20,23 @@ public class DevicePlanTask extends OrgBaseDO { @TableId(type = IdType.AUTO) private Long id; - private Long planId; //归属于某个计划任务 + private Long planId; // 归属于某个计划任务 private String deviceId; - private DeviceTaskStaus taskStaus; //任务状态 + private DeviceTaskStaus taskStaus; // 任务状态 @TableField(exist = false) - private String taskStausTranslate; //任务状态 + private String taskStausTranslate; // 任务状态 private Long routeId; // 线路id private LocalDateTime finishTime; - private LocalDateTime startTime; //开始时间 时分秒 + private LocalDateTime startTime; // 开始时间 时分秒 - private String taskType; //任务类型分类 + private String taskType; // 任务类型分类 + + private LocalDateTime canExecuteTime; // 这个时间之前都不能执行 } diff --git a/maibu-common/src/main/java/com/maibu/core/business/DeviceRunParam.java b/maibu-common/src/main/java/com/maibu/core/business/DeviceRunParam.java index 556382c..419b0ac 100644 --- a/maibu-common/src/main/java/com/maibu/core/business/DeviceRunParam.java +++ b/maibu-common/src/main/java/com/maibu/core/business/DeviceRunParam.java @@ -1,13 +1,19 @@ package com.maibu.core.business; import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; +import com.maibu.constant.CommandConstant; import com.maibu.core.domain.BaseDO; import lombok.Data; import lombok.EqualsAndHashCode; +import java.nio.ByteBuffer; +import java.nio.ByteOrder; +import java.nio.charset.StandardCharsets; + @EqualsAndHashCode(callSuper = true) @Data @TableName(value = "iot_device_run_param", autoResultMap = true) @@ -22,6 +28,432 @@ public class DeviceRunParam extends BaseDO { private Long orgId; - private Double runSpeed; + private Integer runSpeed; //不下发到设备自己用 + + + @TableField(exist = false) + public byte header1; + @TableField(exist = false) + public byte header2; + @TableField(exist = false) + public byte cmd; + + + public byte chipUidSign;//芯片UID固化标志位 + public String chipUid;//芯片UID + + public byte[] remoteConfig;//遥控器通道配置 + public int knifeMotorMode;//割刀电机模式 + public int walkMotorMode;//行走电机模式 + public int leftMotorReverse;//左轮电机方向极性 + public int rightMotorReverse;//右轮电机方向极性 + public int swapChannel;//左右轮通道互换标志位 + public int use4G;//联网标志位 + + public short forwardSpeedLimit;//前进速度限制 + public short turnSpeedLimit;//转向速度限制 + + public int knifePolarity;//割刀通道极性 + public int fanPolarity;//风门通道极性 + public int throttlePolarity;//油门通道极性 + public int liftProtectTime;//底盘升降电机保护时间 + public int dualRtk;//RTK配置 + + + public int knifeChannel;//割刀通道配置 + public int fanChannel;//风门通道配置 + + public int throttleChannel;//油门通道配置 + public int remoteType;//遥控器类型 + public boolean relayBoard;//是否搭载继电器板 + + public int liftChannel;//底盘升通道配置 + public int chassisChannel;//底盘降通道配置 + + public int armChannel;//抱闸通道配置 + public int fuelPumpChannel;//燃油励磁通道配置 + + public String wifiName;//wifi名称 + public String wifiPassword;//wifi密码 + + public int batteryType;//电池类型 + public int driveType;//行走驱动配置 + + public float gearRatio;//转速比 + public float robotLength;//机器人长度 + public float robotWidth;//机器人宽度 + public float robotHeight;//机器人高度 + public float knifeWidth;//割刀宽度 + public float tyreSize;//轮胎尺寸 + public float leftForwardGain;//左轮前进增益 + public float leftBackwardGain;//左轮后退增益 + public float rightForwardGain;//右轮前进增益 + public float rightBackwardGain;//右轮后退增益 + + public String firmwareVersion;//固件版本 + @TableField(exist = false) + public int crc16; + @TableField(exist = false) + public byte tail1; + @TableField(exist = false) + public byte tail2; + @TableField(exist = false) + private byte[] originalData; + + public static byte[] toReadBytes() { + ByteBuffer buffer = ByteBuffer.allocate(7); // 修改为27字节 + buffer.order(ByteOrder.LITTLE_ENDIAN); + + buffer.put((byte) 0xAB); + buffer.put((byte) 0xAA); + + buffer.put(CommandConstant.readConfig); + + buffer.putShort((short) 0); + + buffer.put((byte) 0xAA); + buffer.put((byte) 0xAB); + + 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() { + // 如果没有原始数据,使用静态方法重新构建 + if (originalData == null || originalData.length < 178) { + return null; + } + + // 克隆原始数据,避免修改原始数据 + byte[] result = originalData.clone(); + ByteBuffer buffer = ByteBuffer.wrap(result); + buffer.order(ByteOrder.LITTLE_ENDIAN); + + // 修改指令为写配置(字节2) + buffer.put(2, CommandConstant.writeConfig); + + // 修改字节68:遥控器配置 + byte remote = 0; + remote |= (getKnifeMotorMode() & 0x03); + remote |= (getWalkMotorMode() & 0x03) << 2; + remote |= (getLeftMotorReverse() & 0x01) << 4; + remote |= (getRightMotorReverse() & 0x01) << 5; + remote |= (getSwapChannel() & 0x01) << 6; + remote |= (getUse4G() & 0x01) << 7; + buffer.put(68, remote); + + // 修改字节69-72:速度限制 + buffer.putShort(69, getForwardSpeedLimit()); + buffer.putShort(71, getTurnSpeedLimit()); + + // 修改字节73:通道极性 + byte b73 = 0; + b73 |= (getKnifePolarity() & 1); + b73 |= (getFanPolarity() & 1) << 1; + b73 |= (getThrottlePolarity() & 1) << 2; + b73 |= (getLiftProtectTime() & 0x0F) << 3; + b73 |= (getDualRtk() & 1) << 7; + buffer.put(73, b73); + + // 修改字节74-77:通道配置 + byte b74 = 0; + b74 |= (getKnifeChannel() & 0x0F); + b74 |= (getFanChannel() & 0x0F) << 4; + buffer.put(74, b74); + + byte b75 = 0; + b75 |= (getThrottleChannel() & 0x0F); + b75 |= (getRemoteType() & 0x07) << 4; + if (isRelayBoard()) b75 |= 1 << 7; + buffer.put(75, b75); + + byte b76 = 0; + b76 |= (getLiftChannel() & 0x0F); + b76 |= (getChassisChannel() & 0x0F) << 4; + buffer.put(76, b76); + + byte b77 = 0; + b77 |= (getArmChannel() & 0x0F); + b77 |= (getFuelPumpChannel() & 0x0F) << 4; + buffer.put(77, b77); + +// // 修改字节78-117:WiFi信息 +// byte[] wifiNameBytes = new byte[20]; +// if (getWifiName() != null) { +// byte[] src = getWifiName().getBytes(StandardCharsets.UTF_8); +// System.arraycopy(src, 0, wifiNameBytes, 0, Math.min(src.length, 20)); +// } +// System.arraycopy(wifiNameBytes, 0, result, 78, 20); +// +// byte[] wifiPwdBytes = new byte[20]; +// if (getWifiPassword() != null) { +// byte[] src = getWifiPassword().getBytes(StandardCharsets.UTF_8); +// System.arraycopy(src, 0, wifiPwdBytes, 0, Math.min(src.length, 20)); +// } +// System.arraycopy(wifiPwdBytes, 0, result, 98, 20); + +// // 修改字节118:电池和驱动配置 +// byte b118 = 0; +// b118 |= (getBatteryType() & 0x03); +// b118 |= (getDriveType() & 0x03) << 2; +// buffer.put(118, b118); + + // 修改字节119-158:float参数 + buffer.putFloat(119, getGearRatio()); + buffer.putFloat(123, getRobotLength()); + buffer.putFloat(127, getRobotWidth()); + buffer.putFloat(131, getRobotHeight()); + buffer.putFloat(135, getKnifeWidth()); + buffer.putFloat(139, getTyreSize()); + buffer.putFloat(143, getLeftForwardGain()); + buffer.putFloat(147, getLeftBackwardGain()); + buffer.putFloat(151, getRightForwardGain()); + buffer.putFloat(155, getRightBackwardGain()); + + // 修改字节159-173:固件版本 +// byte[] fwBytes = new byte[15]; +// if (getFirmwareVersion() != null) { +// byte[] src = getFirmwareVersion().getBytes(StandardCharsets.UTF_8); +// System.arraycopy(src, 0, fwBytes, 0, Math.min(src.length, 15)); +// } +// System.arraycopy(fwBytes, 0, result, 159, 15); + + // 保留原始的 CRC 和尾部,不强制修改 + // 移除以下强制修改: + // buffer.putShort(174, (short) 0); + // buffer.put(176, (byte) 0xAA); + // buffer.put(177, (byte) 0xAB); + + return result; + } + + public static void putFixedString(ByteBuffer buffer, String value, int len) { + + byte[] bytes = new byte[len]; + + if (value != null) { + byte[] src = value.getBytes(StandardCharsets.UTF_8); + + System.arraycopy(src, 0, bytes, 0, Math.min(src.length, len)); + } + + buffer.put(bytes); + } + + + public static DeviceRunParam fromBytes(byte[] data) { + // 183 + if (data == null || data.length < 178) { + throw new IllegalArgumentException("数据长度不足"); + } + + ByteBuffer buffer = ByteBuffer.wrap(data); + buffer.order(ByteOrder.LITTLE_ENDIAN); + + DeviceRunParam p = new DeviceRunParam(); + + p.setOriginalData(data); + + p.setHeader1(buffer.get()); + p.setHeader2(buffer.get()); + + p.setCmd(buffer.get()); + + p.setChipUidSign(buffer.get()); + + p.setChipUid(readString(buffer, 45)); + + // 跳过字节49-67(共19字节,预留不用) + buffer.position(buffer.position() + 19); + + byte remote = buffer.get(); + +// p.setRemoteConfig(remote); + + p.setKnifeMotorMode(remote & 0x03); + p.setWalkMotorMode((remote >> 2) & 0x03); + p.setLeftMotorReverse((remote >> 4) & 0x01); + p.setRightMotorReverse((remote >> 5) & 0x01); + p.setSwapChannel((remote >> 6) & 0x01); + p.setUse4G((remote >> 7) & 0x01); + + p.setForwardSpeedLimit(buffer.getShort()); + p.setTurnSpeedLimit(buffer.getShort()); + + byte b73 = buffer.get(); + + p.setKnifePolarity(b73 & 1); + p.setFanPolarity((b73 >> 1) & 1); + p.setThrottlePolarity((b73 >> 2) & 1); + p.setLiftProtectTime((b73 >> 3) & 0x0F); + p.setDualRtk((b73 >> 7) & 1); + + byte b74 = buffer.get(); + + p.setKnifeChannel(b74 & 0x0F); + p.setFanChannel((b74 >> 4) & 0x0F); + + byte b75 = buffer.get(); + + p.setThrottleChannel(b75 & 0x0F); + p.setRemoteType((b75 >> 4) & 0x07); + p.setRelayBoard(((b75 >> 7) & 1) == 1); + + byte b76 = buffer.get(); + + p.setLiftChannel(b76 & 0x0F); + p.setChassisChannel((b76 >> 4) & 0x0F); + + byte b77 = buffer.get(); + + p.setArmChannel(b77 & 0x0F); + p.setFuelPumpChannel((b77 >> 4) & 0x0F); + + p.setWifiName(readString(buffer, 20)); + p.setWifiPassword(readString(buffer, 20)); + + byte b118 = buffer.get(); + + p.setBatteryType(b118 & 0x03); + p.setDriveType((b118 >> 2) & 0x03); + + // float + p.setGearRatio(buffer.getFloat()); + p.setRobotLength(buffer.getFloat()); + p.setRobotWidth(buffer.getFloat()); + p.setRobotHeight(buffer.getFloat()); + p.setKnifeWidth(buffer.getFloat()); + p.setTyreSize(buffer.getFloat()); + p.setLeftForwardGain(buffer.getFloat()); + p.setLeftBackwardGain(buffer.getFloat()); + p.setRightForwardGain(buffer.getFloat()); + p.setRightBackwardGain(buffer.getFloat()); + + p.setFirmwareVersion(readString(buffer, 15)); + + p.setCrc16(Short.toUnsignedInt(buffer.getShort())); + + p.setTail1(buffer.get()); + p.setTail2(buffer.get()); + + return p; + } + + public static String readString(ByteBuffer buffer, int len) { + byte[] bytes = new byte[len]; + buffer.get(bytes); + + int end = 0; + while (end < bytes.length && bytes[end] != 0) { + end++; + } + + return new String(bytes, 0, end, StandardCharsets.UTF_8); + } } diff --git a/maibu-common/src/main/java/com/maibu/core/business/IOTWorkOrder.java b/maibu-common/src/main/java/com/maibu/core/business/IOTWorkOrder.java index e4d5193..2aed40b 100644 --- a/maibu-common/src/main/java/com/maibu/core/business/IOTWorkOrder.java +++ b/maibu-common/src/main/java/com/maibu/core/business/IOTWorkOrder.java @@ -2,10 +2,14 @@ package com.maibu.core.business; import java.math.BigDecimal; import java.time.LocalDateTime; +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.fasterxml.jackson.annotation.JsonFormat; import com.maibu.core.domain.OrgNoUserDO; import com.maibu.core.enums.ErrorLevel; import com.maibu.core.enums.ErrorSource; @@ -15,10 +19,11 @@ import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; import lombok.EqualsAndHashCode; +import org.springframework.format.annotation.DateTimeFormat; @Data @EqualsAndHashCode(callSuper = true) -@TableName("iot_work_order") +@TableName(value = "iot_work_order", autoResultMap = true) @ApiModel("工单记录") public class IOTWorkOrder extends OrgNoUserDO { @@ -64,21 +69,31 @@ public class IOTWorkOrder extends OrgNoUserDO { private String collaboratorNames; @ApiModelProperty("计划开始时间") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") private LocalDateTime planStartTime; @ApiModelProperty("计划结束时间") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") private LocalDateTime planEndTime; @ApiModelProperty("截止时间") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") private LocalDateTime deadlineTime; @ApiModelProperty("实际开始时间") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") private LocalDateTime actualStartTime; @ApiModelProperty("实际完成时间") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") private LocalDateTime actualEndTime; - @ApiModelProperty("工单状态:1-待处理 2-已派发 3-执行中 4-已完成 5-已挂起") + @ApiModelProperty("工单状态:1-待处理 2-执行中 3-已完成 4-已挂起") private Integer orderStatus; @ApiModelProperty("关联告警 ID") @@ -105,7 +120,23 @@ public class IOTWorkOrder extends OrgNoUserDO { @ApiModelProperty("处理备注") private String handleRemark; + @TableField(typeHandler = JacksonTypeHandler.class) + private List imgUrl; //创建时候的照片 + + @TableField(typeHandler = JacksonTypeHandler.class) + private List videoUrl;//创建时候的视频 + private Long modelId; - private Long taskId; + private String taskId; + + private boolean autoCreate = false; //自动创建 + + private String failureCause; //故障原因 + + private String handleMeasures; //处理措施 + + @TableField(typeHandler = JacksonTypeHandler.class) + private List images; //现场图片 处理后的照片 + } diff --git a/maibu-common/src/main/java/com/maibu/core/business/alarm_center/Alarm.java b/maibu-common/src/main/java/com/maibu/core/business/alarm_center/Alarm.java index a2e6c89..53da9d4 100644 --- a/maibu-common/src/main/java/com/maibu/core/business/alarm_center/Alarm.java +++ b/maibu-common/src/main/java/com/maibu/core/business/alarm_center/Alarm.java @@ -3,6 +3,8 @@ package com.maibu.core.business.alarm_center; import com.baomidou.mybatisplus.annotation.*; import com.maibu.annotation.Excel; import com.maibu.core.domain.TenantBaseDO; +import com.maibu.core.enums.AlarmHandleResult; +import com.maibu.core.enums.AlarmType; import com.maibu.core.enums.ErrorLevel; import com.maibu.core.enums.ErrorSource; @@ -34,7 +36,7 @@ public class Alarm extends TenantBaseDO { @ApiModelProperty("告警类型:1-设备故障 2-数据异常 3-通信中断 4-性能告警 5-安全告警 6-环境告警") @Excel(name = "告警类型", readConverterExp = "1=设备故障,2=数据异常,3=通信中断,4=性能告警,5=安全告警,6=环境告警") - private Integer alarmType; + private AlarmType alarmType; @ApiModelProperty("告警标题") @Excel(name = "告警标题") @@ -44,6 +46,8 @@ public class Alarm extends TenantBaseDO { @Excel(name = "告警内容") private String alarmContent; + private String timeValues; //告警时上报的值 + @ApiModelProperty("设备ID") @Excel(name = "设备ID", cellType = Excel.ColumnType.NUMERIC) private String deviceId; @@ -68,8 +72,8 @@ public class Alarm extends TenantBaseDO { @Excel(name = "持续时长(秒)", cellType = Excel.ColumnType.NUMERIC) private Integer duration; - @ApiModelProperty("处理状态:1-待处理 2-处理中 3-已关闭 4-已忽略") - @Excel(name = "处理状态", readConverterExp = "1=待处理,2=处理中,3=已关闭,4=已忽略") + @ApiModelProperty("处理状态:1-待处理 2已关闭") + @Excel(name = "处理状态", readConverterExp = "1=待处理,2=已关闭") private Integer handleStatus; @ApiModelProperty("处理人ID") @@ -111,4 +115,6 @@ public class Alarm extends TenantBaseDO { private Long siteId; private Long orgId; + + private AlarmHandleResult handleResult; } diff --git a/maibu-common/src/main/java/com/maibu/core/business/alarm_center/AlarmMessage.java b/maibu-common/src/main/java/com/maibu/core/business/alarm_center/AlarmMessage.java index a32725a..23d65e8 100644 --- a/maibu-common/src/main/java/com/maibu/core/business/alarm_center/AlarmMessage.java +++ b/maibu-common/src/main/java/com/maibu/core/business/alarm_center/AlarmMessage.java @@ -6,6 +6,7 @@ import com.fasterxml.jackson.annotation.JsonFormat; import com.maibu.core.enums.ErrorLevel; import lombok.Data; +import org.springframework.format.annotation.DateTimeFormat; @Data public class AlarmMessage { @@ -21,6 +22,7 @@ public class AlarmMessage { /** 告警时间 */ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") private LocalDateTime time; /** 设备名称 */ @@ -45,4 +47,6 @@ public class AlarmMessage { private Long orgId; + private String timeValues; + } 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 f4d3317..f4351bc 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 @@ -1,9 +1,12 @@ package com.maibu.core.business.device; +import java.nio.ByteBuffer; +import java.nio.ByteOrder; import java.time.LocalDateTime; import java.util.LinkedList; import java.util.Queue; +import com.maibu.utils.json.JsonUtils; import org.springframework.util.CollectionUtils; import com.fasterxml.jackson.annotation.JsonIgnore; @@ -74,7 +77,7 @@ public class NettyDevice extends Connector { this.deviceType = deviceType; } - // todo 重发 + // todo 如何确定命令已收到? public void sendNextPoint() { if (task.getTaskStaus().equals(DeviceTaskStaus.PAUSE)) return; @@ -139,9 +142,9 @@ public class NettyDevice extends Connector { return true; } - public void sendPathCommand(byte coommadnType, short pointCounts, double lat, double lng, short speed) { + public void sendPathCommand(byte commandType, short pointCounts, double lat, double lng, short speed) { RoutePlanSendEntity routePlanSendEntity = new RoutePlanSendEntity(); - routePlanSendEntity.setCommandType(coommadnType); + routePlanSendEntity.setCommandType(commandType); routePlanSendEntity.setPointCounts(pointCounts); routePlanSendEntity.setTargetLatitude(lat); routePlanSendEntity.setTargetLongitude(lng); @@ -153,6 +156,57 @@ public class NettyDevice extends Connector { } } + //配置左右轮增益系数 + public void sendWheelGainCoefficientsCommand(double leftForwardGain, double leftBackwardGain, double rightForwardGain, double rightBackwardGain) { + ByteBuffer buffer = ByteBuffer.allocate(39); + buffer.order(ByteOrder.LITTLE_ENDIAN); + + buffer.put((byte) 0xAB); + buffer.put((byte) 0xAA); + + buffer.put((byte) 0x13); + + long leftForward = Double.doubleToLongBits(leftForwardGain); + buffer.putLong(leftForward); + + long leftBackward = Double.doubleToLongBits(leftBackwardGain); + buffer.putLong(leftBackward); + + long rightForward = Double.doubleToLongBits(rightForwardGain); + buffer.putLong(rightForward); + + long rightBackward = Double.doubleToLongBits(rightBackwardGain); + buffer.putLong(rightBackward); + + buffer.putShort((short) 0); + + buffer.put((byte) 0xAA); + buffer.put((byte) 0xAB); + + log.debug("下发设置左右轮增益系数报文:{}", toHexString(buffer.array())); + if (this.getChannel() != null && this.getChannel().isActive()) { + this.getChannel().writeAndFlush(Unpooled.wrappedBuffer(buffer.array())); + } + } + + + public void readConfigCommand() { + byte[] bytes = DeviceRunParam.toReadBytes(); + log.debug("下发读取配置的报文:{}", toHexString(bytes)); + if (this.getChannel() != null && this.getChannel().isActive()) { + this.getChannel().writeAndFlush(Unpooled.wrappedBuffer(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)); + } + } + // todo 优化 public synchronized boolean pauseTask() { if (executingTask) { diff --git a/maibu-common/src/main/java/com/maibu/core/business/dto/AlarmHandleDTO.java b/maibu-common/src/main/java/com/maibu/core/business/dto/AlarmHandleDTO.java index 5ae57d9..2ad4db0 100644 --- a/maibu-common/src/main/java/com/maibu/core/business/dto/AlarmHandleDTO.java +++ b/maibu-common/src/main/java/com/maibu/core/business/dto/AlarmHandleDTO.java @@ -1,5 +1,6 @@ package com.maibu.core.business.dto; +import com.maibu.core.enums.AlarmHandleResult; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; @@ -11,7 +12,7 @@ public class AlarmHandleDTO { @ApiModelProperty("告警ID") private Long alarmId; - @ApiModelProperty("处理状态:2-处理中 3-已关闭 4-已忽略") + @ApiModelProperty("处理状态:1-待处理 2已关闭") private Integer handleStatus; @ApiModelProperty("处理备注") @@ -19,4 +20,7 @@ public class AlarmHandleDTO { @ApiModelProperty("根因分析") private String rootCause; + + @ApiModelProperty("处理结果") + private AlarmHandleResult handleResult; } diff --git a/maibu-common/src/main/java/com/maibu/core/business/dto/AlarmQueryDTO.java b/maibu-common/src/main/java/com/maibu/core/business/dto/AlarmQueryDTO.java index 23ac69c..78522d7 100644 --- a/maibu-common/src/main/java/com/maibu/core/business/dto/AlarmQueryDTO.java +++ b/maibu-common/src/main/java/com/maibu/core/business/dto/AlarmQueryDTO.java @@ -39,4 +39,6 @@ public class AlarmQueryDTO extends BaseEntity { @ApiModelProperty("场站ID") private Long siteId; + + private Integer handleStatus; } diff --git a/maibu-common/src/main/java/com/maibu/core/business/dto/WorkOrderQueryDTO.java b/maibu-common/src/main/java/com/maibu/core/business/dto/WorkOrderQueryDTO.java index 01d5143..1404014 100644 --- a/maibu-common/src/main/java/com/maibu/core/business/dto/WorkOrderQueryDTO.java +++ b/maibu-common/src/main/java/com/maibu/core/business/dto/WorkOrderQueryDTO.java @@ -6,8 +6,10 @@ import lombok.Data; import java.time.LocalDateTime; -import javax.lang.model.type.ErrorType; +import org.springframework.format.annotation.DateTimeFormat; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.maibu.core.enums.ErrorLevel; import com.maibu.core.enums.OrderType; @Data @@ -27,7 +29,7 @@ public class WorkOrderQueryDTO { private OrderType orderType; @ApiModelProperty("优先级") - private ErrorType priorityLevel; + private ErrorLevel priorityLevel; @ApiModelProperty("负责人 ID") private Long assigneeId; @@ -44,10 +46,12 @@ public class WorkOrderQueryDTO { @ApiModelProperty("工单状态") private Integer orderStatus; - @ApiModelProperty("开始时间") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") private LocalDateTime startTime; - @ApiModelProperty("结束时间") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") private LocalDateTime endTime; @ApiModelProperty("搜索关键词") diff --git a/maibu-common/src/main/java/com/maibu/core/business/inter/mower/MowerCommandDispather.java b/maibu-common/src/main/java/com/maibu/core/business/inter/mower/MowerCommandDispather.java index 61358b7..0340e5c 100644 --- a/maibu-common/src/main/java/com/maibu/core/business/inter/mower/MowerCommandDispather.java +++ b/maibu-common/src/main/java/com/maibu/core/business/inter/mower/MowerCommandDispather.java @@ -15,12 +15,14 @@ public class MowerCommandDispather { @Resource private ApplicationContext applicationContext; - public void dispathDeviceTask(DeviceTaskCommandDTO dto) { + public Long dispathDeviceTask(DeviceTaskCommandDTO dto) { Map beanMap = applicationContext.getBeansOfType(MowerCommandInter.class); // 遍历 - beanMap.values().forEach(x -> { - x.createDeviceTask(dto); - }); + Long id = null; + for (MowerCommandInter value : beanMap.values()) { + id = value.createDeviceTask(dto); + } + return id; } } diff --git a/maibu-common/src/main/java/com/maibu/core/business/inter/mower/MowerCommandInter.java b/maibu-common/src/main/java/com/maibu/core/business/inter/mower/MowerCommandInter.java index b60f7c6..23f3851 100644 --- a/maibu-common/src/main/java/com/maibu/core/business/inter/mower/MowerCommandInter.java +++ b/maibu-common/src/main/java/com/maibu/core/business/inter/mower/MowerCommandInter.java @@ -4,6 +4,6 @@ import com.maibu.core.business.dto.DeviceTaskCommandDTO; public interface MowerCommandInter { - void createDeviceTask(DeviceTaskCommandDTO dto); + Long createDeviceTask(DeviceTaskCommandDTO dto); } diff --git a/maibu-common/src/main/java/com/maibu/core/business/inter/uav/UAVCommandDispather.java b/maibu-common/src/main/java/com/maibu/core/business/inter/uav/UAVCommandDispather.java index 9ba5234..c917b8f 100644 --- a/maibu-common/src/main/java/com/maibu/core/business/inter/uav/UAVCommandDispather.java +++ b/maibu-common/src/main/java/com/maibu/core/business/inter/uav/UAVCommandDispather.java @@ -15,12 +15,14 @@ public class UAVCommandDispather { @Resource private ApplicationContext applicationContext; - public void dispathFightTask(FlightTaskCreateDTO dto) { + public String dispathFightTask(FlightTaskCreateDTO dto) { Map beanMap = applicationContext.getBeansOfType(UAVCommandInter.class); // 遍历 - beanMap.values().forEach(x -> { - x.createFlightTask(dto); - }); + String taskId = null; + for (UAVCommandInter value : beanMap.values()) { + taskId = value.createFlightTask(dto); + } + return taskId; } } diff --git a/maibu-common/src/main/java/com/maibu/core/business/inter/uav/UAVCommandInter.java b/maibu-common/src/main/java/com/maibu/core/business/inter/uav/UAVCommandInter.java index ff80362..278f218 100644 --- a/maibu-common/src/main/java/com/maibu/core/business/inter/uav/UAVCommandInter.java +++ b/maibu-common/src/main/java/com/maibu/core/business/inter/uav/UAVCommandInter.java @@ -4,6 +4,6 @@ import com.maibu.core.business.dto.uav.FlightTaskCreateDTO; public interface UAVCommandInter { - void createFlightTask(FlightTaskCreateDTO dto); + String createFlightTask(FlightTaskCreateDTO dto); } 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 6805e22..54732b1 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 @@ -41,4 +41,6 @@ public class SysSite extends BaseDO { private String dingTalkToken; // 钉钉推送token + private boolean dingTalkOrderPush = false;// 工单是否推送 + } diff --git a/maibu-common/src/main/java/com/maibu/core/enums/AlarmHandleResult.java b/maibu-common/src/main/java/com/maibu/core/enums/AlarmHandleResult.java new file mode 100644 index 0000000..dc2a414 --- /dev/null +++ b/maibu-common/src/main/java/com/maibu/core/enums/AlarmHandleResult.java @@ -0,0 +1,31 @@ +package com.maibu.core.enums; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +@Getter +@AllArgsConstructor +public enum AlarmHandleResult { + + Handled("Handled", "已处理"), + + Restored("Restored", "已恢复"), + + Ignored("Ignored", "已忽略"), + + UnableToHandle("UnableToHandle", "无法处理"), + + ManufacturerHandling("ManufacturerHandling", "厂家处理中"), + + FalseAlarm("FalseAlarm", "误报"); + + /** + * 错误来源值(存储在数据库中) + */ + private final String value; + + /** + * 错误来源名称(用于前端显示) + */ + private final String name; +} diff --git a/maibu-common/src/main/java/com/maibu/core/enums/AlarmType.java b/maibu-common/src/main/java/com/maibu/core/enums/AlarmType.java new file mode 100644 index 0000000..29c5b0c --- /dev/null +++ b/maibu-common/src/main/java/com/maibu/core/enums/AlarmType.java @@ -0,0 +1,27 @@ +package com.maibu.core.enums; + +import com.maibu.annotation.Excel; +import lombok.AllArgsConstructor; +import lombok.Getter; + +@Getter +@AllArgsConstructor +public enum AlarmType { + + UAV_FAULT("UAV_FAULT", "无人机故障"), + + MOWER_FAULT("MOWER_FAULT", "割草机故障"), + + OTHER_DEVICE_FAULT("OTHER_DEVICE_FAULT", "其他设备故障"), + + SERVER_FAILURE("SERVER_FAILURE", "服务器故障"), + + SYSTEM_ERROR("SYSTEM_ERROR", "系统错误"); + + /** 错误来源值(存储在数据库中) */ + private final String value; + + /** 错误来源名称(用于前端显示) */ + private final String name; + +} diff --git a/maibu-netty-server/src/main/java/com/maibu/manager/DeviceSessionManager.java b/maibu-common/src/main/java/com/maibu/memory/DeviceSessionManager.java similarity index 99% rename from maibu-netty-server/src/main/java/com/maibu/manager/DeviceSessionManager.java rename to maibu-common/src/main/java/com/maibu/memory/DeviceSessionManager.java index 8ad22cb..3bf3056 100644 --- a/maibu-netty-server/src/main/java/com/maibu/manager/DeviceSessionManager.java +++ b/maibu-common/src/main/java/com/maibu/memory/DeviceSessionManager.java @@ -1,11 +1,11 @@ -package com.maibu.manager; +package com.maibu.memory; import cn.hutool.core.util.ObjectUtil; -import com.maibu.core.enums.ConnectorStatus; -import com.maibu.core.enums.ConnectorType; import com.maibu.core.business.device.Connector; import com.maibu.core.business.device.NettyDevice; +import com.maibu.core.enums.ConnectorStatus; +import com.maibu.core.enums.ConnectorType; import io.netty.channel.Channel; import lombok.Data; import org.apache.commons.lang3.StringUtils; diff --git a/maibu-common/src/main/java/com/maibu/memory/GlobalMemory.java b/maibu-common/src/main/java/com/maibu/memory/GlobalMemory.java index 9dab0a5..f9ce05e 100644 --- a/maibu-common/src/main/java/com/maibu/memory/GlobalMemory.java +++ b/maibu-common/src/main/java/com/maibu/memory/GlobalMemory.java @@ -35,6 +35,8 @@ public class GlobalMemory { public static MqttClientUtil mqttClientUtil; + + public static SiteMemory getSiteMemory(Long orgId, Long siteId) { if (orgId != null && siteId != null) { Map siteMemories = orgAttrs.get(orgId); 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 2d7247e..ea3f56f 100644 --- a/maibu-common/src/main/java/com/maibu/memory/SiteMemory.java +++ b/maibu-common/src/main/java/com/maibu/memory/SiteMemory.java @@ -35,7 +35,7 @@ public class SiteMemory { public SysSite sysSite; - public static final ConcurrentHashMap ordrModelMap = new ConcurrentHashMap<>(); + public static final ConcurrentHashMap orderModelMap = new ConcurrentHashMap<>(); public static final ConcurrentHashMap orderConfigMap = new ConcurrentHashMap<>(); @@ -87,7 +87,19 @@ public class SiteMemory { if (CollectionUtils.isEmpty(list)) { list = new ArrayList<>(); } - list.add(errorIdentificationStandard); + // 替换已存在的记录,兼容后续保存 + int index = -1; + for (int i = 0; i < list.size(); i++) { + if (Objects.equals(list.get(i).getErrorCode(), errorIdentificationStandard.getErrorCode())){ + index = i; + break; + } + } + if (index >= 0) { + list.set(index, errorIdentificationStandard); + } else { + list.add(errorIdentificationStandard); + } standards.put(errorIdentificationStandard.getErrorSource(), list); } @@ -108,19 +120,19 @@ public class SiteMemory { } public void saveOrderModel(OrderModel orderModel) { - ordrModelMap.put(orderModel.getId(), orderModel); + orderModelMap.put(orderModel.getId(), orderModel); } public OrderModel getOrderModel(Long id) { if (id != null) { - return ordrModelMap.get(id); + return orderModelMap.get(id); } return null; } public void removeOrderModel(Long id) { if (id != null) { - ordrModelMap.remove(id); + orderModelMap.remove(id); } } 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 53191e8..d926eb1 100644 --- a/maibu-common/src/main/java/com/maibu/mqtt/MqttTopic.java +++ b/maibu-common/src/main/java/com/maibu/mqtt/MqttTopic.java @@ -1,15 +1,108 @@ package com.maibu.mqtt; + public class MqttTopic { - public static final String DEVICE_STATUS_TOPIC = "device/%s/realTimeMessage"; // 实时消息 + /** @deprecated 通用设备主题,建议使用 MOWER_* 系列主题 */ + public static final String DEVICE_STATUS_TOPIC = "device/%s/realTimeMessage"; + /** @deprecated 通用设备主题,建议使用 MOWER_* 系列主题 */ + public static final String DEVICE_TASK_STATUS_TOPIC = "task/%s/status"; + /** @deprecated 通用设备主题,建议使用 MOWER_* 系列主题 */ + public static final String DEVICE_TASK_ARRIVE_TOPIC = "task/%s/arrive"; + /** @deprecated 通用设备主题,建议使用 MOWER_* 系列主题 */ + public static final String DEVICE_ERROR_PUSH_TOPIC = "device/%s/error"; - public static final String DEVICE_TASK_STATUS_TOPIC = "task/%s/status"; // 任务状态 完成、取消、暂停、继续 + /** 产品标识:割草机 */ + public static final String MOWER_PRODUCT = "mower"; - public static final String DEVICE_TASK_ARRIVE_TOPIC = "task/%s/arrive"; // 任务到达 + // ==================== 设备连接与状态 ==================== + /** 设备上线/下线事件上报(设备->平台),对应 TCP 0x03 connect */ + public static final String MOWER_STATUS_POST = "mower/%s/event/status/post"; + /** 状态变更确认回复(平台->设备) */ +// public static final String MOWER_STATUS_REPLY = "mower/%s/event/status/reply"; - public static final String DEVICE_ERROR_PUSH_TOPIC = "device/%s/error"; // 设备错误推送 + // ==================== 实时运行数据 ==================== + /** 实时运行数据上报:电压/速度/温度/位置等(设备->平台),对应 TCP 0x02 status */ + public static final String MOWER_REALTIME_POST = "mower/%s/property/realtime/post"; + // ==================== 心跳保活 ==================== + /** 设备心跳上报(设备->平台),对应 TCP 0xFF heartbeat */ + public static final String MOWER_HEARTBEAT_POST = "mower/%s/event/heartbeat/post"; + /** 心跳确认回复(平台->设备) */ + public static final String MOWER_HEARTBEAT_REPLY = "mower/%s/event/heartbeat/reply"; -} - \ No newline at end of file + // ==================== 参数配置 ==================== + /** 下发读取配置请求(平台->设备),对应 TCP 0x05 readConfig */ + public static final String MOWER_CONFIG_GET = "mower/%s/action/config/get"; + /** 下发配置修改指令(平台->设备),对应 TCP 0x06 writeConfig */ + public static final String MOWER_CONFIG_SET = "mower/%s/action/config/set"; + /** 配置读取/修改响应(设备->平台) */ + public static final String MOWER_CONFIG_REPLY = "mower/%s/action/config/reply"; + + // ==================== 远程控制 ==================== + /** 远程控制指令下发:前进/后退/转向/割草等(平台->设备),对应 TCP 0x00 remoteControl */ + 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 */ + public static final String MOWER_TASK_ROUTE_SET = "mower/%s/task/route/set"; + public static final String MOWER_TASK_ROUTE_POST = "mower/%s/task/route/post"; + /** 启动任务执行(平台->设备),对应 TCP 0x12 interaction */ + 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_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"; + + // ==================== OTA 固件升级 ==================== +// /** 下发 OTA 升级指令(平台->设备) */ +// public static final String MOWER_OTA_UPGRADE_SET = "mower/%s/ota/upgrade/set"; +// /** OTA 升级进度上报(设备->平台) */ +// public static final String MOWER_OTA_PROGRESS_POST = "mower/%s/ota/progress/post"; +// /** OTA 升级结果上报(设备->平台) */ +// public static final String MOWER_OTA_RESULT_POST = "mower/%s/ota/result/post"; + + // ==================== 设备信息 ==================== +// /** 查询设备信息(平台->设备) */ +// public static final String MOWER_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_VERSION_POST = "mower/%s/info/version/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_ERROR = "mower/+/event/error/post"; + /** 订阅所有设备的任务状态变更 */ + public static final String MOWER_WILDCARD_TASK_STATUS = "mower/+/task/status/post"; + + /** + * 格式化 Topic 模板,将 %s 替换为设备ID + * + * @param template Topic 模板,如 {@link #MOWER_REALTIME_POST} + * @param deviceId 设备ID + * @return 格式化后的完整 Topic + */ + public static String formatTopic(String template, String deviceId) { + return String.format(template, deviceId); + } +} \ No newline at end of file diff --git a/maibu-common/src/main/java/com/maibu/utils/json/JsonUtils.java b/maibu-common/src/main/java/com/maibu/utils/json/JsonUtils.java index 81ca0d5..4b05029 100644 --- a/maibu-common/src/main/java/com/maibu/utils/json/JsonUtils.java +++ b/maibu-common/src/main/java/com/maibu/utils/json/JsonUtils.java @@ -17,6 +17,7 @@ import java.io.IOException; import java.lang.reflect.Type; import java.util.ArrayList; import java.util.List; +import java.util.Map; /** * JSON 工具类 @@ -87,10 +88,11 @@ public class JsonUtils { /** * 将字符串解析成指定类型的对象 - * 使用 {@link #parseObject(String, Class)} 时,在@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS) 的场景下, + * 使用 {@link #parseObject(String, Class)} 时,在@JsonTypeInfo(use = + * JsonTypeInfo.Id.CLASS) 的场景下, * 如果 text 没有 class 属性,则会报错。此时,使用这个方法,可以解决。 * - * @param text 字符串 + * @param text 字符串 * @param clazz 类型 * @return 对象 */ @@ -127,7 +129,8 @@ public class JsonUtils { return new ArrayList<>(); } try { - return objectMapper.readValue(text, objectMapper.getTypeFactory().constructCollectionType(List.class, clazz)); + return objectMapper.readValue(text, + objectMapper.getTypeFactory().constructCollectionType(List.class, clazz)); } catch (IOException e) { log.error("json parse err,json:{}", text, e); throw new RuntimeException(e); diff --git a/maibu-external/src/main/java/com/maibu/uav/service/UAVCommamdHandler.java b/maibu-external/src/main/java/com/maibu/uav/service/UAVCommamdHandler.java index a6280d6..06bc1e7 100644 --- a/maibu-external/src/main/java/com/maibu/uav/service/UAVCommamdHandler.java +++ b/maibu-external/src/main/java/com/maibu/uav/service/UAVCommamdHandler.java @@ -1,10 +1,15 @@ package com.maibu.uav.service; +import java.util.Map; + import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; +import com.fasterxml.jackson.databind.ObjectMapper; import com.maibu.core.business.dto.uav.FlightTaskCreateDTO; import com.maibu.core.business.inter.uav.UAVCommandInter; +import com.maibu.uav.dto.SK2ResultDTO; +import com.maibu.utils.json.JsonUtils; @Component public class UAVCommamdHandler implements UAVCommandInter { @@ -13,8 +18,18 @@ public class UAVCommamdHandler implements UAVCommandInter { private UAVService uService; @Override - public void createFlightTask(FlightTaskCreateDTO dto){ - uService.createFlightTask(dto); + public String createFlightTask(FlightTaskCreateDTO dto) { + String json = uService.createFlightTask(dto); + SK2ResultDTO res = JsonUtils.parseObject(json, SK2ResultDTO.class); + String taskId = null; + if (res != null && res.getData() != null) { + ObjectMapper objectMapper = new ObjectMapper(); + Map map = objectMapper.convertValue( + res.getData(), + Map.class); + taskId = (String) map.get("task_uuid"); + } + return taskId; } } diff --git a/maibu-iotDA/src/main/java/com/maibu/utils/IoTDAMqttClient.java b/maibu-iotDA/src/main/java/com/maibu/utils/IoTDAMqttClient.java index 5981d64..b652c12 100644 --- a/maibu-iotDA/src/main/java/com/maibu/utils/IoTDAMqttClient.java +++ b/maibu-iotDA/src/main/java/com/maibu/utils/IoTDAMqttClient.java @@ -11,7 +11,7 @@ import com.maibu.core.business.DeviceRunningStatusHistory; import com.maibu.core.business.DeviceStatusRecordDTO; import com.maibu.core.redis.RedisCache; import com.maibu.core.business.device.NettyDevice; -import com.maibu.manager.DeviceSessionManager; +import com.maibu.memory.DeviceSessionManager; import com.maibu.utils.spring.SpringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/maibu-netty-server/src/main/java/com/maibu/common/CommandConstant.java b/maibu-netty-server/src/main/java/com/maibu/common/CommandConstant.java deleted file mode 100644 index 343bac9..0000000 --- a/maibu-netty-server/src/main/java/com/maibu/common/CommandConstant.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.maibu.common; - -public class CommandConstant { - - public static byte remoteControl = (byte)0x00; - - public static byte heartbeat = (byte)0xff; - - public static byte path = (byte)0x01; - - public static byte status = (byte)0x02; - - public static byte connect = (byte)0x03; - - public static byte interaction = (byte)0x12; //主要用于推送状态消息等 -} diff --git a/maibu-netty-server/src/main/java/com/maibu/controller/DeviceExternalApiController.java b/maibu-netty-server/src/main/java/com/maibu/controller/DeviceExternalApiController.java index 834a85f..6c60f64 100644 --- a/maibu-netty-server/src/main/java/com/maibu/controller/DeviceExternalApiController.java +++ b/maibu-netty-server/src/main/java/com/maibu/controller/DeviceExternalApiController.java @@ -1,11 +1,11 @@ package com.maibu.controller; -import com.maibu.common.CommandConstant; +import com.maibu.constant.CommandConstant; import com.maibu.core.controller.BaseController; import com.maibu.core.domain.AjaxResult; import com.maibu.core.business.device.NettyDevice; import com.maibu.dto.ObstacleData; -import com.maibu.manager.DeviceSessionManager; +import com.maibu.memory.DeviceSessionManager; import com.maibu.utils.CommandUtils; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; diff --git a/maibu-netty-server/src/main/java/com/maibu/controller/DeviceMemoryController.java b/maibu-netty-server/src/main/java/com/maibu/controller/DeviceMemoryController.java index 5a68a7a..af97dd9 100644 --- a/maibu-netty-server/src/main/java/com/maibu/controller/DeviceMemoryController.java +++ b/maibu-netty-server/src/main/java/com/maibu/controller/DeviceMemoryController.java @@ -1,6 +1,6 @@ package com.maibu.controller; -import com.maibu.manager.DeviceSessionManager; +import com.maibu.memory.DeviceSessionManager; import com.maibu.memory.GlobalMemory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; diff --git a/maibu-netty-server/src/main/java/com/maibu/controller/NettyDeviceController.java b/maibu-netty-server/src/main/java/com/maibu/controller/NettyDeviceController.java index fcf041d..5ed7411 100644 --- a/maibu-netty-server/src/main/java/com/maibu/controller/NettyDeviceController.java +++ b/maibu-netty-server/src/main/java/com/maibu/controller/NettyDeviceController.java @@ -5,6 +5,7 @@ import com.maibu.core.controller.BaseController; import com.maibu.core.domain.AjaxResult; import com.maibu.core.page.TableDataInfo; import com.maibu.core.business.ErrorIdentificationStandard; +import com.maibu.dto.SendCommandDTO; import com.maibu.service.NettyDeviceService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; @@ -19,26 +20,29 @@ public class NettyDeviceController extends BaseController { private NettyDeviceService nettyDeviceService; @GetMapping("/statusHistory") - public TableDataInfo statusHistory(DeviceRunningStatusHistory history) - { + public TableDataInfo statusHistory(DeviceRunningStatusHistory history) { startPage(); List list = nettyDeviceService.statusHistory(history); return getDataTable(list); } @GetMapping("/getErrorIdentification") - public TableDataInfo getErrorIdentification() - { + public TableDataInfo getErrorIdentification() { startPage(); List list = nettyDeviceService.allErrorIdentificationStandard(); return getDataTable(list); } @PostMapping("/updateErrorIdentification") - public AjaxResult updateErrorIdentification(@RequestBody ErrorIdentificationStandard standard) - { - int i = nettyDeviceService.updateErrorIdentification(standard); + public AjaxResult updateErrorIdentification(@RequestBody ErrorIdentificationStandard standard) { + int i = nettyDeviceService.updateErrorIdentification(standard); return AjaxResult.success(i); } + @PostMapping("/sendCommand") + public AjaxResult sendCommand(@RequestBody SendCommandDTO command) { + nettyDeviceService.sendCommand(command); + return AjaxResult.success(); + } + } diff --git a/maibu-netty-server/src/main/java/com/maibu/dto/SendCommandDTO.java b/maibu-netty-server/src/main/java/com/maibu/dto/SendCommandDTO.java new file mode 100644 index 0000000..fa27b2f --- /dev/null +++ b/maibu-netty-server/src/main/java/com/maibu/dto/SendCommandDTO.java @@ -0,0 +1,16 @@ +package com.maibu.dto; + +import lombok.Data; + +import java.util.List; +import java.util.Map; + +@Data +public class SendCommandDTO { + + private String commandType; + + private Map params; + + private List deviceIds; +} diff --git a/maibu-netty-server/src/main/java/com/maibu/handler/MowerCommamdHandler.java b/maibu-netty-server/src/main/java/com/maibu/handler/MowerCommamdHandler.java index 6da9a23..c8e3296 100644 --- a/maibu-netty-server/src/main/java/com/maibu/handler/MowerCommamdHandler.java +++ b/maibu-netty-server/src/main/java/com/maibu/handler/MowerCommamdHandler.java @@ -4,9 +4,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import com.maibu.core.business.dto.DeviceTaskCommandDTO; -import com.maibu.core.business.dto.uav.FlightTaskCreateDTO; import com.maibu.core.business.inter.mower.MowerCommandInter; -import com.maibu.core.business.inter.uav.UAVCommandInter; import com.maibu.service.DeviceTaskService; @Component @@ -16,8 +14,8 @@ public class MowerCommamdHandler implements MowerCommandInter { private DeviceTaskService dService; @Override - public void createDeviceTask(DeviceTaskCommandDTO dto) { - dService.createDeviceTask(dto, "system"); + public Long createDeviceTask(DeviceTaskCommandDTO dto) { + return dService.createDeviceTask(dto, "system"); } } 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 ae5e323..e6bf684 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 @@ -162,7 +162,7 @@ public class InitThread implements ApplicationRunner { if (!CollectionUtils.isEmpty(deviceRunParamList)) { deviceRunParamList.forEach(x -> { Long orgId = x.getOrgId(); - Long siteId = x.getId(); + Long siteId = x.getSiteId(); SiteMemory siteMemory = GlobalMemory.getSiteMemory(orgId, siteId); if (siteMemory != null) { siteMemory.saveDeviceRunParam(x); @@ -174,7 +174,7 @@ public class InitThread implements ApplicationRunner { if (!CollectionUtils.isEmpty(standadList)) { standadList.forEach(x -> { Long orgId = x.getOrgId(); - Long siteId = x.getId(); + Long siteId = x.getSiteId(); SiteMemory siteMemory = GlobalMemory.getSiteMemory(orgId, siteId); if (siteMemory != null) { siteMemory.saveErrorIdentificationStandard(x); @@ -186,7 +186,7 @@ public class InitThread implements ApplicationRunner { if (!CollectionUtils.isEmpty(orderModelList)) { orderModelList.forEach(x -> { Long orgId = x.getOrgId(); - Long siteId = x.getId(); + Long siteId = x.getSiteId(); SiteMemory siteMemory = GlobalMemory.getSiteMemory(orgId, siteId); if (siteMemory != null) { siteMemory.saveOrderModel(x); @@ -198,7 +198,7 @@ public class InitThread implements ApplicationRunner { if (!CollectionUtils.isEmpty(alarmOrderList)) { alarmOrderList.forEach(x -> { Long orgId = x.getOrgId(); - Long siteId = x.getId(); + Long siteId = x.getSiteId(); SiteMemory siteMemory = GlobalMemory.getSiteMemory(orgId, siteId); if (siteMemory != null) { siteMemory.saveAlarmOrderConfig(x); diff --git a/maibu-netty-server/src/main/java/com/maibu/netty/handler/CommandForwardHandler.java b/maibu-netty-server/src/main/java/com/maibu/netty/handler/CommandForwardHandler.java index d08f171..2575929 100644 --- a/maibu-netty-server/src/main/java/com/maibu/netty/handler/CommandForwardHandler.java +++ b/maibu-netty-server/src/main/java/com/maibu/netty/handler/CommandForwardHandler.java @@ -3,6 +3,7 @@ package com.maibu.netty.handler; import java.util.List; import java.util.Set; +import com.maibu.memory.DeviceSessionManager; import org.apache.commons.codec.binary.Hex; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -10,11 +11,10 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import org.springframework.util.CollectionUtils; -import com.maibu.common.CommandConstant; +import com.maibu.constant.CommandConstant; import com.maibu.core.business.device.Connector; import com.maibu.core.business.device.NettyDevice; import com.maibu.core.enums.ConnectorType; -import com.maibu.manager.DeviceSessionManager; import io.netty.buffer.ByteBuf; import io.netty.channel.Channel; @@ -36,7 +36,10 @@ public class CommandForwardHandler extends SimpleChannelInboundHandler { protected void channelRead0(ChannelHandlerContext ctx, String msg) throws Exception { Channel currentChannel = ctx.channel(); byte[] bytes = Hex.decodeHex(msg.toCharArray()); - if (bytes.length > 3 && (bytes[2] == CommandConstant.remoteControl || bytes[2] == CommandConstant.path || bytes[2] == CommandConstant.status)) { + if (bytes.length > 3 && (bytes[2] == CommandConstant.remoteControl + || bytes[2] == CommandConstant.path + || bytes[2] == CommandConstant.status + )) { String senderDeviceId = deviceSessionManager.getDeviceIdByChannel(currentChannel); NettyDevice senderNettyDevice = diff --git a/maibu-netty-server/src/main/java/com/maibu/netty/handler/DataToDataBaseHandler.java b/maibu-netty-server/src/main/java/com/maibu/netty/handler/DataToDataBaseHandler.java index 44b8907..87760a1 100644 --- a/maibu-netty-server/src/main/java/com/maibu/netty/handler/DataToDataBaseHandler.java +++ b/maibu-netty-server/src/main/java/com/maibu/netty/handler/DataToDataBaseHandler.java @@ -7,7 +7,13 @@ import java.time.LocalDateTime; import java.util.ArrayList; import java.util.Date; import java.util.List; +import java.util.concurrent.CompletableFuture; +import com.maibu.constant.Constant; +import com.maibu.core.business.DeviceRunParam; +import com.maibu.mapper.DeviceRunParamMapper; +import com.maibu.memory.DeviceSessionManager; +import com.maibu.memory.SiteMemory; import org.apache.commons.codec.binary.Hex; import org.apache.commons.lang3.StringUtils; import org.eclipse.paho.client.mqttv3.MqttException; @@ -17,7 +23,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import org.springframework.util.CollectionUtils; -import com.maibu.common.CommandConstant; +import com.maibu.constant.CommandConstant; import com.maibu.common.NettyCacheKey; import com.maibu.core.business.DeviceRunStatistics; import com.maibu.core.business.DeviceRunningStatusHistory; @@ -30,7 +36,6 @@ import com.maibu.core.redis.RedisCache; import com.maibu.dto.WebStatusMessageDTO; import com.maibu.influxdb.MowerRealTimeData; import com.maibu.influxdb.util.InfluxSqlBuilder; -import com.maibu.manager.DeviceSessionManager; import com.maibu.memory.GlobalMemory; import com.maibu.mqtt.MqttTopic; import com.maibu.utils.json.JsonUtils; @@ -55,6 +60,9 @@ public class DataToDataBaseHandler extends SimpleChannelInboundHandler { @Autowired private WebsocketMesDispather websocketMesDispather; + @Autowired + private DeviceRunParamMapper deviceRunParamMapper; + private static final Long recordInterval = 5000L; // 5秒记录一次 // private static final Long pushInterval = 500L; // 0.5秒推送一次 @@ -136,6 +144,15 @@ public class DataToDataBaseHandler extends SimpleChannelInboundHandler { latestStatus.setWorkArea(Double.valueOf(workArea)); nettyDevice.setLatestStatus(latestStatus); } + } else if (bytes[2] == CommandConstant.readConfig) { + DeviceRunParam runParam = DeviceRunParam.fromBytes(bytes); + logger.debug("收到返回的设备运行参数: {}", JsonUtils.toJsonString(runParam)); + CompletableFuture future = + ctx.channel().attr(Constant.READ_CONFIG_KEY).get(); + if (future != null) { + future.complete(runParam); + ctx.channel().attr(Constant.READ_CONFIG_KEY).set(null); + } } ctx.fireChannelRead(msg); } catch (Exception e) { @@ -143,6 +160,7 @@ public class DataToDataBaseHandler extends SimpleChannelInboundHandler { } } + public WebStatusMessageDTO createWebDeviceStatusMessage(String[] split) { WebStatusMessageDTO webStatusMessageDTO = new WebStatusMessageDTO(); List transferData = transferStatusData(split); diff --git a/maibu-netty-server/src/main/java/com/maibu/netty/handler/DeviceConnectHandler.java b/maibu-netty-server/src/main/java/com/maibu/netty/handler/DeviceConnectHandler.java index cc6a0fc..3744165 100644 --- a/maibu-netty-server/src/main/java/com/maibu/netty/handler/DeviceConnectHandler.java +++ b/maibu-netty-server/src/main/java/com/maibu/netty/handler/DeviceConnectHandler.java @@ -8,6 +8,7 @@ import java.util.concurrent.ConcurrentHashMap; import javax.annotation.Resource; +import com.maibu.memory.DeviceSessionManager; import org.apache.commons.codec.binary.Hex; import org.apache.commons.lang3.StringUtils; import org.eclipse.paho.client.mqttv3.MqttException; @@ -17,8 +18,8 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import org.springframework.util.CollectionUtils; -import com.maibu.common.CommandConstant; -import com.maibu.common.Constant; +import com.maibu.constant.CommandConstant; +import com.maibu.constant.Constant; import com.maibu.core.business.Device; import com.maibu.core.business.device.NettyDevice; import com.maibu.core.business.inter.WebsocketMesDispather; @@ -37,7 +38,6 @@ import com.maibu.dto.DeviceRequestDTO; import com.maibu.dto.DeviceRespondDTO; import com.maibu.dto.DeviceStatusChangeDTO; import com.maibu.dto.DeviceTaskStatusMessageDTO; -import com.maibu.manager.DeviceSessionManager; import com.maibu.mapper.DeviceRunStatisticsMapper; import com.maibu.memory.GlobalMemory; import com.maibu.mqtt.MqttTopic; diff --git a/maibu-netty-server/src/main/java/com/maibu/netty/handler/HeartbeatHandler.java b/maibu-netty-server/src/main/java/com/maibu/netty/handler/HeartbeatHandler.java index 4baff7b..8c26224 100644 --- a/maibu-netty-server/src/main/java/com/maibu/netty/handler/HeartbeatHandler.java +++ b/maibu-netty-server/src/main/java/com/maibu/netty/handler/HeartbeatHandler.java @@ -1,8 +1,8 @@ package com.maibu.netty.handler; -import com.maibu.common.Constant; -import com.maibu.manager.DeviceSessionManager; +import com.maibu.constant.Constant; +import com.maibu.memory.DeviceSessionManager; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.ChannelHandler; diff --git a/maibu-netty-server/src/main/java/com/maibu/netty/handler/HexDecoder.java b/maibu-netty-server/src/main/java/com/maibu/netty/handler/HexDecoder.java index 6ec3ff0..0d92729 100644 --- a/maibu-netty-server/src/main/java/com/maibu/netty/handler/HexDecoder.java +++ b/maibu-netty-server/src/main/java/com/maibu/netty/handler/HexDecoder.java @@ -1,7 +1,7 @@ package com.maibu.netty.handler; -import com.maibu.common.CommandConstant; -import com.maibu.common.Constant; +import com.maibu.constant.CommandConstant; +import com.maibu.constant.Constant; import io.netty.buffer.ByteBuf; import io.netty.channel.Channel; import io.netty.channel.ChannelHandlerContext; diff --git a/maibu-netty-server/src/main/java/com/maibu/scheduled/ScheduledTask.java b/maibu-netty-server/src/main/java/com/maibu/scheduled/ScheduledTask.java index f2780e7..8ede101 100644 --- a/maibu-netty-server/src/main/java/com/maibu/scheduled/ScheduledTask.java +++ b/maibu-netty-server/src/main/java/com/maibu/scheduled/ScheduledTask.java @@ -2,10 +2,14 @@ package com.maibu.scheduled; import com.maibu.common.NettyCacheKey; import com.maibu.core.business.DevicePlan; +import com.maibu.core.business.DeviceRunParam; import com.maibu.core.business.DeviceStatusRecordDTO; import com.maibu.core.redis.RedisCache; import com.maibu.mapper.DeviceStatusHistoryMapper; import com.maibu.memory.SiteMemory; +import com.maibu.utils.json.JsonUtils; +import org.apache.commons.codec.DecoderException; +import org.apache.commons.codec.binary.Hex; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Component; @@ -70,4 +74,21 @@ public class ScheduledTask { } System.out.println("0点定时刷新状态执行完成"); } + + public static void main(String[] args) throws DecoderException { + String hex = "AB AA 05 88 4D 43 37 30 30 50 4C 55 53 2D 43 4E 2D 4A 53 2D 31 37 38 34 38 37 31 39 37 39 31 39 30 2D 30 30 30 30 30 30 30 41 2D 36 30 00 B1 FB 7F FE FE FE 00 00 00 00 00 00 00 00 00 00 00 00 00 12 01 48 95 E8 03 E8 03 28 32 91 53 24 4D 43 37 30 30 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 31 32 33 34 35 36 37 38 00 00 00 00 00 00 00 00 00 00 00 00 00 08 00 00 00 CD CC A4 41 00 00 80 3F 33 33 33 3F B8 1E 05 3F 33 33 33 3F 9A 99 19 3E 00 00 80 3F 00 00 80 3F 00 00 80 3F 32 36 2D 34 2D 32 37 00 2D 32 37 00 50 B1 BF 00 00 AA AB"; + String cleanHex = hex.replaceAll("\\s+", ""); // 移除所有空白字符 + byte[] bytes = Hex.decodeHex(cleanHex); + DeviceRunParam runParam = DeviceRunParam.fromBytes(bytes); + System.out.println(JsonUtils.toJsonString(runParam)); + + runParam.setLeftBackwardGain(0.2f); + runParam.setLeftForwardGain(0.2f); + runParam.setRightForwardGain(0.2f); + runParam.setRightBackwardGain(0.2f); + + byte[] newB = runParam.toWriteBytes(); + System.out.println(Hex.encodeHexString(newB)); + + } } \ No newline at end of file diff --git a/maibu-netty-server/src/main/java/com/maibu/service/AlertPushService.java b/maibu-netty-server/src/main/java/com/maibu/service/AlertPushService.java index 39d625c..c2a389f 100644 --- a/maibu-netty-server/src/main/java/com/maibu/service/AlertPushService.java +++ b/maibu-netty-server/src/main/java/com/maibu/service/AlertPushService.java @@ -11,6 +11,8 @@ import java.util.concurrent.TimeUnit; import javax.crypto.Mac; import javax.crypto.spec.SecretKeySpec; +import com.maibu.core.business.alarm_center.Alarm; +import com.maibu.memory.DeviceSessionManager; import org.apache.commons.codec.binary.Base64; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @@ -26,7 +28,6 @@ import com.maibu.core.business.alarm_center.AlarmMessage; import com.maibu.core.business.device.NettyDevice; import com.maibu.core.redis.RedisCache; import com.maibu.dto.DeviceErrorPushDTO; -import com.maibu.manager.DeviceSessionManager; import com.maibu.memory.GlobalMemory; import com.maibu.memory.SiteMemory; import com.maibu.service.impl.AlarmServiceImpl; @@ -93,25 +94,37 @@ public class AlertPushService { Boolean exists = redisCache.hasKey(pushKey); if (exists != null && !exists) { newList.add(detail); - redisCache.setCacheObject(pushKey, JsonUtils.toJsonString(detail), 10, - TimeUnit.MINUTES); + redisCache.setCacheObject(pushKey, JsonUtils.toJsonString(detail)); + AlarmOrderConfig config = siteMemory.getAlarmOrderConfig(detail.getNo()); + log.debug("compare config:{}", JsonUtils.toJsonString(config)); + if (config != null && config.isAutoGenerateOrder()) { + IOTWorkOrder workOrder = wService.generateWorkOrders(siteId, deviceId, orgId, config.getModelId(), detail.getNo()); + workOrders.add(workOrder); + } } } - AlarmOrderConfig config = siteMemory.getAlarmOrderConfig(detail.getNo()); - if (config != null && config.isAutoGenerateOrder()) { - IOTWorkOrder workOrder = wService.generateWorkOrders(siteId, deviceId, orgId, orgId); - workOrders.add(workOrder); - } }); + //todo 后续添加配置推送的告警等级 if (alertPush == 1) { - alarmService.pushAlertMes(dto.getDetails()); - } - if (!CollectionUtils.isEmpty(workOrders)) { - wService.saveAll(workOrders); + List alarms = alarmService.pushAlertMes(newList); + log.debug("alarms : {}", JsonUtils.toJsonString(alarms)); + log.debug("workOrders : {}", JsonUtils.toJsonString(workOrders)); + if (!CollectionUtils.isEmpty(workOrders)) { + if (!CollectionUtils.isEmpty(alarms)) { + workOrders.forEach(x -> { + alarms.forEach(y -> { + if (x.getAlarmNo().equals(y.getAlarmNo())) { + x.setAlarmId(y.getId()); + x.setTaskDescription(y.getAlarmContent()); + } + }); + }); + } + wService.saveAll(workOrders); + } } } }); - } } } diff --git a/maibu-netty-server/src/main/java/com/maibu/service/DevicePlanTaskMonitorService.java b/maibu-netty-server/src/main/java/com/maibu/service/DevicePlanTaskMonitorService.java index a9322a4..703d29c 100644 --- a/maibu-netty-server/src/main/java/com/maibu/service/DevicePlanTaskMonitorService.java +++ b/maibu-netty-server/src/main/java/com/maibu/service/DevicePlanTaskMonitorService.java @@ -4,14 +4,13 @@ package com.maibu.service; import com.maibu.core.business.DevicePlan; import com.maibu.core.business.DevicePlanTask; import com.maibu.core.business.DeviceTaskPlanRule; -import com.maibu.core.business.WorkRecord; import com.maibu.core.business.device.NettyDevice; import com.maibu.core.enums.DeviceTaskPlanRepeatType; import com.maibu.core.enums.DeviceTaskStaus; -import com.maibu.manager.DeviceSessionManager; import com.maibu.mapper.DevicePlanMapper; import com.maibu.mapper.DevicePlanTaskMapper; import com.maibu.mapper.WorkRecordMapper; +import com.maibu.memory.DeviceSessionManager; import com.maibu.memory.GlobalMemory; import com.maibu.memory.SiteMemory; import lombok.extern.slf4j.Slf4j; 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 61571a4..d6bbe30 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 @@ -9,6 +9,7 @@ import java.util.List; import java.util.Random; import java.util.stream.Collectors; +import com.maibu.memory.DeviceSessionManager; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @@ -29,7 +30,6 @@ import com.maibu.dto.DevicePlanStatisticsDTO; import com.maibu.dto.DevicePlanTaskStatisticsDTO; import com.maibu.dto.DeviceTaskQueryDTO; import com.maibu.dto.DeviceWorkStatisticsDTO; -import com.maibu.manager.DeviceSessionManager; import com.maibu.mapper.DeviceMapper; import com.maibu.mapper.DevicePlanMapper; import com.maibu.mapper.DevicePlanTaskMapper; @@ -454,7 +454,7 @@ public class DeviceTaskService { return list; } - public boolean createDeviceTask(DeviceTaskCommandDTO dto, String username) { + public Long createDeviceTask(DeviceTaskCommandDTO dto, String username) { DevicePlanTask task = new DevicePlanTask(); task.setOrgId(dto.getOrgId()); task.setSiteId(dto.getSiteId()); @@ -464,7 +464,7 @@ public class DeviceTaskService { task.setCreateTime(LocalDateTime.now()); task.setRouteId(dto.getRouteId()); task.setStartTime(dto.getStartTime()); - boolean result = devicePlanTaskMapper.saveOrUpdate(task); + devicePlanTaskMapper.saveOrUpdate(task); if (dto.getOrgId() == null) { SysSite site = sysSiteMapper.selectById(dto.getSiteId()); if (site != null) { @@ -473,7 +473,7 @@ public class DeviceTaskService { } SiteMemory siteMemory = GlobalMemory.getSiteMemory(task.getOrgId(), task.getSiteId()); siteMemory.addDevicePlanPrepare(task); - return result; + return task.getId(); } public boolean cancelTask(DeviceTaskCommandDTO dto, String username) { 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 2ea8e94..0a6e9a2 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 @@ -14,6 +14,7 @@ import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; +import com.maibu.memory.DeviceSessionManager; import org.apache.commons.lang3.StringUtils; import org.eclipse.paho.client.mqttv3.MqttException; import org.springframework.beans.factory.annotation.Autowired; @@ -36,7 +37,6 @@ import com.maibu.core.enums.ErrorSource; import com.maibu.core.enums.RespondCode; import com.maibu.core.redis.RedisCache; import com.maibu.dto.DeviceErrorPushDTO; -import com.maibu.manager.DeviceSessionManager; import com.maibu.mapper.ErrorIdentificationStandardMapper; import com.maibu.memory.GlobalMemory; import com.maibu.memory.SiteMemory; @@ -92,19 +92,22 @@ public class DeviceThreadService { String[] parts = k.split(":"); String deviceId = parts[1]; NettyDevice slaveDevice = sessionManager.getDevice(deviceId); - Long siteId = slaveDevice != null ? slaveDevice.getDevice().getSiteId() : null; - Long orgId = slaveDevice != null ? slaveDevice.getDevice().getOrgId() : null; - - SiteMemory siteMemory = GlobalMemory.getSiteMemory(orgId, siteId); - List compared = compareErrorStandard(siteId, orgId, history, - siteMemory.standards.get(ErrorSource.MOWER)); - - DeviceErrorPushDTO pushDTO = new DeviceErrorPushDTO(); - pushDTO.setDeviceId(deviceId); - pushDTO.setTime(System.currentTimeMillis()); - pushDTO.setDetails(compared); - pushDTO.setEvent(RespondCode.device_error_push); - pushList.add(pushDTO); + if (slaveDevice != null && slaveDevice.isOnline()) { + Long siteId = slaveDevice.getDevice().getSiteId(); + Long orgId = slaveDevice.getDevice().getOrgId(); + log.debug("compare siteId:{},orgId:{}", siteId, orgId); + SiteMemory siteMemory = GlobalMemory.getSiteMemory(orgId, siteId); + if (siteMemory != null) { + List compared = compareErrorStandard(siteId, orgId, history, + siteMemory.standards.get(ErrorSource.MOWER)); + DeviceErrorPushDTO pushDTO = new DeviceErrorPushDTO(); + pushDTO.setDeviceId(deviceId); + pushDTO.setTime(System.currentTimeMillis()); + pushDTO.setDetails(compared); + pushDTO.setEvent(RespondCode.device_error_push); + pushList.add(pushDTO); + } + } } }); // 按实际deviceId分组,推送错误信息 @@ -195,7 +198,7 @@ public class DeviceThreadService { } public List compareErrorStandard(Long siteId, Long orgId, DeviceRunningStatusHistory history, - List standards) { + List standards) { if (history == null || CollectionUtils.isEmpty(standards)) return null; List list = new ArrayList<>(); @@ -204,9 +207,11 @@ public class DeviceThreadService { String compareValues = standard.getCompareValues(); CompareEnum compareType = standard.getCompareType(); String targetValue = knownClassFieldFinding(fieldName, history); + log.debug("compare2 compareType:{} compareValues:{},targetValue:{}", compareType, compareValues, targetValue); if (!StringUtils.isEmpty(compareValues) && !StringUtils.isEmpty(targetValue)) { - boolean result = CompareUtils.compare(compareType, compareValues, targetValue); - if (!result) { + boolean result = CompareUtils.compare(compareType, targetValue, compareValues); + log.debug("compare3 result:{}", result); + if (result) { AlarmMessage alarm = new AlarmMessage(); alarm.setContent(standard.getErrorDescription()); alarm.setDeviceSn(history.getDeviceId()); @@ -217,6 +222,7 @@ public class DeviceThreadService { alarm.setNo(standard.getErrorCode()); alarm.setSuggestion(standard.getSuggestion()); alarm.setStatus("未处理"); + alarm.setTimeValues(targetValue); alarm.setTime(LocalDateTime.now()); alarm.setOrgId(orgId); alarm.setSiteId(siteId); diff --git a/maibu-netty-server/src/main/java/com/maibu/service/NettyDeviceService.java b/maibu-netty-server/src/main/java/com/maibu/service/NettyDeviceService.java index b020c50..0ddd1c9 100644 --- a/maibu-netty-server/src/main/java/com/maibu/service/NettyDeviceService.java +++ b/maibu-netty-server/src/main/java/com/maibu/service/NettyDeviceService.java @@ -1,14 +1,19 @@ package com.maibu.service; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.maibu.constant.Constant; import com.maibu.core.business.DeviceRunningStatusHistory; import com.maibu.core.business.ErrorIdentificationStandard; +import com.maibu.core.business.device.NettyDevice; +import com.maibu.dto.SendCommandDTO; import com.maibu.mapper.DeviceStatusHistoryMapper; import com.maibu.mapper.ErrorIdentificationStandardMapper; +import com.maibu.memory.DeviceSessionManager; 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; @@ -19,6 +24,9 @@ public class NettyDeviceService { @Autowired private DeviceStatusHistoryMapper deviceStatusHistoryMapper; + @Autowired + private DeviceSessionManager deviceSessionManager; + @Autowired private ErrorIdentificationStandardMapper errorIdentificationStandardMapper; @@ -40,5 +48,25 @@ public class NettyDeviceService { return errorIdentificationStandardMapper.updateById(standard); } + public void sendCommand(SendCommandDTO command) { + if (command == null || command.getCommandType() == null || CollectionUtils.isEmpty(command.getDeviceIds())) + return; + command.getDeviceIds().forEach(deviceId -> { + NettyDevice nettyDevice = deviceSessionManager.getDevice(deviceId); + if (nettyDevice != null && !nettyDevice.isExecutingTask()) { + if (nettyDevice.getChannel() != null && nettyDevice.getChannel().isActive()) { + if (Constant.WheelGainCoefficients.equals(command.getCommandType())) { + double leftForwardGain = (double) command.getParams().get("leftForwardGain"); + double leftBackwardGain = (double) command.getParams().get("leftBackwardGain"); + double rightForwardGain = (double) command.getParams().get("rightForwardGain"); + double rightBackwardGain = (double) command.getParams().get("rightBackwardGain"); + nettyDevice.sendWheelGainCoefficientsCommand(leftForwardGain, leftBackwardGain, rightForwardGain, rightBackwardGain); + } + } + } + }); + + } + } diff --git a/maibu-netty-server/src/main/java/com/maibu/service/TransferDeviceService.java b/maibu-netty-server/src/main/java/com/maibu/service/TransferDeviceService.java index 01d0255..cd747d5 100644 --- a/maibu-netty-server/src/main/java/com/maibu/service/TransferDeviceService.java +++ b/maibu-netty-server/src/main/java/com/maibu/service/TransferDeviceService.java @@ -7,9 +7,9 @@ import com.maibu.core.domain.AjaxResult; import com.maibu.core.domain.entity.UserClient; import com.maibu.core.domain.model.LoginUser; import com.maibu.core.enums.ConnectorStatus; -import com.maibu.manager.DeviceSessionManager; import com.maibu.mapper.DeviceMapper; import com.maibu.mapper.SysUserClientMapper; +import com.maibu.memory.DeviceSessionManager; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; diff --git a/maibu-netty-server/src/main/java/com/maibu/utils/CompareUtils.java b/maibu-netty-server/src/main/java/com/maibu/utils/CompareUtils.java index 84637a6..97028b7 100644 --- a/maibu-netty-server/src/main/java/com/maibu/utils/CompareUtils.java +++ b/maibu-netty-server/src/main/java/com/maibu/utils/CompareUtils.java @@ -31,38 +31,38 @@ public class CompareUtils { return !compareValue.equals(targetValue); case GT: return isNumeric(compareValue) && isNumeric(targetValue) && - Double.parseDouble(compareValue) > Double.parseDouble(targetValue); + Double.parseDouble(targetValue) > Double.parseDouble(compareValue); case LT: return isNumeric(compareValue) && isNumeric(targetValue) && - Double.parseDouble(compareValue) < Double.parseDouble(targetValue); + Double.parseDouble(targetValue) < Double.parseDouble(compareValue); case GTE: return isNumeric(compareValue) && isNumeric(targetValue) && - Double.parseDouble(compareValue) >= Double.parseDouble(targetValue); + Double.parseDouble(targetValue) >= Double.parseDouble(compareValue); case LTE: return isNumeric(compareValue) && isNumeric(targetValue) && - Double.parseDouble(compareValue) <= Double.parseDouble(targetValue); + Double.parseDouble(targetValue) <= Double.parseDouble(compareValue); case BETWEEN: // 范围值用英文中划线分割 - String[] rangeValues = targetValue.split("-"); + String[] rangeValues = compareValue.split("-"); if (rangeValues.length != 2) { return false; } return isNumeric(compareValue) && isNumeric(rangeValues[0]) && isNumeric(rangeValues[1]) && - Double.parseDouble(compareValue) >= Double.parseDouble(rangeValues[0]) && - Double.parseDouble(compareValue) <= Double.parseDouble(rangeValues[1]); + Double.parseDouble(targetValue) >= Double.parseDouble(rangeValues[0]) && + Double.parseDouble(targetValue) <= Double.parseDouble(rangeValues[1]); case NOT_BETWEEN: // 范围值用英文中划线分割 - String[] notRangeValues = targetValue.split("-"); + String[] notRangeValues = compareValue.split("-"); if (notRangeValues.length != 2) { return false; } return isNumeric(compareValue) && isNumeric(notRangeValues[0]) && isNumeric(notRangeValues[1]) && - (Double.parseDouble(compareValue) < Double.parseDouble(notRangeValues[0]) || - Double.parseDouble(compareValue) > Double.parseDouble(notRangeValues[1])); + (Double.parseDouble(targetValue) < Double.parseDouble(notRangeValues[0]) || + Double.parseDouble(targetValue) > Double.parseDouble(notRangeValues[1])); case CONTAIN: - return compareValue.contains(targetValue); + return targetValue.contains(compareValue); case NOT_CONTAIN: - return !compareValue.contains(targetValue); + return !targetValue.contains(compareValue); default: return false; } diff --git a/maibu-netty-server/src/main/java/com/maibu/utils/DingTalkTemplate.java b/maibu-netty-server/src/main/java/com/maibu/utils/DingTalkTemplate.java index 8b0d6ff..ef2ea54 100644 --- a/maibu-netty-server/src/main/java/com/maibu/utils/DingTalkTemplate.java +++ b/maibu-netty-server/src/main/java/com/maibu/utils/DingTalkTemplate.java @@ -12,6 +12,7 @@ public class DingTalkTemplate { "告警时间:%s\n\n" + "设备名称:%s\n\n" + "设备编号:%s\n\n" + + "当前值:%s\n\n" + "告警内容:\n%s\n\n" + "发生位置:\n%s\n\n" + "处理建议:\n%s\n\n" + @@ -21,6 +22,7 @@ public class DingTalkTemplate { alarm.getTime(), alarm.getDeviceName(), alarm.getDeviceSn(), + alarm.getTimeValues(), alarm.getContent(), alarm.getLocation(), alarm.getSuggestion(), diff --git a/maibu-service/maibu-iot-service/src/main/java/com/maibu/controller/AlarmController.java b/maibu-service/maibu-iot-service/src/main/java/com/maibu/controller/AlarmController.java index 1bc362d..d3f77f9 100644 --- a/maibu-service/maibu-iot-service/src/main/java/com/maibu/controller/AlarmController.java +++ b/maibu-service/maibu-iot-service/src/main/java/com/maibu/controller/AlarmController.java @@ -75,7 +75,7 @@ public class AlarmController extends BaseController { //@PreAuthorize("@ss.hasPermi('iot:alarm:handle')") @Log(title = "告警处理", businessType = BusinessType.UPDATE) - @PutMapping("/handle") + @PostMapping("/handle") @ApiOperation("处理告警") public AjaxResult handle(@RequestBody AlarmHandleDTO handleDTO) { return toAjax(alarmService.handleAlarm(handleDTO)); diff --git a/maibu-service/maibu-iot-service/src/main/java/com/maibu/controller/DeviceRunParamController.java b/maibu-service/maibu-iot-service/src/main/java/com/maibu/controller/DeviceRunParamController.java index 97c86e5..30bd7ab 100644 --- a/maibu-service/maibu-iot-service/src/main/java/com/maibu/controller/DeviceRunParamController.java +++ b/maibu-service/maibu-iot-service/src/main/java/com/maibu/controller/DeviceRunParamController.java @@ -1,6 +1,8 @@ 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; @@ -25,7 +27,7 @@ public class DeviceRunParamController extends BaseController { private DeviceRunParamService service; @PostMapping("/save") - public AjaxResult save(@RequestBody DeviceRunParam deviceRunParam) { + public AjaxResult save(@RequestBody DeviceRunParam deviceRunParam) throws ExecutionException, InterruptedException, TimeoutException { return AjaxResult.success(service.save(deviceRunParam)); } @@ -37,7 +39,7 @@ public class DeviceRunParamController extends BaseController { } @GetMapping("/selectByDeviceId") - public AjaxResult selectByDeviceId(@RequestParam String deviceId) { + public AjaxResult selectByDeviceId(@RequestParam String deviceId) throws ExecutionException, InterruptedException, TimeoutException { return AjaxResult.success(service.selectByDeviceId(deviceId)); } diff --git a/maibu-service/maibu-iot-service/src/main/java/com/maibu/controller/IOTWorkOrderController.java b/maibu-service/maibu-iot-service/src/main/java/com/maibu/controller/IOTWorkOrderController.java index 465126e..55e301f 100644 --- a/maibu-service/maibu-iot-service/src/main/java/com/maibu/controller/IOTWorkOrderController.java +++ b/maibu-service/maibu-iot-service/src/main/java/com/maibu/controller/IOTWorkOrderController.java @@ -1,11 +1,16 @@ package com.maibu.controller; +import java.io.InputStream; +import java.util.ArrayList; import java.util.List; import java.util.Map; +import java.util.UUID; import javax.servlet.http.HttpServletResponse; +import com.maibu.service.impl.AlarmServiceImpl; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.MediaType; import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; @@ -13,7 +18,9 @@ import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.PutMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestPart; import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.multipart.MultipartFile; import com.maibu.annotation.Log; import com.maibu.core.business.IOTWorkOrder; @@ -25,6 +32,7 @@ import com.maibu.core.domain.AjaxResult; import com.maibu.core.page.TableDataInfo; import com.maibu.enums.BusinessType; import com.maibu.service.IWorkOrderService; +import com.maibu.utils.MinioUtil; import com.maibu.utils.poi.ExcelUtil; import io.swagger.annotations.Api; @@ -40,29 +48,103 @@ public class IOTWorkOrderController extends BaseController { @Autowired private IWorkOrderService workOrderService; - // @PreAuthorize("@ss.hasPermi('iot:workOrder:list')") + @Autowired + private AlarmServiceImpl alarmServiceImpl; + + @Autowired + private MinioUtil minioUtil; + + // @PreAuthorize("@ss.hasPermi('iot:workOrder:list')") @GetMapping("/list") @ApiOperation("工单分页列表") public TableDataInfo list(WorkOrderQueryDTO queryDTO) { return workOrderService.selectWorkOrderPage(queryDTO); } - //@PreAuthorize("@ss.hasPermi('iot:workOrder:query')") + // @PreAuthorize("@ss.hasPermi('iot:workOrder:query')") @GetMapping("/{id}") @ApiOperation("获取工单详情") public AjaxResult getInfo(@PathVariable Long id) { return AjaxResult.success(workOrderService.selectWorkOrderById(id)); } - // @PreAuthorize("@ss.hasPermi('iot:workOrder:add')") - @Log(title = "工单管理", businessType = BusinessType.INSERT) @PostMapping @ApiOperation("新增工单") public AjaxResult add(@RequestBody IOTWorkOrder workOrder) { + if (workOrder != null && workOrder.getAlarmId() != null) { + if (alarmServiceImpl.existWorkOrder(workOrder.getAlarmId())) { + return AjaxResult.error("当前告警已存在创建的工单!"); + } + } return toAjax(workOrderService.insertWorkOrder(workOrder)); } - //@PreAuthorize("@ss.hasPermi('iot:workOrder:edit')") + @PostMapping(value = "/add", consumes = MediaType.MULTIPART_FORM_DATA_VALUE) + public AjaxResult addWorkRecord( + @RequestPart(value = "file", required = false) MultipartFile[] files, // 接收上传的图片 + @RequestPart(value = "video", required = false) MultipartFile[] videos, // 接收上传的视频 + @RequestPart("workOrder") IOTWorkOrder workOrder // 接收表单里的 JSON 对象 + ) { +// try (InputStream inputStream = file.getInputStream()) { +// String fileName = "workOrder/img_" + workOrder.getOrderTitle() + System.currentTimeMillis() + ".png"; +// // 上传到 MinIO +// minioUtil.uploadFile(fileName, inputStream, "image/png"); +// // 获取访问 URL +// String url = minioUtil.getPublicUrl(fileName); +// System.out.println("✅ 图片上传成功,访问地址: " + url); +// // 这里可以把 URL 存到 workRecord 里 +// workOrder.setImgUrl(url); +// } catch (Exception e) { +// return AjaxResult.error(e.getMessage()); +// } + if (workOrder != null && workOrder.getAlarmId() != null) { + if (alarmServiceImpl.existWorkOrder(workOrder.getAlarmId())) { + return AjaxResult.error("当前告警已存在创建的工单!"); + } + } + List imgUrls = new ArrayList<>(); + + if (files != null) { + for (MultipartFile file : files) { + String suffix = file.getOriginalFilename() + .substring(file.getOriginalFilename().lastIndexOf(".")); + + String fileName = "workOrder/img_" + UUID.randomUUID() + suffix + file.getContentType(); + + try (InputStream inputStream = file.getInputStream()) { + minioUtil.uploadFile(fileName, inputStream, file.getContentType()); + imgUrls.add(minioUtil.getPublicUrl(fileName)); + } catch (Exception e) { + return AjaxResult.error("图片上传失败:" + e.getMessage()); + } + } + } + // 保存图片URL(建议数据库存JSON或逗号分隔) + workOrder.setImgUrl(imgUrls); + + List videoUrls = new ArrayList<>(); + if (videos != null) { + for (MultipartFile video : videos) { + String suffix = video.getOriginalFilename() + .substring(video.getOriginalFilename().lastIndexOf(".")); + + String fileName = "workOrder/video_" + UUID.randomUUID() + suffix + video.getContentType(); + ; + + try (InputStream inputStream = video.getInputStream()) { + minioUtil.uploadFile(fileName, inputStream, video.getContentType()); + videoUrls.add(minioUtil.getPublicUrl(fileName)); + } catch (Exception e) { + return AjaxResult.error("视频上传失败:" + e.getMessage()); + } + } + } + workOrder.setVideoUrl(videoUrls); + + return AjaxResult.success(workOrderService.insertWorkOrder(workOrder)); + } + + // @PreAuthorize("@ss.hasPermi('iot:workOrder:edit')") @Log(title = "工单管理", businessType = BusinessType.UPDATE) @PutMapping @ApiOperation("修改工单") @@ -70,7 +152,7 @@ public class IOTWorkOrderController extends BaseController { return toAjax(workOrderService.updateWorkOrder(workOrder)); } - // @PreAuthorize("@ss.hasPermi('iot:workOrder:dispatch')") + // @PreAuthorize("@ss.hasPermi('iot:workOrder:dispatch')") @Log(title = "工单派发", businessType = BusinessType.UPDATE) @PostMapping("/dispatch") @ApiOperation("派发工单") @@ -78,22 +160,41 @@ public class IOTWorkOrderController extends BaseController { return toAjax(workOrderService.dispatchWorkOrder(dispatchDTO)); } - @PostMapping("/start") @ApiOperation("开始执行工单") - public AjaxResult start(@RequestBody WorkOrderStartDTO dto) { + public AjaxResult start( + @RequestBody WorkOrderStartDTO dto) { return toAjax(workOrderService.startWorkOrder(dto)); } - // @PreAuthorize("@ss.hasPermi('iot:workOrder:complete')") + // @PreAuthorize("@ss.hasPermi('iot:workOrder:complete')") @Log(title = "工单完成", businessType = BusinessType.UPDATE) @PostMapping("/complete") @ApiOperation("完成工单") - public AjaxResult complete(@RequestBody IOTWorkOrder workOrder) { - return toAjax(workOrderService.completeWorkOrder(workOrder)); + public AjaxResult complete(@RequestPart(value = "files", required = false) MultipartFile[] files, + @RequestPart("workOrder") IOTWorkOrder workOrder + ) { + List imgUrls = new ArrayList<>(); + + if (files != null) { + for (MultipartFile file : files) { + String suffix = file.getOriginalFilename() + .substring(file.getOriginalFilename().lastIndexOf(".")); + + String fileName = "workOrder/img_" + UUID.randomUUID() + suffix + file.getContentType(); + + try (InputStream inputStream = file.getInputStream()) { + minioUtil.uploadFile(fileName, inputStream, file.getContentType()); + imgUrls.add(minioUtil.getPublicUrl(fileName)); + } catch (Exception e) { + return AjaxResult.error("图片上传失败:" + e.getMessage()); + } + } + } + return toAjax(workOrderService.completeWorkOrder(workOrder, imgUrls)); } - //@PreAuthorize("@ss.hasPermi('iot:workOrder:suspend')") + // @PreAuthorize("@ss.hasPermi('iot:workOrder:suspend')") @Log(title = "工单挂起", businessType = BusinessType.UPDATE) @PostMapping("/suspend/{id}") @ApiOperation("挂起工单") @@ -101,7 +202,7 @@ public class IOTWorkOrderController extends BaseController { return toAjax(workOrderService.suspendWorkOrder(id)); } - //@PreAuthorize("@ss.hasPermi('iot:workOrder:remove')") + // @PreAuthorize("@ss.hasPermi('iot:workOrder:remove')") @Log(title = "工单管理", businessType = BusinessType.DELETE) @DeleteMapping("/{ids}") @ApiOperation("删除工单") @@ -109,7 +210,7 @@ public class IOTWorkOrderController extends BaseController { return toAjax(workOrderService.deleteWorkOrderByIds(ids)); } - // @PreAuthorize("@ss.hasPermi('iot:workOrder:statistics')") + // @PreAuthorize("@ss.hasPermi('iot:workOrder:statistics')") @GetMapping("/statistics") @ApiOperation("工单统计") public AjaxResult statistics() { @@ -117,7 +218,7 @@ public class IOTWorkOrderController extends BaseController { return AjaxResult.success(statistics); } - //@PreAuthorize("@ss.hasPermi('iot:workOrder:export')") + // @PreAuthorize("@ss.hasPermi('iot:workOrder:export')") @Log(title = "工单管理", businessType = BusinessType.EXPORT) @PostMapping("/export") @ApiOperation("导出工单") @@ -131,7 +232,7 @@ public class IOTWorkOrderController extends BaseController { } } - // @PreAuthorize("@ss.hasPermi('iot:workOrder:add')") + // @PreAuthorize("@ss.hasPermi('iot:workOrder:add')") @Log(title = "从告警生成工单", businessType = BusinessType.INSERT) @PostMapping("/generateFromAlarm/{alarmId}") @ApiOperation("从告警生成工单") diff --git a/maibu-service/maibu-iot-service/src/main/java/com/maibu/service/IAlarmService.java b/maibu-service/maibu-iot-service/src/main/java/com/maibu/service/IAlarmService.java index 938e8d1..d49cef1 100644 --- a/maibu-service/maibu-iot-service/src/main/java/com/maibu/service/IAlarmService.java +++ b/maibu-service/maibu-iot-service/src/main/java/com/maibu/service/IAlarmService.java @@ -19,9 +19,9 @@ public interface IAlarmService extends IService { int insertAlarm(Alarm alarm); - int updateAlarm(Alarm alarm); + boolean updateAlarm(Alarm alarm); - int handleAlarm(AlarmHandleDTO handleDTO); + boolean handleAlarm(AlarmHandleDTO handleDTO); int deleteAlarmById(Long id); diff --git a/maibu-service/maibu-iot-service/src/main/java/com/maibu/service/IWorkOrderService.java b/maibu-service/maibu-iot-service/src/main/java/com/maibu/service/IWorkOrderService.java index 175a5a1..51ebe5c 100644 --- a/maibu-service/maibu-iot-service/src/main/java/com/maibu/service/IWorkOrderService.java +++ b/maibu-service/maibu-iot-service/src/main/java/com/maibu/service/IWorkOrderService.java @@ -26,7 +26,7 @@ public interface IWorkOrderService extends IService { boolean startWorkOrder(WorkOrderStartDTO dto); - int completeWorkOrder(IOTWorkOrder workOrder); + int completeWorkOrder(IOTWorkOrder workOrder, List imgUrls); int suspendWorkOrder(Long id); diff --git a/maibu-service/maibu-iot-service/src/main/java/com/maibu/service/impl/AlarmServiceImpl.java b/maibu-service/maibu-iot-service/src/main/java/com/maibu/service/impl/AlarmServiceImpl.java index 3dbb0df..105cc07 100644 --- a/maibu-service/maibu-iot-service/src/main/java/com/maibu/service/impl/AlarmServiceImpl.java +++ b/maibu-service/maibu-iot-service/src/main/java/com/maibu/service/impl/AlarmServiceImpl.java @@ -6,8 +6,11 @@ import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; +import com.maibu.core.enums.AlarmType; +import com.maibu.core.redis.RedisCache; import org.eclipse.paho.client.mqttv3.MqttException; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @@ -45,6 +48,9 @@ public class AlarmServiceImpl extends ServiceImpl implements @Autowired private AlarmMapper alarmMapper; + @Autowired + private RedisCache redisCache; + @Override public List selectAlarmPage(AlarmQueryDTO queryDTO) { // validateQueryParams(queryDTO); @@ -71,8 +77,8 @@ public class AlarmServiceImpl extends ServiceImpl implements Map statistics = new HashMap<>(); statistics.put("total", alarms.size()); statistics.put("pending", alarms.stream().filter(a -> a.getHandleStatus() == 1).count()); - statistics.put("processing", alarms.stream().filter(a -> a.getHandleStatus() == 2).count()); - statistics.put("closed", alarms.stream().filter(a -> a.getHandleStatus() == 3).count()); +// statistics.put("processing", alarms.stream().filter(a -> a.getHandleStatus() == 2).count()); + statistics.put("closed", alarms.stream().filter(a -> a.getHandleStatus() == 2).count()); statistics.put("levelStats", alarms.stream().collect(Collectors.groupingBy(Alarm::getAlarmLevel, Collectors.counting()))); @@ -196,6 +202,9 @@ public class AlarmServiceImpl extends ServiceImpl implements if (!StringUtils.isEmpty(queryDTO.getAlarmNo())) { wrapper.like(Alarm::getAlarmNo, queryDTO.getAlarmNo()); } + if (queryDTO.getHandleStatus() != null) { + wrapper.eq(Alarm::getHandleStatus, queryDTO.getHandleStatus()); + } if (!StringUtils.isEmpty(queryDTO.getDeviceId())) { wrapper.eq(Alarm::getDeviceId, queryDTO.getDeviceId()); } @@ -226,11 +235,10 @@ public class AlarmServiceImpl extends ServiceImpl implements Alarm alarm = alarmMapper.selectById(id); if (alarm == null) throw new ServiceException("告警不存在"); - - Long userId = SecurityUtils.getUserId(); - if (!SecurityUtils.isAdmin(userId) && alarm.getDeviceId() != null) { - validateDeviceAccess(alarm.getDeviceId()); - } +// Long userId = SecurityUtils.getUserId(); +// if (!SecurityUtils.isAdmin(userId) && alarm.getDeviceId() != null) { +// validateDeviceAccess(alarm.getDeviceId()); +// } return alarm; } @@ -247,40 +255,65 @@ public class AlarmServiceImpl extends ServiceImpl implements } @Override - public int updateAlarm(Alarm alarm) { - Long userId = SecurityUtils.getUserId(); - if (!SecurityUtils.isAdmin(userId) && alarm.getId() != null) { - Alarm existAlarm = alarmMapper.selectById(alarm.getId()); - if (existAlarm != null && existAlarm.getDeviceId() != null) { - validateDeviceAccess(existAlarm.getDeviceId()); - } - } - return alarmMapper.updateById(alarm); + public boolean updateAlarm(Alarm alarm) { +// Long userId = SecurityUtils.getUserId(); +// if (!SecurityUtils.isAdmin(userId) && alarm.getId() != null) { +// Alarm existAlarm = alarmMapper.selectById(alarm.getId()); +// if (existAlarm != null && existAlarm.getDeviceId() != null) { +// validateDeviceAccess(existAlarm.getDeviceId()); +// } +// } + return alarmMapper.saveOrUpdate(alarm); } @Override - public int handleAlarm(AlarmHandleDTO handleDTO) { + public boolean handleAlarm(AlarmHandleDTO handleDTO) { Alarm alarm = alarmMapper.selectById(handleDTO.getAlarmId()); if (alarm == null) throw new ServiceException("告警不存在"); - Long userId = SecurityUtils.getUserId(); - if (!SecurityUtils.isAdmin(userId) && alarm.getDeviceId() != null) { - validateDeviceAccess(alarm.getDeviceId()); - } +// Long userId = SecurityUtils.getUserId(); +// if (!SecurityUtils.isAdmin(userId) && alarm.getDeviceId() != null) { +// validateDeviceAccess(alarm.getDeviceId()); +// } - Alarm updateAlarm = new Alarm(); - updateAlarm.setId(handleDTO.getAlarmId()); - updateAlarm.setHandleStatus(handleDTO.getHandleStatus()); - updateAlarm.setHandleUserId(SecurityUtils.getUserId()); - updateAlarm.setHandleUserName(SecurityUtils.getLoginUser().getUser().getNickName()); - updateAlarm.setHandleTime(LocalDateTime.now()); - updateAlarm.setHandleRemark(handleDTO.getHandleRemark()); +// Alarm updateAlarm = new Alarm(); +// updateAlarm.setId(handleDTO.getAlarmId()); + alarm.setHandleStatus(handleDTO.getHandleStatus()); + alarm.setHandleUserId(SecurityUtils.getUserId()); + alarm.setHandleUserName(SecurityUtils.getLoginUser().getUser().getNickName()); + alarm.setHandleTime(LocalDateTime.now()); + alarm.setHandleRemark(handleDTO.getHandleRemark()); + alarm.setHandleResult(handleDTO.getHandleResult()); + + removeRedisAlarm(alarm.getDeviceId(), alarm.getAlarmNo()); + return alarmMapper.saveOrUpdate(alarm); + } + + public void removeRedisAlarm(String deviceId, String alarmNo) { + if (StringUtils.isEmpty(deviceId) || StringUtils.isEmpty(alarmNo)) return; + String pushKey = "alarm:" + "dingtalk:" + deviceId + ":" + alarmNo; +// Boolean exists = redisCache.hasKey(pushKey); +// if (exists != null && exists) { +// redisCache.deleteObject(pushKey); +// } + + String pushKey2 = "alarm:" + "email:" + deviceId + ":" + alarmNo; +// Boolean exists2 = redisCache.hasKey(pushKey2); +// if (exists2 != null && exists2) { +// redisCache.deleteObject(pushKey2); +// } + + String pushKey3 = "alarm:" + "mqtt:" + deviceId + ":" + alarmNo; +// Boolean exists3 = redisCache.hasKey(pushKey3); +// if (exists3 != null && exists3) { +// redisCache.deleteObject(pushKey3); +// } + + redisCache.deleteObject(pushKey); + redisCache.deleteObject(pushKey2); + redisCache.deleteObject(pushKey3); - if (handleDTO.getHandleStatus() == 3) { - updateAlarm.setRecoverTime(LocalDateTime.now()); - } - return alarmMapper.updateById(updateAlarm); } @Override @@ -344,16 +377,16 @@ public class AlarmServiceImpl extends ServiceImpl implements return statistics; } - public void pushAlertMes(List alarmMessages) { + public List pushAlertMes(List alarmMessages) { if (alarmMessages == null || alarmMessages.isEmpty()) { - return; + return null; } List list = new ArrayList<>(); for (AlarmMessage alarmMessage : alarmMessages) { Alarm alarm = new Alarm(); alarm.setAlarmNo(alarmMessage.getNo()); alarm.setAlarmLevel(alarmMessage.getLevel()); - alarm.setAlarmType(1); + alarm.setAlarmType(AlarmType.MOWER_FAULT); alarm.setAlarmTitle(alarmMessage.getName()); alarm.setAlarmContent(alarmMessage.getContent()); alarm.setDeviceId(alarmMessage.getDeviceName()); @@ -361,12 +394,14 @@ public class AlarmServiceImpl extends ServiceImpl implements alarm.setDeviceType(ErrorSource.MOWER); alarm.setAlarmTime(LocalDateTime.now()); alarm.setOrgId(alarmMessage.getOrgId()); + alarm.setTimeValues(alarmMessage.getTimeValues()); alarm.setSiteId(alarmMessage.getSiteId()); alarm.setAlarmTime(LocalDateTime.now()); pushErrorMessage(alarmMessage.getDeviceName(), JsonUtils.toJsonString(alarm)); list.add(alarm); } alarmMapper.saveOrUpdateBatch(list); + return list; // todo 推送websocket? } @@ -386,4 +421,12 @@ public class AlarmServiceImpl extends ServiceImpl implements } } + public boolean existWorkOrder(Long alarmId) { + boolean b = false; + if (alarmId != null) { + b = alarmMapper.selectById(alarmId) != null; + } + return b; + } + } diff --git a/maibu-service/maibu-iot-service/src/main/java/com/maibu/service/impl/DeviceRunParamService.java b/maibu-service/maibu-iot-service/src/main/java/com/maibu/service/impl/DeviceRunParamService.java index ffbd2f3..c7e749b 100644 --- a/maibu-service/maibu-iot-service/src/main/java/com/maibu/service/impl/DeviceRunParamService.java +++ b/maibu-service/maibu-iot-service/src/main/java/com/maibu/service/impl/DeviceRunParamService.java @@ -1,31 +1,74 @@ package com.maibu.service.impl; -import java.util.List; - +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.maibu.constant.Constant; +import com.maibu.core.business.DeviceRunParam; +import com.maibu.core.business.device.NettyDevice; +import com.maibu.dto.BaseQueryDTO; +import com.maibu.exception.ServiceException; +import com.maibu.mapper.DeviceRunParamMapper; +import com.maibu.memory.DeviceSessionManager; +import com.maibu.memory.GlobalMemory; +import com.maibu.memory.SiteMemory; +import lombok.extern.slf4j.Slf4j; 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.DeviceRunParam; -import com.maibu.dto.BaseQueryDTO; -import com.maibu.mapper.DeviceRunParamMapper; -import com.maibu.memory.GlobalMemory; -import com.maibu.memory.SiteMemory; +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 +@Slf4j public class DeviceRunParamService { @Autowired private DeviceRunParamMapper deviceRunParamMapper; - public boolean save(DeviceRunParam deviceRunParam) { - SiteMemory siteMemory = GlobalMemory.getSiteMemory(deviceRunParam.getOrgId(), deviceRunParam.getSiteId()); - if (siteMemory != null) { - siteMemory.saveDeviceRunParam(deviceRunParam); + @Autowired + private DeviceSessionManager sessionManager; + + public boolean save(DeviceRunParam deviceRunParam) throws ExecutionException, InterruptedException, TimeoutException { + + NettyDevice nettyDevice = sessionManager.getDevice(deviceRunParam.getDeviceId()); + if (nettyDevice == null || !nettyDevice.getChannel().isActive()) { + throw new ServiceException("设备不在线,无法操作!"); + } + + CompletableFuture future = new CompletableFuture<>(); + nettyDevice.getChannel().attr(Constant.READ_CONFIG_KEY).set(future); + + try { + nettyDevice.readConfigCommand(); + + DeviceRunParam param = future.get(5, TimeUnit.SECONDS); + + if (param == null) { + throw new ServiceException("获取设备当前属性失败!"); + } + + param.setLeftForwardGain(deviceRunParam.getLeftForwardGain()); + param.setLeftBackwardGain(deviceRunParam.getLeftBackwardGain()); + param.setRightForwardGain(deviceRunParam.getRightForwardGain()); + param.setRightBackwardGain(deviceRunParam.getRightBackwardGain()); + + nettyDevice.writeConfigCommand(param); + if (deviceRunParam.getRunSpeed() != null) { + param.setRunSpeed(deviceRunParam.getRunSpeed()); + } + + SiteMemory siteMemory = GlobalMemory.getSiteMemory(deviceRunParam.getOrgId(), deviceRunParam.getSiteId()); + if (siteMemory != null) { + siteMemory.saveDeviceRunParam(param); + } + return deviceRunParamMapper.saveOrUpdate(param); + } finally { + nettyDevice.getChannel().attr(Constant.READ_CONFIG_KEY).set(null); } - return deviceRunParamMapper.saveOrUpdate(deviceRunParam); } public List list(BaseQueryDTO dto) { @@ -34,19 +77,44 @@ public class DeviceRunParamService { if (dto.getSiteId() != null) { queryWrapper.eq(DeviceRunParam::getSiteId, dto.getSiteId()); } - if (StringUtils.isEmpty(dto.getDeviceId())) { + if (!StringUtils.isEmpty(dto.getDeviceId())) { queryWrapper.eq(DeviceRunParam::getDeviceId, dto.getDeviceId()); } } return deviceRunParamMapper.selectList(queryWrapper); } - public DeviceRunParam selectByDeviceId(String deviceId) { + public DeviceRunParam selectByDeviceId(String deviceId) throws ExecutionException, InterruptedException, TimeoutException { LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); if (!StringUtils.isEmpty(deviceId)) { queryWrapper.eq(DeviceRunParam::getDeviceId, deviceId); } - return deviceRunParamMapper.selectOne(queryWrapper); + DeviceRunParam result = deviceRunParamMapper.selectOne(queryWrapper); + if (result == null) { + NettyDevice nettyDevice = sessionManager.getDevice(deviceId); + CompletableFuture future = new CompletableFuture<>(); + if (nettyDevice != null && nettyDevice.getChannel().isActive()) { + nettyDevice.getChannel().attr(Constant.READ_CONFIG_KEY).set(future); + try { + nettyDevice.readConfigCommand(); + DeviceRunParam param = future.get(5, TimeUnit.SECONDS); + SiteMemory siteMemory = GlobalMemory.getSiteMemory(nettyDevice.getDevice().getOrgId(), nettyDevice.getDevice().getSiteId()); + if (siteMemory != null) { + param.setDeviceId(deviceId); + param.setOrgId(nettyDevice.getDevice().getOrgId()); + param.setSiteId(nettyDevice.getDevice().getSiteId()); + siteMemory.saveDeviceRunParam(param); + } + if (param != null) { + deviceRunParamMapper.saveOrUpdate(param); + return param; + } + } finally { + nettyDevice.getChannel().attr(Constant.READ_CONFIG_KEY).set(null); + } + } + } + return result; } public int delete(List ids) { diff --git a/maibu-service/maibu-iot-service/src/main/java/com/maibu/service/impl/OrderModelService.java b/maibu-service/maibu-iot-service/src/main/java/com/maibu/service/impl/OrderModelService.java index e5d992f..a04be9b 100644 --- a/maibu-service/maibu-iot-service/src/main/java/com/maibu/service/impl/OrderModelService.java +++ b/maibu-service/maibu-iot-service/src/main/java/com/maibu/service/impl/OrderModelService.java @@ -73,11 +73,12 @@ public class OrderModelService { return i; } - public void createTask(String deviceId, Long siteId, Long orgId, Long modelId) { + public String createTask(String deviceId, Long siteId, Long orgId, Long modelId) { SiteMemory siteMemory = GlobalMemory.getSiteMemory(orgId, siteId); OrderModel orderModel = siteMemory.getOrderModel(modelId); OrderType orderType = orderModel.getOrderType(); // 割草机 + String taskId = null; if (orderType != null && orderType.getType() == 1) { Long routeId = orderModel.getRouteId(); DeviceTaskCommandDTO dto = new DeviceTaskCommandDTO(); @@ -86,7 +87,7 @@ public class OrderModelService { dto.setOrgId(orgId); dto.setSiteId(siteId); dto.setStartTime(LocalDateTime.now()); - mowerDispather.dispathDeviceTask(dto); + taskId = String.valueOf(mowerDispather.dispathDeviceTask(dto)); } // 无人机 if (orderType != null && orderType.getType() == 2) { @@ -99,12 +100,13 @@ public class OrderModelService { dto.setName(name); dto.setRth_altitude(orderModel.getRthAltitude()); dto.setRth_mode(orderModel.getRthMode()); - dispather.dispathFightTask(dto); + taskId = dispather.dispathFightTask(dto); } // 其他 if (orderType != null && orderType.getType() == 3) { } + return taskId; } diff --git a/maibu-service/maibu-iot-service/src/main/java/com/maibu/service/impl/WorkOrderServiceImpl.java b/maibu-service/maibu-iot-service/src/main/java/com/maibu/service/impl/WorkOrderServiceImpl.java index 08d05eb..949beaa 100644 --- a/maibu-service/maibu-iot-service/src/main/java/com/maibu/service/impl/WorkOrderServiceImpl.java +++ b/maibu-service/maibu-iot-service/src/main/java/com/maibu/service/impl/WorkOrderServiceImpl.java @@ -2,13 +2,20 @@ package com.maibu.service.impl; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Map; +import java.util.*; +import com.maibu.core.business.alarm_center.Alarm; +import com.maibu.core.domain.entity.SysRole; +import com.maibu.core.enums.AlarmHandleResult; +import com.maibu.mapper.AlarmMapper; +import com.maibu.memory.GlobalMemory; +import com.maibu.memory.SiteMemory; +import com.maibu.service.ISysRoleService; +import com.maibu.utils.MinioUtil; +import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; import org.springframework.util.CollectionUtils; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; @@ -34,6 +41,7 @@ import com.maibu.utils.SecurityUtils; import com.maibu.utils.StringUtils; @Service +@Slf4j public class WorkOrderServiceImpl extends ServiceImpl implements IWorkOrderService { @Autowired @@ -42,17 +50,30 @@ public class WorkOrderServiceImpl extends ServiceImpl wrapper = buildQueryWrapper(queryDTO); @@ -150,43 +171,26 @@ public class WorkOrderServiceImpl extends ServiceImpl buildQueryWrapper(WorkOrderQueryDTO queryDTO) { LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); - - Long userId = SecurityUtils.getUserId(); LoginUser loginUser = SecurityUtils.getLoginUser(); - Long userOrgId = loginUser.getOrgId(); - Long userSiteId = loginUser.getSiteId(); - - if (!SecurityUtils.isAdmin(userId)) { - if (queryDTO.getSiteId() != null) { - wrapper.eq(IOTWorkOrder::getSiteId, queryDTO.getSiteId()); - if (userOrgId != null) { - wrapper.eq(IOTWorkOrder::getOrgId, userOrgId); + if (loginUser != null && loginUser.getRoleId() != null) { + SysRole sysRole = roleService.selectRoleById(loginUser.getRoleId()); + if (sysRole != null) { + String roleKey = sysRole.getRoleKey(); + if (!StringUtils.isEmpty(roleKey)) { + if ("manager".equals(roleKey) || "siteManager".equals(roleKey) || "admin".equals(roleKey)) { + // device.setSiteId(siteId); + } else { + wrapper.eq(IOTWorkOrder::getAssigneeId, loginUser.getUserId()); + } } - } else if (userSiteId != null) { - wrapper.eq(IOTWorkOrder::getSiteId, userSiteId); - } else if (userOrgId != null) { - wrapper.eq(IOTWorkOrder::getOrgId, userOrgId); - } - - if (queryDTO.getAssigneeId() != null) { - wrapper.eq(IOTWorkOrder::getAssigneeId, queryDTO.getAssigneeId()); - } else { - wrapper.and(w -> w.eq(IOTWorkOrder::getAssigneeId, userId) - .or() - .apply("FIND_IN_SET({0}, collaborator_ids)", userId)); - } - } else { - if (queryDTO.getSiteId() != null) { - wrapper.eq(IOTWorkOrder::getSiteId, queryDTO.getSiteId()); - } - if (queryDTO.getOrgId() != null) { - wrapper.eq(IOTWorkOrder::getOrgId, queryDTO.getOrgId()); - } - if (queryDTO.getAssigneeId() != null) { - wrapper.eq(IOTWorkOrder::getAssigneeId, queryDTO.getAssigneeId()); } } - + if (queryDTO.getSiteId() != null) { + wrapper.eq(IOTWorkOrder::getSiteId, queryDTO.getSiteId()); + } + if (queryDTO.getOrgId() != null) { + wrapper.eq(IOTWorkOrder::getOrgId, queryDTO.getOrgId()); + } if (queryDTO.getOrderNo() != null && !queryDTO.getOrderNo().isEmpty()) { wrapper.like(IOTWorkOrder::getOrderNo, queryDTO.getOrderNo()); } @@ -226,14 +230,14 @@ public class WorkOrderServiceImpl extends ServiceImpl { - workOrder.setOrderStatus(3); + workOrder.setOrderStatus(2); + if (workOrder.getPlanStartTime() == null) { + workOrder.setPlanStartTime(LocalDateTime.now()); + } workOrder.setActualStartTime(LocalDateTime.now()); workOrder.setUpdateTime(LocalDateTime.now()); workOrder.setUpdateBy(userName); @@ -377,30 +384,46 @@ public class WorkOrderServiceImpl extends ServiceImpl imgUrls) { + IOTWorkOrder existWorkOrder = iotWorkOrderMapper.selectById(workOrder.getId()); if (existWorkOrder == null) throw new ServiceException("工单不存在"); - Long userId = SecurityUtils.getUserId(); - if (!SecurityUtils.isAdmin(userId)) { - validateWorkOrderAccess(existWorkOrder); - } +// Long userId = SecurityUtils.getUserId(); +// if (!SecurityUtils.isAdmin(userId)) { +// validateWorkOrderAccess(existWorkOrder); +// } IOTWorkOrder updateWorkOrder = new IOTWorkOrder(); updateWorkOrder.setId(workOrder.getId()); - updateWorkOrder.setOrderStatus(4); + updateWorkOrder.setOrderStatus(3); + updateWorkOrder.setImages(imgUrls); updateWorkOrder.setActualEndTime(LocalDateTime.now()); updateWorkOrder.setHandleResult(workOrder.getHandleResult()); updateWorkOrder.setHandleRemark(workOrder.getHandleRemark()); updateWorkOrder.setUpdateTime(LocalDateTime.now()); + updateWorkOrder.setUpdateBy(SecurityUtils.getLoginUser().getUser().getNickName()); + + if (existWorkOrder.getAlarmId() != null) { + Alarm alarm = alarmMapper.selectById(existWorkOrder.getAlarmId()); + if (alarm != null) { +// alarm.setHandleResult(AlarmHandleResult.Handled); + alarm.setHandleStatus(2); + alarm.setUpdateTime(LocalDateTime.now()); + alarm.setUpdateBy("system"); + alarmMapper.saveOrUpdate(alarm); + alarmServiceImpl.removeRedisAlarm(alarm.getDeviceId(), alarm.getAlarmNo()); + } + } return baseMapper.updateById(updateWorkOrder); } @@ -417,7 +440,7 @@ public class WorkOrderServiceImpl extends ServiceImpl