#更新
This commit is contained in:
@@ -3,7 +3,7 @@ spring:
|
||||
datasource:
|
||||
type: com.alibaba.druid.pool.DruidDataSource
|
||||
driver-class-name: com.mysql.cj.jdbc.Driver
|
||||
url: jdbc:mysql://1.95.137.212:3306/maibu?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
|
||||
url: jdbc:mysql://localhost:3306/maibu?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
|
||||
username: satabot
|
||||
password: satabot
|
||||
|
||||
@@ -31,7 +31,7 @@ spring:
|
||||
mqtt:
|
||||
username: maibu # 账号
|
||||
password: jsmbzn520 # 密码
|
||||
host-url: tcp://1.95.137.212:1883 # mqtt连接tcp地址
|
||||
host-url: tcp://localhost:1883 # mqtt连接tcp地址
|
||||
client-id: maibu-mqtt-client # 客户端Id,不能相同,采用随机数 ${random.value}
|
||||
default-topic: test # 默认主题
|
||||
timeout: 30 # 超时时间
|
||||
@@ -84,3 +84,6 @@ influxdb:
|
||||
org: maibu
|
||||
token: maibu-token
|
||||
url: http://localhost:8086
|
||||
|
||||
minio:
|
||||
endpoint : https://oss.satabot.com
|
||||
|
||||
@@ -29,6 +29,9 @@ public class DevicePlanTask extends OrgBaseDO {
|
||||
@TableField(exist = false)
|
||||
private String deviceAlias; // 别名
|
||||
|
||||
@TableField(exist = false)
|
||||
private String workName; // 路径规划名称
|
||||
|
||||
private DeviceTaskStaus taskStaus; // 任务状态
|
||||
|
||||
@TableField(exist = false)
|
||||
|
||||
@@ -21,7 +21,7 @@ public class WorkRecord extends OrgBaseDO {
|
||||
private String workName;
|
||||
private Long userId;
|
||||
|
||||
private String mode;// 导航任务模式 single_point|coverage
|
||||
private String mode;// 导航任务模式 single_point|coverage |predefined_path
|
||||
|
||||
// private String jsonData;
|
||||
|
||||
@@ -31,4 +31,6 @@ public class WorkRecord extends OrgBaseDO {
|
||||
private PlanPath jsonData; // 计划
|
||||
|
||||
private String imgUrl;
|
||||
|
||||
private String fileUrl; // 存放的 路径规划的id
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ import com.maibu.core.business.path.RoutePlanSendEntity;
|
||||
import com.maibu.core.enums.ConnectorType;
|
||||
import com.maibu.core.enums.DeviceTaskStaus;
|
||||
import com.maibu.core.enums.RouteType;
|
||||
import com.maibu.core.host.HostModeChangeDTO;
|
||||
import com.maibu.core.host.HostWorkRecordCreateDTO;
|
||||
import com.maibu.core.host.MutiPointEntity;
|
||||
import com.maibu.core.host.PointEntity;
|
||||
@@ -149,7 +150,6 @@ public class NettyDevice extends Connector {
|
||||
regionConsecutiveTaskRecordMapper.saveOrUpdate(record);
|
||||
}
|
||||
|
||||
|
||||
siteMemory.removeDevicePlanExecute(task.getDeviceId());
|
||||
GlobalMemory.taskPathMap.remove(task.getId());
|
||||
task = null;
|
||||
@@ -293,11 +293,26 @@ public class NettyDevice extends Connector {
|
||||
// }
|
||||
|
||||
// todo 优化
|
||||
public synchronized boolean pauseTask() {
|
||||
public synchronized boolean pauseTask() throws MqttException {
|
||||
if (executingTask) {
|
||||
task.setTaskStaus(DeviceTaskStaus.PAUSE);
|
||||
sendPathCommand((byte) 0x01, (short) 2, 0.00d, 0.00d, (short) 0);
|
||||
// executingTask = false;
|
||||
HostWorkRecordCreateDTO dto = new HostWorkRecordCreateDTO();
|
||||
dto.setAction("pause");
|
||||
dto.setCommand_id(task.getId() + "_" + System.currentTimeMillis());
|
||||
dto.setTask_id(String.valueOf(task.getId()));
|
||||
dto.setSn(task.getDeviceId());
|
||||
// TODO 存内存
|
||||
WorkRecord workRecord = workRecordMapper.selectById(task.getRouteId());
|
||||
log.debug("发送开始任务 workRecord {}", workRecord);
|
||||
if (workRecord != null) {
|
||||
dto.setMode(workRecord.getMode());
|
||||
}
|
||||
dto.setTimestamp(System.currentTimeMillis());
|
||||
dto.setMessage_id(task.getId() + "_" + System.currentTimeMillis());
|
||||
dto.setProtocol_version(Constant.protocol_version);
|
||||
GlobalMemory.customMqttDeviceMonitor.publish(mqttClientId,
|
||||
String.format(MqttTopic.MOWER_TASK_ROUTE_SET, task.getDeviceId()),
|
||||
JsonUtils.toJsonString(dto));
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
@@ -306,15 +321,26 @@ public class NettyDevice extends Connector {
|
||||
}
|
||||
|
||||
// todo 优化
|
||||
public synchronized boolean recoveryTask() throws InterruptedException {
|
||||
public synchronized boolean recoveryTask() throws InterruptedException, MqttException {
|
||||
if (task.getTaskStaus().equals(DeviceTaskStaus.PAUSE)) {
|
||||
task.setTaskStaus(DeviceTaskStaus.EXECUTING);
|
||||
executingTask = true;
|
||||
sendPathCommand((byte) 0x01, (short) 3, 0.00d, 0.00d, (short) 0);
|
||||
// Thread.sleep(1000);
|
||||
// sendPathCommand((byte) 0x01, (short) 1, currentPoint.getLat(),
|
||||
// currentPoint.getLng(), (short) 0);
|
||||
// sendNextPoint();
|
||||
task.setTaskStaus(DeviceTaskStaus.PAUSE);
|
||||
HostWorkRecordCreateDTO dto = new HostWorkRecordCreateDTO();
|
||||
dto.setAction("resume");
|
||||
dto.setCommand_id(task.getId() + "_" + System.currentTimeMillis());
|
||||
dto.setTask_id(String.valueOf(task.getId()));
|
||||
dto.setSn(task.getDeviceId());
|
||||
// TODO 存内存
|
||||
WorkRecord workRecord = workRecordMapper.selectById(task.getRouteId());
|
||||
log.debug("发送开始任务 workRecord {}", workRecord);
|
||||
if (workRecord != null) {
|
||||
dto.setMode(workRecord.getMode());
|
||||
}
|
||||
dto.setTimestamp(System.currentTimeMillis());
|
||||
dto.setMessage_id(task.getId() + "_" + System.currentTimeMillis());
|
||||
dto.setProtocol_version(Constant.protocol_version);
|
||||
GlobalMemory.customMqttDeviceMonitor.publish(mqttClientId,
|
||||
String.format(MqttTopic.MOWER_TASK_ROUTE_SET, task.getDeviceId()),
|
||||
JsonUtils.toJsonString(dto));
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
@@ -372,7 +398,7 @@ public class NettyDevice extends Connector {
|
||||
}
|
||||
}
|
||||
|
||||
public void sendNavigationCommand() throws MqttException {
|
||||
public synchronized void sendNavigationCommand() throws MqttException {
|
||||
|
||||
log.debug("发送开始任务 taskStatus:{},routeId:{}", task.getTaskStaus(), task.getRouteId());
|
||||
if (!task.getTaskStaus().equals(DeviceTaskStaus.EXECUTING))
|
||||
@@ -404,13 +430,6 @@ public class NettyDevice extends Connector {
|
||||
}
|
||||
if (workRecord.getMode().equals("coverage")) {
|
||||
List<MutiPointEntity> boundary_points = new ArrayList<>();
|
||||
// workRecord.getJsonData().getPath().forEach(x -> {
|
||||
// MutiPointEntity mutiPoint = new MutiPointEntity();
|
||||
// mutiPoint.setLongitude(x.getLng());
|
||||
// mutiPoint.setLatitude(x.getLat());
|
||||
// mutiPoint.setIndex();
|
||||
// boundary_points.add(mutiPoint);
|
||||
// });
|
||||
List<LatAndLngEntity> path = workRecord.getJsonData().getPath();
|
||||
|
||||
for (int i = 0; i < path.size(); i++) {
|
||||
@@ -424,8 +443,59 @@ public class NettyDevice extends Connector {
|
||||
}
|
||||
point.setBoundary_points(boundary_points);
|
||||
}
|
||||
if (workRecord.getMode().equals("predefined_path")) {
|
||||
point.setPath_id(workRecord.getId());
|
||||
point.setUrl(workRecord.getFileUrl());
|
||||
point.setVersion("v2");
|
||||
}
|
||||
}
|
||||
}
|
||||
point.setExecute(true);
|
||||
dto.setData(point);
|
||||
GlobalMemory.customMqttDeviceMonitor.publish(mqttClientId,
|
||||
String.format(MqttTopic.MOWER_TASK_ROUTE_SET, task.getDeviceId()),
|
||||
JsonUtils.toJsonString(dto));
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized void sendPredefined(WorkRecord workRecord) throws MqttException {
|
||||
|
||||
log.debug("发送开始任务 taskStatus:{},routeId:{}", task.getTaskStaus(), task.getRouteId());
|
||||
if (task != null)
|
||||
return;
|
||||
|
||||
if (workRecord != null) {
|
||||
HostWorkRecordCreateDTO dto = new HostWorkRecordCreateDTO();
|
||||
dto.setAction("start");
|
||||
dto.setCommand_id(task.getId() + "_" + System.currentTimeMillis());
|
||||
dto.setTask_id(String.valueOf(task.getId()));
|
||||
dto.setSn(task.getDeviceId());
|
||||
|
||||
dto.setMode(workRecord.getMode());
|
||||
|
||||
dto.setTimestamp(System.currentTimeMillis());
|
||||
dto.setMessage_id("predefined" + "_" + System.currentTimeMillis());
|
||||
dto.setProtocol_version(Constant.protocol_version);
|
||||
|
||||
PointEntity point = new PointEntity();
|
||||
|
||||
List<MutiPointEntity> boundary_points = new ArrayList<>();
|
||||
List<LatAndLngEntity> path = workRecord.getJsonData().getPath();
|
||||
|
||||
for (int i = 0; i < path.size(); i++) {
|
||||
LatAndLngEntity x = path.get(i);
|
||||
|
||||
MutiPointEntity mutiPoint = new MutiPointEntity();
|
||||
mutiPoint.setLongitude(x.getLng());
|
||||
mutiPoint.setLatitude(x.getLat());
|
||||
mutiPoint.setIndex(i);
|
||||
boundary_points.add(mutiPoint);
|
||||
}
|
||||
point.setBoundary_points(boundary_points);
|
||||
point.setPath_id(workRecord.getId());
|
||||
point.setVersion("v2");
|
||||
point.setExecute(false);
|
||||
|
||||
dto.setData(point);
|
||||
GlobalMemory.customMqttDeviceMonitor.publish(mqttClientId,
|
||||
String.format(MqttTopic.MOWER_TASK_ROUTE_SET, task.getDeviceId()),
|
||||
@@ -461,4 +531,28 @@ public class NettyDevice extends Connector {
|
||||
JsonUtils.toJsonString(payload));
|
||||
}
|
||||
|
||||
/**
|
||||
* 下发模式切换指令
|
||||
*
|
||||
* @param deviceId
|
||||
* @param controlMode
|
||||
* @throws MqttException
|
||||
*/
|
||||
public void modeChage(String deviceId, Integer controlMode) throws MqttException {
|
||||
HostModeChangeDTO payload = new HostModeChangeDTO();
|
||||
payload.setSn(deviceId);
|
||||
payload.setTimestamp(System.currentTimeMillis());
|
||||
payload.setMessage_id("modeChange_" + System.currentTimeMillis());
|
||||
payload.setCommand_id("modeChangeCommand_ " + System.currentTimeMillis());
|
||||
payload.setProtocol_version(Constant.protocol_version);
|
||||
Map<String, Object> data = new HashMap<>();
|
||||
data.put("control_mode", controlMode);
|
||||
payload.setData(data);
|
||||
|
||||
GlobalMemory.customMqttDeviceMonitor.publish(
|
||||
mqttClientId,
|
||||
String.format(MqttTopic.MOWER_MODE_CHANGE_SET, deviceId),
|
||||
JsonUtils.toJsonString(payload));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
package com.maibu.core.business.dto;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import com.maibu.core.enums.DeviceTaskStaus;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class ConsecutiveTaskQueryDTO {
|
||||
|
||||
private Long siteId;
|
||||
|
||||
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
|
||||
private LocalDateTime startTime;
|
||||
|
||||
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
|
||||
private LocalDateTime endTime;
|
||||
|
||||
private String deviceId;
|
||||
|
||||
private DeviceTaskStaus taskStatus;
|
||||
|
||||
}
|
||||
@@ -12,6 +12,8 @@ public class DeviceMapPushDTO {
|
||||
private double a; // altitude
|
||||
private String s;// status 运行状态
|
||||
private Long t; // taskId 任务id
|
||||
private double p; // 任务进度
|
||||
private String wk; // 任务进度
|
||||
private double b; // 电量
|
||||
private boolean ha = false;// hasAlarm 有无告警
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ public class MowerCommandDispather {
|
||||
@Resource
|
||||
private ApplicationContext applicationContext;
|
||||
|
||||
public Long dispathDeviceTask(DeviceTaskCommandDTO dto) {
|
||||
public Long dispathDeviceTask(DeviceTaskCommandDTO dto) throws Exception {
|
||||
Map<String, MowerCommandInter> beanMap = applicationContext.getBeansOfType(MowerCommandInter.class);
|
||||
// 遍历
|
||||
Long id = null;
|
||||
|
||||
@@ -4,6 +4,6 @@ import com.maibu.core.business.dto.DeviceTaskCommandDTO;
|
||||
|
||||
public interface MowerCommandInter {
|
||||
|
||||
Long createDeviceTask(DeviceTaskCommandDTO dto);
|
||||
Long createDeviceTask(DeviceTaskCommandDTO dto) throws Exception;
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
package com.maibu.core.host;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Data
|
||||
public class HostModeChangeDTO extends HostBase {
|
||||
|
||||
private String command_id;
|
||||
|
||||
private Map<String, Object> data; // map key control_mode 2=自动任务,3=远程遥控
|
||||
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package com.maibu.core.host;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Data
|
||||
public class HostModeChangeReplyDTO extends HostBase {
|
||||
|
||||
private Boolean accepted;
|
||||
|
||||
private String code;
|
||||
|
||||
private String message;
|
||||
|
||||
}
|
||||
@@ -1,12 +1,25 @@
|
||||
package com.maibu.core.host;
|
||||
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class HostTaskStatusDetailDTO {
|
||||
private float progress;
|
||||
private double progress;// 已完成作业路径比例,转移段持平且任务内不回退。规划完成前的 0 不代表已开始覆盖。
|
||||
|
||||
private double distance_remaining; // 整任务剩余作业路径
|
||||
private Integer number_of_recoveries;// 恢复行为次数,不代表障碍数量。
|
||||
private double elapsed_s;
|
||||
private double eta_s;
|
||||
private Integer current_cell_index;
|
||||
private Integer total_cells;
|
||||
private double distance_traveled;
|
||||
private double speed;
|
||||
private Integer task_phase;
|
||||
|
||||
private String error_code;
|
||||
private String error_message;
|
||||
|
||||
private double total_distance_m;
|
||||
private double distance_traveled_m;
|
||||
private double execution_time_s;
|
||||
private Integer cells_completed;
|
||||
}
|
||||
|
||||
@@ -1,20 +1,20 @@
|
||||
package com.maibu.core.host;
|
||||
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Data
|
||||
public class HostWorkRecordCreateDTO extends HostBase {
|
||||
public class HostWorkRecordCreateDTO extends HostBase {
|
||||
|
||||
private String task_id; //任务唯一编号
|
||||
private String command_id;//指令唯一编号
|
||||
private String mode;//导航任务模式 single_point|coverage
|
||||
private String action;//任务动作 start/pause/resume/cancel
|
||||
// private String frame_id; //WGS84
|
||||
private String task_id; // 任务唯一编号
|
||||
private String command_id;// 指令唯一编号
|
||||
private String mode;// 导航任务模式 single_point|coverage
|
||||
private String action;// 任务动作 start/pause/resume/cancel
|
||||
// private String frame_id; //WGS84
|
||||
|
||||
private PointEntity data;
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@ import lombok.Data;
|
||||
@Data
|
||||
public class ObstacleDetectionData {
|
||||
|
||||
private MesType mesType;
|
||||
private MesType type;
|
||||
|
||||
/**
|
||||
* 融合状态
|
||||
|
||||
@@ -9,12 +9,16 @@ public class PointEntity {
|
||||
|
||||
private double latitude;
|
||||
private double longitude;
|
||||
private double yaw;//目标航向,正北0°、顺时针正、0-360°
|
||||
private double yaw;// 目标航向,正北0°、顺时针正、0-360°
|
||||
|
||||
private List<MutiPointEntity> boundary_points;
|
||||
|
||||
private double cell_size;//覆盖分辨率,单位m
|
||||
private double cell_size;// 覆盖分辨率,单位m
|
||||
|
||||
private double angle;//覆盖作业方向,单位度
|
||||
private double angle;// 覆盖作业方向,单位度
|
||||
|
||||
private String url; // minio 存放文件的地址
|
||||
private Long path_id; // 路径id 系统保存用的routeId;
|
||||
private String version;
|
||||
private boolean execute = true; // 是直接执行还是创建自定义任务
|
||||
}
|
||||
|
||||
@@ -17,9 +17,10 @@ import com.maibu.mybatis.mapper.BaseMapperX;
|
||||
@Repository
|
||||
public interface DevicePlanTaskMapper extends BaseMapperX<DevicePlanTask> {
|
||||
|
||||
@Select("SELECT t.*, d.device_alias " +
|
||||
@Select("SELECT t.*, iwr.work_name,d.device_alias " +
|
||||
"FROM iot_device_task t " +
|
||||
"LEFT JOIN iot_device d ON d.device_id = t.device_id " +
|
||||
"LEFT JOIN iot_device d ON d.serial_number = t.device_id " +
|
||||
"left join iot_work_record iwr on t.route_id = iwr.id " +
|
||||
"${ew.customSqlSegment}")
|
||||
List<DevicePlanTask> selectTaskHistoryWithDeviceAlias(
|
||||
@Param(Constants.WRAPPER) Wrapper<DevicePlanTask> wrapper);
|
||||
|
||||
@@ -11,6 +11,7 @@ import org.springframework.stereotype.Component;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
@Component
|
||||
@@ -29,6 +30,8 @@ public class GlobalMemory {
|
||||
|
||||
public static InfluxDBUtil influxDBUtil;
|
||||
|
||||
public static ConcurrentHashMap<String, CompletableFuture<Boolean>> modeFutureMap = new ConcurrentHashMap<>();
|
||||
|
||||
// public static MqttClientUtil mqttClientUtil;
|
||||
|
||||
public static CustomMqttDeviceMonitor customMqttDeviceMonitor = null; // 这里面包含了 连我们自己的mqtt 和外部的一些设备,自己的用clientId
|
||||
@@ -114,8 +117,11 @@ public class GlobalMemory {
|
||||
MqttTopic.MOWER_WILDCARD_REALTIME, // 状态消息
|
||||
MqttTopic.MOWER_WILDCARD_TASK_TARGET_REPLY, // 路径规划下发回复
|
||||
MqttTopic.MOWER_OTA_RESULT_POST, // 在线升级
|
||||
MqttTopic.MOWER_OBSTACLE
|
||||
));
|
||||
MqttTopic.MOWER_OBSTACLE, // 障碍物
|
||||
MqttTopic.MOWER_MODE_REPLY, // 模式切换回复
|
||||
MqttTopic.MOWER_FAULT_POST, // 故障上报
|
||||
MqttTopic.MOWER_FAULT_RECOVERY_REPLY // 故障恢复回复
|
||||
));
|
||||
deviceConfig.setHandlerType(Constant.mqttHandleKey); // 唯一的 用于处理上位机mqtt的
|
||||
customMqttDeviceMonitor.registerDevice(deviceConfig);
|
||||
}
|
||||
|
||||
@@ -1,15 +1,12 @@
|
||||
package com.maibu.memory;
|
||||
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Queue;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.poi.ss.formula.functions.T;
|
||||
import org.eclipse.paho.client.mqttv3.MqttClient;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
@@ -75,11 +72,11 @@ public class SiteMemory {
|
||||
// 记录 设备上线后的运行数据 下线后清除并保存到数据库
|
||||
public static ConcurrentHashMap<String, DeviceRunStatistics> deviceRunStatisticsMap = new ConcurrentHashMap<>();
|
||||
|
||||
public static ConcurrentHashMap<String, DeviceMapPushDTO> deviceMapPushMap = new ConcurrentHashMap<>();
|
||||
public static final ConcurrentHashMap<String, DeviceMapPushDTO> deviceMapPushMap = new ConcurrentHashMap<>();
|
||||
|
||||
public static ConcurrentHashMap<String, VehicleMessage> vehicleMessageMap = new ConcurrentHashMap<>();
|
||||
|
||||
public static ConcurrentHashMap<RuleType, IotAutoRule> iotAutoRuleMap = new ConcurrentHashMap<>();
|
||||
public static final ConcurrentHashMap<RuleType, List<IotAutoRule>> iotAutoRuleMap = new ConcurrentHashMap<>();
|
||||
|
||||
public static final ConcurrentHashMap<String, RegionConsecutiveTaskRecord> regionConsecutiveTaskMap = new ConcurrentHashMap<>();
|
||||
|
||||
@@ -109,20 +106,21 @@ public class SiteMemory {
|
||||
return record;
|
||||
}
|
||||
|
||||
public List<IotAutoRule> getAllIotAutoRule() {
|
||||
return new ArrayList<>(iotAutoRuleMap.values());
|
||||
}
|
||||
|
||||
public IotAutoRule getIotAutoRule(RuleType ruleType) {
|
||||
public List<IotAutoRule> getIotAutoRule(RuleType ruleType) {
|
||||
return iotAutoRuleMap.get(ruleType);
|
||||
}
|
||||
|
||||
public void saveIotAutoRule(RuleType ruleType, IotAutoRule iotAutoRule) {
|
||||
iotAutoRuleMap.put(ruleType, iotAutoRule);
|
||||
List<IotAutoRule> list = iotAutoRuleMap.computeIfAbsent(
|
||||
ruleType, k -> new ArrayList<>());
|
||||
|
||||
list.removeIf(item -> Objects.equals(item.getId(), iotAutoRule.getId()));
|
||||
list.add(iotAutoRule);
|
||||
}
|
||||
|
||||
public void removeIotAutoRule(RuleType ruleType) {
|
||||
iotAutoRuleMap.remove(ruleType);
|
||||
public void removeIotAutoRule(IotAutoRule iotAutoRule) {
|
||||
List<IotAutoRule> list = iotAutoRuleMap.get(iotAutoRule.getRuleType());
|
||||
list.removeIf(i -> iotAutoRule.getId().equals(i.getId()));
|
||||
}
|
||||
|
||||
public List<VehicleMessage> getAllVehicleMessage() {
|
||||
@@ -154,6 +152,10 @@ public class SiteMemory {
|
||||
return deviceMapPushMap;
|
||||
}
|
||||
|
||||
public DeviceMapPushDTO getDeviceMapPusById(String deviceId) {
|
||||
return deviceMapPushMap.get(deviceId);
|
||||
}
|
||||
|
||||
public void saveMapPushDTO(String deviceId, DeviceMapPushDTO dto) {
|
||||
deviceMapPushMap.put(deviceId, dto);
|
||||
}
|
||||
|
||||
@@ -28,6 +28,7 @@ import org.springframework.util.CollectionUtils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
/**
|
||||
* mqtt相关的 上位机处理器
|
||||
@@ -111,6 +112,15 @@ public class HostMessageHandler implements CustomMqttMessageHandler {
|
||||
case "obstacle_post":
|
||||
handleObstaclePost(deviceId, topic, payload);
|
||||
break;
|
||||
case "mode_reply":
|
||||
handleModeReply(deviceId, topic, payload);
|
||||
break;
|
||||
case "fault_post":
|
||||
handleFaultPost(deviceId, topic, payload);
|
||||
break;
|
||||
case "fault_recovery_reply":
|
||||
handleFaultRecoveryReply(deviceId, topic, payload);
|
||||
break;
|
||||
|
||||
default:
|
||||
log.debug("割草机消息: deviceId={}, topic={}, action={}", deviceId, topic, action);
|
||||
@@ -255,6 +265,7 @@ public class HostMessageHandler implements CustomMqttMessageHandler {
|
||||
dto.setMs(vehicleMessage.getMotion());
|
||||
dto.setB(vehicleMessage.getBattery_percentage());
|
||||
}
|
||||
dto.setWk(nettyDevice.getTask() != null ? nettyDevice.getTask().getWorkName() : "");
|
||||
siteMemory.saveMapPushDTO(deviceId, dto);
|
||||
}
|
||||
}
|
||||
@@ -560,6 +571,16 @@ public class HostMessageHandler implements CustomMqttMessageHandler {
|
||||
// NettyDevice nettyDevice = deviceSessionManager.getDevice(deviceId);
|
||||
// nettyDevice.finishTask();
|
||||
// }
|
||||
// 任务进度 百分比
|
||||
Long siteId = nettyDevice.getDevice().getSiteId();
|
||||
Long orgId = nettyDevice.getDevice().getOrgId();
|
||||
SiteMemory siteMemory = GlobalMemory.getSiteMemory(orgId, siteId);
|
||||
if (siteMemory != null) {
|
||||
DeviceMapPushDTO pushDto = siteMemory.getDeviceMapPusById(deviceId);
|
||||
if (pushDto != null && dto.getData() != null) {
|
||||
pushDto.setP(dto.getData().getProgress());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -700,7 +721,7 @@ public class HostMessageHandler implements CustomMqttMessageHandler {
|
||||
|
||||
List<NettyDevice> controlMasters = deviceSessionManager
|
||||
.getAllSlaveControl(deviceId);
|
||||
data.setMesType(MesType.detectionReport);
|
||||
data.setType(MesType.detectionReport);
|
||||
if (!CollectionUtils.isEmpty(controlMasters)) {
|
||||
|
||||
for (NettyDevice x : controlMasters) {
|
||||
@@ -732,6 +753,44 @@ public class HostMessageHandler implements CustomMqttMessageHandler {
|
||||
|
||||
}
|
||||
|
||||
private void handleModeReply(String deviceId, String topic, String payload) {
|
||||
log.debug("【模式切换回复】deviceId={}, payload={}", deviceId, payload);
|
||||
|
||||
HostModeChangeReplyDTO data = JsonUtils.parseObject(payload, HostModeChangeReplyDTO.class);
|
||||
|
||||
CompletableFuture<Boolean> future = GlobalMemory.modeFutureMap.get(deviceId);
|
||||
|
||||
if (future != null && data != null) {
|
||||
future.complete(data.getAccepted());
|
||||
}
|
||||
}
|
||||
|
||||
private void handleFaultPost(String deviceId, String topic, String payload) {
|
||||
log.debug("【故障上报】deviceId={}, payload={}", deviceId, payload);
|
||||
|
||||
// HostFaultPostDTO data = JsonUtils.parseObject(payload,
|
||||
// HostFaultPostDTO.class);
|
||||
|
||||
// CompletableFuture<Boolean> future = GlobalMemory.modeFutureMap.get(deviceId);
|
||||
|
||||
// if (future != null && data != null) {
|
||||
// future.complete(data.getAccepted());
|
||||
// }
|
||||
}
|
||||
|
||||
private void handleFaultRecoveryReply(String deviceId, String topic, String payload) {
|
||||
log.debug("【故障恢复回复】deviceId={}, payload={}", deviceId, payload);
|
||||
|
||||
// HostFaultRecoveryReplyDTO data = JsonUtils.parseObject(payload,
|
||||
// HostFaultRecoveryReplyDTO.class);
|
||||
|
||||
// CompletableFuture<Boolean> future = GlobalMemory.modeFutureMap.get(deviceId);
|
||||
|
||||
// if (future != null && data != null) {
|
||||
// future.complete(data.getAccepted());
|
||||
// }
|
||||
}
|
||||
|
||||
/**
|
||||
* 从 Topic 中解析 deviceId
|
||||
* Topic 格式:mower/{deviceId}/...
|
||||
@@ -782,10 +841,16 @@ public class HostMessageHandler implements CustomMqttMessageHandler {
|
||||
return "control_reply";
|
||||
if (remaining.equals("task/target/reply"))
|
||||
return "route_reply";
|
||||
if (remaining.equals("/ota/result/post"))
|
||||
if (remaining.equals("ota/result/post"))
|
||||
return "upgrade_reply";
|
||||
if (remaining.equals("/perception/obstacle/post"))
|
||||
if (remaining.equals("perception/obstacle/post"))
|
||||
return "obstacle_post";
|
||||
if (remaining.equals("control/mode/set/reply"))
|
||||
return "mode_reply";
|
||||
if (remaining.equals("event/fault/post"))
|
||||
return "fault_post";
|
||||
if (remaining.equals("fault/recovery/reply"))
|
||||
return "fault_recovery_reply";
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -109,9 +109,24 @@ public class MqttTopic {
|
||||
|
||||
public static final String MOWER_HEARTBEAT = "mower/+/event/heartbeat/post";
|
||||
|
||||
//障碍物
|
||||
// 障碍物
|
||||
public static final String MOWER_OBSTACLE = "mower/+/perception/obstacle/post";
|
||||
|
||||
/** 模式切换指令 无遥才能下发(平台->设备) */
|
||||
public static final String MOWER_MODE_CHANGE_SET = "mower/%s/control/mode/set";
|
||||
|
||||
// 模式切换回复
|
||||
public static final String MOWER_MODE_REPLY = "mower/+/control/mode/reply";
|
||||
|
||||
// 故障上报
|
||||
public static final String MOWER_FAULT_POST = "mower/+/event/fault/post";
|
||||
|
||||
// 故障恢复 (平台->设备)
|
||||
public static final String MOWER_FAULT_RECOVERY = "mower/%s/fault/recovery/set";
|
||||
|
||||
// 故障恢复回复
|
||||
public static final String MOWER_FAULT_RECOVERY_REPLY = "mower/+/fault/recovery/reply";
|
||||
|
||||
/**
|
||||
* 格式化 Topic 模板,将 %s 替换为设备ID
|
||||
*
|
||||
|
||||
@@ -15,7 +15,9 @@ import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import com.maibu.core.business.DevicePlan;
|
||||
import com.maibu.core.business.RegionConsecutiveTaskRecord;
|
||||
import com.maibu.core.business.dto.ConsecutiveTaskDTO;
|
||||
import com.maibu.core.business.dto.ConsecutiveTaskQueryDTO;
|
||||
import com.maibu.core.business.dto.DeviceTaskCommandDTO;
|
||||
import com.maibu.core.controller.BaseController;
|
||||
import com.maibu.core.domain.AjaxResult;
|
||||
@@ -106,7 +108,7 @@ public class DeviceTaskController extends BaseController {
|
||||
}
|
||||
|
||||
@PostMapping("/createDeviceTask")
|
||||
public AjaxResult createDeviceTask(@RequestBody DeviceTaskCommandDTO dto) {
|
||||
public AjaxResult createDeviceTask(@RequestBody DeviceTaskCommandDTO dto) throws Exception {
|
||||
String deviceId = dto.getDeviceId();
|
||||
Long siteId = dto.getSiteId();
|
||||
Long orgId = dto.getOrgId();
|
||||
@@ -135,7 +137,7 @@ public class DeviceTaskController extends BaseController {
|
||||
}
|
||||
|
||||
@PostMapping("/createRegionDefaultTask")
|
||||
public AjaxResult createRegionDeviceTask(@RequestBody DeviceTaskCommandDTO dto) {
|
||||
public AjaxResult createRegionDeviceTask(@RequestBody DeviceTaskCommandDTO dto) throws Exception {
|
||||
String deviceId = dto.getDeviceId();
|
||||
Long siteId = dto.getSiteId();
|
||||
Long orgId = dto.getOrgId();
|
||||
@@ -177,7 +179,7 @@ public class DeviceTaskController extends BaseController {
|
||||
}
|
||||
|
||||
@PostMapping("/pauseTask")
|
||||
public AjaxResult pauseTask(@RequestBody DeviceTaskCommandDTO dto) {
|
||||
public AjaxResult pauseTask(@RequestBody DeviceTaskCommandDTO dto) throws MqttException {
|
||||
String deviceId = dto.getDeviceId();
|
||||
if (StringUtils.isEmpty(deviceId) && dto.getTaskId() == null) {
|
||||
return AjaxResult.error("deviceId或taskId为空!");
|
||||
@@ -186,7 +188,7 @@ public class DeviceTaskController extends BaseController {
|
||||
}
|
||||
|
||||
@PostMapping("/recoveryTask")
|
||||
public AjaxResult recoveryTask(@RequestBody DeviceTaskCommandDTO dto) throws InterruptedException {
|
||||
public AjaxResult recoveryTask(@RequestBody DeviceTaskCommandDTO dto) throws InterruptedException, MqttException {
|
||||
String deviceId = dto.getDeviceId();
|
||||
if (StringUtils.isEmpty(deviceId) && dto.getTaskId() == null) {
|
||||
return AjaxResult.error("deviceId或taskId为空!");
|
||||
@@ -195,7 +197,7 @@ public class DeviceTaskController extends BaseController {
|
||||
}
|
||||
|
||||
@PostMapping("/backToRestPoint")
|
||||
public AjaxResult backToRestPoint(@RequestBody DeviceTaskCommandDTO dto) {
|
||||
public AjaxResult backToRestPoint(@RequestBody DeviceTaskCommandDTO dto) throws Exception {
|
||||
String deviceId = dto.getDeviceId();
|
||||
Long siteId = dto.getSiteId();
|
||||
Long orgId = dto.getOrgId();
|
||||
@@ -223,8 +225,8 @@ public class DeviceTaskController extends BaseController {
|
||||
return AjaxResult.success(deviceTaskService.backToRestPoint(dto, getLoginUser().getUsername()));
|
||||
}
|
||||
|
||||
@PostMapping("/createConsecutiveTasks")
|
||||
public AjaxResult createConsecutiveTasks(@RequestBody ConsecutiveTaskDTO dto) {
|
||||
@PostMapping("/createConsecutiveTask")
|
||||
public AjaxResult createConsecutiveTasks(@RequestBody ConsecutiveTaskDTO dto) throws Exception {
|
||||
String deviceId = dto.getDeviceId();
|
||||
Long siteId = dto.getSiteId();
|
||||
Long orgId = dto.getOrgId();
|
||||
@@ -278,4 +280,11 @@ public class DeviceTaskController extends BaseController {
|
||||
return AjaxResult.success();
|
||||
}
|
||||
|
||||
@PostMapping("/getConsecutiveTask")
|
||||
public TableDataInfo getConsecutiveTask(@RequestBody ConsecutiveTaskQueryDTO dto) {
|
||||
startPage();
|
||||
List<RegionConsecutiveTaskRecord> list = deviceTaskService.getRegionConsecutiveTaskRecords(dto);
|
||||
return getDataTable(list);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@ public class MowerCommamdHandler implements MowerCommandInter {
|
||||
private DeviceTaskService dService;
|
||||
|
||||
@Override
|
||||
public Long createDeviceTask(DeviceTaskCommandDTO dto) {
|
||||
public Long createDeviceTask(DeviceTaskCommandDTO dto) throws Exception {
|
||||
return dService.createDeviceTask(dto, "system");
|
||||
}
|
||||
|
||||
|
||||
@@ -36,6 +36,7 @@ import com.maibu.core.business.WorkRecord;
|
||||
import com.maibu.core.domain.entity.SysParam;
|
||||
import com.maibu.core.domain.entity.SysSite;
|
||||
import com.maibu.core.domain.map.SiteMapInfo;
|
||||
import com.maibu.core.domain.rule.IotAutoRule;
|
||||
import com.maibu.core.enums.DeviceTaskStaus;
|
||||
import com.maibu.core.enums.RouteType;
|
||||
import com.maibu.influxdb.util.InfluxDBUtil;
|
||||
@@ -45,6 +46,7 @@ import com.maibu.mapper.DevicePlanTaskMapper;
|
||||
import com.maibu.mapper.DeviceProductMapper;
|
||||
import com.maibu.mapper.DeviceRunParamMapper;
|
||||
import com.maibu.mapper.ErrorIdentificationStandardMapper;
|
||||
import com.maibu.mapper.IotAutoRuleMapper;
|
||||
import com.maibu.mapper.IotDeviceCommonMapper;
|
||||
import com.maibu.mapper.OrderModelMapper;
|
||||
import com.maibu.mapper.SiteMapInfoMapper;
|
||||
@@ -138,6 +140,9 @@ public class InitThread implements ApplicationRunner {
|
||||
@Autowired
|
||||
private WorkRecordMapper workRecordMapper;
|
||||
|
||||
@Autowired
|
||||
private IotAutoRuleMapper iotAutoRuleMapper;
|
||||
|
||||
@Value("${influxdb.url}")
|
||||
private String influxDBUrl;
|
||||
|
||||
@@ -250,6 +255,19 @@ public class InitThread implements ApplicationRunner {
|
||||
});
|
||||
}
|
||||
|
||||
// 任务触发规则
|
||||
List<IotAutoRule> iotAutoRuleList = iotAutoRuleMapper.selectList();
|
||||
if (!CollectionUtils.isEmpty(iotAutoRuleList)) {
|
||||
iotAutoRuleList.forEach(x -> {
|
||||
Long orgId = x.getOrgId();
|
||||
Long siteId = x.getSiteId();
|
||||
SiteMemory siteMemory = GlobalMemory.getSiteMemory(orgId, siteId);
|
||||
if (siteMemory != null) {
|
||||
siteMemory.saveIotAutoRule(x.getRuleType(), x);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 场站的 地图配置信息
|
||||
List<SiteMapInfo> siteMapInfoList = siteMapInfoMapper.selectList();
|
||||
if (!CollectionUtils.isEmpty(siteMapInfoList)) {
|
||||
@@ -452,7 +470,7 @@ public class InitThread implements ApplicationRunner {
|
||||
workRecord -> workRecord.getRouteType().toString()));
|
||||
if (!CollectionUtils.isEmpty(records)) {
|
||||
records.forEach(x -> {
|
||||
if (!map.containsKey(x.getRouteType())) {
|
||||
if (!map.containsKey(x.getRouteType().toString())) {
|
||||
x.setUserId(1L);
|
||||
saveList.add(x);
|
||||
}
|
||||
|
||||
@@ -117,7 +117,7 @@ public class CommandForwardHandler extends SimpleChannelInboundHandler<String> {
|
||||
data.setCutter(pEntity.getMowerSpeedFlag());
|
||||
data.setIgnition(pEntity.getIgnitionFlag());
|
||||
data.setEmergency_stop(pEntity.getEmergencyStopFlag());
|
||||
data.setValid_for_ms(500);
|
||||
data.setValid_for_ms(200); //间隔 可调整
|
||||
deviceRemoteControlDTO.setData(data);
|
||||
deviceRemoteControlDTO
|
||||
.setCommand_id(Constant.remote_control_cmd_prefix + System.currentTimeMillis());
|
||||
|
||||
@@ -1,9 +1,26 @@
|
||||
package com.maibu.service;
|
||||
|
||||
import java.time.DayOfWeek;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.LocalTime;
|
||||
import java.util.Comparator;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
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.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;
|
||||
@@ -13,21 +30,8 @@ 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;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
|
||||
import javax.annotation.PreDestroy;
|
||||
import java.time.DayOfWeek;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.LocalTime;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
@Slf4j
|
||||
@Service
|
||||
@@ -47,6 +51,7 @@ public class DevicePlanTaskMonitorService {
|
||||
|
||||
@Autowired
|
||||
private ScheduledExecutorService executor;
|
||||
|
||||
/**
|
||||
* 计划迟的任务生成机器执行任务
|
||||
*/
|
||||
@@ -71,7 +76,8 @@ public class DevicePlanTaskMonitorService {
|
||||
}
|
||||
|
||||
private void createPlanTask(DevicePlan devicePlan) {
|
||||
if (devicePlan.isDayTriggerFlag()) return; //当天应该创建的全部创建完
|
||||
if (devicePlan.isDayTriggerFlag())
|
||||
return; // 当天应该创建的全部创建完
|
||||
DeviceTaskPlanRule rules = devicePlan.getDeviceTaskPlanRules();
|
||||
if (rules != null) {
|
||||
DeviceTaskPlanRepeatType type = rules.getType();
|
||||
@@ -85,9 +91,9 @@ public class DevicePlanTaskMonitorService {
|
||||
case MONTH:
|
||||
monthPlan(devicePlan);
|
||||
break;
|
||||
// case ONCE:
|
||||
// oncePlan(devicePlan);
|
||||
// break;
|
||||
// case ONCE:
|
||||
// oncePlan(devicePlan);
|
||||
// break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -102,18 +108,25 @@ public class DevicePlanTaskMonitorService {
|
||||
devicePlanTask.setDeviceId(devicePlan.getDeviceId());
|
||||
devicePlanTask.setTaskStaus(DeviceTaskStaus.NEW);
|
||||
devicePlanTask.setRouteId(devicePlan.getRouteId());
|
||||
// 设置当前的路径规划信息
|
||||
WorkRecord workRecord = workRecordMapper.selectById(devicePlan.getRouteId());
|
||||
if (workRecord != null) {
|
||||
devicePlanTask.setRouteType(workRecord.getRouteType());
|
||||
devicePlanTask.setWorkName(workRecord.getWorkName());
|
||||
}
|
||||
|
||||
devicePlanTask.setCreateTime(LocalDateTime.now());
|
||||
devicePlanTask.setTaskType("");//待拓展任务类型
|
||||
devicePlanTask.setTaskType("");// 待拓展任务类型
|
||||
devicePlanTask.setOrgId(devicePlan.getOrgId());
|
||||
devicePlanTask.setSiteId(devicePlan.getSiteId());
|
||||
devicePlanTaskMapper.insert(devicePlanTask);
|
||||
SiteMemory siteMemory = GlobalMemory.getSiteMemory(devicePlan.getOrgId(), devicePlan.getSiteId());
|
||||
siteMemory.addDevicePlanPrepare(devicePlanTask);
|
||||
//啥时候重置?每日0点?
|
||||
// 啥时候重置?每日0点?
|
||||
devicePlan.setDayTriggerFlag(true);
|
||||
devicePlan.setUpdateTime(LocalDateTime.now());
|
||||
devicePlan.setTaskStaus(DeviceTaskStaus.EXECUTING);
|
||||
//todo 怎么判断任务全部排完了?排完了就删除
|
||||
// todo 怎么判断任务全部排完了?排完了就删除
|
||||
LocalDate today = LocalDate.now(); // 获取当前日期(系统时区)
|
||||
LocalDate endTime = rules.getEndTime();
|
||||
if (endTime != null && endTime.isEqual(today)) {
|
||||
@@ -139,18 +152,24 @@ public class DevicePlanTaskMonitorService {
|
||||
devicePlanTask.setDeviceId(devicePlan.getDeviceId());
|
||||
devicePlanTask.setTaskStaus(DeviceTaskStaus.NEW);
|
||||
devicePlanTask.setRouteId(devicePlan.getRouteId());
|
||||
// 设置当前的路径规划信息
|
||||
WorkRecord workRecord = workRecordMapper.selectById(devicePlan.getRouteId());
|
||||
if (workRecord != null) {
|
||||
devicePlanTask.setRouteType(workRecord.getRouteType());
|
||||
devicePlanTask.setWorkName(workRecord.getWorkName());
|
||||
}
|
||||
devicePlanTask.setCreateTime(LocalDateTime.now());
|
||||
devicePlanTask.setOrgId(devicePlan.getOrgId());
|
||||
devicePlanTask.setSiteId(devicePlan.getSiteId());
|
||||
devicePlanTask.setTaskType("");//待拓展任务类型
|
||||
devicePlanTask.setTaskType("");// 待拓展任务类型
|
||||
devicePlanTaskMapper.insert(devicePlanTask);
|
||||
SiteMemory siteMemory = GlobalMemory.getSiteMemory(devicePlan.getOrgId(), devicePlan.getSiteId());
|
||||
siteMemory.addDevicePlanPrepare(devicePlanTask);
|
||||
//啥时候重置?每日0点?
|
||||
// 啥时候重置?每日0点?
|
||||
devicePlan.setDayTriggerFlag(true);
|
||||
devicePlan.setUpdateTime(LocalDateTime.now());
|
||||
devicePlan.setTaskStaus(DeviceTaskStaus.EXECUTING);
|
||||
//todo 怎么判断任务全部排完了?排完了就删除
|
||||
// todo 怎么判断任务全部排完了?排完了就删除
|
||||
LocalDate endTime = rules.getEndTime();
|
||||
if (endTime != null && endTime.isEqual(today)) {
|
||||
devicePlan.setFinishTime(LocalDateTime.now());
|
||||
@@ -168,24 +187,31 @@ public class DevicePlanTaskMonitorService {
|
||||
LocalTime nowTime = LocalTime.now();
|
||||
int dayOfMonth = today.getDayOfMonth();
|
||||
LocalTime dayTime = LocalTime.parse(rules.getDayTime());
|
||||
if (!CollectionUtils.isEmpty(dayOfMonthList) && dayOfMonthList.contains(dayOfMonth) && nowTime.isAfter(dayTime)) {
|
||||
if (!CollectionUtils.isEmpty(dayOfMonthList) && dayOfMonthList.contains(dayOfMonth)
|
||||
&& nowTime.isAfter(dayTime)) {
|
||||
DevicePlanTask devicePlanTask = new DevicePlanTask();
|
||||
devicePlanTask.setPlanId(devicePlan.getId());
|
||||
devicePlanTask.setDeviceId(devicePlan.getDeviceId());
|
||||
devicePlanTask.setTaskStaus(DeviceTaskStaus.NEW);
|
||||
devicePlanTask.setRouteId(devicePlan.getRouteId());
|
||||
// 设置当前的路径规划信息
|
||||
WorkRecord workRecord = workRecordMapper.selectById(devicePlan.getRouteId());
|
||||
if (workRecord != null) {
|
||||
devicePlanTask.setRouteType(workRecord.getRouteType());
|
||||
devicePlanTask.setWorkName(workRecord.getWorkName());
|
||||
}
|
||||
devicePlanTask.setCreateTime(LocalDateTime.now());
|
||||
devicePlanTask.setTaskType("");//待拓展任务类型
|
||||
devicePlanTask.setTaskType("");// 待拓展任务类型
|
||||
devicePlanTask.setOrgId(devicePlan.getOrgId());
|
||||
devicePlanTask.setSiteId(devicePlan.getSiteId());
|
||||
devicePlanTaskMapper.insert(devicePlanTask);
|
||||
SiteMemory siteMemory = GlobalMemory.getSiteMemory(devicePlan.getOrgId(), devicePlan.getSiteId());
|
||||
siteMemory.addDevicePlanPrepare(devicePlanTask);
|
||||
//啥时候重置?每日0点?
|
||||
// 啥时候重置?每日0点?
|
||||
devicePlan.setDayTriggerFlag(true);
|
||||
devicePlan.setUpdateTime(LocalDateTime.now());
|
||||
devicePlan.setTaskStaus(DeviceTaskStaus.EXECUTING);
|
||||
//todo 怎么判断任务全部排完了?排完了就删除
|
||||
// todo 怎么判断任务全部排完了?排完了就删除
|
||||
LocalDate endTime = rules.getEndTime();
|
||||
if (endTime != null && endTime.isEqual(today)) {
|
||||
devicePlan.setFinishTime(LocalDateTime.now());
|
||||
@@ -197,13 +223,12 @@ public class DevicePlanTaskMonitorService {
|
||||
}
|
||||
|
||||
public void oncePlan(DevicePlan devicePlan) {
|
||||
// DeviceTaskPlanRule rules = devicePlan.getDeviceTaskPlanRules();
|
||||
|
||||
// DeviceTaskPlanRule rules = devicePlan.getDeviceTaskPlanRules();
|
||||
|
||||
}
|
||||
|
||||
public void doLoop() throws InterruptedException {
|
||||
//prepare 进执行execute的逻辑
|
||||
// prepare 进执行execute的逻辑
|
||||
executor.scheduleWithFixedDelay(() -> {
|
||||
try {
|
||||
List<SiteMemory> list = GlobalMemory.getAllSiteMemory();
|
||||
@@ -213,17 +238,16 @@ public class DevicePlanTaskMonitorService {
|
||||
if (!CollectionUtils.isEmpty(planMap.keySet())) {
|
||||
planMap.keySet().forEach(key -> {
|
||||
NettyDevice device = deviceSessionManager.getDevice(key);
|
||||
//判断是否能进execute
|
||||
if (device != null && device.getTask() == null && device.getOnlineStatus() != null && device.getOnlineStatus() == 1) {
|
||||
// 判断是否能进execute
|
||||
if (device != null && device.getTask() == null && device.getOnlineStatus() != null
|
||||
&& device.getOnlineStatus() == 1) {
|
||||
List<DevicePlanTask> tasks = planMap.get(key);
|
||||
if (!CollectionUtils.isEmpty(tasks)) {
|
||||
tasks.removeIf(Objects::isNull);
|
||||
tasks.sort(
|
||||
tasks.sort(
|
||||
Comparator.comparing(
|
||||
DevicePlanTask::getStartTime,
|
||||
Comparator.nullsLast(Comparator.naturalOrder())
|
||||
)
|
||||
);
|
||||
Comparator.nullsLast(Comparator.naturalOrder())));
|
||||
if (!CollectionUtils.isEmpty(tasks)) {
|
||||
DevicePlanTask devicePlanTask = tasks.get(0);
|
||||
String deviceId = devicePlanTask.getDeviceId();
|
||||
@@ -248,7 +272,7 @@ public class DevicePlanTaskMonitorService {
|
||||
}
|
||||
|
||||
public void doExecute() {
|
||||
//prepare 进执行execute的逻辑
|
||||
// prepare 进执行execute的逻辑
|
||||
executor.scheduleWithFixedDelay(() -> {
|
||||
try {
|
||||
List<SiteMemory> list = GlobalMemory.getAllSiteMemory();
|
||||
|
||||
@@ -6,7 +6,10 @@ import java.time.format.DateTimeFormatter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Random;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
@@ -27,6 +30,7 @@ import com.maibu.core.business.RegionConsecutiveTaskRecord;
|
||||
import com.maibu.core.business.WorkRecord;
|
||||
import com.maibu.core.business.device.NettyDevice;
|
||||
import com.maibu.core.business.dto.ConsecutiveTaskDTO;
|
||||
import com.maibu.core.business.dto.ConsecutiveTaskQueryDTO;
|
||||
import com.maibu.core.business.dto.DeviceTaskCommandDTO;
|
||||
import com.maibu.core.domain.entity.SysRegion;
|
||||
import com.maibu.core.domain.entity.SysSite;
|
||||
@@ -35,6 +39,7 @@ import com.maibu.core.domain.map.SiteMapInfo;
|
||||
import com.maibu.core.domain.model.LoginUser;
|
||||
import com.maibu.core.enums.DeviceTaskStaus;
|
||||
import com.maibu.core.enums.RouteType;
|
||||
import com.maibu.core.host.VehicleMessage;
|
||||
import com.maibu.dto.DevicePlanStatisticsDTO;
|
||||
import com.maibu.dto.DevicePlanTaskStatisticsDTO;
|
||||
import com.maibu.dto.DeviceTaskQueryDTO;
|
||||
@@ -50,6 +55,7 @@ import com.maibu.mapper.WorkRecordMapper;
|
||||
import com.maibu.memory.DeviceSessionManager;
|
||||
import com.maibu.memory.GlobalMemory;
|
||||
import com.maibu.memory.SiteMemory;
|
||||
import com.maibu.service.impl.HostComputerService;
|
||||
import com.maibu.utils.MessageUtils;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
@@ -82,6 +88,9 @@ public class DeviceTaskService {
|
||||
@Autowired
|
||||
private RegionConsecutiveTaskRecordMapper regionConsecutiveTaskRecordMapper;
|
||||
|
||||
@Autowired
|
||||
private HostComputerService hostComputerService;
|
||||
|
||||
private static final ObjectMapper objectMapper = new ObjectMapper();
|
||||
|
||||
public int insertOrUpdate(DevicePlan devicePlan, LoginUser loginUser) {
|
||||
@@ -422,6 +431,47 @@ public class DeviceTaskService {
|
||||
&& !x.getCreateTime().isAfter(dto.getEndTime()))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
// 批量查询路线名称
|
||||
Set<Long> routeIds = list.stream()
|
||||
.map(DevicePlanTask::getRouteId)
|
||||
.filter(Objects::nonNull)
|
||||
.collect(Collectors.toSet());
|
||||
|
||||
if (!routeIds.isEmpty()) {
|
||||
List<WorkRecord> workRecords = workRecordMapper.selectList(
|
||||
new LambdaQueryWrapper<WorkRecord>()
|
||||
.select(WorkRecord::getId, WorkRecord::getWorkName)
|
||||
.in(WorkRecord::getId, routeIds));
|
||||
|
||||
Map<Long, String> workNameMap = workRecords.stream()
|
||||
.collect(Collectors.toMap(
|
||||
WorkRecord::getId,
|
||||
WorkRecord::getWorkName,
|
||||
(a, b) -> a));
|
||||
|
||||
list.forEach(task -> task.setWorkName(workNameMap.get(task.getRouteId())));
|
||||
}
|
||||
|
||||
// 查别名
|
||||
Set<String> deviceIds = list.stream()
|
||||
.map(DevicePlanTask::getDeviceId)
|
||||
.filter(Objects::nonNull)
|
||||
.collect(Collectors.toSet());
|
||||
if (!deviceIds.isEmpty()) {
|
||||
List<Device> devices = deviceMapper.selectList(
|
||||
new LambdaQueryWrapper<Device>()
|
||||
.select(Device::getSerialNumber, Device::getDeviceAlias)
|
||||
.in(Device::getSerialNumber, deviceIds));
|
||||
Map<String, String> deviceAliasMap = devices.stream()
|
||||
.collect(Collectors.toMap(
|
||||
Device::getSerialNumber,
|
||||
Device::getDeviceAlias,
|
||||
(a, b) -> a));
|
||||
|
||||
list.forEach(task -> task.setDeviceAlias(deviceAliasMap.get(task.getDeviceId())));
|
||||
}
|
||||
|
||||
return transferDeviceTaskData(list);
|
||||
}
|
||||
|
||||
@@ -476,7 +526,10 @@ public class DeviceTaskService {
|
||||
return list;
|
||||
}
|
||||
|
||||
public Long createDeviceTask(DeviceTaskCommandDTO dto, String username) {
|
||||
public Long createDeviceTask(DeviceTaskCommandDTO dto, String username) throws Exception {
|
||||
SiteMemory siteMemory = GlobalMemory.getSiteMemory(dto.getOrgId(), dto.getSiteId());
|
||||
|
||||
sendAutoTaskMode(siteMemory, dto.getDeviceId()); // 检验权限
|
||||
DevicePlanTask task = new DevicePlanTask();
|
||||
task.setOrgId(dto.getOrgId());
|
||||
task.setSiteId(dto.getSiteId());
|
||||
@@ -490,6 +543,7 @@ public class DeviceTaskService {
|
||||
WorkRecord workRecord = workRecordMapper.selectById(dto.getRouteId());
|
||||
if (workRecord != null) {
|
||||
task.setRouteType(workRecord.getRouteType());
|
||||
task.setWorkName(workRecord.getWorkName());
|
||||
}
|
||||
|
||||
devicePlanTaskMapper.saveOrUpdate(task);
|
||||
@@ -499,12 +553,12 @@ public class DeviceTaskService {
|
||||
dto.setOrgId(site.getOrgId());
|
||||
}
|
||||
}
|
||||
SiteMemory siteMemory = GlobalMemory.getSiteMemory(task.getOrgId(), task.getSiteId());
|
||||
|
||||
siteMemory.addDevicePlanPrepare(task);
|
||||
return task.getId();
|
||||
}
|
||||
|
||||
public Long createRegionDeviceTask(DeviceTaskCommandDTO dto, String username) {
|
||||
public Long createRegionDeviceTask(DeviceTaskCommandDTO dto, String username) throws Exception {
|
||||
LambdaQueryWrapper<SysRegion> queryWrapper = new LambdaQueryWrapper<>();
|
||||
queryWrapper.eq(SysRegion::getId, dto.getRegionId());
|
||||
SysRegion region = sysRegionMapper.selectOne(queryWrapper);
|
||||
@@ -517,6 +571,8 @@ public class DeviceTaskService {
|
||||
routeId = region.getDefaultRoute();
|
||||
}
|
||||
|
||||
SiteMemory siteMemory = GlobalMemory.getSiteMemory(dto.getOrgId(), dto.getSiteId());
|
||||
sendAutoTaskMode(siteMemory, dto.getDeviceId()); // 检验权限
|
||||
if (dto.getOrgId() == null) {
|
||||
SysSite site = sysSiteMapper.selectById(dto.getSiteId());
|
||||
if (site != null) {
|
||||
@@ -536,11 +592,11 @@ public class DeviceTaskService {
|
||||
WorkRecord workRecord = workRecordMapper.selectById(region.getDefaultRoute());
|
||||
if (workRecord != null) {
|
||||
task.setRouteType(workRecord.getRouteType());
|
||||
task.setWorkName(workRecord.getWorkName());
|
||||
}
|
||||
|
||||
devicePlanTaskMapper.saveOrUpdate(task);
|
||||
|
||||
SiteMemory siteMemory = GlobalMemory.getSiteMemory(task.getOrgId(), task.getSiteId());
|
||||
siteMemory.addDevicePlanPrepare(task);
|
||||
return task.getId();
|
||||
}
|
||||
@@ -558,6 +614,7 @@ public class DeviceTaskService {
|
||||
NettyDevice device = deviceSessionManager.getDevice(deviceId);
|
||||
if (device != null && device.getTask() != null) {
|
||||
if (dto.isForceCancel()) {
|
||||
device.cancelingTask();
|
||||
return device.canceledTask() != null;
|
||||
} else {
|
||||
return device.cancelingTask();
|
||||
@@ -579,7 +636,7 @@ public class DeviceTaskService {
|
||||
}
|
||||
|
||||
// todo 完善
|
||||
public boolean pauseTask(DeviceTaskCommandDTO dto, String username) {
|
||||
public boolean pauseTask(DeviceTaskCommandDTO dto, String username) throws MqttException {
|
||||
if (!StringUtils.isEmpty(dto.getDeviceId())) {
|
||||
NettyDevice device = deviceSessionManager.getDevice(dto.getDeviceId());
|
||||
if (device != null) {
|
||||
@@ -599,7 +656,7 @@ public class DeviceTaskService {
|
||||
}
|
||||
|
||||
// todo 完善
|
||||
public boolean recoveryTask(DeviceTaskCommandDTO dto, String username) throws InterruptedException {
|
||||
public boolean recoveryTask(DeviceTaskCommandDTO dto, String username) throws InterruptedException, MqttException {
|
||||
if (!StringUtils.isEmpty(dto.getDeviceId())) {
|
||||
NettyDevice device = deviceSessionManager.getDevice(dto.getDeviceId());
|
||||
if (device != null) {
|
||||
@@ -618,7 +675,9 @@ public class DeviceTaskService {
|
||||
return false;
|
||||
}
|
||||
|
||||
public Long backToRestPoint(DeviceTaskCommandDTO dto, String username) {
|
||||
public Long backToRestPoint(DeviceTaskCommandDTO dto, String username) throws Exception {
|
||||
|
||||
// 先判断 mode 是不是 0 是0 切换成2 成功 失败返回 不是 0 判断是不是2 ,是2 执行 不是2 切换 等结果
|
||||
|
||||
if (dto.getOrgId() == null) {
|
||||
SysSite site = sysSiteMapper.selectById(dto.getSiteId());
|
||||
@@ -628,12 +687,13 @@ public class DeviceTaskService {
|
||||
}
|
||||
|
||||
SiteMemory siteMemory = GlobalMemory.getSiteMemory(dto.getOrgId(), dto.getSiteId());
|
||||
SiteMapInfo siteMapInfo;
|
||||
if (siteMemory == null) {
|
||||
throw new ServiceException(MessageUtils.message("任务下发出错!"));
|
||||
}
|
||||
|
||||
siteMapInfo = siteMemory.getSysSite().getSiteMapInfo();
|
||||
sendAutoTaskMode(siteMemory, dto.getDeviceId()); // 检验权限
|
||||
|
||||
SiteMapInfo siteMapInfo = siteMemory.getSysSite().getSiteMapInfo();
|
||||
|
||||
if (siteMapInfo == null || CollectionUtils.isEmpty(siteMapInfo.getRestPoints())) {
|
||||
throw new ServiceException(MessageUtils.message("当前机器未配置返回点!"));
|
||||
@@ -659,6 +719,7 @@ public class DeviceTaskService {
|
||||
|
||||
task.setRouteId(workRecord.getId());
|
||||
task.setRouteType(workRecord.getRouteType());
|
||||
task.setWorkName(workRecord.getWorkName());
|
||||
|
||||
task.setBackTaskPoint(switchRestPoint);
|
||||
task.setOrgId(dto.getOrgId());
|
||||
@@ -674,7 +735,7 @@ public class DeviceTaskService {
|
||||
return task.getId();
|
||||
}
|
||||
|
||||
public void createConsecutiveTasks(ConsecutiveTaskDTO dto, String username) {
|
||||
public void createConsecutiveTasks(ConsecutiveTaskDTO dto, String username) throws Exception {
|
||||
|
||||
if (dto.getOrgId() == null) {
|
||||
SysSite site = sysSiteMapper.selectById(dto.getSiteId());
|
||||
@@ -686,6 +747,7 @@ public class DeviceTaskService {
|
||||
if (siteMemory == null) {
|
||||
throw new ServiceException(MessageUtils.message("任务下发出错!"));
|
||||
}
|
||||
sendAutoTaskMode(siteMemory, dto.getDeviceId()); // 检验权限
|
||||
siteMemory.saveRegionConsecutiveTask(dto.getDeviceId(), dto, username);
|
||||
|
||||
}
|
||||
@@ -720,4 +782,38 @@ public class DeviceTaskService {
|
||||
}
|
||||
}
|
||||
|
||||
public List<RegionConsecutiveTaskRecord> getRegionConsecutiveTaskRecords(ConsecutiveTaskQueryDTO dto) {
|
||||
LambdaQueryWrapper<RegionConsecutiveTaskRecord> queryWrapper = new LambdaQueryWrapper<>();
|
||||
queryWrapper.eq(RegionConsecutiveTaskRecord::getSiteId, dto.getSiteId());
|
||||
if (!StringUtils.isEmpty(dto.getDeviceId())) {
|
||||
queryWrapper.eq(RegionConsecutiveTaskRecord::getDeviceId, dto.getDeviceId());
|
||||
}
|
||||
if (dto.getTaskStatus() != null) {
|
||||
queryWrapper.eq(RegionConsecutiveTaskRecord::getTaskStatus, dto.getTaskStatus());
|
||||
}
|
||||
if (dto.getStartTime() != null) {
|
||||
queryWrapper.ge(RegionConsecutiveTaskRecord::getCreateTime, dto.getStartTime());
|
||||
}
|
||||
if (dto.getEndTime() != null) {
|
||||
queryWrapper.le(RegionConsecutiveTaskRecord::getCreateTime, dto.getEndTime());
|
||||
}
|
||||
queryWrapper.orderByDesc(RegionConsecutiveTaskRecord::getCreateTime);
|
||||
return regionConsecutiveTaskRecordMapper.selectList(queryWrapper);
|
||||
}
|
||||
|
||||
public void sendAutoTaskMode(SiteMemory siteMemory, String deviceId) throws Exception {
|
||||
VehicleMessage vehicleMessage = siteMemory.getVehicleMessage(deviceId);
|
||||
if (vehicleMessage == null || vehicleMessage.getControl_mode() == null) {
|
||||
throw new ServiceException(MessageUtils.message("当前机器未连接!"));
|
||||
}
|
||||
Integer controlMode = vehicleMessage.getControl_mode();
|
||||
boolean isSend = controlMode != 2;
|
||||
if (isSend) {
|
||||
boolean result = hostComputerService.modeChage(deviceId, 2);
|
||||
if (!result) {
|
||||
throw new ServiceException(MessageUtils.message("当前设备切换模式失败!"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@ package com.maibu.service;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Field;
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
@@ -14,16 +13,7 @@ import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import com.maibu.core.business.dto.DeviceMapPushDTO;
|
||||
import com.maibu.core.business.dto.DeviceTaskCommandDTO;
|
||||
import com.maibu.core.business.dto.WebMapMessageDTO;
|
||||
import com.maibu.core.business.dto.WebOlineStatusMessageDTO;
|
||||
import com.maibu.core.enums.*;
|
||||
import com.maibu.utils.json.JsonUtils;
|
||||
import com.maibu.utils.spring.SpringUtils;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.checkerframework.checker.units.qual.s;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.core.io.Resource;
|
||||
@@ -44,17 +34,27 @@ import com.maibu.core.business.ErrorIdentificationStandard;
|
||||
import com.maibu.core.business.RegionConsecutiveTaskRecord;
|
||||
import com.maibu.core.business.alarm_center.AlarmMessage;
|
||||
import com.maibu.core.business.device.NettyDevice;
|
||||
import com.maibu.core.business.dto.DeviceMapPushDTO;
|
||||
import com.maibu.core.business.dto.DeviceTaskCommandDTO;
|
||||
import com.maibu.core.business.dto.WebMapMessageDTO;
|
||||
import com.maibu.core.business.dto.WebOlineStatusMessageDTO;
|
||||
import com.maibu.core.business.inter.WebsocketMesDispather;
|
||||
import com.maibu.core.domain.AjaxResult;
|
||||
import com.maibu.core.domain.rule.ActionConfig;
|
||||
import com.maibu.core.domain.rule.IotAutoRule;
|
||||
import com.maibu.core.domain.rule.TriggerConditions;
|
||||
import com.maibu.core.enums.ActionType;
|
||||
import com.maibu.core.enums.CompareEnum;
|
||||
import com.maibu.core.enums.ConnectorStatus;
|
||||
import com.maibu.core.enums.DeviceStatus;
|
||||
import com.maibu.core.enums.ErrorSource;
|
||||
import com.maibu.core.enums.MesType;
|
||||
import com.maibu.core.enums.RespondCode;
|
||||
import com.maibu.core.enums.RuleType;
|
||||
import com.maibu.core.host.HeartBeatDTO;
|
||||
import com.maibu.core.host.LocationMessage;
|
||||
import com.maibu.core.host.VehicleMessage;
|
||||
import com.maibu.core.redis.RedisCache;
|
||||
import com.maibu.dto.DeviceErrorPushDTO;
|
||||
import com.maibu.dto.DeviceTaskStatusMessageDTO;
|
||||
import com.maibu.mapper.DeviceRunStatisticsMapper;
|
||||
import com.maibu.mapper.ErrorIdentificationStandardMapper;
|
||||
import com.maibu.mapper.HostLocationMapper;
|
||||
@@ -64,6 +64,7 @@ import com.maibu.memory.GlobalMemory;
|
||||
import com.maibu.memory.SiteMemory;
|
||||
import com.maibu.mqtt.MqttTopic;
|
||||
import com.maibu.utils.CompareUtils;
|
||||
import com.maibu.utils.json.JsonUtils;
|
||||
|
||||
import cn.hutool.core.io.IORuntimeException;
|
||||
import cn.hutool.core.io.IoUtil;
|
||||
@@ -162,7 +163,7 @@ public class DeviceThreadService {
|
||||
});
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("执行监测错误线程错误:{}", e.getMessage());
|
||||
log.error("执行监测错误线程错误", e);
|
||||
}
|
||||
}, 0, 5, TimeUnit.SECONDS);
|
||||
}
|
||||
@@ -237,7 +238,7 @@ public class DeviceThreadService {
|
||||
});
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("推送错误信息失败 device:{}error:{}", deviceId, e.getMessage());
|
||||
log.error("推送错误信息失败 device:{}error", deviceId);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -287,8 +288,7 @@ public class DeviceThreadService {
|
||||
Object value = field.get(history);
|
||||
return (String) value;
|
||||
} catch (NoSuchFieldException | IllegalAccessException e) {
|
||||
System.out.println("获取字段失败: " + e.getMessage());
|
||||
log.error("获取属性值失败:{}", e.getMessage());
|
||||
log.error("获取属性值失败", e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
@@ -318,63 +318,44 @@ public class DeviceThreadService {
|
||||
// 超时了判断离线
|
||||
if (nettyDevice != null && nettyDevice.getOnlineStatus() != null
|
||||
&& nettyDevice.getOnlineStatus() == 1) {
|
||||
nettyDevice.status(DeviceStatus.offline.getType());
|
||||
// todo 推送设备离线
|
||||
String key = NettyCacheKey.latestPositonKey + deviceId;
|
||||
// 保存一下最新一次的数据到 数据库
|
||||
LocationMessage locationMessage = redisCache.getCacheObject(key);
|
||||
if (locationMessage != null) {
|
||||
LambdaQueryWrapper<LocationMessage> queryWrapper = new LambdaQueryWrapper<>();
|
||||
queryWrapper.eq(LocationMessage::getDeviceId, deviceId);
|
||||
LocationMessage existing = hostLocationMapper.selectOne(queryWrapper);
|
||||
if (existing != null) {
|
||||
locationMessage.setId(existing.getId());
|
||||
} else {
|
||||
locationMessage.setCreateTime(LocalDateTime.now());
|
||||
}
|
||||
locationMessage.setUpdateTime(LocalDateTime.now());
|
||||
hostLocationMapper.saveOrUpdate(locationMessage);
|
||||
}
|
||||
Device device = deviceService.selectDeviceBySerialNumber(deviceId);
|
||||
if (device != null) {
|
||||
device.setOnlineStatus(DeviceStatus.offline.getType());
|
||||
device.setUpdateTime(LocalDateTime.now());
|
||||
deviceService.updateDeviceBySelf(device);
|
||||
}
|
||||
|
||||
Long orgId = nettyDevice.getDevice().getOrgId();
|
||||
Long siteId = nettyDevice.getDevice().getSiteId();
|
||||
SiteMemory siteMemory = GlobalMemory.getSiteMemory(orgId, siteId);
|
||||
if (siteMemory != null) {
|
||||
DeviceRunStatistics deviceRunStatistics = siteMemory.getRunStatistics(deviceId);
|
||||
if (deviceRunStatistics != null) {
|
||||
LambdaQueryWrapper<DeviceRunStatistics> queryWrapper = new LambdaQueryWrapper<>();
|
||||
queryWrapper.eq(DeviceRunStatistics::getDeviceId, deviceId);
|
||||
DeviceRunStatistics existing = deviceRunStatisticsMapper
|
||||
.selectOne(queryWrapper);
|
||||
if (existing != null) {
|
||||
deviceRunStatistics.setId(existing.getId());
|
||||
deviceRunStatistics.setDistance(
|
||||
existing.getDistance() + deviceRunStatistics.getDistance());
|
||||
deviceRunStatistics.setWorkArea(
|
||||
existing.getWorkArea() + deviceRunStatistics.getWorkArea());
|
||||
long time = System.currentTimeMillis() - nettyDevice.getLatestLoginTime();
|
||||
deviceRunStatistics.setTime(existing.getTime() + time / (1000 * 60)); // 累加时长,单位为分钟
|
||||
} else {
|
||||
long time = System.currentTimeMillis() - nettyDevice.getLatestLoginTime();
|
||||
deviceRunStatistics.setTime(time / (1000 * 60)); // 累加时长,单位为分钟
|
||||
}
|
||||
deviceRunStatisticsMapper.saveOrUpdate(deviceRunStatistics);
|
||||
|
||||
try {
|
||||
// 标记离线
|
||||
nettyDevice.status(DeviceStatus.offline.getType());
|
||||
updatelatestLocation(deviceId);
|
||||
Device device = deviceService.selectDeviceBySerialNumber(deviceId);
|
||||
if (device != null) {
|
||||
device.setOnlineStatus(DeviceStatus.offline.getType());
|
||||
device.setUpdateTime(LocalDateTime.now());
|
||||
deviceService.updateDeviceBySelf(device);
|
||||
}
|
||||
|
||||
SiteMemory siteMemory = GlobalMemory.getSiteMemory(orgId, siteId);
|
||||
if (siteMemory != null) {
|
||||
updateTotalArea(nettyDevice, siteMemory, deviceId);
|
||||
}
|
||||
// TODO 统计总里程、总作业面积
|
||||
statusChangePush(deviceId, siteId, 0);
|
||||
sessionManager.removeDevice(deviceId);
|
||||
|
||||
} catch (Exception e) {
|
||||
log.error("设备离线处理异常,deviceId={}", deviceId, e);
|
||||
|
||||
} finally {
|
||||
// 必须执行:清理实时缓存
|
||||
try {
|
||||
SiteMemory siteMemory = GlobalMemory.getSiteMemory(orgId, siteId);
|
||||
if (siteMemory != null) {
|
||||
siteMemory.removeMapPushDTO(deviceId);
|
||||
siteMemory.removeVehicleMessage(deviceId);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("设备离线缓存清理失败,deviceId={}", deviceId, e);
|
||||
}
|
||||
// todo 删除实时消息推送里面的数据
|
||||
siteMemory.removeMapPushDTO(deviceId);
|
||||
siteMemory.removeVehicleMessage(deviceId);
|
||||
}
|
||||
|
||||
statusChangePush(deviceId, siteId, 0);
|
||||
sessionManager.removeDevice(deviceId);
|
||||
// TODO 统计总里程、总作业面积
|
||||
|
||||
}
|
||||
} else {
|
||||
Device device = deviceService.selectDeviceBySerialNumber(deviceId);
|
||||
@@ -428,6 +409,50 @@ public class DeviceThreadService {
|
||||
}, 0, 500, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
|
||||
public void updatelatestLocation(String deviceId) {
|
||||
// todo 推送设备离线
|
||||
String key = NettyCacheKey.latestPositonKey + deviceId;
|
||||
// 保存一下最新一次的数据到 数据库
|
||||
LocationMessage locationMessage = redisCache.getCacheObject(key);
|
||||
if (locationMessage != null) {
|
||||
LambdaQueryWrapper<LocationMessage> queryWrapper = new LambdaQueryWrapper<>();
|
||||
queryWrapper.eq(LocationMessage::getDeviceId, deviceId);
|
||||
LocationMessage existing = hostLocationMapper.selectOne(queryWrapper);
|
||||
if (existing != null) {
|
||||
locationMessage.setId(existing.getId());
|
||||
} else {
|
||||
locationMessage.setCreateTime(LocalDateTime.now());
|
||||
}
|
||||
locationMessage.setUpdateTime(LocalDateTime.now());
|
||||
hostLocationMapper.saveOrUpdate(locationMessage);
|
||||
}
|
||||
}
|
||||
|
||||
public void updateTotalArea(NettyDevice nettyDevice, SiteMemory siteMemory, String deviceId) {
|
||||
DeviceRunStatistics deviceRunStatistics = siteMemory.getRunStatistics(deviceId);
|
||||
if (deviceRunStatistics != null) {
|
||||
LambdaQueryWrapper<DeviceRunStatistics> queryWrapper = new LambdaQueryWrapper<>();
|
||||
queryWrapper.eq(DeviceRunStatistics::getDeviceId, deviceId);
|
||||
DeviceRunStatistics existing = deviceRunStatisticsMapper
|
||||
.selectOne(queryWrapper);
|
||||
if (existing != null) {
|
||||
deviceRunStatistics.setId(existing.getId());
|
||||
deviceRunStatistics.setDistance(
|
||||
existing.getDistance() + deviceRunStatistics.getDistance());
|
||||
deviceRunStatistics.setWorkArea(
|
||||
existing.getWorkArea() + deviceRunStatistics.getWorkArea());
|
||||
long time = System.currentTimeMillis()
|
||||
- nettyDevice.getLatestLoginTime();
|
||||
deviceRunStatistics.setTime(existing.getTime() + time / (1000 * 60)); // 累加时长,单位为分钟
|
||||
} else {
|
||||
long time = System.currentTimeMillis()
|
||||
- nettyDevice.getLatestLoginTime();
|
||||
deviceRunStatistics.setTime(time / (1000 * 60)); // 累加时长,单位为分钟
|
||||
}
|
||||
deviceRunStatisticsMapper.saveOrUpdate(deviceRunStatistics);
|
||||
}
|
||||
}
|
||||
|
||||
public void statusChangePush(String deviceId, Long siteId, Integer status) {
|
||||
// todo 推送设备离线
|
||||
WebOlineStatusMessageDTO dto = new WebOlineStatusMessageDTO();
|
||||
@@ -474,7 +499,7 @@ public class DeviceThreadService {
|
||||
});
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("执行监测心跳线程错误:{}", e.getMessage());
|
||||
log.error("执行监测心跳线程错误", e);
|
||||
}
|
||||
}, 0, 100, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
@@ -488,17 +513,24 @@ public class DeviceThreadService {
|
||||
List<SiteMemory> list = GlobalMemory.getAllSiteMemory();
|
||||
if (!CollectionUtils.isEmpty(list)) {
|
||||
list.forEach(x -> {
|
||||
List<IotAutoRule> rules = x.getAllIotAutoRule();
|
||||
if (!CollectionUtils.isEmpty(rules)) {
|
||||
rules.forEach(rule -> {
|
||||
// 根据不同的 类型区分处理方式
|
||||
handleAutoRule(rule, x);
|
||||
if (!CollectionUtils.isEmpty(x.iotAutoRuleMap)) {
|
||||
x.iotAutoRuleMap.keySet().forEach(y -> {
|
||||
List<IotAutoRule> rules = x.iotAutoRuleMap.get(y);
|
||||
if (!CollectionUtils.isEmpty(rules)) {
|
||||
rules.forEach(rule -> {
|
||||
// 根据不同的 类型区分处理方式
|
||||
if (rule != null && rule.getEnabled()) {
|
||||
handleAutoRule(rule, x);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("执行规则出发线程错误:{}", e.getMessage());
|
||||
log.error("执行规则出发线程错误", e);
|
||||
}
|
||||
}, 0, 500, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
@@ -529,7 +561,12 @@ public class DeviceThreadService {
|
||||
dto.setOrgId(siteMemory.getSysSite().getOrgId());
|
||||
dto.setSiteId(siteMemory.getSysSite().getId());
|
||||
|
||||
deviceTaskService.backToRestPoint(dto, "system");
|
||||
try {
|
||||
deviceTaskService.backToRestPoint(dto, "system");
|
||||
} catch (Exception e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
if (ActionType.AUTO_TASK.equals(actionType)) {
|
||||
if (siteMemory.hasTask(deviceId)) {
|
||||
@@ -541,7 +578,12 @@ public class DeviceThreadService {
|
||||
dto.setOrgId(siteMemory.getSysSite().getOrgId());
|
||||
dto.setSiteId(siteMemory.getSysSite().getId());
|
||||
dto.setRouteId(routeId);
|
||||
deviceTaskService.createDeviceTask(dto, "system");
|
||||
try {
|
||||
deviceTaskService.createDeviceTask(dto, "system");
|
||||
} catch (Exception e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
if (ActionType.ALARM.equals(actionType)) {
|
||||
|
||||
@@ -568,10 +610,9 @@ public class DeviceThreadService {
|
||||
Field field = vehicleClass.getDeclaredField(fieldName);
|
||||
field.setAccessible(true);
|
||||
Object value = field.get(history);
|
||||
return (String) value;
|
||||
return String.valueOf(value);
|
||||
} catch (NoSuchFieldException | IllegalAccessException e) {
|
||||
System.out.println("获取字段失败: " + e.getMessage());
|
||||
log.error("获取属性值失败:{}", e.getMessage());
|
||||
log.error("获取属性值失败:", e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
@@ -602,7 +643,13 @@ public class DeviceThreadService {
|
||||
dto.setOrgId(siteMemory.getSysSite().getOrgId());
|
||||
dto.setSiteId(siteMemory.getSysSite().getId());
|
||||
dto.setRouteId(routeId);
|
||||
Long taskId = deviceTaskService.createDeviceTask(dto, "system");
|
||||
Long taskId = null;
|
||||
try {
|
||||
taskId = deviceTaskService.createDeviceTask(dto, "system");
|
||||
} catch (Exception e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
}
|
||||
if (taskId != null) {
|
||||
record.getTaskIds().add(taskId);
|
||||
record.setCurrentIndex(currentIndex + 1);
|
||||
@@ -616,7 +663,7 @@ public class DeviceThreadService {
|
||||
});
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("区域连续任务处理线程错误:{}", e.getMessage());
|
||||
log.error("区域连续任务处理线程错误", e);
|
||||
}
|
||||
}, 0, 500, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
@@ -19,7 +20,7 @@ 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.DeviceRunParam;
|
||||
import com.maibu.core.business.WorkRecord;
|
||||
import com.maibu.core.business.device.NettyDevice;
|
||||
import com.maibu.core.business.dto.WebRouteStatusMessageDTO;
|
||||
import com.maibu.core.business.inter.WebsocketMesDispather;
|
||||
@@ -32,6 +33,8 @@ import com.maibu.memory.DeviceSessionManager;
|
||||
import com.maibu.memory.GlobalMemory;
|
||||
import com.maibu.mqtt.MqttTopic;
|
||||
import com.maibu.service.impl.HostComputerService;
|
||||
import com.maibu.service.impl.WorkRecordService;
|
||||
import com.maibu.utils.MinioUtil;
|
||||
import com.maibu.utils.json.JsonUtils;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
@@ -52,9 +55,18 @@ public class HostComputerController extends BaseController {
|
||||
@Autowired
|
||||
private DeviceSessionManager deviceSessionManager;
|
||||
|
||||
@Autowired
|
||||
private WorkRecordService workRecordService;
|
||||
|
||||
@Value("${mqtt.client-id}")
|
||||
private String mqttClientId;
|
||||
|
||||
@Value("${minio.endpoint}")
|
||||
private String minioUrl;
|
||||
|
||||
@Autowired
|
||||
private MinioUtil minioUtil;
|
||||
|
||||
/**
|
||||
* 上传 csv.gz 轨迹文件并解析为 LatAndLngEntity 列表(分批处理,每批 BATCH_SIZE 条)
|
||||
*
|
||||
@@ -69,7 +81,8 @@ public class HostComputerController extends BaseController {
|
||||
@PostMapping(value = "/upload-path-csv", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
|
||||
public R uploadCsv(
|
||||
@RequestPart("file") MultipartFile file,
|
||||
@RequestParam("taskId") Long taskId) {
|
||||
@RequestParam(value = "taskId") Long taskId,
|
||||
@RequestParam(value = "pathId", required = false) Long pathId) {
|
||||
if (file == null || file.isEmpty()) {
|
||||
return R.fail("文件不能为空");
|
||||
}
|
||||
@@ -136,8 +149,22 @@ public class HostComputerController extends BaseController {
|
||||
|
||||
log.info("csv 解析完成: taskId={}, 共 {} 个轨迹点, 分 {} 批处理", taskId, allPath.size(), batchIndex);
|
||||
|
||||
GlobalMemory.taskPathMap.put(taskId, allPath);
|
||||
sendMessage(taskId, allPath);
|
||||
if (pathId == null) {
|
||||
GlobalMemory.taskPathMap.put(taskId, allPath);
|
||||
sendMessage(taskId, allPath);
|
||||
} else {
|
||||
// 上传到 MinIO
|
||||
minioUtil.uploadFile(originalFilename, gzipInputStream, "application/gzip");
|
||||
// 获取访问 URL
|
||||
String url = minioUtil.getPublicUrl(originalFilename);
|
||||
|
||||
WorkRecord workRecord = workRecordService.selectById(pathId);
|
||||
if (workRecord != null) {
|
||||
workRecord.setFileUrl(url);
|
||||
workRecordService.updateWorkRecord(workRecord);
|
||||
}
|
||||
}
|
||||
|
||||
// TODO 推送数据到前端
|
||||
|
||||
return R.ok();
|
||||
@@ -261,7 +288,12 @@ public class HostComputerController extends BaseController {
|
||||
@GetMapping("/searchDevice")
|
||||
public AjaxResult searchDevice(@RequestParam String deviceId) throws Exception {
|
||||
hostComputerService.searchDevice(deviceId);
|
||||
return success();
|
||||
return AjaxResult.success();
|
||||
}
|
||||
|
||||
@GetMapping("/modeChage")
|
||||
public AjaxResult modeChange(@RequestParam String deviceId, @RequestParam Integer controlMode) throws Exception {
|
||||
return AjaxResult.success(hostComputerService.modeChage(deviceId, controlMode));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -12,7 +12,6 @@ import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import com.maibu.core.controller.BaseController;
|
||||
import com.maibu.core.domain.AjaxResult;
|
||||
import com.maibu.core.domain.entity.SysMenu;
|
||||
import com.maibu.core.domain.rule.IotAutoRule;
|
||||
import com.maibu.core.domain.rule.IotAutoRuleRecord;
|
||||
import com.maibu.core.page.TableDataInfo;
|
||||
|
||||
@@ -1,20 +1,32 @@
|
||||
package com.maibu.controller;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.commons.collections4.CollectionUtils;
|
||||
import org.eclipse.paho.client.mqttv3.MqttException;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.util.StringUtils;
|
||||
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.dto.DeviceMapPushDTO;
|
||||
import com.maibu.core.controller.BaseController;
|
||||
import com.maibu.core.domain.AjaxResult;
|
||||
import com.maibu.core.domain.R;
|
||||
import com.maibu.core.enums.RouteType;
|
||||
import com.maibu.memory.GlobalMemory;
|
||||
import com.maibu.memory.SiteMemory;
|
||||
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.util.List;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/iot/workRecord")
|
||||
@@ -49,7 +61,26 @@ public class WorkRecordController extends BaseController {
|
||||
if (workRecord1 != null) {
|
||||
return R.fail("该任务已存在");
|
||||
}
|
||||
|
||||
// 自定义模式的任务需要有在线 且空闲的车辆;
|
||||
String deviceId = null;
|
||||
if ("predefined_path".equals(workRecord.getMode())) {
|
||||
Long siteId = workRecord.getSiteId();
|
||||
Long orgId = workRecord.getOrgId();
|
||||
SiteMemory siteMemory = GlobalMemory.getSiteMemory(orgId, siteId);
|
||||
if (siteMemory != null) {
|
||||
if (CollectionUtils.isEmpty(siteMemory.deviceMapPushMap.values())) {
|
||||
return R.fail("当前模式的规划需有在线且空闲的机器!");
|
||||
} else {
|
||||
DeviceMapPushDTO dto = siteMemory.deviceMapPushMap.values().stream()
|
||||
.filter(x -> x.getT() == null)
|
||||
.findFirst().orElse(null);
|
||||
if (dto == null) {
|
||||
return R.fail("当前模式的规划需有在线且空闲的机器!");
|
||||
}
|
||||
deviceId = dto.getId();
|
||||
}
|
||||
}
|
||||
}
|
||||
try (InputStream inputStream = file.getInputStream()) {
|
||||
|
||||
String fileName = "routePlanImage/rt" + workRecord.getWorkName() + System.currentTimeMillis() + ".png";
|
||||
@@ -65,7 +96,7 @@ public class WorkRecordController extends BaseController {
|
||||
workRecord.setImgUrl(url);
|
||||
workRecord.setUserId(getUserId());
|
||||
workRecord.setOrgId(getLoginUser().getOrgId());
|
||||
i = workRecordService.addWorkRecord(workRecord);
|
||||
i = workRecordService.addWorkRecord(workRecord, deviceId);
|
||||
} catch (Exception e) {
|
||||
return R.fail("新增失败: " + e.getMessage());
|
||||
}
|
||||
@@ -92,8 +123,25 @@ public class WorkRecordController extends BaseController {
|
||||
}
|
||||
|
||||
@PostMapping("/update")
|
||||
public R updateWorkRecord(@RequestBody WorkRecord workRecord) {
|
||||
boolean b = workRecordService.updateWorkRecord(workRecord);
|
||||
public R updateWorkRecord(@RequestBody WorkRecord workRecord) throws MqttException {
|
||||
String deviceId = null;
|
||||
Long siteId = workRecord.getSiteId();
|
||||
Long orgId = workRecord.getOrgId();
|
||||
SiteMemory siteMemory = GlobalMemory.getSiteMemory(orgId, siteId);
|
||||
if (siteMemory != null) {
|
||||
if (CollectionUtils.isEmpty(siteMemory.deviceMapPushMap.values())) {
|
||||
return R.fail("当前模式的规划需有在线且空闲的机器!");
|
||||
} else {
|
||||
DeviceMapPushDTO dto = siteMemory.deviceMapPushMap.values().stream()
|
||||
.filter(x -> StringUtils.isEmpty(x.getT()))
|
||||
.findFirst().orElse(null);
|
||||
if (dto == null) {
|
||||
return R.fail("当前模式的规划需有在线且空闲的机器!");
|
||||
}
|
||||
deviceId = dto.getId();
|
||||
}
|
||||
}
|
||||
boolean b = workRecordService.updateWorkRecord(workRecord, deviceId);
|
||||
return !b ? R.fail("更新失败") : R.ok("更新成功");
|
||||
}
|
||||
|
||||
|
||||
@@ -4,8 +4,10 @@ import java.util.List;
|
||||
|
||||
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.core.domain.map.SiteMapInfo;
|
||||
import com.maibu.core.domain.rule.IotAutoRule;
|
||||
import com.maibu.core.domain.rule.IotAutoRuleRecord;
|
||||
@@ -31,7 +33,7 @@ public class IotAutoRuleService {
|
||||
public boolean save(IotAutoRule iotAutoRule) {
|
||||
try {
|
||||
boolean b = iotAutoRuleMapper.saveOrUpdate(iotAutoRule);
|
||||
SiteMemory siteMemory = GlobalMemory.getSiteMemory(iotAutoRule.getOrgId(), iotAutoRule.getId());
|
||||
SiteMemory siteMemory = GlobalMemory.getSiteMemory(iotAutoRule.getOrgId(), iotAutoRule.getSiteId());
|
||||
if (siteMemory != null && siteMemory.sysSite != null) {
|
||||
siteMemory.saveIotAutoRule(iotAutoRule.getRuleType(), iotAutoRule);
|
||||
return b;
|
||||
@@ -48,10 +50,10 @@ public class IotAutoRuleService {
|
||||
return iotAutoRuleMapper.selectById(id);
|
||||
}
|
||||
|
||||
public IotAutoRule selectBySiteId(Long siteId) {
|
||||
public List<IotAutoRule> selectBySiteId(Long siteId) {
|
||||
LambdaQueryWrapper<IotAutoRule> queryWrapper = new LambdaQueryWrapper<>();
|
||||
queryWrapper.eq(IotAutoRule::getSiteId, siteId);
|
||||
return iotAutoRuleMapper.selectOne(queryWrapper);
|
||||
return iotAutoRuleMapper.selectList(queryWrapper);
|
||||
}
|
||||
|
||||
public List<IotAutoRuleRecord> selectAllRecord(IotAutoRuleRecordQueryDTO queryDto) {
|
||||
@@ -77,6 +79,16 @@ public class IotAutoRuleService {
|
||||
}
|
||||
|
||||
public int delete(List<Long> ids) {
|
||||
return iotAutoRuleRecordMapper.deleteBatchIds(ids);
|
||||
|
||||
List<IotAutoRule> iotAutoRules = iotAutoRuleMapper.selectBatchIds(ids);
|
||||
if (!CollectionUtils.isEmpty(iotAutoRules)) {
|
||||
iotAutoRules.forEach(x -> {
|
||||
SiteMemory siteMemory = GlobalMemory.getSiteMemory(x.getOrgId(), x.getSiteId());
|
||||
if (siteMemory != null) {
|
||||
siteMemory.removeIotAutoRule(x);
|
||||
}
|
||||
});
|
||||
}
|
||||
return iotAutoRuleMapper.deleteBatchIds(ids);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,12 +4,9 @@ import java.time.LocalDate;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
@@ -20,11 +17,8 @@ import org.springframework.stereotype.Service;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.maibu.constant.Constant;
|
||||
import com.maibu.core.business.DeviceRunParam;
|
||||
import com.maibu.core.business.device.NettyDevice;
|
||||
import com.maibu.dto.BaseQueryDTO;
|
||||
import com.maibu.exception.ServiceException;
|
||||
import com.maibu.mapper.DeviceRunParamMapper;
|
||||
import com.maibu.memory.DeviceSessionManager;
|
||||
import com.maibu.memory.GlobalMemory;
|
||||
@@ -89,6 +83,8 @@ public class DeviceRunParamService {
|
||||
|
||||
public boolean save(DeviceRunParam deviceRunParam) {
|
||||
|
||||
parseSn(deviceRunParam.getDeviceId(), deviceRunParam);
|
||||
|
||||
return deviceRunParamMapper.saveOrUpdate(deviceRunParam);
|
||||
|
||||
}
|
||||
|
||||
@@ -1,10 +1,19 @@
|
||||
package com.maibu.service.impl;
|
||||
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import com.maibu.core.business.device.NettyDevice;
|
||||
import com.maibu.core.host.VehicleMessage;
|
||||
import com.maibu.exception.ServiceException;
|
||||
import com.maibu.memory.DeviceSessionManager;
|
||||
import com.maibu.memory.GlobalMemory;
|
||||
import com.maibu.memory.SiteMemory;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
@@ -22,4 +31,80 @@ public class HostComputerService {
|
||||
}
|
||||
}
|
||||
|
||||
// public void modeChage(String deviceId, Integer controlMode) throws Exception
|
||||
// {
|
||||
// NettyDevice device = deviceSessionManager.getDevice(deviceId);
|
||||
|
||||
// if (device == null || device.getOnlineStatus() == null ||
|
||||
// device.getOnlineStatus() == 0) {
|
||||
// throw new ServiceException("设备不在线");
|
||||
// }
|
||||
// Long orgId = device.getDevice().getOrgId();
|
||||
// Long siteId = device.getDevice().getSiteId();
|
||||
// SiteMemory siteMemory = GlobalMemory.getSiteMemory(orgId, siteId);
|
||||
// if (siteMemory != null) {
|
||||
// VehicleMessage vehicleMessage = siteMemory.getVehicleMessage(deviceId);
|
||||
// if (vehicleMessage != null && vehicleMessage.getControl_mode() != null) {
|
||||
// Integer nowMode = vehicleMessage.getControl_mode();
|
||||
// if (controlMode.equals(nowMode)) {
|
||||
// throw new ServiceException("设备已处于该模式");
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// device.modeChage(deviceId, controlMode);
|
||||
// }
|
||||
|
||||
public Boolean modeChage(String deviceId, Integer controlMode) throws Exception {
|
||||
NettyDevice device = deviceSessionManager.getDevice(deviceId);
|
||||
|
||||
if (device == null || device.getOnlineStatus() == null
|
||||
|| device.getOnlineStatus() == 0) {
|
||||
throw new ServiceException("设备不在线");
|
||||
}
|
||||
|
||||
Long orgId = device.getDevice().getOrgId();
|
||||
Long siteId = device.getDevice().getSiteId();
|
||||
|
||||
SiteMemory siteMemory = GlobalMemory.getSiteMemory(orgId, siteId);
|
||||
|
||||
if (siteMemory != null) {
|
||||
VehicleMessage vehicleMessage = siteMemory.getVehicleMessage(deviceId);
|
||||
|
||||
if (vehicleMessage != null && vehicleMessage.getControl_mode() != null) {
|
||||
Integer nowMode = vehicleMessage.getControl_mode();
|
||||
|
||||
if (controlMode.equals(nowMode)) {
|
||||
throw new ServiceException("设备已处于该模式");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 创建等待回传的 Future
|
||||
CompletableFuture<Boolean> future = new CompletableFuture<>();
|
||||
|
||||
// 一个设备同时只允许一个模式切换请求
|
||||
CompletableFuture<Boolean> oldFuture = GlobalMemory.modeFutureMap.putIfAbsent(deviceId, future);
|
||||
|
||||
if (oldFuture != null) {
|
||||
throw new ServiceException("设备正在执行模式切换,请稍后再试");
|
||||
}
|
||||
|
||||
try {
|
||||
// 下发指令
|
||||
device.modeChage(deviceId, controlMode);
|
||||
|
||||
// 等待设备回传,最多等待 5 秒
|
||||
Boolean result = future.get(5, TimeUnit.SECONDS);
|
||||
|
||||
return result;
|
||||
|
||||
} catch (Exception e) {
|
||||
throw new ServiceException("设备模式切换失败");
|
||||
|
||||
} finally {
|
||||
// 无论成功、失败还是超时,都清理 Future
|
||||
GlobalMemory.modeFutureMap.remove(deviceId, future);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -73,7 +73,7 @@ public class OrderModelService {
|
||||
return i;
|
||||
}
|
||||
|
||||
public String createTask(String deviceId, Long siteId, Long orgId, Long modelId) {
|
||||
public String createTask(String deviceId, Long siteId, Long orgId, Long modelId) throws Exception {
|
||||
SiteMemory siteMemory = GlobalMemory.getSiteMemory(orgId, siteId);
|
||||
OrderModel orderModel = siteMemory.getOrderModel(modelId);
|
||||
OrderType orderType = orderModel.getOrderType();
|
||||
|
||||
@@ -235,9 +235,9 @@ public class WorkOrderServiceImpl extends ServiceImpl<IotWorkOrderMapper, IOTWor
|
||||
throw new ServiceException("工单不存在");
|
||||
|
||||
Long userId = SecurityUtils.getUserId();
|
||||
// if (!SecurityUtils.isAdmin(userId)) {
|
||||
// validateWorkOrderAccess(workOrder);
|
||||
// }
|
||||
// if (!SecurityUtils.isAdmin(userId)) {
|
||||
// validateWorkOrderAccess(workOrder);
|
||||
// }
|
||||
return workOrder;
|
||||
}
|
||||
|
||||
@@ -297,13 +297,13 @@ public class WorkOrderServiceImpl extends ServiceImpl<IotWorkOrderMapper, IOTWor
|
||||
throw new ServiceException("工单ID不能为空");
|
||||
}
|
||||
|
||||
// Long userId = SecurityUtils.getUserId();
|
||||
// if (!SecurityUtils.isAdmin(userId)) {
|
||||
// IOTWorkOrder existWorkOrder = baseMapper.selectById(workOrder.getId());
|
||||
// if (existWorkOrder != null) {
|
||||
// validateWorkOrderAccess(existWorkOrder);
|
||||
// }
|
||||
// }
|
||||
// Long userId = SecurityUtils.getUserId();
|
||||
// if (!SecurityUtils.isAdmin(userId)) {
|
||||
// IOTWorkOrder existWorkOrder = baseMapper.selectById(workOrder.getId());
|
||||
// if (existWorkOrder != null) {
|
||||
// validateWorkOrderAccess(existWorkOrder);
|
||||
// }
|
||||
// }
|
||||
|
||||
IOTWorkOrder updateEntity = new IOTWorkOrder();
|
||||
updateEntity.setId(workOrder.getId());
|
||||
@@ -340,10 +340,10 @@ public class WorkOrderServiceImpl extends ServiceImpl<IotWorkOrderMapper, IOTWor
|
||||
if (workOrder == null)
|
||||
throw new ServiceException("工单不存在");
|
||||
|
||||
// Long userId = SecurityUtils.getUserId();
|
||||
// if (!SecurityUtils.isAdmin(userId)) {
|
||||
// validateWorkOrderAccess(workOrder);
|
||||
// }
|
||||
// Long userId = SecurityUtils.getUserId();
|
||||
// if (!SecurityUtils.isAdmin(userId)) {
|
||||
// validateWorkOrderAccess(workOrder);
|
||||
// }
|
||||
|
||||
IOTWorkOrder updateWorkOrder = new IOTWorkOrder();
|
||||
updateWorkOrder.setId(dispatchDTO.getOrderId());
|
||||
@@ -381,11 +381,18 @@ public class WorkOrderServiceImpl extends ServiceImpl<IotWorkOrderMapper, IOTWor
|
||||
workOrder.setAssigneeName(userName);
|
||||
// todo 派发自定义的路径规划任务
|
||||
Long modelId = workOrder.getModelId();
|
||||
if (modelId == null) return;
|
||||
if (modelId == null)
|
||||
return;
|
||||
Long siteId = workOrder.getSiteId();
|
||||
Long orgId = workOrder.getOrgId();
|
||||
String id = orderModelService.createTask(dto.getDeviceId(), siteId, orgId, modelId);
|
||||
workOrder.setTaskId(id);
|
||||
String id;
|
||||
try {
|
||||
id = orderModelService.createTask(dto.getDeviceId(), siteId, orgId, modelId);
|
||||
workOrder.setTaskId(id);
|
||||
} catch (Exception e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
}
|
||||
});
|
||||
return baseMapper.saveOrUpdateBatch(workOrders);
|
||||
}
|
||||
@@ -397,10 +404,10 @@ public class WorkOrderServiceImpl extends ServiceImpl<IotWorkOrderMapper, IOTWor
|
||||
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());
|
||||
@@ -416,7 +423,7 @@ public class WorkOrderServiceImpl extends ServiceImpl<IotWorkOrderMapper, IOTWor
|
||||
if (existWorkOrder.getAlarmId() != null) {
|
||||
Alarm alarm = alarmMapper.selectById(existWorkOrder.getAlarmId());
|
||||
if (alarm != null) {
|
||||
// alarm.setHandleResult(AlarmHandleResult.Handled);
|
||||
// alarm.setHandleResult(AlarmHandleResult.Handled);
|
||||
alarm.setHandleStatus(2);
|
||||
alarm.setUpdateTime(LocalDateTime.now());
|
||||
alarm.setUpdateBy("system");
|
||||
@@ -460,15 +467,15 @@ public class WorkOrderServiceImpl extends ServiceImpl<IotWorkOrderMapper, IOTWor
|
||||
|
||||
@Override
|
||||
public int deleteWorkOrderByIds(Long[] ids) {
|
||||
// Long userId = SecurityUtils.getUserId();
|
||||
// if (!SecurityUtils.isAdmin(userId)) {
|
||||
// for (Long id : ids) {
|
||||
// IOTWorkOrder workOrder = baseMapper.selectById(id);
|
||||
// if (workOrder != null) {
|
||||
// validateWorkOrderAccess(workOrder);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// Long userId = SecurityUtils.getUserId();
|
||||
// if (!SecurityUtils.isAdmin(userId)) {
|
||||
// for (Long id : ids) {
|
||||
// IOTWorkOrder workOrder = baseMapper.selectById(id);
|
||||
// if (workOrder != null) {
|
||||
// validateWorkOrderAccess(workOrder);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
return iotWorkOrderMapper.deleteBatchIds(Arrays.asList(ids));
|
||||
}
|
||||
|
||||
|
||||
@@ -3,11 +3,16 @@ package com.maibu.service.impl;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.maibu.core.business.DevicePlanTask;
|
||||
import com.maibu.core.business.WorkRecord;
|
||||
import com.maibu.core.business.device.NettyDevice;
|
||||
import com.maibu.mapper.DevicePlanTaskMapper;
|
||||
import com.maibu.mapper.WorkRecordMapper;
|
||||
import com.maibu.memory.DeviceSessionManager;
|
||||
|
||||
import org.eclipse.paho.client.mqttv3.MqttException;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Comparator;
|
||||
@@ -22,9 +27,19 @@ public class WorkRecordService {
|
||||
@Autowired
|
||||
private DevicePlanTaskMapper devicePlanTaskMapper;
|
||||
|
||||
public int addWorkRecord(WorkRecord workRecord) throws Exception {
|
||||
@Autowired
|
||||
private DeviceSessionManager deviceSessionManager;
|
||||
|
||||
public int addWorkRecord(WorkRecord workRecord, String deviceId) throws Exception {
|
||||
int i = workRecordMapper.insert(workRecord);
|
||||
// int i = workRecordMapper.insertWorkRecord(workRecord);
|
||||
if (StringUtils.hasText(deviceId)) {
|
||||
NettyDevice device = deviceSessionManager.getDevice(deviceId);
|
||||
if (device != null) {
|
||||
device.sendPredefined(workRecord);
|
||||
}
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
@@ -53,8 +68,19 @@ public class WorkRecordService {
|
||||
return workRecordMapper.delete(queryWrapper);
|
||||
}
|
||||
|
||||
public boolean updateWorkRecord(WorkRecord workRecord, String deviceId) throws MqttException {
|
||||
boolean i = workRecordMapper.saveOrUpdate(workRecord);
|
||||
NettyDevice device = deviceSessionManager.getDevice(deviceId);
|
||||
if (device != null) {
|
||||
device.sendPredefined(workRecord);
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
public boolean updateWorkRecord(WorkRecord workRecord) {
|
||||
return workRecordMapper.saveOrUpdate(workRecord);
|
||||
boolean i = workRecordMapper.saveOrUpdate(workRecord);
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
public List<WorkRecord> selectBySiteId(Long siteId) {
|
||||
|
||||
@@ -19,7 +19,7 @@ public class SiteMapInfoService {
|
||||
public boolean save(SiteMapInfo siteMapInfo) {
|
||||
try {
|
||||
boolean b = siteMapInfoMapper.saveOrUpdate(siteMapInfo);
|
||||
SiteMemory siteMemory = GlobalMemory.getSiteMemory(siteMapInfo.getOrgId(), siteMapInfo.getId());
|
||||
SiteMemory siteMemory = GlobalMemory.getSiteMemory(siteMapInfo.getOrgId(), siteMapInfo.getSiteId());
|
||||
if (siteMemory != null && siteMemory.sysSite != null) {
|
||||
siteMemory.sysSite.setSiteMapInfo(siteMapInfo);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user