This commit is contained in:
2026-07-09 08:40:32 +08:00
parent caf4e2c415
commit 8f7a35e3c7
44 changed files with 1328 additions and 188 deletions

View File

@@ -227,8 +227,17 @@
<version>3.5.1</version>
</dependency>
<!-- OkHttp3依赖 -->
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>alibaba-dingtalk-service-sdk</artifactId>
<version>2.0.0</version>
</dependency>
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
<version>1.11</version>
</dependency>
</dependencies>
<properties>

View File

@@ -1,6 +1,14 @@
package com.maibu.core.business;
import com.baomidou.mybatisplus.annotation.*;
import java.math.BigDecimal;
import java.util.Date;
import java.util.Map;
import com.baomidou.mybatisplus.annotation.FieldStrategy;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.maibu.annotation.Excel;
@@ -11,12 +19,6 @@ import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.springframework.data.annotation.Transient;
import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.Map;
/**
* 设备对象 iot_device
@@ -228,4 +230,7 @@ public class Device extends BaseDO {
@TableField(exist = false)
private Map<Integer,Integer> statusStatistics;
@TableField(exist = false)
private DeviceRunParam runParam;
}

View File

@@ -1,25 +1,18 @@
package com.maibu.core.business;
import java.util.List;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.maibu.annotation.Excel;
import com.maibu.core.domain.BaseDO;
import com.maibu.core.enums.ConnectType;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.springframework.data.annotation.Transient;
import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.Map;
@EqualsAndHashCode(callSuper = true)

View File

@@ -0,0 +1,27 @@
package com.maibu.core.business;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.maibu.core.domain.BaseDO;
import lombok.Data;
import lombok.EqualsAndHashCode;
@EqualsAndHashCode(callSuper = true)
@Data
@TableName(value = "iot_device_run_param", autoResultMap = true)
public class DeviceRunParam extends BaseDO {
@TableId(type = IdType.AUTO)
private Long id;
private String deviceId;
private Long siteId;
private Long orgId;
private Double runSpeed;
}

View File

@@ -3,7 +3,10 @@ package com.maibu.core.business;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.maibu.core.enums.CompareEnum;import lombok.Data;
import com.maibu.core.enums.CompareEnum;
import com.maibu.core.enums.ErrorLevel;
import com.maibu.core.enums.ErrorSource;
import lombok.Data;
@Data
@@ -16,4 +19,8 @@ public class ErrorIdentificationStandard {
private CompareEnum compareType;
private String errorDescription;
private String errorName;
private ErrorSource errorSource;
private String errorCode;
private ErrorLevel errorLevel;
private String suggestion;
}

View File

@@ -1 +1,112 @@
package com.maibu.core.business;
package com.maibu.core.business;
import com.baomidou.mybatisplus.annotation.*;
import com.maibu.core.domain.TenantBaseDO;
import com.maibu.core.enums.ErrorLevel;
import com.maibu.core.enums.ErrorSource;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.math.BigDecimal;
import java.time.LocalDateTime;
@Data
@EqualsAndHashCode(callSuper = true)
@TableName("iot_work_order")
@ApiModel("工单记录")
public class IOTWorkOrder extends TenantBaseDO {
@ApiModelProperty("主键 ID")
@TableId(type = IdType.AUTO)
private Long id;
@ApiModelProperty("工单编号")
private String orderNo;
@ApiModelProperty("工单标题")
private String orderTitle;
@ApiModelProperty("工单来源:1-AI 诊断 2-无人机巡检 3-清洗优化 4-视频监控 5-装备控制 6-人工创建 7-告警关联")
private Integer sourceType;
@ApiModelProperty("工单类型:1-巡检 2-检修 3-清洗 4-维修 5-运维")
private Integer orderType;
@ApiModelProperty("优先级:1-高 2-中 3-低")
private ErrorLevel priorityLevel;
@ApiModelProperty("关联设备 ID")
private String deviceId;
@ApiModelProperty("关联设备名称")
private String deviceName;
@ApiModelProperty("设备类型")
private ErrorSource deviceType;
@ApiModelProperty("关联场站 ID")
private Long siteId;
@ApiModelProperty("关联场站名称")
private String siteName;
@ApiModelProperty("关联组织 ID")
private Long orgId;
@ApiModelProperty("负责人 ID")
private Long assigneeId;
@ApiModelProperty("负责人姓名")
private String assigneeName;
@ApiModelProperty("协同人员 ID 列表 (逗号分隔)")
private String collaboratorIds;
@ApiModelProperty("协同人员姓名列表 (逗号分隔)")
private String collaboratorNames;
@ApiModelProperty("计划开始时间")
private LocalDateTime planStartTime;
@ApiModelProperty("计划结束时间")
private LocalDateTime planEndTime;
@ApiModelProperty("截止时间")
private LocalDateTime deadlineTime;
@ApiModelProperty("实际开始时间")
private LocalDateTime actualStartTime;
@ApiModelProperty("实际完成时间")
private LocalDateTime actualEndTime;
@ApiModelProperty("工单状态:1-待处理 2-已派发 3-执行中 4-已完成 5-已挂起")
private Integer orderStatus;
@ApiModelProperty("关联告警 ID")
private Long alarmId;
@ApiModelProperty("关联告警编号")
private String alarmNo;
@ApiModelProperty("任务描述")
private String taskDescription;
@ApiModelProperty("AI 建议")
private String aiSuggestion;
@ApiModelProperty("建议携带设备")
private String requiredEquipment;
@ApiModelProperty("预计影响发电量 (%)")
private BigDecimal estimatedImpact;
@ApiModelProperty("处理结果")
private String handleResult;
@ApiModelProperty("处理备注")
private String handleRemark;
}

View File

@@ -3,6 +3,9 @@ package com.maibu.core.business.alarm_center;
import com.baomidou.mybatisplus.annotation.*;
import com.maibu.annotation.Excel;
import com.maibu.core.domain.TenantBaseDO;
import com.maibu.core.enums.ErrorLevel;
import com.maibu.core.enums.ErrorSource;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@@ -27,7 +30,7 @@ public class Alarm extends TenantBaseDO {
@ApiModelProperty("告警级别:1-严重 2-重要 3-一般 4-提示")
@Excel(name = "告警级别", readConverterExp = "1=严重,2=重要,3=一般,4=提示")
private Integer alarmLevel;
private ErrorLevel alarmLevel;
@ApiModelProperty("告警类型:1-设备故障 2-数据异常 3-通信中断 4-性能告警 5-安全告警 6-环境告警")
@Excel(name = "告警类型", readConverterExp = "1=设备故障,2=数据异常,3=通信中断,4=性能告警,5=安全告警,6=环境告警")
@@ -43,7 +46,7 @@ public class Alarm extends TenantBaseDO {
@ApiModelProperty("设备ID")
@Excel(name = "设备ID", cellType = Excel.ColumnType.NUMERIC)
private Long deviceId;
private String deviceId;
@ApiModelProperty("设备名称")
@Excel(name = "设备名称")
@@ -51,7 +54,7 @@ public class Alarm extends TenantBaseDO {
@ApiModelProperty("设备类型:1-逆变器 2-汇流箱 3-组串 4-气象站 5-电表 6-智能汇流箱 7-箱变 8-SVG")
@Excel(name = "设备类型", readConverterExp = "1=逆变器,2=汇流箱,3=组串,4=气象站,5=电表,6=智能汇流箱,7=箱变,8=SVG")
private Integer deviceType;
private ErrorSource deviceType;
@ApiModelProperty("告警发生时间")
@Excel(name = "告警时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")

View File

@@ -0,0 +1,43 @@
package com.maibu.core.business.alarm_center;
import java.time.LocalDateTime;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.maibu.core.enums.ErrorLevel;
import lombok.Data;
@Data
public class AlarmMessage {
/** 告警等级 P1/P2/P3/P4 */
private ErrorLevel level;
/** 告警名称 */
private String name;
/** 告警code */
private String no;
/** 告警时间 */
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime time;
/** 设备名称 */
private String deviceName;
/** 设备SN */
private String deviceSn;
/** 告警内容 */
private String content;
/** 所在位置 */
private String location;
/** 处理建议 */
private String suggestion;
/** 状态 */
private String status;
}

View File

@@ -7,7 +7,9 @@ import java.util.Queue;
import org.springframework.util.CollectionUtils;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.maibu.core.business.Device;
import com.maibu.core.business.DevicePlanTask;
import com.maibu.core.business.DeviceRunParam;
import com.maibu.core.business.DeviceRunStatistics;
import com.maibu.core.business.PlanPath;
import com.maibu.core.business.WorkRecord;
@@ -50,6 +52,8 @@ public class NettyDevice extends Connector {
private Long latestLoginTime;
private boolean executingTask = false;
// todo 注册的时候更新 siteId
private Device device;
@JsonIgnore
private DevicePlanTaskMapper devicePlanTaskMapper = SpringUtils.getBean(DevicePlanTaskMapper.class);
@@ -74,7 +78,17 @@ public class NettyDevice extends Connector {
if (!locationQueue.isEmpty()) {
LatAndLngEntity entity = locationQueue.poll();
if (entity != null) {
sendPathCommand((byte) 0x01, (short) 1, entity.getLat(), entity.getLng(), (short) 1000);
short speed = 1000;
if (device != null) {
SiteMemory siteMemory = GlobalMemory.getSiteMemory(device.getOrgId(), device.getSiteId());
if (siteMemory != null) {
DeviceRunParam deviceRunParam = siteMemory.getDeviceRunParam(device.getSerialNumber());
if (deviceRunParam != null && deviceRunParam.getRunSpeed() != null) {
speed = deviceRunParam.getRunSpeed().shortValue();
}
}
}
sendPathCommand((byte) 0x01, (short) 1, entity.getLat(), entity.getLng(), speed);
currentPoint = entity;
}
}

View File

@@ -1,14 +1,14 @@
package com.maibu.core.business.dto;
import java.time.LocalDateTime;
import org.springframework.format.annotation.DateTimeFormat;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.time.LocalDateTime;
import com.fasterxml.jackson.annotation.JsonFormat;
import org.springframework.format.annotation.DateTimeFormat;
import java.time.LocalDateTime;
@Data
@ApiModel("告警查询参数")
@@ -46,7 +46,7 @@ public class AlarmQueryDTO {
private String keyword;
@ApiModelProperty("设备ID")
private Long deviceId;
private String deviceId;
@ApiModelProperty("场站ID")
private Long siteId;

View File

@@ -31,6 +31,14 @@ public class SysSite extends BaseDO {
private String remark;
private Integer status;
private Integer dingTalkPush; // 钉钉推送 0-关闭 1-开启
private Integer emailPush;// 邮件推送 0-关闭 1-开启
private Integer alertPush;// 告警弹窗推送 0-关闭 1-开启
private String dingTalkSecret; // 钉钉推送密钥
private String dingTalkToken; // 钉钉推送token
}

View File

@@ -0,0 +1,21 @@
package com.maibu.core.enums;
import lombok.AllArgsConstructor;
import lombok.Getter;
@Getter
@AllArgsConstructor
public enum ErrorLevel {
INFO("INFO", "信息"),
WARNING("WARNING", "警告"),
ERROR("ERROR", "错误");
/** 错误来源值(存储在数据库中) */
private final String value;
/** 错误来源名称(用于前端显示) */
private final String name;
}

View File

@@ -0,0 +1,24 @@
package com.maibu.core.enums;
import lombok.AllArgsConstructor;
import lombok.Getter;
@Getter
@AllArgsConstructor
public enum ErrorSource {
/** 无人机 */
UAV("UAV", "无人机"),
/** 割草机 */
MOWER("MOWER", "割草机"),
/** 其他 */
OTHERS("OTHERS", "其他");
/** 错误来源值(存储在数据库中) */
private final String value;
/** 错误来源名称(用于前端显示) */
private final String name;
}

View File

@@ -1,11 +1,15 @@
package com.maibu.influxdb;
import java.time.Instant;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import org.springframework.util.CollectionUtils;
import com.influxdb.query.FluxRecord;
import com.influxdb.query.FluxTable;
import com.maibu.influxdb.inter.InfluxField;
import com.maibu.influxdb.inter.InfluxMeasurement;
import com.maibu.influxdb.inter.InfluxTag;
@@ -152,4 +156,101 @@ public class MowerRealTimeData {
return data;
}
// 适用于flux默认行存储结构,按device分组合并成一条实体
public static Map<String, List<MowerRealTimeData>> fluxTableMergeToEntity(List<FluxTable> tables) {
Map<String, MowerRealTimeData> tempMap = new HashMap<>();
for (FluxTable table : tables) {
for (FluxRecord record : table.getRecords()) {
String deviceId = (String) record.getValueByKey("deviceId");
Instant time = record.getTime();
String fieldName = (String) record.getValueByKey("_field");
String fieldVal = (String) record.getValueByKey("_value");
// 唯一key:设备+时间
String key = deviceId + "_" + time.toEpochMilli();
MowerRealTimeData data = tempMap.getOrDefault(key, new MowerRealTimeData());
data.setTime(time);
data.setDeviceId(deviceId);
// 根据_field填充对应属性
switch (fieldName) {
case "voltage":
data.setVoltage(fieldVal);
break;
case "leftTargetSpeed":
data.setLeftTargetSpeed(fieldVal);
break;
case "rightTargetSpeed":
data.setRightTargetSpeed(fieldVal);
break;
case "leftMeasureSpeed":
data.setLeftMeasureSpeed(fieldVal);
break;
case "rightMeasureSpeed":
data.setRightMeasureSpeed(fieldVal);
break;
case "leftMotorTemp":
data.setLeftMotorTemp(fieldVal);
break;
case "rightMotorTemp":
data.setRightMotorTemp(fieldVal);
break;
case "leftCurrent":
data.setLeftCurrent(fieldVal);
break;
case "rightCurrent":
data.setRightCurrent(fieldVal);
break;
case "chipTemp":
data.setChipTemp(fieldVal);
break;
case "yaw":
data.setYaw(fieldVal);
break;
case "pitch":
data.setPitch(fieldVal);
break;
case "roll":
data.setRoll(fieldVal);
break;
case "satelliteCnt":
data.setSatelliteCnt(fieldVal);
break;
case "qual":
data.setQual(fieldVal);
break;
case "headingStatus":
data.setHeadingStatus(fieldVal);
break;
case "latitude":
data.setLatitude(fieldVal);
break;
case "longitude":
data.setLongitude(fieldVal);
break;
case "cuttingSpeed":
data.setCuttingSpeed(fieldVal);
break;
case "controlMode":
data.setControlMode(fieldVal);
break;
case "battery":
data.setBattery(fieldVal);
break;
case "workingArea":
data.setWorkingArea(fieldVal);
break;
case "obstacleSign":
data.setObstacleSign(fieldVal);
break;
}
tempMap.put(key, data);
}
}
// 转List返回
return tempMap.values().stream()
.collect(Collectors.groupingBy(MowerRealTimeData::getDeviceId));
}
}

View File

@@ -0,0 +1,12 @@
package com.maibu.mapper;
import org.springframework.stereotype.Repository;
import com.maibu.core.business.DeviceRunParam;
import com.maibu.mybatis.mapper.BaseMapperX;
@Repository
public interface DeviceRunParamMapper extends BaseMapperX<DeviceRunParam> {
}

View File

@@ -1,8 +1,8 @@
package com.maibu.memory;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;
@@ -13,8 +13,11 @@ import org.springframework.util.CollectionUtils;
import com.maibu.core.business.Device;
import com.maibu.core.business.DevicePlan;
import com.maibu.core.business.DevicePlanTask;
import com.maibu.core.business.DeviceRunParam;
import com.maibu.core.business.ErrorIdentificationStandard;
import com.maibu.core.business.IoTCommonDevice;
import com.maibu.core.domain.entity.SysSite;
import com.maibu.core.enums.ErrorSource;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
@@ -24,19 +27,23 @@ import lombok.extern.slf4j.Slf4j;
@Slf4j
public class SiteMemory {
public List<ErrorIdentificationStandard> standard = null;
public Map<ErrorSource, List<ErrorIdentificationStandard>> standards = null;
public Long siteId;
public SysSite sysSite;
public static final ConcurrentHashMap<String, DeviceRunParam> deviceRunParamMap = new ConcurrentHashMap<>();
private static final ConcurrentHashMap<String, Device> deviceMap = new ConcurrentHashMap<>();
private static final ConcurrentHashMap<String, IoTCommonDevice> commonDeviceMap = new ConcurrentHashMap<>();
//key deviceId
// key deviceId
public static ConcurrentHashMap<String, List<DevicePlan>> devicePlanMap = new ConcurrentHashMap<>();
//key deviceId prepare
// key deviceId prepare
public static ConcurrentHashMap<String, List<DevicePlanTask>> devicePlanTaskPrepareMap = new ConcurrentHashMap<>();
//key deviceId execute
// key deviceId execute
public static ConcurrentHashMap<String, DevicePlanTask> devicePlanTaskExecuteMap = new ConcurrentHashMap<>();
public static void saveDevice(Device device) {
@@ -49,6 +56,23 @@ public class SiteMemory {
}
}
public void saveDeviceRunParam(DeviceRunParam deviceRunParam) {
deviceRunParamMap.put(deviceRunParam.getDeviceId(), deviceRunParam);
}
public DeviceRunParam getDeviceRunParam(String deviceId) {
if (!StringUtils.isEmpty(deviceId)) {
return deviceRunParamMap.get(deviceId);
}
return null;
}
public void removeDeviceRunParam(String deviceId) {
if (!StringUtils.isEmpty(deviceId)) {
deviceRunParamMap.remove(deviceId);
}
}
public void addDevicePlan(DevicePlan devicePlan) {
if (devicePlan != null && !StringUtils.isEmpty(devicePlan.getDeviceId())) {
String deviceId = devicePlan.getDeviceId();
@@ -65,7 +89,6 @@ public class SiteMemory {
}
}
public void removeDevicePlan(DevicePlan devicePlan) {
if (devicePlan != null && !StringUtils.isEmpty(devicePlan.getDeviceId())) {
String deviceId = devicePlan.getDeviceId();
@@ -98,7 +121,6 @@ public class SiteMemory {
}
}
public void addDevicePlanExecute(DevicePlanTask devicePlanTask) {
if (devicePlanTask != null && !StringUtils.isEmpty(devicePlanTask.getDeviceId())) {
String deviceId = devicePlanTask.getDeviceId();
@@ -120,12 +142,9 @@ public class SiteMemory {
public DevicePlanTask getDeviceExecuteTask(String deviceId) {
if (!StringUtils.isEmpty(deviceId)) {
return devicePlanTaskExecuteMap.get(deviceId);
return devicePlanTaskExecuteMap.get(deviceId);
}
return null;
}
}

View File

@@ -7,4 +7,9 @@ public class MqttTopic {
public static final String DEVICE_TASK_STATUS_TOPIC = "task/%s/status"; // 任务状态 完成、取消、暂停、继续
public static final String DEVICE_TASK_ARRIVE_TOPIC = "task/%s/arrive"; // 任务到达
public static final String DEVICE_ERROR_PUSH_TOPIC = "device/%s/error"; // 设备错误推送
}

View File

@@ -1,6 +1,17 @@
package com.maibu.controller;
import com.github.pagehelper.PageHelper;
import java.time.LocalDate;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import com.maibu.core.business.DevicePlan;
import com.maibu.core.controller.BaseController;
import com.maibu.core.domain.AjaxResult;
@@ -13,12 +24,6 @@ import com.maibu.memory.GlobalMemory;
import com.maibu.memory.SiteMemory;
import com.maibu.service.DeviceTaskService;
import com.maibu.utils.SecurityUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.web.bind.annotation.*;
import java.time.LocalDate;
@RestController
@RequestMapping("/iot/deviceTask")

View File

@@ -1,5 +1,6 @@
package com.maibu.dto;
import com.maibu.core.business.alarm_center.AlarmMessage;
import com.maibu.core.enums.RespondCode;
import lombok.Data;
@@ -8,7 +9,7 @@ import java.util.List;
@Data
public class DeviceErrorPushDTO {
private List<DeviceErrorPushDetail> details;
private List<AlarmMessage> details;
private long time;

View File

@@ -7,6 +7,8 @@ public class DeviceErrorPushDetail {
private String errorName;
private String errorCode;
private String description;
private String range;

View File

@@ -18,11 +18,13 @@ import org.springframework.util.CollectionUtils;
import com.maibu.constant.FastBeeConstant;
import com.maibu.core.business.DevicePlan;
import com.maibu.core.business.DevicePlanTask;
import com.maibu.core.business.DeviceRunParam;
import com.maibu.core.domain.entity.SysSite;
import com.maibu.core.enums.DeviceTaskStaus;
import com.maibu.influxdb.util.InfluxDBUtil;
import com.maibu.mapper.DevicePlanMapper;
import com.maibu.mapper.DevicePlanTaskMapper;
import com.maibu.mapper.DeviceRunParamMapper;
import com.maibu.mapper.SysSiteMapper;
import com.maibu.memory.GlobalMemory;
import com.maibu.memory.SiteMemory;
@@ -59,6 +61,9 @@ public class InitThread implements ApplicationRunner {
@Autowired
private SysSiteMapper sysSiteMapper;
@Autowired
private DeviceRunParamMapper deviceRunParamMapper;
@Value("${influxdb.url}")
private String influxDBUrl;
@@ -127,9 +132,6 @@ public class InitThread implements ApplicationRunner {
* 恢复内存
*/
public void recoverMemory() {
// todo 启动时清除当前登录记录
// System.out.println("开始清除登录信息");
// sysUserClientMapper.clearDeviceName();
List<SysSite> siteList = sysSiteMapper.selectList();
if (!CollectionUtils.isEmpty(siteList)) {
siteList.forEach(x -> {
@@ -138,10 +140,23 @@ public class InitThread implements ApplicationRunner {
SiteMemory siteMemory = GlobalMemory.getSiteMemory(orgId, siteId);
if (siteMemory == null) {
siteMemory = new SiteMemory();
siteMemory.setSiteId(siteId);
siteMemory.setSysSite(x);
GlobalMemory.addSiteMemory(orgId, siteId, siteMemory);
}
});
}
List<DeviceRunParam> deviceRunParamList = deviceRunParamMapper.selectList();
if (!CollectionUtils.isEmpty(deviceRunParamList)) {
deviceRunParamList.forEach(x -> {
Long orgId = x.getOrgId();
Long siteId = x.getId();
SiteMemory siteMemory = GlobalMemory.getSiteMemory(orgId, siteId);
if (siteMemory != null) {
siteMemory.saveDeviceRunParam(x);
}
});
}
// 未执行完的重复计划
LambdaQueryWrapperX<DevicePlan> query = new LambdaQueryWrapperX<>();
List<String> list = Arrays.asList(DeviceTaskStaus.NEW.getCode(), DeviceTaskStaus.EXECUTING.getCode(),

View File

@@ -289,6 +289,7 @@ public class DeviceConnectHandler extends SimpleChannelInboundHandler<String> {
NettyDevice slaveDevice = sessionManager.getDevice(data);
if (slaveDevice != null) {
slaveDevice.setOnlineStatus(1);
slaveDevice.setDevice(device);
}
// 推送json 找到设备绑定的主机进行推送
List<NettyDevice> controlMasters = sessionManager.getAllSlaveControl(device.getSerialNumber());

View File

@@ -0,0 +1,158 @@
package com.maibu.service;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.time.LocalDateTime;
import java.util.List;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import org.apache.commons.codec.binary.Base64;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import com.dingtalk.api.DefaultDingTalkClient;
import com.dingtalk.api.DingTalkClient;
import com.dingtalk.api.request.OapiRobotSendRequest;
import com.dingtalk.api.response.OapiRobotSendResponse;
import com.maibu.core.business.alarm_center.Alarm;
import com.maibu.core.business.alarm_center.AlarmMessage;
import com.maibu.core.business.device.NettyDevice;
import com.maibu.dto.DeviceErrorPushDTO;
import com.maibu.dto.DeviceErrorPushDetail;
import com.maibu.manager.DeviceSessionManager;
import com.maibu.memory.GlobalMemory;
import com.maibu.memory.SiteMemory;
import com.maibu.service.impl.AlarmServiceImpl;
import com.maibu.utils.DingTalkTemplate;
import com.maibu.utils.SecurityUtils;
import com.taobao.api.ApiException;
import lombok.extern.slf4j.Slf4j;
@Service
@Slf4j
public class AlertPushService {
@Autowired
private DeviceSessionManager sessionManager;
@Autowired
private AlarmServiceImpl alarmService;
public void messagePushHandler(String deviceId, List<DeviceErrorPushDTO> dtos) {
NettyDevice nettyDevice = sessionManager.getDevice(deviceId);
if (nettyDevice != null && nettyDevice.getDevice() != null) {
Long siteId = nettyDevice.getDevice().getSiteId();
Long orgId = nettyDevice.getDevice().getOrgId();
SiteMemory siteMemory = GlobalMemory.getSiteMemory(orgId, siteId);
if (siteMemory != null) {
Integer dingTalkPush = siteMemory.getSysSite().getDingTalkPush();
Integer emailPush = siteMemory.getSysSite().getEmailPush();
Integer alertPush = siteMemory.getSysSite().getAlertPush();
String secret = siteMemory.getSysSite().getDingTalkSecret();
String token = siteMemory.getSysSite().getDingTalkToken();
dtos.forEach(dto -> {
if (!CollectionUtils.isEmpty(dto.getDetails())) {
dto.getDetails().forEach(detail -> {
if (dingTalkPush == 1) {
pushDingTalkMessage(secret, token, DingTalkTemplate.buildText(detail));
}
if (emailPush == 1) {
pushEmailMessage(null, null);
}
});
if (alertPush == 1) {
alarmService.pushAlertMes(dto.getDetails());
}
}
});
}
}
}
public void pushDingTalkMessage(String secret, String token, String alertMessage) {
try {
Long timestamp = System.currentTimeMillis();
String stringToSign = timestamp + "\n" + secret;
Mac mac = Mac.getInstance("HmacSHA256");
mac.init(new SecretKeySpec(secret.getBytes("UTF-8"), "HmacSHA256"));
byte[] signData = mac.doFinal(stringToSign.getBytes("UTF-8"));
String sign = URLEncoder.encode(new String(Base64.encodeBase64(signData)), "UTF-8");
// sign字段和timestamp字段必须拼接到请求URL上,否则会出现 310000 的错误信息
DingTalkClient client = new DefaultDingTalkClient(
"https://oapi.dingtalk.com/robot/send?sign=" + sign + "&timestamp=" + timestamp);
OapiRobotSendRequest req = new OapiRobotSendRequest();
// 定义文本内容
OapiRobotSendRequest.Text text = new OapiRobotSendRequest.Text();
text.setContent(alertMessage);
// 定义 @ 对象
// OapiRobotSendRequest.At at = new OapiRobotSendRequest.At();
// at.setAtUserIds(Arrays.asList(USER_ID));
// 设置消息类型
req.setMsgtype("text");
req.setText(text);
// req.setAt(at);
client.execute(req, token);
} catch (Exception e) {
e.printStackTrace();
log.error("发送钉钉消息失败:{}", e.getMessage());
}
}
public void pushEmailMessage(String deviceId, String errorMessage) {
// Implement the logic to push error messages to the appropriate channels
// This could involve sending notifications, logging errors, etc.
System.out.println("Error for device " + deviceId + ": " + errorMessage);
}
public static void main(String[] args) {
try {
Long timestamp = System.currentTimeMillis();
System.out.println(timestamp);
String secret = "SEC6e538cab506df2efda5d327dfe582f8fd12ac55b77664d662031e90d2a3a3887";
String stringToSign = timestamp + "\n" + secret;
Mac mac = Mac.getInstance("HmacSHA256");
mac.init(new SecretKeySpec(secret.getBytes("UTF-8"), "HmacSHA256"));
byte[] signData = mac.doFinal(stringToSign.getBytes("UTF-8"));
String sign = URLEncoder.encode(new String(Base64.encodeBase64(signData)), "UTF-8");
System.out.println(sign);
// sign字段和timestamp字段必须拼接到请求URL上,否则会出现 310000 的错误信息
DingTalkClient client = new DefaultDingTalkClient(
"https://oapi.dingtalk.com/robot/send?sign=" + sign + "&timestamp=" + timestamp);
OapiRobotSendRequest req = new OapiRobotSendRequest();
/**
* 发送文本消息
*/
// 定义文本内容
OapiRobotSendRequest.Text text = new OapiRobotSendRequest.Text();
text.setContent("昀姐牛逼");
// 定义 @ 对象
OapiRobotSendRequest.At at = new OapiRobotSendRequest.At();
// at.setAtUserIds(Arrays.asList(USER_ID));
// 设置消息类型
req.setMsgtype("text");
req.setText(text);
req.setAt(at);
OapiRobotSendResponse rsp = client.execute(req,
"8bfdf609c7edeff5f31c6a243088d2a4f6672221afc86c008ad8622156a58407");
System.out.println(rsp.getBody());
} catch (ApiException e) {
e.printStackTrace();
} catch (UnsupportedEncodingException e) {
throw new RuntimeException(e);
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException(e);
} catch (InvalidKeyException e) {
throw new RuntimeException(e);
}
}
}

View File

@@ -2,9 +2,6 @@ package com.maibu.service;
import org.springframework.stereotype.Service;
import java.util.LinkedList;
import java.util.Queue;
@Service
public class DevicePathService {

View File

@@ -1,32 +1,45 @@
package com.maibu.service;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.maibu.core.business.*;
import com.maibu.core.business.device.NettyDevice;
import com.maibu.core.domain.entity.SysSite;
import com.maibu.core.domain.model.LoginUser;
import com.maibu.core.enums.DeviceTaskStaus;
import com.maibu.dto.*;
import com.maibu.manager.DeviceSessionManager;
import com.maibu.mapper.*;
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 java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Objects;
import java.util.Random;
import java.util.stream.Collectors;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.maibu.core.business.Device;
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.domain.entity.SysSite;
import com.maibu.core.domain.model.LoginUser;
import com.maibu.core.enums.DeviceTaskStaus;
import com.maibu.dto.DevicePlanStatisticsDTO;
import com.maibu.dto.DevicePlanTaskStatisticsDTO;
import com.maibu.dto.DeviceTaskCommandDTO;
import com.maibu.dto.DeviceTaskQueryDTO;
import com.maibu.dto.DeviceWorkStatisticsDTO;
import com.maibu.manager.DeviceSessionManager;
import com.maibu.mapper.DeviceMapper;
import com.maibu.mapper.DevicePlanMapper;
import com.maibu.mapper.DevicePlanTaskMapper;
import com.maibu.mapper.SysSiteMapper;
import com.maibu.mapper.WorkRecordMapper;
import com.maibu.memory.GlobalMemory;
import com.maibu.memory.SiteMemory;
import lombok.extern.slf4j.Slf4j;
@Service
@Slf4j
public class DeviceTaskService {

View File

@@ -1,6 +1,5 @@
package com.maibu.service;
import cn.hutool.core.io.IoUtil;
import com.alibaba.fastjson2.JSON;
import com.maibu.common.CommandConstant;
@@ -8,21 +7,29 @@ import com.maibu.common.NettyCacheKey;
import com.maibu.core.business.DeviceRunningStatusHistory;
import com.maibu.core.business.DeviceStatusRecordDTO;
import com.maibu.core.enums.CompareEnum;
import com.maibu.core.enums.ErrorSource;
import com.maibu.core.enums.RespondCode;
import com.maibu.core.redis.RedisCache;
import com.maibu.dto.DeviceErrorPushDTO;
import com.maibu.dto.DeviceErrorPushDetail;
import com.maibu.core.business.device.NettyDevice;
import com.maibu.core.business.inter.WebsocketMesDispather;
import com.maibu.core.business.ErrorIdentificationStandard;
import com.maibu.core.business.alarm_center.AlarmMessage;
import com.maibu.manager.DeviceSessionManager;
import com.maibu.mapper.ErrorIdentificationStandardMapper;
import com.maibu.memory.GlobalMemory;
import com.maibu.memory.SiteMemory;
import com.maibu.mqtt.MqttTopic;
import com.maibu.utils.CommandUtils;
import com.maibu.utils.CompareUtils;
import com.maibu.utils.json.JsonUtils;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.eclipse.paho.client.mqttv3.MqttException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
@@ -31,10 +38,12 @@ import org.springframework.util.CollectionUtils;
import java.io.IOException;
import java.lang.reflect.Field;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
@@ -58,6 +67,11 @@ public class DeviceThreadService {
@Autowired
private ErrorIdentificationStandardMapper standardMapper;
@Autowired
private WebsocketMesDispather websocketMesDispather;
@Autowired
private AlertPushService alertPushService;
public void deviceErrorMonitor() throws InterruptedException, IOException {
initStandard();
@@ -68,12 +82,15 @@ public class DeviceThreadService {
String key = NettyCacheKey.deviceRunningStatusKey;
Collection<String> keys = redisCache.getListKeyByPrefix(key);
if (!CollectionUtils.isEmpty(keys)) {
List<DeviceErrorPushDTO> pushList = new ArrayList<>();
keys.forEach(k -> {
DeviceStatusRecordDTO recordDTO = redisCache.getCacheObject(k);
if (recordDTO != null && !CollectionUtils.isEmpty(recordDTO.getHistories())) {
recordDTO.getHistories().sort(Comparator.comparing(DeviceRunningStatusHistory::getCreateTime).reversed());
recordDTO.getHistories()
.sort(Comparator.comparing(DeviceRunningStatusHistory::getCreateTime).reversed());
DeviceRunningStatusHistory history = recordDTO.getHistories().get(0);
List<DeviceErrorPushDetail> compared = compareErrorStandard(history, siteMemory.standard);
List<AlarmMessage> compared = compareErrorStandard(history,
siteMemory.standards.get(ErrorSource.MOWER));
String[] parts = k.split(":");
String deviceId = parts[1];
@@ -83,10 +100,18 @@ public class DeviceThreadService {
pushDTO.setTime(System.currentTimeMillis());
pushDTO.setDetails(compared);
pushDTO.setEvent(RespondCode.device_error_push);
//todo push 推送到前端
pushErrorMessage(deviceId, JSON.toJSONString(pushDTO));
pushList.add(pushDTO);
}
});
// 按实际deviceId分组,推送错误信息
Map<String, List<DeviceErrorPushDTO>> pushMap = pushList.stream()
.collect(java.util.stream.Collectors.groupingBy(DeviceErrorPushDTO::getDeviceId));
pushMap.forEach((deviceId, dtos) -> {
// pushErrorMessage(deviceId, JSON.toJSONString(dtos));
// todo 判断错误级别,是否需要推送邮件 或者钉钉。
// 找到这个设备的场站 添加场站是否开启关闭 钉钉或者邮件推送,推送邮件 添加人员是否订阅邮件,钉钉是加入钉钉群
alertPushService.messagePushHandler(deviceId, dtos);
});
}
} catch (Exception e) {
log.error("执行监测错误线程错误:{}", e.getMessage());
@@ -95,35 +120,56 @@ public class DeviceThreadService {
}
public void initStandard() throws IOException {
if (siteMemory.standard == null) {
List<ErrorIdentificationStandard> standards = standardMapper.selectList();
if (CollectionUtils.isEmpty(standards)) {
if (siteMemory.standards == null) {
List<ErrorIdentificationStandard> list = standardMapper.selectList();
if (CollectionUtils.isEmpty(list)) {
// 读取resource目录下的device-config.json文件
Resource resource = resourceLoader.getResource("classpath:errorStandard.json");
// 使用fastjson2转换为DeviceConfig对象
String jsonContent = IoUtil.readUtf8(resource.getInputStream());
siteMemory.standard = JSON.parseArray(jsonContent, ErrorIdentificationStandard.class);
List<ErrorIdentificationStandard> newStandards = JSON.parseArray(jsonContent,
ErrorIdentificationStandard.class);
if (!CollectionUtils.isEmpty(newStandards)) {
standardMapper.insertBatch(newStandards);
siteMemory.standards = newStandards.stream()
.collect(java.util.stream.Collectors
.groupingBy(ErrorIdentificationStandard::getErrorSource));
}
} else {
siteMemory.standard = standards;
siteMemory.standards = list.stream()
.collect(java.util.stream.Collectors.groupingBy(ErrorIdentificationStandard::getErrorSource));
}
}
}
public void pushErrorMessage(String deviceId, String dto) {
NettyDevice device = sessionManager.getDevice(deviceId);
if (device != null) {
ByteBuf buf = Unpooled.buffer();
CommandUtils.buildCommand(buf, dto, CommandConstant.interaction);
if (device.getChannel() != null && device.getChannel().isActive()) {
device.getChannel().writeAndFlush(buf);
// NettyDevice device = sessionManager.getDevice(deviceId);
// if (device != null) {
// ByteBuf buf = Unpooled.buffer();
// CommandUtils.buildCommand(buf, dto, CommandConstant.interaction);
// if (device.getChannel() != null && device.getChannel().isActive()) {
// device.getChannel().writeAndFlush(buf);
// }
// }
try {
GlobalMemory.mqttClientUtil.publish(String.format(MqttTopic.DEVICE_ERROR_PUSH_TOPIC, deviceId), dto);
List<NettyDevice> controlMasters = sessionManager.getAllSlaveControl(deviceId);
if (!CollectionUtils.isEmpty(controlMasters)) {
controlMasters.forEach(x -> {
websocketMesDispather.dispather(x.getConnectorId(), dto);
log.info("推送错误信息 device:{},content:{}", deviceId, dto);
});
}
} catch (MqttException e) {
log.error("推送错误信息失败 device:{}error:{}", deviceId, e.getMessage());
}
}
public List<DeviceErrorPushDetail> compareErrorStandard(DeviceRunningStatusHistory history, List<ErrorIdentificationStandard> standards) {
if (history == null || CollectionUtils.isEmpty(standards)) return null;
List<DeviceErrorPushDetail> list = new ArrayList<>();
public List<AlarmMessage> compareErrorStandard(DeviceRunningStatusHistory history,
List<ErrorIdentificationStandard> standards) {
if (history == null || CollectionUtils.isEmpty(standards))
return null;
List<AlarmMessage> list = new ArrayList<>();
standards.forEach(standard -> {
String fieldName = standard.getField();
String compareValues = standard.getCompareValues();
@@ -132,19 +178,24 @@ public class DeviceThreadService {
if (!StringUtils.isEmpty(compareValues) && !StringUtils.isEmpty(targetValue)) {
boolean result = CompareUtils.compare(compareType, compareValues, targetValue);
if (!result) {
DeviceErrorPushDetail detail = new DeviceErrorPushDetail();
detail.setErrorName(standard.getErrorName());
detail.setDescription(standard.getErrorDescription());
detail.setValue(targetValue);
detail.setRange(compareValues);
list.add(detail);
AlarmMessage alarm = new AlarmMessage();
alarm.setContent(standard.getErrorDescription());
alarm.setDeviceSn(history.getDeviceId());
alarm.setDeviceName(history.getDeviceId());
alarm.setLevel(standard.getErrorLevel());
alarm.setLocation(history.getLatitude() + "," + history.getLongitude());
alarm.setName(standard.getErrorName());
alarm.setNo(standard.getErrorCode());
alarm.setSuggestion(standard.getSuggestion());
alarm.setStatus("未处理");
alarm.setTime(LocalDateTime.now());
list.add(alarm);
}
}
});
return list;
}
private static String knownClassFieldFinding(String fieldName, DeviceRunningStatusHistory history) {
try {
// 1. 获取类的Class对象

View File

@@ -0,0 +1,30 @@
package com.maibu.utils;
import com.maibu.core.business.alarm_center.AlarmMessage;
public class DingTalkTemplate {
public static String buildText(AlarmMessage alarm) {
return String.format(
"【系统告警通知】\n\n" +
"⚠️ 告警等级:%s\n\n" +
"告警名称:%s\n\n" +
"告警时间:%s\n\n" +
"设备名称:%s\n\n" +
"设备编号:%s\n\n" +
"告警内容:\n%s\n\n" +
"发生位置:\n%s\n\n" +
"处理建议:\n%s\n\n" +
"状态:%s",
alarm.getLevel(),
alarm.getName(),
alarm.getTime(),
alarm.getDeviceName(),
alarm.getDeviceSn(),
alarm.getContent(),
alarm.getLocation(),
alarm.getSuggestion(),
alarm.getStatus());
}
}

View File

@@ -1,16 +1,24 @@
[
{
"field": "voltage",
"errorCode": "1001",
"compareValues": 58,
"compareType": "GT",
"errorName" : "电压过高",
"errorDescription" : "当前电池电压过高,超过正常范围"
"errorName": "电压过高",
"errorDescription": "当前电池电压过高,超过正常范围",
"errorSource": "MOWER",
"errorLevel": "WARNING",
"suggestion": "请检查电池连接或更换电池"
},
{
"field": "battery",
"errorCode": "1002",
"compareValues": 20,
"compareType": "LT",
"errorName" : "电量过低",
"errorDescription" : "当前电池电量过低,请及时充电"
"errorName": "电量过低",
"errorDescription": "当前电池电量过低,请及时充电",
"errorSource": "MOWER",
"errorLevel": "WARNING",
"suggestion": "请检查电池电量,及时充电"
}
]

View File

@@ -1 +1,125 @@
package com.maibu.controller;
package com.maibu.controller;
import java.util.List;
import java.util.Map;
import javax.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.maibu.annotation.Log;
import com.maibu.core.business.alarm_center.Alarm;
import com.maibu.core.business.dto.AlarmHandleDTO;
import com.maibu.core.business.dto.AlarmQueryDTO;
import com.maibu.core.controller.BaseController;
import com.maibu.core.domain.AjaxResult;
import com.maibu.core.page.TableDataInfo;
import com.maibu.enums.BusinessType;
import com.maibu.service.IAlarmService;
import com.maibu.utils.poi.ExcelUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
@Api("告警中心接口")
@RestController
@Slf4j
@RequestMapping("/iot/alarm")
public class AlarmController extends BaseController{
@Autowired
private IAlarmService alarmService;
// @PreAuthorize("@ss.hasPermi('iot:alarm:list')")
@GetMapping("/list")
@ApiOperation("告警分页列表")
public TableDataInfo list(AlarmQueryDTO queryDTO) {
// startPage();
// return alarmService.selectAlarmPage(queryDTO);
return alarmService.selectAlarmPage(queryDTO);
}
// @PreAuthorize("@ss.hasPermi('iot:alarm:query')")
@GetMapping("/{id}")
@ApiOperation("获取告警详情")
public AjaxResult getInfo(@PathVariable Long id) {
return AjaxResult.success(alarmService.selectAlarmById(id));
}
// @PreAuthorize("@ss.hasPermi('iot:alarm:add')")
@Log(title = "告警", businessType = BusinessType.INSERT)
@PostMapping
@ApiOperation("新增告警")
public AjaxResult add(@RequestBody Alarm alarm) {
return toAjax(alarmService.insertAlarm(alarm));
}
// @PreAuthorize("@ss.hasPermi('iot:alarm:edit')")
@Log(title = "告警", businessType = BusinessType.UPDATE)
@PutMapping
@ApiOperation("修改告警")
public AjaxResult edit(@RequestBody Alarm alarm) {
return toAjax(alarmService.updateAlarm(alarm));
}
//@PreAuthorize("@ss.hasPermi('iot:alarm:handle')")
@Log(title = "告警处理", businessType = BusinessType.UPDATE)
@PutMapping("/handle")
@ApiOperation("处理告警")
public AjaxResult handle(@RequestBody AlarmHandleDTO handleDTO) {
return toAjax(alarmService.handleAlarm(handleDTO));
}
// @PreAuthorize("@ss.hasPermi('iot:alarm:remove')")
@Log(title = "告警", businessType = BusinessType.DELETE)
@DeleteMapping("/{ids}")
@ApiOperation("删除告警")
public AjaxResult remove(@PathVariable Long[] ids) {
return toAjax(alarmService.deleteAlarmByIds(ids));
}
// @PreAuthorize("@ss.hasPermi('iot:alarm:statistics')")
// @GetMapping("/statistics")
// @ApiOperation("告警统计")
// public AjaxResult statistics() {
// Map<String, Object> statistics = alarmService.getAlarmStatistics();
// return AjaxResult.success(statistics);
// }
@GetMapping("/statistics")
@ApiOperation("告警统计")
public AjaxResult statistics(AlarmQueryDTO queryDTO) {
Map<String, Object> statistics = alarmService.getAlarmStatistics(queryDTO);
return AjaxResult.success(statistics);
}
// @PreAuthorize("@ss.hasPermi('iot:alarm:export')")
@Log(title = "告警", businessType = BusinessType.EXPORT)
@PostMapping("/export")
@ApiOperation("导出告警")
public void export(HttpServletResponse response, AlarmQueryDTO queryDTO) {
try {
List<Alarm> list = alarmService.selectAlarmList(queryDTO);
ExcelUtil<Alarm> util = new ExcelUtil<>(Alarm.class);
util.exportExcel(response, list, "告警数据");
} catch (Exception e) {
log.error("导出告警失败", e);
}
}
}

View File

@@ -0,0 +1,49 @@
package com.maibu.controller;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import com.maibu.core.business.DeviceRunParam;
import com.maibu.core.controller.BaseController;
import com.maibu.core.domain.AjaxResult;
import com.maibu.core.page.TableDataInfo;
import com.maibu.dto.DeviceRunParamQueryDTO;
import com.maibu.service.impl.DeviceRunParamService;
@RestController
@RequestMapping("/iot/deviceRunParam")
public class DeviceRunParamController extends BaseController {
@Autowired
private DeviceRunParamService service;
@PostMapping("/save")
public AjaxResult save(@RequestBody DeviceRunParam deviceRunParam) {
return AjaxResult.success(service.save(deviceRunParam));
}
@PostMapping("/list")
public TableDataInfo list(@RequestBody DeviceRunParamQueryDTO dto) {
startPage();
return getDataTable(service.list(dto));
}
@GetMapping("/selectByDeviceId")
public AjaxResult selectByDeviceId(@RequestParam String deviceId) {
return AjaxResult.success(service.selectByDeviceId(deviceId));
}
@PostMapping("/delete")
public AjaxResult delete(@RequestBody List<Long> ids) {
return AjaxResult.success(service.delete(ids));
}
}

View File

@@ -0,0 +1,43 @@
package com.maibu.controller;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.maibu.core.business.ErrorIdentificationStandard;
import com.maibu.core.controller.BaseController;
import com.maibu.core.domain.AjaxResult;
import com.maibu.core.page.TableDataInfo;
import com.maibu.dto.ErrorQueryDTO;
import com.maibu.service.impl.ErrorIdentificationService;
@RestController
@RequestMapping("/iot/errorIdentification")
public class ErrorIdentificationController extends BaseController {
@Autowired
private ErrorIdentificationService service;
@PostMapping("/save")
public AjaxResult save(@RequestBody ErrorIdentificationStandard error) {
return AjaxResult.success(service.save(error));
}
@PostMapping("/list")
public TableDataInfo list(@RequestBody ErrorQueryDTO dto) {
startPage();
return getDataTable(service.list(dto));
}
@PostMapping("/delete")
public AjaxResult delete(@RequestBody List<Long> ids) {
return AjaxResult.success(service.delete(ids));
}
}

View File

@@ -1,5 +1,20 @@
package com.maibu.controller;
import java.util.List;
import java.util.Map;
import javax.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.maibu.annotation.Log;
import com.maibu.core.business.IOTWorkOrder;
import com.maibu.core.business.dto.WorkOrderDispatchDTO;
@@ -10,16 +25,10 @@ import com.maibu.core.page.TableDataInfo;
import com.maibu.enums.BusinessType;
import com.maibu.service.IWorkOrderService;
import com.maibu.utils.poi.ExcelUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletResponse;
import java.util.List;
import java.util.Map;
@Api("工单任务接口")
@RestController

View File

@@ -1,20 +1,25 @@
package com.maibu.controller;
import java.io.InputStream;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RequestPart;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import com.maibu.core.business.WorkRecord;
import com.maibu.core.business.path.LatAndLngEntity;
import com.maibu.core.controller.BaseController;
import com.maibu.core.domain.R;
import com.maibu.service.impl.WorkRecordService;
import com.maibu.utils.MinioUtil;
import com.maibu.utils.json.JsonUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.http.MediaType;
import java.io.InputStream;
import java.util.List;
@RestController
@RequestMapping("/iot/workRecord")

View File

@@ -0,0 +1,11 @@
package com.maibu.dto;
import com.maibu.core.domain.BaseEntity;
import lombok.Data;
@Data
public class DeviceRunParamQueryDTO extends BaseEntity {
private Long siteId;
private String deviceId;
}

View File

@@ -0,0 +1,15 @@
package com.maibu.dto;
import com.maibu.core.domain.BaseEntity;
import com.maibu.core.enums.ErrorLevel;
import com.maibu.core.enums.ErrorSource;
import lombok.Data;
@Data
public class ErrorQueryDTO extends BaseEntity {
private String errorName;
private ErrorSource errorSource;
private String errorCode;
private ErrorLevel errorLevel;
}

View File

@@ -1 +1,11 @@
package com.maibu.mapper;
package com.maibu.mapper;
import org.apache.ibatis.annotations.Mapper;
import com.maibu.core.business.alarm_center.Alarm;
import com.maibu.mybatis.mapper.BaseMapperX;
@Mapper
public interface AlarmMapper extends BaseMapperX<Alarm> {
}

View File

@@ -5,20 +5,31 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.maibu.core.business.Device;
import com.maibu.core.business.alarm_center.Alarm;
import com.maibu.core.business.alarm_center.AlarmMessage;
import com.maibu.core.business.device.NettyDevice;
import com.maibu.core.business.dto.AlarmHandleDTO;
import com.maibu.core.business.dto.AlarmQueryDTO;
import com.maibu.core.domain.model.LoginUser;
import com.maibu.core.enums.ErrorSource;
import com.maibu.core.page.TableDataInfo;
import com.maibu.exception.ServiceException;
import com.maibu.mapper.AlarmMapper;
import com.maibu.mapper.DeviceMapper;
import com.maibu.memory.GlobalMemory;
import com.maibu.mqtt.MqttTopic;
import com.maibu.service.IAlarmService;
import com.maibu.utils.SecurityUtils;
import com.maibu.utils.StringUtils;
import com.maibu.utils.json.JsonUtils;
import lombok.extern.slf4j.Slf4j;
import org.eclipse.paho.client.mqttv3.MqttException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
@@ -26,9 +37,9 @@ import java.util.Map;
import java.util.stream.Collectors;
@Service
@Slf4j
public class AlarmServiceImpl extends ServiceImpl<AlarmMapper, Alarm> implements IAlarmService {
@Autowired
private DeviceMapper deviceMapper;
@@ -55,7 +66,6 @@ public class AlarmServiceImpl extends ServiceImpl<AlarmMapper, Alarm> implements
return baseMapper.selectList(wrapper);
}
@Override
public Map<String, Object> getAlarmStatistics(AlarmQueryDTO queryDTO) {
com.github.pagehelper.PageHelper.clearPage();
@@ -69,14 +79,14 @@ public class AlarmServiceImpl extends ServiceImpl<AlarmMapper, Alarm> implements
statistics.put("processing", alarms.stream().filter(a -> a.getHandleStatus() == 2).count());
statistics.put("closed", alarms.stream().filter(a -> a.getHandleStatus() == 3).count());
statistics.put("levelStats", alarms.stream().collect(Collectors.groupingBy(Alarm::getAlarmLevel, Collectors.counting())));
statistics.put("typeStats", alarms.stream().collect(Collectors.groupingBy(Alarm::getAlarmType, Collectors.counting())));
statistics.put("levelStats",
alarms.stream().collect(Collectors.groupingBy(Alarm::getAlarmLevel, Collectors.counting())));
statistics.put("typeStats",
alarms.stream().collect(Collectors.groupingBy(Alarm::getAlarmType, Collectors.counting())));
return statistics;
}
private void validateQueryParams(AlarmQueryDTO queryDTO) {
Long userId = SecurityUtils.getUserId();
if (SecurityUtils.isAdmin(userId)) {
@@ -93,10 +103,12 @@ public class AlarmServiceImpl extends ServiceImpl<AlarmMapper, Alarm> implements
}
private void validateSiteAccess(Long siteId) {
if (siteId == null) return;
if (siteId == null)
return;
Long userId = SecurityUtils.getUserId();
if (SecurityUtils.isAdmin(userId)) return;
if (SecurityUtils.isAdmin(userId))
return;
LoginUser loginUser = SecurityUtils.getLoginUser();
Long userSiteId = loginUser.getSiteId();
@@ -116,8 +128,7 @@ public class AlarmServiceImpl extends ServiceImpl<AlarmMapper, Alarm> implements
Long count = deviceMapper.selectCount(
new LambdaQueryWrapper<Device>()
.eq(Device::getSiteId, siteId)
.eq(Device::getOrgId, userOrgId)
);
.eq(Device::getOrgId, userOrgId));
if (count == 0) {
// 如果查不到设备,说明要么场站无设备,要么场站不属于该组织
// 这里为了安全,默认拦截。如果允许查空场站,需改为校验 SysSite 表
@@ -128,17 +139,18 @@ public class AlarmServiceImpl extends ServiceImpl<AlarmMapper, Alarm> implements
}
}
private void validateDeviceAccess(Long deviceId) {
if (deviceId == null) return;
private void validateDeviceAccess(String deviceId) {
if (deviceId == null)
return;
Long userId = SecurityUtils.getUserId();
if (SecurityUtils.isAdmin(userId)) return;
if (SecurityUtils.isAdmin(userId))
return;
Device device = deviceMapper.selectOne(
new LambdaQueryWrapper<Device>()
.eq(Device::getDeviceId, deviceId)
.select(Device::getOrgId, Device::getSiteId)
);
.select(Device::getOrgId, Device::getSiteId));
if (device == null) {
throw new ServiceException("设备不存在");
@@ -175,9 +187,11 @@ public class AlarmServiceImpl extends ServiceImpl<AlarmMapper, Alarm> implements
}
wrapper.exists(sql, queryDTO.getSiteId());
} else if (userSiteId != null) {
wrapper.exists("SELECT 1 FROM iot_device d WHERE d.device_id = iot_alarm.device_id AND d.site_id = {0}", userSiteId);
wrapper.exists("SELECT 1 FROM iot_device d WHERE d.device_id = iot_alarm.device_id AND d.site_id = {0}",
userSiteId);
} else if (userOrgId != null) {
wrapper.exists("SELECT 1 FROM iot_device d WHERE d.device_id = iot_alarm.device_id AND d.org_id = {0}", userOrgId);
wrapper.exists("SELECT 1 FROM iot_device d WHERE d.device_id = iot_alarm.device_id AND d.org_id = {0}",
userOrgId);
}
}
@@ -196,12 +210,12 @@ public class AlarmServiceImpl extends ServiceImpl<AlarmMapper, Alarm> implements
if (queryDTO.getHandleStatus() != null) {
wrapper.eq(Alarm::getHandleStatus, queryDTO.getHandleStatus());
}
// if (queryDTO.getStartTime() != null) {
// wrapper.ge(Alarm::getAlarmTime, queryDTO.getStartTime());
// }
// if (queryDTO.getEndTime() != null) {
// wrapper.le(Alarm::getAlarmTime, queryDTO.getEndTime());
// }
// if (queryDTO.getStartTime() != null) {
// wrapper.ge(Alarm::getAlarmTime, queryDTO.getStartTime());
// }
// if (queryDTO.getEndTime() != null) {
// wrapper.le(Alarm::getAlarmTime, queryDTO.getEndTime());
// }
if (queryDTO.getStartTime() != null) {
wrapper.ge(Alarm::getAlarmTime, queryDTO.getStartTime());
@@ -222,7 +236,8 @@ public class AlarmServiceImpl extends ServiceImpl<AlarmMapper, Alarm> implements
@Override
public Alarm selectAlarmById(Long id) {
Alarm alarm = baseMapper.selectById(id);
if (alarm == null) throw new ServiceException("告警不存在");
if (alarm == null)
throw new ServiceException("告警不存在");
Long userId = SecurityUtils.getUserId();
if (!SecurityUtils.isAdmin(userId) && alarm.getDeviceId() != null) {
@@ -258,7 +273,8 @@ public class AlarmServiceImpl extends ServiceImpl<AlarmMapper, Alarm> implements
@Override
public int handleAlarm(AlarmHandleDTO handleDTO) {
Alarm alarm = baseMapper.selectById(handleDTO.getAlarmId());
if (alarm == null) throw new ServiceException("告警不存在");
if (alarm == null)
throw new ServiceException("告警不存在");
Long userId = SecurityUtils.getUserId();
if (!SecurityUtils.isAdmin(userId) && alarm.getDeviceId() != null) {
@@ -307,7 +323,7 @@ public class AlarmServiceImpl extends ServiceImpl<AlarmMapper, Alarm> implements
@Override
public Map<String, Object> getAlarmStatistics() {
com.github.pagehelper.PageHelper.clearPage(); // 清除可能的分页参数
com.github.pagehelper.PageHelper.clearPage(); // 清除可能的分页参数
Long userId = SecurityUtils.getUserId();
LoginUser loginUser = SecurityUtils.getLoginUser();
Long userOrgId = loginUser.getOrgId();
@@ -316,9 +332,11 @@ public class AlarmServiceImpl extends ServiceImpl<AlarmMapper, Alarm> implements
LambdaQueryWrapper<Alarm> wrapper = new LambdaQueryWrapper<>();
if (!SecurityUtils.isAdmin(userId)) {
if (userSiteId != null) {
wrapper.exists("SELECT 1 FROM iot_device d WHERE d.device_id = iot_alarm.device_id AND d.site_id = {0}", userSiteId);
wrapper.exists("SELECT 1 FROM iot_device d WHERE d.device_id = iot_alarm.device_id AND d.site_id = {0}",
userSiteId);
} else if (userOrgId != null) {
wrapper.exists("SELECT 1 FROM iot_device d WHERE d.device_id = iot_alarm.device_id AND d.org_id = {0}", userOrgId);
wrapper.exists("SELECT 1 FROM iot_device d WHERE d.device_id = iot_alarm.device_id AND d.org_id = {0}",
userOrgId);
}
}
wrapper.ge(Alarm::getAlarmTime, LocalDateTime.now().minusDays(7));
@@ -330,9 +348,50 @@ public class AlarmServiceImpl extends ServiceImpl<AlarmMapper, Alarm> implements
statistics.put("processing", alarms.stream().filter(a -> a.getHandleStatus() == 2).count());
statistics.put("closed", alarms.stream().filter(a -> a.getHandleStatus() == 3).count());
statistics.put("levelStats", alarms.stream().collect(Collectors.groupingBy(Alarm::getAlarmLevel, Collectors.counting())));
statistics.put("typeStats", alarms.stream().collect(Collectors.groupingBy(Alarm::getAlarmType, Collectors.counting())));
statistics.put("levelStats",
alarms.stream().collect(Collectors.groupingBy(Alarm::getAlarmLevel, Collectors.counting())));
statistics.put("typeStats",
alarms.stream().collect(Collectors.groupingBy(Alarm::getAlarmType, Collectors.counting())));
return statistics;
}
public void pushAlertMes(List<AlarmMessage> alarmMessages) {
if (alarmMessages == null || alarmMessages.isEmpty()) {
return;
}
List<Alarm> list = new ArrayList<>();
for (AlarmMessage alarmMessage : alarmMessages) {
Alarm alarm = new Alarm();
alarm.setAlarmNo(alarmMessage.getNo());
alarm.setAlarmLevel(alarmMessage.getLevel());
alarm.setAlarmType(1);
alarm.setAlarmTitle(alarmMessage.getName());
alarm.setAlarmContent(alarmMessage.getContent());
alarm.setDeviceId(alarmMessage.getDeviceName());
alarm.setDeviceName(alarmMessage.getDeviceName());
alarm.setDeviceType(ErrorSource.MOWER);
alarm.setAlarmTime(LocalDateTime.now());
pushErrorMessage(alarmMessage.getDeviceName(), JsonUtils.toJsonString(alarm));
list.add(alarm);
}
baseMapper.insertBatch(list);
// todo 推送websocket?
}
public void pushErrorMessage(String deviceId, String dto) {
try {
GlobalMemory.mqttClientUtil.publish(String.format(MqttTopic.DEVICE_ERROR_PUSH_TOPIC, deviceId), dto);
// List<NettyDevice> controlMasters = sessionManager.getAllSlaveControl(deviceId);
// if (!CollectionUtils.isEmpty(controlMasters)) {
// controlMasters.forEach(x -> {
// websocketMesDispather.dispather(x.getConnectorId(), dto);
// log.info("推送错误信息 device:{},content:{}", deviceId, dto);
// });
// }
} catch (MqttException e) {
log.error("推送错误信息失败 device:{}error:{}", deviceId, e.getMessage());
}
}
}

View File

@@ -0,0 +1,67 @@
package com.maibu.service.impl;
import java.util.Collection;
import java.util.List;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.maibu.core.business.DeviceRunParam;
import com.maibu.dto.DeviceRunParamQueryDTO;
import com.maibu.mapper.DeviceRunParamMapper;
import com.maibu.memory.GlobalMemory;
import com.maibu.memory.SiteMemory;
@Service
public class DeviceRunParamService {
@Autowired
private DeviceRunParamMapper deviceRunParamMapper;
public boolean save(DeviceRunParam deviceRunParam) {
SiteMemory siteMemory = GlobalMemory.getSiteMemory(deviceRunParam.getOrgId(), deviceRunParam.getSiteId());
if (siteMemory != null) {
siteMemory.saveDeviceRunParam(deviceRunParam);
}
return deviceRunParamMapper.saveOrUpdate(deviceRunParam);
}
public List<DeviceRunParam> list(DeviceRunParamQueryDTO dto) {
LambdaQueryWrapper<DeviceRunParam> queryWrapper = new LambdaQueryWrapper<>();
if (dto != null) {
if (dto.getSiteId() != null) {
queryWrapper.eq(DeviceRunParam::getSiteId, dto.getSiteId());
}
if (StringUtils.isEmpty(dto.getDeviceId())) {
queryWrapper.eq(DeviceRunParam::getDeviceId, dto.getDeviceId());
}
}
return deviceRunParamMapper.selectList(queryWrapper);
}
public DeviceRunParam selectByDeviceId(String deviceId) {
LambdaQueryWrapper<DeviceRunParam> queryWrapper = new LambdaQueryWrapper<>();
if (!StringUtils.isEmpty(deviceId)) {
queryWrapper.eq(DeviceRunParam::getDeviceId, deviceId);
}
return deviceRunParamMapper.selectOne(queryWrapper);
}
public int delete(List<Long> ids) {
List<DeviceRunParam> deviceRunParams = deviceRunParamMapper.selectBatchIds(ids);
if (!CollectionUtils.isEmpty(deviceRunParams)) {
deviceRunParams.forEach(x -> {
SiteMemory siteMemory = GlobalMemory.getSiteMemory(x.getOrgId(), x.getSiteId());
if (siteMemory != null) {
siteMemory.removeDeviceRunParam(x.getDeviceId());
}
});
}
int i = deviceRunParamMapper.deleteBatchIds(ids);
return i;
}
}

View File

@@ -0,0 +1,48 @@
package com.maibu.service.impl;
import java.util.List;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.maibu.core.business.ErrorIdentificationStandard;
import com.maibu.dto.ErrorQueryDTO;
import com.maibu.mapper.ErrorIdentificationStandardMapper;
@Service
public class ErrorIdentificationService {
@Autowired
private ErrorIdentificationStandardMapper errorIdentificationStandardMapper;
public boolean save(ErrorIdentificationStandard errorIdentificationStandard) {
return errorIdentificationStandardMapper.saveOrUpdate(errorIdentificationStandard);
}
public List<ErrorIdentificationStandard> list(ErrorQueryDTO dto) {
LambdaQueryWrapper<ErrorIdentificationStandard> queryWrapper = new LambdaQueryWrapper<>();
if (dto != null) {
if (!StringUtils.isEmpty(dto.getErrorCode())) {
queryWrapper.eq(ErrorIdentificationStandard::getErrorCode, dto.getErrorCode());
}
if (!StringUtils.isEmpty(dto.getErrorName())) {
queryWrapper.like(ErrorIdentificationStandard::getErrorName, dto.getErrorName());
}
if (dto.getErrorLevel() != null) {
queryWrapper.eq(ErrorIdentificationStandard::getErrorLevel, dto.getErrorLevel());
}
if (dto.getErrorSource() != null) {
queryWrapper.eq(ErrorIdentificationStandard::getErrorSource, dto.getErrorSource());
}
}
return errorIdentificationStandardMapper.selectList(queryWrapper);
}
public int delete(List<Long> ids) {
int i = errorIdentificationStandardMapper.deleteBatchIds(ids);
return i;
}
}

View File

@@ -8,6 +8,7 @@ import com.maibu.core.business.IOTWorkOrder;
import com.maibu.core.business.dto.WorkOrderDispatchDTO;
import com.maibu.core.business.dto.WorkOrderQueryDTO;
import com.maibu.core.domain.model.LoginUser;
import com.maibu.core.enums.ErrorLevel;
import com.maibu.core.page.TableDataInfo;
import com.maibu.exception.ServiceException;
import com.maibu.mapper.DeviceMapper;
@@ -451,7 +452,7 @@ public class WorkOrderServiceImpl extends ServiceImpl<IotWorkOrderMapper, IOTWor
.filter(w -> w.getCreateTime().toLocalDate().equals(LocalDateTime.now().toLocalDate()))
.count());
statistics.put("highPriority", workOrders.stream().filter(w -> w.getPriorityLevel() == 1).count());
statistics.put("highPriority", workOrders.stream().filter(w -> w.getPriorityLevel().equals(ErrorLevel.ERROR)).count());
return statistics;
}
@@ -483,7 +484,7 @@ public class WorkOrderServiceImpl extends ServiceImpl<IotWorkOrderMapper, IOTWor
workOrder.setOrderTitle(alarm.getAlarmTitle());
workOrder.setSourceType(7);
workOrder.setOrderType(2);
workOrder.setPriorityLevel(determinePriority(alarm.getAlarmLevel()));
workOrder.setPriorityLevel(alarm.getAlarmLevel());
workOrder.setDeviceId(alarm.getDeviceId());
workOrder.setDeviceName(alarm.getDeviceName());
workOrder.setDeviceType(alarm.getDeviceType());

View File

@@ -3,8 +3,6 @@ package com.maibu.service;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.maibu.core.business.DeviceModel;
import java.util.List;
/**
* @author jsmbz
* @description 针对表【iot_device_model(设备模型表)】的数据库操作Service
@@ -13,6 +11,7 @@ import java.util.List;
public interface SysDeviceModelService {
/**
* 新增设备模型
*
* @param deviceModel
* @return
*/
@@ -20,7 +19,8 @@ public interface SysDeviceModelService {
/**
* 分页查询设备模型列表
* @param page 分页对象
*
* @param page 分页对象
* @param deviceModel 查询条件
* @return 分页结果
*/
@@ -28,6 +28,7 @@ public interface SysDeviceModelService {
/**
* selectDeviceModelById
*
* @param id
* @return
*/
@@ -35,6 +36,7 @@ public interface SysDeviceModelService {
/**
* updateDeviceModel
*
* @param deviceModel
* @return
*/
@@ -42,6 +44,7 @@ public interface SysDeviceModelService {
/**
* 删除(逻辑删除模型)
*
* @param id
* @return
*/

View File

@@ -5,6 +5,9 @@ import com.maibu.core.domain.entity.SysSite;
import com.maibu.exception.ServiceException;
import com.maibu.mapper.SysRegionMapper;
import com.maibu.mapper.SysSiteMapper;
import com.maibu.memory.GlobalMemory;
import com.maibu.memory.SiteMemory;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@@ -13,7 +16,6 @@ import org.springframework.util.CollectionUtils;
import java.util.List;
@Service
public class SysSiteService {
@@ -23,21 +25,25 @@ public class SysSiteService {
@Autowired
private SysRegionService sysRegionService;
public List<SysSite> list(SysSite site) {
LambdaQueryWrapper<SysSite> queryWrapper = new LambdaQueryWrapper<>();
if (site != null && !StringUtils.isEmpty(site.getSiteName())) {
queryWrapper.like(SysSite::getSiteName, site.getSiteName());
}
if (site != null && site.getOrgId()!=null) {
if (site != null && site.getOrgId() != null) {
queryWrapper.eq(SysSite::getOrgId, site.getOrgId());
}
queryWrapper.orderByAsc(SysSite::getOrgId);
return sysSiteMapper.selectList(queryWrapper);
}
public boolean save(SysSite org) {
return sysSiteMapper.saveOrUpdate(org);
public boolean save(SysSite site) {
boolean b = sysSiteMapper.saveOrUpdate(site);
SiteMemory siteMemory = GlobalMemory.getSiteMemory(site.getOrgId(), site.getId());
if (siteMemory != null) {
siteMemory.setSysSite(site);
}
return b;
}
@Transactional
@@ -46,7 +52,6 @@ public class SysSiteService {
return sysSiteMapper.deleteBatchIds(ids);
}
public boolean checkExistSite(Long id) {
List<SysSite> sysSites = selectByOrgId(id);
if (CollectionUtils.isEmpty(sysSites)) {

View File

@@ -1,34 +1,42 @@
package com.maibu.netty.handler;
import cn.hutool.json.JSONObject;
import com.maibu.common.MiddleCommandConstant;
import com.maibu.common.MiddleConstant;
import com.maibu.core.business.device.DeviceStatusDetail;
import com.maibu.core.business.inter.WebsocketMesDispather;
import com.maibu.core.business.path.LatAndLngEntity;
import com.maibu.core.enums.MesType;
import com.maibu.core.enums.RespondCode;
import com.maibu.dto.*;
import com.maibu.memory.MiddleGlobalMemory;
import com.maibu.netty.NettyClient;
import com.maibu.utils.HttpService;
import com.maibu.utils.json.JsonUtils;
import com.maibu.utils.spring.SpringUtils;
import com.maibu.websocket.WebsocketHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.java_websocket.WebSocket;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.TimeUnit;
import org.apache.commons.lang3.StringUtils;
import org.java_websocket.WebSocket;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.maibu.common.MiddleCommandConstant;
import com.maibu.common.MiddleConstant;
import com.maibu.core.business.device.DeviceStatusDetail;
import com.maibu.core.business.inter.WebsocketMesDispather;
import com.maibu.core.business.path.LatAndLngEntity;
import com.maibu.core.enums.MesType;
import com.maibu.dto.DeviceRespondDTO;
import com.maibu.dto.NettySwitchDeviceDTO;
import com.maibu.dto.ResultDTO;
import com.maibu.dto.WebAuthResponseDTO;
import com.maibu.dto.WebDeviceTaskStatusMessageDTO;
import com.maibu.dto.WebOlineStatusMessageDTO;
import com.maibu.dto.WebStatusMessageDTO;
import com.maibu.dto.WebSwitchControlResponseDTO;
import com.maibu.memory.MiddleGlobalMemory;
import com.maibu.netty.NettyClient;
import com.maibu.utils.HttpService;
import com.maibu.utils.json.JsonUtils;
import com.maibu.utils.spring.SpringUtils;
import com.maibu.websocket.WebsocketHandler;
import cn.hutool.json.JSONObject;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import lombok.extern.slf4j.Slf4j;
/**
* Netty客户端处理器
*/