瀏覽代碼

Merge branch 'master' of http://114.215.146.132:3000/Mqy/Wisdom-Data into mqy20260511

 Conflicts:
	iot-platform/src/main/java/com/iot/platform/task/VehicleSyncTask.java
mqy20260511
lenovo 2 天之前
父節點
當前提交
b7dee4c46f

+ 21
- 8
deploy/deploy.sh 查看文件

@@ -19,6 +19,7 @@ REMOTE_DIR="${REMOTE_DIR:-/opt/iot-platform}"
19 19
 APP_NAME="iot-platform"
20 20
 LOCAL_JAR=""
21 21
 DO_BUILD=false
22
+NO_ROLLBACK=false
22 23
 
23 24
 # 颜色
24 25
 RED='\033[0;31m'
@@ -33,14 +34,19 @@ while [[ $# -gt 0 ]]; do
33 34
             DO_BUILD=true
34 35
             shift
35 36
             ;;
37
+        --no-rollback)
38
+            NO_ROLLBACK=true
39
+            shift
40
+            ;;
36 41
         --jar)
37 42
             LOCAL_JAR="$2"
38 43
             shift 2
39 44
             ;;
40 45
         --help|-h)
41
-            echo "用法: ./deploy.sh [--build] [--jar <path>]"
42
-            echo "  --build     本地执行 mvn clean package"
43
-            echo "  --jar       指定要部署的 jar 文件路径"
46
+            echo "用法: ./deploy.sh [--build] [--no-rollback] [--jar <path>]"
47
+            echo "  --build        本地执行 mvn clean package"
48
+            echo "  --no-rollback  健康检查失败时不自动回滚,保留新版本用于排查"
49
+            echo "  --jar          指定要部署的 jar 文件路径"
44 50
             exit 0
45 51
             ;;
46 52
         *)
@@ -127,7 +133,7 @@ echo -e "${GREEN}[5/6] 服务已启动${NC}"
127 133
 
128 134
 # 步骤 6: 健康检查
129 135
 echo -e "${YELLOW}[6/6] 健康检查...${NC}"
130
-if ssh "${SERVER_USER}@${SERVER_HOST}" "bash ${REMOTE_DIR}/bin/health-check.sh localhost 8887 30"; then
136
+if ssh "${SERVER_USER}@${SERVER_HOST}" "bash ${REMOTE_DIR}/bin/health-check.sh localhost 8887 60"; then
131 137
     echo -e "${GREEN}[6/6] 健康检查通过,部署成功!${NC}"
132 138
     echo ""
133 139
     echo "========================================"
@@ -142,10 +148,17 @@ if ssh "${SERVER_USER}@${SERVER_HOST}" "bash ${REMOTE_DIR}/bin/health-check.sh l
142 148
     ssh "${SERVER_USER}@${SERVER_HOST}" "systemctl status ${APP_NAME} --no-pager"
143 149
     exit 0
144 150
 else
145
-    echo -e "${RED}[6/6] 健康检查失败! 执行回滚...${NC}"
151
+    echo -e "${RED}[6/6] 健康检查失败!${NC}"
152
+
153
+    if [ "$NO_ROLLBACK" = true ]; then
154
+        echo -e "${YELLOW}[no-rollback] 已启用不回滚模式,保留新版本用于排查${NC}"
155
+        echo -e "${YELLOW}排查命令:${NC}"
156
+        echo "  ssh ${SERVER_USER}@${SERVER_HOST} 'journalctl -u ${APP_NAME} -f'"
157
+        echo "  ssh ${SERVER_USER}@${SERVER_HOST} 'systemctl status ${APP_NAME}'"
158
+        exit 1
159
+    fi
146 160
 
147
-    # 回滚
148
-    echo -e "${YELLOW}[rollback] 停止服务...${NC}"
161
+    echo -e "${YELLOW}[rollback] 执行回滚...${NC}"
149 162
     ssh "${SERVER_USER}@${SERVER_HOST}" "systemctl stop ${APP_NAME} || true"
150 163
 
151 164
     if ssh "${SERVER_USER}@${SERVER_HOST}" "test -f ${REMOTE_DIR}/backup/${BACKUP_NAME}"; then
@@ -156,7 +169,7 @@ else
156 169
         "
157 170
         sleep 3
158 171
 
159
-        if ssh "${SERVER_USER}@${SERVER_HOST}" "bash ${REMOTE_DIR}/bin/health-check.sh localhost 8887 30"; then
172
+        if ssh "${SERVER_USER}@${SERVER_HOST}" "bash ${REMOTE_DIR}/bin/health-check.sh localhost 8887 60"; then
160 173
             echo -e "${GREEN}[rollback] 回滚成功,旧版本已恢复${NC}"
161 174
         else
162 175
             echo -e "${RED}[rollback] 回滚后健康检查仍失败,请手动排查!${NC}"

+ 3
- 3
iot-platform/pom.xml 查看文件

@@ -3,9 +3,9 @@
3 3
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4 4
          xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
5 5
     <parent>
6
-        <artifactId>ruoyi</artifactId>
7
-        <groupId>com.ruoyi</groupId>
8
-        <version>3.9.0</version>
6
+        <groupId>com.iot.platform</groupId>
7
+        <artifactId>wisdom-data</artifactId>
8
+        <version>1.0.0</version>
9 9
     </parent>
10 10
     <modelVersion>4.0.0</modelVersion>
11 11
     <packaging>jar</packaging>

+ 1
- 1
iot-platform/src/main/java/com/iot/platform/service/TDengineService.java 查看文件

@@ -17,7 +17,7 @@ import java.util.zip.*;
17 17
 
18 18
 import com.fasterxml.jackson.databind.ObjectMapper;
19 19
 
20
-@Service
20
+@Service("tdengineService")
21 21
 public class TDengineService {
22 22
     private static final Logger log = LoggerFactory.getLogger(TDengineService.class);
23 23
 

+ 0
- 327
iot-platform/src/main/java/com/iot/platform/task/VehicleSyncTask.java 查看文件

@@ -1,327 +0,0 @@
1
-package com.iot.platform.task;
2
-
3
-import com.iot.platform.domain.SysCar;
4
-import com.iot.platform.domain.SysDevice;
5
-import com.iot.platform.domain.SysDeviceControl;
6
-import com.iot.platform.config.IotProperties;
7
-import com.iot.platform.service.*;
8
-import org.slf4j.Logger;
9
-import org.slf4j.LoggerFactory;
10
-import org.springframework.dao.DataAccessException;
11
-import org.springframework.data.redis.RedisConnectionFailureException;
12
-import org.springframework.data.redis.core.RedisCallback;
13
-import org.springframework.data.redis.core.ScanOptions;
14
-import org.springframework.data.redis.core.StringRedisTemplate;
15
-import org.springframework.scheduling.annotation.Scheduled;
16
-import org.springframework.stereotype.Component;
17
-import org.springframework.web.client.RestClientException;
18
-import org.springframework.web.client.RestTemplate;
19
-
20
-import java.util.*;
21
-import java.util.concurrent.TimeUnit;
22
-
23
-@Component
24
-public class VehicleSyncTask {
25
-
26
-//    private static final Logger log = LoggerFactory.getLogger(VehicleSyncTask.class);
27
-//
28
-//    private final SysCarService sysCarService;
29
-//    private final SysDeviceService sysDeviceService;
30
-//    private final StringRedisTemplate stringRedisTemplate;
31
-//    private final SysrealtimeService sysrealtimeService;
32
-//    private final SysDeviceVoService sysDeviceVoService;
33
-//    private final SysDeviceControlService sysDeviceControlService;
34
-//    private final RestTemplate restTemplate;
35
-//    private final IotProperties iotProperties;
36
-//
37
-//    public VehicleSyncTask(SysCarService sysCarService,
38
-//                           SysDeviceService sysDeviceService,
39
-//                           StringRedisTemplate stringRedisTemplate,
40
-//                           SysrealtimeService sysrealtimeService,
41
-//                           SysDeviceVoService sysDeviceVoService,
42
-//                           SysDeviceControlService sysDeviceControlService,
43
-//                           RestTemplate restTemplate,
44
-//                           IotProperties iotProperties) {
45
-//        this.sysCarService = sysCarService;
46
-//        this.sysDeviceService = sysDeviceService;
47
-//        this.stringRedisTemplate = stringRedisTemplate;
48
-//        this.sysrealtimeService = sysrealtimeService;
49
-//        this.sysDeviceVoService = sysDeviceVoService;
50
-//        this.sysDeviceControlService = sysDeviceControlService;
51
-//        this.restTemplate = restTemplate;
52
-//        this.iotProperties = iotProperties;
53
-//    }
54
-//
55
-//    private boolean tryLock(String lockKey, long expireSeconds) {
56
-//        Boolean acquired = stringRedisTemplate.opsForValue().setIfAbsent(lockKey, "1", expireSeconds, TimeUnit.SECONDS);
57
-//        return Boolean.TRUE.equals(acquired);
58
-//    }
59
-//
60
-//    private void unlock(String lockKey) {
61
-//        Boolean deleted = stringRedisTemplate.delete(lockKey);
62
-//        if (!Boolean.TRUE.equals(deleted)) {
63
-//            log.warn("分布式锁释放失败: {}", lockKey);
64
-//        }
65
-//    }
66
-//
67
-//    /**
68
-//     * 更新车辆的控制器信息
69
-//     * 30秒更新一次
70
-//     */
71
-//    @Scheduled(fixedDelay = 30000)
72
-//    public void updateSysCar() {
73
-//        String lockKey = "lock:vehicle-sync:updateSysCar";
74
-//        if (!tryLock(lockKey, 60)) {
75
-//            log.debug("获取锁失败,跳过本次执行: {}", lockKey);
76
-//            return;
77
-//        }
78
-//        try {
79
-//            doUpdateSysCar();
80
-//        } finally {
81
-//            unlock(lockKey);
82
-//        }
83
-//    }
84
-//
85
-//    private void doUpdateSysCar() {
86
-//        List<SysCar> sysCarList = sysCarService.selectcontrollerId();
87
-//        for (SysCar sysCar : sysCarList) {
88
-//            try {
89
-//                if (sysCar.getControllerId() == null || sysCar.getControllerId().isEmpty()) {
90
-//                    continue;
91
-//                }
92
-//                SysDevice latitude = sysDeviceService.selectsysdevice(sysCar.getControllerId(), "纬度");
93
-//                SysDevice longitude = sysDeviceService.selectsysdevice(sysCar.getControllerId(), "经度");
94
-//
95
-//                String redisKeyPattern = "workorder:coordinate:" + sysCar.getControllerId() + ":*";
96
-//                Set<String> keys = scanKeys(redisKeyPattern);
97
-//
98
-//                if (keys == null || keys.isEmpty()) {
99
-//                    updateCarPosition(sysCar, latitude, longitude);
100
-//                } else {
101
-//                    for (String key : keys) {
102
-//                        Map<Object, Object> coordinateMap = stringRedisTemplate.opsForHash().entries(key);
103
-//                        Object cachedLat = coordinateMap.get("latitude");
104
-//                        Object cachedLon = coordinateMap.get("longitude");
105
-//                        if (cachedLat != null && cachedLat.equals(latitude.getV()) && cachedLon != null && cachedLon.equals(longitude.getV())) {
106
-//                            continue;
107
-//                        }
108
-//                        updateCarPosition(sysCar, latitude, longitude);
109
-//                    }
110
-//                }
111
-//            } catch (DataAccessException e) {
112
-//                log.error("更新车辆位置失败 carId={}: {}", sysCar.getCarId(), e.getMessage(), e);
113
-//            } catch (Exception e) {
114
-//                log.error("更新车辆位置异常 carId={}: {}", sysCar.getCarId(), e.getMessage(), e);
115
-//            }
116
-//        }
117
-//    }
118
-//
119
-//    private void updateCarPosition(SysCar sysCar, SysDevice latitude, SysDevice longitude) {
120
-//        String redisKey = "workorder:coordinate:" + sysCar.getControllerId();
121
-//        stringRedisTemplate.opsForHash().put(redisKey, "latitude", latitude.getV());
122
-//        stringRedisTemplate.opsForHash().put(redisKey, "longitude", longitude.getV());
123
-//        stringRedisTemplate.persist(redisKey);
124
-//
125
-//        String position = latitude.getV() + "," + longitude.getV();
126
-//        sysCarService.updatecarposition(position, sysCar.getCarId());
127
-//        String url = iotProperties.getMqtt().getVehicleTriggerUrl() + "?carId=" + sysCar.getCarId();
128
-//        try {
129
-//            restTemplate.postForObject(url, null, String.class);
130
-//        } catch (RestClientException e) {
131
-//            log.warn("触发webhook失败 carId={}: {}", sysCar.getCarId(), e.getMessage());
132
-//        }
133
-//    }
134
-//
135
-//    private Set<String> scanKeys(String pattern) {
136
-//        Set<String> keys = new HashSet<>();
137
-//        ScanOptions options = ScanOptions.scanOptions().match(pattern).count(100).build();
138
-//        try {
139
-//            stringRedisTemplate.execute((RedisCallback<Void>) connection -> {
140
-//                org.springframework.data.redis.core.Cursor<byte[]> cursor = connection.scan(options);
141
-//                while (cursor.hasNext()) {
142
-//                    keys.add(new String(cursor.next()));
143
-//                }
144
-//                cursor.close();
145
-//                return null;
146
-//            });
147
-//        } catch (RedisConnectionFailureException e) {
148
-//            log.warn("Redis SCAN 连接失败 pattern={}: {}", pattern, e.getMessage());
149
-//        } catch (Exception e) {
150
-//            log.error("Redis SCAN 失败 pattern={}: {}", pattern, e.getMessage(), e);
151
-//        }
152
-//        return keys;
153
-//    }
154
-//
155
-////    @Scheduled(fixedDelay = 30000)
156
-////    public void insertDevice() {
157
-////        String lockKey = "lock:vehicle-sync:insertDevice";
158
-////        if (!tryLock(lockKey, 60)) {
159
-////            log.debug("获取锁失败,跳过本次执行: {}", lockKey);
160
-////            return;
161
-////        }
162
-////        try {
163
-////            doInsertDevice();
164
-////        } finally {
165
-////            unlock(lockKey);
166
-////        }
167
-////    }
168
-////
169
-////    private void doInsertDevice() {
170
-////        Set<String> activeKeys;
171
-////        try {
172
-////            activeKeys = stringRedisTemplate.opsForSet().members("DSB:active:devices");
173
-////        } catch (Exception e) {
174
-////            log.warn("redis中无数据");
175
-////            return;
176
-////        }
177
-////        try {
178
-////            if (activeKeys == null || activeKeys.isEmpty()) {
179
-////                log.info("redis中无数据");
180
-////                return;
181
-////            }
182
-////            List<SysDeviceControl> sysDeviceControlList = sysDeviceControlService.selectdevice("device");
183
-////            for (String redisKey : activeKeys) {
184
-////                Map<Object, Object> dataMap = stringRedisTemplate.opsForHash().entries(redisKey);
185
-////                if (dataMap == null || dataMap.isEmpty()) {
186
-////                    stringRedisTemplate.opsForSet().remove("DSB:active:devices", redisKey);
187
-////                    continue;
188
-////                }
189
-////                String[] parts = redisKey.split(":", 3);
190
-////                if (parts.length != 3 || !"DSB".equals(parts[0])) {
191
-////                    log.warn("跳过非法 key: {}", redisKey);
192
-////                    continue;
193
-////                }
194
-////                String controllerId = parts[1];
195
-////                Integer count = sysDeviceVoService.selectcount(controllerId);
196
-////                if (count != null && count > 0) {
197
-////                    StringBuilder keyvalue = new StringBuilder();
198
-////                    for (int i = 0; i < sysDeviceControlList.size(); i++) {
199
-////                        for (Map.Entry<Object, Object> entry : dataMap.entrySet()) {
200
-////                            String fieldKey = entry.getKey().toString();
201
-////                            String fieldvalue = entry.getValue().toString();
202
-////                            if (sysDeviceControlList.get(i).getControllerName().equals(fieldKey)) {
203
-////                                keyvalue.append(fieldKey).append("=/'").append(fieldvalue).append("/'");
204
-////                                if (i < sysDeviceControlList.size() - 1) {
205
-////                                    keyvalue.append(",");
206
-////                                }
207
-////                            }
208
-////                        }
209
-////                    }
210
-////                    boolean updated = sysDeviceVoService.updatesysdevice(keyvalue.toString(), controllerId);
211
-////                    if (!updated) {
212
-////                        log.warn("更新设备配置失败: controllerId={}", controllerId);
213
-////                    }
214
-////                } else {
215
-////                    StringBuilder key = new StringBuilder();
216
-////                    StringBuilder value = new StringBuilder();
217
-////                    for (int i = 0; i < sysDeviceControlList.size(); i++) {
218
-////                        for (Map.Entry<Object, Object> entry : dataMap.entrySet()) {
219
-////                            String fieldKey = entry.getKey().toString();
220
-////                            String fieldvalue = entry.getValue().toString();
221
-////                            if (sysDeviceControlList.get(i).getControllerName().equals(fieldKey)) {
222
-////                                key.append(fieldKey);
223
-////                                value.append(fieldvalue);
224
-////                                if (i < sysDeviceControlList.size() - 1) {
225
-////                                    key.append(",");
226
-////                                    value.append(",");
227
-////                                }
228
-////                            }
229
-////                        }
230
-////                    }
231
-////                    boolean inserted = sysDeviceVoService.insertdevice(key.toString(), value.toString());
232
-////                    if (!inserted) {
233
-////                        log.warn("插入设备配置失败: controllerId={}", controllerId);
234
-////                    }
235
-////                }
236
-////            }
237
-////        } catch (RedisConnectionFailureException e) {
238
-////            log.warn("Redis 连接失败,跳过本次同步: {}", e.getMessage());
239
-////        } catch (DataAccessException e) {
240
-////            log.error("数据库操作失败: {}", e.getMessage(), e);
241
-////        } catch (Exception e) {
242
-////            log.error("同步设备配置失败: {}", e.getMessage(), e);
243
-////        }
244
-////    }
245
-//
246
-//    /**
247
-//     * 更新数据库实时数据
248
-//     */
249
-//    @Scheduled(fixedDelay = 30000)
250
-//    public void syncRedisToMySQL() {
251
-//        String lockKey = "lock:vehicle-sync:syncRedisToMySQL";
252
-//        if (!tryLock(lockKey, 60)) {
253
-//            log.debug("获取锁失败,跳过本次执行: {}", lockKey);
254
-//            return;
255
-//        }
256
-//        try {
257
-//            doSyncRedisToMySQL();
258
-//        } finally {
259
-//            unlock(lockKey);
260
-//        }
261
-//    }
262
-//
263
-//    private void doSyncRedisToMySQL() {
264
-//        Set<String> activeKeys = stringRedisTemplate.opsForSet().members("DSB:active:devices");
265
-//        if (activeKeys == null || activeKeys.isEmpty()) return;
266
-//
267
-//        for (String redisKey : activeKeys) {
268
-//            try {
269
-//                Map<Object, Object> dataMap = stringRedisTemplate.opsForHash().entries(redisKey);
270
-//                if (dataMap == null || dataMap.isEmpty()) {
271
-//                    stringRedisTemplate.opsForSet().remove("DSB:active:devices", redisKey);
272
-//                    continue;
273
-//                }
274
-//
275
-//                String[] parts = redisKey.split(":", 3);
276
-//                if (parts.length != 3 || !"DSB".equals(parts[0])) {
277
-//                    log.warn("跳过非法 key: {}", redisKey);
278
-//                    continue;
279
-//                }
280
-//                String controllerId = parts[1];
281
-//
282
-//                try {
283
-//                    sysrealtimeService.createrealtime(controllerId);
284
-//                } catch (Exception e) {
285
-//                    log.error("创建表失败: {} | {}", controllerId, e.getMessage(), e);
286
-//                    continue;
287
-//                }
288
-//
289
-//                String createTime = getStringValue(dataMap, "createTime");
290
-//                String timestamp = getStringValue(dataMap, "timestamp");
291
-//                String deviceId = getStringValue(dataMap, "device_id");
292
-//                if (createTime == null || timestamp == null || deviceId == null) {
293
-//                    continue;
294
-//                }
295
-//
296
-//                List<String> existingKeys = sysrealtimeService.selectAllKeys(controllerId);
297
-//                Set<String> existingKeySet = existingKeys != null ? new HashSet<>(existingKeys) : Collections.emptySet();
298
-//
299
-//                for (Map.Entry<Object, Object> entry : dataMap.entrySet()) {
300
-//                    String fieldKey = entry.getKey().toString();
301
-//                    if ("createTime".equals(fieldKey) || "timestamp".equals(fieldKey) || "device_id".equals(fieldKey)) {
302
-//                        continue;
303
-//                    }
304
-//                    String fieldValue = getStringValue(dataMap, fieldKey);
305
-//                    if (fieldValue == null) continue;
306
-//
307
-//                    if (existingKeySet.contains(fieldKey)) {
308
-//                        sysrealtimeService.updatetables(controllerId, createTime, fieldValue, timestamp, fieldKey, deviceId);
309
-//                    } else {
310
-//                        sysrealtimeService.inserttables(controllerId, createTime, deviceId, timestamp, fieldKey, fieldValue);
311
-//                    }
312
-//                }
313
-//            } catch (RedisConnectionFailureException e) {
314
-//                log.error("Redis 连接失败: {} | {}", redisKey, e.getMessage());
315
-//            } catch (DataAccessException e) {
316
-//                log.error("数据库操作失败: {} | {}", redisKey, e.getMessage(), e);
317
-//            } catch (Exception e) {
318
-//                log.error("同步设备失败: {} | {}", redisKey, e.getMessage(), e);
319
-//            }
320
-//        }
321
-//    }
322
-//
323
-//    private String getStringValue(Map<Object, Object> map, String key) {
324
-//        Object val = map.get(key);
325
-//        return val == null ? null : val.toString().trim();
326
-//    }
327
-}

+ 0
- 209
iot-platform/src/test/java/com/iot/platform/task/VehicleSyncTaskTest.java 查看文件

@@ -1,209 +0,0 @@
1
-package com.iot.platform.task;
2
-
3
-import com.iot.platform.config.IotProperties;
4
-import com.iot.platform.domain.SysCar;
5
-import com.iot.platform.domain.SysDevice;
6
-import com.iot.platform.service.*;
7
-import org.junit.jupiter.api.BeforeEach;
8
-import org.junit.jupiter.api.DisplayName;
9
-import org.junit.jupiter.api.Test;
10
-import org.junit.jupiter.api.extension.ExtendWith;
11
-import org.mockito.InjectMocks;
12
-import org.mockito.Mock;
13
-import org.mockito.junit.jupiter.MockitoExtension;
14
-import org.mockito.junit.jupiter.MockitoSettings;
15
-import org.mockito.quality.Strictness;
16
-import org.springframework.dao.DataAccessException;
17
-import org.springframework.data.redis.RedisConnectionFailureException;
18
-import org.springframework.data.redis.core.StringRedisTemplate;
19
-import org.springframework.data.redis.core.ValueOperations;
20
-import org.springframework.web.client.RestClientException;
21
-import org.springframework.web.client.RestTemplate;
22
-
23
-import java.util.*;
24
-
25
-import static org.assertj.core.api.Assertions.assertThat;
26
-import static org.mockito.ArgumentMatchers.*;
27
-import static org.mockito.Mockito.*;
28
-
29
-@ExtendWith(MockitoExtension.class)
30
-@MockitoSettings(strictness = Strictness.LENIENT)
31
-class VehicleSyncTaskTest {
32
-
33
-    @Mock
34
-    private SysCarService sysCarService;
35
-    @Mock
36
-    private SysDeviceService sysDeviceService;
37
-    @Mock
38
-    private StringRedisTemplate stringRedisTemplate;
39
-    @Mock
40
-    private SysrealtimeService sysrealtimeService;
41
-    @Mock
42
-    private SysDeviceVoService sysDeviceVoService;
43
-    @Mock
44
-    private SysDeviceControlService sysDeviceControlService;
45
-    @Mock
46
-    private SysWorkorderService sysWorkorderService;
47
-    @Mock
48
-    private SysIndicatorsService sysIndicatorsService;
49
-
50
-    @Mock
51
-    private RestTemplate restTemplate;
52
-    @Mock
53
-    private IotProperties iotProperties;
54
-    @Mock
55
-    private IotProperties.Mqtt mqttConfig;
56
-
57
-    @InjectMocks
58
-    private VehicleSyncTask task;
59
-
60
-    @Mock
61
-    private ValueOperations<String, String> valueOps;
62
-
63
-    @BeforeEach
64
-    void setUp() {
65
-        when(stringRedisTemplate.opsForValue()).thenReturn(valueOps);
66
-        when(iotProperties.getMqtt()).thenReturn(mqttConfig);
67
-        when(mqttConfig.getVehicleTriggerUrl()).thenReturn("https://esos-iot.com:9443/syscar/trigger");
68
-    }
69
-
70
-    @Test
71
-    @DisplayName("updateSysCar: 获取锁失败时应跳过执行")
72
-    void updateSysCar_lockFail_skipsExecution() {
73
-        when(valueOps.setIfAbsent(anyString(), eq("1"), anyLong(), any())).thenReturn(false);
74
-
75
-        task.updateSysCar();
76
-
77
-        verify(sysCarService, never()).selectcontrollerId();
78
-    }
79
-
80
-    @Test
81
-    @DisplayName("updateSysCar: 获取锁成功时应执行车辆位置更新")
82
-    void updateSysCar_lockSuccess_executesUpdate() {
83
-        when(valueOps.setIfAbsent(anyString(), eq("1"), anyLong(), any())).thenReturn(true);
84
-
85
-        SysCar car = new SysCar();
86
-        car.setCarId("1");
87
-        car.setControllerId("CTRL001");
88
-        when(sysCarService.selectcontrollerId()).thenReturn(Collections.singletonList(car));
89
-
90
-        SysDevice lat = new SysDevice();
91
-        lat.setV("31.2304");
92
-        SysDevice lon = new SysDevice();
93
-        lon.setV("121.4737");
94
-        when(sysDeviceService.selectsysdevice("CTRL001", "纬度")).thenReturn(lat);
95
-        when(sysDeviceService.selectsysdevice("CTRL001", "经度")).thenReturn(lon);
96
-
97
-        when(stringRedisTemplate.opsForHash()).thenReturn(mock(org.springframework.data.redis.core.HashOperations.class));
98
-        when(stringRedisTemplate.delete(anyString())).thenReturn(true);
99
-
100
-        task.updateSysCar();
101
-
102
-        verify(sysCarService).selectcontrollerId();
103
-    }
104
-
105
-    @Test
106
-    @DisplayName("updateSysCar: 单条记录异常时不应中断整个批次")
107
-    void updateSysCar_singleRecordException_continuesBatch() {
108
-        when(valueOps.setIfAbsent(anyString(), eq("1"), anyLong(), any())).thenReturn(true);
109
-
110
-        SysCar car1 = new SysCar();
111
-        car1.setCarId("1");
112
-        car1.setControllerId("CTRL001");
113
-        SysCar car2 = new SysCar();
114
-        car2.setCarId("2");
115
-        car2.setControllerId("CTRL002");
116
-        when(sysCarService.selectcontrollerId()).thenReturn(Arrays.asList(car1, car2));
117
-
118
-        // car1 正常
119
-        SysDevice lat1 = new SysDevice();
120
-        lat1.setV("31.2304");
121
-        SysDevice lon1 = new SysDevice();
122
-        lon1.setV("121.4737");
123
-        when(sysDeviceService.selectsysdevice("CTRL001", "纬度")).thenReturn(lat1);
124
-        when(sysDeviceService.selectsysdevice("CTRL001", "经度")).thenReturn(lon1);
125
-
126
-        // car2 抛异常
127
-        when(sysDeviceService.selectsysdevice("CTRL002", "纬度"))
128
-                .thenThrow(new DataAccessException("DB error") {});
129
-
130
-        when(stringRedisTemplate.opsForHash()).thenReturn(mock(org.springframework.data.redis.core.HashOperations.class));
131
-        when(stringRedisTemplate.delete(anyString())).thenReturn(true);
132
-
133
-        task.updateSysCar();
134
-
135
-        // car1 正常执行,car2 异常被捕获,两者都应该尝试
136
-        verify(sysDeviceService).selectsysdevice("CTRL001", "纬度");
137
-        verify(sysDeviceService).selectsysdevice("CTRL002", "纬度");
138
-    }
139
-
140
-    @Test
141
-    @DisplayName("insertDevice: Redis 连接失败时应跳过执行")
142
-    void insertDevice_redisConnectionFailure_skipsGracefully() {
143
-        when(valueOps.setIfAbsent(anyString(), eq("1"), anyLong(), any())).thenReturn(true);
144
-        when(stringRedisTemplate.opsForSet()).thenThrow(
145
-                new RedisConnectionFailureException("Redis down"));
146
-        when(stringRedisTemplate.delete(anyString())).thenReturn(true);
147
-
148
-        task.insertDevice();
149
-
150
-        verify(sysDeviceControlService, never()).selectdevice(anyString());
151
-    }
152
-
153
-    @Test
154
-    @DisplayName("insertDevice: 空数据时应直接返回")
155
-    void insertDevice_emptyData_returnsEarly() {
156
-        when(valueOps.setIfAbsent(anyString(), eq("1"), anyLong(), any())).thenReturn(true);
157
-
158
-        org.springframework.data.redis.core.SetOperations setOps = mock(org.springframework.data.redis.core.SetOperations.class);
159
-        when(stringRedisTemplate.opsForSet()).thenReturn(setOps);
160
-        when(setOps.members("DSB:active:devices")).thenReturn(Collections.emptySet());
161
-        when(stringRedisTemplate.delete(anyString())).thenReturn(true);
162
-
163
-        task.insertDevice();
164
-
165
-        verify(sysDeviceControlService, never()).selectdevice(anyString());
166
-    }
167
-
168
-    @Test
169
-    @DisplayName("syncRedisToMySQL: 空活跃 key 时应直接返回")
170
-    void syncRedisToMySQL_emptyKeys_returnsEarly() {
171
-        when(valueOps.setIfAbsent(anyString(), eq("1"), anyLong(), any())).thenReturn(true);
172
-
173
-        org.springframework.data.redis.core.SetOperations setOps = mock(org.springframework.data.redis.core.SetOperations.class);
174
-        when(stringRedisTemplate.opsForSet()).thenReturn(setOps);
175
-        when(setOps.members("DSB:active:devices")).thenReturn(null);
176
-        when(stringRedisTemplate.delete(anyString())).thenReturn(true);
177
-
178
-        task.syncRedisToMySQL();
179
-
180
-        verify(sysrealtimeService, never()).createrealtime(anyString());
181
-    }
182
-
183
-
184
-    @Test
185
-    @DisplayName("webhook 调用失败时不应中断主流程")
186
-    void updateCarPosition_webhookFailure_continues() {
187
-        when(valueOps.setIfAbsent(anyString(), eq("1"), anyLong(), any())).thenReturn(true);
188
-
189
-        SysCar car = new SysCar();
190
-        car.setCarId("1");
191
-        car.setControllerId("CTRL001");
192
-        when(sysCarService.selectcontrollerId()).thenReturn(Collections.singletonList(car));
193
-
194
-        SysDevice lat = new SysDevice();
195
-        lat.setV("31.2304");
196
-        SysDevice lon = new SysDevice();
197
-        lon.setV("121.4737");
198
-        when(sysDeviceService.selectsysdevice("CTRL001", "纬度")).thenReturn(lat);
199
-        when(sysDeviceService.selectsysdevice("CTRL001", "经度")).thenReturn(lon);
200
-
201
-        when(stringRedisTemplate.opsForHash()).thenReturn(mock(org.springframework.data.redis.core.HashOperations.class));
202
-        when(stringRedisTemplate.delete(anyString())).thenReturn(true);
203
-        when(restTemplate.postForObject(anyString(), isNull(), eq(String.class)))
204
-                .thenThrow(new RestClientException("Connection refused"));
205
-
206
-        // 不应抛异常
207
-        task.updateSysCar();
208
-    }
209
-}

+ 4
- 6
pom.xml 查看文件

@@ -4,16 +4,14 @@
4 4
          xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
5 5
 	<modelVersion>4.0.0</modelVersion>
6 6
 
7
-    <groupId>com.ruoyi</groupId>
8
-    <artifactId>ruoyi</artifactId>
9
-    <version>3.9.0</version>
7
+    <groupId>com.iot.platform</groupId>
8
+    <artifactId>wisdom-data</artifactId>
9
+    <version>1.0.0</version>
10 10
 
11
-    <name>iot-platform</name>
12
-    <url>http://www.ruoyi.vip</url>
11
+    <name>wisdom-data</name>
13 12
     <description>IoT储能运营平台</description>
14 13
 
15 14
     <properties>
16
-        <ruoyi.version>3.9.0</ruoyi.version>
17 15
         <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
18 16
         <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
19 17
         <java.version>1.8</java.version>

Loading…
取消
儲存