Compare commits

49 Commits

Author SHA1 Message Date
dyf
740a638444 Merge pull request 'fix(device):修复SOS报警类型判断逻辑' (#17) from liwenlong/fys-Multi-tenant:jingquan into jingquan
Reviewed-on: #17
2025-10-11 13:35:08 +08:00
a3d44a157a fix(device):修复SOS报警类型判断逻辑
- 简化报警类型判断,固定为SOS类型
- 移除不必要的shake类型判断逻辑
2025-10-11 13:23:51 +08:00
cc23f082a6 Merge remote-tracking branch 'upstream/6170' into 6170 2025-10-11 11:06:15 +08:00
1bc7dc676e 控制中心查询 2025-10-11 11:06:07 +08:00
5cdacad468 获取设备使用频次统计 2025-10-11 10:32:16 +08:00
62af38cbf0 Merge branch 'dyf-device' into 6170 2025-10-11 09:05:38 +08:00
04a21567aa 设备所属分组 2025-10-11 09:04:48 +08:00
5b4fa38dbd 设备告警 2025-10-10 15:46:25 +08:00
2c3effa683 历史轨迹1 2025-10-10 09:26:52 +08:00
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
9f0155a6e3 Merge branch 'dyf-device' into 6170 2025-10-08 14:12:09 +08:00
6c99cef65d 解除告警 2025-10-08 14:11:11 +08:00
840c4fd68f 设备在线状态2 2025-10-08 13:53:03 +08:00
dc0fe96652 设备在线状态 2025-10-08 13:38:07 +08:00
cf883bfa00 Merge remote-tracking branch 'upstream/6170' into 6170 2025-10-08 11:48:16 +08:00
6a6397da23 控制查询条件加模糊查询 2025-10-08 11:48:05 +08:00
d701a834b3 设备IMEI 模糊查询 2025-10-08 09:37:18 +08:00
e1ac87e5f2 在线状态 2025-10-07 16:11:06 +08:00
5c3a35c83e 在线状态 2025-10-07 16:09:59 +08:00
2c0eff2b2c Merge remote-tracking branch 'origin/6170' into 6170 2025-10-07 15:50:26 +08:00
37e07d2706 控制中心优化2 2025-10-07 15:50:16 +08:00
dyf
5c0c4e40e4 Merge pull request 'fix(device):优化Redis缓存更新逻辑' (#15) from liwenlong/fys-Multi-tenant:jingquan into jingquan
Reviewed-on: #15
2025-10-07 15:46:56 +08:00
eceedae676 fix(device):优化Redis缓存更新逻辑
- 删除原有的直接设置缓存列表逻辑
- 新增先删除后写入的缓存更新策略- 统一使用变量存储Redis键值避免重复拼接- 保持原有缓存过期时间设置为5分钟
2025-10-07 15:29:19 +08:00
dfa5b446f9 控制中心优化 2025-10-07 09:50:49 +08:00
9afc0222d5 app批量上传logo 2025-09-30 17:53:28 +08:00
2cfcea65f1 Merge branch '6170' into dyf-device 2025-09-30 16:10:13 +08:00
dyf
9b72a6ebd2 Merge pull request 'feat(device): 新增设备类型查询与设备添加功能' (#14) from liwenlong/fys-Multi-tenant:jingquan into jingquan
Reviewed-on: #14
2025-09-30 16:06:10 +08:00
13db094336 feat(device): 新增设备类型查询与设备添加功能
- 在AppDeviceXinghanController中新增查询所有设备类型接口
- 实现新增设备功能,包含设备MAC和IMEI唯一性校验- 添加设备类型权限验证逻辑
- 完善设备绑定状态和主题设置
- 在DeviceXinghanBizService中实现设备分配记录保存
- 优化文件批量插入逻辑,支持是否批量删除历史数据- 增加文件删除功能,支持根据ID列表删除业务文件
- 缩短MQTT消息去重时间窗口至3秒
- 在设备维修记录查询条件中增加维修人员模糊查询- 调整设备消息发送数据顺序,单位名称移至首位
2025-09-30 15:59:24 +08:00
a1d6604520 app产品参数修改 2025-09-30 15:42:59 +08:00
b0e51e73c7 岗位信息1 2025-09-30 13:21:43 +08:00
dba537b83f 发送信息和告警故障5 2025-09-30 09:57:45 +08:00
d9b69ddc4e 不同的一级目录下的分组应当可以重名 2025-09-29 17:53:26 +08:00
6cec86bafe Merge remote-tracking branch 'upstream/6170' into jingquan 2025-09-29 13:57:29 +08:00
608aa8449a Merge branch 'main' into dyf-device 2025-09-29 09:26:49 +08:00
994e63bcde Merge branch '6170' of http://47.107.152.87:3000/dyf/fys-Multi-tenant into 6170 2025-09-29 09:24:52 +08:00
d6520d777a 发送信息和告警故障4 2025-09-29 09:17:20 +08:00
1898fe5db9 Merge branch '6170' into dyf-device 2025-09-28 18:19:21 +08:00
7d56e2e80e 发送信息和告警故障3 2025-09-28 17:18:47 +08:00
233e0e32b0 发送信息和告警故障2 2025-09-28 16:19:28 +08:00
5230a95865 自动报警 2025-09-28 15:28:19 +08:00
461fd9364c Merge remote-tracking branch 'upstream/6170' into 6170 2025-09-27 15:40:39 +08:00
ad81647939 发送信息和告警故障 2025-09-27 15:40:31 +08:00
42 changed files with 632 additions and 169 deletions

View File

@ -3,6 +3,7 @@ package com.fuyuanshen;
import org.springframework.boot.SpringApplication; import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.metrics.buffering.BufferingApplicationStartup; import org.springframework.boot.context.metrics.buffering.BufferingApplicationStartup;
import org.springframework.scheduling.annotation.EnableScheduling;
/** /**
* 启动程序 * 启动程序
@ -10,6 +11,7 @@ import org.springframework.boot.context.metrics.buffering.BufferingApplicationSt
* @author Lion Li * @author Lion Li
*/ */
@SpringBootApplication @SpringBootApplication
@EnableScheduling
public class DromaraApplication { public class DromaraApplication {
public static void main(String[] args) { public static void main(String[] args) {

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()); List<SystemVersionDto> list = JSON.parseArray(versionJson, SystemVersionDto.class);
d.setDictValue(""); // 或者 d.setDictValue(d.getDictValue());
d.setRemark(""); // 下载地址留空
return; // 跳过
}
// 2. 正常赋值
d.setDictValue(arr[0].trim()); // 版本号
d.setRemark(arr[1].trim()); // 下载地址
});
return R.ok(list); return R.ok(list);
} }

View File

@ -6,6 +6,7 @@ import com.fuyuanshen.app.domain.vo.APPDeviceTypeVo;
import com.fuyuanshen.common.core.domain.R; import com.fuyuanshen.common.core.domain.R;
import com.fuyuanshen.common.mybatis.core.page.PageQuery; import com.fuyuanshen.common.mybatis.core.page.PageQuery;
import com.fuyuanshen.common.mybatis.core.page.TableDataInfo; import com.fuyuanshen.common.mybatis.core.page.TableDataInfo;
import com.fuyuanshen.common.satoken.utils.AppLoginHelper;
import com.fuyuanshen.common.web.core.BaseController; import com.fuyuanshen.common.web.core.BaseController;
import com.fuyuanshen.equipment.domain.Device; import com.fuyuanshen.equipment.domain.Device;
import com.fuyuanshen.equipment.domain.dto.AppDeviceBo; import com.fuyuanshen.equipment.domain.dto.AppDeviceBo;
@ -53,7 +54,8 @@ public class AppDeviceController extends BaseController {
*/ */
@DeleteMapping("/unBind") @DeleteMapping("/unBind")
public R<Void> unBind(Long id) { public R<Void> unBind(Long id) {
return toAjax(appDeviceService.unBindDevice(id)); Long userId = AppLoginHelper.getUserId();
return toAjax(appDeviceService.unBindDevice(id,userId,0));
} }
/** /**

View File

@ -5,6 +5,7 @@ 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.exception.ServiceException;
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;
@ -17,6 +18,8 @@ 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.util.List;
/** /**
* BJQ6170设备控制类 * BJQ6170设备控制类
*/ */
@ -82,6 +85,8 @@ public class AppDeviceBJQController extends BaseController {
return R.ok(); return R.ok();
} }
/** /**
* 灯光模式 * 灯光模式
* 0关灯1强光模式2弱光模式, 3爆闪模式, 4泛光模式 * 0关灯1强光模式2弱光模式, 3爆闪模式, 4泛光模式

View File

@ -9,15 +9,24 @@ import com.fuyuanshen.common.log.annotation.Log;
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.web.core.BaseController; import com.fuyuanshen.common.web.core.BaseController;
import com.fuyuanshen.customer.mapper.CustomerMapper;
import com.fuyuanshen.equipment.domain.DeviceType;
import com.fuyuanshen.equipment.domain.dto.AppDeviceSendMsgBo; import com.fuyuanshen.equipment.domain.dto.AppDeviceSendMsgBo;
import com.fuyuanshen.equipment.domain.form.DeviceForm;
import com.fuyuanshen.equipment.mapper.DeviceMapper;
import com.fuyuanshen.equipment.service.DeviceService;
import com.fuyuanshen.equipment.service.DeviceTypeService;
import com.fuyuanshen.web.domain.Dto.DeviceXinghanInstructDto; import com.fuyuanshen.web.domain.Dto.DeviceXinghanInstructDto;
import com.fuyuanshen.web.service.device.DeviceBJQBizService; import com.fuyuanshen.web.service.device.DeviceBJQBizService;
import com.fuyuanshen.web.service.device.DeviceXinghanBizService; import com.fuyuanshen.web.service.device.DeviceXinghanBizService;
import io.swagger.v3.oas.annotations.Operation;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import org.springframework.validation.annotation.Validated; 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.util.List;
/** /**
* HBY670设备控制类 * HBY670设备控制类
*/ */
@ -28,6 +37,7 @@ import org.springframework.web.multipart.MultipartFile;
public class AppDeviceXinghanController extends BaseController { public class AppDeviceXinghanController extends BaseController {
private final DeviceXinghanBizService appDeviceService; private final DeviceXinghanBizService appDeviceService;
private final DeviceService deviceService;
/** /**
* 人员信息登记 * 人员信息登记
*/ */
@ -113,4 +123,23 @@ public class AppDeviceXinghanController extends BaseController {
return R.ok(); return R.ok();
} }
@GetMapping(value = "/typeAll")
@Operation(summary = "查询所有设备类型")
public R<List<DeviceType>> queryDeviceTypes() {
List<DeviceType> deviceTypes = appDeviceService.queryDeviceTypes();
return R.ok(deviceTypes);
}
// @Log("新增设备")
@Operation(summary = "新增设备")
@PostMapping(value = "/add")
public R<Void> addDevice(@RequestBody DeviceForm deviceForm) {
try {
appDeviceService.addDevice(deviceForm);
} catch (Exception e) {
return R.fail(e.getMessage());
}
return R.ok();
}
} }

View File

@ -3,6 +3,8 @@ package com.fuyuanshen.app.domain.dto;
import lombok.Data; import lombok.Data;
import org.springframework.web.multipart.MultipartFile; import org.springframework.web.multipart.MultipartFile;
import java.util.List;
@Data @Data
public class AppDeviceLogoUploadDto { public class AppDeviceLogoUploadDto {
@ -14,5 +16,13 @@ public class AppDeviceLogoUploadDto {
*/ */
private MultipartFile file; private MultipartFile file;
// /**
// * 文件
// */
// private List<MultipartFile> files;
private List<Long> deviceIds;
private Integer chunkSize; private Integer chunkSize;
} }

View File

@ -73,10 +73,11 @@ public class AppDeviceShareService {
private static void buildDeviceStatus(AppDeviceShareVo item) { private static void buildDeviceStatus(AppDeviceShareVo item) {
// 设备在线状态 // 设备在线状态
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 (StringUtils.isNotBlank(onlineStatus)) { if("1".equals(onlineStatus)){
item.setOnlineStatus(1); item.setOnlineStatus(1);
} else { }else if("2".equals(onlineStatus)){
item.setOnlineStatus(2);
}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);

View File

@ -32,7 +32,7 @@ public class AppFileService {
private final IAppBusinessFileService appBusinessFileService; private final IAppBusinessFileService appBusinessFileService;
public List<AppFileVo> list(AppBusinessFileBo bo) { public List<AppFileVo> list(AppBusinessFileBo bo) {
bo.setCreateBy(AppLoginHelper.getUserId()); // bo.setCreateBy(AppLoginHelper.getUserId());
return appBusinessFileService.queryAppFileList(bo); return appBusinessFileService.queryAppFileList(bo);
} }
@ -68,7 +68,7 @@ public class AppFileService {
public Boolean delete(Long[] ids) { public Boolean delete(Long[] ids) {
AppBusinessFileBo bo = new AppBusinessFileBo(); AppBusinessFileBo bo = new AppBusinessFileBo();
bo.setCreateBy(AppLoginHelper.getUserId()); // bo.setCreateBy(AppLoginHelper.getUserId());
bo.setIds(List.of(ids)); bo.setIds(List.of(ids));
List<AppBusinessFileVo> appBusinessFileVos = appBusinessFileService.queryList(bo); List<AppBusinessFileVo> appBusinessFileVos = appBusinessFileService.queryList(bo);
List<Long> fileIds = appBusinessFileVos.stream().map(AppBusinessFileVo::getFileId).toList(); List<Long> fileIds = appBusinessFileVos.stream().map(AppBusinessFileVo::getFileId).toList();

View File

@ -65,13 +65,22 @@ public class RedisKeyExpirationListener implements MessageListener {
if (lockInfo != null) { if (lockInfo != null) {
try { try {
String deviceOnlineStatusRedisKey = GlobalConstants.GLOBAL_REDIS_KEY+ DEVICE_KEY_PREFIX+ message + DeviceRedisKeyConstants.DEVICE_ONLINE_STATUS_KEY_PREFIX ; String deviceOnlineStatusRedisKey = GlobalConstants.GLOBAL_REDIS_KEY+ DEVICE_KEY_PREFIX+ message + DeviceRedisKeyConstants.DEVICE_ONLINE_STATUS_KEY_PREFIX ;
// String deviceOnlineStatusRedis = RedisUtils.getCacheObject(deviceOnlineStatusRedisKey);
// if(StringUtils.isBlank(deviceOnlineStatusRedis)){
// UpdateWrapper<Device> deviceUpdateWrapper = new UpdateWrapper<>();
// deviceUpdateWrapper.eq("device_imei", element);
// deviceUpdateWrapper.set("online_status", 0);
// deviceMapper.update(deviceUpdateWrapper);
// }else{
// RedisUtils.deleteObject(deviceOnlineStatusRedisKey);
// }
UpdateWrapper<Device> deviceUpdateWrapper = new UpdateWrapper<>();
deviceUpdateWrapper.eq("device_imei", element);
deviceUpdateWrapper.set("online_status", 0);
deviceMapper.update(deviceUpdateWrapper);
String deviceOnlineStatusRedis = RedisUtils.getCacheObject(deviceOnlineStatusRedisKey); String deviceOnlineStatusRedis = RedisUtils.getCacheObject(deviceOnlineStatusRedisKey);
if(StringUtils.isBlank(deviceOnlineStatusRedis)){ if(StringUtils.isNotBlank(deviceOnlineStatusRedis)){
UpdateWrapper<Device> deviceUpdateWrapper = new UpdateWrapper<>();
deviceUpdateWrapper.eq("device_imei", element);
deviceUpdateWrapper.set("online_status", 0);
deviceMapper.update(deviceUpdateWrapper);
}else{
RedisUtils.deleteObject(deviceOnlineStatusRedisKey); RedisUtils.deleteObject(deviceOnlineStatusRedisKey);
} }
} finally { } finally {

View File

@ -48,17 +48,18 @@ public class ReceiverMessageHandler implements MessageHandler {
} }
String[] subStr = receivedTopic.split("/"); String[] subStr = receivedTopic.split("/");
String deviceImei = subStr[1]; String deviceImei = subStr[1];
String state = payloadDict.getStr("state");
Object[] convertArr = ImageToCArrayConverter.convertByteStringToMixedObjectArray(state);
if(StringUtils.isNotBlank(deviceImei)){ if(StringUtils.isNotBlank(deviceImei)){
String queueKey = MqttMessageQueueConstants.MQTT_MESSAGE_QUEUE_KEY; String queueKey = MqttMessageQueueConstants.MQTT_MESSAGE_QUEUE_KEY;
String dedupKey = MqttMessageQueueConstants.MQTT_MESSAGE_DEDUP_KEY; String dedupKey = MqttMessageQueueConstants.MQTT_MESSAGE_DEDUP_KEY;
RedisUtils.offerDeduplicated(queueKey,dedupKey,deviceImei, Duration.ofHours(24)); RedisUtils.offerDeduplicated(queueKey,dedupKey,deviceImei, Duration.ofHours(24));
//在线状态 //在线状态
String deviceOnlineStatusRedisKey = GlobalConstants.GLOBAL_REDIS_KEY+ DEVICE_KEY_PREFIX+ deviceImei + DeviceRedisKeyConstants.DEVICE_ONLINE_STATUS_KEY_PREFIX ; String deviceOnlineStatusRedisKey = GlobalConstants.GLOBAL_REDIS_KEY+ DEVICE_KEY_PREFIX+ deviceImei + DeviceRedisKeyConstants.DEVICE_ONLINE_STATUS_KEY_PREFIX ;
RedisUtils.setCacheObject(deviceOnlineStatusRedisKey, "1", Duration.ofSeconds(120)); RedisUtils.setCacheObject(deviceOnlineStatusRedisKey, "1", Duration.ofSeconds(360));
} }
String state = payloadDict.getStr("state");
Object[] convertArr = ImageToCArrayConverter.convertByteStringToMixedObjectArray(state);
if (convertArr.length > 0) { if (convertArr.length > 0) {
Byte val1 = (Byte) convertArr[0]; Byte val1 = (Byte) convertArr[0];

View File

@ -57,12 +57,17 @@ 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;
String sendMessageIng = GLOBAL_REDIS_KEY+ DEVICE_KEY_PREFIX + context.getDeviceImei() + ":messageSending";
// 存储到Redis if ("1".equals(convertValue)) {
RedisUtils.setCacheObject(deviceRedisKey, convertValue); RedisUtils.setCacheObject(sendMessageIng, "1", Duration.ofDays(1));
// 存储到Redis
RedisUtils.setCacheObject(deviceRedisKey, "1");
}else if ("0".equals(convertValue)){
RedisUtils.deleteObject(sendMessageIng);
RedisUtils.deleteObject(deviceRedisKey);
}
} }
RedisUtils.setCacheObject(functionAccess, FunctionAccessStatus.OK.getCode(), Duration.ofSeconds(20)); RedisUtils.setCacheObject(functionAccess, FunctionAccessStatus.OK.getCode(), Duration.ofSeconds(20));
// 保存告警信息 // 保存告警信息
String deviceImei = context.getDeviceImei(); String deviceImei = context.getDeviceImei();
// 设备告警状态 0:解除告警 1:报警产生 // 设备告警状态 0:解除告警 1:报警产生

View File

@ -56,7 +56,11 @@ public class BjqLocationDataRule implements MqttMessageRule {
// Latitude, longitude // Latitude, longitude
String latitude = convertArr[1].toString(); String latitude = convertArr[1].toString();
String longitude = convertArr[2].toString(); String longitude = convertArr[2].toString();
// 判断 latitude 和 longitude 是否都为 0
if ("0".equals(latitude) && "0".equals(longitude)) {
log.info("位置信息为0不存储到Redis: device={}, lat={}, lon={}", context.getDeviceImei(), latitude, longitude);
return;
}
// 异步发送经纬度到Redis // 异步发送经纬度到Redis
asyncSendLocationToRedisWithFuture(context.getDeviceImei(), latitude, longitude); asyncSendLocationToRedisWithFuture(context.getDeviceImei(), latitude, longitude);
// 异步保存数据 // 异步保存数据
@ -122,6 +126,7 @@ public class BjqLocationDataRule implements MqttMessageRule {
if (StringUtils.isBlank(latitude) || StringUtils.isBlank(longitude)) { if (StringUtils.isBlank(latitude) || StringUtils.isBlank(longitude)) {
return; return;
} }
// String[] latArr = latitude.split("\\."); // String[] latArr = latitude.split("\\.");
// String[] lonArr = longitude.split("\\."); // String[] lonArr = longitude.split("\\.");
// // 将位置信息存储到Redis中 // // 将位置信息存储到Redis中

View File

@ -1,8 +1,16 @@
package com.fuyuanshen.global.mqtt.rule.bjq; package com.fuyuanshen.global.mqtt.rule.bjq;
import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.fuyuanshen.common.core.constant.GlobalConstants; import com.fuyuanshen.common.core.constant.GlobalConstants;
import com.fuyuanshen.common.core.utils.StringUtils; import com.fuyuanshen.common.core.utils.StringUtils;
import com.fuyuanshen.common.core.utils.date.DurationUtils;
import com.fuyuanshen.common.redis.utils.RedisUtils; import com.fuyuanshen.common.redis.utils.RedisUtils;
import com.fuyuanshen.equipment.domain.Device;
import com.fuyuanshen.equipment.domain.bo.DeviceAlarmBo;
import com.fuyuanshen.equipment.domain.vo.DeviceAlarmVo;
import com.fuyuanshen.equipment.service.DeviceService;
import com.fuyuanshen.equipment.service.IDeviceAlarmService;
import com.fuyuanshen.global.mqtt.base.MqttMessageRule; import com.fuyuanshen.global.mqtt.base.MqttMessageRule;
import com.fuyuanshen.global.mqtt.base.MqttRuleContext; import com.fuyuanshen.global.mqtt.base.MqttRuleContext;
import com.fuyuanshen.global.mqtt.constants.DeviceRedisKeyConstants; import com.fuyuanshen.global.mqtt.constants.DeviceRedisKeyConstants;
@ -13,9 +21,11 @@ import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import java.time.Duration; import java.time.Duration;
import java.util.Date;
import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletableFuture;
import static com.fuyuanshen.common.core.constant.GlobalConstants.FUNCTION_ACCESS_KEY; import static com.fuyuanshen.common.core.constant.GlobalConstants.FUNCTION_ACCESS_KEY;
import static com.fuyuanshen.common.core.constant.GlobalConstants.GLOBAL_REDIS_KEY;
import static com.fuyuanshen.global.mqtt.constants.DeviceRedisKeyConstants.*; import static com.fuyuanshen.global.mqtt.constants.DeviceRedisKeyConstants.*;
/** /**
@ -26,6 +36,10 @@ import static com.fuyuanshen.global.mqtt.constants.DeviceRedisKeyConstants.*;
@Slf4j @Slf4j
public class BjqModeRule implements MqttMessageRule { public class BjqModeRule implements MqttMessageRule {
private final DeviceService deviceService;
private final IDeviceAlarmService deviceAlarmService;
@Override @Override
public String getCommandType() { public String getCommandType() {
return LightingCommandTypeConstants.LIGHT_MODE; return LightingCommandTypeConstants.LIGHT_MODE;
@ -39,14 +53,36 @@ public class BjqModeRule implements MqttMessageRule {
String mainLightMode = convertArr[1].toString(); String mainLightMode = convertArr[1].toString();
String batteryRemainingTime = convertArr[2].toString(); String batteryRemainingTime = convertArr[2].toString();
if(StringUtils.isNotBlank(mainLightMode)){ if (StringUtils.isNotBlank(mainLightMode)) {
if("0".equals(mainLightMode)){ log.info("设备离线mainLightMode{}", mainLightMode);
String deviceOnlineStatusRedisKey = GlobalConstants.GLOBAL_REDIS_KEY+ DEVICE_KEY_PREFIX+ context.getDeviceImei() + DeviceRedisKeyConstants.DEVICE_ONLINE_STATUS_KEY_PREFIX ; if ("0".equals(mainLightMode)) {
RedisUtils.setCacheObject(deviceOnlineStatusRedisKey, "0", Duration.ofSeconds(60*15));
// 设备离线
String deviceOnlineStatusRedisKey = GlobalConstants.GLOBAL_REDIS_KEY + DEVICE_KEY_PREFIX + context.getDeviceImei() + DeviceRedisKeyConstants.DEVICE_ONLINE_STATUS_KEY_PREFIX;
RedisUtils.setCacheObject(deviceOnlineStatusRedisKey, "0");
String sendMessageIng = GLOBAL_REDIS_KEY + DEVICE_KEY_PREFIX + context.getDeviceImei() + ":messageSending";
String messageSendingValue = RedisUtils.getCacheObject(sendMessageIng);
if ("1".equals(messageSendingValue)) {
// 设置为故障状态
RedisUtils.setCacheObject(deviceOnlineStatusRedisKey, "2");
UpdateWrapper<Device> updateWrapper = new UpdateWrapper<>();
updateWrapper.eq("device_imei", context.getDeviceImei());
updateWrapper.set("online_status", 2);
deviceService.update(updateWrapper);
RedisUtils.deleteObject(sendMessageIng);
// 解除告警
String deviceRedisKey = GlobalConstants.GLOBAL_REDIS_KEY + DeviceRedisKeyConstants.DEVICE_KEY_PREFIX + context.getDeviceImei() + DEVICE_ALARM_KEY_PREFIX;
if (RedisUtils.getCacheObject(deviceRedisKey) != null) {
RedisUtils.deleteObject(deviceRedisKey);
}
cancelAlarm(context.getDeviceImei());
}
} }
// 发送设备状态和位置信息到Redis // 发送设备状态和位置信息到Redis
syncSendDeviceDataToRedisWithFuture(context.getDeviceImei(),mainLightMode); syncSendDeviceDataToRedisWithFuture(context.getDeviceImei(), mainLightMode);
String deviceRedisKey = GlobalConstants.GLOBAL_REDIS_KEY+DeviceRedisKeyConstants.DEVICE_KEY_PREFIX + context.getDeviceImei() + DEVICE_LIGHT_BRIGHTNESS_KEY_PREFIX; String deviceRedisKey = GlobalConstants.GLOBAL_REDIS_KEY + DeviceRedisKeyConstants.DEVICE_KEY_PREFIX + context.getDeviceImei() + DEVICE_LIGHT_BRIGHTNESS_KEY_PREFIX;
// 存储到Redis // 存储到Redis
RedisUtils.setCacheObject(deviceRedisKey, batteryRemainingTime); RedisUtils.setCacheObject(deviceRedisKey, batteryRemainingTime);
@ -63,13 +99,13 @@ public class BjqModeRule implements MqttMessageRule {
* *
* @param deviceImei 设备IMEI * @param deviceImei 设备IMEI
*/ */
public void syncSendDeviceDataToRedisWithFuture(String deviceImei,Object convertValue) { public void syncSendDeviceDataToRedisWithFuture(String deviceImei, Object convertValue) {
// CompletableFuture.runAsync(() -> { // CompletableFuture.runAsync(() -> {
// //
// }); // });
try { try {
// 将设备状态信息存储到Redis中 // 将设备状态信息存储到Redis中
String deviceRedisKey = GlobalConstants.GLOBAL_REDIS_KEY+DeviceRedisKeyConstants.DEVICE_KEY_PREFIX + deviceImei + DEVICE_LIGHT_MODE_KEY_PREFIX; String deviceRedisKey = GlobalConstants.GLOBAL_REDIS_KEY + DeviceRedisKeyConstants.DEVICE_KEY_PREFIX + deviceImei + DEVICE_LIGHT_MODE_KEY_PREFIX;
// 存储到Redis // 存储到Redis
RedisUtils.setCacheObject(deviceRedisKey, convertValue.toString()); RedisUtils.setCacheObject(deviceRedisKey, convertValue.toString());
@ -80,5 +116,29 @@ public class BjqModeRule implements MqttMessageRule {
} }
/**
* 解除告警
*
* @param deviceImei 设备IMEI
*/
public void cancelAlarm(String deviceImei) {
DeviceAlarmVo deviceAlarmVo = deviceAlarmService.queryLatestByDeviceImei(deviceImei);
DeviceAlarmBo deviceAlarmBo = new DeviceAlarmBo();
if (deviceAlarmVo != null) {
if (deviceAlarmVo.getFinishTime() == null) {
BeanUtil.copyProperties(deviceAlarmVo, deviceAlarmBo);
deviceAlarmBo.setFinishTime(new Date());
String durationBetween = DurationUtils.getDurationBetween(deviceAlarmVo.getStartTime(), deviceAlarmBo.getFinishTime());
deviceAlarmBo.setDurationTime(durationBetween);
// 0已处理1未处理
deviceAlarmBo.setTreatmentState(0);
// 告警状态0 解除告警, 1 告警中
deviceAlarmBo.setAlarmState(0);
deviceAlarmService.updateByBo(deviceAlarmBo);
}
}
}
} }

View File

@ -43,12 +43,23 @@ public class BjqSendMessageRule implements MqttMessageRule {
public void execute(MqttRuleContext context) { public void execute(MqttRuleContext context) {
String functionAccess = FUNCTION_ACCESS_KEY + context.getDeviceImei(); String functionAccess = FUNCTION_ACCESS_KEY + context.getDeviceImei();
try { try {
Byte val2 = (Byte) context.getConvertArr()[1];
// Byte val2 = (Byte) context.getConvertArr()[1];
String val2Str = context.getConvertArr()[1].toString();
int val2 = Integer.parseInt(val2Str);
System.out.println("收到设备信息命令:"+val2);
if (val2 == 100) { if (val2 == 100) {
RedisUtils.setCacheObject(functionAccess, FunctionAccessStatus.OK.getCode(), Duration.ofSeconds(20)); RedisUtils.setCacheObject(functionAccess, FunctionAccessStatus.OK.getCode(), Duration.ofSeconds(20));
return; return;
} }
if(val2==200){
String sendMessageIng = GLOBAL_REDIS_KEY+ DEVICE_KEY_PREFIX + context.getDeviceImei() + ":messageSending";
RedisUtils.deleteObject(sendMessageIng);
return;
}
String data = RedisUtils.getCacheObject(GLOBAL_REDIS_KEY+ DEVICE_KEY_PREFIX + context.getDeviceImei() + ":app_send_message_data"); String data = RedisUtils.getCacheObject(GLOBAL_REDIS_KEY+ DEVICE_KEY_PREFIX + context.getDeviceImei() + ":app_send_message_data");
if (StringUtils.isEmpty(data)) { if (StringUtils.isEmpty(data)) {
return; return;
@ -61,7 +72,7 @@ public class BjqSendMessageRule implements MqttMessageRule {
ArrayList<Integer> intData = new ArrayList<>(); ArrayList<Integer> intData = new ArrayList<>();
intData.add(6); intData.add(6);
intData.add((int) val2); intData.add(val2);
ImageToCArrayConverter.buildArr(convertHexToDecimal(specificChunk), intData); ImageToCArrayConverter.buildArr(convertHexToDecimal(specificChunk), intData);
intData.add(0); intData.add(0);
intData.add(0); intData.add(0);

View File

@ -64,7 +64,7 @@ public class XinghanBootLogoRule implements MqttMessageRule {
// --- 去重 START --- // --- 去重 START ---
String dedupKey = "xd:MSG:LOGO:" + ctx.getDeviceImei() + ":" + respText; String dedupKey = "xd:MSG:LOGO:" + ctx.getDeviceImei() + ":" + respText;
boolean first = RedisUtils.setObjectIfAbsent(dedupKey, "1", Duration.ofSeconds(10)); boolean first = RedisUtils.setObjectIfAbsent(dedupKey, "1", Duration.ofSeconds(3));
if (!first) { if (!first) {
log.warn("重复消息丢弃 {}", dedupKey); log.warn("重复消息丢弃 {}", dedupKey);
return; return;

View File

@ -57,7 +57,7 @@ public class XinghanSendAlarmMessageRule implements MqttMessageRule {
log.info("设备上报紧急通知握手: {} ", respText); log.info("设备上报紧急通知握手: {} ", respText);
// --- 去重 START --- // --- 去重 START ---
String dedupKey = "xd:ALARM:dedup:" + ctx.getDeviceImei() + ":" + respText; String dedupKey = "xd:ALARM:dedup:" + ctx.getDeviceImei() + ":" + respText;
boolean first = RedisUtils.setObjectIfAbsent(dedupKey, "1", Duration.ofSeconds(10)); boolean first = RedisUtils.setObjectIfAbsent(dedupKey, "1", Duration.ofSeconds(3));
if (!first) { if (!first) {
log.warn("重复消息丢弃 {}", dedupKey); log.warn("重复消息丢弃 {}", dedupKey);
return; return;

View File

@ -17,10 +17,7 @@ import org.springframework.stereotype.Component;
import java.nio.charset.Charset; import java.nio.charset.Charset;
import java.time.Duration; import java.time.Duration;
import java.util.ArrayList; import java.util.*;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import static com.fuyuanshen.common.core.constant.GlobalConstants.FUNCTION_ACCESS_KEY; import static com.fuyuanshen.common.core.constant.GlobalConstants.FUNCTION_ACCESS_KEY;
import static com.fuyuanshen.common.core.constant.GlobalConstants.GLOBAL_REDIS_KEY; import static com.fuyuanshen.common.core.constant.GlobalConstants.GLOBAL_REDIS_KEY;
@ -42,6 +39,12 @@ public class XinghanSendMsgRule implements MqttMessageRule {
@Override @Override
public String getCommandType() { public String getCommandType() {
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);
// 三种等价的写法
Integer[] array1 = list.toArray(new Integer[0]);
Integer[] array2 = list.toArray(size -> new Integer[size]);
return XingHanCommandTypeConstants.XingHan_ESEND_MSG; return XingHanCommandTypeConstants.XingHan_ESEND_MSG;
} }
@ -57,7 +60,7 @@ public class XinghanSendMsgRule implements MqttMessageRule {
// --- 去重 START --- // --- 去重 START ---
String dedupKey = "xd:MSG:dedup:" + ctx.getDeviceImei() + ":" + respText; String dedupKey = "xd:MSG:dedup:" + ctx.getDeviceImei() + ":" + respText;
boolean first = RedisUtils.setObjectIfAbsent(dedupKey, "1", Duration.ofSeconds(10)); boolean first = RedisUtils.setObjectIfAbsent(dedupKey, "1", Duration.ofSeconds(3));
if (!first) { if (!first) {
log.warn("重复消息丢弃 {}", dedupKey); log.warn("重复消息丢弃 {}", dedupKey);
return; return;

View File

@ -106,16 +106,22 @@ public class MqttMessageConsumer {
// .set("online_status", 1); // .set("online_status", 1);
// deviceMapper.update(updateWrapper); // deviceMapper.update(updateWrapper);
// } // }
QueryWrapper<Device> queryWrapper = new QueryWrapper<>(); // QueryWrapper<Device> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("device_imei", message); // queryWrapper.eq("device_imei", message);
queryWrapper.eq("online_status", 1); // queryWrapper.eq("online_status", 1);
Long count = deviceMapper.selectCount(queryWrapper); // Long count = deviceMapper.selectCount(queryWrapper);
if(count == 0){ // if(count == 0){
UpdateWrapper<Device> updateWrapper = new UpdateWrapper<>(); // UpdateWrapper<Device> updateWrapper = new UpdateWrapper<>();
updateWrapper.eq("device_imei", message) // updateWrapper.eq("device_imei", message)
.set("online_status", 1); // .eq("online_status", 0)
deviceMapper.update(updateWrapper); // .set("online_status", 1);
} // deviceMapper.update(updateWrapper);
// }
UpdateWrapper<Device> updateWrapper = new UpdateWrapper<>();
updateWrapper.eq("device_imei", message)
.in("online_status", 0,2)
.set("online_status", 1);
int update = deviceMapper.update(updateWrapper);
// 模拟业务处理耗时 // 模拟业务处理耗时
// Thread.sleep(200); // Thread.sleep(200);

View File

@ -0,0 +1,43 @@
package com.fuyuanshen.global.queue;// ScheduledTasks.java
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.fuyuanshen.common.core.utils.StringUtils;
import com.fuyuanshen.common.redis.utils.RedisUtils;
import com.fuyuanshen.equipment.domain.Device;
import com.fuyuanshen.equipment.mapper.DeviceMapper;
import com.fuyuanshen.global.mqtt.constants.DeviceRedisKeyConstants;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import java.util.List;
import static com.fuyuanshen.common.core.constant.GlobalConstants.GLOBAL_REDIS_KEY;
import static com.fuyuanshen.global.mqtt.constants.DeviceRedisKeyConstants.DEVICE_KEY_PREFIX;
@Component
public class OnlineStatusTask {
@Autowired
private DeviceMapper deviceMapper;
// 使用cron表达式每分钟的第0秒执行
@Scheduled(cron = "0 */3 * * * ?")
public void cronTask() {
QueryWrapper<Device> queryWrapper = new QueryWrapper<>();
List<Device> devices = deviceMapper.selectList(queryWrapper);
devices.forEach(item -> {
String onlineStatusKey = GLOBAL_REDIS_KEY + DEVICE_KEY_PREFIX + item.getDeviceImei() + DeviceRedisKeyConstants.DEVICE_ONLINE_STATUS_KEY_PREFIX;
String status = RedisUtils.getCacheObject(onlineStatusKey);
String onlineStatus = item.getOnlineStatus()==null?"0" : item.getOnlineStatus().toString();
if("1".equals(onlineStatus) || "2".equals(onlineStatus)){
if(StringUtils.isBlank(status) || "0".equals(status)){
UpdateWrapper<Device> updateWrapper = new UpdateWrapper<>();
updateWrapper.eq("id", item.getId());
updateWrapper.set("online_status", 0);
deviceMapper.update(updateWrapper);
}
}
});
}
}

View File

@ -82,6 +82,22 @@ public class DeviceBJQController extends BaseController {
return R.ok(); return R.ok();
} }
/**
* 批量上传设备logo图片
*/
@PostMapping("/batchUploadLogo")
@FunctionAccessAnnotation("batchUploadLogo")
public R<Void> batchUploadLogo(@Validated @ModelAttribute AppDeviceLogoUploadDto bo) {
MultipartFile file = bo.getFile();
if(file.getSize()>1024*1024*2){
return R.warn("图片不能大于2M");
}
appDeviceService.batchUploadLogo(bo);
return R.ok();
}
/** /**
* 灯光模式 * 灯光模式
* 0关灯1强光模式2弱光模式, 3爆闪模式, 4泛光模式 * 0关灯1强光模式2弱光模式, 3爆闪模式, 4泛光模式

View File

@ -61,7 +61,7 @@ public class DeviceDebugController extends BaseController {
@Log(title = "批量上传文件") @Log(title = "批量上传文件")
@PostMapping("/addFile") @PostMapping("/addFile")
public R<Void> uploadFile(@Validated @ModelAttribute AppFileDto bo) throws IOException { public R<Void> uploadFile(@Validated @ModelAttribute AppFileDto bo) throws IOException {
return toAjax(deviceDebugService.addFileHash(bo)); return toAjax(deviceDebugService.addFileHash(bo,true));
} }
/** /**
@ -113,7 +113,7 @@ public class DeviceDebugController extends BaseController {
appFileDto.setDeviceIds(new Long[]{ bo.getDeviceId() }); appFileDto.setDeviceIds(new Long[]{ bo.getDeviceId() });
appFileDto.setFileType(1L); appFileDto.setFileType(1L);
appFileDto.setFiles(bo.getExplanationFiles()); appFileDto.setFiles(bo.getExplanationFiles());
deviceDebugService.addFileHash(appFileDto); deviceDebugService.addFileHash(appFileDto,false);
} }
// 修改上传设备参数 // 修改上传设备参数
if (bo.getParameterFiles() != null) { if (bo.getParameterFiles() != null) {
@ -121,8 +121,9 @@ public class DeviceDebugController extends BaseController {
appFileDto.setDeviceIds(new Long[]{ bo.getDeviceId() }); appFileDto.setDeviceIds(new Long[]{ bo.getDeviceId() });
appFileDto.setFileType(2L); appFileDto.setFileType(2L);
appFileDto.setFiles(bo.getParameterFiles()); appFileDto.setFiles(bo.getParameterFiles());
deviceDebugService.addFileHash(appFileDto); deviceDebugService.addFileHash(appFileDto,false);
} }
deviceDebugService.delFile(bo.getFileIds());
// 修改操作视频 // 修改操作视频
if (bo.getVideoUrl().isEmpty()) { if (bo.getVideoUrl().isEmpty()) {
AppOperationVideoBo appOperationVideoBo = new AppOperationVideoBo(); AppOperationVideoBo appOperationVideoBo = new AppOperationVideoBo();

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

@ -31,4 +31,6 @@ public class DeviceDebugEditDto {
* 视频链接 * 视频链接
*/ */
private String videoUrl; private String videoUrl;
private List<Long> fileIds;
} }

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

@ -15,6 +15,7 @@ import com.fuyuanshen.app.domain.vo.AppPersonnelInfoVo;
import com.fuyuanshen.app.mapper.AppPersonnelInfoMapper; import com.fuyuanshen.app.mapper.AppPersonnelInfoMapper;
import com.fuyuanshen.app.mapper.AppPersonnelInfoRecordsMapper; import com.fuyuanshen.app.mapper.AppPersonnelInfoRecordsMapper;
import com.fuyuanshen.common.core.constant.GlobalConstants; import com.fuyuanshen.common.core.constant.GlobalConstants;
import com.fuyuanshen.common.core.domain.R;
import com.fuyuanshen.common.core.exception.ServiceException; import com.fuyuanshen.common.core.exception.ServiceException;
import com.fuyuanshen.common.core.utils.*; import com.fuyuanshen.common.core.utils.*;
import com.fuyuanshen.common.redis.utils.RedisUtils; import com.fuyuanshen.common.redis.utils.RedisUtils;
@ -108,7 +109,8 @@ public class DeviceBJQBizService {
log.info("发送信息设备发送信息失败:{}" ,deviceId); log.info("发送信息设备发送信息失败:{}" ,deviceId);
throw new ServiceException("发送指令失败"); throw new ServiceException("发送指令失败");
} }
//发送消息
messageSending(device.getDeviceImei());
} }
@ -171,10 +173,13 @@ public class DeviceBJQBizService {
} }
//设备在线状态 //设备在线状态
String onlineStatus = RedisUtils.getCacheObject(GLOBAL_REDIS_KEY+ DEVICE_KEY_PREFIX + device.getDeviceImei()+ DeviceRedisKeyConstants.DEVICE_ONLINE_STATUS_KEY_PREFIX); 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); if("1".equals(onlineStatus)){
vo.setOnlineStatus(1);
}else if("2".equals(onlineStatus)){
vo.setOnlineStatus(2);
}else{ }else{
vo.setOnlineStatus(0); vo.setOnlineStatus(0);
} }
String deviceStatus = RedisUtils.getCacheObject(GLOBAL_REDIS_KEY+ DEVICE_KEY_PREFIX + device.getDeviceImei() + DeviceRedisKeyConstants.DEVICE_STATUS_KEY_PREFIX); String deviceStatus = RedisUtils.getCacheObject(GLOBAL_REDIS_KEY+ DEVICE_KEY_PREFIX + device.getDeviceImei() + DeviceRedisKeyConstants.DEVICE_STATUS_KEY_PREFIX);
// 获取电量 // 获取电量
@ -250,8 +255,8 @@ public class DeviceBJQBizService {
ArrayList<Integer> intData = new ArrayList<>(); ArrayList<Integer> intData = new ArrayList<>();
intData.add(2); intData.add(2);
buildArr(convertHexToDecimal(unitName), intData); buildArr(convertHexToDecimal(unitName), intData);
buildArr(convertHexToDecimal(position), intData);
buildArr(convertHexToDecimal(name), intData); buildArr(convertHexToDecimal(name), intData);
buildArr(convertHexToDecimal(position), intData);
buildArr(convertHexToDecimal(id), intData); buildArr(convertHexToDecimal(id), intData);
intData.add(0); intData.add(0);
intData.add(0); intData.add(0);
@ -333,7 +338,10 @@ public class DeviceBJQBizService {
throw new ServiceException("设备不存在"); throw new ServiceException("设备不存在");
} }
if(getDeviceStatus(device.getDeviceImei())){ if(getDeviceStatus(device.getDeviceImei())){
throw new ServiceException(device.getDeviceName()+",设备已断开连接"); // throw new ServiceException(device.getDeviceName()+",设备已断开连接");
log.info(device.getDeviceName()+",设备已断开连接");
recordDeviceLog(device.getId(), device.getDeviceName(), "上传开机画面", device.getDeviceName()+",设备已断开连接", AppLoginHelper.getUserId());
return;
} }
MultipartFile file = bo.getFile(); MultipartFile file = bo.getFile();
@ -518,16 +526,20 @@ 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);
recordDeviceLog(device.getId(), device.getDeviceName(), "发送告警信息", bo.getSendMsg(), AppLoginHelper.getUserId()); if("0".equals(bo.getInstructValue())){
recordDeviceLog(device.getId(), device.getDeviceName(), "解除告警信息", "关闭设备", AppLoginHelper.getUserId());
}else{
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("设备发送告警信息信息失败");
} }
messageSending(device.getDeviceImei());
} }
} catch (Exception e){ } catch (Exception e){
e.printStackTrace(); e.printStackTrace();
throw new ServiceException("发送告警信息指令失败"); throw new ServiceException("发送告警信息指令失败");
@ -535,8 +547,28 @@ public class DeviceBJQBizService {
return 1; return 1;
} }
private void messageSending(String deviceImei){
String sendMessageIng = GLOBAL_REDIS_KEY+ DEVICE_KEY_PREFIX + deviceImei + ":messageSending";
RedisUtils.setCacheObject(sendMessageIng, "1", Duration.ofDays(1));
}
private boolean getDeviceStatus(String deviceImei) { private boolean getDeviceStatus(String deviceImei) {
String deviceOnlineStatusRedisKey = GlobalConstants.GLOBAL_REDIS_KEY+ DEVICE_KEY_PREFIX+ deviceImei + DeviceRedisKeyConstants.DEVICE_ONLINE_STATUS_KEY_PREFIX ; String deviceOnlineStatusRedisKey = GlobalConstants.GLOBAL_REDIS_KEY+ DEVICE_KEY_PREFIX+ deviceImei + DeviceRedisKeyConstants.DEVICE_ONLINE_STATUS_KEY_PREFIX ;
return RedisUtils.getCacheObject(deviceOnlineStatusRedisKey) == null; return RedisUtils.getCacheObject(deviceOnlineStatusRedisKey) == null;
} }
public void batchUploadLogo(AppDeviceLogoUploadDto bo) {
List<Long> deviceIds = bo.getDeviceIds();
MultipartFile file = bo.getFile();
if (deviceIds == null || deviceIds.isEmpty()) {
throw new ServiceException("请选择设备");
}
for (Long deviceId : deviceIds) {
AppDeviceLogoUploadDto dto = new AppDeviceLogoUploadDto();
dto.setDeviceId(deviceId);
dto.setFile(file);
uploadDeviceLogo(dto);
}
}
} }

View File

@ -90,9 +90,10 @@ public class DeviceBizService {
//设备在线状态 //设备在线状态
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(StringUtils.isNotBlank(onlineStatus)){ if("1".equals(onlineStatus)){
item.setOnlineStatus(1); item.setOnlineStatus(1);
}else if("2".equals(onlineStatus)){
item.setOnlineStatus(2);
}else{ }else{
item.setOnlineStatus(0); item.setOnlineStatus(0);
} }
@ -130,13 +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(StringUtils.isNotBlank(onlineStatus)){ // if("1".equals(onlineStatus)){
// item.setOnlineStatus(1);
item.setOnlineStatus(1); // }else if("2".equals(onlineStatus)){
}else{ // item.setOnlineStatus(2);
item.setOnlineStatus(0); // }else{
} // 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)){
@ -263,43 +265,63 @@ public class DeviceBizService {
if (device == null) { if (device == null) {
throw new RuntimeException("请先将设备入库!!!"); throw new RuntimeException("请先将设备入库!!!");
} }
UpdateWrapper<Device> deviceUpdateWrapper = new UpdateWrapper<>();
deviceUpdateWrapper.eq("id", device.getId())
.set("binding_user_id", null)
.set("binding_status", BindingStatusEnum.UNBOUND.getCode())
.set("binding_time", null);
deviceMapper.update(null, deviceUpdateWrapper);
if (userId == null) { // type: 0 app,1 web
userId = AppLoginHelper.getUserId(); if (type == 0) {
} QueryWrapper<AppDeviceBindRecord> bindRecordQueryWrapper = new QueryWrapper<>();
QueryWrapper<AppDeviceBindRecord> bindRecordQueryWrapper = new QueryWrapper<>(); bindRecordQueryWrapper.eq("device_id", device.getId());
bindRecordQueryWrapper.eq("device_id", device.getId());
// 设备端解绑 0:设备端解绑 1:web端解绑
if (type == 1) {
bindRecordQueryWrapper.eq("binding_user_id", userId); bindRecordQueryWrapper.eq("binding_user_id", userId);
Long count = appDeviceBindRecordMapper.selectCount(bindRecordQueryWrapper);
if (count == 0) {
throw new RuntimeException("请先绑定设备!!!");
}
if(count<2){
UpdateWrapper<Device> deviceUpdateWrapper = new UpdateWrapper<>();
deviceUpdateWrapper.eq("id", device.getId())
.set("binding_user_id", null)
.set("binding_status", BindingStatusEnum.UNBOUND.getCode())
.set("binding_time", null);
deviceMapper.update(null, deviceUpdateWrapper);
}
}else{
QueryWrapper<AppDeviceBindRecord> bindRecordQueryWrapper = new QueryWrapper<>();
bindRecordQueryWrapper.eq("device_id", device.getId());
Long count = appDeviceBindRecordMapper.selectCount(bindRecordQueryWrapper);
if (count == 0) {
throw new RuntimeException("请先绑定设备!!!");
}
UpdateWrapper<Device> deviceUpdateWrapper = new UpdateWrapper<>();
deviceUpdateWrapper.eq("id", device.getId())
.set("binding_user_id", null)
.set("binding_status", BindingStatusEnum.UNBOUND.getCode())
.set("binding_time", null);
deviceMapper.update(null, deviceUpdateWrapper);
} }
// AppDeviceBindRecord appDeviceBindRecord = appDeviceBindRecordMapper.selectOne(bindRecordQueryWrapper); QueryWrapper<AppDeviceBindRecord> brqWrapper = new QueryWrapper<>();
// if (appDeviceBindRecord != null) { brqWrapper.eq("device_id", device.getId());
// return appDeviceBindRecordMapper.deleteById(appDeviceBindRecord.getId()); if(userId != null){
// } brqWrapper.eq("binding_user_id", userId);
}
List<AppDeviceBindRecord> appDeviceBindRecordList = appDeviceBindRecordMapper.selectList(bindRecordQueryWrapper); List<AppDeviceBindRecord> appDeviceBindRecordList = appDeviceBindRecordMapper.selectList(brqWrapper);
if (CollectionUtil.isNotEmpty(appDeviceBindRecordList)) { if (CollectionUtil.isNotEmpty(appDeviceBindRecordList)) {
appDeviceBindRecordList.forEach(appDeviceBindRecord -> appDeviceBindRecordList.forEach(appDeviceBindRecord ->
appDeviceBindRecordMapper.deleteById(appDeviceBindRecord.getId())); appDeviceBindRecordMapper.deleteById(appDeviceBindRecord.getId()));
} }
AppUserVo appUserVo = appUserMapper.selectVoById(userId); AppUserVo appUserVo = appUserMapper.selectVoById(userId);
QueryWrapper<AppDeviceShare> appDeviceShareQueryWrapper = new QueryWrapper<>(); if(appUserVo != null){
appDeviceShareQueryWrapper.eq("device_id", device.getId()); QueryWrapper<AppDeviceShare> appDeviceShareQueryWrapper = new QueryWrapper<>();
appDeviceShareQueryWrapper.eq("phonenumber", appUserVo.getPhonenumber()); appDeviceShareQueryWrapper.eq("device_id", device.getId());
List<AppDeviceShare> appDeviceShareList = appDeviceShareMapper.selectList(appDeviceShareQueryWrapper); appDeviceShareQueryWrapper.eq("phonenumber", appUserVo.getPhonenumber());
if (CollectionUtil.isNotEmpty(appDeviceShareList)) { List<AppDeviceShare> appDeviceShareList = appDeviceShareMapper.selectList(appDeviceShareQueryWrapper);
appDeviceShareList.forEach(appDeviceShare -> if (CollectionUtil.isNotEmpty(appDeviceShareList)) {
appDeviceShareMapper.deleteById(appDeviceShare.getId())); appDeviceShareList.forEach(appDeviceShare ->
appDeviceShareMapper.deleteById(appDeviceShare.getId()));
}
} }
return 1; return 1;
} }
@ -373,6 +395,10 @@ public class DeviceBizService {
JSONObject jsonObject = JSONObject.parseObject(obj); JSONObject jsonObject = JSONObject.parseObject(obj);
Long timestamp = jsonObject.getLong("timestamp"); Long timestamp = jsonObject.getLong("timestamp");
LocalDate date = LocalDateTime.ofInstant(Instant.ofEpochMilli(timestamp), ZoneId.systemDefault()).toLocalDate(); LocalDate date = LocalDateTime.ofInstant(Instant.ofEpochMilli(timestamp), ZoneId.systemDefault()).toLocalDate();
String address = jsonObject.getString("address");
if(StringUtils.isBlank( address) || "[]".equals(address)){
continue;
}
if (map.containsKey(date.toString())) { if (map.containsKey(date.toString())) {
map.get(date.toString()).add(jsonObject); map.get(date.toString()).add(jsonObject);
} else { } else {

View File

@ -47,7 +47,7 @@ public class DeviceDebugService {
* @throws IOException * @throws IOException
*/ */
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
public Boolean addFileHash(AppFileDto bo) throws IOException { public Boolean addFileHash(AppFileDto bo,Boolean isBatch) throws IOException {
MultipartFile[] files = bo.getFiles(); MultipartFile[] files = bo.getFiles();
if (files == null || files.length == 0) { if (files == null || files.length == 0) {
throw new ServiceException("请选择要上传的文件"); throw new ServiceException("请选择要上传的文件");
@ -100,7 +100,7 @@ public class DeviceDebugService {
if (CollUtil.isEmpty(bizList)) { // 空集合直接返回 if (CollUtil.isEmpty(bizList)) { // 空集合直接返回
throw new ServiceException("请选择要上传的文件"); throw new ServiceException("请选择要上传的文件");
} }
return appBusinessFileService.insertBatch(bizList); return appBusinessFileService.insertBatch(bizList,isBatch);
} }
public Boolean addVideoList(AppOperationVideoBo bo){ public Boolean addVideoList(AppOperationVideoBo bo){
@ -124,6 +124,13 @@ public class DeviceDebugService {
} }
return appOperationVideoService.insertBatch(bizList); return appOperationVideoService.insertBatch(bizList);
} }
// 删除文件
public void delFile(List<Long> ids) {
// 3. 删除旧图片
if(ids != null){
appBusinessFileService.deleteWithValidByIds(ids, true);
}
}
/** /**
* 设备详情 * 设备详情

View File

@ -1,6 +1,8 @@
package com.fuyuanshen.web.service.device; package com.fuyuanshen.web.service.device;
import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.lang.UUID;
import cn.hutool.core.util.StrUtil; import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson2.JSON; import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject; import com.alibaba.fastjson2.JSONObject;
@ -19,6 +21,10 @@ import com.fuyuanshen.app.domain.vo.AppPersonnelInfoVo;
import com.fuyuanshen.app.mapper.AppPersonnelInfoMapper; import com.fuyuanshen.app.mapper.AppPersonnelInfoMapper;
import com.fuyuanshen.app.mapper.AppPersonnelInfoRecordsMapper; import com.fuyuanshen.app.mapper.AppPersonnelInfoRecordsMapper;
import com.fuyuanshen.common.core.constant.GlobalConstants; import com.fuyuanshen.common.core.constant.GlobalConstants;
import com.fuyuanshen.common.core.domain.R;
import com.fuyuanshen.common.core.domain.model.AppLoginUser;
import com.fuyuanshen.common.core.domain.model.LoginUser;
import com.fuyuanshen.common.core.exception.BadRequestException;
import com.fuyuanshen.common.core.exception.ServiceException; import com.fuyuanshen.common.core.exception.ServiceException;
import com.fuyuanshen.common.core.utils.ImageToCArrayConverter; import com.fuyuanshen.common.core.utils.ImageToCArrayConverter;
import com.fuyuanshen.common.core.utils.MapstructUtils; import com.fuyuanshen.common.core.utils.MapstructUtils;
@ -27,20 +33,26 @@ import com.fuyuanshen.common.core.utils.StringUtils;
import com.fuyuanshen.common.json.utils.JsonUtils; import com.fuyuanshen.common.json.utils.JsonUtils;
import com.fuyuanshen.common.redis.utils.RedisUtils; import com.fuyuanshen.common.redis.utils.RedisUtils;
import com.fuyuanshen.common.satoken.utils.AppLoginHelper; import com.fuyuanshen.common.satoken.utils.AppLoginHelper;
import com.fuyuanshen.equipment.domain.Device; import com.fuyuanshen.common.satoken.utils.LoginHelper;
import com.fuyuanshen.equipment.domain.DeviceLog; import com.fuyuanshen.equipment.domain.*;
import com.fuyuanshen.equipment.domain.DeviceType;
import com.fuyuanshen.equipment.domain.bo.DeviceAlarmBo; import com.fuyuanshen.equipment.domain.bo.DeviceAlarmBo;
import com.fuyuanshen.equipment.domain.dto.AppDeviceSendMsgBo; import com.fuyuanshen.equipment.domain.dto.AppDeviceSendMsgBo;
import com.fuyuanshen.equipment.domain.form.DeviceForm;
import com.fuyuanshen.equipment.domain.query.DeviceTypeQueryCriteria;
import com.fuyuanshen.equipment.enums.DeviceActiveStatusEnum;
import com.fuyuanshen.equipment.enums.LightModeEnum; import com.fuyuanshen.equipment.enums.LightModeEnum;
import com.fuyuanshen.equipment.mapper.DeviceLogMapper; import com.fuyuanshen.equipment.mapper.DeviceLogMapper;
import com.fuyuanshen.equipment.mapper.DeviceMapper; import com.fuyuanshen.equipment.mapper.DeviceMapper;
import com.fuyuanshen.equipment.mapper.DeviceTypeGrantsMapper;
import com.fuyuanshen.equipment.mapper.DeviceTypeMapper; import com.fuyuanshen.equipment.mapper.DeviceTypeMapper;
import com.fuyuanshen.equipment.service.DeviceAssignmentsService;
import com.fuyuanshen.equipment.service.IDeviceAlarmService; import com.fuyuanshen.equipment.service.IDeviceAlarmService;
import com.fuyuanshen.global.mqtt.base.MqttXinghanJson; import com.fuyuanshen.global.mqtt.base.MqttXinghanJson;
import com.fuyuanshen.global.mqtt.config.MqttGateway; import com.fuyuanshen.global.mqtt.config.MqttGateway;
import com.fuyuanshen.global.mqtt.constants.DeviceRedisKeyConstants; import com.fuyuanshen.global.mqtt.constants.DeviceRedisKeyConstants;
import com.fuyuanshen.global.mqtt.constants.MqttConstants; import com.fuyuanshen.global.mqtt.constants.MqttConstants;
import com.fuyuanshen.system.domain.vo.SysOssVo;
import com.fuyuanshen.system.domain.vo.SysRoleVo;
import com.fuyuanshen.web.domain.Dto.DeviceDebugLogoUploadDto; import com.fuyuanshen.web.domain.Dto.DeviceDebugLogoUploadDto;
import com.fuyuanshen.web.domain.Dto.DeviceXinghanInstructDto; import com.fuyuanshen.web.domain.Dto.DeviceXinghanInstructDto;
import com.fuyuanshen.web.domain.vo.DeviceXinghanDetailVo; import com.fuyuanshen.web.domain.vo.DeviceXinghanDetailVo;
@ -50,17 +62,19 @@ import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.multipart.MultipartFile; import org.springframework.web.multipart.MultipartFile;
import java.io.IOException; import java.io.IOException;
import java.time.Duration; import java.time.Duration;
import java.time.LocalDateTime;
import java.util.*; import java.util.*;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import static com.fuyuanshen.common.core.constant.GlobalConstants.GLOBAL_REDIS_KEY; import static com.fuyuanshen.common.core.constant.GlobalConstants.GLOBAL_REDIS_KEY;
import static com.fuyuanshen.common.core.utils.Bitmap80x12Generator.buildArr;
import static com.fuyuanshen.common.core.utils.Bitmap80x12Generator.generateFixedBitmapData;
import static com.fuyuanshen.common.core.utils.ImageToCArrayConverter.convertHexToDecimal; import static com.fuyuanshen.common.core.utils.ImageToCArrayConverter.convertHexToDecimal;
import static com.fuyuanshen.equipment.service.impl.DeviceServiceImpl.USER_ID_SEPARATOR;
import static com.fuyuanshen.global.mqtt.constants.DeviceRedisKeyConstants.*; import static com.fuyuanshen.global.mqtt.constants.DeviceRedisKeyConstants.*;
@Slf4j @Slf4j
@ -75,6 +89,8 @@ public class DeviceXinghanBizService {
private final DeviceLogMapper deviceLogMapper; private final DeviceLogMapper deviceLogMapper;
private final AppPersonnelInfoRecordsMapper appPersonnelInfoRecordsMapper; private final AppPersonnelInfoRecordsMapper appPersonnelInfoRecordsMapper;
private final IDeviceAlarmService deviceAlarmService; private final IDeviceAlarmService deviceAlarmService;
private final DeviceTypeGrantsMapper deviceTypeGrantsMapper;
private final DeviceAssignmentsService deviceAssignmentsService;
@Autowired @Autowired
private ObjectMapper objectMapper; private ObjectMapper objectMapper;
@ -324,12 +340,14 @@ public class DeviceXinghanBizService {
} }
List<String> list = new ArrayList<>(); List<String> list = new ArrayList<>();
list.add(bo.getUnitName());
list.add(bo.getName()); list.add(bo.getName());
list.add(bo.getPosition()); list.add(bo.getPosition());
list.add(bo.getUnitName());
list.add(bo.getCode()); list.add(bo.getCode());
RedisUtils.setCacheList(GLOBAL_REDIS_KEY+ DEVICE_KEY_PREFIX + deviceObj.getDeviceImei() + ":app_send_message_data", list); String key = GLOBAL_REDIS_KEY + DEVICE_KEY_PREFIX + deviceObj.getDeviceImei() + ":app_send_message_data";
RedisUtils.expire(GLOBAL_REDIS_KEY+ DEVICE_KEY_PREFIX + deviceObj.getDeviceImei() + ":app_send_message_data", Duration.ofSeconds(5 * 60L)); RedisUtils.deleteObject(key); // 先整体删掉
RedisUtils.setCacheList(key, list); // 再重新写入
RedisUtils.expire(key, Duration.ofSeconds(5*60));
Map<String, Object> payload = Map.of("ins_TexTrans", Map<String, Object> payload = Map.of("ins_TexTrans",
Collections.singletonList(0)); Collections.singletonList(0));
@ -615,7 +633,7 @@ public class DeviceXinghanBizService {
if (!"ins_SOSGrade".equals(payloadKey) || value == 0) { if (!"ins_SOSGrade".equals(payloadKey) || value == 0) {
return; return;
} }
AlarmTypeEnum type = value == 1 ? AlarmTypeEnum.SOS : AlarmTypeEnum.SHAKE; AlarmTypeEnum type = AlarmTypeEnum.SOS;
String redisKey = buildAlarmRedisKey(deviceImei, type); String redisKey = buildAlarmRedisKey(deviceImei, type);
Long alarmId = RedisUtils.getCacheObject(redisKey); Long alarmId = RedisUtils.getCacheObject(redisKey);
// 已存在未结束报警 -> 什么都不做(同一条报警) // 已存在未结束报警 -> 什么都不做(同一条报警)
@ -677,4 +695,76 @@ public class DeviceXinghanBizService {
return RedisUtils.getCacheObject(deviceOnlineStatusRedisKey)==null; return RedisUtils.getCacheObject(deviceOnlineStatusRedisKey)==null;
} }
public List<DeviceType> queryDeviceTypes() {
DeviceTypeQueryCriteria criteria = new DeviceTypeQueryCriteria();
return deviceTypeMapper.findAll(criteria);
}
// @Log("新增设备")
public void addDevice(DeviceForm deviceForm) {
if (deviceForm.getDeviceMac() != null && deviceForm.getBluetoothName() == null) {
throw new BadRequestException("请填写蓝牙名称!!!");
}
Device device1 = deviceMapper.selectOne(new QueryWrapper<Device>().eq("device_mac", deviceForm.getDeviceMac()));
if (device1 != null) {
throw new BadRequestException("设备MAC已存在");
}
Device device2 = deviceMapper.selectOne(new QueryWrapper<Device>().eq("device_imei", deviceForm.getDeviceImei()));
if (device2 != null) {
throw new BadRequestException("设备IMEI已存在");
}
DeviceTypeQueryCriteria queryCriteria = new DeviceTypeQueryCriteria();
queryCriteria.setDeviceTypeId(deviceForm.getDeviceType());
queryCriteria.setCustomerId(LoginHelper.getUserId());
DeviceTypeGrants typeGrants = deviceTypeGrantsMapper.selectById(queryCriteria.getDeviceTypeId());
if (typeGrants == null) {
throw new ServiceException("设备类型不存在!!!");
}
DeviceType deviceTypes = deviceTypeMapper.selectById(typeGrants.getDeviceTypeId());
if (deviceTypes == null) {
throw new ServiceException("设备类型不存在!!!");
}
// 转换对象并插入数据库
Device device = new Device();
BeanUtil.copyProperties(deviceForm, device, true);
device.setDeviceNo(createDeviceNo());
AppLoginUser loginUser = AppLoginHelper.getLoginUser();
device.setCurrentOwnerId(loginUser.getUserId());
device.setOriginalOwnerId(loginUser.getUserId());
device.setCreateByName(loginUser.getNickname());
device.setTypeName(deviceTypes.getTypeName());
device.setDeviceType(deviceTypes.getId());
if (device.getDeviceImei() != null) {
device.setPubTopic("A/" + device.getDeviceImei());
device.setSubTopic("B/" + device.getDeviceImei());
}
// 0 未绑定
device.setBindingStatus(0);
deviceMapper.insert(device);
// 新增设备类型记录
DeviceAssignments assignments = new DeviceAssignments();
assignments.setDeviceId(device.getId());
assignments.setAssignedAt(LocalDateTime.now());
// 分配者
assignments.setAssignerId(loginUser.getUserId());
assignments.setAssignerName(loginUser.getUsername());
// 接收者
assignments.setAssigneeId(loginUser.getUserId());
assignments.setActive(DeviceActiveStatusEnum.ACTIVE.getCode());
String lever = USER_ID_SEPARATOR + loginUser.getUserId();
assignments.setLever(lever);
deviceAssignmentsService.save(assignments);
}
private String createDeviceNo() {
String uuidStr = UUID.fastUUID().toString(); // 获取带 - 的标准格式字符串
return uuidStr.replaceAll("-", "");
}
} }

View File

@ -301,7 +301,7 @@ file:
mqtt: mqtt:
username: admin username: admin
password: #YtvpSfCNG password: #YtvpSfCNG
url: tcp://47.120.79.150:2883 url: tcp://www.cnxhyc.com:2883
subClientId: fys_subClient subClientId: fys_subClient
subTopic: A/# subTopic: A/#
pubTopic: B/# pubTopic: B/#

View File

@ -57,7 +57,7 @@ public interface IAppBusinessFileService {
* @param bo 批量新增app业务文件 * @param bo 批量新增app业务文件
* @return 是否新增成功 * @return 是否新增成功
*/ */
Boolean insertBatch(Collection<AppBusinessFile> bo); Boolean insertBatch(Collection<AppBusinessFile> bo,Boolean isBatch);
/** /**
* 修改app业务文件 * 修改app业务文件

View File

@ -102,16 +102,18 @@ public class AppBusinessFileServiceImpl implements IAppBusinessFileService {
} }
@Override @Override
public Boolean insertBatch(Collection<AppBusinessFile> bo) { public Boolean insertBatch(Collection<AppBusinessFile> bo,Boolean isBatch) {
// 1. 去重后的 businessId 集合 // 1. 去重后的 businessId 集合
List<Long> businessIds = bo.stream() if(isBatch){
.map(AppBusinessFile::getBusinessId) List<Long> businessIds = bo.stream()
.distinct() .map(AppBusinessFile::getBusinessId)
.toList(); .distinct()
QueryWrapper<AppBusinessFile> queryWrapper = new QueryWrapper<>(); .toList();
queryWrapper.in("business_id", businessIds); QueryWrapper<AppBusinessFile> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("file_type", bo.stream().findFirst().orElseThrow().getFileType()); queryWrapper.in("business_id", businessIds);
baseMapper.delete(queryWrapper); queryWrapper.eq("file_type", bo.stream().findFirst().orElseThrow().getFileType());
baseMapper.delete(queryWrapper);
}
return baseMapper.insertBatch(bo); return baseMapper.insertBatch(bo);
} }

View File

@ -163,6 +163,8 @@ public class Device extends TenantEntity {
/** /**
* 在线状态(0离线1在线,2异常) * 在线状态(0离线1在线,2异常)
* online_status
*/ */
private Integer onlineStatus; private Integer onlineStatus;
} }

View File

@ -31,7 +31,7 @@ public class DeviceGroupBo extends BaseEntity {
* 分组名称 * 分组名称
*/ */
@Schema(title = "分组名称") @Schema(title = "分组名称")
@NotBlank(message = "分组名称不能为空", groups = { AddGroup.class, EditGroup.class }) @NotBlank(message = "分组名称不能为空", groups = {AddGroup.class, EditGroup.class})
private String groupName; private String groupName;
/** /**
@ -43,6 +43,7 @@ public class DeviceGroupBo extends BaseEntity {
/** /**
* 父分组ID * 父分组ID
* parent_id
*/ */
@Schema(title = "父分组ID") @Schema(title = "父分组ID")
private Long parentId; private Long parentId;

View File

@ -105,6 +105,7 @@ public class DeviceQueryCriteria extends BaseEntity {
/** /**
* 设备所属分组 * 设备所属分组
* group_id
*/ */
private Long groupId; private Long groupId;
@ -117,7 +118,8 @@ public class DeviceQueryCriteria extends BaseEntity {
/** /**
* 设备在线状态 * 设备在线状态
* 0:离线;1:在线 * 0:离线;1:在线2:故障
* online_status
*/ */
private Integer onlineStatus; private Integer onlineStatus;

View File

@ -4,6 +4,7 @@ import lombok.Data;
/** /**
* 报警信息 * 报警信息
* 0-强制报警1-撞击闯入2-自动报警3-电子围栏告警
* *
* @author: 默苍璃 * @author: 默苍璃
* @date: 2025-09-0114:24 * @date: 2025-09-0114:24
@ -21,7 +22,6 @@ public class AlarmInformationVo {
*/ */
private Integer processingAlarm = 0; private Integer processingAlarm = 0;
/** /**
* 今日报警总数 * 今日报警总数
*/ */
@ -32,7 +32,6 @@ public class AlarmInformationVo {
*/ */
private Integer processingAlarmToday = 0; private Integer processingAlarmToday = 0;
/** /**
* 强制报警 * 强制报警
*/ */
@ -44,12 +43,12 @@ public class AlarmInformationVo {
private Integer intrusionImpact = 0; private Integer intrusionImpact = 0;
/** /**
* 动报警 * 动报警
*/ */
private Integer alarmManual = 0; private Integer alarmAuto = 0;
/** /**
* * 电子围栏告警
*/ */
private Integer fenceElectronic = 0; private Integer fenceElectronic = 0;

View File

@ -43,10 +43,10 @@ public class AlarmStatisticsVo implements Serializable {
private Integer intrusionImpactAlarms = 0; private Integer intrusionImpactAlarms = 0;
/** /**
* 动报警数量 * 动报警数量
* device_action = 2 * device_action = 2
*/ */
private Integer manualAlarms = 0; private Integer autoAlarms = 0;
/** /**
* 电子围栏告警数量 * 电子围栏告警数量

View File

@ -58,6 +58,13 @@ public class WebDeviceVo implements Serializable {
*/ */
private Integer deviceStatus; private Integer deviceStatus;
/**绑定状态
* 0 未绑定
* 1 已绑定
*/
private Integer bindingStatus;
/** /**
* 绑定时间 * 绑定时间
*/ */

View File

@ -120,7 +120,14 @@ public class DeviceGroupServiceImpl implements IDeviceGroupService {
public Boolean insertByBo(DeviceGroupBo bo) { public Boolean insertByBo(DeviceGroupBo bo) {
// 验证分组名称唯一性 // 验证分组名称唯一性
DeviceGroup deviceGroup = baseMapper.selectOne(new QueryWrapper<DeviceGroup>().eq("group_name", bo.getGroupName())); QueryWrapper<DeviceGroup> queryWrapper = new QueryWrapper<DeviceGroup>().eq("group_name", bo.getGroupName());
if (bo.getParentId() != null) {
queryWrapper.eq("parent_id", bo.getParentId());
} else {
queryWrapper.isNull("parent_id");
}
DeviceGroup deviceGroup = baseMapper.selectOne(queryWrapper);
if (deviceGroup != null) { if (deviceGroup != null) {
throw new RuntimeException("分组名称已存在,请勿重复添加!!!"); throw new RuntimeException("分组名称已存在,请勿重复添加!!!");
} }
@ -159,10 +166,24 @@ public class DeviceGroupServiceImpl implements IDeviceGroupService {
/** /**
* 保存前的数据校验 * 保存前的数据校验
*/ */
private void validEntityBeforeSave(DeviceGroup entity) { private void validEntityBeforeSave(DeviceGroup bo) {
// TODO 做一些数据校验,如唯一约束 // TODO 做一些数据校验,如唯一约束
// 验证分组名称唯一性
QueryWrapper<DeviceGroup> queryWrapper = new QueryWrapper<DeviceGroup>().eq("group_name", bo.getGroupName());
if (bo.getParentId() != null) {
queryWrapper.eq("parent_id", bo.getParentId());
} else {
queryWrapper.isNull("parent_id");
}
DeviceGroup deviceGroup = baseMapper.selectOne(queryWrapper);
if (deviceGroup != null && deviceGroup.getId() != bo.getId()) {
throw new RuntimeException("分组名称已存在,请勿重复添加!!!");
}
} }
/** /**
* 校验并批量删除设备分组信息 * 校验并批量删除设备分组信息
* *
@ -210,7 +231,7 @@ public class DeviceGroupServiceImpl implements IDeviceGroupService {
* @return 是否解绑成功 * @return 是否解绑成功
*/ */
@Override @Override
public Boolean groupUnbind( Long[] deviceId) { public Boolean groupUnbind(Long[] deviceId) {
if (deviceId != null && deviceId.length > 0) { if (deviceId != null && deviceId.length > 0) {
// 创建更新条件 // 创建更新条件

View File

@ -342,6 +342,9 @@ public class DeviceServiceImpl extends ServiceImpl<DeviceMapper, Device> impleme
for (Long id : ids) { for (Long id : ids) {
DeviceAssignments deviceAssignment = deviceAssignmentsMapper.selectById(id); DeviceAssignments deviceAssignment = deviceAssignmentsMapper.selectById(id);
if (deviceAssignment == null) {
continue;
}
Device device = deviceMapper.selectById(deviceAssignment.getDeviceId()); Device device = deviceMapper.selectById(deviceAssignment.getDeviceId());
if (StringUtils.isNotEmpty(deviceAssignment.getAssigneeName())) { if (StringUtils.isNotEmpty(deviceAssignment.getAssigneeName())) {
@ -815,10 +818,10 @@ public class DeviceServiceImpl extends ServiceImpl<DeviceMapper, Device> impleme
DeviceAlarmVo latestAlarm = deviceAlarmMapper.selectLatestByDeviceImei(device.getDeviceImei()); DeviceAlarmVo latestAlarm = deviceAlarmMapper.selectLatestByDeviceImei(device.getDeviceImei());
// 判断是否正在告警:未处理的告警(treatmentState=1)且不是电子围栏告警(deviceAction!=3) // 判断是否正在告警:未处理的告警(treatmentState=1)且不是电子围栏告警(deviceAction!=3)
if (latestAlarm != null && if (latestAlarm != null &&
latestAlarm.getTreatmentState() != null && latestAlarm.getTreatmentState() != null &&
latestAlarm.getTreatmentState() == 1 && latestAlarm.getTreatmentState() == 1 &&
latestAlarm.getDeviceAction() != null && latestAlarm.getDeviceAction() != null &&
latestAlarm.getDeviceAction() != 3) { latestAlarm.getDeviceAction() != 3) {
vo.setIsAlarming(true); vo.setIsAlarming(true);
} else { } else {
vo.setIsAlarming(false); vo.setIsAlarming(false);
@ -834,5 +837,4 @@ public class DeviceServiceImpl extends ServiceImpl<DeviceMapper, Device> impleme
} }
} }

View File

@ -76,7 +76,7 @@
(SELECT COUNT(1) FROM device_alarm WHERE treatment_state = 0) AS processedAlarms, (SELECT COUNT(1) FROM device_alarm WHERE treatment_state = 0) AS processedAlarms,
(SELECT COUNT(1) FROM device_alarm WHERE device_action = 0) AS forcedAlarms, (SELECT COUNT(1) FROM device_alarm WHERE device_action = 0) AS forcedAlarms,
(SELECT COUNT(1) FROM device_alarm WHERE device_action = 1) AS intrusionImpactAlarms, (SELECT COUNT(1) FROM device_alarm WHERE device_action = 1) AS intrusionImpactAlarms,
(SELECT COUNT(1) FROM device_alarm WHERE device_action = 2) AS manualAlarms, (SELECT COUNT(1) FROM device_alarm WHERE device_action = 2) AS autoAlarms,
(SELECT COUNT(1) FROM device_alarm WHERE device_action = 3) AS geoFenceAlarms (SELECT COUNT(1) FROM device_alarm WHERE device_action = 3) AS geoFenceAlarms
</select> </select>

View File

@ -42,7 +42,7 @@
FROM ( FROM (
SELECT SELECT
da.id AS id, d.id AS deviceId, d.device_name, d.bluetooth_name, d.group_id, da.id AS id, d.id AS deviceId, d.device_name, d.bluetooth_name, d.group_id,
d.pub_topic, d.sub_topic, d.device_pic, d.pub_topic, d.sub_topic, d.device_pic,d.online_status,
d.device_mac, d.device_sn, d.update_by, d.device_mac, d.device_sn, d.update_by,
d.device_imei, d.update_time, dg.id AS device_type, d.device_imei, d.update_time, dg.id AS device_type,
d.remark, d.binding_status, t.type_name AS typeName, d.remark, d.binding_status, t.type_name AS typeName,
@ -59,11 +59,11 @@
<if test="criteria.deviceName != null and criteria.deviceName.trim() != ''"> <if test="criteria.deviceName != null and criteria.deviceName.trim() != ''">
and d.device_name like concat('%', TRIM(#{criteria.deviceName}), '%') and d.device_name like concat('%', TRIM(#{criteria.deviceName}), '%')
</if> </if>
<if test="criteria.deviceMac != null"> <if test="criteria.deviceMac != null and criteria.deviceMac.trim() != ''">
and d.device_mac = #{criteria.deviceMac} and d.device_mac like concat('%', TRIM(#{criteria.deviceMac}), '%')
</if> </if>
<if test="criteria.deviceImei != null"> <if test="criteria.deviceImei != null and criteria.deviceImei.trim() != ''">
and d.device_imei = #{criteria.deviceImei} and d.device_imei like concat('%', TRIM(#{criteria.deviceImei}), '%')
</if> </if>
<if test="criteria.deviceType != null"> <if test="criteria.deviceType != null">
and d.device_type = #{criteria.deviceType} and d.device_type = #{criteria.deviceType}
@ -71,6 +71,9 @@
<if test="criteria.deviceStatus != null"> <if test="criteria.deviceStatus != null">
and da.active = #{criteria.deviceStatus} and da.active = #{criteria.deviceStatus}
</if> </if>
<if test="criteria.onlineStatus != null">
and d.online_status = #{criteria.onlineStatus}
</if>
<if test="criteria.groupId != null"> <if test="criteria.groupId != null">
and d.group_id = #{criteria.groupId} and d.group_id = #{criteria.groupId}
</if> </if>
@ -125,10 +128,10 @@
<if test="criteria.deviceName != null and criteria.deviceName.trim() != ''"> <if test="criteria.deviceName != null and criteria.deviceName.trim() != ''">
and d.device_name like concat('%', TRIM(#{criteria.deviceName}), '%') and d.device_name like concat('%', TRIM(#{criteria.deviceName}), '%')
</if> </if>
<if test="criteria.deviceMac != null"> <if test="criteria.deviceMac != null and criteria.deviceMac.trim() != ''">
and d.device_mac = #{criteria.deviceMac} and d.device_mac = #{criteria.deviceMac}
</if> </if>
<if test="criteria.deviceImei != null"> <if test="criteria.deviceImei != null and criteria.deviceImei.trim() != ''">
and d.device_imei = #{criteria.deviceImei} and d.device_imei = #{criteria.deviceImei}
</if> </if>
<if test="criteria.deviceType != null"> <if test="criteria.deviceType != null">
@ -137,6 +140,9 @@
<if test="criteria.deviceStatus != null"> <if test="criteria.deviceStatus != null">
and d.device_status = #{criteria.deviceStatus} and d.device_status = #{criteria.deviceStatus}
</if> </if>
<if test="criteria.groupId != null">
and d.group_id = #{criteria.groupId}
</if>
<if test="criteria.currentOwnerId != null"> <if test="criteria.currentOwnerId != null">
and d.current_owner_id = #{criteria.currentOwnerId} and d.current_owner_id = #{criteria.currentOwnerId}
</if> </if>
@ -241,23 +247,27 @@
<select id="queryWebDeviceList" resultType="com.fuyuanshen.equipment.domain.vo.WebDeviceVo"> <select id="queryWebDeviceList" resultType="com.fuyuanshen.equipment.domain.vo.WebDeviceVo">
select * from (select d.id, d.device_name, select * from (select d.id, d.device_name,
d.device_mac, d.device_mac,
d.device_type,
d.device_sn, d.device_sn,
d.device_imei, d.device_imei,
d.device_pic, d.device_pic,
d.group_id,
dt.type_name, dt.type_name,
dt.communication_mode, dt.communication_mode,
d.bluetooth_name, d.bluetooth_name,
dt.pc_model_dictionary detailPageUrl, dt.pc_model_dictionary detailPageUrl,
ap.name personnelBy, ap.name personnelBy,
d.device_status, d.device_status,
d.binding_status,
d.online_status, d.online_status,
c.binding_time, c.binding_time,
ROW_NUMBER() OVER (PARTITION BY d.id ORDER BY c.binding_time) AS row_num d.create_time,
ROW_NUMBER() OVER (PARTITION BY d.id ORDER BY d.id) 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
inner join app_device_bind_record c on d.id = c.device_id left join app_device_bind_record c on d.id = c.device_id
left join app_personnel_info ap on ap.device_id = d.id left join app_personnel_info ap on ap.device_id = d.id
where dt.communication_mode in (0, 2) ) a where a.row_num = 1 where dt.communication_mode in (0, 2) ORDER BY (case when d.online_status = 1 then 2 else 1 end) DESC) a where a.row_num = 1
<if test="criteria.deviceType != null"> <if test="criteria.deviceType != null">
and a.device_type = #{criteria.deviceType} and a.device_type = #{criteria.deviceType}
</if> </if>
@ -265,10 +275,13 @@
and a.device_name like concat('%', #{criteria.deviceName}, '%') and a.device_name like concat('%', #{criteria.deviceName}, '%')
</if> </if>
<if test="criteria.deviceImei != null and criteria.deviceImei != ''"> <if test="criteria.deviceImei != null and criteria.deviceImei != ''">
and a.device_imei = #{criteria.deviceImei} and a.device_imei like concat('%',#{criteria.deviceImei}, '%')
</if>
<if test="criteria.deviceMac != null and criteria.deviceMac != ''">
and a.device_mac like concat('%',#{criteria.deviceMac}, '%')
</if> </if>
<if test="criteria.content != null and criteria.content != ''"> <if test="criteria.content != null and criteria.content != ''">
AND (a.device_imei = #{criteria.content} or a.device_mac = #{criteria.content}) AND (a.device_imei like concat('%',#{criteria.content}, '%') or a.device_mac like concat('%',#{criteria.content}, '%') )
</if> </if>
<if test="criteria.deviceStatus != null"> <if test="criteria.deviceStatus != null">
and a.device_status = #{criteria.deviceStatus} and a.device_status = #{criteria.deviceStatus}
@ -285,7 +298,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.binding_time 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
@ -301,10 +314,10 @@
AND a.device_mac = #{bo.deviceMac} AND a.device_mac = #{bo.deviceMac}
</if> </if>
<if test="bo.deviceImei != null and bo.deviceImei != ''"> <if test="bo.deviceImei != null and bo.deviceImei != ''">
AND a.device_imei = #{bo.deviceImei} and a.device_imei like concat('%',#{bo.deviceImei}, '%')
</if> </if>
<if test="bo.content != null and bo.content != ''"> <if test="bo.content != null and bo.content != ''">
AND a.device_imei = #{bo.content} or a.device_mac = #{bo.content} AND (a.device_imei like concat('%',#{bo.content}, '%') or a.device_mac like concat('%',#{bo.content}, '%') )
</if> </if>
<if test="bo.startTime != null and bo.startTime != ''"> <if test="bo.startTime != null and bo.startTime != ''">
AND a.create_time <![CDATA[>=]]> #{bo.startTime} AND a.create_time <![CDATA[>=]]> #{bo.startTime}
@ -404,7 +417,7 @@
SELECT COUNT (1) SELECT COUNT (1)
FROM device_alarm FROM device_alarm
WHERE device_action = 2 WHERE device_action = 2
) AS alarmManual ) AS alarmAuto
, ( , (
SELECT COUNT (1) SELECT COUNT (1)
FROM device_alarm FROM device_alarm
@ -450,7 +463,7 @@
</select> </select>
<!-- 获取设备使用频次统计 --> <!-- 获取设备使用频次统计 -->
<select id="getDeviceUsageFrequency" resultType="com.fuyuanshen.equipment.domain.vo.DeviceUsageFrequencyVo"> <select id="getDeviceUsageFrequency1" resultType="com.fuyuanshen.equipment.domain.vo.DeviceUsageFrequencyVo">
SELECT SELECT
device_name AS deviceName, device_name AS deviceName,
COUNT(*) AS frequency COUNT(*) AS frequency
@ -459,6 +472,17 @@
GROUP BY device_name GROUP BY device_name
ORDER BY frequency DESC ORDER BY frequency DESC
</select> </select>
<!-- 获取设备使用频次统计 (设备类型)-->
<select id="getDeviceUsageFrequency" resultType="com.fuyuanshen.equipment.domain.vo.DeviceUsageFrequencyVo">
SELECT
d.type_name AS deviceName,
COUNT(*) AS frequency
FROM device_log dl
INNER JOIN device d ON dl.device_id = d.id
WHERE dl.create_time >= DATE_SUB(NOW(), INTERVAL #{days} DAY)
GROUP BY d.device_type, d.type_name
ORDER BY frequency DESC
</select>
<!-- 根据设备IMEI查询设备 --> <!-- 根据设备IMEI查询设备 -->
<select id="selectDeviceByImei" resultType="com.fuyuanshen.equipment.domain.Device"> <select id="selectDeviceByImei" resultType="com.fuyuanshen.equipment.domain.Device">

View File

@ -32,6 +32,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="criteria.repairPart != null"> <if test="criteria.repairPart != null">
and dr.repair_part like concat('%', TRIM(#{criteria.repairPart}), '%') and dr.repair_part like concat('%', TRIM(#{criteria.repairPart}), '%')
</if> </if>
<if test="criteria.repairPerson != null">
and dr.repair_person like concat('%', TRIM(#{criteria.repairPerson}), '%')
</if>
<!-- 时间段条件 --> <!-- 时间段条件 -->
<if test="criteria.repairBeginTime != null"> <if test="criteria.repairBeginTime != null">
AND dr.repair_time <![CDATA[ >= ]]> #{criteria.repairBeginTime} AND dr.repair_time <![CDATA[ >= ]]> #{criteria.repairBeginTime}