Commit fc6176f2 by huangjy

fix: 实时监控状态

parent 54b0bd29
......@@ -10,7 +10,7 @@ public class StandardDeviationUtil {
* @param x
* @return 平均值
*/
public static double average(double[] x) {
public static double average(Double[] x) {
int n = x.length; //数列元素个数
double sum = 0;
for (double i : x) { //求和
......@@ -35,7 +35,7 @@ public class StandardDeviationUtil {
* @param x 要计算的数列
* @return 方差
*/
public static double variance(double[] x) {
public static double variance(Double[] x) {
int n = x.length; //数列元素个数
double avg = average(x); //求平均值
double var = 0;
......@@ -62,7 +62,7 @@ public class StandardDeviationUtil {
* @param x 要计算的数列
* @return 标准差
*/
public static double standardDeviation(double[] x) {
public static double standardDeviation(Double[] x) {
return Math.sqrt(variance(x));
}
......
......@@ -6,10 +6,11 @@ import com.makeit.utils.sys.SysDictUtil;
public class PlatElderRealtimeReportEnum {
public enum NowStatus implements BaseEnum {
OUT("elder.realtime.now.status.out"),
RUN("elder.realtime.now.status.run"),
REST("elder.realtime.now.status.rest"),
BED("elder.realtime.now.status.bed"),
SLEEP("elder.realtime.now.status.sleep");
RUN("elder.realtime.now.status.noBed.run"),
REST("elder.realtime.now.status.noBen.rest"),
BED("elder.realtime.now.status.bed.rest"),
SLEEP("elder.realtime.now.status.bed.sleep"),
SPORT("elder.realtime.now.status.bed.sport");
private String code;
......
......@@ -26,7 +26,6 @@ import com.makeit.service.saas.SaasSleepAnalysisModelService;
import com.makeit.utils.StandardDeviationUtil;
import com.makeit.utils.data.convert.StreamUtil;
import com.makeit.utils.data.validate.CollectionUtils;
import com.makeit.utils.old.StringUtils;
import com.makeit.utils.redis.RedisUtil;
import com.makeit.vo.platform.elder.realtime.PlatElderCoordinateVO;
import com.makeit.vo.platform.elder.realtime.PlatElderRealTimeBodyVO;
......@@ -34,6 +33,7 @@ import com.makeit.vo.platform.elder.realtime.PlatElderRealTimeHeartRespiratoryVO
import com.makeit.vo.platform.elder.realtime.PlatElderRealTimeNowVO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.RandomUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
......@@ -41,11 +41,9 @@ import org.springframework.stereotype.Service;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import java.util.stream.Stream;
......@@ -71,6 +69,13 @@ public class PlatElderRealTimeServiceImpl implements PlatElderRealTimeService {
public static final String DEVICE_SPACE_DATA = "device:space:data:";
public static final String DEVICE_FALL_DATA = "device:fall:data:";
public static final String DEVICE_BR_ANALYSIS = "device:brhr:analysis:";
public static final String SLEEP_ANALYSIS_THRESHOLD_KEY = "saas:sleep:analysis:threshold";
public static final String DEVICE_SPACE_TEMP_DATA = "device:space:tempData:";
@Autowired
private PlatElderService platElderService;
......@@ -238,7 +243,8 @@ public class PlatElderRealTimeServiceImpl implements PlatElderRealTimeService {
}
if (CollectionUtils.isNotEmpty(coordinateList)) {
double v = StandardDeviationUtil.average(StreamUtil.map(coordinateList, e -> e.getDistance().doubleValue()));
Double[] doubleArr = coordinateList.stream().map(e -> e.getDistance().doubleValue()).toArray(Double[]::new);
double v = StandardDeviationUtil.variance(doubleArr);
if (new BigDecimal(v + "").compareTo(new BigDecimal(2)) > 0) {
platElderRealTimeNowVO.setStatus((PlatElderRealtimeReportEnum.NowStatus.RUN.getValue()));
}
......@@ -310,60 +316,151 @@ public class PlatElderRealTimeServiceImpl implements PlatElderRealTimeService {
@Override
public PlatElderRealTimeNowVO nowStatus(PlatElderIdDTO platElderIdDTO) {
PlatElderRealTimeNowVO platElderRealTimeNowVO = new PlatElderRealTimeNowVO();
platElderRealTimeNowVO.setStatus(PlatElderRealtimeReportEnum.NowStatus.RUN.getValue());
PlatDevice platDevice = getBreathDevice(platElderIdDTO.getElderId(), platElderIdDTO.getDeviceId());
if (platDevice == null) {
return platElderRealTimeNowVO;
}
String brResult = redisTemplate.opsForValue().get(DEVICE_BR_DATA + platDevice.getOriDeviceId());
if (brResult != null) {
JSONObject jsonObject = JSON.parseObject(brResult);
String person = jsonObject.getString("person");
String personState = jsonObject.getString("personState");
log.info("当前人员人员状态:{}",person);
if (StringUtils.equals(person,"1")) {
platElderRealTimeNowVO.setStatus(PlatElderRealtimeReportEnum.NowStatus.BED.getValue());
return platElderRealTimeNowVO;
// 在床运动
if (StringUtils.equals(personState,"1")) {
platElderRealTimeNowVO.setStatus(PlatElderRealtimeReportEnum.NowStatus.SPORT.getValue());
return platElderRealTimeNowVO;
}
// 在床静息
if (StringUtils.equals(personState,"2")) {
platElderRealTimeNowVO.setStatus(PlatElderRealtimeReportEnum.NowStatus.BED.getValue());
return platElderRealTimeNowVO;
}
// 判断是否在床睡觉
Integer sleepTimeActionThreshold = getSleepTimeActionThreshold();
Map<Object, Object> entries = redisTemplate.opsForHash().entries(DEVICE_BR_ANALYSIS + platDevice.getOriDeviceId());
Collection<Object> values = entries.values();
Predicate<Object> predicate = entity -> {
JSONObject result = JSON.parseObject(entity.toString());
Integer bodymove = Integer.valueOf(result.getString("bodymove"));
return bodymove.compareTo(sleepTimeActionThreshold) <= 0;
};
boolean sleepFlag = values.stream().allMatch(predicate);
if (sleepFlag) {
platElderRealTimeNowVO.setStatus(PlatElderRealtimeReportEnum.NowStatus.SLEEP.getValue());
return platElderRealTimeNowVO;
}
}
}
return platElderRealTimeNowVO;
List<PlatDevice> spaceDeviceList = getSpaceDevice(platElderIdDTO.getElderId(), platElderIdDTO.getDeviceId());
List<PlatDevice> fallDeviceList = getFallDevice(platElderIdDTO.getElderId(), platElderIdDTO.getDeviceId());
boolean sportFlag = true;
boolean hasPeronFlag = true; // 有没有人
for (PlatDevice device : spaceDeviceList) {
// 无人
Map<Object, Object> entries = redisTemplate.opsForHash().entries(DEVICE_SPACE_TEMP_DATA + device.getOriDeviceId());
if (entries.isEmpty()) {
continue;
}
Collection<Object> values = entries.values();
List<PlatElderCoordinateVO> voList = values.stream().map(entity -> {
PlatElderCoordinateVO vo = new PlatElderCoordinateVO();
JSONObject result = JSON.parseObject(entity.toString());
String distance = result.getString("distance");
String angle = result.getString("angle");
BigDecimal x = new BigDecimal(distance).multiply(BigDecimal.valueOf(Math.cos(Double.parseDouble(angle)))
.setScale(2, RoundingMode.HALF_UP));
BigDecimal y = new BigDecimal(distance).multiply(BigDecimal.valueOf(Math.sin(Math.cos(Double.parseDouble(angle))))
.setScale(2, RoundingMode.HALF_UP));
vo.setX(x);
vo.setY(y);
vo.setPersonState(Integer.valueOf(result.getString("personState")));
return vo;
}).collect(Collectors.toList());
boolean noPersonFlag = voList.stream().allMatch(e -> e.getPersonState() == 0);
if (noPersonFlag) {
platElderRealTimeNowVO.setStatus(PlatElderRealtimeReportEnum.NowStatus.OUT.getValue());
return platElderRealTimeNowVO;
}
/* Object result = RedisUtil.get(ELDER_STATUS + platElderIdDTO.getElderId());
if (result != null) {
return JSON.parseObject(result.toString(), PlatElderRealTimeNowVO.class);
}
Double[] doubleArrX = voList.stream().map(e -> e.getX().doubleValue()).toArray(Double[]::new);
double x = StandardDeviationUtil.variance(doubleArrX);
boolean xFlag = new BigDecimal(x + "").compareTo(new BigDecimal(2)) > 0;
DeviceInfoContentBreathe deviceInfoContentBreathe = getNowDataBreathe(platElderIdDTO.getElderId(), platElderIdDTO.getDeviceId());
//
if (deviceInfoContentBreathe == null) {
Double[] doubleArrY = voList.stream().map(e -> e.getY().doubleValue()).toArray(Double[]::new);
double y = StandardDeviationUtil.variance(doubleArrY);
boolean yFlag = new BigDecimal(y + "").compareTo(new BigDecimal(2)) > 0;
if (xFlag && yFlag) {
platElderRealTimeNowVO.setStatus(PlatElderRealtimeReportEnum.NowStatus.RUN.getValue());
return platElderRealTimeNowVO;
} else {
sportFlag = false;
}
}
for (PlatDevice device : fallDeviceList) {
// 无人
Map<Object, Object> entries = redisTemplate.opsForHash().entries(DEVICE_FALL_DATA + device.getOriDeviceId());
if (entries.isEmpty()) {
continue;
}
Collection<Object> values = entries.values();
List<PlatElderCoordinateVO> voList = values.stream().map(entity -> {
PlatElderCoordinateVO vo = new PlatElderCoordinateVO();
JSONObject result = JSON.parseObject(entity.toString());
Object track = result.get("track");
List<Integer> list = track == null ? Lists.newArrayList() : (List<Integer>) track;
String distance = result.getString("track");
BigDecimal x = new BigDecimal(distance).multiply(BigDecimal.valueOf(Math.cos(Double.parseDouble(list.get(1) + "")))
.setScale(2, RoundingMode.HALF_UP));
BigDecimal y = new BigDecimal(distance).multiply(BigDecimal.valueOf(Math.sin(Math.cos(Double.parseDouble(list.get(2) + ""))))
.setScale(2, RoundingMode.HALF_UP));
vo.setX(x);
vo.setY(y);
vo.setPersonState(Integer.valueOf(result.getString("personState")));
return vo;
}).collect(Collectors.toList());
boolean noPersonFlag = voList.stream().allMatch(e -> e.getPersonState() == 0);
if (noPersonFlag) {
platElderRealTimeNowVO.setStatus(PlatElderRealtimeReportEnum.NowStatus.OUT.getValue());
return platElderRealTimeNowVO;
}
Double[] doubleArrX = voList.stream().map(e -> e.getX().doubleValue()).toArray(Double[]::new);
double x = StandardDeviationUtil.variance(doubleArrX);
boolean xFlag = new BigDecimal(x + "").compareTo(new BigDecimal(2)) > 0;
Double[] doubleArrY = voList.stream().map(e -> e.getY().doubleValue()).toArray(Double[]::new);
double y = StandardDeviationUtil.variance(doubleArrY);
boolean yFlag = new BigDecimal(y + "").compareTo(new BigDecimal(2)) > 0;
if (xFlag && yFlag) {
platElderRealTimeNowVO.setStatus(PlatElderRealtimeReportEnum.NowStatus.RUN.getValue());
return platElderRealTimeNowVO;
} else {
sportFlag = false;
}
}
if (!sportFlag) {
platElderRealTimeNowVO.setStatus(PlatElderRealtimeReportEnum.NowStatus.REST.getValue());
return platElderRealTimeNowVO;
}
//platElderRealTimeNowVO.setStatus(deviceInfoContentBreathe.getProperties().getPersonState() + "");
nowStatusOut(platElderRealTimeNowVO, platElderIdDTO);
LocalDateTime now = LocalDateTime.now();
LocalDateTime start = now.minusSeconds(10);
List<PlatElderCoordinateVO> coordinateList = platElderDayReportDayService.coordinateList(platElderIdDTO.getElderId(), platElderIdDTO.getDeviceId(), start, now);
nowStatusRun(platElderRealTimeNowVO, platElderIdDTO, deviceInfoContentBreathe, coordinateList);
nowStatusRest(platElderRealTimeNowVO, platElderIdDTO, deviceInfoContentBreathe, coordinateList);
nowStatusSleepAndBed(platElderRealTimeNowVO, platElderIdDTO, deviceInfoContentBreathe);
// if(StringUtils.isBlank(platElderRealTimeNowVO.getStatus())){
// platElderRealTimeNowVO.setStatus();
// }
platElderRealTimeNowVO.setHeartRate(deviceInfoContentBreathe.getProperties().getHr());
platElderRealTimeNowVO.setRespiratoryRate(deviceInfoContentBreathe.getProperties().getBr());
platElderRealTimeNowVO.setBodyMove(deviceInfoContentBreathe.getProperties().getBodymove());
RedisUtil.set(ELDER_STATUS + platElderIdDTO.getElderId(), JSON.toJSONString(platElderRealTimeNowVO), 10, TimeUnit.SECONDS);
return platElderRealTimeNowVO;
*/
}
private Integer getSleepTimeActionThreshold() {
Integer sleepTimeActionThreshold;
String result = redisTemplate.opsForValue().get(SLEEP_ANALYSIS_THRESHOLD_KEY);
if (result != null) {
sleepTimeActionThreshold = Integer.parseInt(result);
} else {
SaasSleepAnalysisModel analysisModel = saasSleepAnalysisModelService.getOne(new QueryWrapper<SaasSleepAnalysisModel>().lambda()
.orderByDesc(BaseEntity::getCreateBy)
.last("limit 1"));
redisTemplate.opsForValue().set(SLEEP_ANALYSIS_THRESHOLD_KEY,analysisModel.getSleepTimeActionThreshold(),1,TimeUnit.DAYS);
sleepTimeActionThreshold = Integer.parseInt(analysisModel.getSleepTimeActionThreshold());
}
return sleepTimeActionThreshold;
}
@Override
......
......@@ -3,6 +3,7 @@ package com.makeit.vo.platform.elder.realtime;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.math.BigDecimal;
import java.util.List;
@Data
......@@ -31,5 +32,9 @@ public class PlatElderCoordinateVO {
@ApiModelProperty("跌倒设备轨迹")
private List<Integer> track;
@ApiModelProperty("x")
private BigDecimal x;
@ApiModelProperty("y")
private BigDecimal y;
}
......@@ -2,15 +2,19 @@ package com.makeit.mqtt;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.makeit.common.entity.BaseEntity;
import com.makeit.dto.platform.alarm.PlatAlarmCheckDTO;
import com.makeit.entity.platform.alarm.PlatAlarmConfig;
import com.makeit.entity.platform.device.PlatDevice;
import com.makeit.entity.saas.analysis.SaasSleepAnalysisModel;
import com.makeit.global.aspect.tenant.TenantIdIgnore;
import com.makeit.module.iot.enums.DeviceState;
import com.makeit.module.iot.vo.DeviceInfo;
import com.makeit.module.iot.vo.HeaderInfo;
import com.makeit.service.platform.alarm.alarmStrategy.IAlarm;
import com.makeit.service.platform.device.PlatDeviceService;
import com.makeit.service.saas.SaasSleepAnalysisModelService;
import com.makeit.utils.AlarmConfigCacheUtil;
import com.makeit.utils.DeviceCacheUtil;
import org.apache.commons.collections4.CollectionUtils;
......@@ -39,6 +43,12 @@ public class PushCallback implements MqttCallback {
public static final String DEVICE_SPACE_DATA = "device:space:data:";
public static final String DEVICE_FALL_DATA = "device:fall:data:";
public static final String SLEEP_ANALYSIS_KEY = "saas:sleep:analysis";
public static final String DEVICE_BR_ANALYSIS = "device:brhr:analysis:";
public static final String DEVICE_SPACE_TEMP_DATA = "device:space:tempData:";
public static final String DEVICE_FALL_TEMP_DATA = "device:fall:tempData:";
public static final String REPORT_PROPERTY = "REPORT_PROPERTY";
@Autowired
private MqttConfig mqttConfig;
......@@ -56,6 +66,8 @@ public class PushCallback implements MqttCallback {
private PlatDeviceService platDeviceService;
@Autowired
private StringRedisTemplate redisTemplate;
@Autowired
private SaasSleepAnalysisModelService saasSleepAnalysisModelService;
@Override
......@@ -97,16 +109,45 @@ public class PushCallback implements MqttCallback {
public void checkAlarm(DeviceInfo device) {
HeaderInfo headers = device.getHeaders();
List<HeaderInfo.Bind> bindings = headers.getBindings();
Long timestamp = device.getTimestamp();
// TODO 先这样判断
if (REPORT_PROPERTY.equals(device.getMessageType()) && headers.getProductName().contains("呼吸")) {
// 缓存呼吸设备某段时间的数据,hash 最大长度 duration
Long duration = getSleepTimeActionDuration();
Long size = redisTemplate.opsForHash().size(DEVICE_BR_ANALYSIS + device.getDeviceId());
if (size.equals(duration)) {
redisTemplate.opsForHash().delete(DEVICE_BR_ANALYSIS + device.getDeviceId(),timestamp - duration);
}
redisTemplate.opsForHash().put(DEVICE_BR_ANALYSIS + device.getDeviceId(), timestamp,JSON.toJSONString(device.getProperties()));
redisTemplate.expire(DEVICE_BR_ANALYSIS + device.getDeviceId(),duration,TimeUnit.MINUTES);
redisTemplate.opsForValue().set(DEVICE_BR_DATA + device.getDeviceId(),JSON.toJSONString(device.getProperties()),
5000, TimeUnit.MILLISECONDS);
}
if (REPORT_PROPERTY.equals(device.getMessageType()) && headers.getProductName().contains("空间")) {
Long maxSize = 10L;
Long size = redisTemplate.opsForHash().size(DEVICE_SPACE_TEMP_DATA + device.getDeviceId());
if (size.equals(maxSize)) {
redisTemplate.opsForHash().delete(DEVICE_SPACE_TEMP_DATA + device.getDeviceId(),timestamp - maxSize);
}
redisTemplate.opsForHash().put(DEVICE_SPACE_TEMP_DATA + device.getDeviceId(), timestamp,JSON.toJSONString(device.getProperties()));
redisTemplate.expire(DEVICE_SPACE_TEMP_DATA + device.getDeviceId(),maxSize + 1,TimeUnit.SECONDS);
redisTemplate.opsForValue().set(DEVICE_SPACE_DATA + device.getDeviceId(),JSON.toJSONString(device.getProperties()),
5000, TimeUnit.MILLISECONDS);
}
if (REPORT_PROPERTY.equals(device.getMessageType()) && headers.getProductName().contains("跌倒")) {
Long maxSize = 10L;
Long size = redisTemplate.opsForHash().size(DEVICE_FALL_TEMP_DATA + device.getDeviceId());
if (size.equals(maxSize)) {
redisTemplate.opsForHash().delete(DEVICE_FALL_TEMP_DATA + device.getDeviceId(),timestamp - maxSize);
}
redisTemplate.opsForHash().put(DEVICE_FALL_TEMP_DATA + device.getDeviceId(), timestamp,JSON.toJSONString(device.getProperties()));
redisTemplate.expire(DEVICE_FALL_TEMP_DATA + device.getDeviceId(),maxSize + 1,TimeUnit.SECONDS);
redisTemplate.opsForValue().set(DEVICE_FALL_DATA + device.getDeviceId(),JSON.toJSONString(device.getProperties()),
5000, TimeUnit.MILLISECONDS);
}
......@@ -168,6 +209,20 @@ public class PushCallback implements MqttCallback {
}
private Long getSleepTimeActionDuration() {
String sleepTimeActionDuration = "";
String result = redisTemplate.opsForValue().get(SLEEP_ANALYSIS_KEY);
if (result != null) {
sleepTimeActionDuration = result;
} else {
SaasSleepAnalysisModel analysisModel = saasSleepAnalysisModelService.getOne(new QueryWrapper<SaasSleepAnalysisModel>().lambda()
.orderByDesc(BaseEntity::getCreateBy)
.last("limit 1"));
redisTemplate.opsForValue().set(SLEEP_ANALYSIS_KEY,analysisModel.getSleepTimeActionDuration(),1,TimeUnit.DAYS);
sleepTimeActionDuration = analysisModel.getSleepTimeActionDuration();
}
return Long.parseLong(sleepTimeActionDuration) * 60;
}
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment