【功能优化】Bpm:设备日志的展示

This commit is contained in:
YunaiV 2025-01-28 08:35:07 +08:00
parent 5fbfe49305
commit 6071afeae8
9 changed files with 69 additions and 73 deletions

View File

@ -3,10 +3,10 @@ package cn.iocoder.yudao.module.iot.controller.admin.device;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.module.iot.controller.admin.device.vo.deviceData.*;
import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceLogDO;
import cn.iocoder.yudao.module.iot.controller.admin.device.vo.deviceData.IotDeviceDataPageReqVO;
import cn.iocoder.yudao.module.iot.controller.admin.device.vo.deviceData.IotDeviceDataRespVO;
import cn.iocoder.yudao.module.iot.controller.admin.device.vo.deviceData.IotTimeDataRespVO;
import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDevicePropertyDO;
import cn.iocoder.yudao.module.iot.service.device.data.IotDeviceLogService;
import cn.iocoder.yudao.module.iot.service.device.data.IotDevicePropertyService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
@ -30,8 +30,6 @@ public class IotDeviceDataController {
@Resource
private IotDevicePropertyService deviceDataService;
@Resource
private IotDeviceLogService deviceLogDataService;
// TODO @浩浩这里的 /latest-list包括方法名
@GetMapping("/latest")
@ -49,12 +47,4 @@ public class IotDeviceDataController {
return success(BeanUtils.toBean(list, IotTimeDataRespVO.class));
}
// TODO:功能权限
@GetMapping("/log/page")
@Operation(summary = "获得设备日志分页")
public CommonResult<PageResult<IotDeviceLogRespVO>> getDeviceLogPage(@Valid IotDeviceLogPageReqVO pageReqVO) {
PageResult<IotDeviceLogDO> pageResult = deviceLogDataService.getDeviceLogPage(pageReqVO);
return success(BeanUtils.toBean(pageResult, IotDeviceLogRespVO.class));
}
}

View File

@ -0,0 +1,38 @@
package cn.iocoder.yudao.module.iot.controller.admin.device;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.module.iot.controller.admin.device.vo.deviceData.IotDeviceLogPageReqVO;
import cn.iocoder.yudao.module.iot.controller.admin.device.vo.deviceData.IotDeviceLogRespVO;
import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceLogDO;
import cn.iocoder.yudao.module.iot.service.device.data.IotDeviceLogService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import jakarta.validation.Valid;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
@Tag(name = "管理后台 - IoT 设备日志")
@RestController
@RequestMapping("/iot/device/log")
@Validated
public class IotDeviceLogController {
@Resource
private IotDeviceLogService deviceLogService;
// TODO:功能权限
@GetMapping("/page")
@Operation(summary = "获得设备日志分页")
public CommonResult<PageResult<IotDeviceLogRespVO>> getDeviceLogPage(@Valid IotDeviceLogPageReqVO pageReqVO) {
PageResult<IotDeviceLogDO> pageResult = deviceLogService.getDeviceLogPage(pageReqVO);
return success(BeanUtils.toBean(pageResult, IotDeviceLogRespVO.class));
}
}

View File

@ -4,11 +4,6 @@ import cn.iocoder.yudao.framework.common.pojo.PageParam;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotEmpty;
import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;
import java.time.LocalDateTime;
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
@Schema(description = "管理后台 - IoT 设备日志分页查询 Request VO")
@Data
@ -18,16 +13,10 @@ public class IotDeviceLogPageReqVO extends PageParam {
@NotEmpty(message = "设备标识不能为空")
private String deviceKey;
// TODO @super对应的枚举类
@Schema(description = "消息类型", example = "property")
private String type;
private String type; // 参见 IotDeviceMessageTypeEnum 枚举精准匹配
@Schema(description = "标识符", example = "temperature")
// TODO @super对应的枚举类
private String subType;
@Schema(description = "创建时间")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private LocalDateTime[] createTime;
private String identifier; // 参见 IotDeviceMessageIdentifierEnum 枚举模糊匹配
}

View File

@ -4,18 +4,17 @@ import cn.iocoder.yudao.module.iot.controller.admin.device.vo.deviceData.IotDevi
import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceLogDO;
import cn.iocoder.yudao.module.iot.framework.tdengine.core.annotation.TDengineDS;
import com.baomidou.mybatisplus.annotation.InterceptorIgnore;
import com.baomidou.mybatisplus.core.metadata.IPage;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
* 设备日志 {@link IotDeviceLogDO} Mapper 接口
*/
@Mapper
@TDengineDS
@InterceptorIgnore(tenantLine = "true") // 避免 SQL 解析因为 JSqlParser TDengine SQL 解析会报错
public interface IotDeviceLogDataMapper {
public interface IotDeviceLogMapper {
/**
* 创建设备日志超级表
@ -44,7 +43,8 @@ public interface IotDeviceLogDataMapper {
* @param reqVO 分页查询条件
* @return 设备日志列表
*/
List<IotDeviceLogDO> selectPage(@Param("reqVO") IotDeviceLogPageReqVO reqVO);
IPage<IotDeviceLogDO> selectPage(IPage<IotDeviceLogDO> page,
@Param("reqVO") IotDeviceLogPageReqVO reqVO);
/**
* 获得设备日志总数

View File

@ -20,7 +20,7 @@ import java.util.stream.Collectors;
@Mapper
@TDengineDS
@InterceptorIgnore(tenantLine = "true") // 避免 SQL 解析因为 JSqlParser TDengine SQL 解析会报错
public interface IotDevicePropertyDataMapper {
public interface IotDevicePropertyMapper {
List<TDengineTableField> getProductPropertySTableFieldList(@Param("productKey") String productKey);

View File

@ -7,15 +7,15 @@ import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.module.iot.controller.admin.device.vo.deviceData.IotDeviceLogPageReqVO;
import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceLogDO;
import cn.iocoder.yudao.module.iot.dal.tdengine.IotDeviceLogDataMapper;
import cn.iocoder.yudao.module.iot.dal.tdengine.IotDeviceLogMapper;
import cn.iocoder.yudao.module.iot.mq.message.IotDeviceMessage;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;
import java.util.List;
/**
* IoT 设备日志数据 Service 实现类
*
@ -27,17 +27,17 @@ import java.util.List;
public class IotDeviceLogServiceImpl implements IotDeviceLogService {
@Resource
private IotDeviceLogDataMapper deviceLogDataMapper;
private IotDeviceLogMapper deviceLogMapper;
@Override
public void defineDeviceLog() {
if (StrUtil.isNotEmpty(deviceLogDataMapper.showDeviceLogSTable())) {
if (StrUtil.isNotEmpty(deviceLogMapper.showDeviceLogSTable())) {
log.info("[defineDeviceLog][设备日志超级表已存在,创建跳过]");
return;
}
log.info("[defineDeviceLog][设备日志超级表不存在,创建开始...]");
deviceLogDataMapper.createDeviceLogSTable();
deviceLogMapper.createDeviceLogSTable();
log.info("[defineDeviceLog][设备日志超级表不存在,创建成功]");
}
@ -46,15 +46,15 @@ public class IotDeviceLogServiceImpl implements IotDeviceLogService {
IotDeviceLogDO log = BeanUtils.toBean(message, IotDeviceLogDO.class)
.setId(IdUtil.fastSimpleUUID())
.setContent(JsonUtils.toJsonString(message.getData()));
deviceLogDataMapper.insert(log);
deviceLogMapper.insert(log);
}
@Override
public PageResult<IotDeviceLogDO> getDeviceLogPage(IotDeviceLogPageReqVO pageReqVO) {
// TODO @芋艿增加一个表不存在的 try catch
List<IotDeviceLogDO> list = deviceLogDataMapper.selectPage(pageReqVO);
Long total = deviceLogDataMapper.selectCount(pageReqVO);
return new PageResult<>(list, total);
IPage<IotDeviceLogDO> page = deviceLogMapper.selectPage(
new Page<>(pageReqVO.getPageNo(), pageReqVO.getPageSize()), pageReqVO);
return new PageResult<>(page.getRecords(), page.getTotal());
}
}

View File

@ -13,7 +13,7 @@ import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDevicePropertyDO;
import cn.iocoder.yudao.module.iot.dal.dataobject.product.IotProductDO;
import cn.iocoder.yudao.module.iot.dal.dataobject.thingmodel.IotThingModelDO;
import cn.iocoder.yudao.module.iot.dal.redis.device.DevicePropertyRedisDAO;
import cn.iocoder.yudao.module.iot.dal.tdengine.IotDevicePropertyDataMapper;
import cn.iocoder.yudao.module.iot.dal.tdengine.IotDevicePropertyMapper;
import cn.iocoder.yudao.module.iot.enums.thingmodel.IotDataSpecsDataTypeEnum;
import cn.iocoder.yudao.module.iot.enums.thingmodel.IotThingModelTypeEnum;
import cn.iocoder.yudao.module.iot.framework.tdengine.core.TDengineTableField;
@ -68,7 +68,7 @@ public class IotDevicePropertyServiceImpl implements IotDevicePropertyService {
private DevicePropertyRedisDAO deviceDataRedisDAO;
@Resource
private IotDevicePropertyDataMapper devicePropertyDataMapper;
private IotDevicePropertyMapper devicePropertyMapper;
@Override
public void defineDevicePropertyData(Long productId) {
@ -79,7 +79,7 @@ public class IotDevicePropertyServiceImpl implements IotDevicePropertyService {
// 1.2 解析 DB 里的字段
List<TDengineTableField> oldFields = new ArrayList<>();
try {
oldFields.addAll(devicePropertyDataMapper.getProductPropertySTableFieldList(product.getProductKey()));
oldFields.addAll(devicePropertyMapper.getProductPropertySTableFieldList(product.getProductKey()));
} catch (Exception e) {
if (!e.getMessage().contains("Table does not exist")) {
throw e;
@ -93,11 +93,11 @@ public class IotDevicePropertyServiceImpl implements IotDevicePropertyService {
log.info("[defineDevicePropertyData][productId({}) 没有需要定义的属性]", productId);
return;
}
devicePropertyDataMapper.createProductPropertySTable(product.getProductKey(), newFields);
devicePropertyMapper.createProductPropertySTable(product.getProductKey(), newFields);
return;
}
// 2.2 情况二如果是修改的时候需要更新表
devicePropertyDataMapper.alterProductPropertySTable(product.getProductKey(), oldFields, newFields);
devicePropertyMapper.alterProductPropertySTable(product.getProductKey(), oldFields, newFields);
}
private List<TDengineTableField> buildTableFieldList(List<IotThingModelDO> thingModels) {
@ -142,7 +142,7 @@ public class IotDevicePropertyServiceImpl implements IotDevicePropertyService {
}
// 3.1 保存设备属性数据
devicePropertyDataMapper.insert(device, properties,
devicePropertyMapper.insert(device, properties,
LocalDateTimeUtil.toEpochMilli(message.getReportTime())); // TODO @芋艿后续要看看查询的时候能不能用 LocalDateTime
// 3.2 保存设备属性日志

View File

@ -2,7 +2,7 @@
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="cn.iocoder.yudao.module.iot.dal.tdengine.IotDeviceLogDataMapper">
<mapper namespace="cn.iocoder.yudao.module.iot.dal.tdengine.IotDeviceLogMapper">
<update id="createDeviceLogSTable">
CREATE STABLE IF NOT EXISTS device_log (
@ -40,38 +40,17 @@
</insert>
<select id="selectPage" resultType="cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceLogDO">
SELECT ts, id, device_key, product_key, type, sub_type, content, report_time
SELECT ts, id, device_key, product_key, type, identifier, content, report_time
FROM device_log_${reqVO.deviceKey}
<where>
<if test="reqVO.type != null and reqVO.type != ''">
AND type = #{reqVO.type}
</if>
<if test="reqVO.subType != null and reqVO.subType != ''">
AND subType = #{reqVO.subType}
</if>
<if test="reqVO.createTime != null">
AND ts BETWEEN #{reqVO.createTime[0]} AND #{reqVO.createTime[1]}
<if test="reqVO.identifier != null and reqVO.identifier != ''">
AND identifier LIKE CONCAT('%',#{reqVO.identifier},'%')
</if>
</where>
ORDER BY ts DESC
LIMIT #{reqVO.pageSize} OFFSET #{reqVO.pageNo}
</select>
<!-- TODO 芋艿:看看能不能复用 mybatis-plus 的 selectCount 方法 -->
<select id="selectCount" resultType="Long">
SELECT COUNT(*)
FROM device_log_${reqVO.deviceKey}
<where>
<if test="reqVO.type != null and reqVO.type != ''">
AND type = #{reqVO.type}
</if>
<if test="reqVO.subType != null and reqVO.subType != ''">
AND subType = #{reqVO.subType}
</if>
<if test="reqVO.createTime != null">
AND ts BETWEEN #{reqVO.createTime[0]} AND #{reqVO.createTime[1]}
</if>
</where>
</select>
</mapper>

View File

@ -2,7 +2,7 @@
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="cn.iocoder.yudao.module.iot.dal.tdengine.IotDevicePropertyDataMapper">
<mapper namespace="cn.iocoder.yudao.module.iot.dal.tdengine.IotDevicePropertyMapper">
<select id="getProductPropertySTableFieldList" resultType="cn.iocoder.yudao.module.iot.framework.tdengine.core.TDengineTableField">
DESCRIBE product_property_${productKey}