Compare commits
12 Commits
dev_map
...
dev_new_co
| Author | SHA1 | Date | |
|---|---|---|---|
| 4fad6cc929 | |||
| 99d4be4ee4 | |||
| eb1884b972 | |||
| c69e89fa7d | |||
| 9cd3b8e496 | |||
| 25a05ae9d8 | |||
| 5c0ee1f811 | |||
| fce873b662 | |||
| 1d2636f641 | |||
| 40c6edda36 | |||
| be27d2b56e | |||
| f690786847 |
@@ -86,7 +86,7 @@ public class Device extends BaseDO {
|
|||||||
*/
|
*/
|
||||||
@ApiModelProperty("固件版本")
|
@ApiModelProperty("固件版本")
|
||||||
@Excel(name = "固件版本")
|
@Excel(name = "固件版本")
|
||||||
private BigDecimal firmwareVersion;
|
private String firmwareVersion;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* WIFI固件版本
|
* WIFI固件版本
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import com.maibu.core.enums.DeviceTaskStaus;
|
|||||||
import com.maibu.core.host.HostWorkRecordCreateDTO;
|
import com.maibu.core.host.HostWorkRecordCreateDTO;
|
||||||
import com.maibu.core.host.MutiPointEntity;
|
import com.maibu.core.host.MutiPointEntity;
|
||||||
import com.maibu.core.host.PointEntity;
|
import com.maibu.core.host.PointEntity;
|
||||||
|
import com.maibu.core.ota.DeviceOtaFirmware;
|
||||||
import com.maibu.mapper.DevicePlanTaskMapper;
|
import com.maibu.mapper.DevicePlanTaskMapper;
|
||||||
import com.maibu.mapper.WorkRecordMapper;
|
import com.maibu.mapper.WorkRecordMapper;
|
||||||
import com.maibu.memory.GlobalMemory;
|
import com.maibu.memory.GlobalMemory;
|
||||||
@@ -26,10 +27,7 @@ import org.eclipse.paho.client.mqttv3.MqttException;
|
|||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
import java.nio.ByteOrder;
|
import java.nio.ByteOrder;
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
import java.util.ArrayList;
|
import java.util.*;
|
||||||
import java.util.LinkedList;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Queue;
|
|
||||||
import java.util.concurrent.ScheduledExecutorService;
|
import java.util.concurrent.ScheduledExecutorService;
|
||||||
import java.util.concurrent.ScheduledFuture;
|
import java.util.concurrent.ScheduledFuture;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
@@ -182,7 +180,7 @@ public class NettyDevice extends Connector {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized boolean failedTask() {
|
public synchronized boolean failedTask() {
|
||||||
if (task != null) {
|
if (task != null) {
|
||||||
task.setTaskStaus(DeviceTaskStaus.FAILED);
|
task.setTaskStaus(DeviceTaskStaus.FAILED);
|
||||||
task.setUpdateTime(LocalDateTime.now());
|
task.setUpdateTime(LocalDateTime.now());
|
||||||
@@ -216,7 +214,7 @@ public class NettyDevice extends Connector {
|
|||||||
|
|
||||||
// 配置左右轮增益系数
|
// 配置左右轮增益系数
|
||||||
public void sendWheelGainCoefficientsCommand(double leftForwardGain, double leftBackwardGain,
|
public void sendWheelGainCoefficientsCommand(double leftForwardGain, double leftBackwardGain,
|
||||||
double rightForwardGain, double rightBackwardGain) {
|
double rightForwardGain, double rightBackwardGain) {
|
||||||
ByteBuffer buffer = ByteBuffer.allocate(39);
|
ByteBuffer buffer = ByteBuffer.allocate(39);
|
||||||
buffer.order(ByteOrder.LITTLE_ENDIAN);
|
buffer.order(ByteOrder.LITTLE_ENDIAN);
|
||||||
|
|
||||||
@@ -403,4 +401,21 @@ public class NettyDevice extends Connector {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void upgrade(String deviceId, DeviceOtaFirmware firmware) throws MqttException {
|
||||||
|
Map<String, Object> payload = new HashMap<>();
|
||||||
|
payload.put("action", "ota_upgrade");
|
||||||
|
payload.put("version", firmware.getVersion());
|
||||||
|
payload.put("file_url", firmware.getFileUrl());
|
||||||
|
payload.put("firmware_id", firmware.getId());
|
||||||
|
payload.put("sn", deviceId);
|
||||||
|
payload.put("timestamp", System.currentTimeMillis());
|
||||||
|
payload.put("message_id", firmware.getId() + "_" + System.currentTimeMillis());
|
||||||
|
|
||||||
|
GlobalMemory.customMqttDeviceMonitor.publish(
|
||||||
|
mqttClientId,
|
||||||
|
String.format(MqttTopic.MOWER_OTA_UPGRADE_SET, deviceId),
|
||||||
|
JsonUtils.toJsonString(payload)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,18 @@
|
|||||||
|
package com.maibu.core.enums;
|
||||||
|
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@AllArgsConstructor
|
||||||
|
public enum OtaOperate {
|
||||||
|
|
||||||
|
upload("upload", "上传"),
|
||||||
|
upgrade("upgrade", "升级"),
|
||||||
|
rollback("rollback", "回滚"),
|
||||||
|
reboot("reboot", "重启");
|
||||||
|
|
||||||
|
private final String name;
|
||||||
|
private final String value;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,43 +0,0 @@
|
|||||||
package com.maibu.core.mq.message;
|
|
||||||
|
|
||||||
import com.maibu.core.ota.OtaPackageCode;
|
|
||||||
import com.maibu.core.protocol.Message;
|
|
||||||
import com.maibu.core.protocol.modbus.ModbusCode;
|
|
||||||
import io.netty.buffer.ByteBuf;
|
|
||||||
import lombok.Builder;
|
|
||||||
import lombok.Data;
|
|
||||||
import lombok.EqualsAndHashCode;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 消息解析model
|
|
||||||
* @author gsb
|
|
||||||
* @date 2022/10/10 15:53
|
|
||||||
*/
|
|
||||||
@EqualsAndHashCode(callSuper = true)
|
|
||||||
@Data
|
|
||||||
@Builder
|
|
||||||
public class DeviceData extends Message {
|
|
||||||
|
|
||||||
/*topic*/
|
|
||||||
private String topicName;
|
|
||||||
|
|
||||||
/*设备编号*/
|
|
||||||
private String serialNumber;
|
|
||||||
|
|
||||||
/*原数据*/
|
|
||||||
private byte[] data;
|
|
||||||
|
|
||||||
private ByteBuf buf;
|
|
||||||
|
|
||||||
private Object body;
|
|
||||||
/*MQTT OR 其他*/
|
|
||||||
private int type;
|
|
||||||
/*Modbus*/
|
|
||||||
private ModbusCode code;
|
|
||||||
/**产品id*/
|
|
||||||
private Long productId;
|
|
||||||
|
|
||||||
private OtaPackageCode netModbusCode;
|
|
||||||
|
|
||||||
private int bitCount;
|
|
||||||
}
|
|
||||||
@@ -1,59 +0,0 @@
|
|||||||
package com.maibu.core.mq.message;
|
|
||||||
|
|
||||||
import com.maibu.core.protocol.modbus.ModbusCode;
|
|
||||||
import com.maibu.enums.ServerType;
|
|
||||||
import lombok.AllArgsConstructor;
|
|
||||||
import lombok.Builder;
|
|
||||||
import lombok.Data;
|
|
||||||
import lombok.NoArgsConstructor;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 设备下发指令model
|
|
||||||
*
|
|
||||||
* @author gsb
|
|
||||||
* @date 2022/10/10 16:18
|
|
||||||
*/
|
|
||||||
@Data
|
|
||||||
@Builder
|
|
||||||
@NoArgsConstructor
|
|
||||||
@AllArgsConstructor
|
|
||||||
public class DeviceDownMessage {
|
|
||||||
|
|
||||||
private String messageId;
|
|
||||||
/**
|
|
||||||
* 时间戳,单位毫秒
|
|
||||||
*/
|
|
||||||
private Long timestamp;
|
|
||||||
/**
|
|
||||||
* 消息体
|
|
||||||
*/
|
|
||||||
private Object body;
|
|
||||||
/*下发的指令,服务调用的时候就是服务标识符*/
|
|
||||||
private String identifier;
|
|
||||||
/*产品id*/
|
|
||||||
private Long productId;
|
|
||||||
/**
|
|
||||||
* 设备编码
|
|
||||||
*/
|
|
||||||
private String serialNumber;
|
|
||||||
/**
|
|
||||||
* 从机编号
|
|
||||||
*/
|
|
||||||
private Integer slaveId;
|
|
||||||
private ModbusCode code;
|
|
||||||
private String protocolCode;
|
|
||||||
|
|
||||||
private List<PropRead> values;
|
|
||||||
private String topic;
|
|
||||||
private String subCode;
|
|
||||||
private ServerType serverType;
|
|
||||||
|
|
||||||
public DeviceDownMessage(List<PropRead> values, String topic, String subCode,String transport) {
|
|
||||||
this.values = values;
|
|
||||||
this.topic = topic;
|
|
||||||
this.subCode = subCode;
|
|
||||||
this.serverType = ServerType.explain(transport);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
package com.maibu.core.mq.message;
|
|
||||||
|
|
||||||
import lombok.Data;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 平台下发指令数据model
|
|
||||||
* @author bill
|
|
||||||
*/
|
|
||||||
@Data
|
|
||||||
public class DeviceFunctionMessage {
|
|
||||||
|
|
||||||
/*流水号,兼容modbus标准协议没有消息流水号*/
|
|
||||||
private String seqNo;
|
|
||||||
/*平台时间*/
|
|
||||||
private Long pfTimestamp;
|
|
||||||
/*下发的消息体*/
|
|
||||||
private Object body;
|
|
||||||
/*下发的指令物模型标识符*/
|
|
||||||
private String identifier;
|
|
||||||
/*下发的数据寄存器地址*/
|
|
||||||
private String hexAddress;
|
|
||||||
/*产品ID*/
|
|
||||||
private Long productId;
|
|
||||||
/*设备编号*/
|
|
||||||
private String serialNumber;
|
|
||||||
/*网关设备编号*/
|
|
||||||
private String protocolCode;
|
|
||||||
|
|
||||||
/*是否有子设备 0-否,1-是*/
|
|
||||||
private Integer hasSub;
|
|
||||||
/*子设备从机编号 例如 02 编号从机。通过主机集控下发的指定从机编号*/
|
|
||||||
private String subDeviceCode;
|
|
||||||
}
|
|
||||||
@@ -1,31 +0,0 @@
|
|||||||
package com.maibu.core.mq.message;
|
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
|
||||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
|
||||||
import lombok.Data;
|
|
||||||
|
|
||||||
import java.util.Date;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 设备消息
|
|
||||||
* @author bill
|
|
||||||
*/
|
|
||||||
@Data
|
|
||||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
|
||||||
public class DeviceMessage {
|
|
||||||
|
|
||||||
/** 下发的数据*/
|
|
||||||
private Object message;
|
|
||||||
|
|
||||||
/** 下发的topic*/
|
|
||||||
private String topicName;
|
|
||||||
|
|
||||||
/** 设备编号*/
|
|
||||||
private String serialNumber;
|
|
||||||
|
|
||||||
private String dataType;
|
|
||||||
|
|
||||||
/** 时间 */
|
|
||||||
@JsonFormat(pattern ="yyyy-MM-dd HH:mm:ss:SSS")
|
|
||||||
private Date time;
|
|
||||||
}
|
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
package com.maibu.core.mq.message;
|
|
||||||
|
|
||||||
import lombok.Data;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 指令下发组将的model
|
|
||||||
* @author bill
|
|
||||||
*/
|
|
||||||
@Data
|
|
||||||
public class FunctionCallBackBo {
|
|
||||||
|
|
||||||
/*下发的数据*/
|
|
||||||
private byte[] message;
|
|
||||||
|
|
||||||
/*MQTt-下发的topic*/
|
|
||||||
private String topicName;
|
|
||||||
|
|
||||||
/*设备编号*/
|
|
||||||
private String serialNumber;
|
|
||||||
/**
|
|
||||||
* 原数据包
|
|
||||||
*/
|
|
||||||
private String sources;
|
|
||||||
}
|
|
||||||
@@ -1,20 +0,0 @@
|
|||||||
package com.maibu.core.mq.message;
|
|
||||||
|
|
||||||
import lombok.Data;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 指令下发组将的model
|
|
||||||
* @author bill
|
|
||||||
*/
|
|
||||||
@Data
|
|
||||||
public class InstructionsMessage {
|
|
||||||
|
|
||||||
/*下发的数据*/
|
|
||||||
private byte[] message;
|
|
||||||
|
|
||||||
/*MQTt-下发的topic*/
|
|
||||||
private String topicName;
|
|
||||||
|
|
||||||
/*设备编号*/
|
|
||||||
private String serialNumber;
|
|
||||||
}
|
|
||||||
@@ -1,32 +0,0 @@
|
|||||||
package com.maibu.core.mq.message;
|
|
||||||
|
|
||||||
import lombok.Data;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author gsb
|
|
||||||
* @date 2024/6/20 10:53
|
|
||||||
*/
|
|
||||||
@Data
|
|
||||||
public class ModbusPollMsg {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 下发指令
|
|
||||||
*/
|
|
||||||
private List<String> commandList;
|
|
||||||
/**
|
|
||||||
* 服务端类型
|
|
||||||
*/
|
|
||||||
private Integer serverType;
|
|
||||||
/**
|
|
||||||
* 产品id
|
|
||||||
*/
|
|
||||||
private Long productId;
|
|
||||||
/**
|
|
||||||
* 设备编码
|
|
||||||
*/
|
|
||||||
private String serialNumber;
|
|
||||||
|
|
||||||
private String transport;
|
|
||||||
}
|
|
||||||
@@ -1,26 +0,0 @@
|
|||||||
package com.maibu.core.mq.message;
|
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
|
||||||
import lombok.Data;
|
|
||||||
|
|
||||||
import java.util.Date;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author bill
|
|
||||||
*/
|
|
||||||
@Data
|
|
||||||
public class MqttBo {
|
|
||||||
|
|
||||||
/*主题*/
|
|
||||||
private String topic;
|
|
||||||
/*数据*/
|
|
||||||
private String data;
|
|
||||||
/*消息质量*/
|
|
||||||
private int qos = 1;
|
|
||||||
/*发送方向*/
|
|
||||||
private String direction;
|
|
||||||
/*时间*/
|
|
||||||
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
|
|
||||||
private Date ts;
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1,39 +0,0 @@
|
|||||||
package com.maibu.core.mq.message;
|
|
||||||
|
|
||||||
import com.maibu.core.protocol.modbus.ModbusCode;
|
|
||||||
import lombok.Data;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author gsb
|
|
||||||
* @date 2022/12/9 10:15
|
|
||||||
*/
|
|
||||||
@Data
|
|
||||||
public class PropRead {
|
|
||||||
|
|
||||||
/**设备编号*/
|
|
||||||
private String serialNumber;
|
|
||||||
/**寄存器起始地址*/
|
|
||||||
private int address;
|
|
||||||
/**
|
|
||||||
* 读取寄存器个数
|
|
||||||
*/
|
|
||||||
private int count;
|
|
||||||
/**数据结果长度计算值*/
|
|
||||||
private int length;
|
|
||||||
/**
|
|
||||||
* 从机地址
|
|
||||||
*/
|
|
||||||
private int slaveId;
|
|
||||||
/**
|
|
||||||
* 读取个数
|
|
||||||
*/
|
|
||||||
private int quantity;
|
|
||||||
/**
|
|
||||||
* 数据
|
|
||||||
*/
|
|
||||||
private String data;
|
|
||||||
/**
|
|
||||||
* 功能码
|
|
||||||
*/
|
|
||||||
private ModbusCode code;
|
|
||||||
}
|
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
package com.maibu.core.mq.message;
|
|
||||||
|
|
||||||
import lombok.Data;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 协议bean
|
|
||||||
* @author gsb
|
|
||||||
* @date 2022/10/25 14:54
|
|
||||||
*/
|
|
||||||
@Data
|
|
||||||
public class ProtocolDto {
|
|
||||||
|
|
||||||
/**协议编号*/
|
|
||||||
private String code;
|
|
||||||
private String name;
|
|
||||||
/*外部协议url*/
|
|
||||||
private String protocolUrl;
|
|
||||||
private String description;
|
|
||||||
/**协议类型 协议类型 0:系统协议 1:jar,2.js,3.c*/
|
|
||||||
private Integer protocolType;
|
|
||||||
}
|
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
package com.maibu.core.mq.message;
|
|
||||||
|
|
||||||
import lombok.Data;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 网关子设备model
|
|
||||||
* @author gsb
|
|
||||||
* @date 2022/10/10 10:18
|
|
||||||
*/
|
|
||||||
@Data
|
|
||||||
public class SubDeviceMessage {
|
|
||||||
/*子设备编号或编码*/
|
|
||||||
private String serialNumber;
|
|
||||||
/*数据*/
|
|
||||||
private byte[] data;
|
|
||||||
/*消息id*/
|
|
||||||
private String messageId;
|
|
||||||
}
|
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
package com.maibu.core.mq.ota;
|
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
|
||||||
import lombok.Data;
|
|
||||||
|
|
||||||
import java.math.BigDecimal;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* OTA升级回复model
|
|
||||||
* @author gsb
|
|
||||||
* @date 2022/10/24 17:20
|
|
||||||
*/
|
|
||||||
@Data
|
|
||||||
@JsonInclude(JsonInclude.Include.NON_EMPTY)
|
|
||||||
public class OtaReplyMessage {
|
|
||||||
|
|
||||||
private Long taskId;
|
|
||||||
private BigDecimal version;
|
|
||||||
private int status;
|
|
||||||
private int progress;
|
|
||||||
}
|
|
||||||
@@ -1,40 +0,0 @@
|
|||||||
package com.maibu.core.mq.ota;
|
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
|
||||||
import lombok.Builder;
|
|
||||||
import lombok.Data;
|
|
||||||
|
|
||||||
import java.math.BigDecimal;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* OTA远程升级
|
|
||||||
* @author gsb
|
|
||||||
* @date 2022/10/10 10:22
|
|
||||||
*/
|
|
||||||
@Data
|
|
||||||
@Builder
|
|
||||||
@JsonInclude(JsonInclude.Include.NON_EMPTY)
|
|
||||||
public class OtaUpgradeBo {
|
|
||||||
|
|
||||||
// 设备编码
|
|
||||||
private String serialNumber;
|
|
||||||
// 升级任务ID
|
|
||||||
private Long taskId;
|
|
||||||
// 消息内容
|
|
||||||
private byte[] msg;
|
|
||||||
// 设备状态
|
|
||||||
private int status;
|
|
||||||
// topic
|
|
||||||
private String topicName;
|
|
||||||
// 固件包版本
|
|
||||||
private BigDecimal version;
|
|
||||||
// 固件包http地址
|
|
||||||
private String url;
|
|
||||||
// 固件包分包传输大小
|
|
||||||
private int packageSize;
|
|
||||||
// 固件包传输偏移量
|
|
||||||
private int offset;
|
|
||||||
// 升级进度
|
|
||||||
private int progress;
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,63 +0,0 @@
|
|||||||
package com.maibu.core.mq.ota;
|
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
|
||||||
import com.maibu.utils.DateUtils;
|
|
||||||
import lombok.Data;
|
|
||||||
|
|
||||||
import java.util.Date;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.concurrent.Delayed;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* ota升级发送,实现Delayed延时接口
|
|
||||||
*
|
|
||||||
* @author bill
|
|
||||||
*/
|
|
||||||
@Data
|
|
||||||
public class OtaUpgradeDelayTask implements Delayed {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 固件id
|
|
||||||
*/
|
|
||||||
private Long firmwareId;
|
|
||||||
/**
|
|
||||||
* 1:指定产品 2:指定设备
|
|
||||||
*/
|
|
||||||
private Long upgradeType;
|
|
||||||
|
|
||||||
private List<String> devices;
|
|
||||||
/**
|
|
||||||
* 任务id
|
|
||||||
*/
|
|
||||||
private Long taskId;
|
|
||||||
/**
|
|
||||||
* 开始升级时间
|
|
||||||
*/
|
|
||||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
|
|
||||||
private Date startTime;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 设置延迟执行时间 开始升级时间 -当前时间
|
|
||||||
*
|
|
||||||
* @param unit
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public long getDelay(TimeUnit unit) {
|
|
||||||
return startTime.getTime() - DateUtils.getTimestamp();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int compareTo(Delayed o) {
|
|
||||||
OtaUpgradeDelayTask delayTask = (OtaUpgradeDelayTask) o;
|
|
||||||
//比较
|
|
||||||
long diff = this.startTime.getTime() - delayTask.startTime.getTime();
|
|
||||||
if (diff <= 0) {
|
|
||||||
return -1;
|
|
||||||
} else {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
package com.maibu.core.ota;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.annotation.IdType;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableId;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||||
|
import com.maibu.core.domain.BaseDO;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
|
||||||
|
|
||||||
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||||
|
@Data
|
||||||
|
@TableName("iot_ota_firmware")
|
||||||
|
public class DeviceOtaFirmware extends BaseDO {
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
@TableId(type = IdType.AUTO)
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
private String version; //版本号
|
||||||
|
|
||||||
|
private String fileName; //文件名
|
||||||
|
|
||||||
|
private String minioObjectName; //服务器文件名
|
||||||
|
|
||||||
|
private String fileUrl; //存放地址
|
||||||
|
|
||||||
|
private String deviceType;
|
||||||
|
|
||||||
|
private String fileSize;
|
||||||
|
|
||||||
|
private String description;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
package com.maibu.core.ota;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.annotation.IdType;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableId;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||||
|
import com.maibu.core.domain.BaseDO;
|
||||||
|
import com.maibu.core.enums.OtaOperate;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
|
||||||
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||||
|
@Data
|
||||||
|
@TableName(value = "iot_ota_operate_record", autoResultMap = true)
|
||||||
|
public class DeviceOtaOperateRecord extends BaseDO {
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
@TableId(type = IdType.AUTO)
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
private OtaOperate operateType; // 操作类型
|
||||||
|
|
||||||
|
private String fileName; // 名称
|
||||||
|
|
||||||
|
private Long firmwareId; // id
|
||||||
|
|
||||||
|
private String deviceId; // 名称
|
||||||
|
|
||||||
|
private String deviceType;
|
||||||
|
|
||||||
|
private String preVersion;
|
||||||
|
|
||||||
|
private String nowVersion;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,45 +0,0 @@
|
|||||||
package com.maibu.core.ota;
|
|
||||||
|
|
||||||
import com.maibu.exception.ServiceException;
|
|
||||||
import lombok.AllArgsConstructor;
|
|
||||||
import lombok.Getter;
|
|
||||||
|
|
||||||
@Getter
|
|
||||||
@AllArgsConstructor
|
|
||||||
public enum OtaPackageCode {
|
|
||||||
|
|
||||||
OTA_01("查询产品工装号",(byte) 0x01),
|
|
||||||
OTA_0A("OTA升级启动",(byte) 0x0A),
|
|
||||||
OTA_0B("OTA升级包传输",(byte) 0x0B)
|
|
||||||
;
|
|
||||||
|
|
||||||
private String desc;
|
|
||||||
private byte code;
|
|
||||||
|
|
||||||
public static OtaPackageCode getInstance(int code) {
|
|
||||||
switch ((byte)code) {
|
|
||||||
case 0x01:
|
|
||||||
return OTA_01;
|
|
||||||
case 0x0A:
|
|
||||||
return OTA_0A;
|
|
||||||
case 0x0B:
|
|
||||||
return OTA_0B;
|
|
||||||
default:
|
|
||||||
throw new ServiceException("功能码[" + code + "],未定义");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static String getDes(int code){
|
|
||||||
switch ((byte)code) {
|
|
||||||
case 0x01:
|
|
||||||
return OTA_01.desc;
|
|
||||||
case 0x0A:
|
|
||||||
return OTA_0A.desc;
|
|
||||||
case 0x0B:
|
|
||||||
return OTA_0B.desc;
|
|
||||||
default:
|
|
||||||
return "UNKOWN";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
package com.maibu.mapper;
|
||||||
|
|
||||||
|
import com.maibu.core.ota.DeviceOtaFirmware;
|
||||||
|
import com.maibu.mybatis.mapper.BaseMapperX;
|
||||||
|
import org.springframework.stereotype.Repository;
|
||||||
|
|
||||||
|
|
||||||
|
@Repository
|
||||||
|
public interface DeviceOtaFirmwareMapper extends BaseMapperX<DeviceOtaFirmware> {
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
package com.maibu.mapper;
|
||||||
|
|
||||||
|
import com.maibu.core.ota.DeviceOtaOperateRecord;
|
||||||
|
import com.maibu.mybatis.mapper.BaseMapperX;
|
||||||
|
import org.springframework.stereotype.Repository;
|
||||||
|
|
||||||
|
|
||||||
|
@Repository
|
||||||
|
public interface DeviceOtaOperateRecordMapper extends BaseMapperX<DeviceOtaOperateRecord> {
|
||||||
|
|
||||||
|
}
|
||||||
@@ -5,8 +5,12 @@ import com.maibu.core.business.device.Connector;
|
|||||||
import com.maibu.core.business.device.NettyDevice;
|
import com.maibu.core.business.device.NettyDevice;
|
||||||
import com.maibu.core.enums.ConnectorStatus;
|
import com.maibu.core.enums.ConnectorStatus;
|
||||||
import com.maibu.core.enums.ConnectorType;
|
import com.maibu.core.enums.ConnectorType;
|
||||||
|
import com.maibu.utils.json.JsonUtils;
|
||||||
|
|
||||||
import io.netty.channel.Channel;
|
import io.netty.channel.Channel;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
@@ -23,6 +27,7 @@ import java.util.stream.Collectors;
|
|||||||
*/
|
*/
|
||||||
@Component
|
@Component
|
||||||
@Data
|
@Data
|
||||||
|
@Slf4j
|
||||||
public class DeviceSessionManager {
|
public class DeviceSessionManager {
|
||||||
|
|
||||||
private static final Logger logger = LoggerFactory.getLogger(DeviceSessionManager.class);
|
private static final Logger logger = LoggerFactory.getLogger(DeviceSessionManager.class);
|
||||||
@@ -187,7 +192,7 @@ public class DeviceSessionManager {
|
|||||||
public List<NettyDevice> getSlaveControl(String slaveId) {
|
public List<NettyDevice> getSlaveControl(String slaveId) {
|
||||||
// 获取所有连接的主机 且是active状态的
|
// 获取所有连接的主机 且是active状态的
|
||||||
return deviceMap.values().stream()
|
return deviceMap.values().stream()
|
||||||
.filter(device -> ObjectUtil.equals(device.getCurrentSlaveId(), slaveId)
|
.filter(device -> Objects.equals(device.getCurrentSlaveId(), slaveId)
|
||||||
&& ConnectorStatus.ACTIVE.equals(device.getConnectorStatus()))
|
&& ConnectorStatus.ACTIVE.equals(device.getConnectorStatus()))
|
||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
}
|
}
|
||||||
@@ -195,14 +200,16 @@ public class DeviceSessionManager {
|
|||||||
public List<NettyDevice> getAllSlaveControl(String slaveId) {
|
public List<NettyDevice> getAllSlaveControl(String slaveId) {
|
||||||
// 获取所有连接的主机 不区分状态
|
// 获取所有连接的主机 不区分状态
|
||||||
return deviceMap.values().stream()
|
return deviceMap.values().stream()
|
||||||
.filter(device -> ObjectUtil.equals(device.getCurrentSlaveId(), slaveId))
|
.filter(device -> !StringUtils.isEmpty(device.getCurrentSlaveId())
|
||||||
|
&& Objects.equals(device.getCurrentSlaveId(), slaveId)
|
||||||
|
&& device.getDeviceType().equals(ConnectorType.MASTER))
|
||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
}
|
}
|
||||||
|
|
||||||
public NettyDevice getCurrentControl(String slaveId) {
|
public NettyDevice getCurrentControl(String slaveId) {
|
||||||
// 获取所有连接的主机 不区分状态
|
// 获取所有连接的主机 不区分状态
|
||||||
return deviceMap.values().stream()
|
return deviceMap.values().stream()
|
||||||
.filter(device -> ObjectUtil.equals(device.getCurrentSlaveId(), slaveId)
|
.filter(device -> Objects.equals(device.getCurrentSlaveId(), slaveId)
|
||||||
&& ConnectorStatus.ACTIVE.equals(device.getConnectorStatus()))
|
&& ConnectorStatus.ACTIVE.equals(device.getConnectorStatus()))
|
||||||
.findFirst().orElse(null);
|
.findFirst().orElse(null);
|
||||||
}
|
}
|
||||||
@@ -312,8 +319,11 @@ public class DeviceSessionManager {
|
|||||||
if (taskId == null) {
|
if (taskId == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
log.debug("sendMessage deviceMap:{},taskId={}", JsonUtils.toJsonString(deviceMap), taskId);
|
||||||
for (String key : deviceMap.keySet()) {
|
for (String key : deviceMap.keySet()) {
|
||||||
NettyDevice nettyDevice = deviceMap.get(key);
|
NettyDevice nettyDevice = deviceMap.get(key);
|
||||||
|
log.debug("sendMessage currentTaskId:{},equal {}", JsonUtils.toJsonString(nettyDevice.getCurrentTaskId()),
|
||||||
|
Objects.equals(nettyDevice.getCurrentTaskId(), taskId));
|
||||||
if (nettyDevice != null && Objects.equals(nettyDevice.getCurrentTaskId(), taskId)) {
|
if (nettyDevice != null && Objects.equals(nettyDevice.getCurrentTaskId(), taskId)) {
|
||||||
return nettyDevice.getConnectorId();
|
return nettyDevice.getConnectorId();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -111,7 +111,8 @@ public class GlobalMemory {
|
|||||||
MqttTopic.MOWER_WILDCARD_TASK_STATUS,//任务状态
|
MqttTopic.MOWER_WILDCARD_TASK_STATUS,//任务状态
|
||||||
MqttTopic.MOWER_WILDCARD_ERROR,//错误
|
MqttTopic.MOWER_WILDCARD_ERROR,//错误
|
||||||
MqttTopic.MOWER_WILDCARD_REALTIME, //状态消息
|
MqttTopic.MOWER_WILDCARD_REALTIME, //状态消息
|
||||||
MqttTopic.MOWER_WILDCARD_TASK_TARGET_REPLY //路径规划下发回复
|
MqttTopic.MOWER_WILDCARD_TASK_TARGET_REPLY, //路径规划下发回复
|
||||||
|
MqttTopic.MOWER_OTA_RESULT_POST
|
||||||
));
|
));
|
||||||
deviceConfig.setHandlerType(Constant.mqttHandleKey); //唯一的 用于处理上位机mqtt的
|
deviceConfig.setHandlerType(Constant.mqttHandleKey); //唯一的 用于处理上位机mqtt的
|
||||||
customMqttDeviceMonitor.registerDevice(deviceConfig);
|
customMqttDeviceMonitor.registerDevice(deviceConfig);
|
||||||
|
|||||||
@@ -63,10 +63,13 @@ public class SiteMemory {
|
|||||||
return deviceMapPushMap;
|
return deviceMapPushMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void saveMaPushDTO(String deviceId, DeviceMapPushDTO dto) {
|
public void saveMapPushDTO(String deviceId, DeviceMapPushDTO dto) {
|
||||||
deviceMapPushMap.put(deviceId, dto);
|
deviceMapPushMap.put(deviceId, dto);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void removeMapPushDTO(String deviceId) {
|
||||||
|
deviceMapPushMap.remove(deviceId);
|
||||||
|
}
|
||||||
|
|
||||||
public void saveRunStatistics(DeviceRunStatistics deviceRunStatistics) {
|
public void saveRunStatistics(DeviceRunStatistics deviceRunStatistics) {
|
||||||
if (deviceRunStatistics != null && !StringUtils.isEmpty(deviceRunStatistics.getDeviceId())) {
|
if (deviceRunStatistics != null && !StringUtils.isEmpty(deviceRunStatistics.getDeviceId())) {
|
||||||
|
|||||||
@@ -1,29 +1,18 @@
|
|||||||
package com.maibu.mqtt;
|
package com.maibu.mqtt;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import com.maibu.core.business.dto.DeviceMapPushDTO;
|
|
||||||
import org.springframework.util.CollectionUtils;
|
|
||||||
|
|
||||||
import com.fasterxml.jackson.databind.JsonNode;
|
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
import com.maibu.constant.Constant;
|
import com.maibu.constant.Constant;
|
||||||
import com.maibu.constant.NettyCacheKey;
|
import com.maibu.constant.NettyCacheKey;
|
||||||
import com.maibu.core.business.DeviceRunStatistics;
|
import com.maibu.core.business.DeviceRunStatistics;
|
||||||
import com.maibu.core.business.device.DeviceStatusDetail;
|
import com.maibu.core.business.device.DeviceStatusDetail;
|
||||||
import com.maibu.core.business.device.NettyDevice;
|
import com.maibu.core.business.device.NettyDevice;
|
||||||
|
import com.maibu.core.business.dto.DeviceMapPushDTO;
|
||||||
import com.maibu.core.business.dto.WebDeviceTaskStatusMessageDTO;
|
import com.maibu.core.business.dto.WebDeviceTaskStatusMessageDTO;
|
||||||
import com.maibu.core.business.dto.WebStatusMessageDTO;
|
import com.maibu.core.business.dto.WebStatusMessageDTO;
|
||||||
import com.maibu.core.business.inter.WebsocketMesDispather;
|
import com.maibu.core.business.inter.WebsocketMesDispather;
|
||||||
import com.maibu.core.enums.DeviceTaskStaus;
|
import com.maibu.core.enums.DeviceTaskStaus;
|
||||||
import com.maibu.core.enums.MesType;
|
import com.maibu.core.enums.MesType;
|
||||||
import com.maibu.core.host.HeartBeatDTO;
|
import com.maibu.core.host.*;
|
||||||
import com.maibu.core.host.HostLocationRelTimeDTO;
|
|
||||||
import com.maibu.core.host.HostNavigationReplyDTO;
|
|
||||||
import com.maibu.core.host.HostTaskStatusDTO;
|
|
||||||
import com.maibu.core.host.HostVehicleRelTimeDTO;
|
|
||||||
import com.maibu.core.host.LocationMessage;
|
|
||||||
import com.maibu.core.redis.RedisCache;
|
import com.maibu.core.redis.RedisCache;
|
||||||
import com.maibu.enums.DeviceStatusEnum;
|
import com.maibu.enums.DeviceStatusEnum;
|
||||||
import com.maibu.memory.DeviceSessionManager;
|
import com.maibu.memory.DeviceSessionManager;
|
||||||
@@ -32,17 +21,19 @@ import com.maibu.memory.SiteMemory;
|
|||||||
import com.maibu.utils.StringUtils;
|
import com.maibu.utils.StringUtils;
|
||||||
import com.maibu.utils.json.JsonUtils;
|
import com.maibu.utils.json.JsonUtils;
|
||||||
import com.maibu.utils.spring.SpringUtils;
|
import com.maibu.utils.spring.SpringUtils;
|
||||||
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.eclipse.paho.client.mqttv3.MqttException;
|
||||||
|
import org.springframework.util.CollectionUtils;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* mqtt相关的 上位机处理器
|
* mqtt相关的 上位机处理器
|
||||||
*/
|
*/
|
||||||
@Slf4j
|
@Slf4j
|
||||||
public class HostMessageHandler implements CustomMqttMessageHandler {
|
public class HostMessageHandler implements CustomMqttMessageHandler {
|
||||||
|
|
||||||
private final ObjectMapper objectMapper = new ObjectMapper();
|
|
||||||
|
|
||||||
private final DeviceSessionManager deviceSessionManager = SpringUtils.getBean(DeviceSessionManager.class);
|
private final DeviceSessionManager deviceSessionManager = SpringUtils.getBean(DeviceSessionManager.class);
|
||||||
|
|
||||||
private final WebsocketMesDispather websocketMesDispather = SpringUtils.getBean(WebsocketMesDispather.class);
|
private final WebsocketMesDispather websocketMesDispather = SpringUtils.getBean(WebsocketMesDispather.class);
|
||||||
@@ -113,6 +104,9 @@ public class HostMessageHandler implements CustomMqttMessageHandler {
|
|||||||
case "route_reply":
|
case "route_reply":
|
||||||
handleRouteReply(deviceId, topic, payload);
|
handleRouteReply(deviceId, topic, payload);
|
||||||
break;
|
break;
|
||||||
|
case "upgrade_reply":
|
||||||
|
handleUpgradeReply(deviceId, topic, payload);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
log.debug("割草机消息: deviceId={}, topic={}, action={}", deviceId, topic, action);
|
log.debug("割草机消息: deviceId={}, topic={}, action={}", deviceId, topic, action);
|
||||||
break;
|
break;
|
||||||
@@ -164,11 +158,17 @@ public class HostMessageHandler implements CustomMqttMessageHandler {
|
|||||||
String deviceId) {
|
String deviceId) {
|
||||||
WebStatusMessageDTO webStatusMessageDTO = new WebStatusMessageDTO();
|
WebStatusMessageDTO webStatusMessageDTO = new WebStatusMessageDTO();
|
||||||
List<DeviceStatusDetail> transferData = new ArrayList<>();
|
List<DeviceStatusDetail> transferData = new ArrayList<>();
|
||||||
|
|
||||||
|
DeviceStatusDetail d = new DeviceStatusDetail();
|
||||||
|
d.setName("deviceId");
|
||||||
|
d.setValue(deviceId);
|
||||||
|
d.setUnit("");
|
||||||
|
transferData.add(d);
|
||||||
|
|
||||||
DeviceStatusDetail lat = new DeviceStatusDetail();
|
DeviceStatusDetail lat = new DeviceStatusDetail();
|
||||||
lat.setName("latitude");
|
lat.setName("latitude");
|
||||||
lat.setValue(String.valueOf(locationRelTimeDTO.getData().getLatitude()));
|
lat.setValue(String.valueOf(locationRelTimeDTO.getData().getLatitude()));
|
||||||
lat.setUnit("");
|
lat.setUnit("");
|
||||||
|
|
||||||
transferData.add(lat);
|
transferData.add(lat);
|
||||||
|
|
||||||
DeviceStatusDetail lng = new DeviceStatusDetail();
|
DeviceStatusDetail lng = new DeviceStatusDetail();
|
||||||
@@ -227,15 +227,15 @@ public class HostMessageHandler implements CustomMqttMessageHandler {
|
|||||||
DeviceMapPushDTO dto = new DeviceMapPushDTO();
|
DeviceMapPushDTO dto = new DeviceMapPushDTO();
|
||||||
dto.setA(Double.parseDouble(altitude.getValue()));
|
dto.setA(Double.parseDouble(altitude.getValue()));
|
||||||
dto.setId(deviceId);
|
dto.setId(deviceId);
|
||||||
// dto.setB();
|
// dto.setB();
|
||||||
// dto.setHa();
|
// dto.setHa();
|
||||||
dto.setF(fix_status.getValue());
|
dto.setF(fix_status.getValue());
|
||||||
dto.setS(status.getValue());
|
dto.setS(status.getValue());
|
||||||
dto.setLat(Double.parseDouble(lat.getValue()));
|
dto.setLat(Double.parseDouble(lat.getValue()));
|
||||||
dto.setLng(Double.parseDouble(lng.getValue()));
|
dto.setLng(Double.parseDouble(lng.getValue()));
|
||||||
dto.setT(nettyDevice.getCurrentTaskId());
|
dto.setT(nettyDevice.getCurrentTaskId());
|
||||||
dto.setY(Double.parseDouble(yaw.getValue()));
|
dto.setY(Double.parseDouble(yaw.getValue()));
|
||||||
siteMemory.saveMaPushDTO(deviceId, dto);
|
siteMemory.saveMapPushDTO(deviceId, dto);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -376,6 +376,15 @@ public class HostMessageHandler implements CustomMqttMessageHandler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// todo 推送实时位置和状态消息到外部
|
||||||
|
try {
|
||||||
|
GlobalMemory.customMqttDeviceMonitor.publish(mqttClientId,
|
||||||
|
String.format(MqttTopic.DEVICE_TASK_STATUS_TOPIC, taskId),
|
||||||
|
JsonUtils.toJsonString(sendDto));
|
||||||
|
} catch (MqttException e) {
|
||||||
|
// TODO Auto-generated catch block
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
if ("cancelled".equals(dto.getStatus())) {
|
if ("cancelled".equals(dto.getStatus())) {
|
||||||
@@ -431,6 +440,23 @@ public class HostMessageHandler implements CustomMqttMessageHandler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理控制指令响应
|
||||||
|
*/
|
||||||
|
private void handleUpgradeReply(String deviceId, String topic, String payload) {
|
||||||
|
// log.debug("【路径任务下发响应】deviceId={}, payload={}", deviceId, payload);
|
||||||
|
//
|
||||||
|
// // todo 更新任务接收状态
|
||||||
|
// HostNavigationReplyDTO replyDTO = JsonUtils.parseObject(payload, HostNavigationReplyDTO.class);
|
||||||
|
// NettyDevice device = deviceSessionManager.getDevice(deviceId);
|
||||||
|
// if (replyDTO.isAccepted()) {
|
||||||
|
// if (device != null && device.getTask() != null
|
||||||
|
// && String.valueOf(device.getTask().getId()).equals(replyDTO.getTask_id())) {
|
||||||
|
// device.getTask().setTaskAccepted(true);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 从 Topic 中解析 deviceId
|
* 从 Topic 中解析 deviceId
|
||||||
* Topic 格式:mower/{deviceId}/...
|
* Topic 格式:mower/{deviceId}/...
|
||||||
@@ -481,6 +507,9 @@ public class HostMessageHandler implements CustomMqttMessageHandler {
|
|||||||
return "control_reply";
|
return "control_reply";
|
||||||
if (remaining.equals("task/target/reply"))
|
if (remaining.equals("task/target/reply"))
|
||||||
return "route_reply";
|
return "route_reply";
|
||||||
|
if (remaining.equals("/ota/result/post"))
|
||||||
|
return "upgrade_reply";
|
||||||
|
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,15 +2,15 @@ package com.maibu.mqtt;
|
|||||||
|
|
||||||
public class MqttTopic {
|
public class MqttTopic {
|
||||||
|
|
||||||
/** @deprecated 通用设备主题,建议使用 MOWER_* 系列主题 */
|
/** 通用设备主题,建议使用 MOWER_* 系列主题 */
|
||||||
public static final String DEVICE_STATUS_TOPIC = "device/%s/realTimeMessage";
|
public static final String DEVICE_STATUS_TOPIC = "device/%s/realTimeMessage";
|
||||||
|
|
||||||
public static final String DEVICE_LOCATION_TOPIC = "device/%s/locationMessage";
|
public static final String DEVICE_LOCATION_TOPIC = "device/%s/locationMessage";
|
||||||
/** @deprecated 通用设备主题,建议使用 MOWER_* 系列主题 */
|
/** 通用设备主题,建议使用 MOWER_* 系列主题 */
|
||||||
public static final String DEVICE_TASK_STATUS_TOPIC = "task/%s/status";
|
public static final String DEVICE_TASK_STATUS_TOPIC = "task/%s/status";
|
||||||
/** @deprecated 通用设备主题,建议使用 MOWER_* 系列主题 */
|
/** 通用设备主题,建议使用 MOWER_* 系列主题 */
|
||||||
public static final String DEVICE_TASK_ARRIVE_TOPIC = "task/%s/arrive";
|
public static final String DEVICE_TASK_ARRIVE_TOPIC = "task/%s/arrive";
|
||||||
/** @deprecated 通用设备主题,建议使用 MOWER_* 系列主题 */
|
/** 通用设备主题,建议使用 MOWER_* 系列主题 */
|
||||||
public static final String DEVICE_ERROR_PUSH_TOPIC = "device/%s/error";
|
public static final String DEVICE_ERROR_PUSH_TOPIC = "device/%s/error";
|
||||||
public static final String DEVICE_ROUTE_PUSH_TOPIC = "device/%s/route/post";
|
public static final String DEVICE_ROUTE_PUSH_TOPIC = "device/%s/route/post";
|
||||||
|
|
||||||
@@ -64,15 +64,12 @@ public class MqttTopic {
|
|||||||
public static final String MOWER_ERROR_POST = "mower/%s/event/error/post";
|
public static final String MOWER_ERROR_POST = "mower/%s/event/error/post";
|
||||||
|
|
||||||
// ==================== OTA 固件升级 ====================
|
// ==================== OTA 固件升级 ====================
|
||||||
// /** 下发 OTA 升级指令(平台->设备) */
|
/** 下发 OTA 升级指令(平台->设备) */
|
||||||
// public static final String MOWER_OTA_UPGRADE_SET =
|
public static final String MOWER_OTA_UPGRADE_SET = "mower/%s/ota/upgrade/set";
|
||||||
// "mower/%s/ota/upgrade/set";
|
/** OTA 升级进度上报(设备->平台) */
|
||||||
// /** OTA 升级进度上报(设备->平台) */
|
public static final String MOWER_OTA_PROGRESS_POST = "mower/+/ota/progress/post";
|
||||||
// public static final String MOWER_OTA_PROGRESS_POST =
|
/** OTA 升级结果上报(设备->平台) */
|
||||||
// "mower/%s/ota/progress/post";
|
public static final String MOWER_OTA_RESULT_POST = "mower/+/ota/result/post";
|
||||||
// /** OTA 升级结果上报(设备->平台) */
|
|
||||||
// public static final String MOWER_OTA_RESULT_POST =
|
|
||||||
// "mower/%s/ota/result/post";
|
|
||||||
|
|
||||||
// ==================== 设备信息 ====================
|
// ==================== 设备信息 ====================
|
||||||
// /** 查询设备信息(平台->设备) */
|
// /** 查询设备信息(平台->设备) */
|
||||||
|
|||||||
@@ -1,9 +1,6 @@
|
|||||||
package com.maibu.utils;
|
package com.maibu.utils;
|
||||||
|
|
||||||
import io.minio.BucketExistsArgs;
|
import io.minio.*;
|
||||||
import io.minio.MakeBucketArgs;
|
|
||||||
import io.minio.MinioClient;
|
|
||||||
import io.minio.PutObjectArgs;
|
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
@@ -44,6 +41,15 @@ public class MinioUtil {
|
|||||||
// 拼接 public URL
|
// 拼接 public URL
|
||||||
return endpoint + "/" + defaultBucket + "/" + objectName;
|
return endpoint + "/" + defaultBucket + "/" + objectName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void deleteFile(String objectName) throws Exception {
|
||||||
|
minioClient.removeObject(
|
||||||
|
RemoveObjectArgs.builder()
|
||||||
|
.bucket(defaultBucket)
|
||||||
|
.object(objectName)
|
||||||
|
.build()
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -220,7 +220,7 @@ public class DeviceConnectHandler extends SimpleChannelInboundHandler<String> {
|
|||||||
device.setDeviceName(data);
|
device.setDeviceName(data);
|
||||||
device.setProductId(-1L);
|
device.setProductId(-1L);
|
||||||
device.setTenantId(-1L);
|
device.setTenantId(-1L);
|
||||||
device.setFirmwareVersion(BigDecimal.valueOf(1.0));
|
device.setFirmwareVersion("1.0");
|
||||||
device.setProductName("割草机产品MC700");
|
device.setProductName("割草机产品MC700");
|
||||||
device.setCreateTime(LocalDateTime.now());
|
device.setCreateTime(LocalDateTime.now());
|
||||||
device.setUpdateTime(LocalDateTime.now());
|
device.setUpdateTime(LocalDateTime.now());
|
||||||
|
|||||||
@@ -453,9 +453,9 @@ public class DeviceTaskService {
|
|||||||
x.setTaskStausTranslate(taskStaus.getDescription());
|
x.setTaskStausTranslate(taskStaus.getDescription());
|
||||||
});
|
});
|
||||||
list.sort(
|
list.sort(
|
||||||
Comparator.comparing(DevicePlanTask::getFinishTime,
|
Comparator.comparing(DevicePlanTask::getCreateTime,
|
||||||
Comparator.nullsLast(Comparator.reverseOrder()))
|
Comparator.nullsLast(Comparator.reverseOrder()))
|
||||||
.thenComparing(DevicePlanTask::getCreateTime,
|
.thenComparing(DevicePlanTask::getFinishTime,
|
||||||
Comparator.nullsLast(Comparator.reverseOrder())));
|
Comparator.nullsLast(Comparator.reverseOrder())));
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -223,7 +223,7 @@ public class DeviceThreadService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public List<AlarmMessage> compareErrorStandard(Long siteId, Long orgId, DeviceRunningStatusHistory history,
|
public List<AlarmMessage> compareErrorStandard(Long siteId, Long orgId, DeviceRunningStatusHistory history,
|
||||||
List<ErrorIdentificationStandard> standards) {
|
List<ErrorIdentificationStandard> standards) {
|
||||||
if (history == null || CollectionUtils.isEmpty(standards))
|
if (history == null || CollectionUtils.isEmpty(standards))
|
||||||
return null;
|
return null;
|
||||||
List<AlarmMessage> list = new ArrayList<>();
|
List<AlarmMessage> list = new ArrayList<>();
|
||||||
@@ -343,6 +343,8 @@ public class DeviceThreadService {
|
|||||||
}
|
}
|
||||||
deviceRunStatisticsMapper.saveOrUpdate(deviceRunStatistics);
|
deviceRunStatisticsMapper.saveOrUpdate(deviceRunStatistics);
|
||||||
}
|
}
|
||||||
|
// todo 删除实时消息推送里面的数据
|
||||||
|
siteMemory.removeMapPushDTO(deviceId);
|
||||||
}
|
}
|
||||||
|
|
||||||
sessionManager.removeDevice(deviceId);
|
sessionManager.removeDevice(deviceId);
|
||||||
@@ -359,7 +361,7 @@ public class DeviceThreadService {
|
|||||||
device.setDeviceName(deviceId);
|
device.setDeviceName(deviceId);
|
||||||
device.setProductId(-1L);
|
device.setProductId(-1L);
|
||||||
device.setTenantId(-1L);
|
device.setTenantId(-1L);
|
||||||
device.setFirmwareVersion(BigDecimal.valueOf(1.0));
|
device.setFirmwareVersion("1.0");
|
||||||
device.setProductName("割草机产品MC700");
|
device.setProductName("割草机产品MC700");
|
||||||
device.setCreateTime(LocalDateTime.now());
|
device.setCreateTime(LocalDateTime.now());
|
||||||
device.setUpdateTime(LocalDateTime.now());
|
device.setUpdateTime(LocalDateTime.now());
|
||||||
@@ -393,7 +395,6 @@ public class DeviceThreadService {
|
|||||||
}, 0, 500, TimeUnit.MILLISECONDS);
|
}, 0, 500, TimeUnit.MILLISECONDS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 监控心跳
|
* 监控心跳
|
||||||
*/
|
*/
|
||||||
@@ -404,18 +405,16 @@ public class DeviceThreadService {
|
|||||||
if (!CollectionUtils.isEmpty(list)) {
|
if (!CollectionUtils.isEmpty(list)) {
|
||||||
list.forEach(x -> {
|
list.forEach(x -> {
|
||||||
Map<String, DeviceMapPushDTO> map = x.getAllDeviceMapPush();
|
Map<String, DeviceMapPushDTO> map = x.getAllDeviceMapPush();
|
||||||
if (!CollectionUtils.isEmpty(map)) {
|
List<DeviceMapPushDTO> pushList = new ArrayList<>(map.values());
|
||||||
List<DeviceMapPushDTO> pushList = new ArrayList<>(map.values());
|
WebMapMessageDTO dto = new WebMapMessageDTO();
|
||||||
WebMapMessageDTO dto = new WebMapMessageDTO();
|
dto.setData(pushList);
|
||||||
dto.setData(pushList);
|
dto.setType(MesType.mapPush);
|
||||||
dto.setType(MesType.mapPush);
|
try {
|
||||||
try {
|
websocketMesDispather.mapMessageDispather(x.getSiteId(),
|
||||||
websocketMesDispather.mapMessageDispather(x.getSiteId(), JsonUtils.toJsonString(pushList));
|
JsonUtils.toJsonString(dto));
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.error("实时地图数据websocket推送失败: siteId={}, error={}", x.getSiteId(),
|
log.error("实时地图数据websocket推送失败: siteId={}, error={}", x.getSiteId(),
|
||||||
e.getMessage(), e);
|
e.getMessage(), e);
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,129 @@
|
|||||||
|
package com.maibu.controller;
|
||||||
|
|
||||||
|
import com.maibu.core.controller.BaseController;
|
||||||
|
import com.maibu.core.domain.AjaxResult;
|
||||||
|
import com.maibu.core.domain.R;
|
||||||
|
import com.maibu.core.enums.OtaOperate;
|
||||||
|
import com.maibu.core.ota.DeviceOtaFirmware;
|
||||||
|
import com.maibu.core.ota.DeviceOtaOperateRecord;
|
||||||
|
import com.maibu.core.page.TableDataInfo;
|
||||||
|
import com.maibu.dto.BaseQueryDTO;
|
||||||
|
import com.maibu.dto.DeviceOtaOperateDTO;
|
||||||
|
import com.maibu.service.impl.DeviceOtaService;
|
||||||
|
import com.maibu.utils.MinioUtil;
|
||||||
|
import io.swagger.annotations.Api;
|
||||||
|
import io.swagger.annotations.ApiOperation;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
|
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Api(tags = "OTA固件管理")
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/iot/deviceOta")
|
||||||
|
public class DeviceOtaController extends BaseController {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private DeviceOtaService service;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private MinioUtil minioUtil;
|
||||||
|
|
||||||
|
// ==================== 固件管理 ====================
|
||||||
|
|
||||||
|
@ApiOperation("新增或修改固件")
|
||||||
|
@PostMapping("/firmware/save")
|
||||||
|
public R saveFirmware(
|
||||||
|
@RequestPart("file") MultipartFile file, // 接收上传的图片
|
||||||
|
@RequestPart("firmware") DeviceOtaFirmware firmware // 接收表单里的 JSON 对象
|
||||||
|
) {
|
||||||
|
|
||||||
|
try (InputStream inputStream = file.getInputStream()) {
|
||||||
|
|
||||||
|
String fileName = "ota/firmware/" + firmware.getVersion();
|
||||||
|
|
||||||
|
// 上传到 MinIO
|
||||||
|
minioUtil.uploadFile(fileName, inputStream, "application/octet-stream");
|
||||||
|
|
||||||
|
// 获取访问 URL
|
||||||
|
String url = minioUtil.getPublicUrl(fileName);
|
||||||
|
System.out.println("固件上传成功,访问地址: " + url);
|
||||||
|
|
||||||
|
// 这里可以把 URL 存到 workRecord 里
|
||||||
|
firmware.setMinioObjectName(fileName);
|
||||||
|
firmware.setFileUrl(url);
|
||||||
|
boolean b = service.saveFirmware(firmware, file.getSize());
|
||||||
|
DeviceOtaOperateRecord record = new DeviceOtaOperateRecord();
|
||||||
|
record.setFileName(firmware.getVersion());
|
||||||
|
record.setFirmwareId(firmware.getId());
|
||||||
|
record.setOperateType(OtaOperate.upload);
|
||||||
|
record.setCreateBy(getUsername());
|
||||||
|
record.setCreateTime(LocalDateTime.now());
|
||||||
|
service.saveOperateRecord(record);
|
||||||
|
return !b ? R.fail("新增失败") : R.ok("新增成功");
|
||||||
|
} catch (Exception e) {
|
||||||
|
return R.fail("新增失败: " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ApiOperation("固件分页列表")
|
||||||
|
@PostMapping("/firmware/list")
|
||||||
|
public TableDataInfo listFirmware() {
|
||||||
|
startPage();
|
||||||
|
return getDataTable(service.listFirmware());
|
||||||
|
}
|
||||||
|
|
||||||
|
@ApiOperation("根据ID查询固件")
|
||||||
|
@GetMapping("/firmware/detail")
|
||||||
|
public AjaxResult selectFirmwareById(@RequestParam Long id) {
|
||||||
|
return AjaxResult.success(service.selectFirmwareById(id));
|
||||||
|
}
|
||||||
|
|
||||||
|
@ApiOperation("更新固件")
|
||||||
|
@PostMapping("/firmware/upgrade")
|
||||||
|
public AjaxResult upgrade(@RequestBody DeviceOtaOperateDTO dto) {
|
||||||
|
return service.upgrade(dto);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ApiOperation("批量删除固件")
|
||||||
|
@PostMapping("/firmware/delete")
|
||||||
|
public AjaxResult deleteFirmware(@RequestBody List<Long> ids) {
|
||||||
|
return AjaxResult.success(service.deleteFirmware(ids));
|
||||||
|
}
|
||||||
|
|
||||||
|
// ==================== 操作记录管理 ====================
|
||||||
|
|
||||||
|
@ApiOperation("新增或修改操作记录")
|
||||||
|
@PostMapping("/record/save")
|
||||||
|
public AjaxResult saveOperateRecord(@RequestBody DeviceOtaOperateRecord record) {
|
||||||
|
return AjaxResult.success(service.saveOperateRecord(record));
|
||||||
|
}
|
||||||
|
|
||||||
|
@ApiOperation("操作记录分页列表")
|
||||||
|
@PostMapping("/record/list")
|
||||||
|
public TableDataInfo listOperateRecord(@RequestBody BaseQueryDTO dto) {
|
||||||
|
startPage();
|
||||||
|
return getDataTable(service.listOperateRecord(dto));
|
||||||
|
}
|
||||||
|
|
||||||
|
@ApiOperation("根据ID查询操作记录")
|
||||||
|
@GetMapping("/record/detail")
|
||||||
|
public AjaxResult selectOperateRecordById(@RequestParam Long id) {
|
||||||
|
return AjaxResult.success(service.selectOperateRecordById(id));
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("/record/selectListByDeviceId")
|
||||||
|
public AjaxResult selectListByDeviceId(@RequestParam String deviceId) {
|
||||||
|
return AjaxResult.success(service.selectListByDeviceId(deviceId));
|
||||||
|
}
|
||||||
|
|
||||||
|
@ApiOperation("批量删除操作记录")
|
||||||
|
@PostMapping("/record/delete")
|
||||||
|
public AjaxResult deleteOperateRecord(@RequestBody List<Long> ids) {
|
||||||
|
return AjaxResult.success(service.deleteOperateRecord(ids));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,30 +1,20 @@
|
|||||||
package com.maibu.controller;
|
package com.maibu.controller;
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.concurrent.ExecutionException;
|
|
||||||
import java.util.concurrent.TimeoutException;
|
|
||||||
|
|
||||||
import com.maibu.annotation.Log;
|
|
||||||
import com.maibu.core.domain.entity.SysUser;
|
|
||||||
import com.maibu.enums.BusinessType;
|
|
||||||
import com.maibu.utils.poi.ExcelUtil;
|
|
||||||
import io.swagger.annotations.ApiOperation;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
|
||||||
import org.springframework.web.bind.annotation.PostMapping;
|
|
||||||
import org.springframework.web.bind.annotation.RequestBody;
|
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
|
||||||
import org.springframework.web.bind.annotation.RequestParam;
|
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
|
||||||
|
|
||||||
import com.maibu.core.business.DeviceRunParam;
|
import com.maibu.core.business.DeviceRunParam;
|
||||||
import com.maibu.core.controller.BaseController;
|
import com.maibu.core.controller.BaseController;
|
||||||
import com.maibu.core.domain.AjaxResult;
|
import com.maibu.core.domain.AjaxResult;
|
||||||
import com.maibu.core.page.TableDataInfo;
|
import com.maibu.core.page.TableDataInfo;
|
||||||
import com.maibu.dto.BaseQueryDTO;
|
import com.maibu.dto.BaseQueryDTO;
|
||||||
import com.maibu.service.impl.DeviceRunParamService;
|
import com.maibu.service.impl.DeviceRunParamService;
|
||||||
|
import com.maibu.utils.poi.ExcelUtil;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.web.bind.annotation.*;
|
||||||
import org.springframework.web.multipart.MultipartFile;
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.concurrent.ExecutionException;
|
||||||
|
import java.util.concurrent.TimeoutException;
|
||||||
|
|
||||||
@RestController
|
@RestController
|
||||||
@RequestMapping("/iot/deviceRunParam")
|
@RequestMapping("/iot/deviceRunParam")
|
||||||
public class DeviceRunParamController extends BaseController {
|
public class DeviceRunParamController extends BaseController {
|
||||||
|
|||||||
@@ -1,28 +1,20 @@
|
|||||||
package com.maibu.controller;
|
package com.maibu.controller;
|
||||||
|
|
||||||
|
import com.maibu.core.business.WorkRecord;
|
||||||
|
import com.maibu.core.controller.BaseController;
|
||||||
|
import com.maibu.core.domain.AjaxResult;
|
||||||
|
import com.maibu.core.domain.R;
|
||||||
|
import com.maibu.memory.GlobalMemory;
|
||||||
|
import com.maibu.service.impl.WorkRecordService;
|
||||||
|
import com.maibu.utils.MinioUtil;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.http.MediaType;
|
||||||
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
|
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import com.maibu.core.domain.AjaxResult;
|
|
||||||
import com.maibu.memory.GlobalMemory;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.http.MediaType;
|
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
|
||||||
import org.springframework.web.bind.annotation.PostMapping;
|
|
||||||
import org.springframework.web.bind.annotation.RequestBody;
|
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
|
||||||
import org.springframework.web.bind.annotation.RequestParam;
|
|
||||||
import org.springframework.web.bind.annotation.RequestPart;
|
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
|
||||||
import org.springframework.web.multipart.MultipartFile;
|
|
||||||
|
|
||||||
import com.maibu.core.business.WorkRecord;
|
|
||||||
import com.maibu.core.business.path.LatAndLngEntity;
|
|
||||||
import com.maibu.core.controller.BaseController;
|
|
||||||
import com.maibu.core.domain.R;
|
|
||||||
import com.maibu.service.impl.WorkRecordService;
|
|
||||||
import com.maibu.utils.MinioUtil;
|
|
||||||
|
|
||||||
@RestController
|
@RestController
|
||||||
@RequestMapping("/iot/workRecord")
|
@RequestMapping("/iot/workRecord")
|
||||||
public class WorkRecordController extends BaseController {
|
public class WorkRecordController extends BaseController {
|
||||||
|
|||||||
@@ -0,0 +1,15 @@
|
|||||||
|
package com.maibu.dto;
|
||||||
|
|
||||||
|
|
||||||
|
import com.maibu.core.enums.OtaOperate;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class DeviceOtaOperateDTO {
|
||||||
|
|
||||||
|
private OtaOperate operateType;
|
||||||
|
private Long firmwareId;
|
||||||
|
private List<String> deviceModels;
|
||||||
|
}
|
||||||
@@ -0,0 +1,204 @@
|
|||||||
|
package com.maibu.service.impl;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.util.CollectionUtils;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||||
|
import com.maibu.core.business.Device;
|
||||||
|
import com.maibu.core.business.device.NettyDevice;
|
||||||
|
import com.maibu.core.domain.AjaxResult;
|
||||||
|
import com.maibu.core.ota.DeviceOtaFirmware;
|
||||||
|
import com.maibu.core.ota.DeviceOtaOperateRecord;
|
||||||
|
import com.maibu.dto.BaseQueryDTO;
|
||||||
|
import com.maibu.dto.DeviceOtaOperateDTO;
|
||||||
|
import com.maibu.mapper.DeviceOtaFirmwareMapper;
|
||||||
|
import com.maibu.mapper.DeviceOtaOperateRecordMapper;
|
||||||
|
import com.maibu.memory.DeviceSessionManager;
|
||||||
|
import com.maibu.service.IDeviceService;
|
||||||
|
import com.maibu.utils.MinioUtil;
|
||||||
|
import com.maibu.utils.SecurityUtils;
|
||||||
|
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
@Slf4j
|
||||||
|
public class DeviceOtaService {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private DeviceOtaFirmwareMapper deviceOtaFirmwareMapper;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private DeviceOtaOperateRecordMapper deviceOtaOperateRecordMapper;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private MinioUtil minioUtil;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private DeviceSessionManager deviceSessionManager;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private IDeviceService deviceService;
|
||||||
|
|
||||||
|
private static final int BATCH_SIZE = 5;
|
||||||
|
|
||||||
|
public boolean saveFirmware(DeviceOtaFirmware firmware, Long fileSize) {
|
||||||
|
|
||||||
|
firmware.setCreateTime(LocalDateTime.now());
|
||||||
|
firmware.setCreateBy(SecurityUtils.getUsername());
|
||||||
|
firmware.setFileSize(formatFileSize(fileSize));
|
||||||
|
|
||||||
|
return deviceOtaFirmwareMapper.saveOrUpdate(firmware);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String formatFileSize(long size) {
|
||||||
|
if (size < 1024) {
|
||||||
|
return size + " B";
|
||||||
|
}
|
||||||
|
|
||||||
|
double kb = size / 1024.0;
|
||||||
|
if (kb < 1024) {
|
||||||
|
return String.format("%.2f KB", kb);
|
||||||
|
}
|
||||||
|
|
||||||
|
double mb = kb / 1024.0;
|
||||||
|
if (mb < 1024) {
|
||||||
|
return String.format("%.2f MB", mb);
|
||||||
|
}
|
||||||
|
|
||||||
|
double gb = mb / 1024.0;
|
||||||
|
return String.format("%.2f GB", gb);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<DeviceOtaFirmware> listFirmware() {
|
||||||
|
LambdaQueryWrapper<DeviceOtaFirmware> queryWrapper = new LambdaQueryWrapper<>();
|
||||||
|
queryWrapper.orderByDesc(DeviceOtaFirmware::getCreateTime);
|
||||||
|
return deviceOtaFirmwareMapper.selectList(queryWrapper);
|
||||||
|
}
|
||||||
|
|
||||||
|
public DeviceOtaFirmware selectFirmwareById(Long id) {
|
||||||
|
return deviceOtaFirmwareMapper.selectById(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
public AjaxResult upgrade(DeviceOtaOperateDTO dto) {
|
||||||
|
if (dto.getFirmwareId() == null) {
|
||||||
|
return AjaxResult.error("固件ID不能为空");
|
||||||
|
}
|
||||||
|
if (CollectionUtils.isEmpty(dto.getDeviceModels())) {
|
||||||
|
return AjaxResult.error("请选择要升级的设备");
|
||||||
|
}
|
||||||
|
|
||||||
|
DeviceOtaFirmware firmware = deviceOtaFirmwareMapper.selectById(dto.getFirmwareId());
|
||||||
|
if (firmware == null) {
|
||||||
|
return AjaxResult.error("固件不存在");
|
||||||
|
}
|
||||||
|
|
||||||
|
List<DeviceOtaOperateRecord> records = new ArrayList<>();
|
||||||
|
|
||||||
|
int totalDevices = dto.getDeviceModels().size();
|
||||||
|
int successCount = 0;
|
||||||
|
int offlineCount = 0;
|
||||||
|
|
||||||
|
for (int i = 0; i < totalDevices; i += BATCH_SIZE) {
|
||||||
|
List<String> batch = dto.getDeviceModels().subList(i, Math.min(i + BATCH_SIZE, totalDevices));
|
||||||
|
log.info("OTA 灰度升级 第 {} 批, 本批设备数: {}", (i / BATCH_SIZE) + 1, batch.size());
|
||||||
|
|
||||||
|
for (String deviceId : batch) {
|
||||||
|
NettyDevice device = deviceSessionManager.getDevice(deviceId);
|
||||||
|
if (device == null || device.getOnlineStatus() == 0) {
|
||||||
|
log.warn("设备 {} 离线,跳过升级", deviceId);
|
||||||
|
offlineCount++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
device.upgrade(deviceId, firmware);
|
||||||
|
|
||||||
|
Device updatedDevice = device.getDevice();
|
||||||
|
|
||||||
|
DeviceOtaOperateRecord record = new DeviceOtaOperateRecord();
|
||||||
|
record.setOperateType(dto.getOperateType());
|
||||||
|
record.setFirmwareId(firmware.getId());
|
||||||
|
record.setFileName(firmware.getFileName());
|
||||||
|
record.setDeviceType(firmware.getDeviceType());
|
||||||
|
record.setCreateTime(LocalDateTime.now());
|
||||||
|
record.setCreateBy(SecurityUtils.getUsername());
|
||||||
|
record.setDeviceId(deviceId);
|
||||||
|
record.setPreVersion(updatedDevice.getFirmwareVersion());
|
||||||
|
record.setNowVersion(firmware.getVersion());
|
||||||
|
records.add(record);
|
||||||
|
|
||||||
|
updatedDevice.setFirmwareVersion(firmware.getVersion());
|
||||||
|
deviceService.updateDeviceBySelf(updatedDevice);
|
||||||
|
|
||||||
|
successCount++;
|
||||||
|
log.info("OTA 升级指令已下发: deviceId={}, version={}", deviceId, firmware.getVersion());
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("OTA 升级指令下发失败: deviceId={}", deviceId, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
deviceOtaOperateRecordMapper.saveOrUpdateBatch(records);
|
||||||
|
|
||||||
|
String msg = String.format("升级指令下发完成: 成功=%d, 离线=%d, 总计=%d",
|
||||||
|
successCount, offlineCount, totalDevices);
|
||||||
|
log.info(msg);
|
||||||
|
return AjaxResult.success(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int deleteFirmware(List<Long> ids) {
|
||||||
|
if (CollectionUtils.isEmpty(ids)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
List<DeviceOtaFirmware> list = deviceOtaFirmwareMapper.selectBatchIds(ids);
|
||||||
|
if (!CollectionUtils.isEmpty(list)) {
|
||||||
|
list.forEach(l -> {
|
||||||
|
try {
|
||||||
|
minioUtil.deleteFile(l.getMinioObjectName());
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return deviceOtaFirmwareMapper.deleteBatchIds(ids);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean saveOperateRecord(DeviceOtaOperateRecord record) {
|
||||||
|
return deviceOtaOperateRecordMapper.saveOrUpdate(record);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<DeviceOtaOperateRecord> listOperateRecord(BaseQueryDTO dto) {
|
||||||
|
LambdaQueryWrapper<DeviceOtaOperateRecord> queryWrapper = new LambdaQueryWrapper<>();
|
||||||
|
if (dto != null) {
|
||||||
|
if (!StringUtils.isEmpty(dto.getDeviceId())) {
|
||||||
|
queryWrapper.eq(DeviceOtaOperateRecord::getDeviceType, dto.getDeviceId());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
queryWrapper.orderByDesc(DeviceOtaOperateRecord::getCreateTime);
|
||||||
|
return deviceOtaOperateRecordMapper.selectList(queryWrapper);
|
||||||
|
}
|
||||||
|
|
||||||
|
public DeviceOtaOperateRecord selectOperateRecordById(Long id) {
|
||||||
|
return deviceOtaOperateRecordMapper.selectById(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<DeviceOtaOperateRecord> selectListByDeviceId(String deviceId) {
|
||||||
|
LambdaQueryWrapper<DeviceOtaOperateRecord> wrapper = new LambdaQueryWrapper<>();
|
||||||
|
wrapper.eq(DeviceOtaOperateRecord::getDeviceId, deviceId);
|
||||||
|
return deviceOtaOperateRecordMapper.selectList(wrapper);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int deleteOperateRecord(List<Long> ids) {
|
||||||
|
if (CollectionUtils.isEmpty(ids)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return deviceOtaOperateRecordMapper.deleteBatchIds(ids);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -3,7 +3,6 @@ package com.maibu.service.impl;
|
|||||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||||
import com.maibu.core.business.DevicePlanTask;
|
import com.maibu.core.business.DevicePlanTask;
|
||||||
import com.maibu.core.business.WorkRecord;
|
import com.maibu.core.business.WorkRecord;
|
||||||
import com.maibu.core.business.path.LatAndLngEntity;
|
|
||||||
import com.maibu.mapper.DevicePlanTaskMapper;
|
import com.maibu.mapper.DevicePlanTaskMapper;
|
||||||
import com.maibu.mapper.WorkRecordMapper;
|
import com.maibu.mapper.WorkRecordMapper;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
|||||||
Reference in New Issue
Block a user