# 上位机心跳 以及定位信息发送部分

This commit is contained in:
2026-08-19 16:57:55 +08:00
parent 2f94639f0a
commit 16ec98e36a
14 changed files with 238 additions and 118 deletions

View File

@@ -1,14 +0,0 @@
package com.maibu.dto;
import lombok.Data;
import java.util.List;
import com.maibu.core.business.device.DeviceStatusDetail;
import com.maibu.core.enums.MesType;
@Data
public class WebStatusMessageDTO {
private List<DeviceStatusDetail> data;
private MesType type;
}

View File

@@ -4,10 +4,13 @@ import java.util.List;
import java.util.Set;
import com.maibu.memory.DeviceSessionManager;
import com.maibu.memory.GlobalMemory;
import com.maibu.mqtt.MqttTopic;
import org.apache.commons.codec.binary.Hex;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
@@ -32,6 +35,9 @@ public class CommandForwardHandler extends SimpleChannelInboundHandler<String> {
@Autowired
private DeviceSessionManager deviceSessionManager;
@Value("${mqtt.client-id}")
private String mqttClientId;
@Override
protected void channelRead0(ChannelHandlerContext ctx, String msg) throws Exception {
Channel currentChannel = ctx.channel();
@@ -64,12 +70,6 @@ public class CommandForwardHandler extends SimpleChannelInboundHandler<String> {
}
if (ConnectorType.MASTER.equals(senderNettyDevice.getDeviceType())) {
//TODO 有控制权才能发
Set<Connector> connectedDevices = senderNettyDevice.getConnectedConnectors();
if (connectedDevices == null || connectedDevices.isEmpty()) {
logger.debug("发送拒绝master:{},该设备没有关联的设备", senderDeviceId);
@@ -84,11 +84,14 @@ public class CommandForwardHandler extends SimpleChannelInboundHandler<String> {
logger.debug("发送拒绝master:{},消息到达的slave设备:{},处于禁止接收状态", senderDeviceId, target.getConnectorId());
continue;
}
Channel targetChannel = target.getChannel();
if (targetChannel != null && targetChannel.isActive()) {
targetChannel.writeAndFlush(msg);
logger.debug("从master:{},向slave:{}, 转发消息:{}", senderDeviceId, target.getConnectorId(), msg);
}
// todo 向上位机发送控制消息
GlobalMemory.customMqttDeviceMonitor.publish(mqttClientId, String.format(MqttTopic.MOWER_CONTROL_SET, target.getConnectorId()), msg);
// Channel targetChannel = target.getChannel();
// if (targetChannel != null && targetChannel.isActive()) {
// targetChannel.writeAndFlush(msg);
// logger.debug("从master:{},向slave:{}, 转发消息:{}", senderDeviceId, target.getConnectorId(), msg);
// }
}
} else if (ConnectorType.SLAVE.equals(senderNettyDevice.getDeviceType())) {
List<NettyDevice> masters = deviceSessionManager.getMastersBySlaveId(senderDeviceId);

View File

@@ -13,10 +13,8 @@ import com.maibu.constant.Constant;
import com.maibu.core.business.DeviceRunParam;
import com.maibu.mapper.DeviceRunParamMapper;
import com.maibu.memory.DeviceSessionManager;
import com.maibu.memory.SiteMemory;
import org.apache.commons.codec.binary.Hex;
import org.apache.commons.lang3.StringUtils;
import org.eclipse.paho.client.mqttv3.MqttException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
@@ -34,7 +32,7 @@ import com.maibu.core.business.device.NettyDevice;
import com.maibu.core.business.inter.WebsocketMesDispather;
import com.maibu.core.enums.MesType;
import com.maibu.core.redis.RedisCache;
import com.maibu.dto.WebStatusMessageDTO;
import com.maibu.core.business.dto.WebStatusMessageDTO;
import com.maibu.influxdb.MowerRealTimeData;
import com.maibu.influxdb.util.InfluxSqlBuilder;
import com.maibu.memory.GlobalMemory;
@@ -101,15 +99,8 @@ public class DataToDataBaseHandler extends SimpleChannelInboundHandler<String> {
String deviceStatus = new String(bytes, 2, bytes.length - 4, StandardCharsets.UTF_8).trim();
String[] split = deviceStatus.split(",");
WebStatusMessageDTO dto = createWebDeviceStatusMessage(split);
try {
GlobalMemory.customMqttDeviceMonitor.publish(mqttClientId, String.format(MqttTopic.DEVICE_STATUS_TOPIC, deviceID),
GlobalMemory.customMqttDeviceMonitor.publish(mqttClientId, String.format(MqttTopic.DEVICE_STATUS_TOPIC, deviceID),
JsonUtils.toJsonString(dto));
// GlobalMemory.mqttClientUtil.publish(
// String.format(MqttTopic.DEVICE_STATUS_TOPIC, deviceID),
// JsonUtils.toJsonString(dto));
} catch (MqttException e) {
logger.error("发送实时状态数据错误: {}", e.getMessage());
}
List<NettyDevice> controlMasters = deviceSessionManager
.getAllSlaveControl(deviceID);
if (!CollectionUtils.isEmpty(controlMasters)) {

View File

@@ -194,51 +194,6 @@ public class DeviceConnectHandler extends SimpleChannelInboundHandler<String> {
handleMasterConnect(ctx, sessionId, null, ConnectorStatus.ACTIVE);
}
}
} else {
handleSlaveConnect(ctx, data);
logger.info("{}: 下位机连接", data);
Device device = deviceService.selectDeviceBySerialNumber(data);
if (device == null) {
device = new Device();
device.setStatus(3);
device.setOnlineStatus(DeviceStatus.online.getType());
device.setSerialNumber(data);
device.setDeviceName(data);
device.setProductId(-1L);
device.setTenantId(-1L);
device.setFirmwareVersion(BigDecimal.valueOf(1.0));
device.setProductName("割草机产品MC700");
device.setCreateTime(LocalDateTime.now());
device.setUpdateTime(LocalDateTime.now());
deviceService.insertDeviceBySelf(device);
} else {
device.setStatus(3);
device.setOnlineStatus(DeviceStatus.online.getType());
device.setUpdateTime(LocalDateTime.now());
deviceService.updateDeviceBySelf(device);
}
NettyDevice slaveDevice = sessionManager.getDevice(data);
if (slaveDevice != null) {
slaveDevice.setOnlineStatus(1);
slaveDevice.setDevice(device);
}
// 推送json 找到设备绑定的主机进行推送
List<NettyDevice> controlMasters = sessionManager.getAllSlaveControl(device.getSerialNumber());
if (!CollectionUtils.isEmpty(controlMasters)) {
controlMasters.forEach(x -> {
DeviceStatusChangeDTO changeDTO = new DeviceStatusChangeDTO();
changeDTO.setDeviceId(data);
changeDTO.setStatus(DeviceStatus.online.getCode());
changeDTO.setEvent(RespondCode.device_status_changed);
ByteBuf buf = ctx.alloc().buffer();
CommandUtils.buildCommand(buf, changeDTO, CommandConstant.interaction);
String content = buf.toString(CharsetUtil.UTF_8);
logger.info("推送下位机登录状态消息:{}", content);
if (x.getChannel() != null && x.getChannel().isActive()) {
x.getChannel().writeAndFlush(buf);
}
});
}
}
}
} else if (cmdType == CommandConstant.interaction) {
@@ -285,7 +240,7 @@ public class DeviceConnectHandler extends SimpleChannelInboundHandler<String> {
}
}
public void pushFinishData(NettyDevice device, String deviceId) {
public void pushFinishData(NettyDevice device, String deviceId) throws MqttException {
Long taskId = device.finishTask();
// todo 推送信息给前端
DeviceTaskStatusMessageDTO changeDTO = new DeviceTaskStatusMessageDTO();
@@ -294,16 +249,8 @@ public class DeviceConnectHandler extends SimpleChannelInboundHandler<String> {
changeDTO.setType(MesType.device_task_change);
changeDTO.setTaskId(taskId);
try {
GlobalMemory.customMqttDeviceMonitor.publish(mqttClientId, String.format(MqttTopic.DEVICE_TASK_STATUS_TOPIC, taskId),
GlobalMemory.customMqttDeviceMonitor.publish(mqttClientId, String.format(MqttTopic.DEVICE_TASK_STATUS_TOPIC, taskId),
JsonUtils.toJsonString(changeDTO));
// GlobalMemory.mqttClientUtil.publish(String.format(MqttTopic.DEVICE_TASK_STATUS_TOPIC, taskId),
// JsonUtils.toJsonString(changeDTO));
} catch (MqttException e) {
logger.error("任务完成状态推送失败 task:{},device:{}error:{}", taskId, deviceId, e.getMessage());
}
List<NettyDevice> controlMasters = sessionManager
.getAllSlaveControl(deviceId);
if (!CollectionUtils.isEmpty(controlMasters)) {
@@ -317,7 +264,7 @@ public class DeviceConnectHandler extends SimpleChannelInboundHandler<String> {
}
}
public void pushArriveData(NettyDevice device, String deviceId) {
public void pushArriveData(NettyDevice device, String deviceId) throws MqttException {
Long taskId = device.getTask() == null ? null : device.getTask().getId();
// todo 推送信息给前端
DeviceTaskStatusMessageDTO reportDTO = new DeviceTaskStatusMessageDTO();
@@ -325,15 +272,8 @@ public class DeviceConnectHandler extends SimpleChannelInboundHandler<String> {
reportDTO.setTaskId(taskId);
reportDTO.setEntity(device.getCurrentPoint());
reportDTO.setType(MesType.device_task_arrive_point);
try {
GlobalMemory.customMqttDeviceMonitor.publish(mqttClientId, String.format(MqttTopic.DEVICE_TASK_ARRIVE_TOPIC, taskId),
GlobalMemory.customMqttDeviceMonitor.publish(mqttClientId, String.format(MqttTopic.DEVICE_TASK_ARRIVE_TOPIC, taskId),
JsonUtils.toJsonString(reportDTO));
// GlobalMemory.mqttClientUtil.publish(String.format(MqttTopic.DEVICE_TASK_ARRIVE_TOPIC, taskId),
// JsonUtils.toJsonString(reportDTO));
} catch (MqttException e) {
logger.error("任务点位到达推送失败 task:{},device:{}error:{}", taskId, deviceId, e.getMessage());
}
List<NettyDevice> controlMasters = sessionManager
.getAllSlaveControl(deviceId);

View File

@@ -2,6 +2,7 @@ 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,12 +15,19 @@ import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
import com.maibu.constant.CommandConstant;
import com.maibu.constant.Constant;
import com.maibu.core.business.Device;
import com.maibu.core.enums.*;
import com.maibu.core.host.HeartBeatDTO;
import com.maibu.dto.DeviceStatusChangeDTO;
import com.maibu.memory.DeviceSessionManager;
import com.maibu.utils.CommandUtils;
import com.maibu.utils.json.JsonUtils;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.util.CharsetUtil;
import org.apache.commons.lang3.StringUtils;
import org.eclipse.paho.client.mqttv3.MqttException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.Constants;
@@ -37,9 +45,6 @@ import com.maibu.core.business.ErrorIdentificationStandard;
import com.maibu.core.business.alarm_center.AlarmMessage;
import com.maibu.core.business.device.NettyDevice;
import com.maibu.core.business.inter.WebsocketMesDispather;
import com.maibu.core.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.mapper.ErrorIdentificationStandardMapper;
@@ -74,6 +79,9 @@ public class DeviceThreadService {
@Autowired
private AlertPushService alertPushService;
@Autowired
private IDeviceService deviceService;
@Value("${mqtt.client-id}")
private String mqttClientId;
@@ -201,7 +209,7 @@ public class DeviceThreadService {
log.info("推送错误信息 device:{},content:{}", deviceId, dto);
});
}
} catch (MqttException e) {
} catch (Exception e) {
log.error("推送错误信息失败 device:{}error:{}", deviceId, e.getMessage());
}
}
@@ -270,19 +278,58 @@ public class DeviceThreadService {
List<HeartBeatDTO> heartBeatDTOS = GlobalMemory.customMqttDeviceMonitor.getAllHeartBeat();
if (!CollectionUtils.isEmpty(heartBeatDTOS)) {
heartBeatDTOS.forEach(x -> {
String deviceId = x.getSn();
Long lastActiveTime = x.getSysTimestamp();
NettyDevice device = sessionManager.getDevice(x.getSn());
NettyDevice nettyDevice = sessionManager.getDevice(x.getSn());
if (nowTime - lastActiveTime >= Constant.hostOfflineInterval) {
//超时了判断离线
if (device != null) {
device.status(0);
if (nettyDevice != null) {
nettyDevice.status(0);
//todo 推送设备离线
}
} else {
if (nettyDevice == null) {
sessionManager.registerSlaveDevice(deviceId, ConnectorStatus.ACTIVE, null);
Device device = deviceService.selectDeviceBySerialNumber(deviceId);
if (device == null) {
device = new Device();
device.setStatus(3);
device.setOnlineStatus(DeviceStatus.online.getType());
device.setSerialNumber(deviceId);
device.setDeviceName(deviceId);
device.setProductId(-1L);
device.setTenantId(-1L);
device.setFirmwareVersion(BigDecimal.valueOf(1.0));
device.setProductName("割草机产品MC700");
device.setCreateTime(LocalDateTime.now());
device.setUpdateTime(LocalDateTime.now());
deviceService.insertDeviceBySelf(device);
} else {
device.setStatus(3);
device.setOnlineStatus(DeviceStatus.online.getType());
device.setUpdateTime(LocalDateTime.now());
deviceService.updateDeviceBySelf(device);
}
// 推送json 找到设备绑定的主机进行推送
// List<NettyDevice> controlMasters = sessionManager.getAllSlaveControl(device.getSerialNumber());
// if (!CollectionUtils.isEmpty(controlMasters)) {
// controlMasters.forEach(x -> {
// DeviceStatusChangeDTO changeDTO = new DeviceStatusChangeDTO();
// changeDTO.setDeviceId(data);
// changeDTO.setStatus(DeviceStatus.online.getCode());
// changeDTO.setEvent(RespondCode.device_status_changed);
// ByteBuf buf = ctx.alloc().buffer();
// CommandUtils.buildCommand(buf, changeDTO, CommandConstant.interaction);
// String content = buf.toString(CharsetUtil.UTF_8);
// logger.info("推送下位机登录状态消息:{}", content);
// if (x.getChannel() != null && x.getChannel().isActive()) {
// x.getChannel().writeAndFlush(buf);
// }
// });
} else {
//todo 推送设备上线
nettyDevice.status(1);
}
}
});
}
@@ -290,8 +337,6 @@ public class DeviceThreadService {
log.error("执行监测心跳线程错误:{}", e.getMessage());
}
}, 0, 500, TimeUnit.MILLISECONDS);
}
}