From 0510c2038ec2d747559519b01ad4680a151d0591 Mon Sep 17 00:00:00 2001 From: zch Date: Wed, 2 Apr 2025 14:32:45 +0800 Subject: [PATCH 1/4] =?UTF-8?q?add(dms):=20=E4=BF=9D=E5=85=BB=E9=83=A8?= =?UTF-8?q?=E4=BD=8D=E4=B8=8E=E9=A1=B9=E7=9B=AE=E5=85=B3=E8=81=94=E5=8A=9F?= =?UTF-8?q?=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 新增保养部位与项目关联的相关接口和实现 - 在 DmsBaseMaintStation 中添加与 DmsBaseMaintProject 的关联 - 实现保养部位与项目关联的增删改查功能 --- .../dms/domain/DmsBaseMaintStation.java | 12 +++- .../dms/domain/DmsBaseStationProject.java | 7 +- .../dms/domain/bo/DmsBaseMaintStationBo.java | 15 ++-- .../dms/domain/vo/DmsBaseMaintStationVo.java | 14 ++-- .../dms/mapper/DmsBaseMaintProjectMapper.java | 4 ++ .../mapper/DmsBaseStationProjectMapper.java | 18 +++++ .../impl/DmsBaseMaintProjectServiceImpl.java | 33 ++++++--- .../impl/DmsBaseMaintStationServiceImpl.java | 72 ++++++++++++++++--- .../DmsBaseStationProjectServiceImpl.java | 25 ++++--- .../mapper/dms/DmsBaseMaintProjectMapper.xml | 29 ++++++++ .../mapper/dms/DmsBaseMaintStationMapper.xml | 15 ++++ .../dms/DmsBaseStationProjectMapper.xml | 11 +++ 12 files changed, 211 insertions(+), 44 deletions(-) diff --git a/ruoyi-modules/hwmom-dms/src/main/java/org/dromara/dms/domain/DmsBaseMaintStation.java b/ruoyi-modules/hwmom-dms/src/main/java/org/dromara/dms/domain/DmsBaseMaintStation.java index 80d3b63..caf3d28 100644 --- a/ruoyi-modules/hwmom-dms/src/main/java/org/dromara/dms/domain/DmsBaseMaintStation.java +++ b/ruoyi-modules/hwmom-dms/src/main/java/org/dromara/dms/domain/DmsBaseMaintStation.java @@ -1,11 +1,15 @@ package org.dromara.dms.domain; -import org.dromara.common.tenant.core.TenantEntity; -import com.baomidou.mybatisplus.annotation.*; +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; import lombok.Data; import lombok.EqualsAndHashCode; +import org.dromara.common.tenant.core.TenantEntity; import java.io.Serial; +import java.util.List; /** * 保养部位信息对象 dms_base_maint_station @@ -63,5 +67,9 @@ public class DmsBaseMaintStation extends TenantEntity { @TableField(exist = false) private String deviceTypeName;//JOIN +/* + @TableField(exist = false) + private List dmsBaseMaintProject; +*/ } diff --git a/ruoyi-modules/hwmom-dms/src/main/java/org/dromara/dms/domain/DmsBaseStationProject.java b/ruoyi-modules/hwmom-dms/src/main/java/org/dromara/dms/domain/DmsBaseStationProject.java index 2d2d206..f52b5e1 100644 --- a/ruoyi-modules/hwmom-dms/src/main/java/org/dromara/dms/domain/DmsBaseStationProject.java +++ b/ruoyi-modules/hwmom-dms/src/main/java/org/dromara/dms/domain/DmsBaseStationProject.java @@ -1,7 +1,6 @@ package org.dromara.dms.domain; -import org.dromara.common.mybatis.core.domain.BaseEntity; -import com.baomidou.mybatisplus.annotation.*; +import com.baomidou.mybatisplus.annotation.TableName; import lombok.Data; import lombok.EqualsAndHashCode; @@ -14,9 +13,9 @@ import java.io.Serial; * @date 2025-03-21 */ @Data -@EqualsAndHashCode(callSuper = true) +@EqualsAndHashCode @TableName("dms_base_station_project") -public class DmsBaseStationProject extends BaseEntity { +public class DmsBaseStationProject { @Serial private static final long serialVersionUID = 1L; diff --git a/ruoyi-modules/hwmom-dms/src/main/java/org/dromara/dms/domain/bo/DmsBaseMaintStationBo.java b/ruoyi-modules/hwmom-dms/src/main/java/org/dromara/dms/domain/bo/DmsBaseMaintStationBo.java index 8c0a78d..df759e8 100644 --- a/ruoyi-modules/hwmom-dms/src/main/java/org/dromara/dms/domain/bo/DmsBaseMaintStationBo.java +++ b/ruoyi-modules/hwmom-dms/src/main/java/org/dromara/dms/domain/bo/DmsBaseMaintStationBo.java @@ -1,13 +1,14 @@ package org.dromara.dms.domain.bo; -import org.dromara.dms.domain.DmsBaseMaintStation; -import org.dromara.common.mybatis.core.domain.BaseEntity; -import org.dromara.common.core.validate.AddGroup; -import org.dromara.common.core.validate.EditGroup; import io.github.linpeilie.annotations.AutoMapper; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; import lombok.Data; import lombok.EqualsAndHashCode; -import jakarta.validation.constraints.*; +import org.dromara.common.core.validate.AddGroup; +import org.dromara.common.core.validate.EditGroup; +import org.dromara.common.mybatis.core.domain.BaseEntity; +import org.dromara.dms.domain.DmsBaseMaintStation; /** * 保养部位信息业务对象 dms_base_maint_station @@ -60,4 +61,8 @@ public class DmsBaseMaintStationBo extends BaseEntity { private String remark; + /** + * 保养项目 + */ + Long[] maintProjectIds; } diff --git a/ruoyi-modules/hwmom-dms/src/main/java/org/dromara/dms/domain/vo/DmsBaseMaintStationVo.java b/ruoyi-modules/hwmom-dms/src/main/java/org/dromara/dms/domain/vo/DmsBaseMaintStationVo.java index b6742f3..98f48ca 100644 --- a/ruoyi-modules/hwmom-dms/src/main/java/org/dromara/dms/domain/vo/DmsBaseMaintStationVo.java +++ b/ruoyi-modules/hwmom-dms/src/main/java/org/dromara/dms/domain/vo/DmsBaseMaintStationVo.java @@ -1,17 +1,16 @@ package org.dromara.dms.domain.vo; -import org.dromara.dms.domain.DmsBaseMaintStation; import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; import com.alibaba.excel.annotation.ExcelProperty; -import org.dromara.common.excel.annotation.ExcelDictFormat; -import org.dromara.common.excel.convert.ExcelDictConvert; import io.github.linpeilie.annotations.AutoMapper; import lombok.Data; +import org.dromara.common.excel.annotation.ExcelDictFormat; +import org.dromara.common.excel.convert.ExcelDictConvert; +import org.dromara.dms.domain.DmsBaseMaintStation; import java.io.Serial; import java.io.Serializable; -import java.util.Date; - +import java.util.List; /** @@ -76,4 +75,9 @@ public class DmsBaseMaintStationVo implements Serializable { */ private String deviceTypeName;//JOIN + + @ExcelProperty(value = "保养项目") + private List dmsBaseMaintProjectList; + + private Long[] maintProjectIds; } diff --git a/ruoyi-modules/hwmom-dms/src/main/java/org/dromara/dms/mapper/DmsBaseMaintProjectMapper.java b/ruoyi-modules/hwmom-dms/src/main/java/org/dromara/dms/mapper/DmsBaseMaintProjectMapper.java index 7f25db6..949ca48 100644 --- a/ruoyi-modules/hwmom-dms/src/main/java/org/dromara/dms/mapper/DmsBaseMaintProjectMapper.java +++ b/ruoyi-modules/hwmom-dms/src/main/java/org/dromara/dms/mapper/DmsBaseMaintProjectMapper.java @@ -4,6 +4,8 @@ import org.dromara.dms.domain.DmsBaseMaintProject; import org.dromara.dms.domain.vo.DmsBaseMaintProjectVo; import org.dromara.common.mybatis.core.mapper.BaseMapperPlus; +import java.util.List; + /** * 保养项目信息Mapper接口 * @@ -12,4 +14,6 @@ import org.dromara.common.mybatis.core.mapper.BaseMapperPlus; */ public interface DmsBaseMaintProjectMapper extends BaseMapperPlus { + List selectProjectMenuByStationId(Long maintStationId); + } diff --git a/ruoyi-modules/hwmom-dms/src/main/java/org/dromara/dms/mapper/DmsBaseStationProjectMapper.java b/ruoyi-modules/hwmom-dms/src/main/java/org/dromara/dms/mapper/DmsBaseStationProjectMapper.java index ebbe1e0..d4c13a5 100644 --- a/ruoyi-modules/hwmom-dms/src/main/java/org/dromara/dms/mapper/DmsBaseStationProjectMapper.java +++ b/ruoyi-modules/hwmom-dms/src/main/java/org/dromara/dms/mapper/DmsBaseStationProjectMapper.java @@ -12,4 +12,22 @@ import org.dromara.common.mybatis.core.mapper.BaseMapperPlus; */ public interface DmsBaseStationProjectMapper extends BaseMapperPlus { + /** + * 删除保养部位关联项目信息 + * + * @param maintStationId 保养部位关联项目信息主键 + * @return 结果 + */ + public int deleteDmsBaseStationProjectByMaintStationId(Long maintStationId); + + + /** + * 批量删除保养部位关联项目信息 + * + * @param maintStationIds 需要删除的数据主键集合 + * @return 结果 + */ + public int deleteDmsBaseStationProjectByMaintStationIds(Long[] maintStationIds); + + } diff --git a/ruoyi-modules/hwmom-dms/src/main/java/org/dromara/dms/service/impl/DmsBaseMaintProjectServiceImpl.java b/ruoyi-modules/hwmom-dms/src/main/java/org/dromara/dms/service/impl/DmsBaseMaintProjectServiceImpl.java index 6255a3d..da385d5 100644 --- a/ruoyi-modules/hwmom-dms/src/main/java/org/dromara/dms/service/impl/DmsBaseMaintProjectServiceImpl.java +++ b/ruoyi-modules/hwmom-dms/src/main/java/org/dromara/dms/service/impl/DmsBaseMaintProjectServiceImpl.java @@ -1,24 +1,27 @@ package org.dromara.dms.service.impl; -import org.dromara.common.core.utils.MapstructUtils; -import org.dromara.common.core.utils.StringUtils; -import org.dromara.common.mybatis.core.page.TableDataInfo; -import org.dromara.common.mybatis.core.page.PageQuery; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.github.yulichang.toolkit.JoinWrappers; import com.github.yulichang.wrapper.MPJLambdaWrapper; -import com.baomidou.mybatisplus.core.toolkit.Wrappers; import lombok.RequiredArgsConstructor; -import org.springframework.stereotype.Service; -import org.dromara.dms.domain.bo.DmsBaseMaintProjectBo; -import org.dromara.dms.domain.vo.DmsBaseMaintProjectVo; +import org.dromara.common.core.exception.ServiceException; +import org.dromara.common.core.utils.MapstructUtils; +import org.dromara.common.core.utils.StringUtils; +import org.dromara.common.mybatis.core.page.PageQuery; +import org.dromara.common.mybatis.core.page.TableDataInfo; import org.dromara.dms.domain.DmsBaseMaintProject; +import org.dromara.dms.domain.bo.DmsBaseMaintProjectBo; +import org.dromara.dms.domain.bo.DmsBaseStationProjectBo; +import org.dromara.dms.domain.vo.DmsBaseMaintProjectVo; +import org.dromara.dms.domain.vo.DmsBaseStationProjectVo; import org.dromara.dms.mapper.DmsBaseMaintProjectMapper; import org.dromara.dms.service.IDmsBaseMaintProjectService; +import org.dromara.dms.service.IDmsBaseStationProjectService; +import org.springframework.stereotype.Service; +import java.util.Collection; import java.util.List; import java.util.Map; -import java.util.Collection; /** * 保养项目信息Service业务层处理 @@ -32,6 +35,8 @@ public class DmsBaseMaintProjectServiceImpl implements IDmsBaseMaintProjectServi private final DmsBaseMaintProjectMapper baseMapper; + private final IDmsBaseStationProjectService dmsBaseStationProjectService; + /** * 查询保养项目信息 * @@ -129,6 +134,16 @@ public class DmsBaseMaintProjectServiceImpl implements IDmsBaseMaintProjectServi public Boolean deleteWithValidByIds(Collection ids, Boolean isValid) { if(isValid){ //TODO 做一些业务上的校验,判断是否需要校验 + + + for (Long id : ids ){ + DmsBaseStationProjectBo qurey = new DmsBaseStationProjectBo(); + qurey.setMaintProjectId(id); + List dmsBaseStationProjectVos = dmsBaseStationProjectService.queryList(qurey); + if ( ! dmsBaseStationProjectVos.isEmpty()){ + throw new ServiceException("项目已绑定润滑部位,请先取消绑定"); + } + } } return baseMapper.deleteByIds(ids) > 0; } diff --git a/ruoyi-modules/hwmom-dms/src/main/java/org/dromara/dms/service/impl/DmsBaseMaintStationServiceImpl.java b/ruoyi-modules/hwmom-dms/src/main/java/org/dromara/dms/service/impl/DmsBaseMaintStationServiceImpl.java index 1c3670e..f6c9449 100644 --- a/ruoyi-modules/hwmom-dms/src/main/java/org/dromara/dms/service/impl/DmsBaseMaintStationServiceImpl.java +++ b/ruoyi-modules/hwmom-dms/src/main/java/org/dromara/dms/service/impl/DmsBaseMaintStationServiceImpl.java @@ -1,26 +1,32 @@ package org.dromara.dms.service.impl; -import org.dromara.common.core.utils.MapstructUtils; -import org.dromara.common.core.utils.StringUtils; -import org.dromara.common.mybatis.core.page.TableDataInfo; -import org.dromara.common.mybatis.core.page.PageQuery; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.github.yulichang.toolkit.JoinWrappers; import com.github.yulichang.wrapper.MPJLambdaWrapper; -import com.baomidou.mybatisplus.core.toolkit.Wrappers; import lombok.RequiredArgsConstructor; +import org.dromara.common.core.utils.MapstructUtils; +import org.dromara.common.core.utils.StringUtils; +import org.dromara.common.mybatis.core.page.PageQuery; +import org.dromara.common.mybatis.core.page.TableDataInfo; import org.dromara.dms.domain.DmsBaseDeviceType; import org.dromara.dms.domain.DmsBaseMaintStandard; -import org.springframework.stereotype.Service; -import org.dromara.dms.domain.bo.DmsBaseMaintStationBo; -import org.dromara.dms.domain.vo.DmsBaseMaintStationVo; import org.dromara.dms.domain.DmsBaseMaintStation; +import org.dromara.dms.domain.DmsBaseStationProject; +import org.dromara.dms.domain.bo.DmsBaseMaintStationBo; +import org.dromara.dms.domain.bo.DmsBaseStationProjectBo; +import org.dromara.dms.domain.vo.DmsBaseMaintStationVo; +import org.dromara.dms.domain.vo.DmsBaseStationProjectVo; import org.dromara.dms.mapper.DmsBaseMaintStationMapper; +import org.dromara.dms.mapper.DmsBaseStationProjectMapper; import org.dromara.dms.service.IDmsBaseMaintStationService; +import org.dromara.dms.service.IDmsBaseStationProjectService; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import java.util.ArrayList; +import java.util.Collection; import java.util.List; import java.util.Map; -import java.util.Collection; /** * 保养部位信息Service业务层处理 @@ -34,6 +40,11 @@ public class DmsBaseMaintStationServiceImpl implements IDmsBaseMaintStationServi private final DmsBaseMaintStationMapper baseMapper; + private final DmsBaseStationProjectMapper baseStationProjectMapper; + + private final IDmsBaseStationProjectService dmsBaseStationProjectService; + + /** * 查询保养部位信息 * @@ -42,7 +53,16 @@ public class DmsBaseMaintStationServiceImpl implements IDmsBaseMaintStationServi */ @Override public DmsBaseMaintStationVo queryById(Long maintStationId){ - return baseMapper.selectVoById(maintStationId); + DmsBaseStationProjectBo dmsBaseStationProject = new DmsBaseStationProjectBo(); + dmsBaseStationProject.setMaintStationId(maintStationId); + List dmsBaseStationProjectVos = dmsBaseStationProjectService.queryList(dmsBaseStationProject); + Long[] maintProjectIds = dmsBaseStationProjectVos + .stream() + .map(DmsBaseStationProjectVo::getMaintProjectId) + .toArray(Long[]::new); + DmsBaseMaintStationVo dmsBaseMaintStationVo = baseMapper.selectVoById(maintStationId); + dmsBaseMaintStationVo.setMaintProjectIds(maintProjectIds); + return dmsBaseMaintStationVo; } /** @@ -101,6 +121,7 @@ public class DmsBaseMaintStationServiceImpl implements IDmsBaseMaintStationServi * @return 是否新增成功 */ @Override + @Transactional(rollbackFor = Exception.class) public Boolean insertByBo(DmsBaseMaintStationBo bo) { DmsBaseMaintStation add = MapstructUtils.convert(bo, DmsBaseMaintStation.class); validEntityBeforeSave(add); @@ -108,6 +129,18 @@ public class DmsBaseMaintStationServiceImpl implements IDmsBaseMaintStationServi if (flag) { bo.setMaintStationId(add.getMaintStationId()); } + + Long maintStationId = bo.getMaintStationId();//保养部位ID + // 保存保养项目关联信息 + Long[] maintProjectIds = bo.getMaintProjectIds(); + List dmsBaseStationProjectList = new ArrayList<>(); + for (Long maintProjectId : maintProjectIds){ + DmsBaseStationProject addStationProject = new DmsBaseStationProject(); + addStationProject.setMaintStationId(maintStationId); + addStationProject.setMaintProjectId(maintProjectId); + dmsBaseStationProjectList.add(addStationProject); + } + baseStationProjectMapper.insertBatch(dmsBaseStationProjectList); return flag; } @@ -118,9 +151,24 @@ public class DmsBaseMaintStationServiceImpl implements IDmsBaseMaintStationServi * @return 是否修改成功 */ @Override + @Transactional(rollbackFor = Exception.class) public Boolean updateByBo(DmsBaseMaintStationBo bo) { DmsBaseMaintStation update = MapstructUtils.convert(bo, DmsBaseMaintStation.class); validEntityBeforeSave(update); + + // 删除保养项目关联信息,先删再加 + Long maintStationId = bo.getMaintStationId();//保养部位ID + baseStationProjectMapper.deleteDmsBaseStationProjectByMaintStationId(maintStationId); + Long[] maintProjectIds = bo.getMaintProjectIds(); + // 保存保养项目关联信息 + List dmsBaseStationProjectList = new ArrayList<>(); + for (Long maintProjectId : maintProjectIds){ + DmsBaseStationProject addStationProject = new DmsBaseStationProject(); + addStationProject.setMaintStationId(maintStationId); + addStationProject.setMaintProjectId(maintProjectId); + dmsBaseStationProjectList.add(addStationProject); + } + baseStationProjectMapper.insertBatch(dmsBaseStationProjectList); return baseMapper.updateById(update) > 0; } @@ -139,10 +187,14 @@ public class DmsBaseMaintStationServiceImpl implements IDmsBaseMaintStationServi * @return 是否删除成功 */ @Override + @Transactional(rollbackFor = Exception.class) public Boolean deleteWithValidByIds(Collection ids, Boolean isValid) { if(isValid){ //TODO 做一些业务上的校验,判断是否需要校验 } + + Long[] maintStationIds = ids.toArray(new Long[0]); + baseStationProjectMapper.deleteDmsBaseStationProjectByMaintStationIds(maintStationIds); return baseMapper.deleteByIds(ids) > 0; } } diff --git a/ruoyi-modules/hwmom-dms/src/main/java/org/dromara/dms/service/impl/DmsBaseStationProjectServiceImpl.java b/ruoyi-modules/hwmom-dms/src/main/java/org/dromara/dms/service/impl/DmsBaseStationProjectServiceImpl.java index a9a0afe..125b64f 100644 --- a/ruoyi-modules/hwmom-dms/src/main/java/org/dromara/dms/service/impl/DmsBaseStationProjectServiceImpl.java +++ b/ruoyi-modules/hwmom-dms/src/main/java/org/dromara/dms/service/impl/DmsBaseStationProjectServiceImpl.java @@ -1,24 +1,22 @@ package org.dromara.dms.service.impl; -import org.dromara.common.core.utils.MapstructUtils; -import org.dromara.common.core.utils.StringUtils; -import org.dromara.common.mybatis.core.page.TableDataInfo; -import org.dromara.common.mybatis.core.page.PageQuery; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.github.yulichang.toolkit.JoinWrappers; import com.github.yulichang.wrapper.MPJLambdaWrapper; -import com.baomidou.mybatisplus.core.toolkit.Wrappers; import lombok.RequiredArgsConstructor; -import org.springframework.stereotype.Service; +import org.dromara.common.core.utils.MapstructUtils; +import org.dromara.common.mybatis.core.page.PageQuery; +import org.dromara.common.mybatis.core.page.TableDataInfo; +import org.dromara.dms.domain.DmsBaseStationProject; import org.dromara.dms.domain.bo.DmsBaseStationProjectBo; import org.dromara.dms.domain.vo.DmsBaseStationProjectVo; -import org.dromara.dms.domain.DmsBaseStationProject; import org.dromara.dms.mapper.DmsBaseStationProjectMapper; import org.dromara.dms.service.IDmsBaseStationProjectService; +import org.springframework.stereotype.Service; +import java.util.Collection; import java.util.List; import java.util.Map; -import java.util.Collection; /** * 保养部位关联项目信息Service业务层处理 @@ -73,9 +71,18 @@ public class DmsBaseStationProjectServiceImpl implements IDmsBaseStationProjectS Map params = bo.getParams(); MPJLambdaWrapper lqw = JoinWrappers.lambda(DmsBaseStationProject.class) .selectAll(DmsBaseStationProject.class) + +/* // 关联查询项目 + .select(DmsBaseMaintProject::getMaintProjectName) + .leftJoin(DmsBaseMaintProject.class,DmsBaseMaintProject::getMaintProjectId,DmsBaseStationProject::getMaintProjectId) + // 关联查询部位 + .select(DmsBaseMaintStation::getMaintStationName) + .leftJoin(DmsBaseMaintStation.class, DmsBaseMaintStation::getMaintStationId,DmsBaseStationProject::getMaintStationId)*/ + .eq(bo.getMaintStationId() != null, DmsBaseStationProject::getMaintStationId, bo.getMaintStationId()) .eq(bo.getMaintProjectId() != null, DmsBaseStationProject::getMaintProjectId, bo.getMaintProjectId()) - .orderByDesc(DmsBaseStationProject::getCreateTime); +// .orderByDesc(DmsBaseStationProject::getCreateTime) + ; return lqw; } diff --git a/ruoyi-modules/hwmom-dms/src/main/resources/mapper/dms/DmsBaseMaintProjectMapper.xml b/ruoyi-modules/hwmom-dms/src/main/resources/mapper/dms/DmsBaseMaintProjectMapper.xml index c65a696..4f156cb 100644 --- a/ruoyi-modules/hwmom-dms/src/main/resources/mapper/dms/DmsBaseMaintProjectMapper.xml +++ b/ruoyi-modules/hwmom-dms/src/main/resources/mapper/dms/DmsBaseMaintProjectMapper.xml @@ -4,4 +4,33 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> + + + + + + + + + + + + + select dbmp.maint_project_id, + dbmp.maint_project_name, + dbmp.maint_project_desc, + dbmp.remark, dbmp.create_by, dbmp.create_time, dbmp.update_by, dbmp.update_time, + dbsp.maint_station_id + from dms_base_maint_project dbmp + left join dms_base_station_project dbsp on dbmp.maint_project_id = dbsp.maint_project_id + + + + + + diff --git a/ruoyi-modules/hwmom-dms/src/main/resources/mapper/dms/DmsBaseMaintStationMapper.xml b/ruoyi-modules/hwmom-dms/src/main/resources/mapper/dms/DmsBaseMaintStationMapper.xml index 58e9320..6ab2e3b 100644 --- a/ruoyi-modules/hwmom-dms/src/main/resources/mapper/dms/DmsBaseMaintStationMapper.xml +++ b/ruoyi-modules/hwmom-dms/src/main/resources/mapper/dms/DmsBaseMaintStationMapper.xml @@ -4,4 +4,19 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> + + diff --git a/ruoyi-modules/hwmom-dms/src/main/resources/mapper/dms/DmsBaseStationProjectMapper.xml b/ruoyi-modules/hwmom-dms/src/main/resources/mapper/dms/DmsBaseStationProjectMapper.xml index fd09381..5432e9e 100644 --- a/ruoyi-modules/hwmom-dms/src/main/resources/mapper/dms/DmsBaseStationProjectMapper.xml +++ b/ruoyi-modules/hwmom-dms/src/main/resources/mapper/dms/DmsBaseStationProjectMapper.xml @@ -4,4 +4,15 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> + + delete from dms_base_station_project where maint_station_id = #{maintStationId} + + + + delete from dms_base_station_project where maint_station_id in + + #{maintStationId} + + + From 2839a3d13f02deef8052f2b6627807c7e13b3e76 Mon Sep 17 00:00:00 2001 From: zch Date: Wed, 2 Apr 2025 17:05:43 +0800 Subject: [PATCH 2/4] =?UTF-8?q?add(common):=20=E7=A7=BB=E6=A4=8D=E4=BA=AC?= =?UTF-8?q?=E6=BA=90=E6=B7=BB=E5=8A=A0=E5=B8=B8=E9=87=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 在 BusinessType 枚举中添加 START 和 COMPLETE 类型 - 添加检修和保养相关的序列类型和业务类型,在 Seq 类中添加检修计划、检修工单、保养计划和保养工单的序列类型和相关标识 - 更新 getDmsId 方法以支持新的序列类型 --- .../dromara/common/core/utils/uuid/Seq.java | 50 +++++++++++++++++++ .../common/log/enums/BusinessType.java | 12 +++++ 2 files changed, 62 insertions(+) diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/utils/uuid/Seq.java b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/utils/uuid/Seq.java index 26f05f6..35f6587 100644 --- a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/utils/uuid/Seq.java +++ b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/utils/uuid/Seq.java @@ -54,6 +54,51 @@ public class Seq { public static final String dmsLubeInstanceCode = "LI"; + //检修计划序列类型 + public static final String planRepairSeqType = "PLANREPAIR"; + //检修计划接口序列数 + private static AtomicInteger planRepairSeq = new AtomicInteger(1); + //检修记录标识 + public static final String planRepairCode = "PR"; + //检修工单序列类型 + public static final String repairInstanceSeqTupe = "REPAIRINSTANCE"; + //检修工单接口序列数 + private static AtomicInteger repairInstanceSeq = new AtomicInteger(1); + //检修工单标识 + public static final String repairInstanceCode = "RI"; + + //检修计划序列类型 + public static final String planInspectSeqType = "PLANINSPECT"; + //检修计划接口序列数 + private static AtomicInteger planInspectSeq = new AtomicInteger(1); + //检修记录标识 + public static final String planInspectCode = "PIC"; + //检修工单序列类型 + public static final String InspectInstanceSeqTupe = "INSPECTINSTANCE"; + //检修工单接口序列数 + private static AtomicInteger INSPECTInstanceSeq = new AtomicInteger(1); + //检修工单标识 + public static final String InspectInstanceCode = "IIC"; + + // 保养计划序列类型 + public static final String planMaintSeqType = "PLANMAINT"; + + // 保养计划接口序列数 + private static AtomicInteger planMaintSeq = new AtomicInteger(1); + + // 保养记录标识 + public static final String planMaintCode = "PM"; + + + // 保养工单序列类型 + public static final String maintInstanceSeqType = "MAINTINSTANCE"; + + // 保养工单接口序列数 + private static AtomicInteger maintInstanceSeq = new AtomicInteger(1); + + // 保养工单标识 + public static final String maintInstanceCode = "MI"; + /** * 获取通用序列号 * @@ -122,7 +167,12 @@ public class Seq { atomicInt = dmsPlanLubeSeq; }else if (dmsLubeInstanceSeqType.equals(type)) { atomicInt = dmsLubeInstanceSeq; + }else if (planMaintSeqType.equals(type)) { + atomicInt = planMaintSeq; + }else if(maintInstanceSeqType.equals(type)) { + atomicInt = maintInstanceSeq; } + return getId(atomicInt, 4, code); } diff --git a/ruoyi-common/ruoyi-common-log/src/main/java/org/dromara/common/log/enums/BusinessType.java b/ruoyi-common/ruoyi-common-log/src/main/java/org/dromara/common/log/enums/BusinessType.java index 2d25ebb..2cf48cf 100644 --- a/ruoyi-common/ruoyi-common-log/src/main/java/org/dromara/common/log/enums/BusinessType.java +++ b/ruoyi-common/ruoyi-common-log/src/main/java/org/dromara/common/log/enums/BusinessType.java @@ -55,4 +55,16 @@ public enum BusinessType { * 清空数据 */ CLEAN, + + + /** + * 开始 + */ + START, + + /** + * 完成 + */ + COMPLETE, + } From 2b6e5c7642923bec1b3bcde4c9bec73f9d536974 Mon Sep 17 00:00:00 2001 From: yinq Date: Thu, 3 Apr 2025 15:31:40 +0800 Subject: [PATCH 3/4] =?UTF-8?q?update=20mqtt=E6=A8=A1=E5=9D=97=E4=B8=8Edp?= =?UTF-8?q?=E6=95=B0=E6=8D=AE=E5=A4=84=E7=90=86=E6=A8=A1=E5=9D=97kafka?= =?UTF-8?q?=E4=BC=98=E5=8C=96=EF=BC=9A=E8=AE=BE=E5=A4=87=E7=8A=B6=E6=80=81?= =?UTF-8?q?=E3=80=81=E6=95=B0=E6=8D=AE=E3=80=81=E6=8A=A5=E8=AD=A6=E9=80=9A?= =?UTF-8?q?=E7=94=A8=E6=96=B9=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dromara/dp/kafka/config/KafkaConfig.java | 126 ++++ .../kafka/service/KafkaConsumerService.java | 346 ++++++++- .../dp/service/DataProcessService.java | 21 + .../dp/service/DeviceAlarmService.java | 23 + .../dp/service/DeviceStatusService.java | 23 + .../service/impl/DataProcessServiceImpl.java | 103 +++ .../service/impl/DeviceAlarmServiceImpl.java | 34 + .../service/impl/DeviceStatusServiceImpl.java | 22 + .../service/DataProcessServiceImpl.java | 685 ------------------ .../service/DeviceStatusServiceImpl.java | 178 ----- .../src/main/resources/application.yml | 46 +- .../com/hw/mqtt/domain/DeviceInfoDto.java | 2 +- .../java/com/hw/mqtt/enums/ConnectStatus.java | 2 +- .../listener/MqttConnectStatusListener.java | 141 +++- .../listener/MqttServerMessageListener.java | 136 +++- .../hw/mqtt/service/KafkaProducerService.java | 122 +++- .../src/main/java/org/dromara/Main.java | 17 - .../src/main/resources/application.yml | 4 +- 18 files changed, 1079 insertions(+), 952 deletions(-) create mode 100644 ruoyi-modules/hwmom-dp/src/main/java/org/dromara/dp/kafka/config/KafkaConfig.java create mode 100644 ruoyi-modules/hwmom-dp/src/main/java/org/dromara/dp/service/DataProcessService.java create mode 100644 ruoyi-modules/hwmom-dp/src/main/java/org/dromara/dp/service/DeviceAlarmService.java create mode 100644 ruoyi-modules/hwmom-dp/src/main/java/org/dromara/dp/service/DeviceStatusService.java create mode 100644 ruoyi-modules/hwmom-dp/src/main/java/org/dromara/dp/service/impl/DataProcessServiceImpl.java create mode 100644 ruoyi-modules/hwmom-dp/src/main/java/org/dromara/dp/service/impl/DeviceAlarmServiceImpl.java create mode 100644 ruoyi-modules/hwmom-dp/src/main/java/org/dromara/dp/service/impl/DeviceStatusServiceImpl.java delete mode 100644 ruoyi-modules/hwmom-dp/src/main/java/org/dromara/service/DataProcessServiceImpl.java delete mode 100644 ruoyi-modules/hwmom-dp/src/main/java/org/dromara/service/DeviceStatusServiceImpl.java delete mode 100644 ruoyi-modules/hwmom-mqtt/src/main/java/org/dromara/Main.java diff --git a/ruoyi-modules/hwmom-dp/src/main/java/org/dromara/dp/kafka/config/KafkaConfig.java b/ruoyi-modules/hwmom-dp/src/main/java/org/dromara/dp/kafka/config/KafkaConfig.java new file mode 100644 index 0000000..1bbe4f9 --- /dev/null +++ b/ruoyi-modules/hwmom-dp/src/main/java/org/dromara/dp/kafka/config/KafkaConfig.java @@ -0,0 +1,126 @@ +package org.dromara.dp.kafka.config; + +import org.apache.kafka.clients.consumer.ConsumerConfig; +import org.apache.kafka.clients.producer.ProducerConfig; +import org.apache.kafka.common.serialization.StringDeserializer; +import org.apache.kafka.common.serialization.StringSerializer; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.kafka.config.ConcurrentKafkaListenerContainerFactory; +import org.springframework.kafka.core.*; + +import java.util.HashMap; +import java.util.Map; + +/** + * Kafka配置类 + * 用于配置Kafka生产者和消费者的相关参数 + * 包括序列化器、连接参数、性能参数等 + * + * @author hwmom + * @since 2024-04-02 + */ +@Configuration +public class KafkaConfig { + + /** + * Kafka服务器地址 + * 从配置文件中读取,格式为:host:port + */ + @Value("${spring.kafka.bootstrap-servers}") + private String bootstrapServers; + + /** + * 消费者组ID + * 使用默认的消费者组:my-consumer-group + */ + @Value("${spring.kafka.consumer.group-id:my-consumer-group}") + private String groupId; + + /** + * 配置Kafka生产者工厂 + * 设置序列化器、确认机制、重试次数等参数 + * + * @return ProducerFactory 生产者工厂实例 + */ + @Bean + public ProducerFactory producerFactory() { + Map configProps = new HashMap<>(); + // 设置Kafka服务器地址 + configProps.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, bootstrapServers); + // 设置key序列化器 + configProps.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, StringSerializer.class); + // 设置value序列化器 + configProps.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, StringSerializer.class); + // 设置确认机制为all,确保消息被所有副本接收 + configProps.put(ProducerConfig.ACKS_CONFIG, "all"); + // 设置重试次数 + configProps.put(ProducerConfig.RETRIES_CONFIG, 3); + // 设置批量发送大小 + configProps.put(ProducerConfig.BATCH_SIZE_CONFIG, 16384); + return new DefaultKafkaProducerFactory<>(configProps); + } + + /** + * 创建KafkaTemplate实例 + * 用于发送消息到Kafka + * + * @return KafkaTemplate Kafka模板实例 + */ + @Bean + public KafkaTemplate kafkaTemplate() { + return new KafkaTemplate<>(producerFactory()); + } + + /** + * 配置Kafka消费者工厂 + * 设置反序列化器、消费者组ID、自动提交等参数 + * + * @return ConsumerFactory 消费者工厂实例 + */ + @Bean + public ConsumerFactory consumerFactory() { + Map props = new HashMap<>(); + // 设置Kafka服务器地址 + props.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, bootstrapServers); + // 设置消费者组ID + props.put(ConsumerConfig.GROUP_ID_CONFIG, groupId); + // 设置key反序列化器 + props.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class); + // 设置value反序列化器 + props.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class); + // 设置偏移量重置策略为earliest + props.put(ConsumerConfig.AUTO_OFFSET_RESET_CONFIG, "earliest"); + // 禁用自动提交 + props.put(ConsumerConfig.ENABLE_AUTO_COMMIT_CONFIG, false); + // 设置单次拉取最大记录数 + props.put(ConsumerConfig.MAX_POLL_RECORDS_CONFIG, 500); + // 设置最大拉取间隔时间 + props.put(ConsumerConfig.MAX_POLL_INTERVAL_MS_CONFIG, 300000); + // 设置会话超时时间 + props.put(ConsumerConfig.SESSION_TIMEOUT_MS_CONFIG, 60000); + // 设置心跳间隔时间 + props.put(ConsumerConfig.HEARTBEAT_INTERVAL_MS_CONFIG, 20000); + return new DefaultKafkaConsumerFactory<>(props); + } + + /** + * 配置Kafka监听器容器工厂 + * 设置并发度、确认模式等参数 + * + * @return ConcurrentKafkaListenerContainerFactory 监听器容器工厂实例 + */ + @Bean + public ConcurrentKafkaListenerContainerFactory kafkaListenerContainerFactory() { + ConcurrentKafkaListenerContainerFactory factory = + new ConcurrentKafkaListenerContainerFactory<>(); + // 设置消费者工厂 + factory.setConsumerFactory(consumerFactory()); + // 设置并发度为1 + factory.setConcurrency(1); + // 设置手动确认模式 + factory.getContainerProperties().setAckMode(org.springframework.kafka.listener.ContainerProperties.AckMode.MANUAL_IMMEDIATE); + return factory; + } +} diff --git a/ruoyi-modules/hwmom-dp/src/main/java/org/dromara/dp/kafka/service/KafkaConsumerService.java b/ruoyi-modules/hwmom-dp/src/main/java/org/dromara/dp/kafka/service/KafkaConsumerService.java index 782fc34..30ae90c 100644 --- a/ruoyi-modules/hwmom-dp/src/main/java/org/dromara/dp/kafka/service/KafkaConsumerService.java +++ b/ruoyi-modules/hwmom-dp/src/main/java/org/dromara/dp/kafka/service/KafkaConsumerService.java @@ -1,13 +1,353 @@ package org.dromara.dp.kafka.service; +import jakarta.annotation.PostConstruct; +import lombok.extern.slf4j.Slf4j; +import org.apache.kafka.clients.consumer.ConsumerRecord; +import org.dromara.dp.service.DataProcessService; +import org.dromara.dp.service.DeviceAlarmService; +import org.dromara.dp.service.DeviceStatusService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; import org.springframework.kafka.annotation.KafkaListener; +import org.springframework.kafka.support.Acknowledgment; +import org.springframework.kafka.support.KafkaHeaders; +import org.springframework.messaging.handler.annotation.Header; import org.springframework.stereotype.Service; +import org.springframework.util.StringUtils; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicLong; + +/** + * Kafka消费者服务 + * 用于处理从Kafka接收到的消息 + * + * @author hwmom + * @since 2024-04-02 + */ +@Slf4j @Service public class KafkaConsumerService { - @KafkaListener(topics = "test", groupId = "my-consumer-group") - public void listen(String message) { - System.out.println("Received message: " + message); + /** + * 数据处理服务 + */ + @Autowired + private DataProcessService dataProcessService; + + /** + * 设备状态服务 + */ + @Autowired + private DeviceStatusService deviceStatusService; + + /** + * 设备告警服务 + */ + @Autowired + private DeviceAlarmService deviceAlarmService; + + /** + * 消息计数器 + * 用于统计成功处理的消息数量 + */ + private final AtomicLong messageCounter = new AtomicLong(0); + + /** + * 错误计数器 + * 用于统计处理失败的消息数量 + */ + private final AtomicLong errorCounter = new AtomicLong(0); + + /** + * 最大重试次数 + */ + private static final int MAX_RETRY_ATTEMPTS = 3; + + /** + * 重试延迟时间(毫秒) + */ + private static final long RETRY_DELAY_MS = 1000; + + /** + * 设备数据主题 + */ + @Value("${spring.kafka.topic.device-data:device-data}") + private String deviceDataTopic; + + /** + * 设备状态主题 + */ + @Value("${spring.kafka.topic.device-status:device-status}") + private String deviceStatusTopic; + + /** + * 设备告警主题 + */ + @Value("${spring.kafka.topic.device-alarm:device-alarm}") + private String deviceAlarmTopic; + + /** + * 消费者组ID + * 从配置文件中读取,默认为my-consumer-group + */ + @Value("${spring.kafka.consumer.group-id:my-consumer-group}") + private String groupId; + + /** + * 服务初始化 + * 在服务启动时执行 + */ + @PostConstruct + public void init() { + log.info("Kafka消费者服务初始化完成,监听主题: device-data={}, device-status={}, device-alarm={}", + deviceDataTopic, deviceStatusTopic, deviceAlarmTopic); } + + /** + * 监听设备数据主题 + * 处理设备数据消息 + * + * @param record 消息记录 + * @param ack 确认对象 + * @param topic 主题 + * @param partition 分区 + * @param offset 偏移量 + */ + @KafkaListener( + topics = "${spring.kafka.topic.device-data:device-data}", // 监听设备数据主题 + groupId = "${spring.kafka.consumer.group-id:my-consumer-group}", // 消费者组ID + containerFactory = "kafkaListenerContainerFactory", // 容器工厂 + autoStartup = "true", // 自动启动 + concurrency = "1" // 并发度 + ) + public void listenDeviceData( + ConsumerRecord record, + Acknowledgment ack, + @Header(KafkaHeaders.RECEIVED_TOPIC) String topic, + @Header(KafkaHeaders.RECEIVED_PARTITION) int partition, + @Header(KafkaHeaders.OFFSET) long offset + ) { + String message = record.value(); + String key = record.key(); + long timestamp = record.timestamp(); + + log.info("收到设备数据消息 - Topic: {}, Partition: {}, Offset: {}, Key: {}, Timestamp: {}, Message: {}", + topic, partition, offset, key, timestamp, message); + + try { + // 消息内容验证 + if (!StringUtils.hasText(message)) { + throw new IllegalArgumentException("消息内容不能为空"); + } + + // 处理消息 + boolean processed = processDeviceData(message, key); + + if (processed) { + // 更新统计信息 + messageCounter.incrementAndGet(); + + // 确认消息 + ack.acknowledge(); + + log.debug("设备数据消息处理成功 - Topic: {}, Key: {}", topic, key); + } else { + // 更新错误计数 + errorCounter.incrementAndGet(); + log.warn("设备数据消息处理失败 - Topic: {}, Key: {}", topic, key); + } + } catch (Exception e) { + // 更新错误计数 + errorCounter.incrementAndGet(); + log.error("设备数据消息处理失败 - Topic: {}, Key: {}, Error: {}", topic, key, e.getMessage(), e); + } + } + + /** + * 监听设备状态主题 + * 处理设备状态消息 + * + * @param record 消息记录 + * @param ack 确认对象 + * @param topic 主题 + * @param partition 分区 + * @param offset 偏移量 + */ + @KafkaListener( + topics = "${spring.kafka.topic.device-status:device-status}", // 监听设备状态主题 + groupId = "${spring.kafka.consumer.group-id:my-consumer-group}", // 消费者组ID + containerFactory = "kafkaListenerContainerFactory", // 容器工厂 + autoStartup = "true", // 自动启动 + concurrency = "1" // 并发度 + ) + public void listenDeviceStatus( + ConsumerRecord record, + Acknowledgment ack, + @Header(KafkaHeaders.RECEIVED_TOPIC) String topic, + @Header(KafkaHeaders.RECEIVED_PARTITION) int partition, + @Header(KafkaHeaders.OFFSET) long offset + ) { + String message = record.value(); + String key = record.key(); + long timestamp = record.timestamp(); + + log.info("收到设备状态消息 - Topic: {}, Partition: {}, Offset: {}, Key: {}, Timestamp: {}, Message: {}", + topic, partition, offset, key, timestamp, message); + + try { + // 消息内容验证 + if (!StringUtils.hasText(message)) { + throw new IllegalArgumentException("消息内容不能为空"); + } + + // 处理消息 + boolean processed = processDeviceStatus(message, key); + + if (processed) { + // 更新统计信息 + messageCounter.incrementAndGet(); + + // 确认消息 + ack.acknowledge(); + + log.debug("设备状态消息处理成功 - Topic: {}, Key: {}", topic, key); + } else { + // 更新错误计数 + errorCounter.incrementAndGet(); + log.warn("设备状态消息处理失败 - Topic: {}, Key: {}", topic, key); + } + } catch (Exception e) { + // 更新错误计数 + errorCounter.incrementAndGet(); + log.error("设备状态消息处理失败 - Topic: {}, Key: {}, Error: {}", topic, key, e.getMessage(), e); + } + } + + /** + * 监听设备告警主题 + * 处理设备告警消息 + * + * @param record 消息记录 + * @param ack 确认对象 + * @param topic 主题 + * @param partition 分区 + * @param offset 偏移量 + */ + @KafkaListener( + topics = "${spring.kafka.topic.device-alarm:device-alarm}", // 监听设备告警主题 + groupId = "${spring.kafka.consumer.group-id:my-consumer-group}", // 消费者组ID + containerFactory = "kafkaListenerContainerFactory", // 容器工厂 + autoStartup = "true", // 自动启动 + concurrency = "1" // 并发度 + ) + public void listenDeviceAlarm( + ConsumerRecord record, + Acknowledgment ack, + @Header(KafkaHeaders.RECEIVED_TOPIC) String topic, + @Header(KafkaHeaders.RECEIVED_PARTITION) int partition, + @Header(KafkaHeaders.OFFSET) long offset + ) { + String message = record.value(); + String key = record.key(); + long timestamp = record.timestamp(); + + log.info("收到设备告警消息 - Topic: {}, Partition: {}, Offset: {}, Key: {}, Timestamp: {}, Message: {}", + topic, partition, offset, key, timestamp, message); + + try { + // 消息内容验证 + if (!StringUtils.hasText(message)) { + throw new IllegalArgumentException("消息内容不能为空"); + } + + // 处理消息 + boolean processed = processDeviceAlarm(message, key); + + if (processed) { + // 更新统计信息 + messageCounter.incrementAndGet(); + + // 确认消息 + ack.acknowledge(); + + log.debug("设备告警消息处理成功 - Topic: {}, Key: {}", topic, key); + } else { + // 更新错误计数 + errorCounter.incrementAndGet(); + log.warn("设备告警消息处理失败 - Topic: {}, Key: {}", topic, key); + } + } catch (Exception e) { + // 更新错误计数 + errorCounter.incrementAndGet(); + log.error("设备告警消息处理失败 - Topic: {}, Key: {}, Error: {}", topic, key, e.getMessage(), e); + } + } + + /** + * 处理设备数据消息 + * 实现具体的设备数据消息处理逻辑 + * + * @param message 消息内容 + * @param key 消息键 + * @return 处理结果 + */ + private boolean processDeviceData(String message, String key) { + try { + // 调用数据处理服务处理消息 + return dataProcessService.processData(message); + } catch (Exception e) { + log.error("设备数据消息处理异常 - Key: {}, Message: {}, Error: {}", key, message, e.getMessage(), e); + throw e; + } + } + + /** + * 处理设备状态消息 + * 实现具体的设备状态消息处理逻辑 + * + * @param message 消息内容 + * @param key 消息键 + * @return 处理结果 + */ + private boolean processDeviceStatus(String message, String key) { + try { + // 调用设备状态服务处理消息 + // 这里假设设备状态服务有一个处理状态消息的方法 + // 如果没有,需要根据实际情况调整 + return deviceStatusService.updateDeviceStatus(key, message); + } catch (Exception e) { + log.error("设备状态消息处理异常 - Key: {}, Message: {}, Error: {}", key, message, e.getMessage(), e); + throw e; + } + } + + /** + * 处理设备告警消息 + * 实现具体的设备告警消息处理逻辑 + * + * @param message 消息内容 + * @param key 消息键 + * @return 处理结果 + */ + private boolean processDeviceAlarm(String message, String key) { + try { + // 调用设备告警服务处理告警消息 + boolean processed = deviceAlarmService.handleDeviceAlarm(key, message); + + if (processed) { + // 记录告警处理日志 + log.info("设备告警处理成功 - deviceId: {}, alarmData: {}", key, message); + return true; + } else { + log.warn("设备告警处理失败 - deviceId: {}, alarmData: {}", key, message); + return false; + } + } catch (Exception e) { + log.error("设备告警消息处理异常 - deviceId: {}, alarmData: {}, error: {}", + key, message, e.getMessage(), e); + throw e; + } + } + } diff --git a/ruoyi-modules/hwmom-dp/src/main/java/org/dromara/dp/service/DataProcessService.java b/ruoyi-modules/hwmom-dp/src/main/java/org/dromara/dp/service/DataProcessService.java new file mode 100644 index 0000000..f98733d --- /dev/null +++ b/ruoyi-modules/hwmom-dp/src/main/java/org/dromara/dp/service/DataProcessService.java @@ -0,0 +1,21 @@ +package org.dromara.dp.service; + +/** + * 数据处理服务接口 + * 定义数据处理相关的操作方法 + * + * @author hwmom + * @since 2024-04-03 + */ +public interface DataProcessService { + + /** + * 处理数据 + * 对接收到的数据进行处理 + * + * @param data 待处理的数据 + * @return 处理结果 + */ + boolean processData(String data); + +} diff --git a/ruoyi-modules/hwmom-dp/src/main/java/org/dromara/dp/service/DeviceAlarmService.java b/ruoyi-modules/hwmom-dp/src/main/java/org/dromara/dp/service/DeviceAlarmService.java new file mode 100644 index 0000000..1e4a1ff --- /dev/null +++ b/ruoyi-modules/hwmom-dp/src/main/java/org/dromara/dp/service/DeviceAlarmService.java @@ -0,0 +1,23 @@ +package org.dromara.dp.service; + + +/** + * 设备告警服务接口 + * 定义设备告警相关的操作方法 + * + * @author hwmom + * @since 2024-04-03 + */ +public interface DeviceAlarmService { + + /** + * 处理设备告警 + * 处理指定设备的告警信息 + * + * @param deviceId 设备ID + * @param alarmData 告警数据 + * @return 处理是否成功 + */ + boolean handleDeviceAlarm(String deviceId, String alarmData); + +} diff --git a/ruoyi-modules/hwmom-dp/src/main/java/org/dromara/dp/service/DeviceStatusService.java b/ruoyi-modules/hwmom-dp/src/main/java/org/dromara/dp/service/DeviceStatusService.java new file mode 100644 index 0000000..8c91505 --- /dev/null +++ b/ruoyi-modules/hwmom-dp/src/main/java/org/dromara/dp/service/DeviceStatusService.java @@ -0,0 +1,23 @@ +package org.dromara.dp.service; + +/** + * 设备状态存储服务接口 + * 定义设备状态相关的操作方法 + * + * @author hwmom + * @since 2024-04-03 + */ +public interface DeviceStatusService { + + /** + * 更新设备状态 + * 更新指定设备的状态信息 + * + * @param deviceId 设备ID + * @param statusData 状态数据 + * @return 更新是否成功 + */ + boolean updateDeviceStatus(String deviceId, String statusData); + + +} diff --git a/ruoyi-modules/hwmom-dp/src/main/java/org/dromara/dp/service/impl/DataProcessServiceImpl.java b/ruoyi-modules/hwmom-dp/src/main/java/org/dromara/dp/service/impl/DataProcessServiceImpl.java new file mode 100644 index 0000000..3bc48fb --- /dev/null +++ b/ruoyi-modules/hwmom-dp/src/main/java/org/dromara/dp/service/impl/DataProcessServiceImpl.java @@ -0,0 +1,103 @@ +package org.dromara.dp.service.impl; + +import lombok.extern.slf4j.Slf4j; +import org.dromara.dp.service.DataProcessService; +import org.springframework.stereotype.Service; + +import java.util.concurrent.atomic.AtomicLong; + +/** + * 数据处理服务实现类 + * 用于处理从Kafka接收到的数据,进行数据清洗、转换和存储 + * + * @author hwmom + * @since 2024-04-03 + */ +@Slf4j +@Service +public class DataProcessServiceImpl implements DataProcessService { + + /** + * 数据处理计数器 + */ + private final AtomicLong processCounter = new AtomicLong(0); + + /** + * 数据处理错误计数器 + */ + private final AtomicLong errorCounter = new AtomicLong(0); + + /** + * 处理数据 + * 对接收到的数据进行处理 + * + * @param data 待处理的数据 + * @return 处理结果 + */ + @Override + public boolean processData(String data) { + if (data == null || data.isEmpty()) { + log.warn("接收到空数据,无法处理"); + errorCounter.incrementAndGet(); + return false; + } + + try { + log.info("开始处理数据: {}", data); + // 数据验证 + if (!validateData(data)) { + log.warn("数据验证失败: {}", data); + errorCounter.incrementAndGet(); + return false; + } + + // 数据存储 + boolean stored = storeData(data); + + if (stored) { + processCounter.incrementAndGet(); + log.info("数据处理成功: {}", data); + return true; + } else { + log.warn("数据存储失败: {}", data); + errorCounter.incrementAndGet(); + return false; + } + } catch (Exception e) { + log.error("数据处理异常: {}, 错误: {}", data, e.getMessage(), e); + errorCounter.incrementAndGet(); + return false; + } + } + + /** + * 数据验证 + * 验证数据是否符合处理要求 + * + * @param data 待验证的数据 + * @return 验证结果 + */ + private boolean validateData(String data) { + return true; + } + + /** + * 数据存储 + * 将处理后的数据存储到目标系统 + * + * @param data 待存储的数据 + * @return 存储结果 + */ + private boolean storeData(String data) { + try { + // 这里可以实现数据存储逻辑 + // 例如:存储到数据库、文件系统或其他存储系统 + + return true; + } catch (Exception e) { + log.error("数据存储异常: {}", e.getMessage(), e); + return false; + } + } + +} diff --git a/ruoyi-modules/hwmom-dp/src/main/java/org/dromara/dp/service/impl/DeviceAlarmServiceImpl.java b/ruoyi-modules/hwmom-dp/src/main/java/org/dromara/dp/service/impl/DeviceAlarmServiceImpl.java new file mode 100644 index 0000000..38acebb --- /dev/null +++ b/ruoyi-modules/hwmom-dp/src/main/java/org/dromara/dp/service/impl/DeviceAlarmServiceImpl.java @@ -0,0 +1,34 @@ +package org.dromara.dp.service.impl; + +import lombok.extern.slf4j.Slf4j; +import org.dromara.dp.service.DeviceAlarmService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.stereotype.Service; + +import java.util.*; +import java.util.concurrent.TimeUnit; + +/** + * 设备告警服务实现类 + * 实现设备告警相关的操作方法 + * + * @author hwmom + * @since 2024-04-03 + */ +@Slf4j +@Service +public class DeviceAlarmServiceImpl implements DeviceAlarmService { + + @Override + public boolean handleDeviceAlarm(String deviceId, String alarmData) { + try { + return true; + } catch (Exception e) { + log.error("设备告警处理失败 - deviceId: {}, alarmData: {}, error: {}", + deviceId, alarmData, e.getMessage(), e); + return false; + } + } + +} diff --git a/ruoyi-modules/hwmom-dp/src/main/java/org/dromara/dp/service/impl/DeviceStatusServiceImpl.java b/ruoyi-modules/hwmom-dp/src/main/java/org/dromara/dp/service/impl/DeviceStatusServiceImpl.java new file mode 100644 index 0000000..db94883 --- /dev/null +++ b/ruoyi-modules/hwmom-dp/src/main/java/org/dromara/dp/service/impl/DeviceStatusServiceImpl.java @@ -0,0 +1,22 @@ +package org.dromara.dp.service.impl; + +import lombok.extern.slf4j.Slf4j; +import org.dromara.dp.service.DeviceStatusService; +import org.springframework.stereotype.Service; + + +/** + * 设备状态服务实现类 + * + * @author hwmom + * @since 2024-04-03 + */ +@Slf4j +@Service +public class DeviceStatusServiceImpl implements DeviceStatusService { + + @Override + public boolean updateDeviceStatus(String deviceId, String statusData) { + return false; + } +} diff --git a/ruoyi-modules/hwmom-dp/src/main/java/org/dromara/service/DataProcessServiceImpl.java b/ruoyi-modules/hwmom-dp/src/main/java/org/dromara/service/DataProcessServiceImpl.java deleted file mode 100644 index 6e0219f..0000000 --- a/ruoyi-modules/hwmom-dp/src/main/java/org/dromara/service/DataProcessServiceImpl.java +++ /dev/null @@ -1,685 +0,0 @@ -//package org.dromara.service; -// -//import com.alibaba.fastjson.JSON; -//import com.alibaba.fastjson.JSONArray; -//import com.alibaba.fastjson.JSONObject; -//import com.aliyun.auth.credentials.Credential; -//import com.aliyun.auth.credentials.provider.StaticCredentialProvider; -//import com.aliyun.sdk.service.dysmsapi20170525.AsyncClient; -//import com.aliyun.sdk.service.dysmsapi20170525.models.SendSmsRequest; -//import com.aliyun.sdk.service.dysmsapi20170525.models.SendSmsResponse; -//import com.ruoyi.common.core.constant.HwDictConstants; -//import com.ruoyi.common.core.constant.SecurityConstants; -//import com.ruoyi.common.core.constant.TdEngineConstants; -//import com.ruoyi.common.core.domain.R; -//import com.ruoyi.common.core.enums.ResultEnums; -//import com.ruoyi.common.core.utils.RegexUtils; -//import com.ruoyi.common.core.utils.StringUtils; -//import com.ruoyi.dataprocess.amap.LocationVo; -//import com.ruoyi.dataprocess.amap.PositionUtils; -//import com.ruoyi.dataprocess.amap.PositionVo; -//import com.ruoyi.dataprocess.common.ImageUtils; -//import com.ruoyi.dataprocess.domain.*; -//import com.ruoyi.dataprocess.mapper.*; -//import com.ruoyi.dataprocess.service.CommanHandleService; -//import com.ruoyi.dataprocess.service.IDataProcessService; -//import com.ruoyi.tdengine.api.RemoteTdEngineService; -//import com.ruoyi.tdengine.api.domain.TdField; -//import com.ruoyi.tdengine.api.domain.TdHistorySelectDto; -//import com.ruoyi.tdengine.api.domain.TdReturnDataVo; -//import com.ruoyi.tdengine.api.domain.TdTableVo; -//import darabonba.core.client.ClientOverrideConfiguration; -//import org.apache.commons.codec.binary.Base64; -//import org.apache.poi.openxml4j.exceptions.InvalidOperationException; -//import org.slf4j.Logger; -//import org.slf4j.LoggerFactory; -//import org.springframework.beans.factory.annotation.Autowired; -//import org.springframework.stereotype.Service; -// -//import javax.annotation.Resource; -//import javax.script.ScriptEngine; -//import javax.script.ScriptEngineManager; -//import java.io.IOException; -//import java.math.BigDecimal; -//import java.text.SimpleDateFormat; -//import java.util.*; -//import java.util.concurrent.CompletableFuture; -//import java.util.concurrent.ExecutionException; -//import java.util.concurrent.atomic.AtomicBoolean; -//import java.util.stream.Collectors; -// -///** -// * @Description: 数据处理业务类 -// * @ClassName: DataProcessServiceImpl -// * @Author : xins -// * @Date :2023-09-04 8:58 -// * @Version :1.0 -// */ -//@Service -//public class DataProcessServiceImpl extends CommanHandleService implements IDataProcessService { -// -// private static final Logger logger = LoggerFactory.getLogger(DataProcessServiceImpl.class); -// -// private final String AccessKeyId = "LTAI5tPoTQHh8HHst2toxtGa"; -// private final String AccessKeySecret = "K8OIuSNgsSnpGMJ2PdqIJFYyUqL38m"; -// -// @Resource -// private RemoteTdEngineService remoteTdEngineService; -// -// @Autowired -// private HwDeviceMapper hwDeviceMapper; -// -// @Autowired -// private HwElectronicFenceMapper hwElectronicFenceMapper; -// -// @Autowired -// private HwFenceAreaMapper hwFenceAreaMapper; -// -// @Autowired -// private HwAlarmInfoMapper hwAlarmInfoMapper; -// -// @Autowired -// private HwAlarmRuleMapper hwAlarmRuleMapper; -// -// /** -// * @param: jsonData -// * @param: imagePath ruoyifile的上传地址 -// * @param: imagePatterns -// * @param: imageDomain ruoyifile的domain -// * @param: imagePrefix ruoyifile的prefix -// * @param: topic 发布主题,用来获取网关设备devicecode -// * @description -// * @author xins -// * @date 2023-08-31 16:16 -// */ -// @Override -// public int processBusinessData(String jsonData, String imagePath, -// String imagePatterns, String imageDomain, String imagePrefix, String topic) { -// JSONObject json = JSON.parseObject(jsonData); -// Long ts = json.getLong(TdEngineConstants.PAYLOAD_TS); -// String tsStr = String.valueOf(ts); -// if (tsStr.length() == 10) { -// ts = ts * 1000; -// } -// JSONArray paramArr = json.getJSONArray(TdEngineConstants.PAYLOAD_PARAM); -//// System.out.println(this.hwDeviceMapper); -//// System.out.println(this.remoteTdEngineService); -// String deviceCode = ""; -// for (int i = 0; i < paramArr.size(); i++) { -// try { -// JSONObject paramJson = paramArr.getJSONObject(i); -// String dataType = paramJson.getString(TdEngineConstants.PAYLOAD_DATATYPE); -// JSONObject dataValueJson = paramJson.getJSONObject(TdEngineConstants.PAYLOAD_DATAVALUE); -// deviceCode = dataValueJson.getString(TdEngineConstants.PAYLOAD_DEVICE_CODE).toLowerCase(); -// //deviceCode = getUidByParam(json); -// HwDevice hwDevice = hwDeviceMapper.selectHwDeviceByDeviceCode(deviceCode); -// if (hwDevice == null) { -// logger.error("此设备【deviceCode:{}】不存在", deviceCode); -// continue; -// } -// if (hwDevice.getDeviceStatus().equals(HwDictConstants.DEVICE_STATUS_DELETE)) { -// logger.error("此设备【deviceCode:{}】已删除", deviceCode); -// continue; -// } -// -// Long sceneId = hwDevice.getSceneId(); -// Long deviceId = hwDevice.getDeviceId(); -// Long monitorUnitId = hwDevice.getMonitorUnitId(); -// Long tenantId = hwDevice.getTenantId(); -// String databaseName = TdEngineConstants.getDatabaseName(); -// String tableName = TdEngineConstants.DEFAULT_TABLE_NAME_PREFIX + deviceId; -// -// dataValueJson.remove(TdEngineConstants.PAYLOAD_DEVICE_CODE); -// TdTableVo tdTableVo = new TdTableVo(); -// List schemaFields = new ArrayList<>(); -// List alarmSchemaFields = new ArrayList<>(); -// -// //添加timestamp字段,默认字段名称是ts,协议上传的key是timestamp -// TdField firstTdField = new TdField(); -// firstTdField.setFieldName(TdEngineConstants.DEFAULT_FIRST_FIELD_NAME); -// long currentTimeMillis = System.currentTimeMillis(); -// firstTdField.setFieldValue(currentTimeMillis); -//// firstTdField.setFieldValue(ts); -// schemaFields.add(firstTdField); -// -// Object longitude = null; -// Object latitude = null; -// -// for (Map.Entry entry : dataValueJson.entrySet()) { -// String originalKey = entry.getKey();//原来的key -// Object value = entry.getValue(); -// -// /** -// * 先对key进行转换,例如对于key是value的需要转换成value1; -// */ -// String key = TdEngineConstants.TDENGINE_KEY_TRANSFER_MAP.get(originalKey) == null ? originalKey -// : TdEngineConstants.TDENGINE_KEY_TRANSFER_MAP.get(originalKey); -// -// if (key.equalsIgnoreCase(TdEngineConstants.PAYLOAD_DEVICE_DATA_TYPE_TYPE)) { -// continue; -// } -// -// -// if (value instanceof String) { -// String valueStr = (String) value; -// if (StringUtils.isNotBlank(valueStr)) { -// /** -// * 先判读是否是图片,并获取图片名称, 获取到证明是图片 -// */ -// String[] imagePatternArr = imagePatterns.split(","); -// String extension = ImageUtils.getImageType(valueStr, imagePatternArr); -// if (StringUtils.isNotBlank(extension) && valueStr.length() > 300) { -// //保存图片,并返回图片详细地址进行赋值保存 -// value = getImageFileName(imagePath, imageDomain, imagePrefix, valueStr, deviceId, extension); -// if (value == null) continue; -// } else if (dataType.equalsIgnoreCase(TdEngineConstants.PAYLOAD_DEVICE_DATA_TYPE_IMAGE)) { -// if (ImageUtils.checkIsBase64(valueStr) && valueStr.length() > 300) {//判断没有加前缀的情况 -// String type = dataValueJson.getString(TdEngineConstants.PAYLOAD_DEVICE_DATA_TYPE_TYPE); -// if (type == null) { -// type = dataValueJson.getString(TdEngineConstants.PAYLOAD_DEVICE_DATA_TYPE_TYPE_FIRSET_UPPER); -// } -// extension = "jpg"; -// if (type != null) { -// extension = StringUtils.isNotBlank(ImageUtils.getImageType(type, imagePatternArr)) -// ? ImageUtils.getImageType(type, imagePatternArr) : extension; -// } -// value = getImageFileName(imagePath, imageDomain, imagePrefix, valueStr, deviceId, extension); -// if (value == null) continue; -// } -// } -// -// TdField tdField = new TdField(); -// tdField.setFieldName(key); -// tdField.setFieldValue(value); -// schemaFields.add(tdField); -// } -// } else { -// TdField tdField = new TdField(); -// tdField.setFieldName(key); -// tdField.setFieldValue(value); -// schemaFields.add(tdField); -// -// //经纬度判断 -// if (key.equalsIgnoreCase(HwDictConstants.DEFAULT_FUNCTION_LONGITUDE_IDENTIFIER)) { -// longitude = value; -// } else if (key.equalsIgnoreCase(HwDictConstants.DEFAULT_FUNCTION_LATITUDE_IDENTIFIER)) { -// latitude = value; -// } else { -// TdField alarmTdField = new TdField(); -// alarmTdField.setFieldName(originalKey); -// alarmTdField.setFieldValue(value); -// alarmSchemaFields.add(alarmTdField); -// } -// } -// } -// -// tdTableVo.setDatabaseName(databaseName); -// tdTableVo.setTableName(tableName); -// tdTableVo.setSchemaFields(schemaFields); -// -// final R insertResult = this.remoteTdEngineService.insertTable(tdTableVo , SecurityConstants.INNER); -// if (insertResult.getCode() == ResultEnums.SUCCESS.getCode()) { -// logger.info("Insert data result: {}", insertResult.getCode()); -// } else { -// logger.error("Insert data Exception: {},data:{}", insertResult.getMsg(), jsonData); -// } -// -// //校验电子围栏 -// if (longitude != null && latitude != null) { -// checkElectronicFence(deviceId, tenantId, monitorUnitId, sceneId, longitude, latitude, ts); -// } -// -// //校验设备报警信息 -// checkAlarm(deviceId, alarmSchemaFields, tenantId, sceneId, monitorUnitId, topic, deviceCode); -// -// } catch (Exception e) { -// e.printStackTrace(); -// logger.error("deviceCode:{},errorMsg:{},data:{}", deviceCode, e.getMessage(), jsonData); -// } -// } -// -// return paramArr.size(); -// } -// -// /** -// * 获取设备UID -// * @param jsonStr -// * @return -// */ -// private String getUidByParam(JSONObject jsonStr){ -// -// JSONObject jsonObject = new JSONObject(jsonStr); -// -// JSONArray paramArray = jsonObject.getJSONArray("param"); -// -// JSONObject firstParamObject = paramArray.getJSONObject(0); -// -// JSONObject datavalueObject = firstParamObject.getJSONObject("datavalue"); -// -// String uid = datavalueObject.getString("uid"); -// -// return uid; -// } -// -// -// private static String getImageFileName(String imagePath, String imageDomain, String imagePrefix, String valueStr, Long deviceId, String extension) { -// try { -// String imageFileName = ImageUtils.convertBase64ToImage(imagePath, -// valueStr, "device" + deviceId, extension); -// return imageDomain + imagePrefix + imageFileName; -// -// } catch (IOException e) { -// logger.error("转换图片错误:" + e.getMessage(), e); -// } -// return null; -// } -// -// -// /** -// * @param: deviceId -// * @param: monitorUnitId -// * @param: sceneId -// * @param: longitude -// * @param: latitude -// * @param: ts -// * @description 校验此设备电子围栏 -// * @author xins -// * @date 2023-09-04 14:04 -// */ -// private void checkElectronicFence(Long deviceId, Long tenantId, Long monitorUnitId, Long sceneId, Object longitude, Object latitude, Long ts) { -// //根据设备ID、监控单元ID和场景ID获取所有的电子围栏配置。(目前先只支持场景) -//// List hwElectronicFences = hwElectronicFenceMapper.selectElectronicFencesByDeviceId(deviceId); -//// hwElectronicFences = hwElectronicFenceMapper.selectElectronicFencesByMonitorUnitId(monitorUnitId); -// List hwElectronicFences = hwElectronicFenceMapper.selectElectronicFencesBySceneId(sceneId); -// -// if (StringUtils.isNotEmpty(hwElectronicFences)) { -// for (HwElectronicFence hwElectronicFence : hwElectronicFences) { -// HwFenceArea queryFenceArea = new HwFenceArea(); -// queryFenceArea.setElectronicFenceId(hwElectronicFence.getElectronicFenceId()); -// //获取电子围栏下配置的区域列表 -// List fenceAreas = hwFenceAreaMapper.selectHwFenceAreaList(queryFenceArea); -// String effectiveTimeFlag = hwElectronicFence.getEffectiveTimeFlag(); -// String triggerStatus = hwElectronicFence.getTriggerStatus(); -// if (fenceAreas != null && !fenceAreas.isEmpty()) { -// fenceAreas.forEach(fenceArea -> { -// boolean isAlarmed = false;//是否报警 -// if (effectiveTimeFlag.equals(HwDictConstants.EFFECTIVE_TIME_FLAG_LONG)) { -// String areaShapeFlag = fenceArea.getAreaShapeFlag(); -// String areaRange = fenceArea.getAreaRange(); -// //多边形处理 -// if (areaShapeFlag.equals(HwDictConstants.AREA_SHAPE_FLAG_POLYGN)) { -// LocationVo polygonVo = new LocationVo(); -// polygonVo.setMarkerType(LocationVo.MARKER_TYPE_POLYGON); -// List> polygonList = new ArrayList<>(); -// List postionList = new ArrayList<>(); -// String[] areaRangeArr = areaRange.split("_");//多个点,每个点的经纬度信息(经度_纬度) -// for (String areaRange1 : areaRangeArr) { -// String[] areaRange1Arr = areaRange1.split(","); -// String longitudeStr = areaRange1Arr[0]; -// String latitudeStr = areaRange1Arr[1]; -// postionList.add(new PositionVo(new BigDecimal(longitudeStr), new BigDecimal(latitudeStr))); -// polygonList.add(postionList); -// } -// -// polygonVo.setPolygonList(polygonList); -// -// /** -// * 传入的longitude和latitude是object类型,本身有可能是BigDecimal,Double,Long和Integer,先转成String再转成Double -// */ -// boolean isWithin = PositionUtils.checkAddressInLocation(polygonVo, Double.valueOf(String.valueOf(longitude)), Double.valueOf(String.valueOf(latitude))); -// if (triggerStatus.equals(HwDictConstants.ELECTRONIC_FENCE_TRIGGER_STATUS_EXIT) && !isWithin) {//如果电子围栏配置是出界,而此设备出界则报警 -// isAlarmed = true; -// } else if (triggerStatus.equals(HwDictConstants.ELECTRONIC_FENCE_TRIGGER_STATUS_ENTRY) && isWithin) {//如果电子围栏配置是入界,而此设备入界则报警 -// isAlarmed = true; -// } -// -// } else if (areaShapeFlag.equals(HwDictConstants.AREA_SHAPE_FLAG_CIRCULA)) {//圆形处理 -// String[] areaRangeArr = areaRange.split(","); -// String longitudeStr = areaRangeArr[0]; -// String latitudeStr = areaRangeArr[1]; -// String radiusStr = areaRangeArr[2]; -// LocationVo circulrVo = new LocationVo(); -// circulrVo.setRadius(Double.valueOf(radiusStr)); -// circulrVo.setLongitude(Double.valueOf(longitudeStr)); -// circulrVo.setLatitude(Double.valueOf(latitudeStr)); -// circulrVo.setMarkerType(LocationVo.MARKER_TYPE_CIRCULAR); -// boolean isWithin = PositionUtils.checkAddressInLocation(circulrVo, Double.valueOf(String.valueOf(longitude)), Double.valueOf(String.valueOf(latitude))); -// if (triggerStatus.equals(HwDictConstants.ELECTRONIC_FENCE_TRIGGER_STATUS_EXIT) && !isWithin) {//如果电子围栏配置是出界,而此设备出界则报警 -// isAlarmed = true; -// } else if (triggerStatus.equals(HwDictConstants.ELECTRONIC_FENCE_TRIGGER_STATUS_ENTRY) && isWithin) {//如果电子围栏配置是入界,而此设备入界则报警 -// isAlarmed = true; -// } -// } -// } -// -// if (isAlarmed) { -// HwAlarmInfo hwAralmInfo = new HwAlarmInfo(); -// hwAralmInfo.setAlarmInfoType(HwDictConstants.ALARM_INFO_TYPE_ELECTRONIC_FENCE); -// hwAralmInfo.setAlarmReleatedId(hwElectronicFence.getElectronicFenceId()); -// hwAralmInfo.setDeviceId(deviceId); -// hwAralmInfo.setMonitorUnitId(monitorUnitId); -// hwAralmInfo.setTenantId(tenantId); -// hwAralmInfo.setSceneId(sceneId); -// hwAralmInfo.setFunctionValue(longitude + "_" + latitude); -// hwAralmInfo.setTriggerStatus(triggerStatus); -// hwAralmInfo.setAlarmTime(new Date(ts)); -// hwAralmInfo.setCreateTime(new Date()); -// hwAralmInfo.setFenceAreaId(fenceArea.getFenceAreaId()); -// hwAlarmInfoMapper.insertHwAlarmInfo(hwAralmInfo); -// } -// }); -// } -// } -// } -// } -// -// -// /** -// * @param: deviceId -// * @param: alarmFields -// * @description 校验报警 -// * @author xins -// * @date 2023-11-07 10:15 -// */ -// private void checkAlarm(Long deviceId, List alarmFields, -// Long tenantId, Long sceneId, Long monitorUnitId, String topic, String subDeviceCode) { -// -// try { -// HwAlarmRule queryAlarmRule = new HwAlarmRule(); -// queryAlarmRule.setRuleDeviceId(deviceId); -// queryAlarmRule.setRuleType(HwDictConstants.ALARM_RULE_RULE_TYPE_DEVICE); -// queryAlarmRule.setAlarmRuleStatus(HwDictConstants.ALARM_RULE_STATUS_ENABLE); -// List alarmRules = hwAlarmRuleMapper.selectHwAlarmRulesWithLink(queryAlarmRule); -// -// ScriptEngineManager manager = new ScriptEngineManager(); -// ScriptEngine engine = manager.getEngineByName("js"); -// -// if (alarmRules != null) { -// Date currentDate = new Date(); -// for (HwAlarmRule alarmRule : alarmRules) { -// String triggerExpression = alarmRule.getTriggerExpression() -// .replaceAll("and", "&&") -// .replaceAll("or", "||"); -// AtomicBoolean isAlarmed = new AtomicBoolean(false); -// List alarmDetails = new ArrayList(); -// -// for (TdField alarmField : alarmFields) { -// String fieldName = alarmField.getFieldName(); -// Object filedValue = alarmField.getFieldValue(); -// if (triggerExpression.contains("{" + fieldName + "}")) { -// isAlarmed.set(true); -// -// /** -// * Add By 获取五分钟内的数据 WenJY 2024-07-03 14:13:21 -// */ -// if(alarmRule.getTriggerTimeFrame() != null && alarmRule.getTriggerTimeFrame() > 0){ -// double difValue = FilterDeviceValue(deviceId, fieldName, alarmRule.getTriggerTimeFrame()); -//// if(difValue > 0){ -//// filedValue = difValue; -//// } -// filedValue = difValue; -// } -// /** End **/ -// -// triggerExpression = triggerExpression.replaceAll("\\{" + fieldName + "\\}", String.valueOf(filedValue)); -// HwAlarmDetail alarmDetail = new HwAlarmDetail(); -// alarmDetail.setDeviceId(deviceId); -// alarmDetail.setFunctionIdentifier(fieldName); -// alarmDetail.setFunctionValue(String.valueOf(filedValue)); -// alarmDetail.setMonitorTime(currentDate); -// alarmDetails.add(alarmDetail); -// -// } -// } -// -// if (isAlarmed.get() && !triggerExpression.contains("{") -// && RegexUtils.findSymbolInText(triggerExpression).size() > 0 -// && RegexUtils.findNumberInText(triggerExpression).size() > 0) { -// -// Boolean triggerExpressionBool = (Boolean) engine.eval(triggerExpression); -// if (triggerExpressionBool) { -// HwAlarmInfo alarmInfo = new HwAlarmInfo(); -// alarmInfo.setAlarmInfoType(HwDictConstants.ALARM_INFO_TYPE_DEVICE); -// alarmInfo.setAlarmReleatedId(alarmRule.getAlarmRuleId()); -// alarmInfo.setDeviceId(deviceId); -// alarmInfo.setMonitorUnitId(monitorUnitId); -// alarmInfo.setTenantId(tenantId); -// alarmInfo.setSceneId(sceneId); -// alarmInfo.setAlarmLevelId(alarmRule.getAlarmLevelId()); -// alarmInfo.setAlarmTypeId(alarmRule.getAlarmTypeId()); -// alarmInfo.setHwAlarmDetailList(alarmDetails); -// alarmInfo.setHandleStatus(HwDictConstants.ALARM_HANDLE_STATUS_NO); -// alarmInfo.setCreateTime(currentDate); -// alarmInfo.setAlarmTime(currentDate); -// hwAlarmInfoMapper.insertHwAlarmInfo(alarmInfo); -// this.insertHwAlarmDetail(alarmInfo); -// this.handleAlarmLink(alarmRule, topic, subDeviceCode); -// /** -// * Add By WenJY 下发报警信息 -// */ -// if(StringUtils.isNotEmpty(alarmRule.getPhoneNumbers())){ -// SendAlarmInfoBySms(deviceId,alarmRule); -// }else { -// logger.warn("设备:{};报警信息发送失败,联系方式为空",deviceId); -// } -// break; -// } -// } -// } -// } -// }catch (Exception e){ -// logger.error("设备:{};报警逻辑处理异常:{}",deviceId,e.getMessage()); -// } -// } -// -// /** -// * 过滤指定时间段内的数据,返回最大最小的差值,过滤0 -// * @param deviceId -// * @param fieldName -// * @param triggerTimeFrame -// * @return 差值 -// */ -// private double FilterDeviceValue(Long deviceId,String fieldName,long triggerTimeFrame){ -// double differenceValue = 0.00; -// String databaseName = TdEngineConstants.getDatabaseName(); -// String tableName = TdEngineConstants.DEFAULT_TABLE_NAME_PREFIX + deviceId; -// long currentTimeMillis = System.currentTimeMillis(); -// long fiveMinutesInMillis = triggerTimeFrame * 60 * 1000; -// long beforeTimeMillis = currentTimeMillis - fiveMinutesInMillis; -// -// TdHistorySelectDto tdHistorySelectDto = new TdHistorySelectDto(); -// tdHistorySelectDto.setDatabaseName(databaseName); -// tdHistorySelectDto.setTableName(tableName); -// tdHistorySelectDto.setStartTime(beforeTimeMillis); -// tdHistorySelectDto.setEndTime(currentTimeMillis); -// tdHistorySelectDto.setFirstFieldName("ts"); -// R result = this.remoteTdEngineService.getHistoryData(tdHistorySelectDto , SecurityConstants.INNER); -// -// if (result.getCode() == ResultEnums.SUCCESS.getCode()) { -// logger.info("Get history data result: {}", result.getCode()); -// -// TdReturnDataVo data = (TdReturnDataVo) result.getData(); -// -// List> dataList = data.getDataList(); -// List value = dataList.stream().map(map -> (Double)map.get("value1")).distinct().filter(x -> x > 0).collect(Collectors.toList()); -// -// System.out.println(triggerTimeFrame +"分钟内数据:"+JSONArray.toJSON(value) ); -// -// OptionalDouble maxOptional = value.stream().mapToDouble(Double::doubleValue).max(); -// OptionalDouble minOptional = value.stream().mapToDouble(Double::doubleValue).min(); -// -// if (maxOptional.isPresent() && minOptional.isPresent()) { -// double maxValue = maxOptional.getAsDouble(); -// double minValue = minOptional.getAsDouble(); -// differenceValue = maxValue - minValue; -// System.out.println("Difference between max and min values: " + differenceValue); -// } else { -// System.out.println("No values found to calculate difference."); -// } -// -// } else { -// logger.error("Get history data Exception: {}", result.getMsg()); -// } -// -// return differenceValue; -// -// } -// -// /** -// * 新增报警详情信息信息 -// * -// * @param hwAlarmInfo 报警信息对象 -// */ -// private void insertHwAlarmDetail(HwAlarmInfo hwAlarmInfo) { -// List hwAlarmDetailList = hwAlarmInfo.getHwAlarmDetailList(); -// Long alarmInfoId = hwAlarmInfo.getAlarmInfoId(); -// if (StringUtils.isNotNull(hwAlarmDetailList)) { -// List list = new ArrayList(); -// for (HwAlarmDetail hwAlarmDetail : hwAlarmDetailList) { -// hwAlarmDetail.setAlarmInfoId(alarmInfoId); -// list.add(hwAlarmDetail); -// } -// if (list.size() > 0) { -// hwAlarmInfoMapper.batchHwAlarmDetail(list); -// } -// } -// } -// -// /** -// * @param: alarmRule -// * @param: topic -// * @param: subDeviceCode -// * @description 处理报警规则联动设备 -// * @author xins -// * @date 2023-11-07 16:39 -// */ -// private void handleAlarmLink(HwAlarmRule alarmRule, String topic, String subDeviceCode) { -// String controlCommandTopic = topic.replace(HwDictConstants.TOPIC_TYPE_DATA_POSTFIX, HwDictConstants.TOPIC_TYPE_COMMAND_POSTFIX); -// if (alarmRule.getLinkFlag().equals(HwDictConstants.ALARM_RULE_LINK_FLAG_YES)) { -// List alarmRuleLinks = alarmRule.getHwAlarmRuleLinkList(); -// alarmRuleLinks.forEach(alarmRuleLink -> { -// this.publishControlCommand(controlCommandTopic, subDeviceCode, alarmRuleLink.getLinkDeviceFunctionIdentifier()); -// }); -// } -// } -// -// @Override -// public void testBase64(String jsonData, String imagePath, String imagePatterns, String imageDomain, String imagePrefix) { -// JSONObject json = JSON.parseObject(jsonData); -// Object value = json.get("base64"); -// if (value instanceof String) { -// -// String valueStr = (String) value; -// System.out.println(Base64.isBase64(valueStr)); -// if (StringUtils.isNotBlank(valueStr)) { -// /** -// * 先判读是否是图片,并获取图片名称, 获取到证明是图片 -// */ -// String[] imagePatternArr = imagePatterns.split(","); -// String extension = ImageUtils.getImageType(valueStr, imagePatternArr); -// if (StringUtils.isNotBlank(extension)) { -// //保存图片,并返回图片详细地址进行赋值保存 -// Long deviceId = 100L; -// String imageFileName = null; -// try { -// imageFileName = ImageUtils.convertBase64ToImage(imagePath, -// valueStr, "device" + deviceId, extension); -// if (StringUtils.isNotBlank(imageFileName)) { -// String url = imageDomain + imagePrefix + imageFileName; -// System.out.println(url); -// } -// } catch (IOException e) { -// throw new RuntimeException(e); -// } -// -// } -// } -// } -// } -// -// /** -// * 发送报警短信 -// * @param deviceId -// * @param alarmRule -// */ -// private void SendAlarmInfoBySms(Long deviceId,HwAlarmRule alarmRule){ -// try { -// HwDevice hwDevice = hwDeviceMapper.GetDeviceById(deviceId); -// if(hwDevice != null){ -// AlarmMsgTemplateParam alarmMsgTemplateParam = new AlarmMsgTemplateParam(); -// alarmMsgTemplateParam.setWarning(alarmRule.getAlarmRuleName()); -// alarmMsgTemplateParam.setParentname(hwDevice.getMonitorUnitName()); -// alarmMsgTemplateParam.setSensorID(deviceId.toString()); -// AliSmsHandle(alarmRule.getPhoneNumbers(),alarmMsgTemplateParam); -// } -// } catch (ExecutionException | InterruptedException e) { -// throw new InvalidOperationException(String.format("报警信息发送异常:%e",e.getMessage())); -// } -// } -// -// /** -// * 报警短信推送 -// * @param phoneNumbers -// * @param alarmMsgTemplateParam -// * @throws ExecutionException -// * @throws InterruptedException -// */ -// private void AliSmsHandle(String phoneNumbers,AlarmMsgTemplateParam alarmMsgTemplateParam ) throws ExecutionException, InterruptedException { -// StaticCredentialProvider provider = StaticCredentialProvider.create(Credential.builder() -// .accessKeyId(AccessKeyId) -// .accessKeySecret(AccessKeySecret) -// .build()); -// -// AsyncClient client = AsyncClient.builder() -// .region("cn-shenzhen") // Region ID -// .credentialsProvider(provider) -// .overrideConfiguration( -// ClientOverrideConfiguration.create() -// .setEndpointOverride("dysmsapi.aliyuncs.com") -// ) -// .build(); -// -// String jsonString = com.alibaba.fastjson2.JSONArray.toJSONString(alarmMsgTemplateParam); -// -// SendSmsRequest sendSmsRequest = SendSmsRequest.builder() -// .phoneNumbers(phoneNumbers) -// .signName("深圳市金瑞铭科技") -// .templateCode("SMS_468740027") -// .templateParam(jsonString) -// .build(); -// logger.info("向:{};发送报警信息:{}",phoneNumbers,jsonString); -// CompletableFuture response = client.sendSms(sendSmsRequest); -// SendSmsResponse resp = response.get(); -// -// client.close(); -// } -// -// -// public static void main(String[] args) { -// System.out.println(System.currentTimeMillis()); -// SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd"); -// Date date = new Date(); -// System.out.println(format.format(date)); -// Object jsonData = "{\n" + -// "\n" + -// " \"timestamp\": 1689814424,\"type\": \"CMD_REPORTDATA\",\n" + -// " \"param\": [\n{\n" + -// " \"datatype\": \"cttemperature\",\n" + -// "\"datavalue\": {\n" + -// " \"uid\": \"0009340109040126\", \"alias\": \"\",\n" + -// " \"value\": 25.6,\n" + -// " \"voltage\": 3.76,\n" + -// " \"rssi\": -80\n" + -// " } },\n" + -// " {\"datatype\": \"cttemperature\",\n" + -// " \"datavalue\": {\n" + -// " \"uid1\": \"00093440109040924\",\n" + -// " \"alias\": \"\",\n" + -// " \"value\": 25.6,\n" + -// " \"voltage\": 3.64,\n" + -// " \"rssi\": -87\n" + -// " }\n" + -// " }]}"; -// -// } -//} diff --git a/ruoyi-modules/hwmom-dp/src/main/java/org/dromara/service/DeviceStatusServiceImpl.java b/ruoyi-modules/hwmom-dp/src/main/java/org/dromara/service/DeviceStatusServiceImpl.java deleted file mode 100644 index eb3b851..0000000 --- a/ruoyi-modules/hwmom-dp/src/main/java/org/dromara/service/DeviceStatusServiceImpl.java +++ /dev/null @@ -1,178 +0,0 @@ -//package org.dromara.service; -// -//import com.alibaba.fastjson.JSON; -//import com.alibaba.fastjson.JSONObject; -//import com.ruoyi.common.core.constant.HwDictConstants; -//import com.ruoyi.common.core.constant.SecurityConstants; -//import com.ruoyi.common.core.constant.TdEngineConstants; -//import com.ruoyi.common.core.domain.R; -//import com.ruoyi.common.core.utils.StringUtils; -//import com.ruoyi.dataprocess.domain.*; -//import com.ruoyi.dataprocess.mapper.HwAlarmInfoMapper; -//import com.ruoyi.dataprocess.mapper.HwDeviceMapper; -//import com.ruoyi.dataprocess.mapper.HwOfflineRuleMapper; -//import com.ruoyi.dataprocess.service.CommanHandleService; -//import com.ruoyi.dataprocess.service.IDeviceStatusService; -//import com.ruoyi.tdengine.api.RemoteTdEngineService; -//import com.ruoyi.tdengine.api.domain.DeviceStatus; -//import com.ruoyi.tdengine.api.domain.TdField; -//import com.ruoyi.tdengine.api.domain.TdTableVo; -//import org.springframework.beans.factory.annotation.Autowired; -//import org.springframework.stereotype.Service; -// -//import javax.annotation.Resource; -//import java.util.ArrayList; -//import java.util.Date; -//import java.util.List; -//import java.util.Map; -// -///** -// * @Description: 设备状态处理服务 -// * @ClassName: DeviceStatusServiceImpl -// * @Author : xins -// * @Date :2023-09-12 15:31 -// * @Version :1.0 -// */ -//@Service -//public class DeviceStatusServiceImpl extends CommanHandleService implements IDeviceStatusService { -// -// @Autowired -// private HwDeviceMapper hwDeviceMapper; -// @Autowired -// private HwOfflineRuleMapper hwOfflineRuleMapper; -// @Autowired -// private HwAlarmInfoMapper hwAlarmInfoMapper; -// @Resource -// private RemoteTdEngineService remoteTdEngineService; -// -// @Override -// public void handleDeviceStatus(String payloadString, String clientId) { -//// ddd:{"msg":"设备设备连接状态信息","deviceType":"edge","connectStatus":1, -//// "statusTime":1694506127199,"deviceCode":"hw-data-process-1"} -// JSONObject json = JSON.parseObject(payloadString); -// String deviceCode = json.getString("deviceCode").toLowerCase(); -// if (clientId.equals(deviceCode)) { //校验是不是自己,如果是自己则不记录状态,返回即可。 -// return; -// } -// HwDevice hwDevice = hwDeviceMapper.selectHwDeviceByDeviceCode(deviceCode); -// if (hwDevice != null) { -// Long deviceId = hwDevice.getDeviceId(); -// TdTableVo tdTableVo = new TdTableVo(); -// tdTableVo.setDatabaseName(TdEngineConstants.PLATFORM_DB_NAME); -// tdTableVo.setTableName(TdEngineConstants.DEFAULT_DEVICE_STATUS_TABLE_NAME_PREFIX + deviceId); -// -// List schemaFields = new ArrayList<>(); -// TdField onlineStatusField = new TdField(); -// onlineStatusField.setFieldName(TdEngineConstants.ST_TAG_ONLINESTATUS); -// onlineStatusField.setFieldValue(json.getInteger("connectStatus")); -// schemaFields.add(onlineStatusField); -// -// TdField deviceTypeField = new TdField(); -// deviceTypeField.setFieldName(TdEngineConstants.ST_TAG_DEVICETYPE); -// deviceTypeField.setFieldValue(json.getString("deviceType")); -// schemaFields.add(deviceTypeField); -// -// TdField tsField = new TdField(); -// tsField.setFieldName(TdEngineConstants.DEFAULT_FIRST_FIELD_NAME); -// tsField.setFieldValue(json.getLong("statusTime")); -// schemaFields.add(tsField); -// -// tdTableVo.setSchemaFields(schemaFields); -// -// this.remoteTdEngineService.insertTable(tdTableVo, SecurityConstants.INNER); -// -// //更新设备当前状态信息 -// String connectStatus = String.valueOf(json.getInteger("connectStatus")); -// hwDevice.setOnlineStatus(connectStatus); -// //判断如果是否是第一次连接,更新激活状态和激活时间。 -// if (hwDevice.getActiveStatus().equals(HwDictConstants.DEVICE_ACTIVE_STATUS_INACTIVE)) { -// hwDevice.setActiveStatus(HwDictConstants.DEVICE_ACTIVE_STATUS_ACTIVE); -// hwDevice.setActiveTime(new Date()); -// } -// -// hwDeviceMapper.updateHwDevice(hwDevice); -// -// if (connectStatus.equals(HwDictConstants.DEVICE_ONLINE_STATUS_OFFLINE)) { -// this.checkOfflineAlarm(hwDevice); -// } -// -// } -// } -// -// -// /** -// * @param: device -// * @description 离线报警处理 -// * @author xins -// * @date 2023-11-14 16:01 -// */ -// private void checkOfflineAlarm(HwDevice device) { -// Long deviceId = device.getDeviceId(); -// Long sceneId = device.getSceneId(); -// -// HwOfflineRule offlineRule = hwOfflineRuleMapper.selectHwOfflineRuleByDeviceId(deviceId); -// if (offlineRule == null) { -// offlineRule = hwOfflineRuleMapper.selectHwOfflineRuleBySceneId(sceneId); -// } -// -// if (offlineRule != null) { -// Long offlineNumberTime = offlineRule.getOfflineNumberTime();//分钟 -// Long offlineNumber = offlineRule.getOfflineNumber(); -// -// if (offlineNumber > 1) { -// Long currentTime = System.currentTimeMillis(); -// Long startTime = currentTime - offlineNumberTime * 60 * 1000; -// DeviceStatus queryDeviceStatus = new DeviceStatus(); -// queryDeviceStatus.setDeviceId(deviceId); -// queryDeviceStatus.setStartTime(startTime); -// queryDeviceStatus.setEndTime(currentTime); -// queryDeviceStatus.setOnlineStatus(0); -// -// R>> deviceStatusListR = this.remoteTdEngineService.getDeviceStatusList(queryDeviceStatus, SecurityConstants.INNER); -// List> deviceStatusList = deviceStatusListR.getData(); -// //在几分钟时间内离线几次的报警信息保存 -// if (deviceStatusList != null && deviceStatusList.size() > offlineNumber) { -// insertHwAlarmInfo(device, offlineRule, deviceId); -// } -// } else {//只要离线就报警 -// insertHwAlarmInfo(device, offlineRule, deviceId); -// } -// } -// } -// -// private void insertHwAlarmInfo(HwDevice device, HwOfflineRule offlineRule, Long deviceId) { -// Date currentDate = new Date(); -// -// HwAlarmInfo alarmInfo = new HwAlarmInfo(); -// alarmInfo.setAlarmInfoType(HwDictConstants.ALARM_INFO_TYPE_OFFLINE); -// alarmInfo.setAlarmReleatedId(offlineRule.getOfflineRuleId()); -// alarmInfo.setDeviceId(deviceId); -// alarmInfo.setTenantId(device.getTenantId()); -// alarmInfo.setSceneId(device.getSceneId()); -// alarmInfo.setMonitorUnitId(device.getMonitorUnitId()); -// alarmInfo.setAlarmLevelId(offlineRule.getAlarmLevelId()); -// alarmInfo.setHandleStatus(HwDictConstants.ALARM_HANDLE_STATUS_NO); -// alarmInfo.setAlarmTime(currentDate); -// alarmInfo.setCreateTime(currentDate); -// hwAlarmInfoMapper.insertHwAlarmInfo(alarmInfo); -// this.handleAlarmLink(offlineRule, device.getDeviceCode()); -// } -// -// /** -// * @param: offlineRule -// * @param: deviceCode -// * @description 处理报警规则联动设备 -// * @author xins -// * @date 2023-11-07 16:39 -// */ -// private void handleAlarmLink(HwOfflineRule offlineRule, String deviceCode) { -// String controlCommandTopic = StringUtils -// .format(HwDictConstants.CONTROL_COMMAND_TOPIC_VALUE, deviceCode); -// if (offlineRule.getLinkFlag().equals(HwDictConstants.ALARM_RULE_LINK_FLAG_YES)) { -// List offlineRuleLinks = offlineRule.getHwAlarmRuleLinkList(); -// offlineRuleLinks.forEach(offlineRuleLink -> { -// this.publishControlCommand(controlCommandTopic, deviceCode, offlineRuleLink.getLinkDeviceFunctionIdentifier()); -// }); -// } -// } -//} diff --git a/ruoyi-modules/hwmom-dp/src/main/resources/application.yml b/ruoyi-modules/hwmom-dp/src/main/resources/application.yml index 6c724a1..a713956 100644 --- a/ruoyi-modules/hwmom-dp/src/main/resources/application.yml +++ b/ruoyi-modules/hwmom-dp/src/main/resources/application.yml @@ -2,24 +2,24 @@ server: port: 9603 -mqtt: - client: - ip: 127.0.0.1 # mqtt server ip地址 - port: 1883 # mqtt server 端口 - clientId: hw-data-process-1 # 客户端ID,保证唯一 - username: mica # mqtt server 认证用户名 - password: mica # mqtt server 认证密码 - timeout: 10 - keepalive: 20 - qos : 1 # qos服务质量等级,0最多交付一次,1至少交付一次,2只交付一次 - dataTopicFilter: /v1/# # 订阅的处理设备上报数据的topic - deviceStatusTopic: /device/status/v1 # 订阅的处理设备状态的topic - #domain: http://127.0.0.1:9665 # 文件服务地址 - #path: D:/ruoyi/uploadPath # base64图片转换保存的路径 - domain: http://175.27.215.92:9665 # 文件服务地址 - path: /home/ruoyi/uploadPath # base64图片转换保存的路径 - prefix: /statics - imagePatterns: jpg,jpeg,png #支持的图片格式 +#mqtt: +# client: +# ip: 127.0.0.1 # mqtt server ip地址 +# port: 1883 # mqtt server 端口 +# clientId: hw-data-process-1 # 客户端ID,保证唯一 +# username: mica # mqtt server 认证用户名 +# password: mica # mqtt server 认证密码 +# timeout: 10 +# keepalive: 20 +# qos : 1 # qos服务质量等级,0最多交付一次,1至少交付一次,2只交付一次 +# dataTopicFilter: /v1/# # 订阅的处理设备上报数据的topic +# deviceStatusTopic: /device/status/v1 # 订阅的处理设备状态的topic +# #domain: http://127.0.0.1:9665 # 文件服务地址 +# #path: D:/ruoyi/uploadPath # base64图片转换保存的路径 +# domain: http://175.27.215.92:9665 # 文件服务地址 +# path: /home/ruoyi/uploadPath # base64图片转换保存的路径 +# prefix: /statics +# imagePatterns: jpg,jpeg,png #支持的图片格式 # Spring spring: @@ -56,7 +56,15 @@ spring: - optional:nacos:${spring.application.name}.yml kafka: - bootstrap-servers: localhost:9092 + bootstrap-servers: 119.45.202.115:9092 producer: key-serializer: org.apache.kafka.common.serialization.StringSerializer value-serializer: org.apache.kafka.common.serialization.StringSerializer + consumer: + group-id: my-consumer-group + key-deserializer: org.apache.kafka.common.serialization.StringDeserializer + value-deserializer: org.apache.kafka.common.serialization.StringDeserializer + topic: + device-data: device-data + device-status: device-status + device-alarm: device-alarm diff --git a/ruoyi-modules/hwmom-mqtt/src/main/java/com/hw/mqtt/domain/DeviceInfoDto.java b/ruoyi-modules/hwmom-mqtt/src/main/java/com/hw/mqtt/domain/DeviceInfoDto.java index c03e5e6..6943149 100644 --- a/ruoyi-modules/hwmom-mqtt/src/main/java/com/hw/mqtt/domain/DeviceInfoDto.java +++ b/ruoyi-modules/hwmom-mqtt/src/main/java/com/hw/mqtt/domain/DeviceInfoDto.java @@ -13,7 +13,7 @@ import lombok.Data; public class DeviceInfoDto { /** - * 设备编号,ClientId + * 设备编号,prod_base_machine_info的machine_code */ private String deviceCode; diff --git a/ruoyi-modules/hwmom-mqtt/src/main/java/com/hw/mqtt/enums/ConnectStatus.java b/ruoyi-modules/hwmom-mqtt/src/main/java/com/hw/mqtt/enums/ConnectStatus.java index 84d68a9..b56fcb0 100644 --- a/ruoyi-modules/hwmom-mqtt/src/main/java/com/hw/mqtt/enums/ConnectStatus.java +++ b/ruoyi-modules/hwmom-mqtt/src/main/java/com/hw/mqtt/enums/ConnectStatus.java @@ -17,7 +17,7 @@ public enum ConnectStatus { /** * 设备连接 */ - connct(1), + connect(1), /** * 设备断开 diff --git a/ruoyi-modules/hwmom-mqtt/src/main/java/com/hw/mqtt/listener/MqttConnectStatusListener.java b/ruoyi-modules/hwmom-mqtt/src/main/java/com/hw/mqtt/listener/MqttConnectStatusListener.java index fa78dfb..00a2825 100644 --- a/ruoyi-modules/hwmom-mqtt/src/main/java/com/hw/mqtt/listener/MqttConnectStatusListener.java +++ b/ruoyi-modules/hwmom-mqtt/src/main/java/com/hw/mqtt/listener/MqttConnectStatusListener.java @@ -30,19 +30,22 @@ import org.springframework.beans.factory.SmartInitializingSingleton; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.ApplicationContext; import org.springframework.data.redis.core.StringRedisTemplate; +import org.springframework.retry.annotation.Backoff; +import org.springframework.retry.annotation.Retryable; import org.springframework.stereotype.Service; +import org.springframework.util.StringUtils; import org.tio.core.ChannelContext; import java.nio.charset.StandardCharsets; import java.util.HashMap; import java.util.Map; +import java.util.concurrent.TimeUnit; /** - * 状态监听器 - * 性能损失小 + * MQTT 连接状态监听器 + * 负责处理设备上下线状态变更,并将状态信息推送到指定主题 * @author WenJY * @date 2023-03-14 12:17 - * @return null */ @Service public class MqttConnectStatusListener implements IMqttConnectStatusListener, SmartInitializingSingleton, DisposableBean { @@ -66,21 +69,38 @@ public class MqttConnectStatusListener implements IMqttConnectStatusListener, Sm @Override public void online(ChannelContext context, String clientId, String username) { - logger.info("Mqtt clientId:{} username:{} online.", clientId, username); - redisTemplate.opsForSet().add(getRedisKey(), clientId); - pushConnectStatus(clientId,ConnectStatus.connct); + if (!StringUtils.hasText(clientId)) { + logger.warn("Invalid clientId received in online event"); + return; + } + + try { + logger.info("MQTT设备上线 - clientId: {}, username: {}", clientId, username); + redisTemplate.opsForSet().add(getRedisKey(), clientId); + pushConnectStatus(clientId, ConnectStatus.connect, null); + } catch (Exception e) { + logger.error("处理设备上线事件失败 - clientId: {}, error: {}", clientId, e.getMessage(), e); + } } @Override public void offline(ChannelContext context, String clientId, String username, String reason) { - logger.info("Mqtt clientId:{} username:{} offline reason:{}.", clientId, username, reason); - redisTemplate.opsForSet().remove(getRedisKey(), clientId); - pushConnectStatus(clientId,ConnectStatus.disconnect); + if (!StringUtils.hasText(clientId)) { + logger.warn("Invalid clientId received in offline event"); + return; + } + + try { + logger.info("MQTT设备离线 - clientId: {}, username: {}, reason: {}", clientId, username, reason); + redisTemplate.opsForSet().remove(getRedisKey(), clientId); + pushConnectStatus(clientId, ConnectStatus.disconnect, reason); + } catch (Exception e) { + logger.error("处理设备离线事件失败 - clientId: {}, error: {}", clientId, e.getMessage(), e); + } } /** - * 设备上下线存储,key 的值为 前缀:nodeName - * + * 获取设备上下线状态存储的Redis key * @return redis key */ private String getRedisKey() { @@ -89,39 +109,90 @@ public class MqttConnectStatusListener implements IMqttConnectStatusListener, Sm @Override public void afterSingletonsInstantiated() { - this.serverCreator = context.getBean(MqttServerCreator.class); - this.mqttServerTemplate = context.getBean(MqttServerTemplate.class); + try { + this.serverCreator = context.getBean(MqttServerCreator.class); + this.mqttServerTemplate = context.getBean(MqttServerTemplate.class); + logger.info("MQTT连接状态监听器初始化完成"); + } catch (Exception e) { + logger.error("MQTT连接状态监听器初始化失败", e); + throw e; + } } @Override public void destroy() throws Exception { - // 停机时删除集合 - redisTemplate.opsForSet().remove(getRedisKey()); + try { + String redisKey = getRedisKey(); + redisTemplate.delete(redisKey); + logger.info("MQTT连接状态监听器销毁完成,已清理Redis数据"); + } catch (Exception e) { + logger.error("MQTT连接状态监听器销毁失败", e); + throw e; + } } /** - * 推送设备状态到指定主题 - * @param clientId - * @param connectStatus + * 推送设备连接状态到指定主题 + * @param clientId 设备ID + * @param connectStatus 连接状态 + * @param reason 离线原因(仅在离线时有效) */ - public void pushConnectStatus(String clientId, ConnectStatus connectStatus){ - if(publishConnectStatusEnable){ - Map entityMap = new HashMap<>(); - entityMap.put("msg","设备设备连接状态信息"); - entityMap.put("deviceType", DeviceType.edge.getKey()); - entityMap.put("deviceCode",clientId); - entityMap.put("connectStatus",connectStatus.getKey()); - entityMap.put("statusTime",System.currentTimeMillis()); - String jsonString = JSONArray.toJSONString(entityMap); - boolean result = mqttServerTemplate.publishAll(publishConnectStatusTopic, jsonString.getBytes(StandardCharsets.UTF_8)); - if(result){ - logger.info("客户端:"+clientId+";"+ (connectStatus == ConnectStatus.connct ? "连接" :"断开") +"状态推送成功"); - }else { - logger.info("客户端:"+clientId+";"+ (connectStatus == ConnectStatus.connct ? "连接" :"断开") +"状态推送失败"); - } - }else { - logger.info("未开启设备连接状态推送"); + private void pushConnectStatus(String clientId, ConnectStatus connectStatus, String reason) { + if (!publishConnectStatusEnable) { + logger.debug("设备连接状态推送功能未启用"); + return; } + try { + // 检查MQTT服务器状态 + if (!isMqttServerAvailable()) { + logger.error("MQTT服务器不可用,无法推送设备状态"); + return; + } + + Map statusInfo = new HashMap<>(); + statusInfo.put("msg", "设备连接状态信息"); + statusInfo.put("deviceType", DeviceType.edge.getKey()); + statusInfo.put("deviceCode", clientId); + statusInfo.put("connectStatus", connectStatus.getKey()); + statusInfo.put("statusTime", System.currentTimeMillis()); + statusInfo.put("nodeName", serverCreator.getNodeName()); + + // 添加离线原因 + if (connectStatus == ConnectStatus.disconnect && reason != null) { + statusInfo.put("disconnectReason", reason); + } + + String payload = JSONArray.toJSONString(statusInfo); + boolean success = mqttServerTemplate.publishAll( + "device/" + clientId + "/status", + payload.getBytes(StandardCharsets.UTF_8) + ); + + if (success) { + logger.info("设备状态推送成功 - clientId: {}, status: {}", + clientId, connectStatus == ConnectStatus.connect ? "连接" : "断开"); + } else { + logger.warn("设备状态推送失败 - clientId: {}, status: {}", + clientId, connectStatus == ConnectStatus.connect ? "连接" : "断开"); + } + } catch (Exception e) { + logger.error("推送设备状态异常 - clientId: {}, error: {}", clientId, e.getMessage(), e); + throw e; // 触发重试机制 + } + } + + /** + * 检查MQTT服务器是否可用 + */ + private boolean isMqttServerAvailable() { + try { + // 这里可以添加MQTT服务器状态检查逻辑 + // 例如:检查连接数、检查服务器响应等 + return true; + } catch (Exception e) { + logger.error("MQTT服务器状态检查失败", e); + return false; + } } } diff --git a/ruoyi-modules/hwmom-mqtt/src/main/java/com/hw/mqtt/listener/MqttServerMessageListener.java b/ruoyi-modules/hwmom-mqtt/src/main/java/com/hw/mqtt/listener/MqttServerMessageListener.java index eb136a6..95314fd 100644 --- a/ruoyi-modules/hwmom-mqtt/src/main/java/com/hw/mqtt/listener/MqttServerMessageListener.java +++ b/ruoyi-modules/hwmom-mqtt/src/main/java/com/hw/mqtt/listener/MqttServerMessageListener.java @@ -1,7 +1,7 @@ package com.hw.mqtt.listener; -//import net.dreamlu.iot.mqtt.codec.ByteBufferUtil; - +import com.alibaba.fastjson2.JSON; +import com.alibaba.fastjson2.JSONObject; import net.dreamlu.iot.mqtt.codec.MqttPublishMessage; import net.dreamlu.iot.mqtt.codec.MqttQoS; import net.dreamlu.iot.mqtt.core.server.event.IMqttMessageListener; @@ -12,24 +12,50 @@ import org.springframework.beans.factory.SmartInitializingSingleton; import com.hw.mqtt.service.KafkaProducerService; import org.springframework.context.ApplicationContext; import org.springframework.stereotype.Service; +import org.springframework.util.StringUtils; import org.tio.core.ChannelContext; import java.nio.charset.StandardCharsets; +import java.util.HashMap; +import java.util.Map; +import java.util.regex.Pattern; /** - * 消息监听器 + * MQTT 消息监听器 + * 负责处理设备发送的消息,并将消息转发到 Kafka * * @author WenJY * @date 2023-03-14 12:18 - * @return null */ @Service public class MqttServerMessageListener implements IMqttMessageListener, SmartInitializingSingleton { private static final Logger logger = LoggerFactory.getLogger(MqttServerMessageListener.class); + private final ApplicationContext applicationContext; private MqttServerTemplate mqttServerTemplate; private final KafkaProducerService kafkaProducerService; + // 消息处理统计 + private final Map messageStats = new HashMap<>(); + + // MQTT主题到Kafka主题的映射规则 + private static final Map TOPIC_MAPPING = new HashMap<>(); + static { + // 设备数据主题映射 +号是设备编号 + TOPIC_MAPPING.put("device/+/data", "device-data"); + TOPIC_MAPPING.put("device/+/status", "device-status"); + TOPIC_MAPPING.put("device/+/alarm", "device-alarm"); + } + + // 编译主题匹配模式 + private static final Map TOPIC_PATTERNS = new HashMap<>(); + static { + TOPIC_MAPPING.forEach((mqttTopic, kafkaTopic) -> { + String pattern = mqttTopic.replace("+", "[^/]+"); + TOPIC_PATTERNS.put(mqttTopic, Pattern.compile(pattern)); + }); + } + public MqttServerMessageListener(ApplicationContext applicationContext, KafkaProducerService kafkaProducerService) { this.applicationContext = applicationContext; this.kafkaProducerService = kafkaProducerService; @@ -37,13 +63,107 @@ public class MqttServerMessageListener implements IMqttMessageListener, SmartIni @Override public void onMessage(ChannelContext context, String clientId, String topic, MqttQoS qos, MqttPublishMessage message) { - logger.info("context:{} clientId:{} message:{} payload:{}", context, clientId, message, new String(message.getPayload(), StandardCharsets.UTF_8)); - kafkaProducerService.sendMessage("test", new String(message.getPayload(), StandardCharsets.UTF_8)); + if (!StringUtils.hasText(clientId) || !StringUtils.hasText(topic)) { + logger.warn("收到无效消息 - clientId: {}, topic: {}", clientId, topic); + return; + } + + try { + // 记录消息接收时间 + long receiveTime = System.currentTimeMillis(); + + // 解析消息内容 + String payload = new String(message.getPayload(), StandardCharsets.UTF_8); + logger.info("收到MQTT消息 - clientId: {}, topic: {}, qos: {}, payload: {}", + clientId, topic, qos, payload); + + // 构建消息对象 + Map messageInfo = new HashMap<>(); + messageInfo.put("clientId", clientId); + messageInfo.put("topic", topic); + messageInfo.put("qos", qos.value()); + messageInfo.put("payload", payload); + messageInfo.put("receiveTime", receiveTime); + + // 尝试解析JSON + try { + JSONObject jsonPayload = JSON.parseObject(payload); + messageInfo.put("isJson", true); + messageInfo.put("jsonPayload", jsonPayload); + } catch (Exception e) { + messageInfo.put("isJson", false); + messageInfo.put("rawPayload", payload); + } + + // 发送到Kafka + String kafkaTopic = getKafkaTopic(topic); + String messageJson = JSON.toJSONString(messageInfo); + kafkaProducerService.sendMessage(kafkaTopic, messageJson); + + // 更新统计信息 + updateMessageStats(topic); + + // 记录处理完成时间 + long processTime = System.currentTimeMillis() - receiveTime; + logger.info("消息处理完成 - clientId: {}, topic: {}, processTime: {}ms", + clientId, topic, processTime); + + } catch (Exception e) { + logger.error("消息处理异常 - clientId: {}, topic: {}, error: {}", + clientId, topic, e.getMessage(), e); + } } @Override public void afterSingletonsInstantiated() { - // 单利 bean 初始化完成之后从 ApplicationContext 中获取 bean - mqttServerTemplate = applicationContext.getBean(MqttServerTemplate.class); + try { + mqttServerTemplate = applicationContext.getBean(MqttServerTemplate.class); + logger.info("MQTT消息监听器初始化完成"); + } catch (Exception e) { + logger.error("MQTT消息监听器初始化失败", e); + throw e; + } + } + + /** + * 根据MQTT主题获取对应的Kafka主题 + * @param mqttTopic MQTT主题 + * @return Kafka主题 + */ + private String getKafkaTopic(String mqttTopic) { + // 遍历主题映射规则 + for (Map.Entry entry : TOPIC_PATTERNS.entrySet()) { + if (entry.getValue().matcher(mqttTopic).matches()) { + String kafkaTopic = TOPIC_MAPPING.get(entry.getKey()); + logger.debug("MQTT主题映射到Kafka主题 - mqttTopic: {}, kafkaTopic: {}", mqttTopic, kafkaTopic); + return kafkaTopic; + } + } + + // 如果没有匹配的规则,使用默认主题 + String defaultTopic = "test"; + logger.warn("未找到匹配的主题映射规则,使用默认主题 - mqttTopic: {}, defaultTopic: {}", mqttTopic, defaultTopic); + return defaultTopic; + } + + /** + * 更新消息统计信息 + * @param topic 主题 + */ + private void updateMessageStats(String topic) { + messageStats.merge(topic, 1L, Long::sum); + + // 每处理1000条消息输出一次统计信息 + if (messageStats.get(topic) % 1000 == 0) { + logger.info("消息统计 - topic: {}, count: {}", topic, messageStats.get(topic)); + } + } + + /** + * 获取消息统计信息 + * @return 统计信息 + */ + public Map getMessageStats() { + return new HashMap<>(messageStats); } } diff --git a/ruoyi-modules/hwmom-mqtt/src/main/java/com/hw/mqtt/service/KafkaProducerService.java b/ruoyi-modules/hwmom-mqtt/src/main/java/com/hw/mqtt/service/KafkaProducerService.java index eff9e3f..b3dc7ef 100644 --- a/ruoyi-modules/hwmom-mqtt/src/main/java/com/hw/mqtt/service/KafkaProducerService.java +++ b/ruoyi-modules/hwmom-mqtt/src/main/java/com/hw/mqtt/service/KafkaProducerService.java @@ -1,19 +1,135 @@ package com.hw.mqtt.service; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.kafka.core.KafkaTemplate; +import org.springframework.kafka.support.SendResult; import org.springframework.stereotype.Service; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.TimeUnit; + +/** + * Kafka生产者服务 + * 负责将消息发送到Kafka集群 + * + * @author hwmom + * @since 2024-04-03 + */ @Service public class KafkaProducerService { + private static final Logger logger = LoggerFactory.getLogger(KafkaProducerService.class); + + /** + * 消息发送超时时间(秒) + */ + private static final int SEND_TIMEOUT_SECONDS = 10; + private final KafkaTemplate kafkaTemplate; public KafkaProducerService(KafkaTemplate kafkaTemplate) { this.kafkaTemplate = kafkaTemplate; } - public void sendMessage(String topic, String message) { - kafkaTemplate.send(topic, message); - System.out.println("Forwarded message to Kafka: " + message); + /** + * 发送消息到Kafka + * 异步发送,不等待结果 + * + * @param topic 主题 + * @param message 消息内容 + * @return 是否发送成功 + */ + public boolean sendMessage(String topic, String message) { + try { + // 使用CompletableFuture + CompletableFuture> future = kafkaTemplate.send(topic, message); + + // 添加回调处理 + future.whenComplete((result, ex) -> { + if (ex == null) { + logger.info("消息发送成功 - topic: {}, partition: {}, offset: {}", + topic, result.getRecordMetadata().partition(), result.getRecordMetadata().offset()); + } else { + logger.error("消息发送失败 - topic: {}, message: {}, error: {}", + topic, message, ex.getMessage(), ex); + } + }); + + logger.debug("消息已提交到Kafka - topic: {}, message: {}", topic, message); + return true; + } catch (Exception e) { + logger.error("消息发送异常 - topic: {}, message: {}, error: {}", + topic, message, e.getMessage(), e); + return false; + } + } + + /** + * 同步发送消息到Kafka + * 等待发送结果,超时抛出异常 + * + * @param topic 主题 + * @param message 消息内容 + * @return 发送结果 + */ + public SendResult sendMessageSync(String topic, String message) { + try { + // 使用CompletableFuture + CompletableFuture> future = kafkaTemplate.send(topic, message); + + // 等待结果,设置超时时间 + SendResult result = future.get(SEND_TIMEOUT_SECONDS, TimeUnit.SECONDS); + + logger.info("消息同步发送成功 - topic: {}, partition: {}, offset: {}", + topic, result.getRecordMetadata().partition(), result.getRecordMetadata().offset()); + + return result; + } catch (Exception e) { + logger.error("消息同步发送失败 - topic: {}, message: {}, error: {}", + topic, message, e.getMessage(), e); + throw new RuntimeException("Kafka消息同步发送失败", e); + } + } + + /** + * 带重试机制的消息发送 + * 发送失败时自动重试 + * + * @param topic 主题 + * @param message 消息内容 + * @return 发送结果 + */ + public SendResult sendMessageWithRetry(String topic, String message) { + int maxRetries = 3; + int retryCount = 0; + long retryDelayMs = 1000; + + while (retryCount < maxRetries) { + try { + return sendMessageSync(topic, message); + } catch (Exception e) { + retryCount++; + if (retryCount >= maxRetries) { + logger.error("消息发送重试失败,已达到最大重试次数 - topic: {}, message: {}, error: {}", + topic, message, e.getMessage(), e); + throw new RuntimeException("Kafka消息发送重试失败", e); + } + + logger.warn("消息发送失败,准备重试 - topic: {}, message: {}, 重试次数: {}, 错误: {}", + topic, message, retryCount, e.getMessage()); + + try { + // 指数退避策略 + Thread.sleep(retryDelayMs * (1L << (retryCount - 1))); + } catch (InterruptedException ie) { + Thread.currentThread().interrupt(); + throw new RuntimeException("重试等待被中断", ie); + } + } + } + + // 不应该到达这里,但为了编译通过 + throw new RuntimeException("Kafka消息发送失败"); } } diff --git a/ruoyi-modules/hwmom-mqtt/src/main/java/org/dromara/Main.java b/ruoyi-modules/hwmom-mqtt/src/main/java/org/dromara/Main.java deleted file mode 100644 index 7a72da2..0000000 --- a/ruoyi-modules/hwmom-mqtt/src/main/java/org/dromara/Main.java +++ /dev/null @@ -1,17 +0,0 @@ -package org.dromara; - -//TIP To Run code, press or -// click the icon in the gutter. -public class Main { - public static void main(String[] args) { - //TIP Press with your caret at the highlighted text - // to see how IntelliJ IDEA suggests fixing it. - System.out.printf("Hello and welcome!"); - - for (int i = 1; i <= 5; i++) { - //TIP Press to start debugging your code. We have set one breakpoint - // for you, but you can always add more by pressing . - System.out.println("i = " + i); - } - } -} \ No newline at end of file diff --git a/ruoyi-modules/hwmom-mqtt/src/main/resources/application.yml b/ruoyi-modules/hwmom-mqtt/src/main/resources/application.yml index b2e33ba..7062c54 100644 --- a/ruoyi-modules/hwmom-mqtt/src/main/resources/application.yml +++ b/ruoyi-modules/hwmom-mqtt/src/main/resources/application.yml @@ -30,7 +30,7 @@ spring: spring: application: # 应用名称 - name: hw-mqtt-broker + name: hwmom-mqtt cloud: nacos: # nacos 服务地址 @@ -52,7 +52,7 @@ spring: - optional:nacos:${spring.application.name}.yml kafka: - bootstrap-servers: localhost:9092 + bootstrap-servers: 119.45.202.115:9092 producer: key-serializer: org.apache.kafka.common.serialization.StringSerializer value-serializer: org.apache.kafka.common.serialization.StringSerializer From ff7bf451552271273c64add6c8aaddf8a023e011 Mon Sep 17 00:00:00 2001 From: yinq Date: Thu, 3 Apr 2025 16:33:01 +0800 Subject: [PATCH 4/4] =?UTF-8?q?update=20mes=E6=A8=A1=E5=9D=97=E6=9B=B4?= =?UTF-8?q?=E6=96=B0=E8=AE=BE=E5=A4=87MQTT=E8=AE=A4=E8=AF=81=E4=BF=A1?= =?UTF-8?q?=E6=81=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../common/constant/HwMomMesConstants.java | 5 +++ .../dromara/dms/domain/BaseAlarmLevel.java | 1 - .../impl/ProdBaseMachineInfoServiceImpl.java | 43 +++++++++++++++++++ 3 files changed, 48 insertions(+), 1 deletion(-) diff --git a/ruoyi-common/hwmom-common-mom/src/main/java/org/dromara/common/constant/HwMomMesConstants.java b/ruoyi-common/hwmom-common-mom/src/main/java/org/dromara/common/constant/HwMomMesConstants.java index 9ba9a25..c44bccf 100644 --- a/ruoyi-common/hwmom-common-mom/src/main/java/org/dromara/common/constant/HwMomMesConstants.java +++ b/ruoyi-common/hwmom-common-mom/src/main/java/org/dromara/common/constant/HwMomMesConstants.java @@ -16,4 +16,9 @@ public interface HwMomMesConstants { public static final String DELETE_FLAG_YES = "1"; public static final String DELETE_FLAG_NO = "0"; + /** + * 保存设备用户名和密码等信息的redis的key + */ + public static final String REDIS_KEY_DEVICE_INFO = "hw_device_info"; + } diff --git a/ruoyi-modules/hwmom-dms/src/main/java/org/dromara/dms/domain/BaseAlarmLevel.java b/ruoyi-modules/hwmom-dms/src/main/java/org/dromara/dms/domain/BaseAlarmLevel.java index e042037..7dad8d6 100644 --- a/ruoyi-modules/hwmom-dms/src/main/java/org/dromara/dms/domain/BaseAlarmLevel.java +++ b/ruoyi-modules/hwmom-dms/src/main/java/org/dromara/dms/domain/BaseAlarmLevel.java @@ -40,7 +40,6 @@ public class BaseAlarmLevel extends TenantEntity { /** * 状态(1、正常,9、删除) */ - @TableLogic(value="1", delval="9") private String levelStatus; /** diff --git a/ruoyi-modules/hwmom-mes/src/main/java/org/dromara/mes/service/impl/ProdBaseMachineInfoServiceImpl.java b/ruoyi-modules/hwmom-mes/src/main/java/org/dromara/mes/service/impl/ProdBaseMachineInfoServiceImpl.java index 4c57315..c3c07fa 100644 --- a/ruoyi-modules/hwmom-mes/src/main/java/org/dromara/mes/service/impl/ProdBaseMachineInfoServiceImpl.java +++ b/ruoyi-modules/hwmom-mes/src/main/java/org/dromara/mes/service/impl/ProdBaseMachineInfoServiceImpl.java @@ -1,6 +1,11 @@ package org.dromara.mes.service.impl; +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.alibaba.fastjson.serializer.SerializerFeature; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import org.dromara.common.constant.HwMomMesConstants; import org.dromara.common.core.exception.ServiceException; import org.dromara.common.core.utils.MapstructUtils; import org.dromara.common.core.utils.StringUtils; @@ -15,15 +20,24 @@ import org.dromara.mes.domain.*; import org.dromara.mes.domain.bo.ProdBaseMouldInfoBo; import org.dromara.mes.domain.vo.ProdBaseMouldInfoVo; import org.dromara.mes.mapper.ProdBaseMachineProcessMapper; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.stereotype.Service; import org.dromara.mes.domain.bo.ProdBaseMachineInfoBo; import org.dromara.mes.domain.vo.ProdBaseMachineInfoVo; import org.dromara.mes.mapper.ProdBaseMachineInfoMapper; import org.dromara.mes.service.IProdBaseMachineInfoService; +import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.Collection; +import java.util.concurrent.TimeUnit; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import static org.dromara.common.constant.HwMomMesConstants.REDIS_KEY_DEVICE_INFO; /** * 机台信息Service业务层处理 @@ -39,6 +53,9 @@ public class ProdBaseMachineInfoServiceImpl implements IProdBaseMachineInfoServi private final ProdBaseMachineProcessMapper prodBaseMachineProcessMapper; + @Autowired + private StringRedisTemplate redisTemplate; + /** * 查询机台信息 * @@ -166,6 +183,7 @@ public class ProdBaseMachineInfoServiceImpl implements IProdBaseMachineInfoServi throw new ServiceException("编码已存在"); } } + this.updateMqttAuth(); } /** @@ -182,4 +200,29 @@ public class ProdBaseMachineInfoServiceImpl implements IProdBaseMachineInfoServi } return baseMapper.deleteByIds(ids) > 0; } + + /** + * 更新设备MQTT认证信息 + */ + public void updateMqttAuth() { + new Thread(() -> { + try { + List machineInfoList = baseMapper.selectList(); + List deviceInfoJson = new ArrayList<>(); + machineInfoList.forEach(e -> { + JSONObject newDeviceInfo = new JSONObject(); + newDeviceInfo.put("deviceCode", e.getMachineCode()); + newDeviceInfo.put("userName", null); + newDeviceInfo.put("password", null); + deviceInfoJson.add(newDeviceInfo); + }); + + String deviceInfoJsonStr = JSON.toJSONString(deviceInfoJson, SerializerFeature.WriteMapNullValue); + redisTemplate.opsForValue().set(REDIS_KEY_DEVICE_INFO, deviceInfoJsonStr); + } catch (Exception e) { + System.out.println("设备MQTT认证信息异步更新失败 - error: " + e.getMessage()); + } + }, "MqttAuthUpdateThread").start(); + } + }