opt:西门子车辆状态显示报警信息

This commit is contained in:
2026-03-16 20:29:33 +08:00
parent ff64d2d48c
commit 633304c7f5
19 changed files with 898 additions and 23 deletions

View File

@@ -97,7 +97,7 @@ public class NDCAgvServiceImpl implements NDCAgvService {
if(null != startStorageCell && null != endStorageCell
&& "2".equals(startStorageCell.getCar_type())){
inst.setCar_type("2");
startAddress = deviceService.queryAddressBydeviceCode(inst.getStart_point_code());
startAddress = deviceService.queryEndAddressBydeviceCode(inst.getStart_point_code());
nextAddress = deviceService.queryEndAddressBydeviceCode(inst.getNext_point_code());
} else {
inst.setCar_type("1");

View File

@@ -0,0 +1,75 @@
package org.nl.acs.agv_alarm.domain;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.io.Serializable;
import java.util.Date;
/**
* AGV报警信息
*/
@Data
@EqualsAndHashCode(callSuper = false)
@TableName("acs_agv_alarm")
public class AcsAgvAlarm implements Serializable {
private static final long serialVersionUID = 1L;
@TableId(value = "id", type = IdType.ASSIGN_ID)
private String id;
/**
* AGV设备编码
*/
private String deviceCode;
/**
* AGV设备名称
*/
private String deviceName;
/**
* 报警代码
*/
private String alarmCode;
/**
* 报警信息
*/
private String alarmMessage;
/**
* 报警级别: 1-紧急, 2-重要, 3-一般
*/
private String alarmLevel;
/**
* 报警时间
*/
private Date alarmTime;
/**
* 状态: 0-未处理, 1-已处理
*/
private String status;
/**
* 创建时间
*/
private Date createTime;
/**
* 更新时间
*/
private Date updateTime;
/**
* 是否有效: 1-有效, 0-无效
*/
private String isActive;
}

View File

@@ -0,0 +1,70 @@
package org.nl.acs.agv_alarm.domain;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.io.Serializable;
import java.util.Date;
/**
* AGV状态
*/
@Data
@EqualsAndHashCode(callSuper = false)
@TableName("acs_agv_status")
public class AcsAgvStatus implements Serializable {
private static final long serialVersionUID = 1L;
@TableId(value = "id", type = IdType.ASSIGN_ID)
private String id;
/**
* AGV设备编码
*/
private String deviceCode;
/**
* AGV设备名称
*/
private String deviceName;
/**
* 状态
*/
private String status;
/**
* x坐标
*/
private Integer x;
/**
* y坐标
*/
private Integer y;
/**
* 角度
*/
private Integer angle;
/**
* 电量
*/
private Integer electricQty;
/**
* 更新时间
*/
private Date updateTime;
/**
* 是否有效: 1-有效, 0-无效
*/
private String isActive;
}

View File

@@ -0,0 +1,37 @@
package org.nl.acs.agv_alarm.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Param;
import org.nl.acs.agv_alarm.domain.AcsAgvAlarm;
import java.util.List;
import java.util.Map;
/**
* AGV报警信息Mapper
*/
public interface AcsAgvAlarmMapper extends BaseMapper<AcsAgvAlarm> {
/**
* 根据设备编码查询报警信息
* @param deviceCode 设备编码
* @return 报警信息列表
*/
List<AcsAgvAlarm> selectByDeviceCode(String deviceCode);
/**
* 根据设备编码和状态查询报警信息
* @param deviceCode 设备编码
* @param status 状态
* @return 报警信息列表
*/
List<AcsAgvAlarm> selectByDeviceCodeAndStatus(String deviceCode, String status);
/**
* 查询最新的报警信息
* @param limit 限制数量
* @return 报警信息列表
*/
List<Map<String, Object>> selectLatestAlarms( int limit);
}

View File

@@ -0,0 +1,34 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="org.nl.acs.agv_alarm.mapper.AcsAgvAlarmMapper">
<resultMap id="BaseResultMap" type="org.nl.acs.agv_alarm.domain.AcsAgvAlarm">
<id column="id" property="id" />
<result column="device_code" property="deviceCode" />
<result column="device_name" property="deviceName" />
<result column="alarm_code" property="alarmCode" />
<result column="alarm_message" property="alarmMessage" />
<result column="alarm_level" property="alarmLevel" />
<result column="alarm_time" property="alarmTime" />
<result column="status" property="status" />
<result column="create_time" property="createTime" />
<result column="update_time" property="updateTime" />
<result column="is_active" property="isActive" />
</resultMap>
<select id="selectByDeviceCode" resultMap="BaseResultMap">
SELECT * FROM acs_agv_alarm WHERE device_code = #{deviceCode} ORDER BY alarm_time DESC
</select>
<select id="selectByDeviceCodeAndStatus" resultMap="BaseResultMap">
SELECT * FROM acs_agv_alarm WHERE device_code = #{deviceCode} AND status = #{status} ORDER BY alarm_time DESC
</select>
<select id="selectLatestAlarms" resultType="java.util.Map">
SELECT *
FROM acs_agv_alarm
ORDER BY alarm_time DESC
LIMIT #{limit}
</select>
</mapper>

View File

@@ -0,0 +1,26 @@
package org.nl.acs.agv_alarm.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.nl.acs.agv_alarm.domain.AcsAgvStatus;
import java.util.List;
/**
* AGV状态Mapper
*/
public interface AcsAgvStatusMapper extends BaseMapper<AcsAgvStatus> {
/**
* 查询所有AGV状态
* @return AGV状态列表
*/
List<AcsAgvStatus> selectAllStatus();
/**
* 根据设备编码查询AGV状态
* @param deviceCode 设备编码
* @return AGV状态
*/
AcsAgvStatus selectByDeviceCode(String deviceCode);
}

View File

@@ -0,0 +1,26 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="org.nl.acs.agv_alarm.mapper.AcsAgvStatusMapper">
<resultMap id="BaseResultMap" type="org.nl.acs.agv_alarm.domain.AcsAgvStatus">
<id column="id" property="id" />
<result column="device_code" property="deviceCode" />
<result column="device_name" property="deviceName" />
<result column="status" property="status" />
<result column="x" property="x" />
<result column="y" property="y" />
<result column="angle" property="angle" />
<result column="electric_qty" property="electricQty" />
<result column="update_time" property="updateTime" />
<result column="is_active" property="isActive" />
</resultMap>
<select id="selectAllStatus" resultMap="BaseResultMap">
SELECT * FROM acs_agv_status
</select>
<select id="selectByDeviceCode" resultMap="BaseResultMap">
SELECT * FROM acs_agv_status WHERE device_code = #{deviceCode}
</select>
</mapper>

View File

@@ -0,0 +1,60 @@
package org.nl.acs.agv_alarm.rest;
import cn.dev33.satoken.annotation.SaIgnore;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import jdk.nashorn.internal.ir.annotations.Ignore;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.nl.common.logging.annotation.Log;
import org.nl.acs.agv_alarm.service.AcsAgvAlarmService;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import java.util.List;
import java.util.Map;
/**
* AGV报警信息控制器
*/
@Slf4j
@RestController
@RequiredArgsConstructor
@Api(tags = "AGV报警信息接口")
@SaIgnore
@RequestMapping("/api/agv_alarm")
public class AgvAlarmController {
private final AcsAgvAlarmService agvAlarmService;
@GetMapping("/status")
@Log("获取AGV状态")
@ApiOperation("获取AGV状态")
public ResponseEntity<Object> getAgvStatus() {
return new ResponseEntity<>(agvAlarmService.getAllAgvStatus(), HttpStatus.OK);
}
@GetMapping("/alarms")
@Log("获取AGV报警信息")
@ApiOperation("获取AGV报警信息")
public ResponseEntity<Object> getAgvAlarms(
@RequestParam(required = false) String deviceCode) {
if (deviceCode != null && !deviceCode.isEmpty()) {
return new ResponseEntity<>(agvAlarmService.getAgvAlarms(deviceCode), HttpStatus.OK);
} else {
return new ResponseEntity<>(agvAlarmService.getLatestAlarms(50), HttpStatus.OK);
}
}
@GetMapping("/alarms/latest")
@Log("获取最新报警信息")
@ApiOperation("获取最新报警信息")
public ResponseEntity<Object> getLatestAlarms(
@RequestParam(defaultValue = "10") int limit) {
return new ResponseEntity<>(agvAlarmService.getLatestAlarms(limit), HttpStatus.OK);
}
}

View File

@@ -0,0 +1,63 @@
package org.nl.acs.agv_alarm.service;
import org.nl.acs.agv_alarm.domain.AcsAgvAlarm;
import org.nl.acs.agv_alarm.domain.AcsAgvStatus;
import java.util.List;
import java.util.Map;
/**
* AGV报警信息服务
*/
public interface AcsAgvAlarmService {
/**
* 记录AGV报警信息
* @param deviceCode 设备编码
* @param deviceName 设备名称
* @param alarmCode 报警代码
* @param alarmMessage 报警信息
* @param alarmLevel 报警级别
*/
void recordAlarm(String deviceCode, String deviceName, String alarmCode, String alarmMessage, String alarmLevel);
/**
* 更新AGV状态
* @param deviceCode 设备编码
* @param deviceName 设备名称
* @param status 状态
* @param x x坐标
* @param y y坐标
* @param angle 角度
* @param electricQty 电量
*/
void updateAgvStatus(String deviceCode, String deviceName, int statusInt,String status, int x, int y, int angle, int electricQty);
/**
* 获取AGV状态
* @param deviceCode 设备编码
* @return AGV状态
*/
AcsAgvStatus getAgvStatus(String deviceCode);
/**
* 获取所有AGV状态
* @return AGV状态列表
*/
List<AcsAgvStatus> getAllAgvStatus();
/**
* 获取AGV报警信息
* @param deviceCode 设备编码
* @return 报警信息列表
*/
List<AcsAgvAlarm> getAgvAlarms(String deviceCode);
/**
* 获取最新报警信息
* @param limit 限制数量
* @return 报警信息列表
*/
List<Map<String, Object>> getLatestAlarms(int limit);
}

View File

@@ -0,0 +1,108 @@
package org.nl.acs.agv_alarm.service.impl;
import cn.hutool.core.util.IdUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.nl.acs.agv_alarm.domain.AcsAgvAlarm;
import org.nl.acs.agv_alarm.domain.AcsAgvStatus;
import org.nl.acs.agv_alarm.mapper.AcsAgvAlarmMapper;
import org.nl.acs.agv_alarm.mapper.AcsAgvStatusMapper;
import org.nl.acs.agv_alarm.service.AcsAgvAlarmService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.Date;
import java.util.List;
import java.util.Map;
/**
* AGV报警信息服务实现
*/
@Slf4j
@Service
@RequiredArgsConstructor
public class AcsAgvAlarmServiceImpl implements AcsAgvAlarmService {
private final AcsAgvAlarmMapper alarmMapper;
private final AcsAgvStatusMapper statusMapper;
@Override
@Transactional(rollbackFor = Exception.class)
public void recordAlarm(String deviceCode, String deviceName, String alarmCode, String alarmMessage, String alarmLevel) {
AcsAgvAlarm alarm = new AcsAgvAlarm();
alarm.setId(IdUtil.simpleUUID());
alarm.setDeviceCode(deviceCode);
alarm.setDeviceName(deviceName);
alarm.setAlarmCode(alarmCode);
alarm.setAlarmMessage(alarmMessage);
alarm.setAlarmLevel(alarmLevel);
alarm.setAlarmTime(new Date());
alarm.setStatus("0");
alarm.setCreateTime(new Date());
alarm.setUpdateTime(new Date());
alarm.setIsActive("1");
alarmMapper.insert(alarm);
log.info("AGV报警信息记录成功: 设备编码={}, 报警代码={}, 报警信息={}", deviceCode, alarmCode, alarmMessage);
}
@Override
@Transactional(rollbackFor = Exception.class)
public void updateAgvStatus(String deviceCode, String deviceName,int statusInt, String status, int x, int y, int angle, int electricQty) {
AcsAgvStatus agvStatus = statusMapper.selectByDeviceCode(deviceCode);
Boolean insertFlag = false;
if (agvStatus == null) {
// 创建新的状态记录
insertFlag = true;
agvStatus = new AcsAgvStatus();
agvStatus.setId(IdUtil.simpleUUID());
agvStatus.setDeviceCode(deviceCode);
agvStatus.setDeviceName(deviceName);
}
// 更新状态信息
agvStatus.setStatus(status);
agvStatus.setX(x);
agvStatus.setY(y);
agvStatus.setAngle(angle);
agvStatus.setElectricQty(electricQty);
agvStatus.setUpdateTime(new Date());
if (statusInt == 1 || statusInt == 3 || statusInt == 4 || statusInt == 6 || statusInt == 7) {
agvStatus.setIsActive("1");
} else {
agvStatus.setIsActive("0");
}
if (insertFlag) {
statusMapper.insert(agvStatus);
} else {
statusMapper.updateById(agvStatus);
}
log.debug("AGV状态更新成功: 设备编码={}, 状态={}, 坐标=({},{})", deviceCode, status, x, y);
}
@Override
public AcsAgvStatus getAgvStatus(String deviceCode) {
return statusMapper.selectByDeviceCode(deviceCode);
}
@Override
public List<AcsAgvStatus> getAllAgvStatus() {
return statusMapper.selectAllStatus();
}
@Override
public List<AcsAgvAlarm> getAgvAlarms(String deviceCode) {
return alarmMapper.selectByDeviceCode(deviceCode);
}
@Override
public List<Map<String, Object>> getLatestAlarms(int limit) {
return alarmMapper.selectLatestAlarms(limit);
}
}

View File

@@ -13,6 +13,7 @@ import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.nl.acs.AcsConfig;
import org.nl.acs.agv.server.NDCAgvService;
import org.nl.acs.agv_alarm.service.AcsAgvAlarmService;
import org.nl.acs.auto.run.OneNDCSocketConnectionAutoRun;
import org.nl.acs.device.domain.Device;
import org.nl.acs.device.service.DeviceService;
@@ -72,6 +73,7 @@ public class AgvNdcOneDeviceDriver extends AbstractDeviceDriver implements Devic
DeviceService deviceService = SpringContextHolder.getBean(DeviceService.class);
ISysDictService dictService = SpringContextHolder.getBean(ISysDictService.class);
AcsAgvUsageService agvUsageService = SpringContextHolder.getBean(AcsAgvUsageService.class);
AcsAgvAlarmService agvAlarmService = SpringContextHolder.getBean(AcsAgvAlarmService.class);
int agvaddr = 0;
int agvaddr_copy = 0;
@@ -481,7 +483,7 @@ public class AgvNdcOneDeviceDriver extends AbstractDeviceDriver implements Devic
// AGV使用率统计 - 结束工作
try {
String agvDeviceCode = "agv" + inst.getCarno();
String agvDeviceCode = "agv" + carno;
if (StrUtil.isNotEmpty(agvDeviceCode)) {
agvUsageService.endWork(agvDeviceCode, inst.getTask_code(), inst.getInstruction_code());
}
@@ -617,6 +619,35 @@ public class AgvNdcOneDeviceDriver extends AbstractDeviceDriver implements Devic
} else if (phase == 0x74) {
//三色灯状态
status = ikey;
// 更新AGV状态
try {
String agvDeviceCode = "agv" + agvaddr;
String agvDeviceName = this.device_code;
Device agvDevice = deviceAppService.findDeviceByCode(agvDeviceCode);
if (agvDevice != null) {
agvDeviceName = agvDevice.getDevice_name();
}
String statusStr = "正常";
if (status == 1) {
statusStr = "关机";
} else if (status == 2) {
statusStr = "运行中";
}else if (status == 3) {
statusStr = "交通管制";
}else if (status == 4) {
statusStr = "任务等待";
}else if (status == 5) {
statusStr = "充电中";
}else if (status == 6) {
statusStr = "故障中";
}else if (status == 7) {
statusStr = "低电量";
}
agvAlarmService.updateAgvStatus(agvDeviceCode, agvDeviceName, status,statusStr, x, y, angle, electric_qty);
} catch (Exception e) {
log.error("AGV状态更新失败: {}", e.getMessage());
}
}
if (!ObjectUtil.isEmpty(data)) {
logServer.deviceExecuteLog(this.device_code, "", "", "agvphase:" + phase + "反馈:" + data);

View File

@@ -0,0 +1,34 @@
-- AGV报警信息表
CREATE TABLE IF NOT EXISTS acs_agv_alarm (
id VARCHAR(64) NOT NULL COMMENT '主键',
device_code VARCHAR(100) NOT NULL COMMENT 'AGV设备编码',
device_name VARCHAR(200) DEFAULT NULL COMMENT 'AGV设备名称',
alarm_code VARCHAR(50) NOT NULL COMMENT '报警代码',
alarm_message VARCHAR(500) NOT NULL COMMENT '报警信息',
alarm_level VARCHAR(10) DEFAULT '3' COMMENT '报警级别: 1-紧急, 2-重要, 3-一般',
alarm_time DATETIME NOT NULL COMMENT '报警时间',
status VARCHAR(10) DEFAULT '0' COMMENT '状态: 0-未处理, 1-已处理',
create_time DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
update_time DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
is_active VARCHAR(1) DEFAULT '1' COMMENT '是否有效: 1-有效, 0-无效',
PRIMARY KEY (id),
INDEX idx_device_code (device_code),
INDEX idx_alarm_time (alarm_time),
INDEX idx_status (status)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='AGV报警信息表';
-- AGV状态表
CREATE TABLE IF NOT EXISTS acs_agv_status (
id VARCHAR(64) NOT NULL COMMENT '主键',
device_code VARCHAR(100) NOT NULL COMMENT 'AGV设备编码',
device_name VARCHAR(200) DEFAULT NULL COMMENT 'AGV设备名称',
status VARCHAR(50) NOT NULL COMMENT '状态',
x INT DEFAULT 0 COMMENT 'x坐标',
y INT DEFAULT 0 COMMENT 'y坐标',
angle INT DEFAULT 0 COMMENT '角度',
electric_qty INT DEFAULT 0 COMMENT '电量',
update_time DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
is_active VARCHAR(1) DEFAULT '1' COMMENT '是否有效: 1-有效, 0-无效',
PRIMARY KEY (id),
UNIQUE INDEX uk_device_code (device_code)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='AGV状态表';