From e07dbb01b76f37de832160abba42cd171f677a51 Mon Sep 17 00:00:00 2001 From: daiyongfei <974332738@qq.com> Date: Thu, 31 Jul 2025 10:27:02 +0800 Subject: [PATCH 01/19] =?UTF-8?q?=E6=A0=A1=E9=AA=8C=E8=AE=BE=E5=A4=87?= =?UTF-8?q?=E7=B1=BB=E5=9E=8B=E5=90=8D=E7=A7=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/impl/DeviceTypeServiceImpl.java | 23 +++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/service/impl/DeviceTypeServiceImpl.java b/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/service/impl/DeviceTypeServiceImpl.java index fcc373e..6d06c19 100644 --- a/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/service/impl/DeviceTypeServiceImpl.java +++ b/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/service/impl/DeviceTypeServiceImpl.java @@ -107,6 +107,13 @@ public class DeviceTypeServiceImpl extends ServiceImpl typeName = deviceTypeMapper.selectList(new QueryWrapper().eq("type_name", resources.getTypeName())); + if (CollectionUtil.isNotEmpty(typeName)) { + throw new RuntimeException("设备类型名称已存在,无法新增!!!"); + } + LoginUser loginUser = LoginHelper.getLoginUser(); resources.setCustomerId(loginUser.getUserId()); resources.setOwnerCustomerId(loginUser.getUserId()); @@ -141,11 +148,23 @@ public class DeviceTypeServiceImpl extends ServiceImpl devices = deviceMapper.selectList(new QueryWrapper() + .eq("device_type", deviceTypeGrants.getDeviceTypeId())); + if (CollectionUtil.isNotEmpty(devices)) { + throw new RuntimeException("该设备类型已绑定设备,无法修改!!!"); + } + + // 校验设备类型名称 + DeviceType dt = deviceTypeMapper.selectOne(new QueryWrapper().eq("type_name", resources.getTypeName())); + if (dt != null && !dt.getId().equals(deviceType.getId())) { + throw new RuntimeException("设备类型名称已存在,无法修改!!!"); + } + if (!Objects.equals(deviceType.getCustomerId(), LoginHelper.getUserId())) { throw new RuntimeException("无权修改该设备类型"); } - // if (deviceMapper.countByTypeId(resources.getId()) > 0) - // throw new RuntimeException("该设备类型已被使用,无法删除"); + BeanUtil.copyProperties(resources, deviceType); deviceTypeMapper.updateById(deviceType); } From 8ae15dcd9a7bd624efb484377ed71b5e1d69c413 Mon Sep 17 00:00:00 2001 From: daiyongfei <974332738@qq.com> Date: Thu, 31 Jul 2025 15:29:37 +0800 Subject: [PATCH 02/19] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E7=94=A8=E6=88=B7?= =?UTF-8?q?=E7=8A=B6=E6=80=81-=E5=BC=BA=E5=88=B6=E4=B8=8B=E7=BA=BF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/impl/CustomerServiceImpl.java | 24 ++- .../service/impl/DeviceTypeServiceImpl.java | 4 - .../service/impl/SysUserServiceImpl.java | 177 ++++++++++-------- 3 files changed, 109 insertions(+), 96 deletions(-) diff --git a/fys-modules/fys-customer/src/main/java/com/fuyuanshen/customer/service/impl/CustomerServiceImpl.java b/fys-modules/fys-customer/src/main/java/com/fuyuanshen/customer/service/impl/CustomerServiceImpl.java index b67ca9b..75ae139 100644 --- a/fys-modules/fys-customer/src/main/java/com/fuyuanshen/customer/service/impl/CustomerServiceImpl.java +++ b/fys-modules/fys-customer/src/main/java/com/fuyuanshen/customer/service/impl/CustomerServiceImpl.java @@ -5,6 +5,7 @@ import cn.hutool.core.bean.BeanUtil; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.fuyuanshen.common.core.domain.model.LoginUser; +import com.fuyuanshen.common.core.enums.UserType; import com.fuyuanshen.common.core.utils.StringUtils; import com.fuyuanshen.common.mybatis.core.page.TableDataInfo; import com.fuyuanshen.common.satoken.utils.LoginHelper; @@ -95,7 +96,7 @@ public class CustomerServiceImpl extends ServiceImpl i customer.setUserLevel((byte) (loginUser.getUserLevel() + 1)); customer.setPid(loginUser.getUserId()); customer.setStatus("0"); - + customer.setUserType(UserType.SYS_USER.getUserType()); save(customer); // 新增用户与角色管理 @@ -117,6 +118,9 @@ public class CustomerServiceImpl extends ServiceImpl i @Transactional(rollbackFor = Exception.class) public void updateCustomer(Customer customer) throws Exception { + // 获取当前会话账号id, 如果未登录,则抛出异常:`NotLoginException` + Object loginId = StpUtil.getLoginId(); + UserQueryCriteria userQueryCriteria = new UserQueryCriteria(); if (StringUtils.isNotEmpty(customer.getUserName())) { userQueryCriteria.setCustomerName(customer.getUserName()); @@ -130,17 +134,19 @@ public class CustomerServiceImpl extends ServiceImpl i customer.setStatus("0"); } else { // 强制下线 - // StpUtil.logout(customer.getCustomerId()); + // String tokenId = customer.getUserType() + ":" + customer.getCustomerId(); + String tokenId = UserType.SYS_USER.getUserType() + ":" + customer.getCustomerId(); + StpUtil.logout(tokenId); // StpUtil.kickout(customer.getCustomerId()); customer.setStatus("1"); // 检查目标用户是否有有效的登录状态 - if (StpUtil.isLogin(customer.getCustomerId())) { - // 用户已登录,可以执行踢出操作 - StpUtil.kickout(customer.getCustomerId()); - } else { - // 用户未登录,无法踢出 - System.out.println("目标用户未登录,无法执行踢出操作"); - } + // if (StpUtil.isLogin(customer.getCustomerId())) { + // // 用户已登录,可以执行踢出操作 + // StpUtil.kickout(customer.getCustomerId()); + // } else { + // // 用户未登录,无法踢出 + // System.out.println("目标用户未登录,无法执行踢出操作"); + // } } saveOrUpdate(customer); } diff --git a/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/service/impl/DeviceTypeServiceImpl.java b/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/service/impl/DeviceTypeServiceImpl.java index 6d06c19..8f9d7f7 100644 --- a/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/service/impl/DeviceTypeServiceImpl.java +++ b/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/service/impl/DeviceTypeServiceImpl.java @@ -6,17 +6,13 @@ import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; -import com.fuyuanshen.common.core.domain.PageResult; import com.fuyuanshen.common.core.domain.model.LoginUser; -import com.fuyuanshen.common.core.utils.PageUtil; import com.fuyuanshen.common.mybatis.core.page.TableDataInfo; import com.fuyuanshen.common.satoken.utils.LoginHelper; import com.fuyuanshen.equipment.domain.Device; -import com.fuyuanshen.equipment.domain.DeviceAssignments; import com.fuyuanshen.equipment.domain.DeviceType; import com.fuyuanshen.equipment.domain.DeviceTypeGrants; import com.fuyuanshen.equipment.domain.form.DeviceTypeForm; -import com.fuyuanshen.equipment.domain.query.DeviceQueryCriteria; import com.fuyuanshen.equipment.domain.query.DeviceTypeQueryCriteria; import com.fuyuanshen.equipment.mapper.DeviceAssignmentsMapper; import com.fuyuanshen.equipment.mapper.DeviceMapper; diff --git a/fys-modules/fys-system/src/main/java/com/fuyuanshen/system/service/impl/SysUserServiceImpl.java b/fys-modules/fys-system/src/main/java/com/fuyuanshen/system/service/impl/SysUserServiceImpl.java index d4b1a08..24d2204 100644 --- a/fys-modules/fys-system/src/main/java/com/fuyuanshen/system/service/impl/SysUserServiceImpl.java +++ b/fys-modules/fys-system/src/main/java/com/fuyuanshen/system/service/impl/SysUserServiceImpl.java @@ -1,5 +1,6 @@ package com.fuyuanshen.system.service.impl; +import cn.dev33.satoken.stp.StpUtil; import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.convert.Convert; @@ -11,6 +12,8 @@ import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.fuyuanshen.common.core.enums.UserStatus; +import com.fuyuanshen.common.core.enums.UserType; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import com.fuyuanshen.common.core.constant.CacheNames; @@ -76,20 +79,20 @@ public class SysUserServiceImpl implements ISysUserService, UserService { Map params = user.getParams(); QueryWrapper wrapper = Wrappers.query(); wrapper.eq("u.del_flag", SystemConstants.NORMAL) - .eq(ObjectUtil.isNotNull(user.getUserId()), "u.user_id", user.getUserId()) - .in(StringUtils.isNotBlank(user.getUserIds()), "u.user_id", StringUtils.splitTo(user.getUserIds(), Convert::toLong)) - .like(StringUtils.isNotBlank(user.getUserName()), "u.user_name", user.getUserName()) - .like(StringUtils.isNotBlank(user.getNickName()), "u.nick_name", user.getNickName()) - .eq(StringUtils.isNotBlank(user.getStatus()), "u.status", user.getStatus()) - .like(StringUtils.isNotBlank(user.getPhonenumber()), "u.phonenumber", user.getPhonenumber()) - .between(params.get("beginTime") != null && params.get("endTime") != null, - "u.create_time", params.get("beginTime"), params.get("endTime")) - .and(ObjectUtil.isNotNull(user.getDeptId()), w -> { - List deptList = deptMapper.selectListByParentId(user.getDeptId()); - List ids = StreamUtils.toList(deptList, SysDept::getDeptId); - ids.add(user.getDeptId()); - w.in("u.dept_id", ids); - }).orderByAsc("u.user_id"); + .eq(ObjectUtil.isNotNull(user.getUserId()), "u.user_id", user.getUserId()) + .in(StringUtils.isNotBlank(user.getUserIds()), "u.user_id", StringUtils.splitTo(user.getUserIds(), Convert::toLong)) + .like(StringUtils.isNotBlank(user.getUserName()), "u.user_name", user.getUserName()) + .like(StringUtils.isNotBlank(user.getNickName()), "u.nick_name", user.getNickName()) + .eq(StringUtils.isNotBlank(user.getStatus()), "u.status", user.getStatus()) + .like(StringUtils.isNotBlank(user.getPhonenumber()), "u.phonenumber", user.getPhonenumber()) + .between(params.get("beginTime") != null && params.get("endTime") != null, + "u.create_time", params.get("beginTime"), params.get("endTime")) + .and(ObjectUtil.isNotNull(user.getDeptId()), w -> { + List deptList = deptMapper.selectListByParentId(user.getDeptId()); + List ids = StreamUtils.toList(deptList, SysDept::getDeptId); + ids.add(user.getDeptId()); + w.in("u.dept_id", ids); + }).orderByAsc("u.user_id"); if (StringUtils.isNotBlank(user.getExcludeUserIds())) { wrapper.notIn("u.user_id", StringUtils.splitTo(user.getExcludeUserIds(), Convert::toLong)); } @@ -106,11 +109,11 @@ public class SysUserServiceImpl implements ISysUserService, UserService { public TableDataInfo selectAllocatedList(SysUserBo user, PageQuery pageQuery) { QueryWrapper wrapper = Wrappers.query(); wrapper.eq("u.del_flag", SystemConstants.NORMAL) - .eq(ObjectUtil.isNotNull(user.getRoleId()), "r.role_id", user.getRoleId()) - .like(StringUtils.isNotBlank(user.getUserName()), "u.user_name", user.getUserName()) - .eq(StringUtils.isNotBlank(user.getStatus()), "u.status", user.getStatus()) - .like(StringUtils.isNotBlank(user.getPhonenumber()), "u.phonenumber", user.getPhonenumber()) - .orderByAsc("u.user_id"); + .eq(ObjectUtil.isNotNull(user.getRoleId()), "r.role_id", user.getRoleId()) + .like(StringUtils.isNotBlank(user.getUserName()), "u.user_name", user.getUserName()) + .eq(StringUtils.isNotBlank(user.getStatus()), "u.status", user.getStatus()) + .like(StringUtils.isNotBlank(user.getPhonenumber()), "u.phonenumber", user.getPhonenumber()) + .orderByAsc("u.user_id"); Page page = baseMapper.selectAllocatedList(pageQuery.build(), wrapper); return TableDataInfo.build(page); } @@ -126,11 +129,11 @@ public class SysUserServiceImpl implements ISysUserService, UserService { List userIds = userRoleMapper.selectUserIdsByRoleId(user.getRoleId()); QueryWrapper wrapper = Wrappers.query(); wrapper.eq("u.del_flag", SystemConstants.NORMAL) - .and(w -> w.ne("r.role_id", user.getRoleId()).or().isNull("r.role_id")) - .notIn(CollUtil.isNotEmpty(userIds), "u.user_id", userIds) - .like(StringUtils.isNotBlank(user.getUserName()), "u.user_name", user.getUserName()) - .like(StringUtils.isNotBlank(user.getPhonenumber()), "u.phonenumber", user.getPhonenumber()) - .orderByAsc("u.user_id"); + .and(w -> w.ne("r.role_id", user.getRoleId()).or().isNull("r.role_id")) + .notIn(CollUtil.isNotEmpty(userIds), "u.user_id", userIds) + .like(StringUtils.isNotBlank(user.getUserName()), "u.user_name", user.getUserName()) + .like(StringUtils.isNotBlank(user.getPhonenumber()), "u.phonenumber", user.getPhonenumber()) + .orderByAsc("u.user_id"); Page page = baseMapper.selectUnallocatedList(pageQuery.build(), wrapper); return TableDataInfo.build(page); } @@ -183,10 +186,10 @@ public class SysUserServiceImpl implements ISysUserService, UserService { @Override public List selectUserByIds(List userIds, Long deptId) { return baseMapper.selectUserList(new LambdaQueryWrapper() - .select(SysUser::getUserId, SysUser::getUserName, SysUser::getNickName) - .eq(SysUser::getStatus, SystemConstants.NORMAL) - .eq(ObjectUtil.isNotNull(deptId), SysUser::getDeptId, deptId) - .in(CollUtil.isNotEmpty(userIds), SysUser::getUserId, userIds)); + .select(SysUser::getUserId, SysUser::getUserName, SysUser::getNickName) + .eq(SysUser::getStatus, SystemConstants.NORMAL) + .eq(ObjectUtil.isNotNull(deptId), SysUser::getDeptId, deptId) + .in(CollUtil.isNotEmpty(userIds), SysUser::getUserId, userIds)); } /** @@ -228,8 +231,8 @@ public class SysUserServiceImpl implements ISysUserService, UserService { @Override public boolean checkUserNameUnique(SysUserBo user) { boolean exist = baseMapper.exists(new LambdaQueryWrapper() - .eq(SysUser::getUserName, user.getUserName()) - .ne(ObjectUtil.isNotNull(user.getUserId()), SysUser::getUserId, user.getUserId())); + .eq(SysUser::getUserName, user.getUserName()) + .ne(ObjectUtil.isNotNull(user.getUserId()), SysUser::getUserId, user.getUserId())); return !exist; } @@ -241,8 +244,8 @@ public class SysUserServiceImpl implements ISysUserService, UserService { @Override public boolean checkPhoneUnique(SysUserBo user) { boolean exist = baseMapper.exists(new LambdaQueryWrapper() - .eq(SysUser::getPhonenumber, user.getPhonenumber()) - .ne(ObjectUtil.isNotNull(user.getUserId()), SysUser::getUserId, user.getUserId())); + .eq(SysUser::getPhonenumber, user.getPhonenumber()) + .ne(ObjectUtil.isNotNull(user.getUserId()), SysUser::getUserId, user.getUserId())); return !exist; } @@ -254,8 +257,8 @@ public class SysUserServiceImpl implements ISysUserService, UserService { @Override public boolean checkEmailUnique(SysUserBo user) { boolean exist = baseMapper.exists(new LambdaQueryWrapper() - .eq(SysUser::getEmail, user.getEmail()) - .ne(ObjectUtil.isNotNull(user.getUserId()), SysUser::getUserId, user.getUserId())); + .eq(SysUser::getEmail, user.getEmail()) + .ne(ObjectUtil.isNotNull(user.getUserId()), SysUser::getUserId, user.getUserId())); return !exist; } @@ -359,6 +362,7 @@ public class SysUserServiceImpl implements ISysUserService, UserService { insertUserRole(userId, roleIds, true); } + /** * 修改用户状态 * @@ -368,12 +372,19 @@ public class SysUserServiceImpl implements ISysUserService, UserService { */ @Override public int updateUserStatus(Long userId, String status) { + if (UserStatus.DISABLE.getCode().equals(status)) { + // 强制下线 + String tokenId = UserType.SYS_USER.getUserType() + ":" + userId; + StpUtil.logout(tokenId); + } + return baseMapper.update(null, - new LambdaUpdateWrapper() - .set(SysUser::getStatus, status) - .eq(SysUser::getUserId, userId)); + new LambdaUpdateWrapper() + .set(SysUser::getStatus, status) + .eq(SysUser::getUserId, userId)); } + /** * 修改用户基本信息 * @@ -384,12 +395,12 @@ public class SysUserServiceImpl implements ISysUserService, UserService { @Override public int updateUserProfile(SysUserBo user) { return baseMapper.update(null, - new LambdaUpdateWrapper() - .set(ObjectUtil.isNotNull(user.getNickName()), SysUser::getNickName, user.getNickName()) - .set(SysUser::getPhonenumber, user.getPhonenumber()) - .set(SysUser::getEmail, user.getEmail()) - .set(SysUser::getSex, user.getSex()) - .eq(SysUser::getUserId, user.getUserId())); + new LambdaUpdateWrapper() + .set(ObjectUtil.isNotNull(user.getNickName()), SysUser::getNickName, user.getNickName()) + .set(SysUser::getPhonenumber, user.getPhonenumber()) + .set(SysUser::getEmail, user.getEmail()) + .set(SysUser::getSex, user.getSex()) + .eq(SysUser::getUserId, user.getUserId())); } /** @@ -402,9 +413,9 @@ public class SysUserServiceImpl implements ISysUserService, UserService { @Override public boolean updateUserAvatar(Long userId, Long avatar) { return baseMapper.update(null, - new LambdaUpdateWrapper() - .set(SysUser::getAvatar, avatar) - .eq(SysUser::getUserId, userId)) > 0; + new LambdaUpdateWrapper() + .set(SysUser::getAvatar, avatar) + .eq(SysUser::getUserId, userId)) > 0; } /** @@ -417,9 +428,9 @@ public class SysUserServiceImpl implements ISysUserService, UserService { @Override public int resetUserPwd(Long userId, String password) { return baseMapper.update(null, - new LambdaUpdateWrapper() - .set(SysUser::getPassword, password) - .eq(SysUser::getUserId, userId)); + new LambdaUpdateWrapper() + .set(SysUser::getPassword, password) + .eq(SysUser::getUserId, userId)); } /** @@ -471,7 +482,7 @@ public class SysUserServiceImpl implements ISysUserService, UserService { } // 判断是否具有此角色的操作权限 List roles = roleMapper.selectRoleList( - new QueryWrapper().in("r.role_id", roleList)); + new QueryWrapper().in("r.role_id", roleList)); if (CollUtil.isEmpty(roles)) { throw new ServiceException("没有权限访问角色的数据"); } @@ -561,7 +572,7 @@ public class SysUserServiceImpl implements ISysUserService, UserService { @Override public String selectUserNameById(Long userId) { SysUser sysUser = baseMapper.selectOne(new LambdaQueryWrapper() - .select(SysUser::getUserName).eq(SysUser::getUserId, userId)); + .select(SysUser::getUserName).eq(SysUser::getUserId, userId)); return ObjectUtils.notNullGetter(sysUser, SysUser::getUserName); } @@ -575,7 +586,7 @@ public class SysUserServiceImpl implements ISysUserService, UserService { @Cacheable(cacheNames = CacheNames.SYS_NICKNAME, key = "#userId") public String selectNicknameById(Long userId) { SysUser sysUser = baseMapper.selectOne(new LambdaQueryWrapper() - .select(SysUser::getNickName).eq(SysUser::getUserId, userId)); + .select(SysUser::getNickName).eq(SysUser::getUserId, userId)); return ObjectUtils.notNullGetter(sysUser, SysUser::getNickName); } @@ -606,7 +617,7 @@ public class SysUserServiceImpl implements ISysUserService, UserService { @Override public String selectPhonenumberById(Long userId) { SysUser sysUser = baseMapper.selectOne(new LambdaQueryWrapper() - .select(SysUser::getPhonenumber).eq(SysUser::getUserId, userId)); + .select(SysUser::getPhonenumber).eq(SysUser::getUserId, userId)); return ObjectUtils.notNullGetter(sysUser, SysUser::getPhonenumber); } @@ -619,7 +630,7 @@ public class SysUserServiceImpl implements ISysUserService, UserService { @Override public String selectEmailById(Long userId) { SysUser sysUser = baseMapper.selectOne(new LambdaQueryWrapper() - .select(SysUser::getEmail).eq(SysUser::getUserId, userId)); + .select(SysUser::getEmail).eq(SysUser::getUserId, userId)); return ObjectUtils.notNullGetter(sysUser, SysUser::getEmail); } @@ -635,9 +646,9 @@ public class SysUserServiceImpl implements ISysUserService, UserService { return List.of(); } List list = baseMapper.selectVoList(new LambdaQueryWrapper() - .select(SysUser::getUserId, SysUser::getUserName, SysUser::getNickName, SysUser::getEmail, SysUser::getPhonenumber) - .eq(SysUser::getStatus, SystemConstants.NORMAL) - .in(SysUser::getUserId, userIds)); + .select(SysUser::getUserId, SysUser::getUserName, SysUser::getNickName, SysUser::getEmail, SysUser::getPhonenumber) + .eq(SysUser::getStatus, SystemConstants.NORMAL) + .in(SysUser::getUserId, userIds)); return BeanUtil.copyToList(list, UserDTO.class); } @@ -653,7 +664,7 @@ public class SysUserServiceImpl implements ISysUserService, UserService { return List.of(); } List userRoles = userRoleMapper.selectList( - new LambdaQueryWrapper().in(SysUserRole::getRoleId, roleIds)); + new LambdaQueryWrapper().in(SysUserRole::getRoleId, roleIds)); return StreamUtils.toList(userRoles, SysUserRole::getUserId); } @@ -671,7 +682,7 @@ public class SysUserServiceImpl implements ISysUserService, UserService { // 通过角色ID获取用户角色信息 List userRoles = userRoleMapper.selectList( - new LambdaQueryWrapper().in(SysUserRole::getRoleId, roleIds)); + new LambdaQueryWrapper().in(SysUserRole::getRoleId, roleIds)); // 获取用户ID列表 Set userIds = StreamUtils.toSet(userRoles, SysUserRole::getUserId); @@ -691,9 +702,9 @@ public class SysUserServiceImpl implements ISysUserService, UserService { return List.of(); } List list = baseMapper.selectVoList(new LambdaQueryWrapper() - .select(SysUser::getUserId, SysUser::getUserName, SysUser::getNickName, SysUser::getEmail, SysUser::getPhonenumber) - .eq(SysUser::getStatus, SystemConstants.NORMAL) - .in(SysUser::getDeptId, deptIds)); + .select(SysUser::getUserId, SysUser::getUserName, SysUser::getNickName, SysUser::getEmail, SysUser::getPhonenumber) + .eq(SysUser::getStatus, SystemConstants.NORMAL) + .in(SysUser::getDeptId, deptIds)); return BeanUtil.copyToList(list, UserDTO.class); } @@ -711,7 +722,7 @@ public class SysUserServiceImpl implements ISysUserService, UserService { // 通过岗位ID获取用户岗位信息 List userPosts = userPostMapper.selectList( - new LambdaQueryWrapper().in(SysUserPost::getPostId, postIds)); + new LambdaQueryWrapper().in(SysUserPost::getPostId, postIds)); // 获取用户ID列表 Set userIds = StreamUtils.toSet(userPosts, SysUserPost::getUserId); @@ -731,11 +742,11 @@ public class SysUserServiceImpl implements ISysUserService, UserService { return Collections.emptyMap(); } return baseMapper.selectList( - new LambdaQueryWrapper() - .select(SysUser::getUserId, SysUser::getNickName) - .in(SysUser::getUserId, userIds) - ).stream() - .collect(Collectors.toMap(SysUser::getUserId, SysUser::getNickName)); + new LambdaQueryWrapper() + .select(SysUser::getUserId, SysUser::getNickName) + .in(SysUser::getUserId, userIds) + ).stream() + .collect(Collectors.toMap(SysUser::getUserId, SysUser::getNickName)); } /** @@ -750,11 +761,11 @@ public class SysUserServiceImpl implements ISysUserService, UserService { return Collections.emptyMap(); } return roleMapper.selectList( - new LambdaQueryWrapper() - .select(SysRole::getRoleId, SysRole::getRoleName) - .in(SysRole::getRoleId, roleIds) - ).stream() - .collect(Collectors.toMap(SysRole::getRoleId, SysRole::getRoleName)); + new LambdaQueryWrapper() + .select(SysRole::getRoleId, SysRole::getRoleName) + .in(SysRole::getRoleId, roleIds) + ).stream() + .collect(Collectors.toMap(SysRole::getRoleId, SysRole::getRoleName)); } /** @@ -769,11 +780,11 @@ public class SysUserServiceImpl implements ISysUserService, UserService { return Collections.emptyMap(); } return deptMapper.selectList( - new LambdaQueryWrapper() - .select(SysDept::getDeptId, SysDept::getDeptName) - .in(SysDept::getDeptId, deptIds) - ).stream() - .collect(Collectors.toMap(SysDept::getDeptId, SysDept::getDeptName)); + new LambdaQueryWrapper() + .select(SysDept::getDeptId, SysDept::getDeptName) + .in(SysDept::getDeptId, deptIds) + ).stream() + .collect(Collectors.toMap(SysDept::getDeptId, SysDept::getDeptName)); } /** @@ -788,11 +799,11 @@ public class SysUserServiceImpl implements ISysUserService, UserService { return Collections.emptyMap(); } return postMapper.selectList( - new LambdaQueryWrapper() - .select(SysPost::getPostId, SysPost::getPostName) - .in(SysPost::getPostId, postIds) - ).stream() - .collect(Collectors.toMap(SysPost::getPostId, SysPost::getPostName)); + new LambdaQueryWrapper() + .select(SysPost::getPostId, SysPost::getPostName) + .in(SysPost::getPostId, postIds) + ).stream() + .collect(Collectors.toMap(SysPost::getPostId, SysPost::getPostName)); } } From 370783b4574c09929adfad664bb6aacf72efdf5d Mon Sep 17 00:00:00 2001 From: chenyouting <514333061@qq.com> Date: Thu, 31 Jul 2025 18:09:20 +0800 Subject: [PATCH 03/19] =?UTF-8?q?=E4=BB=A3=E7=A0=81=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../app/domain/dto/DeviceInstructDto.java | 2 +- .../app/service/AppDeviceBizService.java | 100 ++++++++++-------- .../constants/DeviceRedisKeyConstants.java | 12 +++ .../rule/ActiveReportingDeviceDataRule.java | 9 +- ...lInfoRule.java => DeviceBootLogoRule.java} | 7 +- .../global/mqtt/rule/LocationDataRule.java | 16 ++- .../app/domain/vo/AppDeviceDetailVo.java | 26 ++++- .../equipment/domain/vo/AppDeviceVo.java | 9 ++ 8 files changed, 121 insertions(+), 60 deletions(-) create mode 100644 fys-admin/src/main/java/com/fuyuanshen/global/mqtt/constants/DeviceRedisKeyConstants.java rename fys-admin/src/main/java/com/fuyuanshen/global/mqtt/rule/{PersonnelInfoRule.java => DeviceBootLogoRule.java} (89%) diff --git a/fys-admin/src/main/java/com/fuyuanshen/app/domain/dto/DeviceInstructDto.java b/fys-admin/src/main/java/com/fuyuanshen/app/domain/dto/DeviceInstructDto.java index f176699..074bed3 100644 --- a/fys-admin/src/main/java/com/fuyuanshen/app/domain/dto/DeviceInstructDto.java +++ b/fys-admin/src/main/java/com/fuyuanshen/app/domain/dto/DeviceInstructDto.java @@ -11,6 +11,6 @@ public class DeviceInstructDto { /** * 下发指令 */ - private Object instructValue; + private String instructValue; } diff --git a/fys-admin/src/main/java/com/fuyuanshen/app/service/AppDeviceBizService.java b/fys-admin/src/main/java/com/fuyuanshen/app/service/AppDeviceBizService.java index c5acd24..4489ba0 100644 --- a/fys-admin/src/main/java/com/fuyuanshen/app/service/AppDeviceBizService.java +++ b/fys-admin/src/main/java/com/fuyuanshen/app/service/AppDeviceBizService.java @@ -13,7 +13,6 @@ import com.fuyuanshen.app.domain.dto.APPReNameDTO; import com.fuyuanshen.app.domain.dto.AppDeviceLogoUploadDto; import com.fuyuanshen.app.domain.dto.DeviceInstructDto; import com.fuyuanshen.app.domain.vo.APPDeviceTypeVo; -import com.fuyuanshen.app.domain.vo.AppDeviceBindRecordVo; import com.fuyuanshen.app.domain.vo.AppDeviceDetailVo; import com.fuyuanshen.app.domain.vo.AppPersonnelInfoVo; import com.fuyuanshen.app.mapper.AppDeviceBindRecordMapper; @@ -38,12 +37,9 @@ import com.fuyuanshen.equipment.enums.BindingStatusEnum; import com.fuyuanshen.equipment.enums.CommunicationModeEnum; import com.fuyuanshen.equipment.mapper.DeviceMapper; import com.fuyuanshen.equipment.mapper.DeviceTypeMapper; - -import static com.fuyuanshen.common.core.utils.Bitmap80x12Generator.*; -import static com.fuyuanshen.common.core.utils.ImageToCArrayConverter.convertHexToDecimal; - import com.fuyuanshen.equipment.utils.c.ReliableTextToBitmap; import com.fuyuanshen.global.mqtt.config.MqttGateway; +import com.fuyuanshen.global.mqtt.constants.DeviceRedisKeyConstants; import com.fuyuanshen.global.mqtt.constants.MqttConstants; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; @@ -53,6 +49,11 @@ import org.springframework.web.multipart.MultipartFile; import java.time.Duration; import java.util.*; +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; + @Slf4j @Service @@ -117,6 +118,31 @@ public class AppDeviceBizService { bo.setBindingUserId(userId); } Page result = deviceMapper.queryAppBindDeviceList(pageQuery.build(), bo); + List records = result.getRecords(); + if(records != null && !records.isEmpty()){ + records.forEach(item -> { + if(item.getCommunicationMode()!=null && item.getCommunicationMode() == 0){ + + //设备在线状态 + String onlineStatus = RedisUtils.getCacheObject(GLOBAL_REDIS_KEY+DeviceRedisKeyConstants.DEVICE_ONLINE_STATUS_KEY_PREFIX + item.getDeviceImei()); + if(StringUtils.isNotBlank(onlineStatus)){ + + item.setOnlineStatus(1); + }else{ + item.setOnlineStatus(0); + } + String deviceStatus = RedisUtils.getCacheObject(GLOBAL_REDIS_KEY+DeviceRedisKeyConstants.DEVICE_STATUS_KEY_PREFIX + item.getDeviceImei()); + // 获取电量 + if(StringUtils.isNotBlank(deviceStatus)){ + JSONObject jsonObject = JSONObject.parseObject(deviceStatus); + item.setBattery(jsonObject.getString("batteryPercentage")); + }else{ + item.setBattery("0"); + } + + } + }); + } return TableDataInfo.build(result); } @@ -275,44 +301,28 @@ public class AppDeviceBizService { AppPersonnelInfoVo personnelInfoVo = MapstructUtils.convert(appPersonnelInfo, AppPersonnelInfoVo.class); vo.setPersonnelInfo(personnelInfoVo); } + //设备在线状态 + String onlineStatus = RedisUtils.getCacheObject(GLOBAL_REDIS_KEY+DeviceRedisKeyConstants.DEVICE_ONLINE_STATUS_KEY_PREFIX + device.getDeviceImei()); + if(StringUtils.isNotBlank(onlineStatus)){ + vo.setOnlineStatus(1); + }else{ + vo.setOnlineStatus(0); + } + String deviceStatus = RedisUtils.getCacheObject(GLOBAL_REDIS_KEY+DeviceRedisKeyConstants.DEVICE_STATUS_KEY_PREFIX + device.getDeviceImei()); + // 获取电量 + if(StringUtils.isNotBlank(deviceStatus)){ + JSONObject jsonObject = JSONObject.parseObject(deviceStatus); + vo.setMainLightMode(jsonObject.getString("mainLightMode")); + vo.setLaserLightMode(jsonObject.getString("laserLightMode")); + vo.setBatteryPercentage(jsonObject.getString("batteryPercentage")); + vo.setChargeState(jsonObject.getString("chargeState")); + vo.setBatteryRemainingTime(jsonObject.getString("batteryRemainingTime")); + }else{ + vo.setBatteryPercentage("0"); + } return vo; } - public static void main(String[] args) { - byte[] unitName = generateFixedBitmapData("富源晟科技", 120); - byte[] position = generateFixedBitmapData("研发", 120); - byte[] name = generateFixedBitmapData("张三", 120); - byte[] id = generateFixedBitmapData("123456", 120); -// int[] intUnitNames = Bitmap80x12Generator.convertHexToDecimal(unitName); -// int[] intPosition = Bitmap80x12Generator.convertHexToDecimal(position); -// int[] intNames = Bitmap80x12Generator.convertHexToDecimal(position); -// int[] intIds = Bitmap80x12Generator.convertHexToDecimal(position); -// Map map = new HashMap<>(); -// map.put("instruct", 2); -// System.out.println(JSON.toJSONString( map)); -// StringBuilder sb = new StringBuilder(); -// sb.append("[") -// buildStr(unitName, sb); -// System.out.println(sb.toString()); -// Object[] arr = new Object[]{2, Bitmap80x12Generator , Arrays.toString(name), Arrays.toString(id)}; - -// System.out.println(Arrays.deepToString(arr)); -// int[] a = new int[]{6,6,6,6,6,6}; - ArrayList intData = new ArrayList<>(); - intData.add(2); - buildArr(convertHexToDecimal(unitName), intData); - buildArr(convertHexToDecimal(position), intData); - buildArr(convertHexToDecimal(name), intData); - buildArr(convertHexToDecimal(id), intData); - intData.add(0); - intData.add(0); - intData.add(0); - intData.add(0); - Map map = new HashMap<>(); - map.put("instruct", intData); - System.out.println(JSON.toJSONString(map)); - } - public boolean registerPersonInfo(AppPersonnelInfoBo bo) { Long deviceId = bo.getDeviceId(); @@ -373,9 +383,9 @@ public class AppDeviceBizService { System.out.println("原始数据大小: " + largeData.length + " 字节"); int[] ints = convertHexToDecimal(largeData); - RedisUtils.setCacheObject("app_logo_data:" + device.getDeviceImei(), Arrays.toString(ints), Duration.ofSeconds(30 * 60L)); + RedisUtils.setCacheObject(GLOBAL_REDIS_KEY+"app_logo_data:" + device.getDeviceImei(), Arrays.toString(ints), Duration.ofSeconds(30 * 60L)); - String data = RedisUtils.getCacheObject("app_logo_data:" + device.getDeviceImei()); + String data = RedisUtils.getCacheObject(GLOBAL_REDIS_KEY+"app_logo_data:" + device.getDeviceImei()); byte[] arr = ImageToCArrayConverter.convertStringToByteArray(data); byte[] specificChunk = ImageToCArrayConverter.getChunk(arr, 0, 512); @@ -410,7 +420,7 @@ public class AppDeviceBizService { if(device == null){ throw new ServiceException("设备不存在"); } - Integer instructValue = (Integer) params.getInstructValue(); + Integer instructValue = Integer.parseInt(params.getInstructValue()); ArrayList intData = new ArrayList<>(); intData.add(1); intData.add(instructValue); @@ -434,7 +444,7 @@ public class AppDeviceBizService { if(device == null){ throw new ServiceException("设备不存在"); } - String instructValue = (String)params.getInstructValue(); + String instructValue = params.getInstructValue(); ArrayList intData = new ArrayList<>(); intData.add(5); String[] values = instructValue.split("\\."); @@ -466,7 +476,7 @@ public class AppDeviceBizService { if(device == null){ throw new ServiceException("设备不存在"); } - Integer instructValue = (Integer) params.getInstructValue(); + Integer instructValue = Integer.parseInt(params.getInstructValue()); ArrayList intData = new ArrayList<>(); intData.add(4); intData.add(instructValue); diff --git a/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/constants/DeviceRedisKeyConstants.java b/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/constants/DeviceRedisKeyConstants.java new file mode 100644 index 0000000..d92ec38 --- /dev/null +++ b/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/constants/DeviceRedisKeyConstants.java @@ -0,0 +1,12 @@ +package com.fuyuanshen.global.mqtt.constants; + +public class DeviceRedisKeyConstants { + // 将设备上报状态 + public static final String DEVICE_STATUS_KEY_PREFIX = "device:status:"; + // 在线状态 + public static final String DEVICE_ONLINE_STATUS_KEY_PREFIX = "device:onlineStatus:"; + // 将设备状态信息存储到Redis中 + public static final String DEVICE_LOCATION_KEY_PREFIX = "device:location:"; + // 存储到一个列表中,保留历史位置信息 + public static final String DEVICE_LOCATION_HISTORY_KEY_PREFIX = "device:location:history:"; +} diff --git a/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/rule/ActiveReportingDeviceDataRule.java b/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/rule/ActiveReportingDeviceDataRule.java index bad3faa..fecffbe 100644 --- a/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/rule/ActiveReportingDeviceDataRule.java +++ b/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/rule/ActiveReportingDeviceDataRule.java @@ -1,10 +1,12 @@ package com.fuyuanshen.global.mqtt.rule; +import com.fuyuanshen.common.core.constant.GlobalConstants; import com.fuyuanshen.common.json.utils.JsonUtils; import com.fuyuanshen.common.redis.utils.RedisUtils; import com.fuyuanshen.global.mqtt.base.MqttMessageRule; import com.fuyuanshen.global.mqtt.base.MqttRuleContext; import com.fuyuanshen.global.mqtt.config.MqttGateway; +import com.fuyuanshen.global.mqtt.constants.DeviceRedisKeyConstants; import com.fuyuanshen.global.mqtt.constants.LightingCommandTypeConstants; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; @@ -78,11 +80,14 @@ public class ActiveReportingDeviceDataRule implements MqttMessageRule { deviceInfo.put("timestamp", System.currentTimeMillis()); // 将设备状态信息存储到Redis中 - String deviceRedisKey = "device:status:" + deviceImei; + String deviceRedisKey = GlobalConstants.GLOBAL_REDIS_KEY+DeviceRedisKeyConstants.DEVICE_STATUS_KEY_PREFIX + deviceImei; String deviceInfoJson = JsonUtils.toJsonString(deviceInfo); // 存储到Redis,设置过期时间(例如24小时) - RedisUtils.setCacheObject(deviceRedisKey, deviceInfoJson, Duration.ofSeconds(24 * 60 * 60)); + RedisUtils.setCacheObject(deviceRedisKey, deviceInfoJson); + //在线状态 + String deviceOnlineStatusRedisKey = GlobalConstants.GLOBAL_REDIS_KEY+DeviceRedisKeyConstants.DEVICE_ONLINE_STATUS_KEY_PREFIX + deviceImei; + RedisUtils.setCacheObject(deviceOnlineStatusRedisKey, "1"); log.info("设备状态信息已异步发送到Redis: device={}, mainLightMode={}, laserLightMode={}, batteryPercentage={}", deviceImei, mainLightMode, laserLightMode, batteryPercentage); diff --git a/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/rule/PersonnelInfoRule.java b/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/rule/DeviceBootLogoRule.java similarity index 89% rename from fys-admin/src/main/java/com/fuyuanshen/global/mqtt/rule/PersonnelInfoRule.java rename to fys-admin/src/main/java/com/fuyuanshen/global/mqtt/rule/DeviceBootLogoRule.java index eed9bde..2d605a9 100644 --- a/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/rule/PersonnelInfoRule.java +++ b/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/rule/DeviceBootLogoRule.java @@ -1,5 +1,6 @@ package com.fuyuanshen.global.mqtt.rule; +import com.fuyuanshen.common.core.constant.GlobalConstants; import com.fuyuanshen.common.core.utils.ImageToCArrayConverter; import com.fuyuanshen.common.core.utils.StringUtils; import com.fuyuanshen.common.json.utils.JsonUtils; @@ -26,13 +27,13 @@ import static com.fuyuanshen.common.core.utils.ImageToCArrayConverter.convertHex @Component @RequiredArgsConstructor @Slf4j -public class PersonnelInfoRule implements MqttMessageRule { +public class DeviceBootLogoRule implements MqttMessageRule { private final MqttGateway mqttGateway; @Override public String getCommandType() { - return LightingCommandTypeConstants.PERSONNEL_INFO; + return LightingCommandTypeConstants.BOOT_LOGO; } @Override @@ -43,7 +44,7 @@ public class PersonnelInfoRule implements MqttMessageRule { return; } - String data = RedisUtils.getCacheObject("894078:app_logo_data:" + context.getDeviceImei()); + String data = RedisUtils.getCacheObject(GlobalConstants.GLOBAL_REDIS_KEY+"app_logo_data:" + context.getDeviceImei()); if (StringUtils.isEmpty(data)) { return; } diff --git a/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/rule/LocationDataRule.java b/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/rule/LocationDataRule.java index feae373..37b4302 100644 --- a/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/rule/LocationDataRule.java +++ b/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/rule/LocationDataRule.java @@ -1,5 +1,6 @@ package com.fuyuanshen.global.mqtt.rule; +import com.fuyuanshen.common.core.constant.GlobalConstants; import com.fuyuanshen.common.core.utils.StringUtils; import com.fuyuanshen.common.json.utils.JsonUtils; import com.fuyuanshen.common.redis.utils.RedisUtils; @@ -8,6 +9,7 @@ import com.fuyuanshen.equipment.utils.map.LngLonUtil; import com.fuyuanshen.global.mqtt.base.MqttMessageRule; import com.fuyuanshen.global.mqtt.base.MqttRuleContext; import com.fuyuanshen.global.mqtt.config.MqttGateway; +import com.fuyuanshen.global.mqtt.constants.DeviceRedisKeyConstants; import com.fuyuanshen.global.mqtt.constants.LightingCommandTypeConstants; import com.fuyuanshen.global.mqtt.constants.MqttConstants; import lombok.RequiredArgsConstructor; @@ -118,12 +120,16 @@ public class LocationDataRule implements MqttMessageRule { // 将位置信息存储到Redis中 - String redisKey = "device:location:" + deviceImei; + String redisKey = GlobalConstants.GLOBAL_REDIS_KEY+DeviceRedisKeyConstants.DEVICE_LOCATION_KEY_PREFIX + deviceImei; String locationJson = JsonUtils.toJsonString(locationInfo); // 存储到Redis - RedisUtils.setCacheObject(redisKey, locationJson, Duration.ofSeconds(24 * 60 * 60)); + RedisUtils.setCacheObject(redisKey, locationJson); + // 存储到一个列表中,保留历史位置信息 + String locationHistoryKey = GlobalConstants.GLOBAL_REDIS_KEY+DeviceRedisKeyConstants.DEVICE_LOCATION_HISTORY_KEY_PREFIX + deviceImei; + RedisUtils.addCacheList(locationHistoryKey, locationJson); + RedisUtils.expire(locationHistoryKey, Duration.ofDays(90)); log.info("位置信息已异步发送到Redis: device={}, lat={}, lon={}", deviceImei, latitude, longitude); } catch (Exception e) { log.error("异步发送位置信息到Redis时出错: device={}, error={}", deviceImei, e.getMessage(), e); @@ -138,9 +144,11 @@ public class LocationDataRule implements MqttMessageRule { ArrayList intData = new ArrayList<>(); intData.add(11); intData.add(Integer.parseInt(latArr[0])); - intData.add(Integer.parseInt(latArr[1])); + String str1 = latArr[1]; + intData.add(Integer.parseInt(str1.substring(0,4))); + String str2 = lonArr[1]; intData.add(Integer.parseInt(lonArr[0])); - intData.add(Integer.parseInt(lonArr[1])); + intData.add(Integer.parseInt(str2.substring(0,4))); Map map = new HashMap<>(); map.put("instruct", intData); diff --git a/fys-modules/fys-app/src/main/java/com/fuyuanshen/app/domain/vo/AppDeviceDetailVo.java b/fys-modules/fys-app/src/main/java/com/fuyuanshen/app/domain/vo/AppDeviceDetailVo.java index d90f808..c2c3be8 100644 --- a/fys-modules/fys-app/src/main/java/com/fuyuanshen/app/domain/vo/AppDeviceDetailVo.java +++ b/fys-modules/fys-app/src/main/java/com/fuyuanshen/app/domain/vo/AppDeviceDetailVo.java @@ -16,11 +16,6 @@ public class AppDeviceDetailVo { @ExcelProperty(value = "设备ID") private Long deviceId; - /** - * 手机号 - */ - @ExcelProperty(value = "手机号") - private String phonenumber; /** * 设备名称 @@ -74,4 +69,25 @@ public class AppDeviceDetailVo { * 发送信息 */ private String sendMsg; + + //"{\"deviceImei\":\"AA\",\"mainLightMode\":\"1\",\"laserLightMode\":\"0\",\"batteryPercentage\":\"60\",\"chargeState\":\"1\",\"batteryRemainingTime\":\"200\",\"timestamp\":1753871635241}" + //设备主灯档位 + private String mainLightMode; + + //激光灯档位 + private String laserLightMode; + + //电量百分比 + private String batteryPercentage; + + //充电状态(0没有充电,1正在充电,2为已充满) + private String chargeState; + + //电池剩余续航时间200分钟 + private String batteryRemainingTime; + + /** + * 在线状态(0离线,1在线) + */ + private Integer onlineStatus; } diff --git a/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/domain/vo/AppDeviceVo.java b/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/domain/vo/AppDeviceVo.java index e948312..ac35877 100644 --- a/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/domain/vo/AppDeviceVo.java +++ b/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/domain/vo/AppDeviceVo.java @@ -57,4 +57,13 @@ public class AppDeviceVo implements Serializable { */ private Date bindingTime; + /** + * 在线状态(0离线,1在线) + */ + private Integer onlineStatus; + + /** + * 电量 百分比 + */ + private String battery; } From 74be5321ec9b2a98d252d1f2e223f6bb866939d7 Mon Sep 17 00:00:00 2001 From: chenyouting <514333061@qq.com> Date: Thu, 31 Jul 2025 19:03:04 +0800 Subject: [PATCH 04/19] =?UTF-8?q?=E4=BB=A3=E7=A0=81=E4=BC=98=E5=8C=962?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../app/controller/AppAuthController.java | 9 ++++++++ .../app/service/AppDeviceBizService.java | 11 ++++++++++ .../app/service/AppLoginService.java | 22 ++++++++++++++++++- .../app/domain/vo/AppDeviceDetailVo.java | 9 ++++++++ 4 files changed, 50 insertions(+), 1 deletion(-) diff --git a/fys-admin/src/main/java/com/fuyuanshen/app/controller/AppAuthController.java b/fys-admin/src/main/java/com/fuyuanshen/app/controller/AppAuthController.java index 9d32a5a..d483e45 100644 --- a/fys-admin/src/main/java/com/fuyuanshen/app/controller/AppAuthController.java +++ b/fys-admin/src/main/java/com/fuyuanshen/app/controller/AppAuthController.java @@ -104,6 +104,15 @@ public class AppAuthController { return R.ok("退出成功"); } + /** + * 用户注销 + */ + @PostMapping("/cancelAccount") + public R cancelAccount() { + loginService.cancelAccount(); + return R.ok("用户注销成功"); + } + /** * 用户注册 */ diff --git a/fys-admin/src/main/java/com/fuyuanshen/app/service/AppDeviceBizService.java b/fys-admin/src/main/java/com/fuyuanshen/app/service/AppDeviceBizService.java index 4489ba0..1a0cd9d 100644 --- a/fys-admin/src/main/java/com/fuyuanshen/app/service/AppDeviceBizService.java +++ b/fys-admin/src/main/java/com/fuyuanshen/app/service/AppDeviceBizService.java @@ -18,6 +18,7 @@ import com.fuyuanshen.app.domain.vo.AppPersonnelInfoVo; import com.fuyuanshen.app.mapper.AppDeviceBindRecordMapper; import com.fuyuanshen.app.mapper.AppPersonnelInfoMapper; import com.fuyuanshen.app.mapper.equipment.APPDeviceMapper; +import com.fuyuanshen.common.core.constant.GlobalConstants; import com.fuyuanshen.common.core.exception.ServiceException; import com.fuyuanshen.common.core.utils.ImageToCArrayConverter; import com.fuyuanshen.common.core.utils.MapstructUtils; @@ -320,6 +321,16 @@ public class AppDeviceBizService { }else{ vo.setBatteryPercentage("0"); } + + // 获取经度纬度 + String locationInfo = GlobalConstants.GLOBAL_REDIS_KEY+DeviceRedisKeyConstants.DEVICE_LOCATION_KEY_PREFIX + device.getDeviceImei(); + if(StringUtils.isNotBlank(locationInfo)){ + JSONObject jsonObject = JSONObject.parseObject(locationInfo); + vo.setLongitude((String)jsonObject.get("longitude")); + vo.setLatitude((String)jsonObject.get("latitude")); + vo.setAddress((String)jsonObject.get("address")); + } + return vo; } diff --git a/fys-admin/src/main/java/com/fuyuanshen/app/service/AppLoginService.java b/fys-admin/src/main/java/com/fuyuanshen/app/service/AppLoginService.java index bd92c2b..0c86da2 100644 --- a/fys-admin/src/main/java/com/fuyuanshen/app/service/AppLoginService.java +++ b/fys-admin/src/main/java/com/fuyuanshen/app/service/AppLoginService.java @@ -51,7 +51,7 @@ public class AppLoginService { private Integer lockTime; private final ISysTenantService tenantService; - private final IAppRoleService roleService; + private final IAppUserService appUserService; /** @@ -185,4 +185,24 @@ public class AppLoginService { } } + public void cancelAccount() { + try { + AppLoginUser loginUser = AppLoginHelper.getLoginUser(); + if (ObjectUtil.isNull(loginUser)) { + return; + } + appUserService.deleteWithValidByIds(Collections.singletonList(loginUser.getUserId()),true); + if (TenantHelper.isEnable() && LoginHelper.isSuperAdmin()) { + // 超级管理员 登出清除动态租户 + TenantHelper.clearDynamic(); + } + recordLogininfor(loginUser.getTenantId(), loginUser.getUsername(), Constants.LOGOUT, "用户注销成功"); + } catch (NotLoginException ignored) { + } finally { + try { + StpUtil.logout(); + } catch (NotLoginException ignored) { + } + } + } } diff --git a/fys-modules/fys-app/src/main/java/com/fuyuanshen/app/domain/vo/AppDeviceDetailVo.java b/fys-modules/fys-app/src/main/java/com/fuyuanshen/app/domain/vo/AppDeviceDetailVo.java index c2c3be8..6478ea4 100644 --- a/fys-modules/fys-app/src/main/java/com/fuyuanshen/app/domain/vo/AppDeviceDetailVo.java +++ b/fys-modules/fys-app/src/main/java/com/fuyuanshen/app/domain/vo/AppDeviceDetailVo.java @@ -90,4 +90,13 @@ public class AppDeviceDetailVo { * 在线状态(0离线,1在线) */ private Integer onlineStatus; + + // 经度 + private String longitude; + + // 纬度 + private String latitude; + + // 逆解析地址 + private String address; } From 51d9d7319a920592dc7b77e9e531b77cfe1c700f Mon Sep 17 00:00:00 2001 From: chenyouting <514333061@qq.com> Date: Fri, 1 Aug 2025 11:11:36 +0800 Subject: [PATCH 05/19] =?UTF-8?q?app=E8=AE=BE=E5=A4=87=E5=88=97=E8=A1=A8?= =?UTF-8?q?=E6=9F=A5=E8=AF=A2=EF=BC=8C=E6=96=B0=E5=A2=9E=E7=BA=AC=E5=BA=A6?= =?UTF-8?q?=E7=BB=8F=E5=BA=A6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../app/service/AppDeviceBizService.java | 12 +++++++++++- .../mqtt/receiver/ReceiverMessageHandler.java | 17 ++++++++++++----- .../rule/ActiveReportingDeviceDataRule.java | 3 --- .../global/mqtt/rule/DeviceBootLogoRule.java | 2 +- .../app/service/impl/AppUserServiceImpl.java | 9 +++++++++ .../equipment/domain/vo/AppDeviceVo.java | 10 ++++++++++ 6 files changed, 43 insertions(+), 10 deletions(-) diff --git a/fys-admin/src/main/java/com/fuyuanshen/app/service/AppDeviceBizService.java b/fys-admin/src/main/java/com/fuyuanshen/app/service/AppDeviceBizService.java index 1a0cd9d..1815dcf 100644 --- a/fys-admin/src/main/java/com/fuyuanshen/app/service/AppDeviceBizService.java +++ b/fys-admin/src/main/java/com/fuyuanshen/app/service/AppDeviceBizService.java @@ -141,6 +141,15 @@ public class AppDeviceBizService { item.setBattery("0"); } + String location = RedisUtils.getCacheObject(GLOBAL_REDIS_KEY+DeviceRedisKeyConstants.DEVICE_LOCATION_KEY_PREFIX + item.getDeviceImei()); + // 获取电量 + if(StringUtils.isNotBlank(location)){ + JSONObject jsonObject = JSONObject.parseObject(location); + item.setLatitude(jsonObject.getString("latitude")); + item.setLongitude(jsonObject.getString("longitude")); + }else{ + item.setBattery("0"); + } } }); } @@ -323,7 +332,8 @@ public class AppDeviceBizService { } // 获取经度纬度 - String locationInfo = GlobalConstants.GLOBAL_REDIS_KEY+DeviceRedisKeyConstants.DEVICE_LOCATION_KEY_PREFIX + device.getDeviceImei(); + String locationKey = GlobalConstants.GLOBAL_REDIS_KEY+DeviceRedisKeyConstants.DEVICE_LOCATION_KEY_PREFIX + device.getDeviceImei(); + String locationInfo = RedisUtils.getCacheObject(locationKey); if(StringUtils.isNotBlank(locationInfo)){ JSONObject jsonObject = JSONObject.parseObject(locationInfo); vo.setLongitude((String)jsonObject.get("longitude")); diff --git a/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/receiver/ReceiverMessageHandler.java b/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/receiver/ReceiverMessageHandler.java index f7619a6..5baddf6 100644 --- a/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/receiver/ReceiverMessageHandler.java +++ b/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/receiver/ReceiverMessageHandler.java @@ -1,10 +1,14 @@ package com.fuyuanshen.global.mqtt.receiver; import cn.hutool.core.lang.Dict; +import com.fuyuanshen.common.core.constant.GlobalConstants; import com.fuyuanshen.common.core.utils.ImageToCArrayConverter; +import com.fuyuanshen.common.core.utils.StringUtils; import com.fuyuanshen.common.json.utils.JsonUtils; +import com.fuyuanshen.common.redis.utils.RedisUtils; import com.fuyuanshen.global.mqtt.base.MqttRuleContext; import com.fuyuanshen.global.mqtt.base.MqttRuleEngine; +import com.fuyuanshen.global.mqtt.constants.DeviceRedisKeyConstants; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.messaging.Message; @@ -37,16 +41,19 @@ public class ReceiverMessageHandler implements MessageHandler { if (receivedTopic == null || payloadDict == null) { return; } - + String[] subStr = receivedTopic.split("/"); + String deviceImei = subStr[1]; + if(StringUtils.isNotBlank(deviceImei)){ + //在线状态 + String deviceOnlineStatusRedisKey = GlobalConstants.GLOBAL_REDIS_KEY+ DeviceRedisKeyConstants.DEVICE_ONLINE_STATUS_KEY_PREFIX + deviceImei; + RedisUtils.setCacheObject(deviceOnlineStatusRedisKey, "1"); + } + String state = payloadDict.getStr("state"); Object[] convertArr = ImageToCArrayConverter.convertByteStringToMixedObjectArray(state); if (convertArr.length > 0) { Byte val1 = (Byte) convertArr[0]; - String[] subStr = receivedTopic.split("/"); - System.out.println("收到设备id: " + subStr[1]); - String deviceImei = subStr[1]; - MqttRuleContext context = new MqttRuleContext(); context.setCommandType(val1); context.setConvertArr(convertArr); diff --git a/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/rule/ActiveReportingDeviceDataRule.java b/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/rule/ActiveReportingDeviceDataRule.java index fecffbe..6b37a47 100644 --- a/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/rule/ActiveReportingDeviceDataRule.java +++ b/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/rule/ActiveReportingDeviceDataRule.java @@ -85,9 +85,6 @@ public class ActiveReportingDeviceDataRule implements MqttMessageRule { // 存储到Redis,设置过期时间(例如24小时) RedisUtils.setCacheObject(deviceRedisKey, deviceInfoJson); - //在线状态 - String deviceOnlineStatusRedisKey = GlobalConstants.GLOBAL_REDIS_KEY+DeviceRedisKeyConstants.DEVICE_ONLINE_STATUS_KEY_PREFIX + deviceImei; - RedisUtils.setCacheObject(deviceOnlineStatusRedisKey, "1"); log.info("设备状态信息已异步发送到Redis: device={}, mainLightMode={}, laserLightMode={}, batteryPercentage={}", deviceImei, mainLightMode, laserLightMode, batteryPercentage); diff --git a/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/rule/DeviceBootLogoRule.java b/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/rule/DeviceBootLogoRule.java index 2d605a9..8b83e0f 100644 --- a/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/rule/DeviceBootLogoRule.java +++ b/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/rule/DeviceBootLogoRule.java @@ -52,7 +52,7 @@ public class DeviceBootLogoRule implements MqttMessageRule { byte[] arr = ImageToCArrayConverter.convertStringToByteArray(data); byte[] specificChunk = ImageToCArrayConverter.getChunk(arr, (val2 - 1), 512); System.out.println("第" + val2 + "块数据大小: " + specificChunk.length + " 字节"); - System.out.println("第" + val2 + "块数据: " + Arrays.toString(specificChunk)); +// System.out.println("第" + val2 + "块数据: " + Arrays.toString(specificChunk)); ArrayList intData = new ArrayList<>(); intData.add(3); diff --git a/fys-modules/fys-app/src/main/java/com/fuyuanshen/app/service/impl/AppUserServiceImpl.java b/fys-modules/fys-app/src/main/java/com/fuyuanshen/app/service/impl/AppUserServiceImpl.java index a362fe4..5c18916 100644 --- a/fys-modules/fys-app/src/main/java/com/fuyuanshen/app/service/impl/AppUserServiceImpl.java +++ b/fys-modules/fys-app/src/main/java/com/fuyuanshen/app/service/impl/AppUserServiceImpl.java @@ -1,5 +1,10 @@ package com.fuyuanshen.app.service.impl; +import cn.dev33.satoken.exception.NotLoginException; +import cn.dev33.satoken.stp.StpUtil; +import cn.hutool.core.util.ObjectUtil; +import com.fuyuanshen.common.core.constant.Constants; +import com.fuyuanshen.common.core.domain.model.AppLoginUser; import com.fuyuanshen.common.core.utils.MapstructUtils; import com.fuyuanshen.common.core.utils.StringUtils; import com.fuyuanshen.common.mybatis.core.page.TableDataInfo; @@ -7,6 +12,9 @@ import com.fuyuanshen.common.mybatis.core.page.PageQuery; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.fuyuanshen.common.satoken.utils.AppLoginHelper; +import com.fuyuanshen.common.satoken.utils.LoginHelper; +import com.fuyuanshen.common.tenant.helper.TenantHelper; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; @@ -16,6 +24,7 @@ import com.fuyuanshen.app.domain.AppUser; import com.fuyuanshen.app.mapper.AppUserMapper; import com.fuyuanshen.app.service.IAppUserService; +import java.util.Collections; import java.util.List; import java.util.Map; import java.util.Collection; diff --git a/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/domain/vo/AppDeviceVo.java b/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/domain/vo/AppDeviceVo.java index ac35877..1642c7f 100644 --- a/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/domain/vo/AppDeviceVo.java +++ b/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/domain/vo/AppDeviceVo.java @@ -66,4 +66,14 @@ public class AppDeviceVo implements Serializable { * 电量 百分比 */ private String battery; + + /** + * 纬度 + */ + private String latitude; + + /** + * 经度 + */ + private String longitude; } From 6fb8e73535610c0bc038da5ca668f5d09e0e2b14 Mon Sep 17 00:00:00 2001 From: chenyouting <514333061@qq.com> Date: Fri, 1 Aug 2025 14:24:03 +0800 Subject: [PATCH 06/19] =?UTF-8?q?=E7=BB=8F=E7=BA=AC=E5=BA=A6bug=E4=BF=AE?= =?UTF-8?q?=E5=A4=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../LightingCommandTypeConstants.java | 34 +------------------ .../global/mqtt/rule/LocationDataRule.java | 2 +- 2 files changed, 2 insertions(+), 34 deletions(-) diff --git a/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/constants/LightingCommandTypeConstants.java b/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/constants/LightingCommandTypeConstants.java index 5687f33..64c8449 100644 --- a/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/constants/LightingCommandTypeConstants.java +++ b/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/constants/LightingCommandTypeConstants.java @@ -40,37 +40,5 @@ public class LightingCommandTypeConstants { * 主动上报设备数据 (Active Reporting Device Data) */ public static final String ACTIVE_REPORTING_DEVICE_DATA = "Light_12"; - - /** - * 获取命令类型描述 - * - * @param commandType 命令类型 - * @return 命令类型描述 - */ - public static String getCommandTypeDescription(String commandType) { - return switch (commandType) { - case LIGHT_MODE -> "灯光模式 (Light Mode)"; - case PERSONNEL_INFO -> "人员信息 (Personnel Information)"; - case BOOT_LOGO -> "开机LOGO (Boot Logo)"; - case LASER_LIGHT -> "激光灯 (Laser Light)"; - case MAIN_LIGHT_BRIGHTNESS -> "主灯亮度 (Main Light Brightness)"; - case LOCATION_DATA -> "定位数据 (Location Data)"; - default -> "未知命令类型 (Unknown Command Type)"; - }; - } - - /** - * 检查是否为有效命令类型 - * - * @param commandType 命令类型 - * @return 是否有效 - */ - public static boolean isValidCommandType(String commandType) { - return commandType.equals(LIGHT_MODE) || - commandType.equals(PERSONNEL_INFO) || - commandType.equals(BOOT_LOGO) || - commandType.equals(LASER_LIGHT) || - commandType.equals(MAIN_LIGHT_BRIGHTNESS) || - commandType.equals(LOCATION_DATA); - } + } diff --git a/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/rule/LocationDataRule.java b/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/rule/LocationDataRule.java index 37b4302..94499cf 100644 --- a/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/rule/LocationDataRule.java +++ b/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/rule/LocationDataRule.java @@ -105,7 +105,7 @@ public class LocationDataRule implements MqttMessageRule { public void asyncSendLocationToRedisWithFuture(String deviceImei, String latitude, String longitude) { CompletableFuture.runAsync(() -> { try { - if(StringUtils.isNotBlank(latitude) || StringUtils.isNotBlank(longitude)){ + if(StringUtils.isBlank(latitude) || StringUtils.isBlank(longitude)){ return; } // 构造位置信息对象 From 8770c217aeb67beea4b6914c77a17e16457e873d Mon Sep 17 00:00:00 2001 From: daiyongfei <974332738@qq.com> Date: Fri, 1 Aug 2025 15:19:41 +0800 Subject: [PATCH 07/19] =?UTF-8?q?=E8=AE=BE=E5=A4=87=E6=97=A5=E5=BF=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../CustomMqttInboundConfiguration.java | 56 +++++ .../web/enums/InstructType6170.java | 42 ++++ .../web/enums/LightModeEnum6170.java | 45 ++++ .../mqtt/DeviceReceiverMessageHandler.java | 236 ++++++++++++++++++ .../src/main/resources/application-dev.yml | 2 +- .../fuyuanshen/equipment/domain/Device.java | 4 + .../equipment/domain/DeviceLog.java | 10 +- .../equipment/domain/vo/DeviceLogVo.java | 7 + .../service/impl/DeviceLogServiceImpl.java | 7 +- 9 files changed, 403 insertions(+), 6 deletions(-) create mode 100644 fys-admin/src/main/java/com/fuyuanshen/web/config/CustomMqttInboundConfiguration.java create mode 100644 fys-admin/src/main/java/com/fuyuanshen/web/enums/InstructType6170.java create mode 100644 fys-admin/src/main/java/com/fuyuanshen/web/enums/LightModeEnum6170.java create mode 100644 fys-admin/src/main/java/com/fuyuanshen/web/handler/mqtt/DeviceReceiverMessageHandler.java diff --git a/fys-admin/src/main/java/com/fuyuanshen/web/config/CustomMqttInboundConfiguration.java b/fys-admin/src/main/java/com/fuyuanshen/web/config/CustomMqttInboundConfiguration.java new file mode 100644 index 0000000..f7f52ae --- /dev/null +++ b/fys-admin/src/main/java/com/fuyuanshen/web/config/CustomMqttInboundConfiguration.java @@ -0,0 +1,56 @@ +package com.fuyuanshen.web.config; + +import cn.hutool.core.lang.UUID; +import com.fuyuanshen.global.mqtt.config.MqttPropertiesConfig; +import com.fuyuanshen.web.handler.mqtt.DeviceReceiverMessageHandler; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.integration.annotation.ServiceActivator; +import org.springframework.integration.channel.DirectChannel; +import org.springframework.integration.core.MessageProducer; +import org.springframework.integration.mqtt.core.MqttPahoClientFactory; +import org.springframework.integration.mqtt.inbound.MqttPahoMessageDrivenChannelAdapter; +import org.springframework.integration.mqtt.support.DefaultPahoMessageConverter; +import org.springframework.messaging.MessageChannel; +import org.springframework.messaging.MessageHandler; + +/** + * @author: 默苍璃 + * @date: 2025-08-0110:46 + */ +@Configuration +public class CustomMqttInboundConfiguration { + @Autowired + private MqttPropertiesConfig mqttPropertiesConfig; + @Autowired + private MqttPahoClientFactory mqttPahoClientFactory; + @Autowired + private DeviceReceiverMessageHandler deviceReceiverMessageHandler; + + @Bean + public MessageChannel customMqttChannel(){ + return new DirectChannel(); + } + + @Bean + public MessageProducer customMessageProducer(){ + String clientId = "custom_client_" + UUID.fastUUID(); + MqttPahoMessageDrivenChannelAdapter adapter = new MqttPahoMessageDrivenChannelAdapter( + mqttPropertiesConfig.getUrl(), + clientId, + mqttPahoClientFactory, + "A/#", "B/#" // 直接指定这两个主题 + ); + adapter.setQos(1); + adapter.setConverter(new DefaultPahoMessageConverter()); + adapter.setOutputChannel(customMqttChannel()); + return adapter; + } + + @Bean + @ServiceActivator(inputChannel = "customMqttChannel") + public MessageHandler customMessageHandler(){ + return deviceReceiverMessageHandler; + } +} diff --git a/fys-admin/src/main/java/com/fuyuanshen/web/enums/InstructType6170.java b/fys-admin/src/main/java/com/fuyuanshen/web/enums/InstructType6170.java new file mode 100644 index 0000000..522b355 --- /dev/null +++ b/fys-admin/src/main/java/com/fuyuanshen/web/enums/InstructType6170.java @@ -0,0 +1,42 @@ +package com.fuyuanshen.web.enums; + +/** + * @author: 默苍璃 + * @date: 2025-08-0114:14 + */ +public enum InstructType6170 { + + EQUIPMENT_REPORTING(0, "设备上报"), + LIGHT_MODE(1, "灯光模式"), + UNIT_INFO(2, "单位/姓名/职位"), + BOOT_IMAGE(3, "开机图片"), + LASER_LIGHT(4, "激光灯"), + BRIGHTNESS(5, "亮度调节"), + LOCATION_DATA(11, "定位数据"); + + private final int code; + private final String description; + + InstructType6170(int code, String description) { + this.code = code; + this.description = description; + } + + public int getCode() { + return code; + } + + public String getDescription() { + return description; + } + + public static InstructType6170 fromCode(int code) { + for (InstructType6170 type : values()) { + if (type.getCode() == code) { + return type; + } + } + throw new IllegalArgumentException("未知的指令类型代码: " + code); + } + +} diff --git a/fys-admin/src/main/java/com/fuyuanshen/web/enums/LightModeEnum6170.java b/fys-admin/src/main/java/com/fuyuanshen/web/enums/LightModeEnum6170.java new file mode 100644 index 0000000..1054481 --- /dev/null +++ b/fys-admin/src/main/java/com/fuyuanshen/web/enums/LightModeEnum6170.java @@ -0,0 +1,45 @@ +package com.fuyuanshen.web.enums; + +/** + * @author: 默苍璃 + * @date: 2025-08-0114:30 + */ +public enum LightModeEnum6170 { + + OFF(0, "关灯"), + HIGH_BEAM(1, "强光模式"), + LOW_BEAM(2, "弱光模式"), + STROBE(3, "爆闪模式"), + FLOOD(4, "泛光模式"), + + UNKNOWN(-1, "未知的灯光模式"); + + + private final int code; + private final String description; + + + LightModeEnum6170(int code, String description) { + this.code = code; + this.description = description; + } + + public int getCode() { + return code; + } + + public String getDescription() { + return description; + } + + public static LightModeEnum6170 fromCode(int code) { + for (LightModeEnum6170 mode : values()) { + if (mode.getCode() == code) { + return mode; + } + } + // throw new IllegalArgumentException("未知的灯光模式代码: " + code); + return UNKNOWN; + } + +} diff --git a/fys-admin/src/main/java/com/fuyuanshen/web/handler/mqtt/DeviceReceiverMessageHandler.java b/fys-admin/src/main/java/com/fuyuanshen/web/handler/mqtt/DeviceReceiverMessageHandler.java new file mode 100644 index 0000000..717aedf --- /dev/null +++ b/fys-admin/src/main/java/com/fuyuanshen/web/handler/mqtt/DeviceReceiverMessageHandler.java @@ -0,0 +1,236 @@ +package com.fuyuanshen.web.handler.mqtt; + +import cn.hutool.core.collection.CollectionUtil; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fuyuanshen.app.domain.APPDevice; +import com.fuyuanshen.app.enums.UserType; +import com.fuyuanshen.equipment.domain.Device; +import com.fuyuanshen.equipment.domain.DeviceLog; +import com.fuyuanshen.equipment.mapper.DeviceLogMapper; +import com.fuyuanshen.equipment.mapper.DeviceMapper; +import com.fuyuanshen.web.enums.InstructType6170; +import com.fuyuanshen.web.enums.LightModeEnum6170; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.messaging.Message; +import org.springframework.messaging.MessageHandler; +import org.springframework.messaging.MessageHeaders; +import org.springframework.messaging.MessagingException; +import org.springframework.stereotype.Component; + +import java.util.List; + +/** + * 定义监听主题消息的处理器 + * + * @author: 默苍璃 + * @date: 2025-08-0110:19 + */ +@Component +@Data +@AllArgsConstructor +@Slf4j +public class DeviceReceiverMessageHandler implements MessageHandler { + + private final DeviceMapper deviceMapper; + private final DeviceLogMapper deviceLogMapper; + + // 使用Jackson解析JSON + private static final ObjectMapper objectMapper = new ObjectMapper(); + + + /** + * 处理接收的消息 + * + * @param message + * @throws MessagingException + */ + @Override + public void handleMessage(Message message) throws MessagingException { + // System.out.println("接收到的消息:" + message.getPayload()); + MessageHeaders headers = message.getHeaders(); + String receivedTopicName = (String) headers.get("mqtt_receivedTopic"); + System.out.println("消息来自主题:" + receivedTopicName); + + String payload = message.getPayload().toString(); + + if (receivedTopicName != null) { + // 1. 提取设备ID (从主题中获取) + String deviceImei = extractDeviceId(receivedTopicName); + Device device = deviceMapper.selectOne(new QueryWrapper().eq("device_imei", deviceImei)); + if (device == null) { + log.info("不存在的设备IMEI: {}", deviceImei); + } else { + + try { + JsonNode root = objectMapper.readTree(payload); + + // 2. 处理instruct消息 + if (root.has("instruct")) { + JsonNode instructNode = root.get("instruct"); + if (instructNode.isArray()) { + DeviceLog record = parseInstruct(device, instructNode); + // 手动设置租户ID + record.setTenantId(device.getTenantId()); // 从设备信息中获取租户ID + // 设备ID + record.setDeviceId(device.getId()); + + // 根据不同主题进行不同处理 + if (receivedTopicName.startsWith("A/")) { + // 处理A主题的消息(设备上传) + record.setDataSource("设备上报"); + } else if (receivedTopicName.startsWith("B/")) { + // 处理B主题的消息 (手动上传) + record.setDataSource("客户端操作"); + } + + deviceLogMapper.insert(record); + } + } + // 3. 处理state消息 + // else if (root.has("state")) { + // JsonNode stateNode = root.get("state"); + // if (stateNode.isArray()) { + // StateRecord record = parseState(device, stateNode); + // stateRepo.save(record); + // } + // } + } catch (Exception e) { + log.error("消息解析失败: {}", payload, e); + } + + } + + } + } + + + /** + * 从主题中提取设备ID(IMEI) + * + * @param topic + * @return + */ + private String extractDeviceId(String topic) { + // 处理 A/# 或 B/# 格式的主题,例如 B/861556078765285 或 A/861556078765285 + String[] segments = topic.split("/"); + if (segments.length >= 2) { + // 返回第二个段,即 / 后面的部分 + return segments[1]; + } + // 如果格式不符合预期,返回原主题 + return topic; + } + + + /** + * 解析instruct消息 + * + * @param device + * @param array + * @return + */ + private DeviceLog parseInstruct(Device device, JsonNode array) { + DeviceLog record = new DeviceLog(); + record.setDeviceName(device.getDeviceName()); + // 设备行为 + record.setDeviceAction(InstructType6170.fromCode(array.get(0).asInt()).getDescription()); + + switch (array.get(0).asInt()) { + case 1: // 灯光模式 + LightModeEnum6170 lightModeEnum6170 = LightModeEnum6170.fromCode(array.get(1).asInt()); + record.setContent(lightModeEnum6170.getDescription()); + break; + + case 2: // 单位/姓名/职位 + byte[] unitBytes = new byte[480]; + for (int i = 1; i <= 480; i++) { + unitBytes[i - 1] = (byte) array.get(i).asInt(); + } + // record.setUnitData(unitBytes); + break; + + case 3: // 开机图片 + // record.setImagePage(array.get(1).asInt()); + byte[] imageBytes = new byte[512]; + for (int i = 2; i <= 513; i++) { + imageBytes[i - 2] = (byte) array.get(i).asInt(); + } + // record.setImageData(imageBytes); + break; + + case 4: // 激光灯 + // record.setLaserLight(array.get(1).asInt() == 1); + break; + + case 5: // 亮度调节 + // record.setBrightness(array.get(1).asInt()); + break; + + case 11: // 定位数据 + // record.setLatitudeDeg(array.get(1).asInt()); + // record.setLatitudeMin(new BigDecimal(array.get(2).asDouble())); + // record.setLongitudeDeg(array.get(3).asInt()); + // record.setLongitudeMin(new BigDecimal(array.get(4).asDouble())); + break; + } + return record; + } + + + /** + * 解析state消息 + * + * @param device + * @param array + * @return + */ + // private StateRecord parseState(Device device, JsonNode array) { + // StateRecord record = new StateRecord(); + // record.setDevice(device); + // record.setStateType(array.get(0).asInt()); + // + // switch (record.getStateType()) { + // case 1: // 灯光状态 + // record.setLightMode(array.get(1).asInt()); + // record.setBrightness(array.get(2).asInt()); + // break; + // + // case 2: // 设置结果 + // record.setSetResult(array.get(1).asInt() == 1); + // break; + // + // case 3: // 图片更新状态 + // record.setImagePage(array.get(1).asInt()); + // break; + // + // case 4: // 激光灯状态 + // record.setLaserStatus(array.get(1).asInt() == 1); + // break; + // + // case 5: // 亮度状态 + // record.setBrightness(array.get(1).asInt()); + // break; + // + // case 11: // 定位上报 + // record.setLatitude(array.get(1).asDouble()); + // record.setLongitude(array.get(2).asDouble()); + // break; + // + // case 12: // 设备状态 + // record.setMainLightGear(array.get(1).asInt()); + // record.setLaserLightGear(array.get(2).asInt()); + // record.setBattery(array.get(3).asInt()); + // record.setChargeStatus(array.get(4).asInt()); + // record.setDuration(array.get(5).asInt()); + // break; + // } + // return record; + // } + + +} diff --git a/fys-admin/src/main/resources/application-dev.yml b/fys-admin/src/main/resources/application-dev.yml index 21268ac..a9cb4ba 100644 --- a/fys-admin/src/main/resources/application-dev.yml +++ b/fys-admin/src/main/resources/application-dev.yml @@ -303,6 +303,6 @@ mqtt: password: #YtvpSfCNG url: tcp://47.120.79.150:2883 subClientId: fys_subClient - subTopic: A/#,worker/location/# + subTopic: A/#,B/#,worker/location/# pubTopic: B/# pubClientId: fys_pubClient \ No newline at end of file diff --git a/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/domain/Device.java b/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/domain/Device.java index 52b05c9..ae1a00d 100644 --- a/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/domain/Device.java +++ b/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/domain/Device.java @@ -82,6 +82,10 @@ public class Device extends TenantEntity { @Schema(name = "蓝牙名称") private String bluetoothName; + /** + * 设备IMEI + * device_imei + */ @Schema(name = "设备IMEI") private String deviceImei; diff --git a/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/domain/DeviceLog.java b/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/domain/DeviceLog.java index 0aaddb0..d651eb0 100644 --- a/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/domain/DeviceLog.java +++ b/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/domain/DeviceLog.java @@ -2,6 +2,7 @@ package com.fuyuanshen.equipment.domain; import com.baomidou.mybatisplus.annotation.*; import com.fuyuanshen.common.mybatis.core.domain.BaseEntity; +import com.fuyuanshen.common.tenant.core.TenantEntity; import lombok.Data; import lombok.EqualsAndHashCode; @@ -16,7 +17,7 @@ import java.io.Serial; @Data @EqualsAndHashCode(callSuper = true) @TableName("device_log") -public class DeviceLog extends BaseEntity { +public class DeviceLog extends TenantEntity { @Serial private static final long serialVersionUID = 1L; @@ -27,10 +28,16 @@ public class DeviceLog extends BaseEntity { @TableId(value = "id") private Long id; + /** + * 设备ID + */ + private Long deviceId; + /** * 设备行为 */ private String deviceAction; + // private Integer deviceActionInt; /** * 设备名称 @@ -47,5 +54,4 @@ public class DeviceLog extends BaseEntity { */ private String content; - } diff --git a/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/domain/vo/DeviceLogVo.java b/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/domain/vo/DeviceLogVo.java index cbfbc6a..b2e13c1 100644 --- a/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/domain/vo/DeviceLogVo.java +++ b/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/domain/vo/DeviceLogVo.java @@ -1,5 +1,7 @@ package com.fuyuanshen.equipment.domain.vo; +import com.baomidou.mybatisplus.annotation.FieldFill; +import com.baomidou.mybatisplus.annotation.TableField; import com.fuyuanshen.equipment.domain.DeviceLog; import cn.idev.excel.annotation.ExcelIgnoreUnannotated; import cn.idev.excel.annotation.ExcelProperty; @@ -58,5 +60,10 @@ public class DeviceLogVo implements Serializable { @ExcelProperty(value = "内容") private String content; + /** + * 创建时间 + */ + @TableField(fill = FieldFill.INSERT) + private Date createTime; } diff --git a/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/service/impl/DeviceLogServiceImpl.java b/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/service/impl/DeviceLogServiceImpl.java index 60d46df..2681445 100644 --- a/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/service/impl/DeviceLogServiceImpl.java +++ b/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/service/impl/DeviceLogServiceImpl.java @@ -73,14 +73,15 @@ public class DeviceLogServiceImpl implements IDeviceLogService { private LambdaQueryWrapper buildQueryWrapper(DeviceLogBo bo) { Map params = bo.getParams(); LambdaQueryWrapper lqw = Wrappers.lambdaQuery(); - lqw.orderByAsc(DeviceLog::getId); - lqw.eq(StringUtils.isNotBlank(bo.getDeviceAction()), DeviceLog::getDeviceAction, bo.getDeviceAction()); + lqw.orderByDesc(DeviceLog::getCreateTime); + lqw.like(StringUtils.isNotBlank(bo.getDeviceAction()), DeviceLog::getDeviceAction, bo.getDeviceAction()); lqw.like(StringUtils.isNotBlank(bo.getDeviceName()), DeviceLog::getDeviceName, bo.getDeviceName()); lqw.eq(StringUtils.isNotBlank(bo.getDataSource()), DeviceLog::getDataSource, bo.getDataSource()); - lqw.eq(StringUtils.isNotBlank(bo.getContent()), DeviceLog::getContent, bo.getContent()); + lqw.like(StringUtils.isNotBlank(bo.getContent()), DeviceLog::getContent, bo.getContent()); return lqw; } + /** * 新增设备日志 * From 0ad100a7a5d7fa9b51161480cbf191ad47b98742 Mon Sep 17 00:00:00 2001 From: chenyouting <514333061@qq.com> Date: Fri, 1 Aug 2025 16:27:17 +0800 Subject: [PATCH 08/19] =?UTF-8?q?=E5=A6=82=E6=9E=9C=E7=BB=8F=E7=BA=AC?= =?UTF-8?q?=E5=BA=A6=E4=B8=8D=E5=8F=98=E5=B0=B1=E4=B8=8D=E5=8E=BB=E8=B0=83?= =?UTF-8?q?=E7=94=A8=E5=9C=B0=E5=9B=BEapi?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../app/service/AppDeviceBizService.java | 4 +-- .../global/mqtt/rule/LocationDataRule.java | 28 +++++++++++++++++-- 2 files changed, 28 insertions(+), 4 deletions(-) diff --git a/fys-admin/src/main/java/com/fuyuanshen/app/service/AppDeviceBizService.java b/fys-admin/src/main/java/com/fuyuanshen/app/service/AppDeviceBizService.java index 1815dcf..c1063f7 100644 --- a/fys-admin/src/main/java/com/fuyuanshen/app/service/AppDeviceBizService.java +++ b/fys-admin/src/main/java/com/fuyuanshen/app/service/AppDeviceBizService.java @@ -336,8 +336,8 @@ public class AppDeviceBizService { String locationInfo = RedisUtils.getCacheObject(locationKey); if(StringUtils.isNotBlank(locationInfo)){ JSONObject jsonObject = JSONObject.parseObject(locationInfo); - vo.setLongitude((String)jsonObject.get("longitude")); - vo.setLatitude((String)jsonObject.get("latitude")); + vo.setLongitude(jsonObject.get("longitude").toString()); + vo.setLatitude(jsonObject.get("latitude").toString()); vo.setAddress((String)jsonObject.get("address")); } diff --git a/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/rule/LocationDataRule.java b/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/rule/LocationDataRule.java index 94499cf..238d244 100644 --- a/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/rule/LocationDataRule.java +++ b/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/rule/LocationDataRule.java @@ -1,5 +1,7 @@ package com.fuyuanshen.global.mqtt.rule; +import com.alibaba.fastjson2.JSON; +import com.alibaba.fastjson2.JSONObject; import com.fuyuanshen.common.core.constant.GlobalConstants; import com.fuyuanshen.common.core.utils.StringUtils; import com.fuyuanshen.common.json.utils.JsonUtils; @@ -108,6 +110,29 @@ public class LocationDataRule implements MqttMessageRule { if(StringUtils.isBlank(latitude) || StringUtils.isBlank(longitude)){ return; } + String[] latArr = latitude.split("\\."); + String[] lonArr = longitude.split("\\."); + // 将位置信息存储到Redis中 + String redisKey = GlobalConstants.GLOBAL_REDIS_KEY+DeviceRedisKeyConstants.DEVICE_LOCATION_KEY_PREFIX + deviceImei; + String redisObj = RedisUtils.getCacheObject(redisKey); + JSONObject jsonOBj = JSONObject.parseObject(redisObj); + if(jsonOBj != null){ + String str1 = latArr[0] +"."+ latArr[1].substring(0,4); + String str2 = lonArr[0] +"."+ lonArr[1].substring(0,4); + + String cacheLatitude = jsonOBj.getString("latitude"); + String cacheLongitude = jsonOBj.getString("longitude"); + String[] latArr1 = cacheLatitude.split("\\."); + String[] lonArr1 = cacheLongitude.split("\\."); + + String cacheStr1 = latArr1[0] +"."+ latArr1[1].substring(0,4); + String cacheStr2 = lonArr1[0] +"."+ lonArr1[1].substring(0,4); + if(str1.equals(cacheStr1) && str2.equals(cacheStr2)){ + log.info("位置信息未发生变化: device={}, lat={}, lon={}", deviceImei, latitude, longitude); + return; + } + } + // 构造位置信息对象 Map locationInfo = new LinkedHashMap<>(); double[] doubles = LngLonUtil.gps84_To_Gcj02(Double.parseDouble(latitude), Double.parseDouble(longitude)); @@ -119,8 +144,7 @@ public class LocationDataRule implements MqttMessageRule { locationInfo.put("timestamp", System.currentTimeMillis()); - // 将位置信息存储到Redis中 - String redisKey = GlobalConstants.GLOBAL_REDIS_KEY+DeviceRedisKeyConstants.DEVICE_LOCATION_KEY_PREFIX + deviceImei; + String locationJson = JsonUtils.toJsonString(locationInfo); // 存储到Redis From c8dff1a082a5dfe578b33dc007588f286150501f Mon Sep 17 00:00:00 2001 From: chenyouting <514333061@qq.com> Date: Fri, 1 Aug 2025 17:02:27 +0800 Subject: [PATCH 09/19] =?UTF-8?q?=E4=BD=8D=E7=BD=AE=E4=BF=A1=E6=81=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/fuyuanshen/global/mqtt/rule/LocationDataRule.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/rule/LocationDataRule.java b/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/rule/LocationDataRule.java index 238d244..518eaf5 100644 --- a/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/rule/LocationDataRule.java +++ b/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/rule/LocationDataRule.java @@ -120,8 +120,8 @@ public class LocationDataRule implements MqttMessageRule { String str1 = latArr[0] +"."+ latArr[1].substring(0,4); String str2 = lonArr[0] +"."+ lonArr[1].substring(0,4); - String cacheLatitude = jsonOBj.getString("latitude"); - String cacheLongitude = jsonOBj.getString("longitude"); + String cacheLatitude = jsonOBj.getString("gps8s_latitude"); + String cacheLongitude = jsonOBj.getString("gps8s_longitude"); String[] latArr1 = cacheLatitude.split("\\."); String[] lonArr1 = cacheLongitude.split("\\."); @@ -139,6 +139,8 @@ public class LocationDataRule implements MqttMessageRule { locationInfo.put("deviceImei", deviceImei); locationInfo.put("latitude", doubles[0]); locationInfo.put("longitude", doubles[1]); + locationInfo.put("gps8s_latitude", latitude); + locationInfo.put("gps8s_longitude", longitude); String address = GetAddressFromLatUtil.getAdd(String.valueOf(doubles[1]), String.valueOf(doubles[0])); locationInfo.put("address", address); locationInfo.put("timestamp", System.currentTimeMillis()); From ce8f6c9a77718be676b2e2dea7238b72b74b16c7 Mon Sep 17 00:00:00 2001 From: chenyouting <514333061@qq.com> Date: Sat, 2 Aug 2025 09:09:02 +0800 Subject: [PATCH 10/19] =?UTF-8?q?=E8=AE=BE=E5=A4=87=E5=8E=86=E5=8F=B2?= =?UTF-8?q?=E8=BD=A8=E8=BF=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../mqtt/receiver/ReceiverMessageHandler.java | 3 +- .../rule/ActiveReportingDeviceDataRule.java | 2 ++ .../global/mqtt/rule/LocationDataRule.java | 31 +++++++++++++++-- .../common/redis/utils/RedisUtils.java | 33 +++++++++++++++++++ 4 files changed, 65 insertions(+), 4 deletions(-) diff --git a/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/receiver/ReceiverMessageHandler.java b/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/receiver/ReceiverMessageHandler.java index 5baddf6..3cd36af 100644 --- a/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/receiver/ReceiverMessageHandler.java +++ b/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/receiver/ReceiverMessageHandler.java @@ -17,6 +17,7 @@ import org.springframework.messaging.MessageHeaders; import org.springframework.messaging.MessagingException; import org.springframework.stereotype.Service; +import java.time.Duration; import java.util.Objects; @Service @@ -46,7 +47,7 @@ public class ReceiverMessageHandler implements MessageHandler { if(StringUtils.isNotBlank(deviceImei)){ //在线状态 String deviceOnlineStatusRedisKey = GlobalConstants.GLOBAL_REDIS_KEY+ DeviceRedisKeyConstants.DEVICE_ONLINE_STATUS_KEY_PREFIX + deviceImei; - RedisUtils.setCacheObject(deviceOnlineStatusRedisKey, "1"); + RedisUtils.setCacheObject(deviceOnlineStatusRedisKey, "1", Duration.ofSeconds(60*15)); } String state = payloadDict.getStr("state"); diff --git a/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/rule/ActiveReportingDeviceDataRule.java b/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/rule/ActiveReportingDeviceDataRule.java index 6b37a47..104bd69 100644 --- a/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/rule/ActiveReportingDeviceDataRule.java +++ b/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/rule/ActiveReportingDeviceDataRule.java @@ -94,4 +94,6 @@ public class ActiveReportingDeviceDataRule implements MqttMessageRule { }); } + + } diff --git a/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/rule/LocationDataRule.java b/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/rule/LocationDataRule.java index 518eaf5..8cf2ef5 100644 --- a/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/rule/LocationDataRule.java +++ b/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/rule/LocationDataRule.java @@ -153,15 +153,40 @@ public class LocationDataRule implements MqttMessageRule { RedisUtils.setCacheObject(redisKey, locationJson); // 存储到一个列表中,保留历史位置信息 - String locationHistoryKey = GlobalConstants.GLOBAL_REDIS_KEY+DeviceRedisKeyConstants.DEVICE_LOCATION_HISTORY_KEY_PREFIX + deviceImei; - RedisUtils.addCacheList(locationHistoryKey, locationJson); - RedisUtils.expire(locationHistoryKey, Duration.ofDays(90)); +// String locationHistoryKey = GlobalConstants.GLOBAL_REDIS_KEY+DeviceRedisKeyConstants.DEVICE_LOCATION_HISTORY_KEY_PREFIX + deviceImei; +// RedisUtils.addCacheList(locationHistoryKey, locationJson); +// RedisUtils.expire(locationHistoryKey, Duration.ofDays(90)); + storeDeviceTrajectoryWithSortedSet(deviceImei, locationJson); log.info("位置信息已异步发送到Redis: device={}, lat={}, lon={}", deviceImei, latitude, longitude); } catch (Exception e) { log.error("异步发送位置信息到Redis时出错: device={}, error={}", deviceImei, e.getMessage(), e); } }); } + + /** + * 存储设备30天历史轨迹到Redis (使用Sorted Set) + */ + public void storeDeviceTrajectoryWithSortedSet(String deviceImei, String locationJson) { + try { + String trajectoryKey = GlobalConstants.GLOBAL_REDIS_KEY+DeviceRedisKeyConstants.DEVICE_LOCATION_HISTORY_KEY_PREFIX + deviceImei; +// String trajectoryKey = "device:trajectory:zset:" + deviceImei; +// String locationJson = JsonUtils.toJsonString(locationInfo); + long timestamp = System.currentTimeMillis(); + + // 添加到Sorted Set,使用时间戳作为score + RedisUtils.zAdd(trajectoryKey, locationJson, timestamp); + +// // 设置30天过期时间 +// RedisUtils.expire(trajectoryKey, Duration.ofDays(30)); + + // 清理30天前的数据(冗余保护) + long thirtyDaysAgo = System.currentTimeMillis() - (90L * 24 * 60 * 60 * 1000); + RedisUtils.zRemoveRangeByScore(trajectoryKey, 0, thirtyDaysAgo); + } catch (Exception e) { + log.error("存储设备轨迹到Redis(ZSet)失败: device={}, error={}", deviceImei, e.getMessage(), e); + } + } private Map buildLocationDataMap(String latitude, String longitude) { String[] latArr = latitude.split("\\."); diff --git a/fys-common/fys-common-redis/src/main/java/com/fuyuanshen/common/redis/utils/RedisUtils.java b/fys-common/fys-common-redis/src/main/java/com/fuyuanshen/common/redis/utils/RedisUtils.java index bb7ba81..17292c0 100644 --- a/fys-common/fys-common-redis/src/main/java/com/fuyuanshen/common/redis/utils/RedisUtils.java +++ b/fys-common/fys-common-redis/src/main/java/com/fuyuanshen/common/redis/utils/RedisUtils.java @@ -339,7 +339,40 @@ public class RedisUtils { RSet rSet = CLIENT.getSet(key); return rSet.addAll(dataSet); } + /** + * 向Sorted Set添加元素 + * + * @param key 键 + * @param value 值 + * @param score 分数 + * @return 添加成功返回true,否则返回false + */ + public static boolean zAdd(String key, Object value, double score) { + try { + RScoredSortedSet sortedSet = CLIENT.getScoredSortedSet(key); + return sortedSet.add(score, value); + } catch (Exception e) { +// log.error("向Sorted Set添加元素失败: key={}, value={}, score={}, error={}", key, value, score, e.getMessage(), e); + return false; + } + } + /** + * 移除Sorted Set中指定范围的元素(按分数) + * + * @param key 键 + * @param min 最小分数 + * @param max 最大分数 + * @return 移除的元素数量 + */ + public static int zRemoveRangeByScore(String key, double min, double max) { + try { + RScoredSortedSet sortedSet = CLIENT.getScoredSortedSet(key); + return sortedSet.removeRangeByScore(min, true, max, true); + } catch (Exception e) { + return 0; + } + } /** * 追加缓存Set数据 * From 8435a5b0e60a1cbb2039724384f4db2147d81518 Mon Sep 17 00:00:00 2001 From: daiyongfei <974332738@qq.com> Date: Sat, 2 Aug 2025 09:18:31 +0800 Subject: [PATCH 11/19] =?UTF-8?q?=E8=AE=BE=E5=A4=87=E8=A1=8C=E4=B8=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../config/CustomMqttInboundConfiguration.java | 5 +++++ .../fuyuanshen/web/enums/InstructType6170.java | 14 +++++++++++--- .../mqtt/DeviceReceiverMessageHandler.java | 17 +++++++++-------- 3 files changed, 25 insertions(+), 11 deletions(-) diff --git a/fys-admin/src/main/java/com/fuyuanshen/web/config/CustomMqttInboundConfiguration.java b/fys-admin/src/main/java/com/fuyuanshen/web/config/CustomMqttInboundConfiguration.java index f7f52ae..faa8cb5 100644 --- a/fys-admin/src/main/java/com/fuyuanshen/web/config/CustomMqttInboundConfiguration.java +++ b/fys-admin/src/main/java/com/fuyuanshen/web/config/CustomMqttInboundConfiguration.java @@ -21,6 +21,7 @@ import org.springframework.messaging.MessageHandler; */ @Configuration public class CustomMqttInboundConfiguration { + @Autowired private MqttPropertiesConfig mqttPropertiesConfig; @Autowired @@ -28,11 +29,13 @@ public class CustomMqttInboundConfiguration { @Autowired private DeviceReceiverMessageHandler deviceReceiverMessageHandler; + @Bean public MessageChannel customMqttChannel(){ return new DirectChannel(); } + @Bean public MessageProducer customMessageProducer(){ String clientId = "custom_client_" + UUID.fastUUID(); @@ -48,9 +51,11 @@ public class CustomMqttInboundConfiguration { return adapter; } + @Bean @ServiceActivator(inputChannel = "customMqttChannel") public MessageHandler customMessageHandler(){ return deviceReceiverMessageHandler; } + } diff --git a/fys-admin/src/main/java/com/fuyuanshen/web/enums/InstructType6170.java b/fys-admin/src/main/java/com/fuyuanshen/web/enums/InstructType6170.java index 522b355..d24ed17 100644 --- a/fys-admin/src/main/java/com/fuyuanshen/web/enums/InstructType6170.java +++ b/fys-admin/src/main/java/com/fuyuanshen/web/enums/InstructType6170.java @@ -8,11 +8,18 @@ public enum InstructType6170 { EQUIPMENT_REPORTING(0, "设备上报"), LIGHT_MODE(1, "灯光模式"), - UNIT_INFO(2, "单位/姓名/职位"), + /** + * 设备信息 + * 单位/姓名/职位 + */ + UNIT_INFO(2, "设备信息"), BOOT_IMAGE(3, "开机图片"), LASER_LIGHT(4, "激光灯"), BRIGHTNESS(5, "亮度调节"), - LOCATION_DATA(11, "定位数据"); + LOCATION_DATA(11, "定位数据"), + + + UNKNOWN(-1, "未知操作"); private final int code; private final String description; @@ -36,7 +43,8 @@ public enum InstructType6170 { return type; } } - throw new IllegalArgumentException("未知的指令类型代码: " + code); + // throw new IllegalArgumentException("未知的指令类型代码: " + code); + return UNKNOWN; } } diff --git a/fys-admin/src/main/java/com/fuyuanshen/web/handler/mqtt/DeviceReceiverMessageHandler.java b/fys-admin/src/main/java/com/fuyuanshen/web/handler/mqtt/DeviceReceiverMessageHandler.java index 717aedf..02215b0 100644 --- a/fys-admin/src/main/java/com/fuyuanshen/web/handler/mqtt/DeviceReceiverMessageHandler.java +++ b/fys-admin/src/main/java/com/fuyuanshen/web/handler/mqtt/DeviceReceiverMessageHandler.java @@ -1,11 +1,8 @@ package com.fuyuanshen.web.handler.mqtt; -import cn.hutool.core.collection.CollectionUtil; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; -import com.fuyuanshen.app.domain.APPDevice; -import com.fuyuanshen.app.enums.UserType; import com.fuyuanshen.equipment.domain.Device; import com.fuyuanshen.equipment.domain.DeviceLog; import com.fuyuanshen.equipment.mapper.DeviceLogMapper; @@ -14,7 +11,6 @@ import com.fuyuanshen.web.enums.InstructType6170; import com.fuyuanshen.web.enums.LightModeEnum6170; import lombok.AllArgsConstructor; import lombok.Data; -import lombok.NoArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.messaging.Message; import org.springframework.messaging.MessageHandler; @@ -22,8 +18,6 @@ import org.springframework.messaging.MessageHeaders; import org.springframework.messaging.MessagingException; import org.springframework.stereotype.Component; -import java.util.List; - /** * 定义监听主题消息的处理器 * @@ -164,11 +158,18 @@ public class DeviceReceiverMessageHandler implements MessageHandler { break; case 4: // 激光灯 - // record.setLaserLight(array.get(1).asInt() == 1); + int anInt = array.get(1).asInt(); + if (anInt == 0) { + record.setContent("关闭激光灯"); + } else if (anInt == 1) { + record.setContent("开启激光灯"); + } else { + record.setContent("未知操作"); + } break; case 5: // 亮度调节 - // record.setBrightness(array.get(1).asInt()); + record.setContent(+array.get(1).asInt() + "%"); break; case 11: // 定位数据 From a74b697c0f45bc2912aadd6f08bba532d5cb6628 Mon Sep 17 00:00:00 2001 From: chenyouting <514333061@qq.com> Date: Sat, 2 Aug 2025 14:51:06 +0800 Subject: [PATCH 12/19] =?UTF-8?q?=E8=AE=BE=E5=A4=87=E5=8E=86=E5=8F=B2?= =?UTF-8?q?=E8=BD=A8=E8=BF=B92?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/fuyuanshen/global/mqtt/rule/LocationDataRule.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/rule/LocationDataRule.java b/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/rule/LocationDataRule.java index 8cf2ef5..16dec3b 100644 --- a/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/rule/LocationDataRule.java +++ b/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/rule/LocationDataRule.java @@ -120,8 +120,8 @@ public class LocationDataRule implements MqttMessageRule { String str1 = latArr[0] +"."+ latArr[1].substring(0,4); String str2 = lonArr[0] +"."+ lonArr[1].substring(0,4); - String cacheLatitude = jsonOBj.getString("gps8s_latitude"); - String cacheLongitude = jsonOBj.getString("gps8s_longitude"); + String cacheLatitude = jsonOBj.getString("wgs84_latitude"); + String cacheLongitude = jsonOBj.getString("wgs84_longitude"); String[] latArr1 = cacheLatitude.split("\\."); String[] lonArr1 = cacheLongitude.split("\\."); @@ -139,8 +139,8 @@ public class LocationDataRule implements MqttMessageRule { locationInfo.put("deviceImei", deviceImei); locationInfo.put("latitude", doubles[0]); locationInfo.put("longitude", doubles[1]); - locationInfo.put("gps8s_latitude", latitude); - locationInfo.put("gps8s_longitude", longitude); + locationInfo.put("wgs84_latitude", latitude); + locationInfo.put("wgs84_longitude", longitude); String address = GetAddressFromLatUtil.getAdd(String.valueOf(doubles[1]), String.valueOf(doubles[0])); locationInfo.put("address", address); locationInfo.put("timestamp", System.currentTimeMillis()); From f4d5f950cefbe5f7c15152df75620461cd212e4d Mon Sep 17 00:00:00 2001 From: daiyongfei <974332738@qq.com> Date: Mon, 4 Aug 2025 09:05:10 +0800 Subject: [PATCH 13/19] =?UTF-8?q?=E8=AE=BE=E5=A4=87=E8=A1=8C=E4=B8=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../web/enums/InstructType6170.java | 2 +- .../mqtt/DeviceReceiverMessageHandler.java | 53 +++-- .../equipment/domain/bo/DeviceLogBo.java | 9 +- .../service/impl/DeviceLogServiceImpl.java | 31 ++- .../utils/c/DotMatrixDisplaySimulator.java | 204 ++++++++++++++++++ .../equipment/utils/c/TextToDotMatrix.java | 185 ++++++++++++++++ 6 files changed, 464 insertions(+), 20 deletions(-) create mode 100644 fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/utils/c/DotMatrixDisplaySimulator.java create mode 100644 fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/utils/c/TextToDotMatrix.java diff --git a/fys-admin/src/main/java/com/fuyuanshen/web/enums/InstructType6170.java b/fys-admin/src/main/java/com/fuyuanshen/web/enums/InstructType6170.java index d24ed17..9f5f0d9 100644 --- a/fys-admin/src/main/java/com/fuyuanshen/web/enums/InstructType6170.java +++ b/fys-admin/src/main/java/com/fuyuanshen/web/enums/InstructType6170.java @@ -6,7 +6,7 @@ package com.fuyuanshen.web.enums; */ public enum InstructType6170 { - EQUIPMENT_REPORTING(0, "设备上报"), + EQUIPMENT_REPORTING(0, "设备启动"), LIGHT_MODE(1, "灯光模式"), /** * 设备信息 diff --git a/fys-admin/src/main/java/com/fuyuanshen/web/handler/mqtt/DeviceReceiverMessageHandler.java b/fys-admin/src/main/java/com/fuyuanshen/web/handler/mqtt/DeviceReceiverMessageHandler.java index 02215b0..2f31fc3 100644 --- a/fys-admin/src/main/java/com/fuyuanshen/web/handler/mqtt/DeviceReceiverMessageHandler.java +++ b/fys-admin/src/main/java/com/fuyuanshen/web/handler/mqtt/DeviceReceiverMessageHandler.java @@ -7,6 +7,8 @@ import com.fuyuanshen.equipment.domain.Device; import com.fuyuanshen.equipment.domain.DeviceLog; import com.fuyuanshen.equipment.mapper.DeviceLogMapper; import com.fuyuanshen.equipment.mapper.DeviceMapper; +import com.fuyuanshen.equipment.utils.map.GetAddressFromLatUtil; +import com.fuyuanshen.equipment.utils.map.LngLonUtil; import com.fuyuanshen.web.enums.InstructType6170; import com.fuyuanshen.web.enums.LightModeEnum6170; import lombok.AllArgsConstructor; @@ -63,16 +65,20 @@ public class DeviceReceiverMessageHandler implements MessageHandler { try { JsonNode root = objectMapper.readTree(payload); + DeviceLog record = new DeviceLog(); + // 手动设置租户ID + record.setTenantId(device.getTenantId()); // 从设备信息中获取租户ID + // 设备ID + record.setDeviceId(device.getId()); + // 设备名称 + record.setDeviceName(device.getDeviceName()); + // 2. 处理instruct消息 if (root.has("instruct")) { JsonNode instructNode = root.get("instruct"); if (instructNode.isArray()) { - DeviceLog record = parseInstruct(device, instructNode); - // 手动设置租户ID - record.setTenantId(device.getTenantId()); // 从设备信息中获取租户ID - // 设备ID - record.setDeviceId(device.getId()); - + boolean b = receivedTopicName.startsWith("B/"); + record = parseInstruct(device, instructNode, b); // 根据不同主题进行不同处理 if (receivedTopicName.startsWith("A/")) { // 处理A主题的消息(设备上传) @@ -81,10 +87,19 @@ public class DeviceReceiverMessageHandler implements MessageHandler { // 处理B主题的消息 (手动上传) record.setDataSource("客户端操作"); } - - deviceLogMapper.insert(record); } + deviceLogMapper.insert(record); } + + if (root.has("imei")) { + // 设备行为 + record.setDeviceAction(InstructType6170.fromCode(0).getDescription()); + record.setDataSource("设备上报"); + record.setContent("设备启动"); + deviceLogMapper.insert(record); + } + + // 3. 处理state消息 // else if (root.has("state")) { // JsonNode stateNode = root.get("state"); @@ -126,9 +141,10 @@ public class DeviceReceiverMessageHandler implements MessageHandler { * * @param device * @param array + * @param b * @return */ - private DeviceLog parseInstruct(Device device, JsonNode array) { + private DeviceLog parseInstruct(Device device, JsonNode array, boolean b) { DeviceLog record = new DeviceLog(); record.setDeviceName(device.getDeviceName()); // 设备行为 @@ -173,10 +189,21 @@ public class DeviceReceiverMessageHandler implements MessageHandler { break; case 11: // 定位数据 - // record.setLatitudeDeg(array.get(1).asInt()); - // record.setLatitudeMin(new BigDecimal(array.get(2).asDouble())); - // record.setLongitudeDeg(array.get(3).asInt()); - // record.setLongitudeMin(new BigDecimal(array.get(4).asDouble())); + if (b) { + break; + } + int i1 = array.get(1).asInt(); + int i2 = array.get(2).asInt(); + int i3 = array.get(3).asInt(); + int i4 = array.get(4).asInt(); + + // 优雅的转换方式 Longitude and latitude + double latitude = i1 + i2 / 10.0; + double Longitude = i3 + i4 / 10.0; + // 84 ==》 高德 + double[] doubles = LngLonUtil.gps84_To_Gcj02(latitude, Longitude); + String address = GetAddressFromLatUtil.getAdd(String.valueOf(doubles[1]), String.valueOf(doubles[0])); + record.setContent(address); break; } return record; diff --git a/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/domain/bo/DeviceLogBo.java b/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/domain/bo/DeviceLogBo.java index 71900d5..2ac1f66 100644 --- a/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/domain/bo/DeviceLogBo.java +++ b/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/domain/bo/DeviceLogBo.java @@ -8,6 +8,8 @@ import lombok.Data; import lombok.EqualsAndHashCode; import jakarta.validation.constraints.*; +import java.util.List; + /** * 设备日志业务对象 device_log * @@ -22,9 +24,14 @@ public class DeviceLogBo extends BaseEntity { /** * ID */ - @NotNull(message = "ID不能为空", groups = { EditGroup.class }) + @NotNull(message = "ID不能为空", groups = {EditGroup.class}) private Long id; + /** + * 设备编号 + */ + private List deviceIds; + /** * 设备行为 */ diff --git a/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/service/impl/DeviceLogServiceImpl.java b/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/service/impl/DeviceLogServiceImpl.java index 2681445..16ca6d3 100644 --- a/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/service/impl/DeviceLogServiceImpl.java +++ b/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/service/impl/DeviceLogServiceImpl.java @@ -1,11 +1,16 @@ package com.fuyuanshen.equipment.service.impl; +import cn.hutool.core.collection.CollectionUtil; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.fuyuanshen.common.core.utils.MapstructUtils; import com.fuyuanshen.common.mybatis.core.page.TableDataInfo; import com.fuyuanshen.common.mybatis.core.page.PageQuery; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.fuyuanshen.common.satoken.utils.LoginHelper; +import com.fuyuanshen.equipment.domain.DeviceAssignments; +import com.fuyuanshen.equipment.mapper.DeviceAssignmentsMapper; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; @@ -19,6 +24,7 @@ import com.fuyuanshen.equipment.service.IDeviceLogService; import java.util.List; import java.util.Map; import java.util.Collection; +import java.util.stream.Collectors; /** * 设备日志Service业务层处理 @@ -33,6 +39,9 @@ public class DeviceLogServiceImpl implements IDeviceLogService { private final DeviceLogMapper baseMapper; + private final DeviceAssignmentsMapper deviceAssignmentsMapper; + + /** * 查询设备日志 * @@ -40,7 +49,7 @@ public class DeviceLogServiceImpl implements IDeviceLogService { * @return 设备日志 */ @Override - public DeviceLogVo queryById(Long id){ + public DeviceLogVo queryById(Long id) { return baseMapper.selectVoById(id); } @@ -53,6 +62,8 @@ public class DeviceLogServiceImpl implements IDeviceLogService { */ @Override public TableDataInfo queryPageList(DeviceLogBo bo, PageQuery pageQuery) { + + LambdaQueryWrapper lqw = buildQueryWrapper(bo); Page result = baseMapper.selectVoPage(pageQuery.build(), lqw); return TableDataInfo.build(result); @@ -71,6 +82,15 @@ public class DeviceLogServiceImpl implements IDeviceLogService { } private LambdaQueryWrapper buildQueryWrapper(DeviceLogBo bo) { + + Long userId = LoginHelper.getUserId(); + List assignments = deviceAssignmentsMapper.selectList(new QueryWrapper().eq("assignee_id", userId)); + List deviceIds = assignments.stream().map(DeviceAssignments::getDeviceId).collect(Collectors.toList()); + if (deviceIds.isEmpty()) { + deviceIds.add(-1L); + } + bo.setDeviceIds(deviceIds); + Map params = bo.getParams(); LambdaQueryWrapper lqw = Wrappers.lambdaQuery(); lqw.orderByDesc(DeviceLog::getCreateTime); @@ -78,6 +98,7 @@ public class DeviceLogServiceImpl implements IDeviceLogService { lqw.like(StringUtils.isNotBlank(bo.getDeviceName()), DeviceLog::getDeviceName, bo.getDeviceName()); lqw.eq(StringUtils.isNotBlank(bo.getDataSource()), DeviceLog::getDataSource, bo.getDataSource()); lqw.like(StringUtils.isNotBlank(bo.getContent()), DeviceLog::getContent, bo.getContent()); + lqw.in(CollectionUtil.isNotEmpty(bo.getDeviceIds()), DeviceLog::getDeviceId, bo.getDeviceIds()); return lqw; } @@ -115,8 +136,8 @@ public class DeviceLogServiceImpl implements IDeviceLogService { /** * 保存前的数据校验 */ - private void validEntityBeforeSave(DeviceLog entity){ - //TODO 做一些数据校验,如唯一约束 + private void validEntityBeforeSave(DeviceLog entity) { + // TODO 做一些数据校验,如唯一约束 } /** @@ -128,8 +149,8 @@ public class DeviceLogServiceImpl implements IDeviceLogService { */ @Override public Boolean deleteWithValidByIds(Collection ids, Boolean isValid) { - if(isValid){ - //TODO 做一些业务上的校验,判断是否需要校验 + if (isValid) { + // TODO 做一些业务上的校验,判断是否需要校验 } return baseMapper.deleteByIds(ids) > 0; } diff --git a/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/utils/c/DotMatrixDisplaySimulator.java b/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/utils/c/DotMatrixDisplaySimulator.java new file mode 100644 index 0000000..3d022fe --- /dev/null +++ b/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/utils/c/DotMatrixDisplaySimulator.java @@ -0,0 +1,204 @@ +package com.fuyuanshen.equipment.utils.c; + +import javax.swing.*; +import java.awt.*; +import java.awt.event.*; +import java.awt.image.BufferedImage; +import java.util.Arrays; + +public class DotMatrixDisplaySimulator extends JFrame { + + private static final int WIDTH = 160; + private static final int HEIGHT = 80; + private static final int SCALE = 4; // 显示缩放比例 + + private JComboBox fontSizeCombo; + private JComboBox exampleCombo; + private JTextArea textInput; + private DotMatrixPanel displayPanel; + + private final String[] examples = { + "紧急通知:现场危险,请立即撤离!", + "警告:高温区域,禁止入内!", + "系统故障:请立即联系技术人员处理", + "安全提示:请佩戴防护装备进入作业区", + "欢迎使用点阵显示屏模拟系统", + "现场危险,停止救援,紧急撤离至安全区域!" + }; + + public DotMatrixDisplaySimulator() { + super("160x80点阵显示屏模拟器"); + setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + setSize(800, 600); + setLayout(new BorderLayout()); + + // 创建控制面板 + JPanel controlPanel = new JPanel(new GridLayout(1, 4, 10, 10)); + controlPanel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10)); + + // 字体大小选择 + controlPanel.add(new JLabel("字体大小:")); + fontSizeCombo = new JComboBox<>(new Integer[]{8, 10, 12, 14, 16, 18, 20, 24}); + fontSizeCombo.setSelectedItem(14); + controlPanel.add(fontSizeCombo); + + // 示例选择 + controlPanel.add(new JLabel("示例文本:")); + exampleCombo = new JComboBox<>(examples); + exampleCombo.addActionListener(e -> textInput.setText(examples[exampleCombo.getSelectedIndex()])); + controlPanel.add(exampleCombo); + + // 文本输入 + textInput = new JTextArea(examples[0]); + textInput.setLineWrap(true); + textInput.setWrapStyleWord(true); + JScrollPane textScroll = new JScrollPane(textInput); + textScroll.setBorder(BorderFactory.createTitledBorder("输入文本")); + + // 点阵显示面板 + displayPanel = new DotMatrixPanel(); + + // 添加组件 + add(controlPanel, BorderLayout.NORTH); + add(textScroll, BorderLayout.CENTER); + add(displayPanel, BorderLayout.SOUTH); + + // 添加事件监听器 + fontSizeCombo.addActionListener(e -> displayPanel.repaint()); + textInput.getDocument().addDocumentListener(new javax.swing.event.DocumentListener() { + public void changedUpdate(javax.swing.event.DocumentEvent e) { update(); } + public void removeUpdate(javax.swing.event.DocumentEvent e) { update(); } + public void insertUpdate(javax.swing.event.DocumentEvent e) { update(); } + private void update() { + displayPanel.repaint(); + } + }); + + setLocationRelativeTo(null); + } + + class DotMatrixPanel extends JPanel { + private final int panelWidth = WIDTH * SCALE; + private final int panelHeight = HEIGHT * SCALE; + + public DotMatrixPanel() { + setPreferredSize(new Dimension(panelWidth, panelHeight + 50)); + setBorder(BorderFactory.createTitledBorder("点阵预览 (160x80)")); + } + + @Override + protected void paintComponent(Graphics g) { + super.paintComponent(g); + + // 绘制点阵背景 + g.setColor(Color.WHITE); + g.fillRect(0, 0, panelWidth, panelHeight); + + // 绘制网格 + g.setColor(new Color(240, 240, 240)); + for (int x = 0; x <= WIDTH; x++) { + int xPos = x * SCALE; + g.drawLine(xPos, 0, xPos, panelHeight); + } + for (int y = 0; y <= HEIGHT; y++) { + int yPos = y * SCALE; + g.drawLine(0, yPos, panelWidth, yPos); + } + + // 绘制文本 + String text = textInput.getText(); + int fontSize = (Integer) fontSizeCombo.getSelectedItem(); + Font font = new Font("黑体", Font.PLAIN, fontSize); + + // 创建虚拟点阵图像 + BufferedImage img = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_BYTE_BINARY); + Graphics2D imgG = img.createGraphics(); + imgG.setColor(Color.WHITE); + imgG.fillRect(0, 0, WIDTH, HEIGHT); + imgG.setColor(Color.BLACK); + imgG.setFont(font); + imgG.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON); + + // 绘制文本到虚拟点阵 + FontMetrics metrics = imgG.getFontMetrics(); + int lineHeight = metrics.getHeight(); + int yPos = metrics.getAscent(); + String[] lines = text.split("\n"); + + int maxLines = HEIGHT / lineHeight; + int actualLines = Math.min(lines.length, maxLines); + int totalChars = 0; + + for (int i = 0; i < actualLines; i++) { + String line = lines[i]; + int lineWidth = metrics.stringWidth(line); + int maxChars = WIDTH / metrics.stringWidth("字"); // 估算每行字数 + + // 截断超过宽度的文本 + if (lineWidth > WIDTH) { + while (metrics.stringWidth(line) > WIDTH) { + line = line.substring(0, line.length() - 1); + } + line += "..."; + } + + // 居中显示文本 + int xPos = (WIDTH - metrics.stringWidth(line)) / 2; + imgG.drawString(line, xPos, yPos); + + totalChars += line.length(); + yPos += lineHeight; + + if (yPos + lineHeight > HEIGHT) break; + } + imgG.dispose(); + + // 绘制到预览面板 + for (int y = 0; y < HEIGHT; y++) { + for (int x = 0; x < WIDTH; x++) { + int rgb = img.getRGB(x, y) & 0xFFFFFF; + if (rgb != 0xFFFFFF) { // 黑色像素 + g.setColor(Color.BLACK); + g.fillRect(x * SCALE, y * SCALE, SCALE, SCALE); + } + } + } + + // 显示统计信息 + g.setColor(Color.BLACK); + g.setFont(new Font("宋体", Font.PLAIN, 12)); + String info = String.format("字体大小: %dpt | 显示行数: %d/%d | 显示字数: %d", + fontSize, actualLines, maxLines, totalChars); + g.drawString(info, 10, panelHeight + 20); + + String capacity = String.format("容量分析: %d×80点阵可显示%d-%d个汉字(%dpt字体)", + WIDTH, + (int)(WIDTH*HEIGHT/(fontSize*fontSize*1.2)), + (int)(WIDTH*HEIGHT/(fontSize*fontSize*0.8)), + fontSize); + g.drawString(capacity, 10, panelHeight + 35); + } + } + + public static void main(String[] args) { + SwingUtilities.invokeLater(() -> { + DotMatrixDisplaySimulator frame = new DotMatrixDisplaySimulator(); + frame.setVisible(true); + + // 显示使用提示 + String message = "
160×80点阵显示屏文字容量分析

" + + "• 使用上方下拉菜单选择字体大小和示例文本
" + + "• 在文本区域输入自定义内容
" + + "• 点阵预览区域实时显示效果

" + + "容量参考:
" + + "8-9pt:约20字/行 × 10行 = 200字
" + + "10-11pt:约16字/行 × 8行 = 128字
" + + "12-13pt:约13字/行 × 6行 = 78字
" + + "14-15pt:约11字/行 × 5行 = 55字
" + + "16-18pt:约9字/行 × 4行 = 36字
" + + "20-24pt:约7字/行 × 3行 = 21字
"; + + JOptionPane.showMessageDialog(frame, message, "使用说明", JOptionPane.INFORMATION_MESSAGE); + }); + } +} \ No newline at end of file diff --git a/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/utils/c/TextToDotMatrix.java b/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/utils/c/TextToDotMatrix.java new file mode 100644 index 0000000..d594deb --- /dev/null +++ b/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/utils/c/TextToDotMatrix.java @@ -0,0 +1,185 @@ +package com.fuyuanshen.equipment.utils.c; + +import javax.imageio.ImageIO; +import java.awt.*; +import java.awt.image.BufferedImage; +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +public class TextToDotMatrix { + + public static void main(String[] args) { + String text = "现场危险,停止救援,\n紧急撤离至安全区域!"; + int width = 160; // 点阵宽度 + int height = 80; // 点阵高度 + + try { + // 1. 创建点阵图片 + BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_BYTE_BINARY); + Graphics2D g = image.createGraphics(); + + // 设置背景为白色 + g.setColor(Color.WHITE); + g.fillRect(0, 0, width, height); + + // 设置字体并居中显示文本 + g.setColor(Color.BLACK); + g.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON); + + // 自动调整字体大小以适应区域 + Font font = findBestFitFont(text, width, height, g); + g.setFont(font); + + // 计算文本位置并绘制 + drawCenteredText(g, text, width, height); + g.dispose(); + + // 2. 生成二进制数组 + List byteList = new ArrayList<>(); + for (int y = 0; y < height; y++) { + for (int x = 0; x < width; x += 8) { + byte b = 0; + for (int bit = 0; bit < 8; bit++) { + int xPos = x + bit; + if (xPos < width) { + int rgb = image.getRGB(xPos, y) & 0xFFFFFF; + if (rgb != 0xFFFFFF) { // 黑色像素 + b |= (1 << (7 - bit)); + } + } + } + byteList.add(b); + } + } + + // 转换为字节数组 + byte[] dotMatrixData = new byte[byteList.size()]; + for (int i = 0; i < byteList.size(); i++) { + dotMatrixData[i] = byteList.get(i); + } + + // 3. 保存预览图片 + ImageIO.write(image, "png", new File("warning_display.png")); + System.out.println("预览图片已生成: warning_display.png"); + + // 4. 打印点阵数据信息 + System.out.println("\n点阵数据信息:"); + System.out.println("尺寸: " + width + "x" + height + " 像素"); + System.out.println("数据大小: " + dotMatrixData.length + " 字节"); + System.out.println("每行字节数: " + (width / 8)); + System.out.println("总行数: " + height); + + // 5. 打印二进制数组(十六进制格式) + System.out.println("\n点阵数据字节数组 (HEX):"); + System.out.print("byte[] dotMatrixData = {"); + for (int i = 0; i < dotMatrixData.length; i++) { + System.out.printf("0x%02X", dotMatrixData[i] & 0xFF); + if (i < dotMatrixData.length - 1) System.out.print(", "); + if (i % 16 == 15) System.out.println(); + } + System.out.println("};\n"); + + // 6. 打印点阵图预览 + System.out.println("点阵图预览 (缩小版):"); + printTextPreview(image); + + } catch (IOException e) { + e.printStackTrace(); + } + } + + // 自动寻找最佳字体大小 + private static Font findBestFitFont(String text, int width, int height, Graphics2D g) { + int fontSize = 20; // 初始字体大小 + Font bestFont = null; + int bestHeight = 0; + + while (fontSize > 8) { + Font font = new Font("黑体", Font.BOLD, fontSize); + g.setFont(font); + FontMetrics metrics = g.getFontMetrics(); + + // 计算文本所需高度 + String[] lines = text.split("\n"); + int textHeight = metrics.getHeight() * lines.length; + + // 检查是否超出高度 + if (textHeight < height * 0.8) { + bestFont = font; + bestHeight = textHeight; + break; + } + fontSize--; + } + + // 如果没有找到合适字体,使用最小字体 + if (bestFont == null) { + bestFont = new Font("黑体", Font.BOLD, 8); + } + + System.out.println("使用字体: " + bestFont.getSize() + "pt"); + return bestFont; + } + + // 居中绘制文本 + private static void drawCenteredText(Graphics g, String text, int width, int height) { + FontMetrics metrics = g.getFontMetrics(); + String[] lines = text.split("\n"); + + // 计算总文本高度 + int totalHeight = metrics.getHeight() * lines.length; + + // 计算起始Y位置 + int y = (height - totalHeight) / 2 + metrics.getAscent(); + + for (String line : lines) { + // 计算X位置使文本居中 + int x = (width - metrics.stringWidth(line)) / 2; + g.drawString(line, x, y); + y += metrics.getHeight(); + } + } + + // 打印文本预览 + private static void printTextPreview(BufferedImage image) { + int width = image.getWidth(); + int height = image.getHeight(); + + // 缩小预览比例 + int scale = 4; + int previewWidth = width / scale; + int previewHeight = height / scale; + + for (int y = 0; y < previewHeight; y++) { + for (int x = 0; x < previewWidth; x++) { + int pixelCount = 0; + for (int dy = 0; dy < scale; dy++) { + for (int dx = 0; dx < scale; dx++) { + int origX = x * scale + dx; + int origY = y * scale + dy; + if (origX < width && origY < height) { + int rgb = image.getRGB(origX, origY) & 0xFFFFFF; + if (rgb != 0xFFFFFF) { // 黑色像素 + pixelCount++; + } + } + } + } + + // 根据黑色像素密度选择字符 + if (pixelCount > scale * scale * 0.7) { + System.out.print("██"); + } else if (pixelCount > scale * scale * 0.4) { + System.out.print("▓▓"); + } else if (pixelCount > scale * scale * 0.1) { + System.out.print("░░"); + } else { + System.out.print(" "); + } + } + System.out.println(); + } + } +} \ No newline at end of file From 57f074995ed4e6e93c7d22c7a7225b11556dd4b6 Mon Sep 17 00:00:00 2001 From: chenyouting <514333061@qq.com> Date: Mon, 4 Aug 2025 15:35:59 +0800 Subject: [PATCH 14/19] =?UTF-8?q?=E5=8F=91=E9=80=81=E8=AE=BE=E5=A4=87?= =?UTF-8?q?=E4=BF=A1=E6=81=AF=E4=BB=A3=E7=A0=81=E5=AE=9E=E7=8E=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../app/controller/AppDeviceController.java | 8 + .../app/service/AppDeviceBizService.java | 113 ++++- .../LightingCommandTypeConstants.java | 5 + .../global/mqtt/rule/DeviceBootLogoRule.java | 2 +- .../mqtt/rule/DeviceSendMessageRule.java | 76 ++++ .../src/main/resources/image/background.png | Bin 0 -> 397 bytes .../core/utils/Bitmap80x12Generator.java | 2 +- .../core/utils/ImageToCArrayConverter.java | 2 +- .../core/utils/ImageWithTextGenerate.java | 429 ++++++++++++++++++ .../domain/dto/AppDeviceSendMsgBo.java | 6 + 10 files changed, 621 insertions(+), 22 deletions(-) create mode 100644 fys-admin/src/main/java/com/fuyuanshen/global/mqtt/rule/DeviceSendMessageRule.java create mode 100644 fys-admin/src/main/resources/image/background.png create mode 100644 fys-common/fys-common-core/src/main/java/com/fuyuanshen/common/core/utils/ImageWithTextGenerate.java diff --git a/fys-admin/src/main/java/com/fuyuanshen/app/controller/AppDeviceController.java b/fys-admin/src/main/java/com/fuyuanshen/app/controller/AppDeviceController.java index d921708..1151c88 100644 --- a/fys-admin/src/main/java/com/fuyuanshen/app/controller/AppDeviceController.java +++ b/fys-admin/src/main/java/com/fuyuanshen/app/controller/AppDeviceController.java @@ -111,6 +111,14 @@ public class AppDeviceController extends BaseController { return toAjax(appDeviceService.sendMessage(bo)); } + /** + * 发送报警信息 + */ + @PostMapping(value = "/sendAlarmMessage") + public R sendAlarmMessage(@RequestBody AppDeviceSendMsgBo bo) { + return toAjax(appDeviceService.sendAlarmMessage(bo)); + } + /** * 上传设备logo图片 */ diff --git a/fys-admin/src/main/java/com/fuyuanshen/app/service/AppDeviceBizService.java b/fys-admin/src/main/java/com/fuyuanshen/app/service/AppDeviceBizService.java index c1063f7..ac36e82 100644 --- a/fys-admin/src/main/java/com/fuyuanshen/app/service/AppDeviceBizService.java +++ b/fys-admin/src/main/java/com/fuyuanshen/app/service/AppDeviceBizService.java @@ -20,10 +20,7 @@ import com.fuyuanshen.app.mapper.AppPersonnelInfoMapper; import com.fuyuanshen.app.mapper.equipment.APPDeviceMapper; import com.fuyuanshen.common.core.constant.GlobalConstants; import com.fuyuanshen.common.core.exception.ServiceException; -import com.fuyuanshen.common.core.utils.ImageToCArrayConverter; -import com.fuyuanshen.common.core.utils.MapstructUtils; -import com.fuyuanshen.common.core.utils.ObjectUtils; -import com.fuyuanshen.common.core.utils.StringUtils; +import com.fuyuanshen.common.core.utils.*; import com.fuyuanshen.common.mybatis.core.page.PageQuery; import com.fuyuanshen.common.mybatis.core.page.TableDataInfo; import com.fuyuanshen.common.redis.utils.RedisUtils; @@ -44,9 +41,12 @@ import com.fuyuanshen.global.mqtt.constants.DeviceRedisKeyConstants; import com.fuyuanshen.global.mqtt.constants.MqttConstants; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import org.springframework.core.io.ClassPathResource; import org.springframework.stereotype.Service; import org.springframework.web.multipart.MultipartFile; +import java.io.IOException; +import java.io.InputStream; import java.time.Duration; import java.util.*; @@ -89,25 +89,49 @@ public class AppDeviceBizService { throw new ServiceException("请选择设备"); } for (Long deviceId : deviceIds) { - Device deviceObj = deviceMapper.selectById(deviceId); - if (deviceObj == null) { + Device device = deviceMapper.selectById(deviceId); + if (device == null) { throw new ServiceException("设备不存在" + deviceId); } - byte[] msg = ReliableTextToBitmap.textToBitmapBytes(bo.getSendMsg()); - ArrayList intData = new ArrayList<>(); - intData.add(2); - buildArr(convertHexToDecimal(msg), intData); - Map map = new HashMap<>(); - map.put("instruct", intData); - mqttGateway.sendMsgToMqtt(MqttConstants.GLOBAL_PUB_KEY + deviceObj.getDeviceImei(), 1, JSON.toJSONString(map)); - log.info("发送设备消息:topic:{},payload:{}", MqttConstants.GLOBAL_PUB_KEY + deviceObj.getDeviceImei(), bo.getSendMsg()); + try { + ClassPathResource resource = new ClassPathResource("image/background.png"); + InputStream inputStream = resource.getInputStream(); + +// String backgroundImagePath = "D:\\background.png"; // 替换为实际背景图片路径 + byte[] largeData = ImageWithTextGenerate.generate160x80ImageWithText2(bo.getSendMsg(), inputStream, 25600); + int[] ints = convertHexToDecimal(largeData); + RedisUtils.setCacheObject(GLOBAL_REDIS_KEY+"app_send_message_data:" + device.getDeviceImei(), Arrays.toString(ints), Duration.ofSeconds(30 * 60L)); + + String data = RedisUtils.getCacheObject(GLOBAL_REDIS_KEY+"app_send_message_data:" + device.getDeviceImei()); + + byte[] arr = ImageToCArrayConverter.convertStringToByteArray(data); + byte[] specificChunk = ImageToCArrayConverter.getChunk(arr, 0, 512); + System.out.println("第0块数据大小: " + specificChunk.length + " 字节"); + System.out.println("第0块数据: " + Arrays.toString(specificChunk)); + + ArrayList intData = new ArrayList<>(); + intData.add(6); + intData.add(1); + ImageToCArrayConverter.buildArr(convertHexToDecimal(specificChunk),intData); + intData.add(0); + intData.add(0); + intData.add(0); + intData.add(0); + Map map = new HashMap<>(); + map.put("instruct", intData); + mqttGateway.sendMsgToMqtt(MqttConstants.GLOBAL_PUB_KEY+device.getDeviceImei(), 1 , JSON.toJSONString(map)); + log.info("发送点阵数据到设备消息=>topic:{},payload:{}", MqttConstants.GLOBAL_PUB_KEY+device.getDeviceImei(),JSON.toJSONString(map)); + + UpdateWrapper updateWrapper = new UpdateWrapper<>(); + updateWrapper.eq("id", deviceId) + .eq("binding_user_id", AppLoginHelper.getUserId()) + .set("send_msg", bo.getSendMsg()); + deviceMapper.update(updateWrapper); + } catch (Exception e) { + log.info("设备发送信息失败:{}" ,deviceId); + } - UpdateWrapper updateWrapper = new UpdateWrapper<>(); - updateWrapper.eq("id", deviceId) - .eq("binding_user_id", AppLoginHelper.getUserId()) - .set("send_msg", bo.getSendMsg()); - deviceMapper.update(updateWrapper); } return 1; } @@ -390,6 +414,16 @@ public class AppDeviceBizService { } + public static void main(String[] args) throws IOException { + byte[] largeData = ImageToCArrayConverter.convertImageToCArray("E:\\workspace\\demo.png", 160, 80, 25600); + System.out.println("长度:" + largeData.length); + + System.out.println("原始数据大小: " + largeData.length + " 字节"); + + int[] ints = convertHexToDecimal(largeData); + System.out.println("转换后的数据: " + Arrays.toString(ints)); + } + public void uploadDeviceLogo(AppDeviceLogoUploadDto bo) { try { Device device = deviceMapper.selectById(bo.getDeviceId()); @@ -524,4 +558,45 @@ public class AppDeviceBizService { } return RedisUtils.getCacheObject("device:location:" + devices.get(0).getDeviceImei()); } + + public int sendAlarmMessage(AppDeviceSendMsgBo bo) { + try { + List deviceIds = bo.getDeviceIds(); + if (deviceIds == null || deviceIds.isEmpty()) { + throw new ServiceException("请选择设备"); + } + for (Long deviceId : deviceIds) { + Device device = deviceMapper.selectById(deviceId); + if (device == null) { + throw new ServiceException("设备不存在" + deviceId); + } + + try { + ArrayList intData = new ArrayList<>(); + intData.add(7); + intData.add(Integer.parseInt(bo.getInstructValue())); + intData.add(0); + intData.add(0); + intData.add(0); + intData.add(0); + Map map = new HashMap<>(); + map.put("instruct", intData); + mqttGateway.sendMsgToMqtt(MqttConstants.GLOBAL_PUB_KEY+device.getDeviceImei(), 1 , JSON.toJSONString(map)); + log.info("发送点阵数据到设备消息=>topic:{},payload:{}", MqttConstants.GLOBAL_PUB_KEY+device.getDeviceImei(),JSON.toJSONString(map)); + + UpdateWrapper updateWrapper = new UpdateWrapper<>(); + updateWrapper.eq("id", deviceId) + .eq("binding_user_id", AppLoginHelper.getUserId()) + .set("send_msg", bo.getSendMsg()); + deviceMapper.update(updateWrapper); + } catch (Exception e) { + log.info("设备发送信息失败:{}" ,deviceId); + } + + } + } catch (Exception e){ + e.printStackTrace(); + } + return 1; + } } diff --git a/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/constants/LightingCommandTypeConstants.java b/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/constants/LightingCommandTypeConstants.java index 64c8449..c0f1ee7 100644 --- a/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/constants/LightingCommandTypeConstants.java +++ b/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/constants/LightingCommandTypeConstants.java @@ -30,6 +30,11 @@ public class LightingCommandTypeConstants { * 主灯亮度 (Main Light Brightness) */ public static final String MAIN_LIGHT_BRIGHTNESS = "Light_5"; + + /** + * 设备发送消息 + */ + public static final String SEND_MESSAGE = "Light_6"; /** * 定位数据 (Location Data) diff --git a/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/rule/DeviceBootLogoRule.java b/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/rule/DeviceBootLogoRule.java index 8b83e0f..af5bc10 100644 --- a/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/rule/DeviceBootLogoRule.java +++ b/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/rule/DeviceBootLogoRule.java @@ -67,7 +67,7 @@ public class DeviceBootLogoRule implements MqttMessageRule { map.put("instruct", intData); mqttGateway.sendMsgToMqtt(MqttConstants.GLOBAL_PUB_KEY + context.getDeviceImei(), 1, JsonUtils.toJsonString(map)); - log.info("发送人员信息点阵数据到设备消息=>topic:{},payload:{}", + log.info("发送开机LOGO点阵数据到设备消息=>topic:{},payload:{}", MqttConstants.GLOBAL_PUB_KEY + context.getDeviceImei(), JsonUtils.toJsonString(map)); } catch (Exception e) { diff --git a/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/rule/DeviceSendMessageRule.java b/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/rule/DeviceSendMessageRule.java new file mode 100644 index 0000000..fab1fde --- /dev/null +++ b/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/rule/DeviceSendMessageRule.java @@ -0,0 +1,76 @@ +package com.fuyuanshen.global.mqtt.rule; + +import com.fuyuanshen.common.core.constant.GlobalConstants; +import com.fuyuanshen.common.core.utils.ImageToCArrayConverter; +import com.fuyuanshen.common.core.utils.StringUtils; +import com.fuyuanshen.common.json.utils.JsonUtils; +import com.fuyuanshen.common.redis.utils.RedisUtils; +import com.fuyuanshen.global.mqtt.base.MqttMessageRule; +import com.fuyuanshen.global.mqtt.base.MqttRuleContext; +import com.fuyuanshen.global.mqtt.config.MqttGateway; +import com.fuyuanshen.global.mqtt.constants.LightingCommandTypeConstants; +import com.fuyuanshen.global.mqtt.constants.MqttConstants; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Map; + +import static com.fuyuanshen.common.core.utils.ImageToCArrayConverter.convertHexToDecimal; + +/** + * 人员信息命令处理 + */ +@Component +@RequiredArgsConstructor +@Slf4j +public class DeviceSendMessageRule implements MqttMessageRule { + + private final MqttGateway mqttGateway; + + @Override + public String getCommandType() { + return LightingCommandTypeConstants.SEND_MESSAGE; + } + + @Override + public void execute(MqttRuleContext context) { + try { + Byte val2 = (Byte) context.getConvertArr()[1]; + if (val2 == 100) { + return; + } + + String data = RedisUtils.getCacheObject(GlobalConstants.GLOBAL_REDIS_KEY+"app_send_message_data:" + context.getDeviceImei()); + if (StringUtils.isEmpty(data)) { + return; + } + + byte[] arr = ImageToCArrayConverter.convertStringToByteArray(data); + byte[] specificChunk = ImageToCArrayConverter.getChunk(arr, (val2 - 1), 512); + System.out.println("第" + val2 + "块数据大小: " + specificChunk.length + " 字节"); +// System.out.println("第" + val2 + "块数据: " + Arrays.toString(specificChunk)); + + ArrayList intData = new ArrayList<>(); + intData.add(6); + intData.add((int) val2); + ImageToCArrayConverter.buildArr(convertHexToDecimal(specificChunk), intData); + intData.add(0); + intData.add(0); + intData.add(0); + intData.add(0); + + Map map = new HashMap<>(); + map.put("instruct", intData); + + mqttGateway.sendMsgToMqtt(MqttConstants.GLOBAL_PUB_KEY + context.getDeviceImei(), 1, JsonUtils.toJsonString(map)); + log.info("发送设备信息数据到设备消息=>topic:{},payload:{}", + MqttConstants.GLOBAL_PUB_KEY + context.getDeviceImei(), + JsonUtils.toJsonString(map)); + } catch (Exception e) { + log.error("处理人员信息命令时出错", e); + } + } +} diff --git a/fys-admin/src/main/resources/image/background.png b/fys-admin/src/main/resources/image/background.png new file mode 100644 index 0000000000000000000000000000000000000000..1670e7f0d6771452a2584551104143b0df20bea6 GIT binary patch literal 397 zcmeAS@N?(olHy`uVBq!ia0vp^3xGI)g&9cZ6eqI-DaPU;cPGZ1Cw1z99L@rd$YKTt zZeb8+WSBKa0w`z@;1lA?#ls(EC9tl8ZEXkJgN;nhN!%?-+^ag+987r}O?k@VIZER> z5|UEp&YQogoi)-@K>qE@DL}p7JY5_^D&{1oEHFxtF)f%Nbz;R558lN~#1HU<^ye&S zYMfKNcmdm{wOk9DDtUPBEaF#SOY>da1!TAW6<}7L9(?k^GOLb8KK2T|6%GQaY)1cE zB~Mg4N;YX2Pk72dHMYZGf>E&>FVN^K2LhShaWN7T7aZf&lDrYaZ5Z%Jbt=!DXRL-3 zGG(W>uaelhF6gjLUudEHg2lx-RZJCAi=OUcx|$#CePH#g{co7ql-N}yo0FL&wuRXL zap;Lk;z>#HnD|m`xBnC`CEk?cxw@`%ypoP5wEhtbxbCp%;EKlP3l0ot-cAmD(tHgR O;0&IwelF{r5}E+`?~7sp literal 0 HcmV?d00001 diff --git a/fys-common/fys-common-core/src/main/java/com/fuyuanshen/common/core/utils/Bitmap80x12Generator.java b/fys-common/fys-common-core/src/main/java/com/fuyuanshen/common/core/utils/Bitmap80x12Generator.java index 5c6996e..5a678e5 100644 --- a/fys-common/fys-common-core/src/main/java/com/fuyuanshen/common/core/utils/Bitmap80x12Generator.java +++ b/fys-common/fys-common-core/src/main/java/com/fuyuanshen/common/core/utils/Bitmap80x12Generator.java @@ -242,7 +242,7 @@ public class Bitmap80x12Generator { return byteListToArray(byteList); } - private static byte[] byteListToArray(List byteList) { + public static byte[] byteListToArray(List byteList) { byte[] result = new byte[byteList.size()]; for (int i = 0; i < byteList.size(); i++) { result[i] = byteList.get(i); diff --git a/fys-common/fys-common-core/src/main/java/com/fuyuanshen/common/core/utils/ImageToCArrayConverter.java b/fys-common/fys-common-core/src/main/java/com/fuyuanshen/common/core/utils/ImageToCArrayConverter.java index 45fea74..8823ad0 100644 --- a/fys-common/fys-common-core/src/main/java/com/fuyuanshen/common/core/utils/ImageToCArrayConverter.java +++ b/fys-common/fys-common-core/src/main/java/com/fuyuanshen/common/core/utils/ImageToCArrayConverter.java @@ -33,7 +33,7 @@ public class ImageToCArrayConverter { public static void main(String[] args) throws IOException { - byte[] largeData = convertImageToCArray("E:\\workspace\\6170_强光_160_80_2.jpg", 160, 80,25600); + byte[] largeData = convertImageToCArray("E:\\workspace\\demo.png", 160, 80,25600); System.out.println("长度:"+largeData.length); System.out.println("原始数据大小: " + largeData.length + " 字节"); diff --git a/fys-common/fys-common-core/src/main/java/com/fuyuanshen/common/core/utils/ImageWithTextGenerate.java b/fys-common/fys-common-core/src/main/java/com/fuyuanshen/common/core/utils/ImageWithTextGenerate.java new file mode 100644 index 0000000..dafb9a6 --- /dev/null +++ b/fys-common/fys-common-core/src/main/java/com/fuyuanshen/common/core/utils/ImageWithTextGenerate.java @@ -0,0 +1,429 @@ +package com.fuyuanshen.common.core.utils; + +import javax.imageio.ImageIO; +import java.awt.*; +import java.awt.image.BufferedImage; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; + +public class ImageWithTextGenerate { + + /** + * 生成160*80画布,嵌入背景图片并居中显示文字(支持自动换行),输出RGB565格式数据 + * + * @param text 要显示的文字 + * @param fixedLength 固定输出长度(字节数) + * @return RGB565格式的图像数据 + */ + public static byte[] generate160x80ImageWithText2(String text, InputStream backgroundImageInputStream, int fixedLength) throws IOException { + // 创建160*80的图像 + BufferedImage image = new BufferedImage(160, 80, BufferedImage.TYPE_INT_RGB); + Graphics2D g = image.createGraphics(); + + // 绘制白色背景 + g.setColor(Color.WHITE); + g.fillRect(0, 0, 160, 80); + + // 如果提供了背景图片,则绘制背景 + if (backgroundImageInputStream != null ) { + BufferedImage backgroundImage = ImageIO.read(backgroundImageInputStream); + // 缩放并绘制背景图片以适应160*80画布 + g.drawImage(backgroundImage, 0, 0, 160, 80, null); + } + + // 设置文字属性 + Font font = new Font("宋体", Font.PLAIN, 12); // 可根据需要调整字体大小 + g.setFont(font); + g.setColor(new Color(255, 255, 255, (int)(0.6 * 255))); + + // 关闭抗锯齿以获得清晰的点阵效果 + g.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, + RenderingHints.VALUE_TEXT_ANTIALIAS_OFF); + g.setRenderingHint(RenderingHints.KEY_RENDERING, + RenderingHints.VALUE_RENDER_QUALITY); + + // 获取字体度量信息 + FontMetrics metrics = g.getFontMetrics(); + int lineHeight = metrics.getHeight(); + + // 文本换行处理 + ArrayList lines = wrapText(text, metrics, 120); // 160为画布宽度 + + // 计算垂直居中起始位置 + int totalTextHeight = lines.size() * lineHeight; + int startY = (80 - totalTextHeight) / 2 + metrics.getAscent(); + + // 绘制每一行文字 + for (int i = 0; i < lines.size(); i++) { + String line = lines.get(i); + int lineWidth = metrics.stringWidth(line); + int x = (160 - lineWidth) / 2; // 水平居中 + int y = startY + i * lineHeight; + g.drawString(line, x, y); + } + + g.dispose(); + + // 转换像素数据为RGB565格式(高位在前) + ByteArrayOutputStream byteStream = new ByteArrayOutputStream(); + for (int yCoord = 0; yCoord < 80; yCoord++) { + for (int xCoord = 0; xCoord < 160; xCoord++) { + int rgb = image.getRGB(xCoord, yCoord); + + // 提取RGB分量 + int r = (rgb >> 16) & 0xFF; + int g1 = (rgb >> 8) & 0xFF; + int b = rgb & 0xFF; + + // 转换为RGB565(5位红,6位绿,5位蓝) + int r5 = (r >> 3) & 0x1F; + int g6 = (g1 >> 2) & 0x3F; + int b5 = (b >> 3) & 0x1F; + + // 组合为16位值 + int rgb565 = (r5 << 11) | (g6 << 5) | b5; + + // 高位在前(大端序)写入字节 + byteStream.write((rgb565 >> 8) & 0xFF); // 高字节 + byteStream.write(rgb565 & 0xFF); // 低字节 + } + } + + // 调整到固定长度 + byte[] rawData = byteStream.toByteArray(); + byte[] result = new byte[fixedLength]; + int copyLength = Math.min(rawData.length, fixedLength); + System.arraycopy(rawData, 0, result, 0, copyLength); + return result; + } + /** + * 生成160*80画布,嵌入背景图片并居中显示文字(支持自动换行),输出RGB565格式数据 + * + * @param text 要显示的文字 + * @param backgroundImagePath 背景图片路径 + * @param fixedLength 固定输出长度(字节数) + * @return RGB565格式的图像数据 + */ + public static byte[] generate160x80ImageWithText(String text, String backgroundImagePath, int fixedLength) throws IOException { + // 创建160*80的图像 + BufferedImage image = new BufferedImage(160, 80, BufferedImage.TYPE_INT_RGB); + Graphics2D g = image.createGraphics(); + + // 绘制白色背景 + g.setColor(Color.WHITE); + g.fillRect(0, 0, 160, 80); + + // 如果提供了背景图片,则绘制背景 + if (backgroundImagePath != null && !backgroundImagePath.isEmpty()) { + File backgroundFile = new File(backgroundImagePath); + if (backgroundFile.exists()) { + BufferedImage backgroundImage = ImageIO.read(backgroundFile); + // 缩放并绘制背景图片以适应160*80画布 + g.drawImage(backgroundImage, 0, 0, 160, 80, null); + } + } + + // 设置文字属性 + Font font = new Font("宋体", Font.PLAIN, 12); // 可根据需要调整字体大小 + g.setFont(font); + g.setColor(new Color(255, 255, 255, (int)(0.6 * 255))); + + // 关闭抗锯齿以获得清晰的点阵效果 + g.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, + RenderingHints.VALUE_TEXT_ANTIALIAS_OFF); + g.setRenderingHint(RenderingHints.KEY_RENDERING, + RenderingHints.VALUE_RENDER_QUALITY); + + // 获取字体度量信息 + FontMetrics metrics = g.getFontMetrics(); + int lineHeight = metrics.getHeight(); + + // 文本换行处理 + ArrayList lines = wrapText(text, metrics, 120); // 160为画布宽度 + + // 计算垂直居中起始位置 + int totalTextHeight = lines.size() * lineHeight; + int startY = (80 - totalTextHeight) / 2 + metrics.getAscent(); + + // 绘制每一行文字 + for (int i = 0; i < lines.size(); i++) { + String line = lines.get(i); + int lineWidth = metrics.stringWidth(line); + int x = (160 - lineWidth) / 2; // 水平居中 + int y = startY + i * lineHeight; + g.drawString(line, x, y); + } + + g.dispose(); + + // 转换像素数据为RGB565格式(高位在前) + ByteArrayOutputStream byteStream = new ByteArrayOutputStream(); + for (int yCoord = 0; yCoord < 80; yCoord++) { + for (int xCoord = 0; xCoord < 160; xCoord++) { + int rgb = image.getRGB(xCoord, yCoord); + + // 提取RGB分量 + int r = (rgb >> 16) & 0xFF; + int g1 = (rgb >> 8) & 0xFF; + int b = rgb & 0xFF; + + // 转换为RGB565(5位红,6位绿,5位蓝) + int r5 = (r >> 3) & 0x1F; + int g6 = (g1 >> 2) & 0x3F; + int b5 = (b >> 3) & 0x1F; + + // 组合为16位值 + int rgb565 = (r5 << 11) | (g6 << 5) | b5; + + // 高位在前(大端序)写入字节 + byteStream.write((rgb565 >> 8) & 0xFF); // 高字节 + byteStream.write(rgb565 & 0xFF); // 低字节 + } + } + + // 调整到固定长度 + byte[] rawData = byteStream.toByteArray(); + byte[] result = new byte[fixedLength]; + int copyLength = Math.min(rawData.length, fixedLength); + System.arraycopy(rawData, 0, result, 0, copyLength); + return result; + } + + /** + * 文本换行处理 + * + * @param text 原始文本 + * @param metrics 字体度量信息 + * @param maxWidth 最大宽度 + * @return 换行后的文本行列表 + */ + private static ArrayList wrapText(String text, FontMetrics metrics, int maxWidth) { + ArrayList lines = new ArrayList<>(); + String[] paragraphs = text.split("\n"); + + for (String paragraph : paragraphs) { + String[] words = paragraph.split("(?<=\\S)(?=\\s)|(?<=\\s)(?=\\S)"); + StringBuilder line = new StringBuilder(); + + for (String word : words) { + String testLine = line.toString() + word; + int lineWidth = metrics.stringWidth(testLine); + + if (lineWidth <= maxWidth) { + line.append(word); + } else { + if (line.length() > 0) { + lines.add(line.toString()); + line = new StringBuilder(word); + } else { + // 单个词就超过宽度,需要进一步拆分 + lines.addAll(wrapWord(word, metrics, maxWidth)); + } + } + } + + if (line.length() > 0) { + lines.add(line.toString()); + } + } + + // 限制最大行数以适应80像素高度 + if (lines.size() > 6) { // 假设每行最多13像素高,80/13约等于6 + return (ArrayList) lines.subList(0, 6); + } + + return lines; + } + + /** + * 对单个超长词进行拆分 + * + * @param word 单词 + * @param metrics 字体度量信息 + * @param maxWidth 最大宽度 + * @return 拆分后的词列表 + */ + private static ArrayList wrapWord(String word, FontMetrics metrics, int maxWidth) { + ArrayList result = new ArrayList<>(); + StringBuilder current = new StringBuilder(); + + for (char c : word.toCharArray()) { + String testStr = current.toString() + c; + if (metrics.stringWidth(testStr) <= maxWidth) { + current.append(c); + } else { + if (current.length() > 0) { + result.add(current.toString()); + } + current = new StringBuilder(String.valueOf(c)); + } + } + + if (current.length() > 0) { + result.add(current.toString()); + } + + return result; + } + + /** + * 生成160*80画布,嵌入背景图片并居中显示文字,输出RGB565格式数据(支持InputStream) + * + * @param text 要显示的文字 + * @param backgroundImageInputStream 背景图片输入流 + * @param fixedLength 固定输出长度(字节数) + * @return RGB565格式的图像数据 + */ + public static byte[] generate160x80ImageWithText(String text, InputStream backgroundImageInputStream, int fixedLength) throws IOException { + // 创建160*80的图像 + BufferedImage image = new BufferedImage(160, 80, BufferedImage.TYPE_INT_RGB); + Graphics2D g = image.createGraphics(); + + // 绘制白色背景 + g.setColor(Color.WHITE); + g.fillRect(0, 0, 160, 80); + + // 如果提供了背景图片,则绘制背景 + if (backgroundImageInputStream != null) { + BufferedImage backgroundImage = ImageIO.read(backgroundImageInputStream); + // 缩放并绘制背景图片以适应160*80画布 + g.drawImage(backgroundImage, 0, 0, 160, 80, null); + } + + // 设置文字属性 + Font font = new Font("宋体", Font.PLAIN, 16); // 可根据需要调整字体大小 + g.setFont(font); + g.setColor(Color.BLACK); + + // 关闭抗锯齿以获得清晰的点阵效果 + g.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, + RenderingHints.VALUE_TEXT_ANTIALIAS_OFF); + g.setRenderingHint(RenderingHints.KEY_RENDERING, + RenderingHints.VALUE_RENDER_QUALITY); + + // 获取字体度量信息 + FontMetrics metrics = g.getFontMetrics(); + + // 计算文字的宽度和高度 + int textWidth = metrics.stringWidth(text); + int textHeight = metrics.getHeight(); + + // 计算居中位置 + int x = (160 - textWidth) / 2; // 水平居中 + int y = (80 - textHeight) / 2 + metrics.getAscent(); // 垂直居中 + + // 绘制文字 + g.drawString(text, x, y); + + g.dispose(); + + // 转换像素数据为RGB565格式(高位在前) + ByteArrayOutputStream byteStream = new ByteArrayOutputStream(); + for (int yCoord = 0; yCoord < 80; yCoord++) { + for (int xCoord = 0; xCoord < 160; xCoord++) { + int rgb = image.getRGB(xCoord, yCoord); + + // 提取RGB分量 + int r = (rgb >> 16) & 0xFF; + int g1 = (rgb >> 8) & 0xFF; + int b = rgb & 0xFF; + + // 转换为RGB565(5位红,6位绿,5位蓝) + int r5 = (r >> 3) & 0x1F; + int g6 = (g1 >> 2) & 0x3F; + int b5 = (b >> 3) & 0x1F; + + // 组合为16位值 + int rgb565 = (r5 << 11) | (g6 << 5) | b5; + + // 高位在前(大端序)写入字节 + byteStream.write((rgb565 >> 8) & 0xFF); // 高字节 + byteStream.write(rgb565 & 0xFF); // 低字节 + } + } + + // 调整到固定长度 + byte[] rawData = byteStream.toByteArray(); + byte[] result = new byte[fixedLength]; + int copyLength = Math.min(rawData.length, fixedLength); + System.arraycopy(rawData, 0, result, 0, copyLength); + return result; + } + /** + * 将RGB565格式的字节数组转换为BufferedImage + * + * @param data RGB565格式的数据 + * @param height 图像高度 + * @param width 图像宽度 + * @return 转换后的BufferedImage + */ + public static BufferedImage convertByteArrayToImage(byte[] data, int height, int width) { + if (data == null || data.length == 0) { + return new BufferedImage(1, 1, BufferedImage.TYPE_INT_RGB); + } + + // 创建图像 + BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); + + // 处理RGB565数据 + int dataIndex = 0; + for (int y = 0; y < height; y++) { + for (int x = 0; x < width; x++) { + // 每个像素占2个字节 + if (dataIndex + 1 >= data.length) { + return image; + } + + // 读取两个字节组成RGB565值 + int highByte = data[dataIndex++] & 0xFF; + int lowByte = data[dataIndex++] & 0xFF; + int rgb565 = (highByte << 8) | lowByte; + + // 将RGB565转换为RGB888 + int r = ((rgb565 >> 11) & 0x1F) << 3; + int g = ((rgb565 >> 5) & 0x3F) << 2; + int b = (rgb565 & 0x1F) << 3; + + int rgb = (r << 16) | (g << 8) | b; + image.setRGB(x, y, rgb); + } + } + + return image; + } + + + public static void main(String[] args) throws IOException { + // ... 原有代码 ... + + // 测试生成160*80画布,嵌入背景图片并居中显示文字 +// String text = "现在危险,停止救援紧急撤离至安全区域"; + String text = "现在危险,停止救援,紧急撤离至安全区域!"; + String backgroundImagePath = "D:\\background.png"; // 替换为实际背景图片路径 + byte[] imageData = generate160x80ImageWithText(text, backgroundImagePath, 25600); + + System.out.println("生成的160*80 RGB565图像数据:"); + System.out.println("数据长度: " + imageData.length + " 字节"); + // 生成预览图片 + // 生成预览图片 + BufferedImage image160x80 = convertByteArrayToImage(imageData, 80, 160); + ImageIO.write(image160x80, "PNG", new File("D:\\bitmap_160x80_preview.png")); +// System.out.println("成功生成160*80预览图片: D:\\bitmap_160x80_preview.png"); + // 转换为十进制数组 +// int[] decimalArray = convertHexToDecimal(imageData); +// System.out.println("生成的十进制数据(前50个):"); +// System.out.println(Arrays.toString(Arrays.copyOf(decimalArray, Math.min(50, decimalArray.length)))); +// +// // 将数据分割成512字节的块 +// List chunks = splitByteArrayIntoChunks(imageData, 512); +// printChunkInfo(chunks); +// +// // 示例:获取特定块的数据 +// byte[] specificChunk = getChunk(imageData, 0, 512); // 获取第1块(索引0) +// System.out.println("第1块数据大小: " + specificChunk.length + " 字节"); + } + +} diff --git a/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/domain/dto/AppDeviceSendMsgBo.java b/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/domain/dto/AppDeviceSendMsgBo.java index 40caaad..1b57ec6 100644 --- a/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/domain/dto/AppDeviceSendMsgBo.java +++ b/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/domain/dto/AppDeviceSendMsgBo.java @@ -13,4 +13,10 @@ public class AppDeviceSendMsgBo { private String sendMsg; private List deviceIds; + + /** + * 下发指令 + */ + private String instructValue; + } From c2eb5ba52495ee030b2a02380f6c968bf3bdafbd Mon Sep 17 00:00:00 2001 From: daiyongfei <974332738@qq.com> Date: Wed, 6 Aug 2025 09:12:47 +0800 Subject: [PATCH 15/19] =?UTF-8?q?=E6=97=A5=E5=BF=97=E9=85=8D=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../mqtt/constants/TenantsConstant.java | 27 +++++++++++++++++++ .../mqtt/DeviceReceiverMessageHandler.java | 8 +++++- .../src/main/resources/application-dev.yml | 6 ++--- fys-admin/src/main/resources/application.yml | 5 ++-- fys-admin/src/main/resources/logback-plus.xml | 14 +++++----- pom.xml | 14 ++++++++++ 6 files changed, 61 insertions(+), 13 deletions(-) create mode 100644 fys-admin/src/main/java/com/fuyuanshen/global/mqtt/constants/TenantsConstant.java diff --git a/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/constants/TenantsConstant.java b/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/constants/TenantsConstant.java new file mode 100644 index 0000000..84931d7 --- /dev/null +++ b/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/constants/TenantsConstant.java @@ -0,0 +1,27 @@ +package com.fuyuanshen.global.mqtt.constants; + +/** + * 租户常量定义类 + * 包含系统中使用的各种租户标识 + * + * @author: 默苍璃 + * @date: 2025-08-05 10:46 + */ +public class TenantsConstant { + + /** + * 晶全租户 + */ + public static final String JING_QUAN = "014443"; + + /** + * 富源晟租户 + */ + public static final String FU_YUAN_SHENG = "894078"; + + /** + * 管理员租户 + */ + public static final String ADMIN = "000000"; + +} diff --git a/fys-admin/src/main/java/com/fuyuanshen/web/handler/mqtt/DeviceReceiverMessageHandler.java b/fys-admin/src/main/java/com/fuyuanshen/web/handler/mqtt/DeviceReceiverMessageHandler.java index 2f31fc3..3548e13 100644 --- a/fys-admin/src/main/java/com/fuyuanshen/web/handler/mqtt/DeviceReceiverMessageHandler.java +++ b/fys-admin/src/main/java/com/fuyuanshen/web/handler/mqtt/DeviceReceiverMessageHandler.java @@ -3,12 +3,14 @@ package com.fuyuanshen.web.handler.mqtt; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; +import com.fuyuanshen.common.satoken.utils.LoginHelper; import com.fuyuanshen.equipment.domain.Device; import com.fuyuanshen.equipment.domain.DeviceLog; import com.fuyuanshen.equipment.mapper.DeviceLogMapper; import com.fuyuanshen.equipment.mapper.DeviceMapper; import com.fuyuanshen.equipment.utils.map.GetAddressFromLatUtil; import com.fuyuanshen.equipment.utils.map.LngLonUtil; +import com.fuyuanshen.global.mqtt.constants.TenantsConstant; import com.fuyuanshen.web.enums.InstructType6170; import com.fuyuanshen.web.enums.LightModeEnum6170; import lombok.AllArgsConstructor; @@ -52,12 +54,16 @@ public class DeviceReceiverMessageHandler implements MessageHandler { String receivedTopicName = (String) headers.get("mqtt_receivedTopic"); System.out.println("消息来自主题:" + receivedTopicName); + // String tenantId = LoginHelper.getTenantId(); + String tenantId = TenantsConstant.FU_YUAN_SHENG; String payload = message.getPayload().toString(); if (receivedTopicName != null) { // 1. 提取设备ID (从主题中获取) String deviceImei = extractDeviceId(receivedTopicName); - Device device = deviceMapper.selectOne(new QueryWrapper().eq("device_imei", deviceImei)); + Device device = deviceMapper.selectOne(new QueryWrapper() + .eq("tenant_id", tenantId) + .eq("device_imei", deviceImei)); if (device == null) { log.info("不存在的设备IMEI: {}", deviceImei); } else { diff --git a/fys-admin/src/main/resources/application-dev.yml b/fys-admin/src/main/resources/application-dev.yml index a9cb4ba..e586574 100644 --- a/fys-admin/src/main/resources/application-dev.yml +++ b/fys-admin/src/main/resources/application-dev.yml @@ -1,15 +1,15 @@ --- # 监控中心配置 spring.boot.admin.client: # 增加客户端开关 - enabled: false + enabled: true url: http://localhost:9090/admin instance: service-host-type: IP metadata: username: ${spring.boot.admin.client.username} userpassword: ${spring.boot.admin.client.password} - username: @monitor.username@ - password: @monitor.password@ + username: ${monitor.username} + password: ${monitor.password} --- # snail-job 配置 snail-job: diff --git a/fys-admin/src/main/resources/application.yml b/fys-admin/src/main/resources/application.yml index 3744835..60c9106 100644 --- a/fys-admin/src/main/resources/application.yml +++ b/fys-admin/src/main/resources/application.yml @@ -35,7 +35,8 @@ captcha: # 日志配置 logging: level: - com.fuyuanshen: @logging.level@ + #com.fuyuanshen: @logging.level@ + com.fuyuanshen: ${logging.level} org.springframework: warn org.mybatis.spring.mapper: error org.apache.fury: warn @@ -254,7 +255,7 @@ management: health: show-details: ALWAYS logfile: - external-file: ./logs/sys-console.log + external-file: ./logs/sys-admin-console.log --- # 默认/推荐使用sse推送 sse: diff --git a/fys-admin/src/main/resources/logback-plus.xml b/fys-admin/src/main/resources/logback-plus.xml index afb8124..e58ea44 100644 --- a/fys-admin/src/main/resources/logback-plus.xml +++ b/fys-admin/src/main/resources/logback-plus.xml @@ -15,13 +15,13 @@ - ${log.path}/sys-console.log - - - - - - + ${log.path}/sys-admin-console.log + + + ${log.path}/sys-admin-console.log.%d{yyyy-MM-dd}.log + + 1 + ${log.pattern} utf-8 diff --git a/pom.xml b/pom.xml index 67f04f5..3adbdc0 100644 --- a/pom.xml +++ b/pom.xml @@ -101,6 +101,20 @@ + + jingquan + + + jingquan + info + fys + 123456 + + + + + + From 67764a733ef48bd9a65f6d7756e2b341b6b6b84e Mon Sep 17 00:00:00 2001 From: chenyouting <514333061@qq.com> Date: Wed, 6 Aug 2025 10:38:21 +0800 Subject: [PATCH 16/19] =?UTF-8?q?=E8=AE=BE=E5=A4=87=E5=88=97=E8=A1=A8?= =?UTF-8?q?=E7=94=B5=E9=87=8F=E6=98=BE=E7=A4=BA=E9=97=AE=E9=A2=98=EF=BC=8C?= =?UTF-8?q?=E6=89=93=E5=8D=B0=E6=97=A5=E5=BF=97=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/fuyuanshen/app/service/AppDeviceBizService.java | 3 --- .../com/fuyuanshen/global/mqtt/config/MqttGateway.java | 6 ------ .../fuyuanshen/global/mqtt/publish/MqttMessageSender.java | 7 +------ .../fuyuanshen/global/mqtt/rule/DeviceBootLogoRule.java | 2 +- .../fuyuanshen/global/mqtt/rule/DeviceSendMessageRule.java | 2 +- .../com/fuyuanshen/global/mqtt/rule/LocationDataRule.java | 2 +- fys-admin/src/main/resources/application-prod.yml | 6 +++--- 7 files changed, 7 insertions(+), 21 deletions(-) diff --git a/fys-admin/src/main/java/com/fuyuanshen/app/service/AppDeviceBizService.java b/fys-admin/src/main/java/com/fuyuanshen/app/service/AppDeviceBizService.java index ac36e82..98142e9 100644 --- a/fys-admin/src/main/java/com/fuyuanshen/app/service/AppDeviceBizService.java +++ b/fys-admin/src/main/java/com/fuyuanshen/app/service/AppDeviceBizService.java @@ -166,13 +166,10 @@ public class AppDeviceBizService { } String location = RedisUtils.getCacheObject(GLOBAL_REDIS_KEY+DeviceRedisKeyConstants.DEVICE_LOCATION_KEY_PREFIX + item.getDeviceImei()); - // 获取电量 if(StringUtils.isNotBlank(location)){ JSONObject jsonObject = JSONObject.parseObject(location); item.setLatitude(jsonObject.getString("latitude")); item.setLongitude(jsonObject.getString("longitude")); - }else{ - item.setBattery("0"); } } }); diff --git a/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/config/MqttGateway.java b/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/config/MqttGateway.java index a1b8eb2..822e5bf 100644 --- a/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/config/MqttGateway.java +++ b/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/config/MqttGateway.java @@ -4,12 +4,6 @@ import org.springframework.integration.annotation.MessagingGateway; import org.springframework.integration.mqtt.support.MqttHeaders; import org.springframework.messaging.handler.annotation.Header; -/** - * @Author: HarryLin - * @Date: 2025/3/20 17:06 - * @Company: 北京红山信息科技研究院有限公司 - * @Email: linyun@***.com.cn - **/ @MessagingGateway(defaultRequestChannel = "mqttOutboundChannel") public interface MqttGateway { public abstract void sendMsgToMqtt(@Header(value = MqttHeaders.TOPIC) String topic, String payload); diff --git a/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/publish/MqttMessageSender.java b/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/publish/MqttMessageSender.java index dcb429c..bb00124 100644 --- a/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/publish/MqttMessageSender.java +++ b/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/publish/MqttMessageSender.java @@ -6,12 +6,7 @@ import org.springframework.integration.mqtt.support.MqttHeaders; import org.springframework.messaging.handler.annotation.Header; import org.springframework.stereotype.Service; -/** - * @Author: HarryLin - * @Date: 2025/3/20 16:16 - * @Company: 北京红山信息科技研究院有限公司 - * @Email: linyun@***.com.cn - **/ + @Service public class MqttMessageSender { @Autowired diff --git a/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/rule/DeviceBootLogoRule.java b/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/rule/DeviceBootLogoRule.java index af5bc10..288a78a 100644 --- a/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/rule/DeviceBootLogoRule.java +++ b/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/rule/DeviceBootLogoRule.java @@ -51,7 +51,7 @@ public class DeviceBootLogoRule implements MqttMessageRule { byte[] arr = ImageToCArrayConverter.convertStringToByteArray(data); byte[] specificChunk = ImageToCArrayConverter.getChunk(arr, (val2 - 1), 512); - System.out.println("第" + val2 + "块数据大小: " + specificChunk.length + " 字节"); + log.info("第{}块数据大小: {} 字节", val2, specificChunk.length); // System.out.println("第" + val2 + "块数据: " + Arrays.toString(specificChunk)); ArrayList intData = new ArrayList<>(); diff --git a/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/rule/DeviceSendMessageRule.java b/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/rule/DeviceSendMessageRule.java index fab1fde..6c2176b 100644 --- a/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/rule/DeviceSendMessageRule.java +++ b/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/rule/DeviceSendMessageRule.java @@ -50,7 +50,7 @@ public class DeviceSendMessageRule implements MqttMessageRule { byte[] arr = ImageToCArrayConverter.convertStringToByteArray(data); byte[] specificChunk = ImageToCArrayConverter.getChunk(arr, (val2 - 1), 512); - System.out.println("第" + val2 + "块数据大小: " + specificChunk.length + " 字节"); + log.info("第{}块数据大小: {} 字节", val2, specificChunk.length); // System.out.println("第" + val2 + "块数据: " + Arrays.toString(specificChunk)); ArrayList intData = new ArrayList<>(); diff --git a/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/rule/LocationDataRule.java b/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/rule/LocationDataRule.java index 16dec3b..71e9403 100644 --- a/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/rule/LocationDataRule.java +++ b/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/rule/LocationDataRule.java @@ -181,7 +181,7 @@ public class LocationDataRule implements MqttMessageRule { // RedisUtils.expire(trajectoryKey, Duration.ofDays(30)); // 清理30天前的数据(冗余保护) - long thirtyDaysAgo = System.currentTimeMillis() - (90L * 24 * 60 * 60 * 1000); + long thirtyDaysAgo = System.currentTimeMillis() - (7L * 24 * 60 * 60 * 1000); RedisUtils.zRemoveRangeByScore(trajectoryKey, 0, thirtyDaysAgo); } catch (Exception e) { log.error("存储设备轨迹到Redis(ZSet)失败: device={}, error={}", deviceImei, e.getMessage(), e); diff --git a/fys-admin/src/main/resources/application-prod.yml b/fys-admin/src/main/resources/application-prod.yml index 45255db..8f210fb 100644 --- a/fys-admin/src/main/resources/application-prod.yml +++ b/fys-admin/src/main/resources/application-prod.yml @@ -107,7 +107,7 @@ spring.data: # 数据库索引 database: 1 # redis 密码必须配置 - password: re_fs_11520631 + password: xhYc_djkl382^#780! # 连接超时时间 timeout: 10s # 是否开启ssl @@ -280,8 +280,8 @@ mqtt: password: #YtvpSfCNG url: tcp://47.120.79.150:2883 subClientId: fys_subClient - subTopic: worker/alert/#,worker/location/# - pubTopic: worker/location + subTopic: A/#,B/#,worker/location/# + pubTopic: B/# pubClientId: fys_pubClient From f67e84825630482174f135f6cd4a0a2f8bf01d8c Mon Sep 17 00:00:00 2001 From: chenyouting <514333061@qq.com> Date: Thu, 7 Aug 2025 15:41:57 +0800 Subject: [PATCH 17/19] =?UTF-8?q?=E6=99=B6=E5=85=A86710?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../app/controller/AppDeviceController.java | 102 ----- .../device/AppDeviceBJQController.java | 119 ++++++ .../device/AppDeviceHBYController.java | 112 +++++ .../app/service/AppDeviceBizService.java | 42 +- .../device/AppDeviceBJQBizService.java | 388 ++++++++++++++++++ .../constants/DeviceRedisKeyConstants.java | 50 ++- .../mqtt/receiver/ReceiverMessageHandler.java | 4 +- .../BjqActiveReportingDeviceDataRule.java} | 15 +- .../mqtt/rule/bjq6170/BjqAlarmRule.java | 69 ++++ .../BjqBootLogoRule.java} | 13 +- .../BjqLocationDataRule.java} | 13 +- .../global/mqtt/rule/bjq6170/BjqModeRule.java | 75 ++++ .../BjqSendMessageRule.java} | 11 +- .../src/main/resources/application-dev.yml | 2 +- .../app/domain/vo/AppDeviceDetailVo.java | 5 + .../equipment/domain/vo/AppDeviceVo.java | 5 + 16 files changed, 871 insertions(+), 154 deletions(-) create mode 100644 fys-admin/src/main/java/com/fuyuanshen/app/controller/device/AppDeviceBJQController.java create mode 100644 fys-admin/src/main/java/com/fuyuanshen/app/controller/device/AppDeviceHBYController.java create mode 100644 fys-admin/src/main/java/com/fuyuanshen/app/service/device/AppDeviceBJQBizService.java rename fys-admin/src/main/java/com/fuyuanshen/global/mqtt/rule/{ActiveReportingDeviceDataRule.java => bjq6170/BjqActiveReportingDeviceDataRule.java} (91%) create mode 100644 fys-admin/src/main/java/com/fuyuanshen/global/mqtt/rule/bjq6170/BjqAlarmRule.java rename fys-admin/src/main/java/com/fuyuanshen/global/mqtt/rule/{DeviceBootLogoRule.java => bjq6170/BjqBootLogoRule.java} (81%) rename fys-admin/src/main/java/com/fuyuanshen/global/mqtt/rule/{LocationDataRule.java => bjq6170/BjqLocationDataRule.java} (95%) create mode 100644 fys-admin/src/main/java/com/fuyuanshen/global/mqtt/rule/bjq6170/BjqModeRule.java rename fys-admin/src/main/java/com/fuyuanshen/global/mqtt/rule/{DeviceSendMessageRule.java => bjq6170/BjqSendMessageRule.java} (83%) diff --git a/fys-admin/src/main/java/com/fuyuanshen/app/controller/AppDeviceController.java b/fys-admin/src/main/java/com/fuyuanshen/app/controller/AppDeviceController.java index 1151c88..beb899e 100644 --- a/fys-admin/src/main/java/com/fuyuanshen/app/controller/AppDeviceController.java +++ b/fys-admin/src/main/java/com/fuyuanshen/app/controller/AppDeviceController.java @@ -1,31 +1,20 @@ package com.fuyuanshen.app.controller; -import cn.hutool.json.JSON; -import com.alibaba.fastjson2.JSONObject; -import com.fuyuanshen.app.domain.bo.AppPersonnelInfoBo; import com.fuyuanshen.app.domain.dto.APPReNameDTO; -import com.fuyuanshen.app.domain.dto.AppDeviceLogoUploadDto; -import com.fuyuanshen.app.domain.dto.DeviceInstructDto; import com.fuyuanshen.app.domain.vo.APPDeviceTypeVo; -import com.fuyuanshen.app.domain.vo.AppDeviceDetailVo; import com.fuyuanshen.app.service.AppDeviceBizService; import com.fuyuanshen.common.core.domain.R; -import com.fuyuanshen.common.core.validate.AddGroup; import com.fuyuanshen.common.mybatis.core.page.PageQuery; import com.fuyuanshen.common.mybatis.core.page.TableDataInfo; import com.fuyuanshen.common.web.core.BaseController; import com.fuyuanshen.equipment.domain.dto.AppDeviceBo; -import com.fuyuanshen.equipment.domain.dto.AppDeviceSendMsgBo; import com.fuyuanshen.equipment.domain.query.DeviceQueryCriteria; import com.fuyuanshen.equipment.domain.vo.AppDeviceVo; -import jakarta.validation.constraints.NotNull; import lombok.RequiredArgsConstructor; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; -import org.springframework.web.multipart.MultipartFile; import java.util.List; -import java.util.Map; /** * APP设备信息管理 @@ -83,95 +72,4 @@ public class AppDeviceController extends BaseController { appDeviceService.reName(reNameDTO); return R.ok("重命名成功!!!"); } - - /** - * 获取设备详细信息 - * - * @param id 主键 - */ - @GetMapping("/{id}") - public R getInfo(@NotNull(message = "主键不能为空") - @PathVariable Long id) { - return R.ok(appDeviceService.getInfo(id)); - } - - /** - * 人员信息登记 - */ - @PostMapping(value = "/registerPersonInfo") - public R registerPersonInfo(@Validated(AddGroup.class) @RequestBody AppPersonnelInfoBo bo) { - return toAjax(appDeviceService.registerPersonInfo(bo)); - } - - /** - * 发送信息 - */ - @PostMapping(value = "/sendMessage") - public R sendMessage(@RequestBody AppDeviceSendMsgBo bo) { - return toAjax(appDeviceService.sendMessage(bo)); - } - - /** - * 发送报警信息 - */ - @PostMapping(value = "/sendAlarmMessage") - public R sendAlarmMessage(@RequestBody AppDeviceSendMsgBo bo) { - return toAjax(appDeviceService.sendAlarmMessage(bo)); - } - - /** - * 上传设备logo图片 - */ - @PostMapping("/uploadLogo") - public R upload(@Validated @ModelAttribute AppDeviceLogoUploadDto bo) { - - MultipartFile file = bo.getFile(); - if(file.getSize()>1024*1024*2){ - return R.warn("图片不能大于2M"); - } - appDeviceService.uploadDeviceLogo(bo); - - return R.ok(); - } - - /** - * 灯光模式 - * 0(关灯),1(强光模式),2(弱光模式), 3(爆闪模式), 4(泛光模式) - */ - @PostMapping("/lightModeSettings") - public R lightModeSettings(@RequestBody DeviceInstructDto params) { - // params 转 JSONObject - appDeviceService.lightModeSettings(params); - return R.ok(); - } - - /** - * 灯光亮度设置 - * - */ - @PostMapping("/lightBrightnessSettings") - public R lightBrightnessSettings(@RequestBody DeviceInstructDto params) { - appDeviceService.lightBrightnessSettings(params); - return R.ok(); - } - - /** - * 激光模式设置 - * - */ - @PostMapping("/laserModeSettings") - public R laserModeSettings(@RequestBody DeviceInstructDto params) { - appDeviceService.laserModeSettings(params); - return R.ok(); - } - - /** - * 地图逆解析 - * - */ - @PostMapping("/mapReverseGeocoding") - public R mapReverseGeocoding(@RequestBody DeviceInstructDto params) { - String mapJson = appDeviceService.mapReverseGeocoding(params); - return R.ok(mapJson); - } } diff --git a/fys-admin/src/main/java/com/fuyuanshen/app/controller/device/AppDeviceBJQController.java b/fys-admin/src/main/java/com/fuyuanshen/app/controller/device/AppDeviceBJQController.java new file mode 100644 index 0000000..2f7caf8 --- /dev/null +++ b/fys-admin/src/main/java/com/fuyuanshen/app/controller/device/AppDeviceBJQController.java @@ -0,0 +1,119 @@ +package com.fuyuanshen.app.controller.device; + +import com.fuyuanshen.app.domain.bo.AppPersonnelInfoBo; +import com.fuyuanshen.app.domain.dto.AppDeviceLogoUploadDto; +import com.fuyuanshen.app.domain.dto.DeviceInstructDto; +import com.fuyuanshen.app.domain.vo.AppDeviceDetailVo; +import com.fuyuanshen.app.service.device.AppDeviceBJQBizService; +import com.fuyuanshen.common.core.domain.R; +import com.fuyuanshen.common.core.validate.AddGroup; +import com.fuyuanshen.common.web.core.BaseController; +import com.fuyuanshen.equipment.domain.dto.AppDeviceSendMsgBo; +import jakarta.validation.constraints.NotNull; +import lombok.RequiredArgsConstructor; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; + +/** + * BJQ6170设备控制类 + */ +@Validated +@RequiredArgsConstructor +@RestController +@RequestMapping("/app/bjq/device") +public class AppDeviceBJQController extends BaseController { + + private final AppDeviceBJQBizService appDeviceService; + + /** + * 获取设备详细信息 + * + * @param id 主键 + */ + @GetMapping("/{id}") + public R getInfo(@NotNull(message = "主键不能为空") + @PathVariable Long id) { + return R.ok(appDeviceService.getInfo(id)); + } + + /** + * 人员信息登记 + */ + @PostMapping(value = "/registerPersonInfo") + public R registerPersonInfo(@Validated(AddGroup.class) @RequestBody AppPersonnelInfoBo bo) { + return toAjax(appDeviceService.registerPersonInfo(bo)); + } + + /** + * 发送信息 + */ + @PostMapping(value = "/sendMessage") + public R sendMessage(@RequestBody AppDeviceSendMsgBo bo) { + return toAjax(appDeviceService.sendMessage(bo)); + } + + /** + * 发送报警信息 + */ + @PostMapping(value = "/sendAlarmMessage") + public R sendAlarmMessage(@RequestBody AppDeviceSendMsgBo bo) { + return toAjax(appDeviceService.sendAlarmMessage(bo)); + } + + /** + * 上传设备logo图片 + */ + @PostMapping("/uploadLogo") + public R upload(@Validated @ModelAttribute AppDeviceLogoUploadDto bo) { + + MultipartFile file = bo.getFile(); + if(file.getSize()>1024*1024*2){ + return R.warn("图片不能大于2M"); + } + appDeviceService.uploadDeviceLogo(bo); + + return R.ok(); + } + + /** + * 灯光模式 + * 0(关灯),1(强光模式),2(弱光模式), 3(爆闪模式), 4(泛光模式) + */ + @PostMapping("/lightModeSettings") + public R lightModeSettings(@RequestBody DeviceInstructDto params) { + // params 转 JSONObject + appDeviceService.lightModeSettings(params); + return R.ok(); + } + + /** + * 灯光亮度设置 + * + */ + @PostMapping("/lightBrightnessSettings") + public R lightBrightnessSettings(@RequestBody DeviceInstructDto params) { + appDeviceService.lightBrightnessSettings(params); + return R.ok(); + } + + /** + * 激光模式设置 + * + */ + @PostMapping("/laserModeSettings") + public R laserModeSettings(@RequestBody DeviceInstructDto params) { + appDeviceService.laserModeSettings(params); + return R.ok(); + } + + /** + * 地图逆解析 + * + */ + @PostMapping("/mapReverseGeocoding") + public R mapReverseGeocoding(@RequestBody DeviceInstructDto params) { + String mapJson = appDeviceService.mapReverseGeocoding(params); + return R.ok(mapJson); + } +} diff --git a/fys-admin/src/main/java/com/fuyuanshen/app/controller/device/AppDeviceHBYController.java b/fys-admin/src/main/java/com/fuyuanshen/app/controller/device/AppDeviceHBYController.java new file mode 100644 index 0000000..93a2204 --- /dev/null +++ b/fys-admin/src/main/java/com/fuyuanshen/app/controller/device/AppDeviceHBYController.java @@ -0,0 +1,112 @@ +package com.fuyuanshen.app.controller.device; + +import com.fuyuanshen.app.domain.bo.AppPersonnelInfoBo; +import com.fuyuanshen.app.domain.dto.AppDeviceLogoUploadDto; +import com.fuyuanshen.app.domain.dto.DeviceInstructDto; +import com.fuyuanshen.app.domain.vo.AppDeviceDetailVo; +import com.fuyuanshen.app.service.AppDeviceBizService; +import com.fuyuanshen.common.core.domain.R; +import com.fuyuanshen.common.core.validate.AddGroup; +import com.fuyuanshen.common.web.core.BaseController; +import com.fuyuanshen.equipment.domain.dto.AppDeviceSendMsgBo; +import jakarta.validation.constraints.NotNull; +import lombok.RequiredArgsConstructor; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; + +/** + * HBY210设备控制类 + */ +@Validated +@RequiredArgsConstructor +@RestController +@RequestMapping("/app/hby/device") +public class AppDeviceHBYController extends BaseController { + + private final AppDeviceBizService appDeviceService; + + + /** + * 获取设备详细信息 + * + * @param id 主键 + */ + @GetMapping("/{id}") + public R getInfo(@NotNull(message = "主键不能为空") + @PathVariable Long id) { + return R.ok(appDeviceService.getInfo(id)); + } + + /** + * 人员信息登记 + */ + @PostMapping(value = "/registerPersonInfo") + public R registerPersonInfo(@Validated(AddGroup.class) @RequestBody AppPersonnelInfoBo bo) { + return toAjax(appDeviceService.registerPersonInfo(bo)); + } + + /** + * 发送信息 + */ + @PostMapping(value = "/sendMessage") + public R sendMessage(@RequestBody AppDeviceSendMsgBo bo) { + return toAjax(appDeviceService.sendMessage(bo)); + } + + /** + * 上传设备logo图片 + */ + @PostMapping("/uploadLogo") + public R upload(@Validated @ModelAttribute AppDeviceLogoUploadDto bo) { + + MultipartFile file = bo.getFile(); + if(file.getSize()>1024*1024*2){ + return R.warn("图片不能大于2M"); + } + appDeviceService.uploadDeviceLogo(bo); + + return R.ok(); + } + + /** + * 灯光模式 + * 0(关灯),1(强光模式),2(弱光模式), 3(爆闪模式), 4(泛光模式) + */ + @PostMapping("/lightModeSettings") + public R lightModeSettings(@RequestBody DeviceInstructDto params) { + // params 转 JSONObject + appDeviceService.lightModeSettings(params); + return R.ok(); + } + + /** + * 灯光亮度设置 + * + */ + @PostMapping("/lightBrightnessSettings") + public R lightBrightnessSettings(@RequestBody DeviceInstructDto params) { + appDeviceService.lightBrightnessSettings(params); + return R.ok(); + } + + /** + * 激光模式设置 + * + */ + @PostMapping("/laserModeSettings") + public R laserModeSettings(@RequestBody DeviceInstructDto params) { + appDeviceService.laserModeSettings(params); + return R.ok(); + } + + /** + * 地图逆解析 + * + */ + @PostMapping("/mapReverseGeocoding") + public R mapReverseGeocoding(@RequestBody DeviceInstructDto params) { + String mapJson = appDeviceService.mapReverseGeocoding(params); + return R.ok(mapJson); + } +} diff --git a/fys-admin/src/main/java/com/fuyuanshen/app/service/AppDeviceBizService.java b/fys-admin/src/main/java/com/fuyuanshen/app/service/AppDeviceBizService.java index 98142e9..80e74f1 100644 --- a/fys-admin/src/main/java/com/fuyuanshen/app/service/AppDeviceBizService.java +++ b/fys-admin/src/main/java/com/fuyuanshen/app/service/AppDeviceBizService.java @@ -54,6 +54,7 @@ import static com.fuyuanshen.common.core.constant.GlobalConstants.GLOBAL_REDIS_K 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.global.mqtt.constants.DeviceRedisKeyConstants.*; @Slf4j @@ -101,14 +102,14 @@ public class AppDeviceBizService { // String backgroundImagePath = "D:\\background.png"; // 替换为实际背景图片路径 byte[] largeData = ImageWithTextGenerate.generate160x80ImageWithText2(bo.getSendMsg(), inputStream, 25600); int[] ints = convertHexToDecimal(largeData); - RedisUtils.setCacheObject(GLOBAL_REDIS_KEY+"app_send_message_data:" + device.getDeviceImei(), Arrays.toString(ints), Duration.ofSeconds(30 * 60L)); + RedisUtils.setCacheObject(GLOBAL_REDIS_KEY+ DEVICE_KEY_PREFIX + device.getDeviceImei() + DEVICE_SEND_MESSAGE_KEY_PREFIX , Arrays.toString(ints), Duration.ofSeconds(30 * 60L)); - String data = RedisUtils.getCacheObject(GLOBAL_REDIS_KEY+"app_send_message_data:" + device.getDeviceImei()); + String data = RedisUtils.getCacheObject(GLOBAL_REDIS_KEY+ DEVICE_KEY_PREFIX + device.getDeviceImei() + DEVICE_SEND_MESSAGE_KEY_PREFIX); byte[] arr = ImageToCArrayConverter.convertStringToByteArray(data); byte[] specificChunk = ImageToCArrayConverter.getChunk(arr, 0, 512); - System.out.println("第0块数据大小: " + specificChunk.length + " 字节"); - System.out.println("第0块数据: " + Arrays.toString(specificChunk)); + log.info("发送信息第0块数据大小: {} 字节",specificChunk.length); +// log.info("第0块数据: {}", Arrays.toString(specificChunk)); ArrayList intData = new ArrayList<>(); intData.add(6); @@ -121,7 +122,7 @@ public class AppDeviceBizService { Map map = new HashMap<>(); map.put("instruct", intData); mqttGateway.sendMsgToMqtt(MqttConstants.GLOBAL_PUB_KEY+device.getDeviceImei(), 1 , JSON.toJSONString(map)); - log.info("发送点阵数据到设备消息=>topic:{},payload:{}", MqttConstants.GLOBAL_PUB_KEY+device.getDeviceImei(),JSON.toJSONString(map)); + log.info("发送信息点阵数据到设备消息=>topic:{},payload:{}", MqttConstants.GLOBAL_PUB_KEY+device.getDeviceImei(),JSON.toJSONString(map)); UpdateWrapper updateWrapper = new UpdateWrapper<>(); updateWrapper.eq("id", deviceId) @@ -129,7 +130,7 @@ public class AppDeviceBizService { .set("send_msg", bo.getSendMsg()); deviceMapper.update(updateWrapper); } catch (Exception e) { - log.info("设备发送信息失败:{}" ,deviceId); + log.info("发送信息设备发送信息失败:{}" ,deviceId); } } @@ -149,14 +150,14 @@ public class AppDeviceBizService { if(item.getCommunicationMode()!=null && item.getCommunicationMode() == 0){ //设备在线状态 - String onlineStatus = RedisUtils.getCacheObject(GLOBAL_REDIS_KEY+DeviceRedisKeyConstants.DEVICE_ONLINE_STATUS_KEY_PREFIX + item.getDeviceImei()); + String onlineStatus = RedisUtils.getCacheObject(GLOBAL_REDIS_KEY+ DEVICE_KEY_PREFIX+ item.getDeviceImei() + DeviceRedisKeyConstants.DEVICE_ONLINE_STATUS_KEY_PREFIX); if(StringUtils.isNotBlank(onlineStatus)){ item.setOnlineStatus(1); }else{ item.setOnlineStatus(0); } - String deviceStatus = RedisUtils.getCacheObject(GLOBAL_REDIS_KEY+DeviceRedisKeyConstants.DEVICE_STATUS_KEY_PREFIX + item.getDeviceImei()); + String deviceStatus = RedisUtils.getCacheObject(GLOBAL_REDIS_KEY + DEVICE_KEY_PREFIX+ item.getDeviceImei() + DEVICE_STATUS_KEY_PREFIX); // 获取电量 if(StringUtils.isNotBlank(deviceStatus)){ JSONObject jsonObject = JSONObject.parseObject(deviceStatus); @@ -165,12 +166,17 @@ public class AppDeviceBizService { item.setBattery("0"); } - String location = RedisUtils.getCacheObject(GLOBAL_REDIS_KEY+DeviceRedisKeyConstants.DEVICE_LOCATION_KEY_PREFIX + item.getDeviceImei()); + String location = RedisUtils.getCacheObject(GLOBAL_REDIS_KEY +DEVICE_KEY_PREFIX+ item.getDeviceImei()+ DEVICE_LOCATION_KEY_PREFIX); if(StringUtils.isNotBlank(location)){ JSONObject jsonObject = JSONObject.parseObject(location); item.setLatitude(jsonObject.getString("latitude")); item.setLongitude(jsonObject.getString("longitude")); } + + String alarmStatus = RedisUtils.getCacheObject(GLOBAL_REDIS_KEY +DEVICE_KEY_PREFIX+ item.getDeviceImei()+ DEVICE_ALARM_KEY_PREFIX); + if(StringUtils.isNotBlank(alarmStatus)){ + item.setAlarmStatus(alarmStatus); + } } }); } @@ -333,13 +339,13 @@ public class AppDeviceBizService { vo.setPersonnelInfo(personnelInfoVo); } //设备在线状态 - String onlineStatus = RedisUtils.getCacheObject(GLOBAL_REDIS_KEY+DeviceRedisKeyConstants.DEVICE_ONLINE_STATUS_KEY_PREFIX + device.getDeviceImei()); + String onlineStatus = RedisUtils.getCacheObject(GLOBAL_REDIS_KEY+ DEVICE_KEY_PREFIX + device.getDeviceImei() + DeviceRedisKeyConstants.DEVICE_ONLINE_STATUS_KEY_PREFIX); if(StringUtils.isNotBlank(onlineStatus)){ vo.setOnlineStatus(1); }else{ vo.setOnlineStatus(0); } - String deviceStatus = RedisUtils.getCacheObject(GLOBAL_REDIS_KEY+DeviceRedisKeyConstants.DEVICE_STATUS_KEY_PREFIX + device.getDeviceImei()); + String deviceStatus = RedisUtils.getCacheObject(GLOBAL_REDIS_KEY+ DEVICE_KEY_PREFIX + device.getDeviceImei() + DeviceRedisKeyConstants.DEVICE_ONLINE_STATUS_KEY_PREFIX); // 获取电量 if(StringUtils.isNotBlank(deviceStatus)){ JSONObject jsonObject = JSONObject.parseObject(deviceStatus); @@ -353,7 +359,7 @@ public class AppDeviceBizService { } // 获取经度纬度 - String locationKey = GlobalConstants.GLOBAL_REDIS_KEY+DeviceRedisKeyConstants.DEVICE_LOCATION_KEY_PREFIX + device.getDeviceImei(); + String locationKey = GlobalConstants.GLOBAL_REDIS_KEY+ DEVICE_KEY_PREFIX + device.getDeviceImei() + DEVICE_LOCATION_KEY_PREFIX; String locationInfo = RedisUtils.getCacheObject(locationKey); if(StringUtils.isNotBlank(locationInfo)){ JSONObject jsonObject = JSONObject.parseObject(locationInfo); @@ -430,19 +436,19 @@ public class AppDeviceBizService { MultipartFile file = bo.getFile(); byte[] largeData = ImageToCArrayConverter.convertImageToCArray(file.getInputStream(), 160, 80, 25600); - System.out.println("长度:" + largeData.length); + log.info("长度:" + largeData.length); - System.out.println("原始数据大小: " + largeData.length + " 字节"); + log.info("原始数据大小: {} 字节", largeData.length); int[] ints = convertHexToDecimal(largeData); - RedisUtils.setCacheObject(GLOBAL_REDIS_KEY+"app_logo_data:" + device.getDeviceImei(), Arrays.toString(ints), Duration.ofSeconds(30 * 60L)); + RedisUtils.setCacheObject(GLOBAL_REDIS_KEY+ DEVICE_KEY_PREFIX + device.getDeviceImei() + DEVICE_BOOT_LOGO_KEY_PREFIX, Arrays.toString(ints), Duration.ofSeconds(30 * 60L)); - String data = RedisUtils.getCacheObject(GLOBAL_REDIS_KEY+"app_logo_data:" + device.getDeviceImei()); + String data = RedisUtils.getCacheObject(GLOBAL_REDIS_KEY+ DEVICE_KEY_PREFIX + device.getDeviceImei() + DEVICE_BOOT_LOGO_KEY_PREFIX); byte[] arr = ImageToCArrayConverter.convertStringToByteArray(data); byte[] specificChunk = ImageToCArrayConverter.getChunk(arr, 0, 512); - System.out.println("第0块数据大小: " + specificChunk.length + " 字节"); - System.out.println("第0块数据: " + Arrays.toString(specificChunk)); + log.info("第0块数据大小: {} 字节", specificChunk.length); +// log.info("第0块数据: {}", Arrays.toString(specificChunk)); ArrayList intData = new ArrayList<>(); intData.add(3); diff --git a/fys-admin/src/main/java/com/fuyuanshen/app/service/device/AppDeviceBJQBizService.java b/fys-admin/src/main/java/com/fuyuanshen/app/service/device/AppDeviceBJQBizService.java new file mode 100644 index 0000000..8dd1a96 --- /dev/null +++ b/fys-admin/src/main/java/com/fuyuanshen/app/service/device/AppDeviceBJQBizService.java @@ -0,0 +1,388 @@ +package com.fuyuanshen.app.service.device; + +import com.alibaba.fastjson2.JSON; +import com.alibaba.fastjson2.JSONObject; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper; +import com.fuyuanshen.app.domain.AppPersonnelInfo; +import com.fuyuanshen.app.domain.bo.AppPersonnelInfoBo; +import com.fuyuanshen.app.domain.dto.AppDeviceLogoUploadDto; +import com.fuyuanshen.app.domain.dto.DeviceInstructDto; +import com.fuyuanshen.app.domain.vo.AppDeviceDetailVo; +import com.fuyuanshen.app.domain.vo.AppPersonnelInfoVo; +import com.fuyuanshen.app.mapper.AppPersonnelInfoMapper; +import com.fuyuanshen.common.core.constant.GlobalConstants; +import com.fuyuanshen.common.core.exception.ServiceException; +import com.fuyuanshen.common.core.utils.*; +import com.fuyuanshen.common.redis.utils.RedisUtils; +import com.fuyuanshen.common.satoken.utils.AppLoginHelper; +import com.fuyuanshen.equipment.domain.Device; +import com.fuyuanshen.equipment.domain.DeviceType; +import com.fuyuanshen.equipment.domain.dto.AppDeviceSendMsgBo; +import com.fuyuanshen.equipment.mapper.DeviceMapper; +import com.fuyuanshen.equipment.mapper.DeviceTypeMapper; +import com.fuyuanshen.global.mqtt.config.MqttGateway; +import com.fuyuanshen.global.mqtt.constants.DeviceRedisKeyConstants; +import com.fuyuanshen.global.mqtt.constants.MqttConstants; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.core.io.ClassPathResource; +import org.springframework.stereotype.Service; +import org.springframework.web.multipart.MultipartFile; + +import java.io.InputStream; +import java.time.Duration; +import java.util.*; + +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.global.mqtt.constants.DeviceRedisKeyConstants.DEVICE_BOOT_LOGO_KEY_PREFIX; +import static com.fuyuanshen.global.mqtt.constants.DeviceRedisKeyConstants.DEVICE_KEY_PREFIX; + + +@Slf4j +@Service +@RequiredArgsConstructor +public class AppDeviceBJQBizService { + + private final DeviceMapper deviceMapper; + private final AppPersonnelInfoMapper appPersonnelInfoMapper; + private final DeviceTypeMapper deviceTypeMapper; + private final MqttGateway mqttGateway; + + public int sendMessage(AppDeviceSendMsgBo bo) { + List deviceIds = bo.getDeviceIds(); + if (deviceIds == null || deviceIds.isEmpty()) { + throw new ServiceException("请选择设备"); + } + for (Long deviceId : deviceIds) { + Device device = deviceMapper.selectById(deviceId); + if (device == null) { + throw new ServiceException("设备不存在" + deviceId); + } + + try { + ClassPathResource resource = new ClassPathResource("image/background.png"); + InputStream inputStream = resource.getInputStream(); + +// String backgroundImagePath = "D:\\background.png"; // 替换为实际背景图片路径 + byte[] largeData = ImageWithTextGenerate.generate160x80ImageWithText2(bo.getSendMsg(), inputStream, 25600); + int[] ints = convertHexToDecimal(largeData); + RedisUtils.setCacheObject(GLOBAL_REDIS_KEY+ DEVICE_KEY_PREFIX + device.getDeviceImei() + ":app_send_message_data" , Arrays.toString(ints), Duration.ofSeconds(30 * 60L)); + + String data = RedisUtils.getCacheObject(GLOBAL_REDIS_KEY+ DEVICE_KEY_PREFIX + device.getDeviceImei() + ":app_send_message_data"); + + byte[] arr = ImageToCArrayConverter.convertStringToByteArray(data); + byte[] specificChunk = ImageToCArrayConverter.getChunk(arr, 0, 512); + log.info("发送信息第0块数据大小: {} 字节",specificChunk.length); +// log.info("第0块数据: {}", Arrays.toString(specificChunk)); + + ArrayList intData = new ArrayList<>(); + intData.add(6); + intData.add(1); + ImageToCArrayConverter.buildArr(convertHexToDecimal(specificChunk),intData); + intData.add(0); + intData.add(0); + intData.add(0); + intData.add(0); + Map map = new HashMap<>(); + map.put("instruct", intData); + mqttGateway.sendMsgToMqtt(MqttConstants.GLOBAL_PUB_KEY+device.getDeviceImei(), 1 , JSON.toJSONString(map)); + log.info("发送信息点阵数据到设备消息=>topic:{},payload:{}", MqttConstants.GLOBAL_PUB_KEY+device.getDeviceImei(),JSON.toJSONString(map)); + + UpdateWrapper updateWrapper = new UpdateWrapper<>(); + updateWrapper.eq("id", deviceId) + .eq("binding_user_id", AppLoginHelper.getUserId()) + .set("send_msg", bo.getSendMsg()); + deviceMapper.update(updateWrapper); + } catch (Exception e) { + log.info("发送信息设备发送信息失败:{}" ,deviceId); + } + + } + return 1; + } + + public AppDeviceDetailVo getInfo(Long id) { + Device device = deviceMapper.selectById(id); + if (device == null) { + throw new RuntimeException("请先将设备入库!!!"); + } + AppDeviceDetailVo vo = new AppDeviceDetailVo(); + vo.setDeviceId(device.getId()); + vo.setDeviceName(device.getDeviceName()); + vo.setDevicePic(device.getDevicePic()); + vo.setDeviceImei(device.getDeviceImei()); + vo.setDeviceMac(device.getDeviceMac()); + vo.setDeviceStatus(device.getDeviceStatus()); + DeviceType deviceType = deviceTypeMapper.selectById(device.getDeviceType()); + if (deviceType != null) { + vo.setCommunicationMode(Integer.valueOf(deviceType.getCommunicationMode())); + vo.setTypeName(deviceType.getTypeName()); + } + vo.setBluetoothName(device.getBluetoothName()); + + vo.setSendMsg(device.getSendMsg()); + + QueryWrapper qw = new QueryWrapper() + .eq("device_id", device.getId()); + AppPersonnelInfo appPersonnelInfo = appPersonnelInfoMapper.selectOne(qw); + if (appPersonnelInfo != null) { + AppPersonnelInfoVo personnelInfoVo = MapstructUtils.convert(appPersonnelInfo, AppPersonnelInfoVo.class); + vo.setPersonnelInfo(personnelInfoVo); + } + //设备在线状态 + String onlineStatus = RedisUtils.getCacheObject(GLOBAL_REDIS_KEY+DeviceRedisKeyConstants.DEVICE_ONLINE_STATUS_KEY_PREFIX + device.getDeviceImei()); + if(StringUtils.isNotBlank(onlineStatus)){ + vo.setOnlineStatus(1); + }else{ + vo.setOnlineStatus(0); + } + String deviceStatus = RedisUtils.getCacheObject(GLOBAL_REDIS_KEY+DeviceRedisKeyConstants.DEVICE_STATUS_KEY_PREFIX + device.getDeviceImei()); + // 获取电量 + if(StringUtils.isNotBlank(deviceStatus)){ + JSONObject jsonObject = JSONObject.parseObject(deviceStatus); + vo.setMainLightMode(jsonObject.getString("mainLightMode")); + vo.setLaserLightMode(jsonObject.getString("laserLightMode")); + vo.setBatteryPercentage(jsonObject.getString("batteryPercentage")); + vo.setChargeState(jsonObject.getString("chargeState")); + vo.setBatteryRemainingTime(jsonObject.getString("batteryRemainingTime")); + }else{ + vo.setBatteryPercentage("0"); + } + + // 获取经度纬度 + String locationKey = GlobalConstants.GLOBAL_REDIS_KEY+DeviceRedisKeyConstants.DEVICE_LOCATION_KEY_PREFIX + device.getDeviceImei(); + String locationInfo = RedisUtils.getCacheObject(locationKey); + if(StringUtils.isNotBlank(locationInfo)){ + JSONObject jsonObject = JSONObject.parseObject(locationInfo); + vo.setLongitude(jsonObject.get("longitude").toString()); + vo.setLatitude(jsonObject.get("latitude").toString()); + vo.setAddress((String)jsonObject.get("address")); + } + + return vo; + } + + + public boolean registerPersonInfo(AppPersonnelInfoBo bo) { + Long deviceId = bo.getDeviceId(); + Device deviceObj = deviceMapper.selectById(deviceId); + if (deviceObj == null) { + throw new RuntimeException("请先将设备入库!!!"); + } + QueryWrapper qw = new QueryWrapper() + .eq("device_id", deviceId); + List appPersonnelInfoVos = appPersonnelInfoMapper.selectVoList(qw); +// unitName,position,name,id + byte[] unitName = generateFixedBitmapData(bo.getUnitName(), 120); + byte[] position = generateFixedBitmapData(bo.getPosition(), 120); + byte[] name = generateFixedBitmapData(bo.getName(), 120); + byte[] id = generateFixedBitmapData(bo.getCode(), 120); + ArrayList intData = new ArrayList<>(); + intData.add(2); + buildArr(convertHexToDecimal(unitName), intData); + buildArr(convertHexToDecimal(position), intData); + buildArr(convertHexToDecimal(name), intData); + buildArr(convertHexToDecimal(id), intData); + intData.add(0); + intData.add(0); + intData.add(0); + intData.add(0); + Map map = new HashMap<>(); + map.put("instruct", intData); + mqttGateway.sendMsgToMqtt(MqttConstants.GLOBAL_PUB_KEY + deviceObj.getDeviceImei(), 1, JSON.toJSONString(map)); + log.info("发送点阵数据到设备消息=>topic:{},payload:{}", MqttConstants.GLOBAL_PUB_KEY + deviceObj.getDeviceImei(), bo); + + if (ObjectUtils.length(appPersonnelInfoVos) == 0) { + AppPersonnelInfo appPersonnelInfo = MapstructUtils.convert(bo, AppPersonnelInfo.class); + return appPersonnelInfoMapper.insertOrUpdate(appPersonnelInfo); + } else { + UpdateWrapper uw = new UpdateWrapper<>(); + uw.eq("device_id", deviceId) + .set("name", bo.getName()) + .set("position", bo.getPosition()) + .set("unit_name", bo.getUnitName()) + .set("code", bo.getCode()); + return appPersonnelInfoMapper.update(null, uw) > 0; + } + + + } + + public void uploadDeviceLogo(AppDeviceLogoUploadDto bo) { + try { + Device device = deviceMapper.selectById(bo.getDeviceId()); + if (device == null) { + throw new ServiceException("设备不存在"); + } + MultipartFile file = bo.getFile(); + + byte[] largeData = ImageToCArrayConverter.convertImageToCArray(file.getInputStream(), 160, 80, 25600); + log.info("长度:" + largeData.length); + + log.info("原始数据大小: {} 字节", largeData.length); + + int[] ints = convertHexToDecimal(largeData); + RedisUtils.setCacheObject(GLOBAL_REDIS_KEY+ DEVICE_KEY_PREFIX + device.getDeviceImei() +DEVICE_BOOT_LOGO_KEY_PREFIX, Arrays.toString(ints), Duration.ofSeconds(30 * 60L)); + + String data = RedisUtils.getCacheObject(GLOBAL_REDIS_KEY+ DEVICE_KEY_PREFIX + device.getDeviceImei() + DEVICE_BOOT_LOGO_KEY_PREFIX); + + byte[] arr = ImageToCArrayConverter.convertStringToByteArray(data); + byte[] specificChunk = ImageToCArrayConverter.getChunk(arr, 0, 512); + log.info("第0块数据大小: {} 字节", specificChunk.length); +// log.info("第0块数据: {}", Arrays.toString(specificChunk)); + + ArrayList intData = new ArrayList<>(); + intData.add(3); + intData.add(1); + ImageToCArrayConverter.buildArr(convertHexToDecimal(specificChunk),intData); + intData.add(0); + intData.add(0); + intData.add(0); + intData.add(0); + Map map = new HashMap<>(); + map.put("instruct", intData); + mqttGateway.sendMsgToMqtt(MqttConstants.GLOBAL_PUB_KEY+device.getDeviceImei(), 1 , JSON.toJSONString(map)); + log.info("发送点阵数据到设备消息=>topic:{},payload:{}", MqttConstants.GLOBAL_PUB_KEY+device.getDeviceImei(),JSON.toJSONString(map)); + } catch (Exception e){ + e.printStackTrace(); + } + } + + /** + * 灯光模式 + * 0(关灯),1(强光模式),2(弱光模式), 3(爆闪模式), 4(泛光模式) + */ + public void lightModeSettings(DeviceInstructDto params) { + try { + Long deviceId = params.getDeviceId(); + Device device = deviceMapper.selectById(deviceId); + if(device == null){ + throw new ServiceException("设备不存在"); + } + Integer instructValue = Integer.parseInt(params.getInstructValue()); + ArrayList intData = new ArrayList<>(); + intData.add(1); + intData.add(instructValue); + intData.add(0); + intData.add(0); + intData.add(0); + Map map = new HashMap<>(); + map.put("instruct", intData); + mqttGateway.sendMsgToMqtt(MqttConstants.GLOBAL_PUB_KEY+device.getDeviceImei(), 1 , JSON.toJSONString(map)); + log.info("发送点阵数据到设备消息=>topic:{},payload:{}", MqttConstants.GLOBAL_PUB_KEY+device.getDeviceImei(),JSON.toJSONString(map)); + } catch (Exception e){ + e.printStackTrace(); + } + } + + //灯光亮度设置 + public void lightBrightnessSettings(DeviceInstructDto params) { + try { + Long deviceId = params.getDeviceId(); + Device device = deviceMapper.selectById(deviceId); + if(device == null){ + throw new ServiceException("设备不存在"); + } + String instructValue = params.getInstructValue(); + ArrayList intData = new ArrayList<>(); + intData.add(5); + String[] values = instructValue.split("\\."); + String value1 = values[0]; + String value2 = values[1]; + if(StringUtils.isNoneBlank(value1)){ + intData.add(Integer.parseInt(value1)); + } + if(StringUtils.isNoneBlank(value2)){ + intData.add(Integer.parseInt(value2)); + } + intData.add(0); + intData.add(0); + intData.add(0); + Map map = new HashMap<>(); + map.put("instruct", intData); + mqttGateway.sendMsgToMqtt(MqttConstants.GLOBAL_PUB_KEY+device.getDeviceImei(), 1 , JSON.toJSONString(map)); + log.info("发送点阵数据到设备消息=>topic:{},payload:{}", MqttConstants.GLOBAL_PUB_KEY+device.getDeviceImei(),JSON.toJSONString(map)); + } catch (Exception e){ + e.printStackTrace(); + } + } + + //激光模式设置 + public void laserModeSettings(DeviceInstructDto params) { + try { + Long deviceId = params.getDeviceId(); + Device device = deviceMapper.selectById(deviceId); + if(device == null){ + throw new ServiceException("设备不存在"); + } + Integer instructValue = Integer.parseInt(params.getInstructValue()); + ArrayList intData = new ArrayList<>(); + intData.add(4); + intData.add(instructValue); + intData.add(0); + intData.add(0); + intData.add(0); + Map map = new HashMap<>(); + map.put("instruct", intData); + mqttGateway.sendMsgToMqtt(MqttConstants.GLOBAL_PUB_KEY+device.getDeviceImei(), 1 , JSON.toJSONString(map)); + log.info("发送点阵数据到设备消息=>topic:{},payload:{}", MqttConstants.GLOBAL_PUB_KEY+device.getDeviceImei(),JSON.toJSONString(map)); + } catch (Exception e){ + e.printStackTrace(); + } + } + + public String mapReverseGeocoding(DeviceInstructDto params) { + QueryWrapper queryWrapper = new QueryWrapper<>(); + queryWrapper.eq("device_imei", params.getDeviceImei()); + List devices = deviceMapper.selectList(queryWrapper); + if(ObjectUtils.length( devices) ==0){ + throw new ServiceException("设备不存在"); + } + return RedisUtils.getCacheObject("device:location:" + devices.get(0).getDeviceImei()); + } + + public int sendAlarmMessage(AppDeviceSendMsgBo bo) { + try { + List deviceIds = bo.getDeviceIds(); + if (deviceIds == null || deviceIds.isEmpty()) { + throw new ServiceException("请选择设备"); + } + for (Long deviceId : deviceIds) { + Device device = deviceMapper.selectById(deviceId); + if (device == null) { + throw new ServiceException("设备不存在" + deviceId); + } + + try { + ArrayList intData = new ArrayList<>(); + intData.add(7); + intData.add(Integer.parseInt(bo.getInstructValue())); + intData.add(0); + intData.add(0); + intData.add(0); + intData.add(0); + Map map = new HashMap<>(); + map.put("instruct", intData); + mqttGateway.sendMsgToMqtt(MqttConstants.GLOBAL_PUB_KEY+device.getDeviceImei(), 1 , JSON.toJSONString(map)); + log.info("发送点阵数据到设备消息=>topic:{},payload:{}", MqttConstants.GLOBAL_PUB_KEY+device.getDeviceImei(),JSON.toJSONString(map)); + + UpdateWrapper updateWrapper = new UpdateWrapper<>(); + updateWrapper.eq("id", deviceId) + .eq("binding_user_id", AppLoginHelper.getUserId()) + .set("send_msg", bo.getSendMsg()); + deviceMapper.update(updateWrapper); + } catch (Exception e) { + log.info("设备发送信息失败:{}" ,deviceId); + } + + } + } catch (Exception e){ + e.printStackTrace(); + } + return 1; + } +} diff --git a/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/constants/DeviceRedisKeyConstants.java b/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/constants/DeviceRedisKeyConstants.java index d92ec38..080debc 100644 --- a/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/constants/DeviceRedisKeyConstants.java +++ b/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/constants/DeviceRedisKeyConstants.java @@ -1,12 +1,50 @@ package com.fuyuanshen.global.mqtt.constants; public class DeviceRedisKeyConstants { - // 将设备上报状态 - public static final String DEVICE_STATUS_KEY_PREFIX = "device:status:"; + public static final String DEVICE_KEY_PREFIX = "device:"; + // 设备上报状态 + public static final String DEVICE_STATUS_KEY_PREFIX = ":status"; // 在线状态 - public static final String DEVICE_ONLINE_STATUS_KEY_PREFIX = "device:onlineStatus:"; - // 将设备状态信息存储到Redis中 - public static final String DEVICE_LOCATION_KEY_PREFIX = "device:location:"; + public static final String DEVICE_ONLINE_STATUS_KEY_PREFIX = ":onlineStatus"; + // 设备状态信息存储到Redis中 + public static final String DEVICE_LOCATION_KEY_PREFIX = ":location"; // 存储到一个列表中,保留历史位置信息 - public static final String DEVICE_LOCATION_HISTORY_KEY_PREFIX = "device:location:history:"; + public static final String DEVICE_LOCATION_HISTORY_KEY_PREFIX = ":location:history"; + + // 存储设备活跃上报信息 + public static final String DEVICE_ACTIVE_REPORTING_KEY_PREFIX = ":activeReporting"; + + // 存储设备人员信息 + public static final String DEVICE_PERSONNEL_INFO_KEY_PREFIX = ":personnelInfo"; + + // 存储设备发送消息 + public static final String DEVICE_SEND_MESSAGE_KEY_PREFIX = ":sendMessage"; + + // 存储设备启动logo + public static final String DEVICE_BOOT_LOGO_KEY_PREFIX = ":bootLogo"; + + /** + * 灯模式 + */ + public static final String DEVICE_LIGHT_MODE_KEY_PREFIX = ":lightMode"; + + /** + * 亮度模式 + */ + public static final String DEVICE_LIGHT_BRIGHTNESS_KEY_PREFIX = ":lightBrightness"; + + /** + * 激光模式 + */ + public static final String DEVICE_LASER_MODE_KEY_PREFIX = ":laserMode"; + + /** + * 地图逆地理编码 + */ + public static final String DEVICE_MAP_REVERSE_GEOCODING_KEY_PREFIX = ":mapReverseGeocoding"; + + /** + * 告警 + */ + public static final String DEVICE_ALARM_KEY_PREFIX = ":alarm"; } diff --git a/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/receiver/ReceiverMessageHandler.java b/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/receiver/ReceiverMessageHandler.java index 3cd36af..618758f 100644 --- a/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/receiver/ReceiverMessageHandler.java +++ b/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/receiver/ReceiverMessageHandler.java @@ -20,6 +20,8 @@ import org.springframework.stereotype.Service; import java.time.Duration; import java.util.Objects; +import static com.fuyuanshen.global.mqtt.constants.DeviceRedisKeyConstants.DEVICE_KEY_PREFIX; + @Service @Slf4j public class ReceiverMessageHandler implements MessageHandler { @@ -46,7 +48,7 @@ public class ReceiverMessageHandler implements MessageHandler { String deviceImei = subStr[1]; if(StringUtils.isNotBlank(deviceImei)){ //在线状态 - String deviceOnlineStatusRedisKey = GlobalConstants.GLOBAL_REDIS_KEY+ DeviceRedisKeyConstants.DEVICE_ONLINE_STATUS_KEY_PREFIX + deviceImei; + String deviceOnlineStatusRedisKey = GlobalConstants.GLOBAL_REDIS_KEY+ DEVICE_KEY_PREFIX+ deviceImei + DeviceRedisKeyConstants.DEVICE_ONLINE_STATUS_KEY_PREFIX ; RedisUtils.setCacheObject(deviceOnlineStatusRedisKey, "1", Duration.ofSeconds(60*15)); } diff --git a/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/rule/ActiveReportingDeviceDataRule.java b/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/rule/bjq6170/BjqActiveReportingDeviceDataRule.java similarity index 91% rename from fys-admin/src/main/java/com/fuyuanshen/global/mqtt/rule/ActiveReportingDeviceDataRule.java rename to fys-admin/src/main/java/com/fuyuanshen/global/mqtt/rule/bjq6170/BjqActiveReportingDeviceDataRule.java index 104bd69..e6319a8 100644 --- a/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/rule/ActiveReportingDeviceDataRule.java +++ b/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/rule/bjq6170/BjqActiveReportingDeviceDataRule.java @@ -1,22 +1,22 @@ -package com.fuyuanshen.global.mqtt.rule; +package com.fuyuanshen.global.mqtt.rule.bjq6170; import com.fuyuanshen.common.core.constant.GlobalConstants; import com.fuyuanshen.common.json.utils.JsonUtils; import com.fuyuanshen.common.redis.utils.RedisUtils; import com.fuyuanshen.global.mqtt.base.MqttMessageRule; import com.fuyuanshen.global.mqtt.base.MqttRuleContext; -import com.fuyuanshen.global.mqtt.config.MqttGateway; import com.fuyuanshen.global.mqtt.constants.DeviceRedisKeyConstants; import com.fuyuanshen.global.mqtt.constants.LightingCommandTypeConstants; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; -import java.time.Duration; import java.util.LinkedHashMap; import java.util.Map; import java.util.concurrent.CompletableFuture; +import static com.fuyuanshen.global.mqtt.constants.DeviceRedisKeyConstants.DEVICE_STATUS_KEY_PREFIX; + /** * 主动上报设备数据命令处理 * "第1位为12表示设备主动上报设备硬件状态,第2为表示当时设备主灯档位,第3位表示当时激光灯档位,第4位电量百分比,第5位为充电状态(0没有充电,1正在充电,2为已充满) @@ -25,10 +25,7 @@ import java.util.concurrent.CompletableFuture; @Component @RequiredArgsConstructor @Slf4j -public class ActiveReportingDeviceDataRule implements MqttMessageRule { - - private final MqttGateway mqttGateway; - +public class BjqActiveReportingDeviceDataRule implements MqttMessageRule { @Override public String getCommandType() { @@ -80,10 +77,10 @@ public class ActiveReportingDeviceDataRule implements MqttMessageRule { deviceInfo.put("timestamp", System.currentTimeMillis()); // 将设备状态信息存储到Redis中 - String deviceRedisKey = GlobalConstants.GLOBAL_REDIS_KEY+DeviceRedisKeyConstants.DEVICE_STATUS_KEY_PREFIX + deviceImei; + String deviceRedisKey = GlobalConstants.GLOBAL_REDIS_KEY+DeviceRedisKeyConstants.DEVICE_KEY_PREFIX + deviceImei + DEVICE_STATUS_KEY_PREFIX; String deviceInfoJson = JsonUtils.toJsonString(deviceInfo); - // 存储到Redis,设置过期时间(例如24小时) + // 存储到Redis RedisUtils.setCacheObject(deviceRedisKey, deviceInfoJson); log.info("设备状态信息已异步发送到Redis: device={}, mainLightMode={}, laserLightMode={}, batteryPercentage={}", diff --git a/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/rule/bjq6170/BjqAlarmRule.java b/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/rule/bjq6170/BjqAlarmRule.java new file mode 100644 index 0000000..bff3a36 --- /dev/null +++ b/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/rule/bjq6170/BjqAlarmRule.java @@ -0,0 +1,69 @@ +package com.fuyuanshen.global.mqtt.rule.bjq6170; + +import com.fuyuanshen.common.core.constant.GlobalConstants; +import com.fuyuanshen.common.core.utils.StringUtils; +import com.fuyuanshen.common.redis.utils.RedisUtils; +import com.fuyuanshen.global.mqtt.base.MqttMessageRule; +import com.fuyuanshen.global.mqtt.base.MqttRuleContext; +import com.fuyuanshen.global.mqtt.constants.DeviceRedisKeyConstants; +import com.fuyuanshen.global.mqtt.constants.LightingCommandTypeConstants; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; + +import java.util.concurrent.CompletableFuture; + +import static com.fuyuanshen.global.mqtt.constants.DeviceRedisKeyConstants.*; + +/** + * 灯光模式订阅设备回传消息 + */ +@Component +@RequiredArgsConstructor +@Slf4j +public class BjqAlarmRule implements MqttMessageRule { + + @Override + public String getCommandType() { + return LightingCommandTypeConstants.LIGHT_MODE; + } + + @Override + public void execute(MqttRuleContext context) { + try { + Object[] convertArr = context.getConvertArr(); + + String mainLightMode = convertArr[1].toString(); + if(StringUtils.isNotBlank(mainLightMode)){ + // 异步发送设备状态和位置信息到Redis + asyncSendDeviceDataToRedisWithFuture(context.getDeviceImei(),mainLightMode); + } + + } catch (Exception e) { + log.error("处理灯光模式命令时出错", e); + } + } + + /** + * 异步发送设备状态信息和位置信息到Redis(使用CompletableFuture) + * + * @param deviceImei 设备IMEI + */ + public void asyncSendDeviceDataToRedisWithFuture(String deviceImei,Object convertValue) { + CompletableFuture.runAsync(() -> { + try { + // 将设备状态信息存储到Redis中 + String deviceRedisKey = GlobalConstants.GLOBAL_REDIS_KEY+DeviceRedisKeyConstants.DEVICE_KEY_PREFIX + deviceImei + DEVICE_ALARM_KEY_PREFIX; + + // 存储到Redis + RedisUtils.setCacheObject(deviceRedisKey, convertValue.toString()); + + } catch (Exception e) { + log.error("异步发送设备信息到Redis时出错: device={}, error={}", deviceImei, e.getMessage(), e); + } + }); + } + + + +} diff --git a/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/rule/DeviceBootLogoRule.java b/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/rule/bjq6170/BjqBootLogoRule.java similarity index 81% rename from fys-admin/src/main/java/com/fuyuanshen/global/mqtt/rule/DeviceBootLogoRule.java rename to fys-admin/src/main/java/com/fuyuanshen/global/mqtt/rule/bjq6170/BjqBootLogoRule.java index 288a78a..dde1c81 100644 --- a/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/rule/DeviceBootLogoRule.java +++ b/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/rule/bjq6170/BjqBootLogoRule.java @@ -1,6 +1,5 @@ -package com.fuyuanshen.global.mqtt.rule; +package com.fuyuanshen.global.mqtt.rule.bjq6170; -import com.fuyuanshen.common.core.constant.GlobalConstants; import com.fuyuanshen.common.core.utils.ImageToCArrayConverter; import com.fuyuanshen.common.core.utils.StringUtils; import com.fuyuanshen.common.json.utils.JsonUtils; @@ -15,11 +14,13 @@ import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; import java.util.ArrayList; -import java.util.Arrays; import java.util.HashMap; import java.util.Map; +import static com.fuyuanshen.common.core.constant.GlobalConstants.GLOBAL_REDIS_KEY; import static com.fuyuanshen.common.core.utils.ImageToCArrayConverter.convertHexToDecimal; +import static com.fuyuanshen.global.mqtt.constants.DeviceRedisKeyConstants.DEVICE_BOOT_LOGO_KEY_PREFIX; +import static com.fuyuanshen.global.mqtt.constants.DeviceRedisKeyConstants.DEVICE_KEY_PREFIX; /** * 人员信息命令处理 @@ -27,7 +28,7 @@ import static com.fuyuanshen.common.core.utils.ImageToCArrayConverter.convertHex @Component @RequiredArgsConstructor @Slf4j -public class DeviceBootLogoRule implements MqttMessageRule { +public class BjqBootLogoRule implements MqttMessageRule { private final MqttGateway mqttGateway; @@ -44,7 +45,7 @@ public class DeviceBootLogoRule implements MqttMessageRule { return; } - String data = RedisUtils.getCacheObject(GlobalConstants.GLOBAL_REDIS_KEY+"app_logo_data:" + context.getDeviceImei()); + String data = RedisUtils.getCacheObject(GLOBAL_REDIS_KEY+ DEVICE_KEY_PREFIX + context.getDeviceImei() +DEVICE_BOOT_LOGO_KEY_PREFIX); if (StringUtils.isEmpty(data)) { return; } @@ -71,7 +72,7 @@ public class DeviceBootLogoRule implements MqttMessageRule { MqttConstants.GLOBAL_PUB_KEY + context.getDeviceImei(), JsonUtils.toJsonString(map)); } catch (Exception e) { - log.error("处理人员信息命令时出错", e); + log.error("处理开机LOGO时出错", e); } } } diff --git a/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/rule/LocationDataRule.java b/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/rule/bjq6170/BjqLocationDataRule.java similarity index 95% rename from fys-admin/src/main/java/com/fuyuanshen/global/mqtt/rule/LocationDataRule.java rename to fys-admin/src/main/java/com/fuyuanshen/global/mqtt/rule/bjq6170/BjqLocationDataRule.java index 71e9403..5f8240c 100644 --- a/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/rule/LocationDataRule.java +++ b/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/rule/bjq6170/BjqLocationDataRule.java @@ -1,6 +1,5 @@ -package com.fuyuanshen.global.mqtt.rule; +package com.fuyuanshen.global.mqtt.rule.bjq6170; -import com.alibaba.fastjson2.JSON; import com.alibaba.fastjson2.JSONObject; import com.fuyuanshen.common.core.constant.GlobalConstants; import com.fuyuanshen.common.core.utils.StringUtils; @@ -18,20 +17,22 @@ import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; -import java.time.Duration; import java.util.ArrayList; import java.util.HashMap; import java.util.LinkedHashMap; import java.util.Map; import java.util.concurrent.CompletableFuture; +import static com.fuyuanshen.global.mqtt.constants.DeviceRedisKeyConstants.DEVICE_KEY_PREFIX; +import static com.fuyuanshen.global.mqtt.constants.DeviceRedisKeyConstants.DEVICE_LOCATION_KEY_PREFIX; + /** * 定位数据命令处理 */ @Component @RequiredArgsConstructor @Slf4j -public class LocationDataRule implements MqttMessageRule { +public class BjqLocationDataRule implements MqttMessageRule { private final MqttGateway mqttGateway; @@ -113,7 +114,7 @@ public class LocationDataRule implements MqttMessageRule { String[] latArr = latitude.split("\\."); String[] lonArr = longitude.split("\\."); // 将位置信息存储到Redis中 - String redisKey = GlobalConstants.GLOBAL_REDIS_KEY+DeviceRedisKeyConstants.DEVICE_LOCATION_KEY_PREFIX + deviceImei; + String redisKey = GlobalConstants.GLOBAL_REDIS_KEY+ DEVICE_KEY_PREFIX+ deviceImei + DEVICE_LOCATION_KEY_PREFIX; String redisObj = RedisUtils.getCacheObject(redisKey); JSONObject jsonOBj = JSONObject.parseObject(redisObj); if(jsonOBj != null){ @@ -169,7 +170,7 @@ public class LocationDataRule implements MqttMessageRule { */ public void storeDeviceTrajectoryWithSortedSet(String deviceImei, String locationJson) { try { - String trajectoryKey = GlobalConstants.GLOBAL_REDIS_KEY+DeviceRedisKeyConstants.DEVICE_LOCATION_HISTORY_KEY_PREFIX + deviceImei; + String trajectoryKey = GlobalConstants.GLOBAL_REDIS_KEY+ DEVICE_KEY_PREFIX + deviceImei + DeviceRedisKeyConstants.DEVICE_LOCATION_HISTORY_KEY_PREFIX; // String trajectoryKey = "device:trajectory:zset:" + deviceImei; // String locationJson = JsonUtils.toJsonString(locationInfo); long timestamp = System.currentTimeMillis(); diff --git a/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/rule/bjq6170/BjqModeRule.java b/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/rule/bjq6170/BjqModeRule.java new file mode 100644 index 0000000..abcc102 --- /dev/null +++ b/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/rule/bjq6170/BjqModeRule.java @@ -0,0 +1,75 @@ +package com.fuyuanshen.global.mqtt.rule.bjq6170; + +import com.fuyuanshen.common.core.constant.GlobalConstants; +import com.fuyuanshen.common.core.utils.StringUtils; +import com.fuyuanshen.common.redis.utils.RedisUtils; +import com.fuyuanshen.global.mqtt.base.MqttMessageRule; +import com.fuyuanshen.global.mqtt.base.MqttRuleContext; +import com.fuyuanshen.global.mqtt.constants.DeviceRedisKeyConstants; +import com.fuyuanshen.global.mqtt.constants.LightingCommandTypeConstants; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; + +import java.time.Duration; +import java.util.concurrent.CompletableFuture; + +import static com.fuyuanshen.global.mqtt.constants.DeviceRedisKeyConstants.DEVICE_KEY_PREFIX; +import static com.fuyuanshen.global.mqtt.constants.DeviceRedisKeyConstants.DEVICE_LIGHT_MODE_KEY_PREFIX; + +/** + * 灯光模式订阅设备回传消息 + */ +@Component +@RequiredArgsConstructor +@Slf4j +public class BjqModeRule implements MqttMessageRule { + + @Override + public String getCommandType() { + return LightingCommandTypeConstants.LIGHT_MODE; + } + + @Override + public void execute(MqttRuleContext context) { + try { + Object[] convertArr = context.getConvertArr(); + + String mainLightMode = convertArr[1].toString(); + if(StringUtils.isNotBlank(mainLightMode)){ + if("0".equals(mainLightMode)){ + String deviceOnlineStatusRedisKey = GlobalConstants.GLOBAL_REDIS_KEY+ DEVICE_KEY_PREFIX+ context.getDeviceImei() + DeviceRedisKeyConstants.DEVICE_ONLINE_STATUS_KEY_PREFIX ; + RedisUtils.setCacheObject(deviceOnlineStatusRedisKey, "0", Duration.ofSeconds(60*15)); + } + // 异步发送设备状态和位置信息到Redis + asyncSendDeviceDataToRedisWithFuture(context.getDeviceImei(),mainLightMode); + } + + } catch (Exception e) { + log.error("处理灯光模式命令时出错", e); + } + } + + /** + * 异步发送设备状态信息和位置信息到Redis(使用CompletableFuture) + * + * @param deviceImei 设备IMEI + */ + public void asyncSendDeviceDataToRedisWithFuture(String deviceImei,Object convertValue) { + CompletableFuture.runAsync(() -> { + try { + // 将设备状态信息存储到Redis中 + String deviceRedisKey = GlobalConstants.GLOBAL_REDIS_KEY+DeviceRedisKeyConstants.DEVICE_KEY_PREFIX + deviceImei + DEVICE_LIGHT_MODE_KEY_PREFIX; + + // 存储到Redis + RedisUtils.setCacheObject(deviceRedisKey, convertValue.toString()); + + } catch (Exception e) { + log.error("异步发送设备信息到Redis时出错: device={}, error={}", deviceImei, e.getMessage(), e); + } + }); + } + + + +} diff --git a/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/rule/DeviceSendMessageRule.java b/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/rule/bjq6170/BjqSendMessageRule.java similarity index 83% rename from fys-admin/src/main/java/com/fuyuanshen/global/mqtt/rule/DeviceSendMessageRule.java rename to fys-admin/src/main/java/com/fuyuanshen/global/mqtt/rule/bjq6170/BjqSendMessageRule.java index 6c2176b..b1cfbbb 100644 --- a/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/rule/DeviceSendMessageRule.java +++ b/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/rule/bjq6170/BjqSendMessageRule.java @@ -1,6 +1,5 @@ -package com.fuyuanshen.global.mqtt.rule; +package com.fuyuanshen.global.mqtt.rule.bjq6170; -import com.fuyuanshen.common.core.constant.GlobalConstants; import com.fuyuanshen.common.core.utils.ImageToCArrayConverter; import com.fuyuanshen.common.core.utils.StringUtils; import com.fuyuanshen.common.json.utils.JsonUtils; @@ -18,7 +17,9 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.Map; +import static com.fuyuanshen.common.core.constant.GlobalConstants.GLOBAL_REDIS_KEY; import static com.fuyuanshen.common.core.utils.ImageToCArrayConverter.convertHexToDecimal; +import static com.fuyuanshen.global.mqtt.constants.DeviceRedisKeyConstants.DEVICE_KEY_PREFIX; /** * 人员信息命令处理 @@ -26,7 +27,7 @@ import static com.fuyuanshen.common.core.utils.ImageToCArrayConverter.convertHex @Component @RequiredArgsConstructor @Slf4j -public class DeviceSendMessageRule implements MqttMessageRule { +public class BjqSendMessageRule implements MqttMessageRule { private final MqttGateway mqttGateway; @@ -43,7 +44,7 @@ public class DeviceSendMessageRule implements MqttMessageRule { return; } - String data = RedisUtils.getCacheObject(GlobalConstants.GLOBAL_REDIS_KEY+"app_send_message_data:" + context.getDeviceImei()); + String data = RedisUtils.getCacheObject(GLOBAL_REDIS_KEY+ DEVICE_KEY_PREFIX + context.getDeviceImei() + ":app_send_message_data"); if (StringUtils.isEmpty(data)) { return; } @@ -70,7 +71,7 @@ public class DeviceSendMessageRule implements MqttMessageRule { MqttConstants.GLOBAL_PUB_KEY + context.getDeviceImei(), JsonUtils.toJsonString(map)); } catch (Exception e) { - log.error("处理人员信息命令时出错", e); + log.error("处理发送设备信息时出错", e); } } } diff --git a/fys-admin/src/main/resources/application-dev.yml b/fys-admin/src/main/resources/application-dev.yml index e586574..d4f0fc6 100644 --- a/fys-admin/src/main/resources/application-dev.yml +++ b/fys-admin/src/main/resources/application-dev.yml @@ -1,7 +1,7 @@ --- # 监控中心配置 spring.boot.admin.client: # 增加客户端开关 - enabled: true + enabled: false url: http://localhost:9090/admin instance: service-host-type: IP diff --git a/fys-modules/fys-app/src/main/java/com/fuyuanshen/app/domain/vo/AppDeviceDetailVo.java b/fys-modules/fys-app/src/main/java/com/fuyuanshen/app/domain/vo/AppDeviceDetailVo.java index 6478ea4..230a2c4 100644 --- a/fys-modules/fys-app/src/main/java/com/fuyuanshen/app/domain/vo/AppDeviceDetailVo.java +++ b/fys-modules/fys-app/src/main/java/com/fuyuanshen/app/domain/vo/AppDeviceDetailVo.java @@ -99,4 +99,9 @@ public class AppDeviceDetailVo { // 逆解析地址 private String address; + + /** + * 告警状态(0解除告警,1告警) + */ + private String alarmStatus; } diff --git a/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/domain/vo/AppDeviceVo.java b/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/domain/vo/AppDeviceVo.java index 1642c7f..1d0ec23 100644 --- a/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/domain/vo/AppDeviceVo.java +++ b/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/domain/vo/AppDeviceVo.java @@ -76,4 +76,9 @@ public class AppDeviceVo implements Serializable { * 经度 */ private String longitude; + + /** + * 告警状态(0解除告警,1告警) + */ + private String alarmStatus; } From efed6f36839ec0307250101846f09756e4bda07c Mon Sep 17 00:00:00 2001 From: chenyouting <514333061@qq.com> Date: Thu, 7 Aug 2025 15:56:12 +0800 Subject: [PATCH 18/19] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E5=8C=85=E5=90=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../rule/{bjq6170 => bjq}/BjqActiveReportingDeviceDataRule.java | 2 +- .../global/mqtt/rule/{bjq6170 => bjq}/BjqAlarmRule.java | 2 +- .../global/mqtt/rule/{bjq6170 => bjq}/BjqBootLogoRule.java | 2 +- .../global/mqtt/rule/{bjq6170 => bjq}/BjqLocationDataRule.java | 2 +- .../global/mqtt/rule/{bjq6170 => bjq}/BjqModeRule.java | 2 +- .../global/mqtt/rule/{bjq6170 => bjq}/BjqSendMessageRule.java | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) rename fys-admin/src/main/java/com/fuyuanshen/global/mqtt/rule/{bjq6170 => bjq}/BjqActiveReportingDeviceDataRule.java (98%) rename fys-admin/src/main/java/com/fuyuanshen/global/mqtt/rule/{bjq6170 => bjq}/BjqAlarmRule.java (97%) rename fys-admin/src/main/java/com/fuyuanshen/global/mqtt/rule/{bjq6170 => bjq}/BjqBootLogoRule.java (98%) rename fys-admin/src/main/java/com/fuyuanshen/global/mqtt/rule/{bjq6170 => bjq}/BjqLocationDataRule.java (99%) rename fys-admin/src/main/java/com/fuyuanshen/global/mqtt/rule/{bjq6170 => bjq}/BjqModeRule.java (98%) rename fys-admin/src/main/java/com/fuyuanshen/global/mqtt/rule/{bjq6170 => bjq}/BjqSendMessageRule.java (98%) diff --git a/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/rule/bjq6170/BjqActiveReportingDeviceDataRule.java b/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/rule/bjq/BjqActiveReportingDeviceDataRule.java similarity index 98% rename from fys-admin/src/main/java/com/fuyuanshen/global/mqtt/rule/bjq6170/BjqActiveReportingDeviceDataRule.java rename to fys-admin/src/main/java/com/fuyuanshen/global/mqtt/rule/bjq/BjqActiveReportingDeviceDataRule.java index e6319a8..eacbcdb 100644 --- a/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/rule/bjq6170/BjqActiveReportingDeviceDataRule.java +++ b/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/rule/bjq/BjqActiveReportingDeviceDataRule.java @@ -1,4 +1,4 @@ -package com.fuyuanshen.global.mqtt.rule.bjq6170; +package com.fuyuanshen.global.mqtt.rule.bjq; import com.fuyuanshen.common.core.constant.GlobalConstants; import com.fuyuanshen.common.json.utils.JsonUtils; diff --git a/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/rule/bjq6170/BjqAlarmRule.java b/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/rule/bjq/BjqAlarmRule.java similarity index 97% rename from fys-admin/src/main/java/com/fuyuanshen/global/mqtt/rule/bjq6170/BjqAlarmRule.java rename to fys-admin/src/main/java/com/fuyuanshen/global/mqtt/rule/bjq/BjqAlarmRule.java index bff3a36..49c1af5 100644 --- a/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/rule/bjq6170/BjqAlarmRule.java +++ b/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/rule/bjq/BjqAlarmRule.java @@ -1,4 +1,4 @@ -package com.fuyuanshen.global.mqtt.rule.bjq6170; +package com.fuyuanshen.global.mqtt.rule.bjq; import com.fuyuanshen.common.core.constant.GlobalConstants; import com.fuyuanshen.common.core.utils.StringUtils; diff --git a/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/rule/bjq6170/BjqBootLogoRule.java b/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/rule/bjq/BjqBootLogoRule.java similarity index 98% rename from fys-admin/src/main/java/com/fuyuanshen/global/mqtt/rule/bjq6170/BjqBootLogoRule.java rename to fys-admin/src/main/java/com/fuyuanshen/global/mqtt/rule/bjq/BjqBootLogoRule.java index dde1c81..97fd0f3 100644 --- a/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/rule/bjq6170/BjqBootLogoRule.java +++ b/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/rule/bjq/BjqBootLogoRule.java @@ -1,4 +1,4 @@ -package com.fuyuanshen.global.mqtt.rule.bjq6170; +package com.fuyuanshen.global.mqtt.rule.bjq; import com.fuyuanshen.common.core.utils.ImageToCArrayConverter; import com.fuyuanshen.common.core.utils.StringUtils; diff --git a/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/rule/bjq6170/BjqLocationDataRule.java b/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/rule/bjq/BjqLocationDataRule.java similarity index 99% rename from fys-admin/src/main/java/com/fuyuanshen/global/mqtt/rule/bjq6170/BjqLocationDataRule.java rename to fys-admin/src/main/java/com/fuyuanshen/global/mqtt/rule/bjq/BjqLocationDataRule.java index 5f8240c..b528a00 100644 --- a/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/rule/bjq6170/BjqLocationDataRule.java +++ b/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/rule/bjq/BjqLocationDataRule.java @@ -1,4 +1,4 @@ -package com.fuyuanshen.global.mqtt.rule.bjq6170; +package com.fuyuanshen.global.mqtt.rule.bjq; import com.alibaba.fastjson2.JSONObject; import com.fuyuanshen.common.core.constant.GlobalConstants; diff --git a/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/rule/bjq6170/BjqModeRule.java b/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/rule/bjq/BjqModeRule.java similarity index 98% rename from fys-admin/src/main/java/com/fuyuanshen/global/mqtt/rule/bjq6170/BjqModeRule.java rename to fys-admin/src/main/java/com/fuyuanshen/global/mqtt/rule/bjq/BjqModeRule.java index abcc102..09aeacc 100644 --- a/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/rule/bjq6170/BjqModeRule.java +++ b/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/rule/bjq/BjqModeRule.java @@ -1,4 +1,4 @@ -package com.fuyuanshen.global.mqtt.rule.bjq6170; +package com.fuyuanshen.global.mqtt.rule.bjq; import com.fuyuanshen.common.core.constant.GlobalConstants; import com.fuyuanshen.common.core.utils.StringUtils; diff --git a/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/rule/bjq6170/BjqSendMessageRule.java b/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/rule/bjq/BjqSendMessageRule.java similarity index 98% rename from fys-admin/src/main/java/com/fuyuanshen/global/mqtt/rule/bjq6170/BjqSendMessageRule.java rename to fys-admin/src/main/java/com/fuyuanshen/global/mqtt/rule/bjq/BjqSendMessageRule.java index b1cfbbb..c9b50e1 100644 --- a/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/rule/bjq6170/BjqSendMessageRule.java +++ b/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/rule/bjq/BjqSendMessageRule.java @@ -1,4 +1,4 @@ -package com.fuyuanshen.global.mqtt.rule.bjq6170; +package com.fuyuanshen.global.mqtt.rule.bjq; import com.fuyuanshen.common.core.utils.ImageToCArrayConverter; import com.fuyuanshen.common.core.utils.StringUtils; From 9de55857bcabbb997987967440da12fedcd41f5a Mon Sep 17 00:00:00 2001 From: daiyongfei <974332738@qq.com> Date: Thu, 7 Aug 2025 18:07:04 +0800 Subject: [PATCH 19/19] =?UTF-8?q?=E6=99=B6=E5=85=A8=E6=97=A5=E5=BF=97?= =?UTF-8?q?=E9=85=8D=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../mqtt/DeviceReceiverMessageHandler.java | 134 ++++++++++++------ .../src/main/resources/application-dev.yml | 2 +- fys-admin/src/main/resources/application.yml | 2 +- 3 files changed, 93 insertions(+), 45 deletions(-) diff --git a/fys-admin/src/main/java/com/fuyuanshen/web/handler/mqtt/DeviceReceiverMessageHandler.java b/fys-admin/src/main/java/com/fuyuanshen/web/handler/mqtt/DeviceReceiverMessageHandler.java index 3548e13..b43d75f 100644 --- a/fys-admin/src/main/java/com/fuyuanshen/web/handler/mqtt/DeviceReceiverMessageHandler.java +++ b/fys-admin/src/main/java/com/fuyuanshen/web/handler/mqtt/DeviceReceiverMessageHandler.java @@ -94,6 +94,30 @@ public class DeviceReceiverMessageHandler implements MessageHandler { record.setDataSource("客户端操作"); } } + // 确保在插入前设置tenantId和deviceId + record.setTenantId(device.getTenantId()); + record.setDeviceId(device.getId()); + deviceLogMapper.insert(record); + } + + // 2. 处理 state 消息 + if (root.has("state")) { + JsonNode instructNode = root.get("state"); + if (instructNode.isArray()) { + boolean b = receivedTopicName.startsWith("B/"); + record = parseState(device, instructNode, b); + // 根据不同主题进行不同处理 + if (receivedTopicName.startsWith("A/")) { + // 处理A主题的消息(设备上传) + record.setDataSource("设备上报"); + } else if (receivedTopicName.startsWith("B/")) { + // 处理B主题的消息 (手动上传) + record.setDataSource("客户端操作"); + } + } + // 确保在插入前设置tenantId和deviceId + record.setTenantId(device.getTenantId()); + record.setDeviceId(device.getId()); deviceLogMapper.insert(record); } @@ -102,6 +126,9 @@ public class DeviceReceiverMessageHandler implements MessageHandler { record.setDeviceAction(InstructType6170.fromCode(0).getDescription()); record.setDataSource("设备上报"); record.setContent("设备启动"); + // 确保在插入前设置tenantId和deviceId + record.setTenantId(device.getTenantId()); + record.setDeviceId(device.getId()); deviceLogMapper.insert(record); } @@ -217,54 +244,75 @@ public class DeviceReceiverMessageHandler implements MessageHandler { /** - * 解析state消息 + * 解析 state 消息 * * @param device * @param array * @return */ - // private StateRecord parseState(Device device, JsonNode array) { - // StateRecord record = new StateRecord(); - // record.setDevice(device); - // record.setStateType(array.get(0).asInt()); - // - // switch (record.getStateType()) { - // case 1: // 灯光状态 - // record.setLightMode(array.get(1).asInt()); - // record.setBrightness(array.get(2).asInt()); - // break; - // - // case 2: // 设置结果 - // record.setSetResult(array.get(1).asInt() == 1); - // break; - // - // case 3: // 图片更新状态 - // record.setImagePage(array.get(1).asInt()); - // break; - // - // case 4: // 激光灯状态 - // record.setLaserStatus(array.get(1).asInt() == 1); - // break; - // - // case 5: // 亮度状态 - // record.setBrightness(array.get(1).asInt()); - // break; - // - // case 11: // 定位上报 - // record.setLatitude(array.get(1).asDouble()); - // record.setLongitude(array.get(2).asDouble()); - // break; - // - // case 12: // 设备状态 - // record.setMainLightGear(array.get(1).asInt()); - // record.setLaserLightGear(array.get(2).asInt()); - // record.setBattery(array.get(3).asInt()); - // record.setChargeStatus(array.get(4).asInt()); - // record.setDuration(array.get(5).asInt()); - // break; - // } - // return record; - // } + private DeviceLog parseState(Device device, JsonNode array, boolean b) { + DeviceLog record = new DeviceLog(); + record.setDeviceName(device.getDeviceName()); + // 设备行为 + record.setDeviceAction(InstructType6170.fromCode(array.get(0).asInt()).getDescription()); + switch (array.get(0).asInt()) { + case 1: // 灯光模式 + LightModeEnum6170 lightModeEnum6170 = LightModeEnum6170.fromCode(array.get(1).asInt()); + record.setContent(lightModeEnum6170.getDescription()); + break; + + case 2: // 单位/姓名/职位 + byte[] unitBytes = new byte[480]; + for (int i = 1; i <= 480; i++) { + unitBytes[i - 1] = (byte) array.get(i).asInt(); + } + // record.setUnitData(unitBytes); + break; + + case 3: // 开机图片 + // record.setImagePage(array.get(1).asInt()); + byte[] imageBytes = new byte[512]; + for (int i = 2; i <= 513; i++) { + imageBytes[i - 2] = (byte) array.get(i).asInt(); + } + // record.setImageData(imageBytes); + break; + + case 4: // 激光灯 + int anInt = array.get(1).asInt(); + if (anInt == 0) { + record.setContent("关闭激光灯"); + } else if (anInt == 1) { + record.setContent("开启激光灯"); + } else { + record.setContent("未知操作"); + } + break; + + case 5: // 亮度调节 + record.setContent(+array.get(1).asInt() + "%"); + break; + + case 11: // 定位数据 + if (b) { + break; + } + int i1 = array.get(1).asInt(); + int i2 = array.get(2).asInt(); + int i3 = array.get(3).asInt(); + int i4 = array.get(4).asInt(); + + // 优雅的转换方式 Longitude and latitude + double latitude = i1 + i2 / 10.0; + double Longitude = i3 + i4 / 10.0; + // 84 ==》 高德 + double[] doubles = LngLonUtil.gps84_To_Gcj02(latitude, Longitude); + String address = GetAddressFromLatUtil.getAdd(String.valueOf(doubles[1]), String.valueOf(doubles[0])); + record.setContent(address); + break; + } + return record; + } } diff --git a/fys-admin/src/main/resources/application-dev.yml b/fys-admin/src/main/resources/application-dev.yml index e586574..d4f0fc6 100644 --- a/fys-admin/src/main/resources/application-dev.yml +++ b/fys-admin/src/main/resources/application-dev.yml @@ -1,7 +1,7 @@ --- # 监控中心配置 spring.boot.admin.client: # 增加客户端开关 - enabled: true + enabled: false url: http://localhost:9090/admin instance: service-host-type: IP diff --git a/fys-admin/src/main/resources/application.yml b/fys-admin/src/main/resources/application.yml index 60c9106..c413dff 100644 --- a/fys-admin/src/main/resources/application.yml +++ b/fys-admin/src/main/resources/application.yml @@ -64,7 +64,7 @@ spring: # 国际化资源文件路径 basename: i18n/messages profiles: - active: @profiles.active@ + active: ${profiles.active} # 文件上传 servlet: multipart: