From a3360878835e4606c968441e432b0c3d4bd921ae Mon Sep 17 00:00:00 2001
From: sean.zhou <sean.zhou@dji.com>
Date: Fri, 23 Sep 2022 18:04:07 +0800
Subject: [PATCH] V1.2.0

---
 src/main/java/com/dji/sample/manage/service/impl/DeviceHmsServiceImpl.java |  172 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 172 insertions(+), 0 deletions(-)

diff --git a/src/main/java/com/dji/sample/manage/service/impl/DeviceHmsServiceImpl.java b/src/main/java/com/dji/sample/manage/service/impl/DeviceHmsServiceImpl.java
index 61c13ee..2b76e49 100644
--- a/src/main/java/com/dji/sample/manage/service/impl/DeviceHmsServiceImpl.java
+++ b/src/main/java/com/dji/sample/manage/service/impl/DeviceHmsServiceImpl.java
@@ -43,6 +43,8 @@
 import java.time.LocalDateTime;
 import java.time.ZoneId;
 import java.util.*;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
 import java.util.stream.Collectors;
 
 /**
@@ -69,9 +71,61 @@
     @Autowired
     private WebSocketManageServiceImpl webSocketManageService;
 
+    private static final Pattern PATTERN_KEY = Pattern.compile(
+            HmsEnum.FormatKeyEnum.KEY_START +
+                    "(" +
+                    Arrays.stream(HmsEnum.FormatKeyEnum.values())
+                            .map(HmsEnum.FormatKeyEnum::getKey)
+                            .collect(Collectors.joining("|")) +
+                    ")");
+
     @Override
     @ServiceActivator(inputChannel = ChannelName.INBOUND_EVENTS_HMS)
     public void handleHms(CommonTopicReceiver receiver, MessageHeaders headers) {
+        String topic = headers.get(MqttHeaders.RECEIVED_TOPIC).toString();
+        String sn  = topic.substring((TopicConst.THING_MODEL_PRE + TopicConst.PRODUCT).length(),
+                topic.indexOf(TopicConst.EVENTS_SUF));
+
+        DeviceHmsEntity entity = DeviceHmsEntity.builder()
+                .bid(receiver.getBid())
+                .tid(receiver.getTid())
+                .createTime(receiver.getTimestamp())
+                .updateTime(0L)
+                .sn(sn)
+                .build();
+        String key = RedisConst.HMS_PREFIX + sn;
+        // Query all unread hms messages of the device in redis.
+        Set<String> hmsMap = redisOps.listGetAll(key).stream().map(String::valueOf).collect(Collectors.toSet());
+
+        DeviceDTO device = (DeviceDTO) redisOps.get(RedisConst.DEVICE_ONLINE_PREFIX + sn);
+
+        List<DeviceHmsDTO> unReadList = new ArrayList<>();
+        objectMapper.convertValue(((Map) (receiver.getData())).get(MapKeyConst.LIST),
+                new TypeReference<List<DeviceHmsReceiver>>() {})
+                .forEach(hmsReceiver -> {
+                    final DeviceHmsEntity hms = entity.clone();
+                    this.fillEntity(hms, hmsReceiver);
+                    // The same unread hms are no longer incremented.
+                    if (hmsMap.contains(hms.getHmsKey())) {
+                        return;
+                    }
+                    this.fillMessage(hms, hmsReceiver.getArgs());
+                    unReadList.add(entity2Dto(hms));
+                    mapper.insert(hms);
+                });
+
+        if (unReadList.isEmpty()) {
+            return;
+        }
+        redisOps.listRPush(key, unReadList.stream().map(DeviceHmsDTO::getKey).toArray(String[]::new));
+        // push to the web
+        Collection<ConcurrentWebSocketSession> sessions = webSocketManageService.getValueWithWorkspaceAndUserType(
+                device.getWorkspaceId(), UserTypeEnum.WEB.getVal());
+        sendMessageService.sendBatch(sessions, CustomWebSocketMessage.builder()
+                .bizCode(BizCodeEnum.DEVICE_HMS.getCode())
+                .data(TelemetryDTO.<List<DeviceHmsDTO>>builder().sn(sn).host(unReadList).build())
+                .timestamp(System.currentTimeMillis())
+                .build());
     }
 
     @Override
@@ -107,6 +161,7 @@
                 new LambdaUpdateWrapper<DeviceHmsEntity>()
                         .eq(DeviceHmsEntity::getSn, deviceSn)
                         .eq(DeviceHmsEntity::getUpdateTime, 0L));
+        // Delete unread messages cached in redis.
         redisOps.del(RedisConst.HMS_PREFIX + deviceSn);
     }
 
@@ -130,4 +185,121 @@
                 .build();
     }
 
+    /**
+     * Populate the received data into the entity. Please refer to the documentation for splicing rules.
+     * @param dto
+     * @param receiver
+     */
+    private void fillEntity(DeviceHmsEntity dto, DeviceHmsReceiver receiver) {
+        dto.setLevel(receiver.getLevel());
+        dto.setModule(receiver.getModule());
+        dto.setHmsId(UUID.randomUUID().toString());
+
+        if (HmsEnum.DomainType.DRONE_NEST.getDomain().equals(receiver.getDomainType())) {
+            dto.setHmsKey(HmsEnum.HmsFaqIdEnum.DOCK_TIP.getText() + receiver.getCode());
+            return;
+        }
+        StringBuilder key = new StringBuilder(HmsEnum.HmsFaqIdEnum.FPV_TIP.getText()).append(receiver.getCode());
+
+        if (receiver.getInTheSky() == HmsEnum.IN_THE_SKY.getVal()) {
+            key.append(HmsEnum.IN_THE_SKY.getText());
+        }
+        dto.setHmsKey(key.toString());
+    }
+
+    /**
+     * Replace wildcards in messages according to the relevant rules.
+     * Please refer to the documentation for splicing rules.
+     * @param dto
+     * @param args
+     */
+    private void fillMessage(DeviceHmsEntity dto, HmsArgsReceiver args) {
+        HmsMessage hmsMessage = HmsJsonUtil.get(dto.getHmsKey());
+        String zh = StringUtils.hasText(hmsMessage.getZh()) ? hmsMessage.getZh() : String.format("未知错误(%s)", dto.getHmsKey());
+        String en = StringUtils.hasText(hmsMessage.getEn()) ? hmsMessage.getEn() : String.format("Unknown(%s)", dto.getHmsKey());//
+
+        dto.setMessageZh(format(Locale.CHINESE.getLanguage(), zh, args));
+        dto.setMessageEn(format(Locale.ENGLISH.getLanguage(), en, args));
+    }
+
+    /**
+     * Set the matching parameters for key.
+     * @param l     language: zh or en
+     * @param hmsArgs
+     * @return
+     */
+    private List<String> fillKeyArgs(String l, HmsArgsReceiver hmsArgs) {
+        List<String> args = new ArrayList<>();
+        args.add(Objects.nonNull(hmsArgs.getAlarmId()) ? Long.toHexString(hmsArgs.getAlarmId()) : null);
+        args.add(Objects.nonNull(hmsArgs.getComponentIndex()) ? String.valueOf(hmsArgs.getComponentIndex() + 1) : null);
+        if (Objects.nonNull(hmsArgs.getSensorIndex())) {
+            args.add(String.valueOf(hmsArgs.getSensorIndex() + 1));
+
+            HmsEnum.HmsBatteryIndexEnum hmsBatteryIndexEnum = HmsEnum.HmsBatteryIndexEnum.find(hmsArgs.getSensorIndex());
+            HmsEnum.HmsDockCoverIndexEnum hmsDockCoverIndexEnum = HmsEnum.HmsDockCoverIndexEnum.find(hmsArgs.getSensorIndex());
+            HmsEnum.HmsChargingRodIndexEnum hmsChargingRodIndexEnum = HmsEnum.HmsChargingRodIndexEnum.find(hmsArgs.getSensorIndex());
+
+            switch (l) {
+                case "zh":
+                    args.add(hmsBatteryIndexEnum.getZh());
+                    args.add(hmsDockCoverIndexEnum.getZh());
+                    args.add(hmsChargingRodIndexEnum.getZh());
+                    break;
+                case "en":
+                    args.add(hmsBatteryIndexEnum.getEn());
+                    args.add(hmsDockCoverIndexEnum.getEn());
+                    args.add(hmsChargingRodIndexEnum.getEn());
+                    break;
+                default:
+                    break;
+            }
+
+        }
+        return args;
+    }
+
+    /**
+     * Returns a formatted string using the specified locale, format string, and arguments.
+     * @param l language: zh or en
+     * @param format
+     * @param hmsArgs
+     * @return
+     */
+    private String format(String l, String format, HmsArgsReceiver hmsArgs) {
+        List<String> args = fillKeyArgs(l, hmsArgs);
+        List<String> list = parse(format);
+        StringBuilder sb = new StringBuilder();
+        for (String word : list) {
+            if (!StringUtils.hasText(word)) {
+                continue;
+            }
+            HmsEnum.FormatKeyEnum keyEnum = HmsEnum.FormatKeyEnum.find(word.substring(1));
+            sb.append(HmsEnum.FormatKeyEnum.KEY_START != word.charAt(0) || HmsEnum.FormatKeyEnum.UNKNOWN == keyEnum ?
+                    word : args.get(keyEnum.getIndex()));
+        }
+        return sb.toString();
+    }
+
+    /**
+     * Finds format specifiers in the format string.
+     * @param s
+     * @return
+     */
+    private List<String> parse(String s) {
+        List<String> list = new ArrayList<>();
+        Matcher matcher = PATTERN_KEY.matcher(s);
+        for (int i = 0; i < s.length(); ) {
+            if (matcher.find(i)) {
+                if (matcher.start() != i) {
+                    list.add(s.substring(i, matcher.start()));
+                }
+                list.add(matcher.group());
+                i = matcher.end();
+            } else {
+                list.add(s.substring(i));
+                break;
+            }
+        }
+        return list;
+    }
 }

--
Gitblit v1.9.3