新疆后端项目

This commit is contained in:
DESKTOP-BLB5287\FP
2025-06-30 14:31:09 +08:00
commit 0e52aff1f1
2596 changed files with 261030 additions and 0 deletions
@@ -0,0 +1,45 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.renkang</groupId>
<artifactId>functional-modules</artifactId>
<version>2.0.0</version>
</parent>
<artifactId>data-center-api</artifactId>
<version>2.0.0</version>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.retry</groupId>
<artifactId>spring-retry</artifactId>
</dependency>
<dependency>
<groupId>org.jeecgframework.boot</groupId>
<artifactId>jeecg-boot-base-core</artifactId>
<scope>provided</scope>
</dependency>
</dependencies>
</project>
@@ -0,0 +1,72 @@
package com.renkang.datacenter.api;
import com.renkang.datacenter.bean.*;
import com.renkang.datacenter.config.ImcCenterConstants;
import org.jeecg.common.api.vo.Result;
import org.springframework.retry.annotation.Retryable;
/**
* @author Shunzhi Jiang
* @since 2023/11/5
*/
@Retryable(maxAttempts = 2, listeners = "restRetryListener")
public interface DataCenterExecutor {
Result<Object> addDevice(WatchDevice device);
Result<Object> addDeviceBatch(WatchDeviceBatch devices);
Result<Object> removeDevice(WatchNo watchNo);
Result<Object> setSwitchStatus(WatchDeviceSwitch watchDeviceSwitch);
Result<Object> setSwitchStatusAll(DeviceSwitch deviceSwitch);
Result<Object> cmdNotice(Notice notice);
Result<Object> cmdNoticeMulti(Notice notice);
Result<Object> watchDataList(WatchDataList watchDataList);
Result<Object> increaseWatchDataCount(IncreaseWatchDataCount dataCount);
Result<Object> increaseWatchDataList(IncreaseWatchDataList dataList);
Result<Object> watchSdcItemData(WatchSdcItemData sdcItemData);
Result<Object> deviceInfoAll(WatchNo watchNo);
Result<Object> getRate(WatchNo watchNo);
Result<Object> getPeriod(WatchNo watchNo);
Result<Object> getWarnSwitch(WatchNo watchNo);
Result<Object> saveRate(Rate rate);
Result<Object> savePeriod(Period period);
Result<Object> saveWarnSwitch(WarnSwitch warnSwitch);
Result<Object> cmdDataPush(String watchNo);
Result<Object> cmdUpdatePeriod(String watchNo);
Result<Object> cmdUpdateTask(String watchNo);
Result<Object> cmdUpdateSwitch(String watchNo);
@Retryable(maxAttempts = 2, listeners = ImcCenterConstants.IMC_LISTENER)
Result<Object> getImageMessage(ImcPeIdVo imcPeIdVo);
/**
* 通过peId获取影像基本信息
* @param imcPeIdVo
* @return
*/
@Retryable(maxAttempts = 2, listeners = ImcCenterConstants.IMC_LISTENER)
Result<Object> getImageItems(ImcPeIdVo imcPeIdVo);
String downloadAsString(String filepath);
}
@@ -0,0 +1,185 @@
package com.renkang.datacenter.api;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.renkang.datacenter.bean.*;
import com.renkang.datacenter.config.DataCenterConstants;
import com.renkang.datacenter.config.DataCenterProperties;
import com.renkang.datacenter.config.MethodApi;
import com.renkang.datacenter.util.RemoteUtils;
import org.jeecg.common.api.vo.Result;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.Map;
import java.util.Objects;
@Service
public class DefaultDataCenterExecutor implements DataCenterExecutor {
private DataCenterProperties properties;
@Autowired
public void setProperties(DataCenterProperties properties) {
this.properties = properties;
}
@Override
public Result<Object> addDevice(WatchDevice device) {
return RemoteUtils.post(MethodApi.ADD_DEVICE,device);
}
@Override
public Result<Object> addDeviceBatch(WatchDeviceBatch devices) {
return RemoteUtils.post(MethodApi.ADD_DEVICE_BATCH,devices);
}
@Override
public Result<Object> removeDevice(WatchNo watchNo) {
return RemoteUtils.post(MethodApi.REMOVE_DEVICE, objectToMap(watchNo));
}
@Override
public Result<Object> setSwitchStatus(WatchDeviceSwitch watchDeviceSwitch) {
return RemoteUtils.post(MethodApi.SET_SWITCH_STATUS, watchDeviceSwitch);
}
@Override
public Result<Object> setSwitchStatusAll(DeviceSwitch deviceSwitch) {
return RemoteUtils.post(MethodApi.SET_SWITCH_STATUS_ALL, deviceSwitch);
}
@Override
public Result<Object> cmdNotice(Notice notice) {
return RemoteUtils.post(MethodApi.CMD_NOTICE, objectToMap(notice));
}
@Override
public Result<Object> cmdNoticeMulti(Notice notice) {
return RemoteUtils.post(MethodApi.CMD_NOTICE_MULTI, objectToMap(notice));
}
@Override
public Result<Object> watchDataList(WatchDataList watchDataList) {
return RemoteUtils.get(MethodApi.WATCH_DATA_LIST, objectToMap(watchDataList));
}
@Override
public Result<Object> increaseWatchDataCount(IncreaseWatchDataCount dataCount) {
if (Objects.isNull(dataCount.getPageSize()) || dataCount.getPageSize() == 0) {
dataCount.setPageSize(properties.getPageSize());
}
return RemoteUtils.get(MethodApi.INCREASE_WATCH_DATA_PAGE_COUNT, objectToMap(dataCount));
}
@Override
public Result<Object> increaseWatchDataList(IncreaseWatchDataList dataList) {
if (Objects.isNull(dataList.getPageSize()) || dataList.getPageSize() == 0) {
dataList.setPageSize(properties.getPageSize());
}
return RemoteUtils.get(MethodApi.INCREASE_WATCH_DATA_PAGE_LIST, objectToMap(dataList));
}
@Override
public Result<Object> watchSdcItemData(WatchSdcItemData sdcItemData) {
return RemoteUtils.get(MethodApi.WATCH_SDC_ITEM_DATA, objectToMap(sdcItemData));
}
@Override
public Result<Object> deviceInfoAll(WatchNo watchNo) {
return RemoteUtils.get(MethodApi.DEVICE_INFO_ALL, objectToMap(watchNo));
}
@Override
public Result<Object> getRate(WatchNo watchNo) {
return RemoteUtils.get(MethodApi.GET_RATE, objectToMap(watchNo));
}
@Override
public Result<Object> getPeriod(WatchNo watchNo) {
return RemoteUtils.get(MethodApi.GET_PERIOD, objectToMap(watchNo));
}
@Override
public Result<Object> getWarnSwitch(WatchNo watchNo) {
return RemoteUtils.get(MethodApi.GET_WARN_SWITCH, objectToMap(watchNo));
}
@Override
public Result<Object> saveRate(Rate rate) {
return RemoteUtils.post(MethodApi.SAVE_RATE, rate);
}
@Override
public Result<Object> savePeriod(Period period) {
return RemoteUtils.post(MethodApi.SAVE_PERIOD, period);
}
@Override
public Result<Object> saveWarnSwitch(WarnSwitch warnSwitch) {
return RemoteUtils.post(MethodApi.SAVE_WARN_SWITCH, warnSwitch);
}
@Override
public Result<Object> cmdDataPush(String watchNo) {
MqttTask task = new MqttTask();
task.setWatchNo(watchNo);
task.setTaskName(DataCenterConstants.MQTT_CMD_DATA_PUSH);
return cmdDataPush(task);
}
@Override
public Result<Object> cmdUpdatePeriod(String watchNo) {
MqttTask task = new MqttTask();
task.setWatchNo(watchNo);
task.setTaskName(DataCenterConstants.MQTT_CMD_UPDATE_PERIOD);
return cmdDataPush(task);
}
@Override
public Result<Object> cmdUpdateTask(String watchNo) {
MqttTask task = new MqttTask();
task.setWatchNo(watchNo);
task.setTaskName(DataCenterConstants.MQTT_CMD_UPDATE_TASK);
return cmdDataPush(task);
}
@Override
public Result<Object> cmdUpdateSwitch(String watchNo) {
MqttTask task = new MqttTask();
task.setWatchNo(watchNo);
task.setTaskName(DataCenterConstants.MQTT_CMD_UPDATE_SWITCH);
return cmdDataPush(task);
}
@Override
public Result<Object> getImageMessage(ImcPeIdVo imcPeIdVo) {
return RemoteUtils.post(MethodApi.GET_IMAGE_MESSAGE, imcPeIdVo);
}
/**
* 通过peId获取影像基本信息
*
* @param imcPeIdVo
* @return
*/
@Override
public Result<Object> getImageItems(ImcPeIdVo imcPeIdVo) {
return RemoteUtils.post(MethodApi.GET_IMAGE_ITEMS, imcPeIdVo);
}
@Override
public String downloadAsString(String filepath) {
return RemoteUtils.downloadAsString(filepath);
}
private Result<Object> cmdDataPush(MqttTask task) {
return RemoteUtils.post(MethodApi.CMD_DATA_PUSH, objectToMap(task));
}
private Map<String,Object> objectToMap(Object source) {
return (JSONObject) JSON.toJSON(source);
}
}
@@ -0,0 +1,22 @@
package com.renkang.datacenter.bean;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
/**
* @author Shunzhi Jiang
* @since 2023/11/13
*/
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
@Data
public class DataCommon extends WatchDataBase {
private String wdType;
private Double dataValue;
private String timeStamp;
}
@@ -0,0 +1,40 @@
package com.renkang.datacenter.bean;
import com.alibaba.fastjson.annotation.JSONField;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import java.util.Date;
/**
* @author Jiang Shunzhi
*/
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
@Data
public class DataEcg extends WatchDataBase {
private Long ecgStartTime;
private Long ecgEndTime;
@JSONField(format = "yyyy-MM-dd")
private Date dataDate;
private Integer ecgArrhyType;
private String ecgArrhyTypeDict;
private Integer ecgUserSymptom;
private String ecgUserSymptomDict;
private Integer ecgArrhyAvgRate;
private Integer ecgDataPointsCount;
private String ecgDataPoints;
}
@@ -0,0 +1,29 @@
package com.renkang.datacenter.bean;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
/**
* @author Shunzhi Jiang
* @since 2023/11/13
*/
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
@Data
public class DataExercise extends WatchDataBase {
/**
* 中高强度运动时间(分钟)
*/
private Integer strengthTimes;
/**
* 总活动时长(小时)
*/
private Integer totalTime;
/**
* 数据日期
*/
private String dataDate;
}
@@ -0,0 +1,24 @@
package com.renkang.datacenter.bean;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
/**
* @author Shunzhi Jiang
* @since 2023/11/13
*/
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
@Data
public class DataGps extends WatchDataBase {
private Double lon;
private Double lat;
private String address;
private String timeStamp;
}
@@ -0,0 +1,22 @@
package com.renkang.datacenter.bean;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
/**
* @author Shunzhi Jiang
* @since 2023/11/13
*/
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
@Data
public class DataHeartRate extends WatchDataBase {
private Double dataValue;
private Double silenceValue;
private String timeStamp;
}
@@ -0,0 +1,22 @@
package com.renkang.datacenter.bean;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
/**
* @author Shunzhi Jiang
* @since 2023/11/13
*/
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
@Data
public class DataSdc extends WatchDataBase {
private String sdcDate;
private Long dataValue;
private String wdType;
}
@@ -0,0 +1,22 @@
package com.renkang.datacenter.bean;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
/**
* @author Shunzhi Jiang
* @since 2023/11/13
*/
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
@Data
public class DataSleep extends WatchDataBase {
private String startTimeStamp;
private String endTimeStamp;
private String sleepType;
}
@@ -0,0 +1,109 @@
package com.renkang.datacenter.bean;
import com.alibaba.fastjson.annotation.JSONField;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import java.io.Serializable;
import java.util.List;
/**
* @author Shunzhi Jiang
* @since 2023/11/13
*/
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
@Data
public class DataSleepNew extends WatchDataBase {
private String sleepFlag;
@JSONField(alternateNames = "DataDate")
private String dataDate;
private Integer errCode;
private List<Error> errCodeArr;
private List<Day> statusInDayArr;
private List<Minute> statusInMinuteArr;
@Data
public static class Error implements Serializable {
private Integer errCode;
private String startTime;
private String endTime;
}
@Data
public static class Day implements Serializable {
/**
* 睡梦时长(分钟)
*/
private Integer deepSleepPartCnt;
/**
* 入睡时间点
*/
private String fallAsleepTime;
/**
* 上床时间
*/
private String goBedTime;
/**
* 睡眠效率百分比
*/
private Integer sleepEfficiency;
/**
* 睡眠潜伏期
*/
private Long sleepLatency;
/**
* 睡眠得分
*/
private Integer sleepScore;
/**
* 原始睡眠得分
*/
@JSONField(alternateNames = "sleepScoreOrign")
private Integer sleepScoreOrigin;
/**
* 鼾声(每小时次数)
*/
private Integer snoreFreq;
/**
* 当天的时间戳
*/
private String startTime;
/**
* 数据有效性
*/
private Double validData;
/**
* 醒来时间
*/
private String wakeUpTime;
}
@Data
public static class Minute implements Serializable {
/**
* 睡眠状态
*/
private String status;
/**
* 开始时间
*/
private String startTime;
/**
* 结束时间
*/
private String endTime;
}
}
@@ -0,0 +1,27 @@
package com.renkang.datacenter.bean;
import com.alibaba.fastjson.annotation.JSONField;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import java.util.Date;
/**
* @author Shunzhi Jiang
* @since 2023/11/13
*/
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
@Data
public class DataSteps extends WatchDataBase {
/**
* 数据日期
*/
@JSONField(format = "yyyy-MM-dd")
private Date stepDate;
private Integer stepCount;
}
@@ -0,0 +1,22 @@
package com.renkang.datacenter.bean;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
/**
* @author Shunzhi Jiang
* @since 2023/11/13
*/
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
@Data
public class DataStress extends WatchDataBase {
private Double dataValue;
private String startTimeStamp;
private String endTimeStamp;
}
@@ -0,0 +1,22 @@
package com.renkang.datacenter.bean;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
/**
* @author Shunzhi Jiang
* @since 2023/11/13
*/
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
@Data
public class DataTemperature extends WatchDataBase {
private Double skinTempera;
private Double dataValue;
private String timeStamp;
}
@@ -0,0 +1,38 @@
package com.renkang.datacenter.bean;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
/**
* @author Shunzhi Jiang
* @since 2023/11/13
*/
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
@Data
public class DataTrace extends WatchDataBase {
private String recordId;
/**
* 海拔
*/
private Double altitude;
/**
* 纬度
*/
private Double latitude;
/**
* 经度
*/
private Double longitude;
/**
* 时间戳
*/
private String utcTime;
/**
* 数据是否合法
*/
private String valid;
}
@@ -0,0 +1,25 @@
package com.renkang.datacenter.bean;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
/**
* @author Shunzhi Jiang
* @since 2023/11/13
*/
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
@Data
public class DataWorkout extends WatchDataBase {
private String workoutType;
private Double calorie;
private Double distance;
private String startTimeStamp;
private String endTimeStamp;
}
@@ -0,0 +1,17 @@
package com.renkang.datacenter.bean;
import lombok.Data;
import java.io.Serializable;
/**
* @author Shunzhi Jiang
* @since 2023/11/5
*/
@Data
public class DeviceSwitch implements Serializable {
private String wdType;
private String switchFlag;
}
@@ -0,0 +1,11 @@
package com.renkang.datacenter.bean;
import lombok.Data;
@Data
public class ImcPeIdVo {
private String peId;
private String hospitalId;
}
@@ -0,0 +1,20 @@
package com.renkang.datacenter.bean;
import lombok.Data;
import java.io.Serializable;
/**
* @author Shunzhi Jiang
* @since 2023/11/5
*/
@Data
public class IncreaseWatchDataCount implements Serializable {
private String wdType;
private String id;
private Integer pageSize;
}
@@ -0,0 +1,20 @@
package com.renkang.datacenter.bean;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import java.io.Serializable;
/**
* @author Shunzhi Jiang
* @since 2023/11/5
*/
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
@Data
public class IncreaseWatchDataList extends IncreaseWatchDataCount implements Serializable {
private Integer pageNo;
}
@@ -0,0 +1,14 @@
package com.renkang.datacenter.bean;
import lombok.Data;
import java.io.Serializable;
@Data
public class Login implements Serializable {
private String username;
private String password;
}
@@ -0,0 +1,18 @@
package com.renkang.datacenter.bean;
import lombok.Data;
import java.io.Serializable;
/**
* @author Shunzhi Jiang
* @since 2023/11/5
*/
@Data
public class MqttTask implements Serializable {
private String watchNo;
private String taskName;
}
@@ -0,0 +1,20 @@
package com.renkang.datacenter.bean;
import lombok.Data;
import java.io.Serializable;
/**
* @author Shunzhi Jiang
* @since 2023/11/5
*/
@Data
public class Notice implements Serializable {
private String noticeTitle;
private String notice;
private String watchNo;
}
@@ -0,0 +1,24 @@
package com.renkang.datacenter.bean;
import lombok.Data;
import java.io.Serializable;
/**
* @author Shunzhi Jiang
* @since 2023/11/5
*/
@Data
public class Period implements Serializable {
private String watchNo;
private String wdType;
private Double warnMin;
private Double warnMax;
private Integer period;
}
@@ -0,0 +1,20 @@
package com.renkang.datacenter.bean;
import lombok.Data;
import java.io.Serializable;
/**
* @author Shunzhi Jiang
* @since 2023/11/5
*/
@Data
public class Rate implements Serializable {
private String watchNo;
private String wdType;
private Integer taskRate;
}
@@ -0,0 +1,20 @@
package com.renkang.datacenter.bean;
import lombok.Data;
import java.io.Serializable;
/**
* @author Shunzhi Jiang
* @since 2023/11/5
*/
@Data
public class WarnSwitch implements Serializable {
private String watchNo;
private String wdType;
private String switchFlag;
}
@@ -0,0 +1,20 @@
package com.renkang.datacenter.bean;
import lombok.Data;
import java.io.Serializable;
/**
* @author Shunzhi Jiang
* @since 2023/11/13
*/
@Data
public class WatchDataBase implements Serializable {
private static final long serialVersionUID = 1L;
private String id;
private String watchNo;
}
@@ -0,0 +1,18 @@
package com.renkang.datacenter.bean;
import lombok.Data;
import java.io.Serializable;
/**
* @author Shunzhi Jiang
* @since 2023/11/5
*/
@Data
public class WatchDataList implements Serializable {
private String watchNo;
private String queryDate;
}
@@ -0,0 +1,57 @@
package com.renkang.datacenter.bean;
import com.alibaba.fastjson.annotation.JSONField;
import lombok.Data;
import java.io.Serializable;
import java.util.List;
/**
* @author Shunzhi Jiang
* @since 2023/11/13
*/
@Data
public class WatchDataResult implements Serializable {
private String maxId;
@JSONField(alternateNames = "commonVoList")
private List<DataCommon> commonList;
@JSONField(alternateNames = "heartRateVoList")
private List<DataHeartRate> heartRateList;
@JSONField(alternateNames = "gpsVoList")
private List<DataGps> gpsList;
@JSONField(alternateNames = "sleepVoList")
private List<DataSleep> sleepList;
@JSONField(alternateNames = "sdcVoList")
private List<DataSdc> sdcList;
@JSONField(alternateNames = "tempVoList")
private List<DataTemperature> tempList;
@JSONField(alternateNames = "workoutVoList")
private List<DataWorkout> workoutList;
@JSONField(alternateNames = "stressVoList")
private List<DataStress> stressList;
@JSONField(alternateNames = "exerciseVoList")
private List<DataExercise> exerciseList;
@JSONField(alternateNames = "traceVoList")
private List<DataTrace> traceList;
@JSONField(alternateNames = "sleepNewVoList")
private List<DataSleepNew> sleepNewList;
@JSONField(alternateNames = "ecgVoList")
private List<DataEcg> ecgList;
@JSONField(alternateNames = "stepVoList")
private List<DataSteps> stepList;
}
@@ -0,0 +1,24 @@
package com.renkang.datacenter.bean;
import lombok.Data;
import java.io.Serializable;
@Data
public class WatchDevice implements Serializable {
/**
* 手表SN编码
*/
private String watchNo;
/**
* IMEI编码
*/
private String imeiNo;
/**
* EID编码
*/
private String eid;
private String watchModel;
}
@@ -0,0 +1,17 @@
package com.renkang.datacenter.bean;
import lombok.Data;
import java.io.Serializable;
import java.util.List;
/**
* @author Shunzhi Jiang
* @since 2023/11/5
*/
@Data
public class WatchDeviceBatch implements Serializable {
private List<WatchDevice> deviceVoList;
}
@@ -0,0 +1,20 @@
package com.renkang.datacenter.bean;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import java.io.Serializable;
/**
* @author Shunzhi Jiang
* @since 2023/11/5
*/
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
@Data
public class WatchDeviceSwitch extends DeviceSwitch implements Serializable {
private String watchNo;
}
@@ -0,0 +1,22 @@
package com.renkang.datacenter.bean;
import lombok.Data;
import java.io.Serializable;
/**
* @author Shunzhi Jiang
* @since 2023/11/5
*/
@Data
public class WatchNo implements Serializable {
private String watchNo;
public static WatchNo of(String watchNo) {
WatchNo instance = new WatchNo();
instance.setWatchNo(watchNo);
return instance;
}
}
@@ -0,0 +1,20 @@
package com.renkang.datacenter.bean;
import lombok.Data;
import java.io.Serializable;
/**
* @author Shunzhi Jiang
* @since 2023/11/5
*/
@Data
public class WatchSdcItemData implements Serializable {
private String watchNo;
private String wdType;
private String queryDate;
}
@@ -0,0 +1,22 @@
package com.renkang.datacenter.config;
/**
* @author Shunzhi Jiang
* @since 2023/11/3
*/
public interface DataCenterConstants {
//通知更新阈值及频率
String MQTT_CMD_UPDATE_PERIOD = "updatePeriod";
//通知更新定时任务
String MQTT_CMD_UPDATE_TASK = "updateTask";
//通知更新开关
String MQTT_CMD_UPDATE_SWITCH = "updateSwitch";
//通知手表上传数据
String MQTT_CMD_DATA_PUSH = "dataPush";
String REDIS_TOKEN_KEY = "DC_TOKEN";
String HEADER_TOKEN_KEY = "X-Access-Token";
}
@@ -0,0 +1,28 @@
package com.renkang.datacenter.config;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
/**
* @author Shunzhi Jiang
* @since 2023/11/3
*/
@Component
@ConfigurationProperties("datacenter")
@Data
public class DataCenterProperties {
private String url = "";
private String username;
private String password;
private String publicKey;
private Long timeout = 3000L;
private Integer pageSize = 500;
}
@@ -0,0 +1,12 @@
package com.renkang.datacenter.config;
/**
* @author Shunzhi Jiang
* @since 2023/11/3
*/
public interface ImcCenterConstants {
String IMC_LISTENER = "RestRetryImcListener";
String REDIS_TOKEN_KEY = "IMC_TOKEN";
}
@@ -0,0 +1,109 @@
package com.renkang.datacenter.config;
import lombok.Getter;
/**
* @author Shunzhi Jiang
* @since 2023/11/3
*/
@Getter
public enum MethodApi {
/**
* 获取令牌
*/
GET_TOKEN("sys/getToken"),
/**
* 添加设备
*/
ADD_DEVICE("watch/api/addDevice"),
/**
* 批量添加设备
*/
ADD_DEVICE_BATCH("watch/api/batchAddDevice"),
/**
* 删除设备
*/
REMOVE_DEVICE("watch/api/removeDevice?watchNo={watchNo}"),
/**
* 设备开关设置
*/
SET_SWITCH_STATUS("watch/api/setSwitchStatus"),
/**
* 设备开关全部设置
*/
SET_SWITCH_STATUS_ALL("watch/api/setAllSwitchStatus"),
/**
* 通知消息
*/
CMD_NOTICE("watch/mqtt/cmdNotice?watchNo={watchNo}&noticeTitle={noticeTitle}&notice={notice}"),
/**
* 通知消息
*/
CMD_NOTICE_MULTI("watch/mqtt/cmdNoticeMulti?watchNo={watchNo}&noticeTitle={noticeTitle}&notice={notice}"),
/**
* 推送数据通知
*/
CMD_DATA_PUSH("watch/mqtt/cmdDataPush?watchNo={watchNo}&taskName={taskName}"),
/**
* 全量数据获取
*/
WATCH_DATA_LIST("watch/api/getWatchDataList/{queryDate}?watchNo={watchNo}"),
/**
* 增量数据获取(页数)
*/
INCREASE_WATCH_DATA_PAGE_COUNT("watch/api/getIncreWatchDataPageCount/{wdType}/{id}/{pageSize}"),
/**
* 增量数据获取(数据)
*/
INCREASE_WATCH_DATA_PAGE_LIST("watch/api/getIncreWatchDataPageList/{wdType}/{id}/{pageNo}/{pageSize}"),
/**
* SDC详细数据获取
*/
WATCH_SDC_ITEM_DATA("watch/api/getWatchSdcItemData/{watchNo}/{queryDate}/{wdType}"),
/**
* 设备列表查询
*/
DEVICE_INFO_ALL("watch/api/getAllDeviceInfo?watchNo={watchNo}"),
/**
* 查询上传频率设置
*/
GET_RATE("watch/api/getRateByWatchNo?watchNo={watchNo}"),
/**
* 设置上传频率
*/
SAVE_RATE("watch/api/saveRateByNoAndWdType"),
/**
* 查询阈值设置
*/
GET_PERIOD("watch/api/getPeriodByWatchNo?watchNo={watchNo}"),
/**
* 设置阈值
*/
SAVE_PERIOD("watch/api/savePeriodByNoAndWdType"),
/**
* 查询报警开关设置
*/
GET_WARN_SWITCH("watch/api/getWarnListByWatchNo?watchNo={watchNo}"),
/**
* 设置报警开关
*/
SAVE_WARN_SWITCH("watch/api/saveWarnByNoAndWdType"),
// =======================影像中心============================
/**
* 查询影像人员信息
*/
GET_IMAGE_MESSAGE("imc/file/getImageMsg"),
/**
* 通过peId获取影像基本信息
*/
GET_IMAGE_ITEMS("imc/file/getImageItems"),
;
private final String url;
MethodApi(String url) {
this.url = url;
}
}
@@ -0,0 +1,40 @@
package com.renkang.datacenter.config;
import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.retry.annotation.EnableRetry;
import org.springframework.web.client.RestTemplate;
import java.nio.charset.StandardCharsets;
import java.time.Duration;
import java.time.temporal.ChronoUnit;
/**
* @author Shunzhi Jiang
* @since 2023/11/3
*/
@Configuration
@EnableRetry
public class RestConfig {
private final DataCenterProperties properties;
public RestConfig(DataCenterProperties properties) {
this.properties = properties;
}
@Bean
public RestTemplate dataCenterTemplate() {
return new RestTemplateBuilder()
.setConnectTimeout(Duration.of(properties.getTimeout(), ChronoUnit.MILLIS))
.additionalMessageConverters(
new StringHttpMessageConverter(StandardCharsets.UTF_8),
new MappingJackson2HttpMessageConverter()
)
.build();
}
}
@@ -0,0 +1,88 @@
package com.renkang.datacenter.config;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.renkang.datacenter.bean.Login;
import com.renkang.datacenter.util.RemoteUtils;
import lombok.extern.slf4j.Slf4j;
import org.jeecg.common.api.vo.Result;
import org.jeecg.util.RSAEncryptUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.retry.RetryContext;
import org.springframework.retry.RetryListener;
import org.springframework.retry.interceptor.MethodInvocationRetryCallback;
import org.springframework.retry.listener.MethodInvocationRetryListenerSupport;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import java.time.Duration;
/**
* @author Shunzhi Jiang
* @since 2023/11/3
*/
@Component(ImcCenterConstants.IMC_LISTENER)
@Slf4j
public class RestRetryImcListener extends MethodInvocationRetryListenerSupport implements RetryListener {
private RedisTemplate<String, Object> redisTemplate;
private DataCenterProperties properties;
@Autowired
public void setRedisTemplate(RedisTemplate<String, Object> redisTemplate) {
this.redisTemplate = redisTemplate;
}
@Autowired
public void setProperties(DataCenterProperties properties) {
this.properties = properties;
}
@Override
protected <T, E extends Throwable> boolean doOpen(RetryContext context, MethodInvocationRetryCallback<T, E> callback) {
String token = "";
try{
token = (String) redisTemplate.opsForValue().get(ImcCenterConstants.REDIS_TOKEN_KEY);
if (!StringUtils.hasLength(token)) {
token = refreshToken();
}
}catch (Exception e){
token = refreshToken();
}
RemoteUtils.TOKEN_CACHE.set(token);
return true;
}
@Override
protected <T, E extends Throwable> void doClose(RetryContext context, MethodInvocationRetryCallback<T, E> callback, Throwable throwable) {
RemoteUtils.TOKEN_CACHE.remove();
}
@Override
protected <T, E extends Throwable> void doOnError(RetryContext context, MethodInvocationRetryCallback<T, E> callback, Throwable throwable) {
String methodName = callback.getInvocation().getMethod().getName();
log.error("执行方法[{}]出错,刷新令牌后重试,当前重试次数:{}",methodName, context.getRetryCount(),throwable);
String token = refreshToken();
RemoteUtils.TOKEN_CACHE.set(token);
}
private String refreshToken() {
Login body = new Login();
body.setUsername(properties.getUsername());
body.setPassword(RSAEncryptUtils.encrypt1(properties.getPassword(),properties.getPublicKey()));
Result<Object> result = RemoteUtils.post(MethodApi.GET_TOKEN, body);
if (!result.isSuccess()) {
log.info("刷新数据中心令牌失败:{}",result.getMessage());
return null;
}
JSONObject data = (JSONObject) JSON.toJSON(result.getResult());
String token = data.getString("token");
redisTemplate.opsForValue().set(ImcCenterConstants.REDIS_TOKEN_KEY,token, Duration.ofDays(1));
log.info("刷新影像中心令牌成功:{}", token);
return token;
}
}
@@ -0,0 +1,88 @@
package com.renkang.datacenter.config;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.renkang.datacenter.bean.Login;
import com.renkang.datacenter.util.RemoteUtils;
import lombok.extern.slf4j.Slf4j;
import org.jeecg.common.api.vo.Result;
import org.jeecg.util.RSAEncryptUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.retry.RetryContext;
import org.springframework.retry.RetryListener;
import org.springframework.retry.interceptor.MethodInvocationRetryCallback;
import org.springframework.retry.listener.MethodInvocationRetryListenerSupport;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import java.time.Duration;
/**
* @author Shunzhi Jiang
* @since 2023/11/3
*/
@Component
@Slf4j
public class RestRetryListener extends MethodInvocationRetryListenerSupport implements RetryListener {
private RedisTemplate<String, Object> redisTemplate;
private DataCenterProperties properties;
@Autowired
public void setRedisTemplate(RedisTemplate<String, Object> redisTemplate) {
this.redisTemplate = redisTemplate;
}
@Autowired
public void setProperties(DataCenterProperties properties) {
this.properties = properties;
}
@Override
protected <T, E extends Throwable> boolean doOpen(RetryContext context, MethodInvocationRetryCallback<T, E> callback) {
String token = "";
try{
token = (String) redisTemplate.opsForValue().get(DataCenterConstants.REDIS_TOKEN_KEY);
if (!StringUtils.hasLength(token)) {
token = refreshToken();
}
}catch (Exception e){
token = refreshToken();
}
RemoteUtils.TOKEN_CACHE.set(token);
return true;
}
@Override
protected <T, E extends Throwable> void doClose(RetryContext context, MethodInvocationRetryCallback<T, E> callback, Throwable throwable) {
RemoteUtils.TOKEN_CACHE.remove();
}
@Override
protected <T, E extends Throwable> void doOnError(RetryContext context, MethodInvocationRetryCallback<T, E> callback, Throwable throwable) {
String methodName = callback.getInvocation().getMethod().getName();
log.error("执行方法[{}]出错,刷新令牌后重试,当前重试次数:{}",methodName, context.getRetryCount(),throwable);
String token = refreshToken();
RemoteUtils.TOKEN_CACHE.set(token);
}
private String refreshToken() {
Login body = new Login();
body.setUsername(properties.getUsername());
body.setPassword(RSAEncryptUtils.encrypt1(properties.getPassword(),properties.getPublicKey()));
Result<Object> result = RemoteUtils.post(MethodApi.GET_TOKEN, body);
if (!result.isSuccess()) {
log.info("刷新数据中心令牌失败:{}",result.getMessage());
return null;
}
JSONObject data = (JSONObject) JSON.toJSON(result.getResult());
String token = data.getString("token");
redisTemplate.opsForValue().set(DataCenterConstants.REDIS_TOKEN_KEY,token, Duration.ofDays(1));
log.info("刷新数据中心令牌成功:{}", token);
return token;
}
}
@@ -0,0 +1,116 @@
package com.renkang.datacenter.util;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.renkang.datacenter.config.DataCenterConstants;
import com.renkang.datacenter.config.DataCenterProperties;
import com.renkang.datacenter.config.MethodApi;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.util.SpringContextUtils;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.client.RestTemplate;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
/**
* @author Shunzhi Jiang
* @since 2023/11/3
*/
public class RemoteUtils {
public static final ThreadLocal<String> TOKEN_CACHE = new ThreadLocal<>();
private static RestTemplate restTemplate;
private static DataCenterProperties properties;
public static RestTemplate getRestTemplate() {
if (Objects.isNull(restTemplate)) {
restTemplate = SpringContextUtils.getBean("dataCenterTemplate", RestTemplate.class);
}
return restTemplate;
}
public static DataCenterProperties getProperties() {
if (Objects.isNull(properties)) {
properties = SpringContextUtils.getBean(DataCenterProperties.class);
}
return properties;
}
public static Result<Object> get(MethodApi api, Map<String, Object> params) {
return exchange(api, HttpMethod.GET, null, params);
}
public static String downloadAsString(String filepath) {
return getRestTemplate().getForObject(urlHandlerForFileDown(filepath), String.class);
}
public static Result<Object> get(MethodApi api) {
return exchange(api, HttpMethod.GET, null, null);
}
public static Result<Object> post(MethodApi api, Object body) {
return exchange(api, HttpMethod.POST, body, null);
}
public static Result<Object> post(MethodApi api, Object body, Map<String, Object> params) {
return exchange(api, HttpMethod.POST, body, params);
}
public static Result<Object> post(MethodApi api, Map<String, Object> params) {
return exchange(api, HttpMethod.POST, null, params);
}
private static Result<Object> exchange(MethodApi api, HttpMethod method, Object body, Map<String, Object> params) {
HttpHeaders headers = new HttpHeaders();
String token = TOKEN_CACHE.get();
if (StringUtils.hasLength(token)) {
headers.add(DataCenterConstants.HEADER_TOKEN_KEY, TOKEN_CACHE.get());
}
HttpEntity<?> entity = new HttpEntity<>(body, headers);
if (CollectionUtils.isEmpty(params)) {
return responseHandler(getRestTemplate().exchange(urlHandler(api), method, entity, String.class));
} else {
return responseHandler(getRestTemplate().exchange(urlHandler(api), method, entity, String.class, params));
}
}
private static String urlHandler(MethodApi api) {
return urlHandler(api.getUrl());
}
private static String urlHandler(String url) {
String baseUrl = getProperties().getUrl();
String path = url;
if (!baseUrl.endsWith("/") && !path.startsWith("/")) {
path = "/".concat(path);
}
return baseUrl + path;
}
private static String urlHandlerForFileDown(String url) {
String fileUrl = "file/down/".concat(url).replace("//", "/");
return urlHandler(fileUrl);
}
private static Result<Object> responseHandler(ResponseEntity<String> entity) {
String body = entity.getBody();
JSONObject responseJson = JSON.parseObject(body);
String message = Optional.ofNullable(responseJson.getString("message")).orElse("");
if (responseJson.getBoolean("success")) {
return Result.OK(message, responseJson.get("result"));
} else {
return Result.error(message);
}
}
}