|
@@ -1,6 +1,5 @@
|
|
|
package com.hfln.portal.infrastructure.mqtt;
|
|
package com.hfln.portal.infrastructure.mqtt;
|
|
|
|
|
|
|
|
-import cn.hfln.framework.extension.BizException;
|
|
|
|
|
import cn.hfln.framework.redis.util.RedisUtil;
|
|
import cn.hfln.framework.redis.util.RedisUtil;
|
|
|
import com.alibaba.fastjson2.JSON;
|
|
import com.alibaba.fastjson2.JSON;
|
|
|
import com.alibaba.fastjson2.JSONArray;
|
|
import com.alibaba.fastjson2.JSONArray;
|
|
@@ -9,10 +8,8 @@ import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
|
|
|
import com.hfln.portal.common.constant.mqtt.topic.TopicConstants;
|
|
import com.hfln.portal.common.constant.mqtt.topic.TopicConstants;
|
|
|
import com.hfln.portal.common.constant.redis.RedisCacheConstant;
|
|
import com.hfln.portal.common.constant.redis.RedisCacheConstant;
|
|
|
import com.hfln.portal.common.dto.data.user.SendMsgUserDto;
|
|
import com.hfln.portal.common.dto.data.user.SendMsgUserDto;
|
|
|
-import com.hfln.portal.common.request.room.SubRegionInfo;
|
|
|
|
|
import com.hfln.portal.domain.customer.util.MsgClient;
|
|
import com.hfln.portal.domain.customer.util.MsgClient;
|
|
|
import com.hfln.portal.domain.customer.util.WxOfficeAccountClient;
|
|
import com.hfln.portal.domain.customer.util.WxOfficeAccountClient;
|
|
|
-import com.hfln.portal.domain.exception.ErrorEnum;
|
|
|
|
|
import com.hfln.portal.infrastructure.po.*;
|
|
import com.hfln.portal.infrastructure.po.*;
|
|
|
import com.hfln.portal.infrastructure.service.*;
|
|
import com.hfln.portal.infrastructure.service.*;
|
|
|
import lombok.extern.slf4j.Slf4j;
|
|
import lombok.extern.slf4j.Slf4j;
|
|
@@ -22,12 +19,9 @@ import org.springframework.messaging.Message;
|
|
|
import org.springframework.stereotype.Component;
|
|
import org.springframework.stereotype.Component;
|
|
|
import org.springframework.util.CollectionUtils;
|
|
import org.springframework.util.CollectionUtils;
|
|
|
|
|
|
|
|
-import java.lang.reflect.Field;
|
|
|
|
|
import java.math.BigDecimal;
|
|
import java.math.BigDecimal;
|
|
|
import java.util.ArrayList;
|
|
import java.util.ArrayList;
|
|
|
-import java.util.HashMap;
|
|
|
|
|
import java.util.List;
|
|
import java.util.List;
|
|
|
-import java.util.Map;
|
|
|
|
|
|
|
|
|
|
@Component
|
|
@Component
|
|
|
@Slf4j
|
|
@Slf4j
|
|
@@ -311,40 +305,69 @@ public class MqttSubHandle {
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
+ //调用 发送短信和微信公众号通知 功能
|
|
|
|
|
+ sendMesAndWxService(sendList, devName, devId);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
- if (!CollectionUtils.isEmpty(sendList)) {
|
|
|
|
|
- for (SendMsgUserDto sendDto : sendList) {
|
|
|
|
|
- log.info("mqttutil--开始处理用户通知: userId={}, messageFlag={}, serviceNumberFlag={}",
|
|
|
|
|
- sendDto.getUserId(), sendDto.isMessageFlag(), sendDto.isServiceNumberFlag());
|
|
|
|
|
|
|
|
|
|
- // 根据短信标志位决定是否发送短信
|
|
|
|
|
- if (sendDto.isMessageFlag()) {
|
|
|
|
|
- log.info("mqttutil--开始发送跌倒短信: phone={}, dev_name={}", sendDto.getPhone(), devName.toString());
|
|
|
|
|
- msgClient.sendNotifyMsg(sendDto.getPhone(), devName.toString());
|
|
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 发送短信和微信公众号通知
|
|
|
|
|
+ * @param sendList 需要发送通知的用户列表
|
|
|
|
|
+ * @param devName 设备名称
|
|
|
|
|
+ * @param devId 设备ID
|
|
|
|
|
+ */
|
|
|
|
|
+ private void sendMesAndWxService(List<SendMsgUserDto> sendList, String devName, String devId) {
|
|
|
|
|
+ if (CollectionUtils.isEmpty(sendList)) {
|
|
|
|
|
+ log.info("没有需要发送通知的用户");
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ for (SendMsgUserDto sendDto : sendList) {
|
|
|
|
|
+ try {
|
|
|
|
|
+ log.info("mqttutil--开始处理用户通知: userId={}, messageFlag={}, serviceNumberFlag={}",
|
|
|
|
|
+ sendDto.getUserId(), sendDto.isMessageFlag(), sendDto.isServiceNumberFlag());
|
|
|
|
|
+
|
|
|
|
|
+ // 根据短信标志位决定是否发送短信
|
|
|
|
|
+ if (sendDto.isMessageFlag()) {
|
|
|
|
|
+ try {
|
|
|
|
|
+ log.info("mqttutil--开始发送跌倒短信: phone={}, dev_name={}", sendDto.getPhone(), devName);
|
|
|
|
|
+ msgClient.sendNotifyMsg(sendDto.getPhone(), devName);
|
|
|
log.info("mqttUtil--短信发送完成");
|
|
log.info("mqttUtil--短信发送完成");
|
|
|
- } else {
|
|
|
|
|
- log.info("用户拒绝短信通知: userId={}", sendDto.getUserId());
|
|
|
|
|
|
|
+ } catch (Exception e) {
|
|
|
|
|
+ log.error("发送短信失败: userId={}, phone={}, error={}",
|
|
|
|
|
+ sendDto.getUserId(), sendDto.getPhone(), e.getMessage(), e);
|
|
|
}
|
|
}
|
|
|
|
|
+ } else {
|
|
|
|
|
+ log.info("用户拒绝短信通知: userId={}", sendDto.getUserId());
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
- // 根据服务号标志位决定是否发送微信公众号消息
|
|
|
|
|
- if (sendDto.isServiceNumberFlag() && StringUtils.isNotBlank(sendDto.getFwhOpenId())) {
|
|
|
|
|
|
|
+ // 根据服务号标志位决定是否发送微信公众号消息
|
|
|
|
|
+ if (sendDto.isServiceNumberFlag() && StringUtils.isNotBlank(sendDto.getFwhOpenId())) {
|
|
|
|
|
+ try {
|
|
|
log.info("发送微信公众号信息:devName={}, phoneNo={}, fwhOpenId={}",
|
|
log.info("发送微信公众号信息:devName={}, phoneNo={}, fwhOpenId={}",
|
|
|
- devName.toString(), sendDto.getPhone(), sendDto.getFwhOpenId());
|
|
|
|
|
|
|
+ devName, sendDto.getPhone(), sendDto.getFwhOpenId());
|
|
|
// 发送微信公众号消息
|
|
// 发送微信公众号消息
|
|
|
- wxOfficeAccountClient.sendMsg(devId, devName.toString(), sendDto.getPhone(),
|
|
|
|
|
|
|
+ wxOfficeAccountClient.sendMsg(devId, devName, sendDto.getPhone(),
|
|
|
sendDto.getFwhOpenId(), "设备检测到跌倒,请前往小程序查看详细信息");
|
|
sendDto.getFwhOpenId(), "设备检测到跌倒,请前往小程序查看详细信息");
|
|
|
log.info("微信公众号消息发送完成");
|
|
log.info("微信公众号消息发送完成");
|
|
|
- } else {
|
|
|
|
|
- log.info("用户拒绝服务号通知或未绑定微信: userId={}, serviceNumberFlag={}, fwhOpenId={}",
|
|
|
|
|
- sendDto.getUserId(), sendDto.isServiceNumberFlag(), sendDto.getFwhOpenId());
|
|
|
|
|
|
|
+ } catch (Exception e) {
|
|
|
|
|
+ log.error("发送微信公众号消息失败: userId={}, fwhOpenId={}, error={}",
|
|
|
|
|
+ sendDto.getUserId(), sendDto.getFwhOpenId(), e.getMessage(), e);
|
|
|
}
|
|
}
|
|
|
|
|
+ } else {
|
|
|
|
|
+ log.info("用户拒绝服务号通知或未绑定微信: userId={}, serviceNumberFlag={}, fwhOpenId={}",
|
|
|
|
|
+ sendDto.getUserId(), sendDto.isServiceNumberFlag(), sendDto.getFwhOpenId());
|
|
|
}
|
|
}
|
|
|
- } else {
|
|
|
|
|
- log.info("没有需要发送通知的用户");
|
|
|
|
|
|
|
+
|
|
|
|
|
+ } catch (Exception e) {
|
|
|
|
|
+ log.error("处理用户通知异常: userId={}, error={}",
|
|
|
|
|
+ sendDto.getUserId(), e.getMessage(), e);
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+
|
|
|
public void subDasAlarmEvent(String topic, String payload) {
|
|
public void subDasAlarmEvent(String topic, String payload) {
|
|
|
|
|
|
|
|
log.info("Received device message: topic={}, payload={}", topic, payload);
|
|
log.info("Received device message: topic={}, payload={}", topic, payload);
|
|
@@ -576,174 +599,6 @@ public class MqttSubHandle {
|
|
|
redisUtil.sRemove(RedisCacheConstant.MQTT_CLIENT_USERID, deviceType + "_" + userId);
|
|
redisUtil.sRemove(RedisCacheConstant.MQTT_CLIENT_USERID, deviceType + "_" + userId);
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
+}
|
|
|
|
|
|
|
|
|
|
|
|
|
- /**
|
|
|
|
|
- * 调用房间家具保存接口的时候如果有更新发送MQTT消息通知算法
|
|
|
|
|
- */
|
|
|
|
|
- public void sendMqttMessage(String topicFormat, String devClientId) {
|
|
|
|
|
- String topic = String.format(topicFormat, devClientId);
|
|
|
|
|
- JSONObject msg = new JSONObject();
|
|
|
|
|
- msg.put("dev_id", devClientId);
|
|
|
|
|
-
|
|
|
|
|
- if (mqttClient != null) {
|
|
|
|
|
- try {
|
|
|
|
|
- mqttClient.sendMessage(topic, msg.toJSONString());
|
|
|
|
|
- log.info("Message sent successfully to topic: {}", topic);
|
|
|
|
|
- } catch (Exception e) {
|
|
|
|
|
- log.error("Failed to send message to topic: {}", topic, e);
|
|
|
|
|
- }
|
|
|
|
|
- } else {
|
|
|
|
|
- log.warn("MQTT client is not available, message not sent to topic: {}", topic);
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- /**
|
|
|
|
|
- * 调用房间家具保存接口的时候如果子区域有更新发送MQTT消息通知设备
|
|
|
|
|
- */
|
|
|
|
|
- public void sendSubRegionToDevice(String devClientId, List<SubRegionInfo> subRegions) {
|
|
|
|
|
- JSONArray extSubRegions = new JSONArray();
|
|
|
|
|
- for (SubRegionInfo region : subRegions) {
|
|
|
|
|
- JSONObject base = new JSONObject();
|
|
|
|
|
- base.put("x_cm_start", region.getStartXx());
|
|
|
|
|
- base.put("x_cm_stop", region.getStopXx());
|
|
|
|
|
- base.put("y_cm_start", region.getStartYy());
|
|
|
|
|
- base.put("y_cm_stop", region.getStopYy());
|
|
|
|
|
- base.put("presence_enter_duration", region.getPresenceEnterDuration());
|
|
|
|
|
- base.put("presence_exit_duration", region.getPresenceExitDuration());
|
|
|
|
|
- base.put("track_presence", region.getTrackPresence());
|
|
|
|
|
- base.put("exclude_falling", region.getExcludeFalling());
|
|
|
|
|
-
|
|
|
|
|
- JSONObject regionJson = new JSONObject();
|
|
|
|
|
- regionJson.put("base", base);
|
|
|
|
|
- regionJson.put("z_cm_start", region.getStartZz());
|
|
|
|
|
- regionJson.put("z_cm_stop", region.getStopZz());
|
|
|
|
|
- regionJson.put("is_low_snr", region.getIsLowSnr());
|
|
|
|
|
- regionJson.put("is_door", region.getIsDoor());
|
|
|
|
|
-
|
|
|
|
|
- extSubRegions.add(regionJson);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- JSONObject infoMsg = new JSONObject();
|
|
|
|
|
- infoMsg.put("ext_sub_regions", extSubRegions);
|
|
|
|
|
-
|
|
|
|
|
- String topicDev = String.format(TopicConstants.TOPIC_SET_DEVICE_PARAM, devClientId);
|
|
|
|
|
- try {
|
|
|
|
|
- mqttClient.sendMessage(topicDev, infoMsg.toJSONString());
|
|
|
|
|
- log.info("SubRegions message sent successfully to topic: {}", topicDev);
|
|
|
|
|
- } catch (Exception e) {
|
|
|
|
|
- log.error("Failed to send subRegions message to topic: {}", topicDev, e);
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- /**
|
|
|
|
|
- * web端修改设备参数之后通过MQTT发送到设备参数
|
|
|
|
|
- * @param clientId 设备客户端ID
|
|
|
|
|
- * @param params 设备参数(DeviceBandingParams或UpdateDeviceParams)
|
|
|
|
|
- */
|
|
|
|
|
- public void sendWebDeviceParamsToMqtt(String clientId, Object params) {
|
|
|
|
|
- String topic = String.format(TopicConstants.TOPIC_SET_DEVICE_PARAM, clientId);
|
|
|
|
|
-
|
|
|
|
|
- //构建检测区域
|
|
|
|
|
- Map<String, BigDecimal> base = new HashMap<>();
|
|
|
|
|
- base.put("x_cm_start", getFieldValue(params, "xxStart"));
|
|
|
|
|
- base.put("x_cm_stop", getFieldValue(params, "xxEnd"));
|
|
|
|
|
- base.put("y_cm_start", getFieldValue(params, "yyStart"));
|
|
|
|
|
- base.put("y_cm_stop", getFieldValue(params, "yyEnd"));
|
|
|
|
|
- base.put("z_cm_start", getFieldValue(params, "zzStart"));
|
|
|
|
|
- base.put("z_cm_stop", getFieldValue(params, "zzEnd"));
|
|
|
|
|
- Map<String, Map<String, BigDecimal>> baseParent = new HashMap<>();
|
|
|
|
|
- baseParent.put("base", base);
|
|
|
|
|
-
|
|
|
|
|
- //构建安装高度
|
|
|
|
|
- Map<String, BigDecimal> z_cm = new HashMap<>();
|
|
|
|
|
- z_cm.put("z_cm", getFieldValue(params, "height"));
|
|
|
|
|
-
|
|
|
|
|
- //构建跌倒确认时间
|
|
|
|
|
- Map<String, Integer> fallingStateMachineDurations = new HashMap<>();
|
|
|
|
|
- // 从参数中获取跌倒确认时间
|
|
|
|
|
- BigDecimal fallingConfirm = getFieldValue(params, "fallingConfirm");
|
|
|
|
|
- if (fallingConfirm != null && fallingConfirm.compareTo(BigDecimal.ZERO) > 0) {
|
|
|
|
|
- int confirmTime = fallingConfirm.intValue();
|
|
|
|
|
- fallingStateMachineDurations.put("durationUntilConfirm_sec", confirmTime);
|
|
|
|
|
- // minTimeOfTarInFallLoc_sec 是 durationUntilConfirm_sec的90%
|
|
|
|
|
- fallingStateMachineDurations.put("minTimeOfTarInFallLoc_sec", (int)(confirmTime * 0.9));
|
|
|
|
|
- // 固定默认值
|
|
|
|
|
- fallingStateMachineDurations.put("durationUntilCalling_sec", 13);
|
|
|
|
|
- fallingStateMachineDurations.put("durationUntilReset_sec", 3);
|
|
|
|
|
- } else {
|
|
|
|
|
- // 使用默认值
|
|
|
|
|
- fallingStateMachineDurations.put("durationUntilConfirm_sec", 53);
|
|
|
|
|
- fallingStateMachineDurations.put("minTimeOfTarInFallLoc_sec", 33);
|
|
|
|
|
- fallingStateMachineDurations.put("durationUntilCalling_sec", 13);
|
|
|
|
|
- fallingStateMachineDurations.put("durationUntilReset_sec", 3);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- //发送最终消息
|
|
|
|
|
- JSONObject jsonObject = new JSONObject();
|
|
|
|
|
- jsonObject.put("ext_region", baseParent);
|
|
|
|
|
- jsonObject.put("sensor_location", z_cm);
|
|
|
|
|
- jsonObject.put("fallingStateMachineDurations", fallingStateMachineDurations);
|
|
|
|
|
-
|
|
|
|
|
- try {
|
|
|
|
|
- mqttClient.sendMessage(topic, jsonObject.toJSONString());
|
|
|
|
|
- } catch (Exception e) {
|
|
|
|
|
- log.error("发送设备参数到MQTT失败", e);
|
|
|
|
|
- throw new BizException(ErrorEnum.MQTT_SEND_ERROR.getErrorCode(), ErrorEnum.MQTT_SEND_ERROR.getErrorMessage());
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- /**
|
|
|
|
|
- * 小程序端修改设备参数之后通过MQTT发送到设备参数
|
|
|
|
|
- * @param clientId 设备客户端ID
|
|
|
|
|
- * @param params 设备参数(DeviceBandingParams或UpdateDeviceParams)
|
|
|
|
|
- */
|
|
|
|
|
- public void sendDeviceParamsToMqtt(String clientId, Object params) {
|
|
|
|
|
- String topic = String.format(TopicConstants.TOPIC_SET_DEVICE_PARAM, clientId);
|
|
|
|
|
-
|
|
|
|
|
- //构建检测区域
|
|
|
|
|
- Map<String, BigDecimal> base = new HashMap<>();
|
|
|
|
|
- base.put("x_cm_start", getFieldValue(params, "xxStart"));
|
|
|
|
|
- base.put("x_cm_stop", getFieldValue(params, "xxEnd"));
|
|
|
|
|
- base.put("y_cm_start", getFieldValue(params, "yyStart"));
|
|
|
|
|
- base.put("y_cm_stop", getFieldValue(params, "yyEnd"));
|
|
|
|
|
- base.put("z_cm_start", getFieldValue(params, "zzStart"));
|
|
|
|
|
- base.put("z_cm_stop", getFieldValue(params, "zzEnd"));
|
|
|
|
|
- Map<String, Map<String, BigDecimal>> baseParent = new HashMap<>();
|
|
|
|
|
- baseParent.put("base", base);
|
|
|
|
|
-
|
|
|
|
|
- //构建安装高度
|
|
|
|
|
- Map<String, BigDecimal> z_cm = new HashMap<>();
|
|
|
|
|
- z_cm.put("z_cm", getFieldValue(params, "height"));
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
- //发送最终消息
|
|
|
|
|
- JSONObject jsonObject = new JSONObject();
|
|
|
|
|
- jsonObject.put("ext_region", baseParent);
|
|
|
|
|
- jsonObject.put("sensor_location", z_cm);
|
|
|
|
|
-
|
|
|
|
|
- try {
|
|
|
|
|
- mqttClient.sendMessage(topic, jsonObject.toJSONString());
|
|
|
|
|
- } catch (Exception e) {
|
|
|
|
|
- log.error("发送设备参数到MQTT失败", e);
|
|
|
|
|
- throw new BizException(ErrorEnum.MQTT_SEND_ERROR.getErrorCode(), ErrorEnum.MQTT_SEND_ERROR.getErrorMessage());
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- /**
|
|
|
|
|
- * 通过反射获取对象字段值
|
|
|
|
|
- * @param obj 对象
|
|
|
|
|
- * @param fieldName 字段名
|
|
|
|
|
- * @return 字段值
|
|
|
|
|
- */
|
|
|
|
|
- private BigDecimal getFieldValue(Object obj, String fieldName) {
|
|
|
|
|
- try {
|
|
|
|
|
- Field field = obj.getClass().getDeclaredField(fieldName);
|
|
|
|
|
- field.setAccessible(true);
|
|
|
|
|
- return (BigDecimal) field.get(obj);
|
|
|
|
|
- } catch (Exception e) {
|
|
|
|
|
- log.error("获取字段值失败: {}", fieldName, e);
|
|
|
|
|
- return BigDecimal.ZERO;
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-}
|
|
|