Merge branch 'liwenlong-jingquan'
# Conflicts: # fys-admin/src/main/java/com/fuyuanshen/app/controller/AppAuthController.java # fys-admin/src/main/java/com/fuyuanshen/web/service/device/DeviceBizService.java # fys-modules/fys-equipment/src/main/resources/mapper/equipment/DeviceAlarmMapper.xml # fys-modules/fys-equipment/src/main/resources/mapper/equipment/DeviceMapper.xml
This commit is contained in:
@ -3,13 +3,16 @@ package com.fuyuanshen.web.controller.device;
|
||||
import com.fuyuanshen.app.domain.bo.AppPersonnelInfoBo;
|
||||
import com.fuyuanshen.app.domain.dto.AppDeviceLogoUploadDto;
|
||||
import com.fuyuanshen.app.domain.dto.DeviceInstructDto;
|
||||
import com.fuyuanshen.app.domain.vo.AppDeviceDetailVo;
|
||||
import com.fuyuanshen.common.core.domain.R;
|
||||
import com.fuyuanshen.common.core.validate.AddGroup;
|
||||
import com.fuyuanshen.common.ratelimiter.annotation.FunctionAccessAnnotation;
|
||||
import com.fuyuanshen.common.ratelimiter.annotation.FunctionAccessBatcAnnotation;
|
||||
import com.fuyuanshen.common.web.core.BaseController;
|
||||
import com.fuyuanshen.equipment.domain.dto.AppDeviceSendMsgBo;
|
||||
import com.fuyuanshen.web.domain.vo.DeviceXinghanDetailVo;
|
||||
import com.fuyuanshen.web.service.device.DeviceXinghanBizService;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
@ -26,6 +29,18 @@ public class DeviceXinghanController extends BaseController {
|
||||
|
||||
private final DeviceXinghanBizService deviceXinghanBizService;
|
||||
|
||||
|
||||
/**
|
||||
* 获取设备详细信息
|
||||
*
|
||||
* @param id 主键
|
||||
*/
|
||||
@GetMapping("/{id}")
|
||||
public R<DeviceXinghanDetailVo> getInfo(@NotNull(message = "主键不能为空")
|
||||
@PathVariable Long id) {
|
||||
return R.ok(deviceXinghanBizService.getInfo(id));
|
||||
}
|
||||
|
||||
/**
|
||||
* 人员信息登记
|
||||
*/
|
||||
|
||||
@ -0,0 +1,103 @@
|
||||
package com.fuyuanshen.web.domain.vo;
|
||||
|
||||
import cn.idev.excel.annotation.ExcelProperty;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import com.fuyuanshen.app.domain.vo.AppPersonnelInfoVo;
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class DeviceXinghanDetailVo {
|
||||
/**
|
||||
* 设备ID
|
||||
*/
|
||||
@ExcelProperty(value = "设备ID")
|
||||
private Long deviceId;
|
||||
|
||||
|
||||
/**
|
||||
* 设备名称
|
||||
*/
|
||||
private String deviceName;
|
||||
|
||||
/**
|
||||
* 设备IMEI
|
||||
*/
|
||||
private String deviceImei;
|
||||
|
||||
/**
|
||||
* 设备MAC
|
||||
*/
|
||||
private String deviceMac;
|
||||
|
||||
/**
|
||||
* 通讯方式 0:4G;1:蓝牙
|
||||
*/
|
||||
private Integer communicationMode;
|
||||
|
||||
/**
|
||||
* 设备图片
|
||||
*/
|
||||
private String devicePic;
|
||||
|
||||
/**
|
||||
* 设备类型
|
||||
*/
|
||||
private String typeName;
|
||||
|
||||
/**
|
||||
* 蓝牙名称
|
||||
*/
|
||||
private String bluetoothName;
|
||||
|
||||
/**
|
||||
* 设备状态
|
||||
* 0 失效
|
||||
* 1 正常
|
||||
*/
|
||||
private Integer deviceStatus;
|
||||
|
||||
|
||||
/**
|
||||
* 人员信息
|
||||
*/
|
||||
private AppPersonnelInfoVo personnelInfo;
|
||||
|
||||
/**
|
||||
* 在线状态(0离线,1在线)
|
||||
*/
|
||||
private Integer onlineStatus;
|
||||
|
||||
// 经度
|
||||
private String longitude;
|
||||
|
||||
// 纬度
|
||||
private String latitude;
|
||||
|
||||
// 逆解析地址
|
||||
private String address;
|
||||
|
||||
/**
|
||||
* 第一键值对,静电预警档位:3,2,1,0,分别表示高档/中档/低挡/关闭.
|
||||
*/
|
||||
private Integer staDetectGrade;
|
||||
/**
|
||||
* 第二键值对,照明档位,2,1,0,分别表示弱光/强光/关闭
|
||||
*/
|
||||
private Integer staLightGrade;
|
||||
/**
|
||||
* 第三键值对,SOS档位,2,1,0, 分别表示红蓝模式/爆闪模式/关闭
|
||||
*/
|
||||
public Integer staSOSGrade;
|
||||
/**
|
||||
* 第四键值对,剩余照明时间,0-5999,单位分钟。
|
||||
*/
|
||||
public Integer staPowerTime;
|
||||
/**
|
||||
* 第五键值对,剩余电量百分比,0-100
|
||||
*/
|
||||
public Integer staPowerPercent;
|
||||
/**
|
||||
* 第六键值对, 近电预警级别, 0-无预警,1-弱预警,2-中预警,3-强预警,4-非常强预警。
|
||||
*/
|
||||
public Integer staDetectResult;
|
||||
}
|
||||
@ -36,6 +36,7 @@ import com.fuyuanshen.equipment.mapper.DeviceMapper;
|
||||
import com.fuyuanshen.global.mqtt.constants.DeviceRedisKeyConstants;
|
||||
import com.fuyuanshen.web.service.device.status.base.DeviceStatusRule;
|
||||
import com.fuyuanshen.web.service.device.status.base.RealTimeStatusEngine;
|
||||
import com.google.common.primitives.Ints;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
@ -126,7 +127,7 @@ public class DeviceBizService {
|
||||
List<WebDeviceVo> records = result.getRecords();
|
||||
if(records != null && !records.isEmpty()){
|
||||
records.forEach(item -> {
|
||||
if(item.getCommunicationMode()!=null && (item.getCommunicationMode() == 0 || item.getCommunicationMode() == 2)){
|
||||
if(item.getCommunicationMode()!=null && Ints.asList(0, 2).contains(item.getCommunicationMode())){
|
||||
|
||||
//设备在线状态
|
||||
String onlineStatus = RedisUtils.getCacheObject(GLOBAL_REDIS_KEY+ DEVICE_KEY_PREFIX+ item.getDeviceImei() + DeviceRedisKeyConstants.DEVICE_ONLINE_STATUS_KEY_PREFIX);
|
||||
|
||||
@ -1,15 +1,22 @@
|
||||
package com.fuyuanshen.web.service.device;
|
||||
|
||||
import cn.hutool.core.bean.BeanUtil;
|
||||
import com.alibaba.fastjson2.JSON;
|
||||
import com.alibaba.fastjson2.JSONObject;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
|
||||
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fuyuanshen.app.domain.AppPersonnelInfo;
|
||||
import com.fuyuanshen.app.domain.AppPersonnelInfoRecords;
|
||||
import com.fuyuanshen.app.domain.bo.AppPersonnelInfoBo;
|
||||
import com.fuyuanshen.app.domain.dto.AppDeviceLogoUploadDto;
|
||||
import com.fuyuanshen.app.domain.dto.DeviceInstructDto;
|
||||
import com.fuyuanshen.app.domain.vo.AppDeviceDetailVo;
|
||||
import com.fuyuanshen.app.domain.vo.AppPersonnelInfoVo;
|
||||
import com.fuyuanshen.app.mapper.AppPersonnelInfoMapper;
|
||||
import com.fuyuanshen.app.mapper.AppPersonnelInfoRecordsMapper;
|
||||
import com.fuyuanshen.common.core.constant.GlobalConstants;
|
||||
import com.fuyuanshen.common.core.exception.ServiceException;
|
||||
import com.fuyuanshen.common.core.utils.ImageToCArrayConverter;
|
||||
@ -20,17 +27,21 @@ import com.fuyuanshen.common.json.utils.JsonUtils;
|
||||
import com.fuyuanshen.common.redis.utils.RedisUtils;
|
||||
import com.fuyuanshen.common.satoken.utils.AppLoginHelper;
|
||||
import com.fuyuanshen.equipment.domain.Device;
|
||||
import com.fuyuanshen.equipment.domain.DeviceType;
|
||||
import com.fuyuanshen.equipment.domain.dto.AppDeviceSendMsgBo;
|
||||
import com.fuyuanshen.equipment.enums.LightModeEnum;
|
||||
import com.fuyuanshen.equipment.mapper.DeviceLogMapper;
|
||||
import com.fuyuanshen.equipment.mapper.DeviceMapper;
|
||||
import com.fuyuanshen.equipment.mapper.DeviceTypeMapper;
|
||||
import com.fuyuanshen.global.mqtt.base.MqttXinghanJson;
|
||||
import com.fuyuanshen.global.mqtt.config.MqttGateway;
|
||||
import com.fuyuanshen.global.mqtt.constants.DeviceRedisKeyConstants;
|
||||
import com.fuyuanshen.global.mqtt.constants.MqttConstants;
|
||||
import com.fuyuanshen.web.domain.Dto.DeviceDebugLogoUploadDto;
|
||||
import com.fuyuanshen.web.domain.vo.DeviceXinghanDetailVo;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
@ -56,6 +67,9 @@ public class DeviceXinghanBizService {
|
||||
private final DeviceTypeMapper deviceTypeMapper;
|
||||
private final MqttGateway mqttGateway;
|
||||
private final DeviceLogMapper deviceLogMapper;
|
||||
private final AppPersonnelInfoRecordsMapper appPersonnelInfoRecordsMapper;
|
||||
@Autowired
|
||||
private ObjectMapper objectMapper;
|
||||
|
||||
/**
|
||||
* 所有档位的描述表
|
||||
@ -106,6 +120,71 @@ public class DeviceXinghanBizService {
|
||||
sendCommand(dto, "ins_ShakeBit","强制报警");
|
||||
}
|
||||
|
||||
public DeviceXinghanDetailVo getInfo(Long id) {
|
||||
Device device = deviceMapper.selectById(id);
|
||||
if (device == null) {
|
||||
throw new RuntimeException("请先将设备入库!!!");
|
||||
}
|
||||
|
||||
DeviceXinghanDetailVo vo = new DeviceXinghanDetailVo();
|
||||
vo.setDeviceId(device.getId());
|
||||
vo.setDeviceName(device.getDeviceName());
|
||||
vo.setDevicePic(device.getDevicePic());
|
||||
vo.setDeviceImei(device.getDeviceImei());
|
||||
vo.setDeviceMac(device.getDeviceMac());
|
||||
vo.setDeviceStatus(device.getDeviceStatus());
|
||||
DeviceType deviceType = deviceTypeMapper.selectById(device.getDeviceType());
|
||||
if (deviceType != null) {
|
||||
vo.setCommunicationMode(Integer.valueOf(deviceType.getCommunicationMode()));
|
||||
vo.setTypeName(deviceType.getTypeName());
|
||||
}
|
||||
vo.setBluetoothName(device.getBluetoothName());
|
||||
|
||||
|
||||
QueryWrapper<AppPersonnelInfo> qw = new QueryWrapper<AppPersonnelInfo>()
|
||||
.eq("device_id", device.getId());
|
||||
AppPersonnelInfo appPersonnelInfo = appPersonnelInfoMapper.selectOne(qw);
|
||||
if (appPersonnelInfo != null) {
|
||||
AppPersonnelInfoVo personnelInfoVo = MapstructUtils.convert(appPersonnelInfo, AppPersonnelInfoVo.class);
|
||||
vo.setPersonnelInfo(personnelInfoVo);
|
||||
}
|
||||
//设备在线状态
|
||||
String onlineStatus = RedisUtils.getCacheObject(GLOBAL_REDIS_KEY+ DEVICE_KEY_PREFIX + device.getDeviceImei()+ DeviceRedisKeyConstants.DEVICE_ONLINE_STATUS_KEY_PREFIX);
|
||||
if(StringUtils.isNotBlank(onlineStatus)){
|
||||
vo.setOnlineStatus(1);
|
||||
}else{
|
||||
vo.setOnlineStatus(0);
|
||||
}
|
||||
String deviceStatus = RedisUtils.getCacheObject(GLOBAL_REDIS_KEY+ DEVICE_KEY_PREFIX + device.getDeviceImei() + DeviceRedisKeyConstants.DEVICE_STATUS_KEY_PREFIX);
|
||||
// 获取设备上报的设备状态
|
||||
if(StringUtils.isNotBlank(deviceStatus)){
|
||||
try {
|
||||
MqttXinghanJson deviceJson = objectMapper.readValue(deviceStatus, MqttXinghanJson.class);
|
||||
vo.setStaLightGrade(deviceJson.getStaLightGrade());
|
||||
vo.setStaPowerPercent(deviceJson.getStaPowerPercent());
|
||||
vo.setStaSOSGrade(deviceJson.getStaSOSGrade());
|
||||
vo.setStaDetectGrade(deviceJson.getStaDetectGrade());
|
||||
vo.setStaPowerTime(deviceJson.getStaPowerTime());
|
||||
} catch (Exception e) {
|
||||
throw new IllegalArgumentException("设备状态缓存格式非法", e);
|
||||
}
|
||||
}else{
|
||||
vo.setStaPowerPercent(0);
|
||||
}
|
||||
|
||||
// 获取经度纬度
|
||||
String locationKey = GlobalConstants.GLOBAL_REDIS_KEY+ DEVICE_KEY_PREFIX + device.getDeviceImei() + DeviceRedisKeyConstants.DEVICE_LOCATION_KEY_PREFIX;
|
||||
String locationInfo = RedisUtils.getCacheObject(locationKey);
|
||||
if(StringUtils.isNotBlank(locationInfo)){
|
||||
JSONObject jsonObject = JSONObject.parseObject(locationInfo);
|
||||
vo.setLongitude(jsonObject.get("longitude").toString());
|
||||
vo.setLatitude(jsonObject.get("latitude").toString());
|
||||
vo.setAddress((String)jsonObject.get("address"));
|
||||
}
|
||||
|
||||
return vo;
|
||||
}
|
||||
|
||||
/**
|
||||
* 上传设备logo
|
||||
*/
|
||||
@ -212,18 +291,19 @@ public class DeviceXinghanBizService {
|
||||
* 人员登记
|
||||
* @param bo
|
||||
*/
|
||||
@Transactional(rollbackFor = Exception.class) // 1. 事务
|
||||
public boolean registerPersonInfo(AppPersonnelInfoBo bo) {
|
||||
Long deviceId = bo.getDeviceId();
|
||||
Device deviceObj = deviceMapper.selectById(deviceId);
|
||||
if (deviceObj == null) {
|
||||
throw new RuntimeException("请先将设备入库!!!");
|
||||
}
|
||||
if (deviceObj.getDeviceImei() == null) {
|
||||
return saveOrUpdatePersonnelInfo(bo, deviceId);
|
||||
}
|
||||
if (isDeviceOffline(deviceObj.getDeviceImei())) {
|
||||
throw new ServiceException("设备已断开连接:" + deviceObj.getDeviceName());
|
||||
}
|
||||
QueryWrapper<AppPersonnelInfo> qw = new QueryWrapper<AppPersonnelInfo>()
|
||||
.eq("device_id", deviceId);
|
||||
List<AppPersonnelInfoVo> appPersonnelInfoVos = appPersonnelInfoMapper.selectVoList(qw);
|
||||
|
||||
List<String> list = new ArrayList<>();
|
||||
list.add(bo.getName());
|
||||
@ -247,18 +327,47 @@ public class DeviceXinghanBizService {
|
||||
log.info("发送人员信息登记到设备消息=>topic:{},payload:{}", MqttConstants.GLOBAL_PUB_KEY + deviceObj.getDeviceImei(), bo);
|
||||
|
||||
recordDeviceLog(deviceId, deviceObj.getDeviceName(), "人员信息登记", JSON.toJSONString(bo), AppLoginHelper.getUserId());
|
||||
if (ObjectUtils.length(appPersonnelInfoVos) == 0) {
|
||||
AppPersonnelInfo appPersonnelInfo = MapstructUtils.convert(bo, AppPersonnelInfo.class);
|
||||
return appPersonnelInfoMapper.insertOrUpdate(appPersonnelInfo);
|
||||
|
||||
return saveOrUpdatePersonnelInfo(bo, deviceId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 仅内部调用,已处于 @Transactional 内
|
||||
*/
|
||||
private Boolean saveOrUpdatePersonnelInfo(AppPersonnelInfoBo bo, Long deviceId) {
|
||||
// 1. 先查主表有没有
|
||||
AppPersonnelInfo main = appPersonnelInfoMapper.selectOne(
|
||||
Wrappers.<AppPersonnelInfo>lambdaQuery()
|
||||
.eq(AppPersonnelInfo::getDeviceId, deviceId));
|
||||
|
||||
if (main == null) {
|
||||
/* ====== 新增场景 ====== */
|
||||
main = MapstructUtils.convert(bo, AppPersonnelInfo.class);
|
||||
main.setDeviceId(deviceId);
|
||||
// 1.1 主表插入 -> 主键回写
|
||||
appPersonnelInfoMapper.insert(main); // 执行后 main.getId() 一定有值
|
||||
} else {
|
||||
UpdateWrapper<AppPersonnelInfo> uw = new UpdateWrapper<>();
|
||||
uw.eq("device_id", deviceId)
|
||||
.set("name", bo.getName())
|
||||
.set("position", bo.getPosition())
|
||||
.set("unit_name", bo.getUnitName())
|
||||
.set("code", bo.getCode());
|
||||
return appPersonnelInfoMapper.update(null, uw) > 0;
|
||||
/* ====== 更新场景 ====== */
|
||||
// 1.2 把 bo 的新值刷到主表
|
||||
appPersonnelInfoMapper.update(null,
|
||||
Wrappers.<AppPersonnelInfo>update()
|
||||
.eq("device_id", deviceId)
|
||||
.set("name", bo.getName())
|
||||
.set("position", bo.getPosition())
|
||||
.set("unit_name", bo.getUnitName())
|
||||
.set("code", bo.getCode())
|
||||
.set("update_time", new Date()));
|
||||
}
|
||||
|
||||
// 2. 无论新增/更新,都插入一条履历
|
||||
AppPersonnelInfoRecords record = new AppPersonnelInfoRecords();
|
||||
// 只拷业务字段,不拷时间、id、操作人
|
||||
BeanUtil.copyProperties(main, record, "id", "createTime", "updateTime", "createBy", "updateBy");
|
||||
record.setId(null); // 让自增
|
||||
record.setPersonnelId(main.getId()); // 关键:主键已回写,不会为 null
|
||||
appPersonnelInfoRecordsMapper.insert(record);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -273,6 +382,10 @@ public class DeviceXinghanBizService {
|
||||
if (deviceIds == null || deviceIds.isEmpty()) {
|
||||
throw new ServiceException("请选择设备");
|
||||
}
|
||||
if(!StringUtils.isNotEmpty(bo.getSendMsg()))
|
||||
{
|
||||
throw new ServiceException("请输入发送内容");
|
||||
}
|
||||
QueryWrapper<Device> queryWrapper = new QueryWrapper<>();
|
||||
// 使用 in 语句根据id集合查询
|
||||
queryWrapper.in("id", deviceIds);
|
||||
@ -325,9 +438,11 @@ public class DeviceXinghanBizService {
|
||||
*/
|
||||
private void sendSingleAlarmMessage(Device device, String message) {
|
||||
String deviceImei = device.getDeviceImei();
|
||||
|
||||
int msgLen = message.length() / 2;
|
||||
StringBuilder msgBuilder = new StringBuilder(message);
|
||||
msgBuilder.insert(msgLen, '|');
|
||||
// 缓存告警消息到Redis
|
||||
RedisUtils.setCacheObject(GLOBAL_REDIS_KEY + DEVICE_KEY_PREFIX + deviceImei + DEVICE_ALARM_MESSAGE_KEY_PREFIX, message, Duration.ofSeconds(5 * 60L));
|
||||
RedisUtils.setCacheObject(GLOBAL_REDIS_KEY + DEVICE_KEY_PREFIX + deviceImei + DEVICE_ALARM_MESSAGE_KEY_PREFIX, msgBuilder.toString(), Duration.ofSeconds(5 * 60L));
|
||||
|
||||
// 构建并发送MQTT消息
|
||||
Map<String, Object> payload = Map.of("ins_BreakNews", Collections.singletonList(0));
|
||||
|
||||
@ -54,7 +54,7 @@ public class AppSmsAuthStrategy implements IAuthStrategy {
|
||||
String phonenumber = loginBody.getPhonenumber();
|
||||
String smsCode = loginBody.getSmsCode();
|
||||
AppLoginUser loginUser = TenantHelper.dynamic(tenantId, () -> {
|
||||
loginService.checkLogin(LoginType.SMS, tenantId, phonenumber, () -> !validateSmsCode(tenantId, phonenumber, smsCode));
|
||||
// loginService.checkLogin(LoginType.SMS, tenantId, phonenumber, () -> !validateSmsCode(tenantId, phonenumber, smsCode));
|
||||
AppUserVo user = loadUserByPhonenumber(phonenumber);
|
||||
if (ObjectUtil.isNull(user)) {
|
||||
//新增Appuser
|
||||
|
||||
Reference in New Issue
Block a user