feat: 新功能开发,监测历史记录。微信和物联网平台,模块搭建。
This commit is contained in:
@@ -102,11 +102,6 @@
|
||||
<groupId>com.intc</groupId>
|
||||
<artifactId>intc-common-websocket</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.taosdata.jdbc</groupId>
|
||||
<artifactId>taos-jdbcdriver</artifactId>
|
||||
<version>2.0.40</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
|
||||
@@ -27,8 +27,11 @@ public class DeviceSensorDataController extends BaseController
|
||||
private IDeviceSensorDataService deviceSensorDataService;
|
||||
|
||||
@GetMapping("/getHistoryData")
|
||||
public List<DeviceSensorData> getHistoryData(@RequestParam("serialNum") String serialNum, @RequestParam("deviceId") Long deviceId, @RequestParam("mobilePhone") String mobilePhone, @RequestParam("deviceType") int deviceType, @RequestParam("startTime") String startTime, @RequestParam("endTime") String endTime)
|
||||
public List<DeviceSensorData> getHistoryData(@RequestParam("serialNum") String serialNum,
|
||||
@RequestParam("startTime") String startTime,
|
||||
@RequestParam("endTime") String endTime,
|
||||
@RequestParam(value = "intervalType", required = false, defaultValue = "1") Integer intervalType)
|
||||
{
|
||||
return deviceSensorDataService.getHistoryDataList(serialNum,deviceId,mobilePhone,deviceType,startTime,endTime);
|
||||
return deviceSensorDataService.getHistoryDataList(serialNum, startTime, endTime, intervalType);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,12 @@
|
||||
package com.intc.tdengine.domain;
|
||||
|
||||
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
|
||||
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import java.math.BigDecimal;
|
||||
import java.math.RoundingMode;
|
||||
import java.time.LocalDateTime;
|
||||
@Data
|
||||
@NoArgsConstructor // 生成无参构造方法
|
||||
@@ -10,17 +14,64 @@ import java.time.LocalDateTime;
|
||||
public class DeviceSensorData {
|
||||
|
||||
// 测量字段(随时间变化的数值)
|
||||
private LocalDateTime time; // 时序主键时间戳
|
||||
private LocalDateTime createTime; // 数据创建时间
|
||||
private double dissolvedOxygen; // 溶解氧
|
||||
private double temperature; // 温度
|
||||
private double saturability; // 饱和度
|
||||
private double ph; // pH值
|
||||
private double salinity; // 盐度
|
||||
private double treference; // 参考值(具体含义需结合业务)
|
||||
private double tfluorescence; // 荧光值
|
||||
private double phaseDifference; // 相位差
|
||||
private double battery; // 电池电量
|
||||
private String time; // 时序主键时间戳
|
||||
private String createTime; // 数据创建时间
|
||||
private Double dissolvedOxygen; // 溶解氧
|
||||
private Double temperature; // 温度
|
||||
private Double saturability; // 饱和度
|
||||
private Double ph; // pH值
|
||||
private Double salinity; // 盐度
|
||||
private Double treference; // 参考值(具体含义需结合业务)
|
||||
private Double tfluorescence; // 荧光值
|
||||
private Double phaseDifference; // 相位差
|
||||
private Double battery; // 电池电量
|
||||
|
||||
// Getter 方法,返回保留两位小数的值
|
||||
public Double getDissolvedOxygen() {
|
||||
return roundToTwoDecimals(dissolvedOxygen);
|
||||
}
|
||||
|
||||
public Double getTemperature() {
|
||||
return roundToTwoDecimals(temperature);
|
||||
}
|
||||
|
||||
public Double getSaturability() {
|
||||
return roundToTwoDecimals(saturability);
|
||||
}
|
||||
|
||||
public Double getPh() {
|
||||
return roundToTwoDecimals(ph);
|
||||
}
|
||||
|
||||
public Double getSalinity() {
|
||||
return roundToTwoDecimals(salinity);
|
||||
}
|
||||
|
||||
public Double getTreference() {
|
||||
return roundToTwoDecimals(treference);
|
||||
}
|
||||
|
||||
public Double getTfluorescence() {
|
||||
return roundToTwoDecimals(tfluorescence);
|
||||
}
|
||||
|
||||
public Double getPhaseDifference() {
|
||||
return roundToTwoDecimals(phaseDifference);
|
||||
}
|
||||
|
||||
public Double getBattery() {
|
||||
return roundToTwoDecimals(battery);
|
||||
}
|
||||
|
||||
// 工具方法:保留两位小数
|
||||
private Double roundToTwoDecimals(Double value) {
|
||||
if (value == null) {
|
||||
return null;
|
||||
}
|
||||
return BigDecimal.valueOf(value)
|
||||
.setScale(2, RoundingMode.HALF_UP)
|
||||
.doubleValue();
|
||||
}
|
||||
|
||||
// 标签字段(元数据,不随时间频繁变化)
|
||||
private String serialNum; // 设备序列号
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
package com.intc.tdengine.mapper;
|
||||
|
||||
import com.baomidou.dynamic.datasource.annotation.DS;
|
||||
import com.baomidou.mybatisplus.annotation.InterceptorIgnore;
|
||||
import com.intc.tdengine.domain.DeviceSensorData;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
@@ -8,7 +10,6 @@ import org.springframework.stereotype.Repository;
|
||||
import java.util.List;
|
||||
|
||||
@Repository
|
||||
@Mapper
|
||||
public interface DeviceSensorDataMapper {
|
||||
|
||||
/**
|
||||
@@ -46,13 +47,24 @@ public interface DeviceSensorDataMapper {
|
||||
* @param dataList 数据列表
|
||||
* @return 影响行数
|
||||
*/
|
||||
@DS("taos")
|
||||
@InterceptorIgnore(tenantLine = "true")
|
||||
int batchInsertDeviceSensorData(@Param("dataList") List<DeviceSensorData> dataList);
|
||||
|
||||
/**
|
||||
* 查询数据
|
||||
*
|
||||
* @return 影响行数
|
||||
* @param serialNum 设备序列号
|
||||
* @param startTime 开始时间
|
||||
* @param endTime 结束时间
|
||||
* @param intervalType 间隔类型:1-原始数据,2-10分钟,3-30分钟,4-1小时,5-3小时,6-6小时
|
||||
* @return 设备传感器数据列表
|
||||
*/
|
||||
List<DeviceSensorData> getHistoryDataList(@Param("serialNum") String serialNum,@Param("deviceId") Long deviceId,@Param("mobilePhone") String mobilePhone,@Param("deviceType") int deviceType,@Param("startTime") String startTime,@Param("endTime") String endTime);
|
||||
@DS("taos")
|
||||
@InterceptorIgnore(tenantLine = "true")
|
||||
List<DeviceSensorData> getHistoryDataList(@Param("serialNum") String serialNum,
|
||||
@Param("startTime") String startTime,
|
||||
@Param("endTime") String endTime,
|
||||
@Param("intervalType") Integer intervalType);
|
||||
|
||||
}
|
||||
|
||||
@@ -29,9 +29,13 @@ public interface IDeviceSensorDataService {
|
||||
public void batchInsertDeviceSensorData(List<DeviceSensorData> dataList);
|
||||
|
||||
/**
|
||||
* 查询数据
|
||||
* 查询历史数据列表
|
||||
*
|
||||
* @return 影响行数
|
||||
* @param serialNum 设备序列号
|
||||
* @param startTime 开始时间
|
||||
* @param endTime 结束时间
|
||||
* @param intervalType 间隔类型:1-原始数据,2-10分钟,3-30分钟,4-1小时,5-3小时,6-6小时
|
||||
* @return 设备传感器数据列表
|
||||
*/
|
||||
public List<DeviceSensorData> getHistoryDataList(String serialNum, Long deviceId, String mobilePhone, int deviceType, String startTime, String endTime);
|
||||
public List<DeviceSensorData> getHistoryDataList(String serialNum, String startTime, String endTime, Integer intervalType);
|
||||
}
|
||||
|
||||
@@ -1,14 +1,19 @@
|
||||
package com.intc.tdengine.service.impl;
|
||||
|
||||
import com.baomidou.dynamic.datasource.annotation.DS;
|
||||
import com.intc.tdengine.domain.DeviceSensorData;
|
||||
import com.intc.tdengine.mapper.DeviceSensorDataMapper;
|
||||
import com.intc.tdengine.service.IDeviceSensorDataService;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@Slf4j
|
||||
@Service
|
||||
@DS("taos") // 指定使用 taos 数据源(TDengine)
|
||||
public class DeviceSensorDataService implements IDeviceSensorDataService {
|
||||
@Resource
|
||||
private DeviceSensorDataMapper deviceSensorDataMapper;
|
||||
@@ -37,18 +42,69 @@ public class DeviceSensorDataService implements IDeviceSensorDataService {
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询数据
|
||||
* 查询历史数据列表
|
||||
*
|
||||
* @return 影响行数
|
||||
* @param serialNum 设备序列号
|
||||
* @param startTime 开始时间
|
||||
* @param endTime 结束时间
|
||||
* @param intervalType 间隔类型:1-原始数据,2-10分钟,3-30分钟,4-1小时,5-3小时,6-6小时
|
||||
* @return 设备传感器数据列表
|
||||
*/
|
||||
@Override
|
||||
public List<DeviceSensorData> getHistoryDataList(String serialNum,Long deviceId, String mobilePhone, int deviceType,String startTime, String endTime) {
|
||||
List<DeviceSensorData> list=new ArrayList<>();
|
||||
public List<DeviceSensorData> getHistoryDataList(String serialNum, String startTime, String endTime, Integer intervalType) {
|
||||
List<DeviceSensorData> list = new ArrayList<>();
|
||||
try {
|
||||
list=deviceSensorDataMapper.getHistoryDataList(serialNum,deviceId,mobilePhone,deviceType,startTime,endTime);
|
||||
}catch (Exception e){
|
||||
|
||||
// 默认为原始数据
|
||||
if (intervalType == null) {
|
||||
intervalType = 1;
|
||||
}
|
||||
|
||||
// 验证intervalType参数
|
||||
if (intervalType < 1 || intervalType > 6) {
|
||||
log.error("无效的intervalType参数: {}, 使用默认值1", intervalType);
|
||||
intervalType = 1;
|
||||
}
|
||||
|
||||
// 处理时间格式
|
||||
if (startTime != null && !startTime.contains(" ")) {
|
||||
startTime = startTime + " 00:00:00";
|
||||
}
|
||||
if (endTime != null && !endTime.contains(" ")) {
|
||||
endTime = endTime + " 23:59:59";
|
||||
}
|
||||
|
||||
String intervalDesc = getIntervalDesc(intervalType);
|
||||
log.info("查询TDengine历史数据: serialNum={}, startTime={}, endTime={}, intervalType={} ({})",
|
||||
serialNum, startTime, endTime, intervalType, intervalDesc);
|
||||
|
||||
list = deviceSensorDataMapper.getHistoryDataList(serialNum, startTime, endTime, intervalType);
|
||||
|
||||
log.info("查询到 {} 条历史数据 ({})", list.size(), intervalDesc);
|
||||
} catch (Exception e) {
|
||||
log.error("查询TDengine历史数据失败", e);
|
||||
// 打印完整异常链
|
||||
Throwable cause = e;
|
||||
int level = 0;
|
||||
while (cause != null && level < 10) {
|
||||
log.error("异常层级 {}: {}", level++, cause.getClass().getName() + ": " + cause.getMessage());
|
||||
cause = cause.getCause();
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取间隔类型描述
|
||||
*/
|
||||
private String getIntervalDesc(Integer intervalType) {
|
||||
switch (intervalType) {
|
||||
case 1: return "原始数据";
|
||||
case 2: return "10分钟间隔";
|
||||
case 3: return "30分钟间隔";
|
||||
case 4: return "1小时间隔";
|
||||
case 5: return "3小时间隔";
|
||||
case 6: return "6小时间隔";
|
||||
default: return "未知";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -52,14 +52,57 @@
|
||||
</foreach>
|
||||
</insert>
|
||||
|
||||
<select id="getHistoryDataList" parameterType="String" resultType="com.intc.tdengine.domain.DeviceSensorData">
|
||||
select time,createTime,dissolvedOxygen,temperature,saturability,ph,salinity,treference,tfluorescence,phaseDifference,battery,serialNum,deviceId,data.mobilePhone,deviceType from fishery.t_#{serialNum}
|
||||
<where>
|
||||
time >= #{startTime} and time <= #{endTime}
|
||||
<if test="serialNum != null and serialNum != ''"> AND serialNum=#{serialNum}</if>
|
||||
<if test="deviceId != null "> AND deviceId=#{deviceId}</if>
|
||||
<if test="mobilePhone != null and mobilePhone != ''"> AND mobilePhone=#{mobilePhone}</if>
|
||||
<if test="deviceType != null"> AND deviceType=#{deviceType}</if>
|
||||
</where>
|
||||
<select id="getHistoryDataList" resultType="com.intc.tdengine.domain.DeviceSensorData">
|
||||
<if test="intervalType == null or intervalType == 1">
|
||||
<!-- 原始数据,不聚合 -->
|
||||
SELECT
|
||||
`time`,
|
||||
createTime,
|
||||
dissolvedOxygen,
|
||||
temperature,
|
||||
saturability,
|
||||
ph,
|
||||
salinity,
|
||||
treference,
|
||||
tfluorescence,
|
||||
phaseDifference,
|
||||
battery,
|
||||
serialNum,
|
||||
deviceId,
|
||||
mobilePhone,
|
||||
deviceType
|
||||
FROM `fishery`.`t_${serialNum}`
|
||||
<where>
|
||||
<if test="startTime != null and startTime != ''">AND `time` >= #{startTime}</if>
|
||||
<if test="endTime != null and endTime != ''">AND `time` <= #{endTime}</if>
|
||||
</where>
|
||||
</if>
|
||||
<if test="intervalType != null and intervalType != 1">
|
||||
<!-- 按时间间隔聚合 -->
|
||||
SELECT
|
||||
_wstart as `time`,
|
||||
_wstart as createTime,
|
||||
AVG(dissolvedOxygen) as dissolvedOxygen,
|
||||
AVG(temperature) as temperature,
|
||||
AVG(saturability) as saturability,
|
||||
AVG(ph) as ph,
|
||||
AVG(salinity) as salinity,
|
||||
AVG(treference) as treference,
|
||||
AVG(tfluorescence) as tfluorescence,
|
||||
AVG(phaseDifference) as phaseDifference,
|
||||
AVG(battery) as battery
|
||||
FROM `fishery`.`t_${serialNum}`
|
||||
<where>
|
||||
<if test="startTime != null and startTime != ''">AND `time` >= #{startTime}</if>
|
||||
<if test="endTime != null and endTime != ''">AND `time` <= #{endTime}</if>
|
||||
</where>
|
||||
<choose>
|
||||
<when test="intervalType == 2">INTERVAL(10m)</when>
|
||||
<when test="intervalType == 3">INTERVAL(30m)</when>
|
||||
<when test="intervalType == 4">INTERVAL(1h)</when>
|
||||
<when test="intervalType == 5">INTERVAL(3h)</when>
|
||||
<when test="intervalType == 6">INTERVAL(6h)</when>
|
||||
</choose>
|
||||
</if>
|
||||
</select>
|
||||
</mapper>
|
||||
|
||||
Reference in New Issue
Block a user