Compare commits

8 Commits

Author SHA1 Message Date
7b8c626cb6 Merge branch 'jingquan' into dyf-device 2025-10-09 14:45:15 +08:00
dyf
9642908035 Merge pull request 'feat(app): 实现系统版本管理功能-Dto 新增 SystemVersion 数据传输对象- 修改 AppAuthController 的 getAppVersion 接口,从 Redis 获取版本信息' (#16) from liwenlong/fys-Multi-tenant:jingquan into jingquan
Reviewed-on: #16
2025-10-09 14:44:18 +08:00
85b2e2b976 设备告警1 2025-10-09 13:31:37 +08:00
88ac0236bd feat(app): 实现系统版本管理功能-Dto 新增 SystemVersion 数据传输对象- 修改 AppAuthController 的 getAppVersion 接口,从 Redis 获取版本信息
- 新增 DeviceXinghanController 的 VersionSettings 接口,用于更新版本信息到 Redis- 引入 FastJSON 和 Redis 工具类支持版本信息的序列化与缓存
- 添加权限注解控制版本更新接口访问
- 定义全局 Redis 键常量用于版本信息存储
2025-10-09 11:09:07 +08:00
609a3e4058 设备在线状态2 2025-10-09 09:44:48 +08:00
68cf78f3f2 设备在线状态5 2025-10-08 17:27:43 +08:00
c9857a679c 设备在线状态4 2025-10-08 15:08:31 +08:00
6439a96e3d 设备在线状态3 2025-10-08 15:07:54 +08:00
7 changed files with 68 additions and 31 deletions

View File

@ -5,6 +5,7 @@ import cn.dev33.satoken.exception.NotLoginException;
import cn.hutool.core.collection.CollUtil; import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.RandomUtil; import cn.hutool.core.util.RandomUtil;
import com.alibaba.fastjson.JSON;
import com.fuyuanshen.app.model.AppRegisterBody; import com.fuyuanshen.app.model.AppRegisterBody;
import com.fuyuanshen.app.model.AppSmsLoginBody; import com.fuyuanshen.app.model.AppSmsLoginBody;
import com.fuyuanshen.app.service.AppLoginService; import com.fuyuanshen.app.service.AppLoginService;
@ -32,6 +33,7 @@ import com.fuyuanshen.system.service.ISysClientService;
import com.fuyuanshen.system.service.ISysConfigService; import com.fuyuanshen.system.service.ISysConfigService;
import com.fuyuanshen.system.service.ISysDictTypeService; import com.fuyuanshen.system.service.ISysDictTypeService;
import com.fuyuanshen.system.service.ISysTenantService; import com.fuyuanshen.system.service.ISysTenantService;
import com.fuyuanshen.web.domain.Dto.SystemVersionDto;
import com.fuyuanshen.web.domain.vo.LoginTenantVo; import com.fuyuanshen.web.domain.vo.LoginTenantVo;
import com.fuyuanshen.web.domain.vo.LoginVo; import com.fuyuanshen.web.domain.vo.LoginVo;
import com.fuyuanshen.web.domain.vo.TenantListVo; import com.fuyuanshen.web.domain.vo.TenantListVo;
@ -54,6 +56,7 @@ import java.util.ArrayList;
import java.util.List; import java.util.List;
import static com.fuyuanshen.common.core.constant.GlobalConstants.DEVICE_SHARE_CODES_KEY; import static com.fuyuanshen.common.core.constant.GlobalConstants.DEVICE_SHARE_CODES_KEY;
import static com.fuyuanshen.common.core.constant.GlobalConstants.GLOBAL_REDIS_KEY;
/** /**
* APP认证 * APP认证
@ -261,23 +264,14 @@ public class AppAuthController {
* @return * @return
*/ */
@GetMapping("/version") @GetMapping("/version")
public R<List<SysDictDataVo>> getAppVersion() { public R<List<SystemVersionDto>> getAppVersion() {
List<SysDictDataVo> list = dictTypeService.selectDictDataByType("app_version"); String versionKey = GLOBAL_REDIS_KEY + "System:Version:Xinghan";
// 缓存告警消息到Redis
list.forEach(d -> { String versionJson = RedisUtils.getCacheObject(versionKey);
// 1. 安全拆分 if (StringUtils.isBlank(versionJson)) { // hutool 工具,可用 StringUtils.isBlank 代替
String[] arr = d.getRemark() == null ? new String[0] : d.getRemark().split("\\|"); return R.fail(versionJson);
if (arr.length < 2) { // 格式不对
log.warn("字典数据 app_version 格式非法dictLabel={}, remark={}", d.getDictLabel(), d.getRemark());
d.setDictValue(""); // 或者 d.setDictValue(d.getDictValue());
d.setRemark(""); // 下载地址留空
return; // 跳过
} }
// 2. 正常赋值 List<SystemVersionDto> list = JSON.parseArray(versionJson, SystemVersionDto.class);
d.setDictValue(arr[0].trim()); // 版本号
d.setRemark(arr[1].trim()); // 下载地址
});
return R.ok(list); return R.ok(list);
} }

View File

@ -57,10 +57,9 @@ public class BjqAlarmRule implements MqttMessageRule {
if (StringUtils.isNotBlank(convertValue)) { if (StringUtils.isNotBlank(convertValue)) {
// 将设备状态信息存储到Redis中 // 将设备状态信息存储到Redis中
String deviceRedisKey = GlobalConstants.GLOBAL_REDIS_KEY + DeviceRedisKeyConstants.DEVICE_KEY_PREFIX + context.getDeviceImei() + DEVICE_ALARM_KEY_PREFIX; String deviceRedisKey = GlobalConstants.GLOBAL_REDIS_KEY + DeviceRedisKeyConstants.DEVICE_KEY_PREFIX + context.getDeviceImei() + DEVICE_ALARM_KEY_PREFIX;
if ("1".equals(convertValue)) {
// 存储到Redis // 存储到Redis
RedisUtils.setCacheObject(deviceRedisKey, convertValue); RedisUtils.setCacheObject(deviceRedisKey, convertValue);
if ("1".equals(convertValue)) {
String sendMessageIng = GLOBAL_REDIS_KEY+ DEVICE_KEY_PREFIX + context.getDeviceImei() + ":messageSending"; String sendMessageIng = GLOBAL_REDIS_KEY+ DEVICE_KEY_PREFIX + context.getDeviceImei() + ":messageSending";
RedisUtils.setCacheObject(sendMessageIng, "1", Duration.ofDays(1)); RedisUtils.setCacheObject(sendMessageIng, "1", Duration.ofDays(1));
}else if ("0".equals(convertValue)){ }else if ("0".equals(convertValue)){

View File

@ -1,16 +1,21 @@
package com.fuyuanshen.web.controller.device; package com.fuyuanshen.web.controller.device;
import cn.dev33.satoken.annotation.SaCheckPermission;
import com.alibaba.fastjson.JSON;
import com.fuyuanshen.app.domain.bo.AppPersonnelInfoBo; import com.fuyuanshen.app.domain.bo.AppPersonnelInfoBo;
import com.fuyuanshen.app.domain.dto.AppDeviceLogoUploadDto; import com.fuyuanshen.app.domain.dto.AppDeviceLogoUploadDto;
import com.fuyuanshen.app.domain.dto.DeviceInstructDto; import com.fuyuanshen.app.domain.dto.DeviceInstructDto;
import com.fuyuanshen.app.domain.vo.AppDeviceDetailVo; import com.fuyuanshen.app.domain.vo.AppDeviceDetailVo;
import com.fuyuanshen.common.core.domain.R; import com.fuyuanshen.common.core.domain.R;
import com.fuyuanshen.common.core.utils.StringUtils;
import com.fuyuanshen.common.core.validate.AddGroup; import com.fuyuanshen.common.core.validate.AddGroup;
import com.fuyuanshen.common.ratelimiter.annotation.FunctionAccessAnnotation; import com.fuyuanshen.common.ratelimiter.annotation.FunctionAccessAnnotation;
import com.fuyuanshen.common.ratelimiter.annotation.FunctionAccessBatcAnnotation; import com.fuyuanshen.common.ratelimiter.annotation.FunctionAccessBatcAnnotation;
import com.fuyuanshen.common.redis.utils.RedisUtils;
import com.fuyuanshen.common.web.core.BaseController; import com.fuyuanshen.common.web.core.BaseController;
import com.fuyuanshen.equipment.domain.dto.AppDeviceSendMsgBo; import com.fuyuanshen.equipment.domain.dto.AppDeviceSendMsgBo;
import com.fuyuanshen.web.domain.Dto.DeviceXinghanInstructDto; import com.fuyuanshen.web.domain.Dto.DeviceXinghanInstructDto;
import com.fuyuanshen.web.domain.Dto.SystemVersionDto;
import com.fuyuanshen.web.domain.vo.DeviceXinghanDetailVo; import com.fuyuanshen.web.domain.vo.DeviceXinghanDetailVo;
import com.fuyuanshen.web.service.device.DeviceXinghanBizService; import com.fuyuanshen.web.service.device.DeviceXinghanBizService;
import jakarta.validation.constraints.NotNull; import jakarta.validation.constraints.NotNull;
@ -19,6 +24,13 @@ import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile; import org.springframework.web.multipart.MultipartFile;
import java.time.Duration;
import java.util.List;
import static com.fuyuanshen.common.core.constant.GlobalConstants.GLOBAL_REDIS_KEY;
import static com.fuyuanshen.global.mqtt.constants.DeviceRedisKeyConstants.DEVICE_ALARM_MESSAGE_KEY_PREFIX;
import static com.fuyuanshen.global.mqtt.constants.DeviceRedisKeyConstants.DEVICE_KEY_PREFIX;
/** /**
* 设备控制类 HBY670 * 设备控制类 HBY670
*/ */
@ -130,4 +142,22 @@ public class DeviceXinghanController extends BaseController {
deviceXinghanBizService.upShakeBitSettings(params); deviceXinghanBizService.upShakeBitSettings(params);
return R.ok(); return R.ok();
} }
/**
* 版本更新
*/
@SaCheckPermission("system:appVersion:up")
@PostMapping("/UpVersion")
public R<Void> VersionSettings(@RequestBody List<SystemVersionDto> params) {
// params 已经是 List<SystemVersionDto>
// 2. 转 JSON 并写 Rediskey 自己定,带个过期时间
String versionKey = GLOBAL_REDIS_KEY + "System:Version:Xinghan";
String json = JSON.toJSONString(params); // fastjson
if (StringUtils.isBlank(json)) { // hutool 工具,可用 StringUtils.isBlank 代替
return R.fail("信息无效");
}
// 缓存告警消息到Redis
RedisUtils.setCacheObject(versionKey, json, Duration.ofDays(30));
return R.ok();
}
} }

View File

@ -0,0 +1,10 @@
package com.fuyuanshen.web.domain.Dto;
import lombok.Data;
@Data
public class SystemVersionDto {
private String dictValue;
private String dictLabel;
private String remark;
}

View File

@ -526,10 +526,13 @@ public class DeviceBJQBizService {
UpdateWrapper<Device> updateWrapper = new UpdateWrapper<>(); UpdateWrapper<Device> updateWrapper = new UpdateWrapper<>();
updateWrapper.eq("id", deviceId) updateWrapper.eq("id", deviceId)
.eq("binding_user_id", AppLoginHelper.getUserId())
.set("send_msg", bo.getSendMsg()); .set("send_msg", bo.getSendMsg());
deviceMapper.update(updateWrapper); deviceMapper.update(updateWrapper);
if("0".equals(bo.getInstructValue())){
recordDeviceLog(device.getId(), device.getDeviceName(), "解除告警信息", "关闭设备", AppLoginHelper.getUserId());
}else{
recordDeviceLog(device.getId(), device.getDeviceName(), "发送告警信息", bo.getSendMsg(), AppLoginHelper.getUserId()); recordDeviceLog(device.getId(), device.getDeviceName(), "发送告警信息", bo.getSendMsg(), AppLoginHelper.getUserId());
}
} catch (Exception e) { } catch (Exception e) {
log.info("设备发送告警信息信息失败:{}" ,deviceId); log.info("设备发送告警信息信息失败:{}" ,deviceId);
throw new ServiceException("设备发送告警信息信息失败"); throw new ServiceException("设备发送告警信息信息失败");

View File

@ -131,14 +131,14 @@ public class DeviceBizService {
if(item.getCommunicationMode()!=null && Ints.asList(0, 2).contains(item.getCommunicationMode())){ 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); // String onlineStatus = RedisUtils.getCacheObject(GLOBAL_REDIS_KEY+ DEVICE_KEY_PREFIX+ item.getDeviceImei() + DeviceRedisKeyConstants.DEVICE_ONLINE_STATUS_KEY_PREFIX);
if("1".equals(onlineStatus)){ // if("1".equals(onlineStatus)){
item.setOnlineStatus(1); // item.setOnlineStatus(1);
}else if("2".equals(onlineStatus)){ // }else if("2".equals(onlineStatus)){
item.setOnlineStatus(2); // item.setOnlineStatus(2);
}else{ // }else{
item.setOnlineStatus(0); // item.setOnlineStatus(0);
} // }
String deviceStatus = RedisUtils.getCacheObject(GLOBAL_REDIS_KEY + DEVICE_KEY_PREFIX+ item.getDeviceImei() + DEVICE_STATUS_KEY_PREFIX); String deviceStatus = RedisUtils.getCacheObject(GLOBAL_REDIS_KEY + DEVICE_KEY_PREFIX+ item.getDeviceImei() + DEVICE_STATUS_KEY_PREFIX);
// 获取电量 // 获取电量
if(StringUtils.isNotBlank(deviceStatus)){ if(StringUtils.isNotBlank(deviceStatus)){

View File

@ -258,6 +258,7 @@
d.binding_status, d.binding_status,
d.online_status, d.online_status,
c.binding_time, c.binding_time,
d.create_time,
ROW_NUMBER() OVER (PARTITION BY d.id ORDER BY c.binding_time) AS row_num ROW_NUMBER() OVER (PARTITION BY d.id ORDER BY c.binding_time) AS row_num
from device d from device d
inner join device_type dt on d.device_type = dt.id inner join device_type dt on d.device_type = dt.id
@ -291,7 +292,7 @@
<if test="criteria.onlineStatus != null"> <if test="criteria.onlineStatus != null">
and a.online_status = #{criteria.onlineStatus} and a.online_status = #{criteria.onlineStatus}
</if> </if>
ORDER BY a.online_status,a.binding_time DESC ORDER BY (case when a.online_status = 1 then 2 else 1 end) DESC
</select> </select>
<select id="getLocationHistory" resultType="com.fuyuanshen.equipment.domain.vo.LocationHistoryVo"> <select id="getLocationHistory" resultType="com.fuyuanshen.equipment.domain.vo.LocationHistoryVo">
select a.id,a.device_name,a.device_type,b.type_name deviceTypeName,a.device_imei,a.device_mac from device a select a.id,a.device_name,a.device_type,b.type_name deviceTypeName,a.device_imei,a.device_mac from device a