| | |
| | | package com.ruoyi.config; |
| | | |
| | | import java.util.ArrayList; |
| | | import java.util.List; |
| | | import java.util.concurrent.TimeUnit; |
| | | import org.springframework.data.redis.core.RedisTemplate; |
| | | import org.springframework.stereotype.Component; |
| | | import com.alibaba.fastjson2.JSON; |
| | | import com.alibaba.fastjson2.JSONArray; |
| | | import com.alibaba.fastjson2.JSONObject; |
| | | import com.ruoyi.device.simulator.BtsSimulatorStateStore; |
| | | import com.ruoyi.device.model.DeviceWorkStatus; |
| | | |
| | | /** 将开发模拟器完整状态写入 Redis,主状态不设置普通 TTL。 */ |
| | | @Component |
| | |
| | | { |
| | | try |
| | | { |
| | | String json = stored.toString(); |
| | | JSONObject root = JSON.parseObject(json); |
| | | // 通用 RedisTemplate 在可执行包中可能将泛型数组恢复为 JSONObject,必须在存储边界逐层重建。 |
| | | JSONObject root = jsonObject(stored); |
| | | Integer version = root.getInteger("version"); |
| | | if (version == null || version != CURRENT_VERSION) |
| | | throw new IllegalStateException("Unsupported BTS simulator state version: " + version); |
| | | return JSON.parseObject(json, SimulatorState.class); |
| | | List<DeviceState> devices = new ArrayList<>(); |
| | | requiredArray(root, "devices").forEach(item -> devices.add(deviceState(item))); |
| | | List<CollectorState> collectors = new ArrayList<>(); |
| | | requiredArray(root, "collectors").forEach(item -> collectors.add(collectorState(item))); |
| | | List<ChannelTombstone> tombstones = new ArrayList<>(); |
| | | requiredArray(root, "tombstones").forEach(item -> tombstones.add(channelTombstone(item))); |
| | | return new SimulatorState(version, devices, collectors, |
| | | requiredInteger(root, "nextDeviceId"), requiredInteger(root, "nextCollectorId"), tombstones); |
| | | } |
| | | catch (IllegalStateException exception) |
| | | { |
| | |
| | | throw new IllegalStateException("Invalid BTS simulator state in Redis", exception); |
| | | } |
| | | } |
| | | |
| | | private JSONObject jsonObject(Object value) |
| | | { |
| | | if (value instanceof JSONObject object) return object; |
| | | if (value instanceof String text) |
| | | { |
| | | Object parsed = JSON.parse(text); |
| | | if (parsed instanceof String nested) parsed = JSON.parse(nested); |
| | | if (parsed instanceof JSONObject object) return object; |
| | | return JSON.parseObject(JSON.toJSONString(parsed)); |
| | | } |
| | | return JSON.parseObject(JSON.toJSONString(value)); |
| | | } |
| | | |
| | | private JSONArray requiredArray(JSONObject object, String field) |
| | | { |
| | | JSONArray array = object.getJSONArray(field); |
| | | if (array == null) throw new IllegalStateException("Missing BTS simulator state field: " + field); |
| | | return array; |
| | | } |
| | | |
| | | private int requiredInteger(JSONObject object, String field) |
| | | { |
| | | Integer value = object.getInteger(field); |
| | | if (value == null) throw new IllegalStateException("Missing BTS simulator state field: " + field); |
| | | return value; |
| | | } |
| | | |
| | | private DeviceState deviceState(Object value) |
| | | { |
| | | JSONObject object = jsonObject(value); |
| | | List<ChannelState> channels = new ArrayList<>(); |
| | | requiredArray(object, "channels").forEach(item -> channels.add(channelState(item))); |
| | | return new DeviceState(requiredInteger(object, "deviceId"), object.getString("ip"), |
| | | object.getBooleanValue("online"), channels); |
| | | } |
| | | |
| | | private CollectorState collectorState(Object value) |
| | | { |
| | | JSONObject object = jsonObject(value); |
| | | return new CollectorState(requiredInteger(object, "collectorId"), object.getString("deviceCode"), |
| | | object.getString("ip"), object.getString("mac"), object.getString("name"), |
| | | object.getString("manufacturer"), object.getString("model"), |
| | | requiredInteger(object, "channelCount"), object.getBooleanValue("online")); |
| | | } |
| | | |
| | | private ChannelState channelState(Object value) |
| | | { |
| | | JSONObject object = jsonObject(value); |
| | | String workStatus = object.getString("workStatus"); |
| | | if (workStatus == null) throw new IllegalStateException("Missing BTS simulator state field: workStatus"); |
| | | return new ChannelState(requiredInteger(object, "channelId"), object.getBooleanValue("online"), |
| | | DeviceWorkStatus.valueOf(workStatus)); |
| | | } |
| | | |
| | | private ChannelTombstone channelTombstone(Object value) |
| | | { |
| | | JSONObject object = jsonObject(value); |
| | | return new ChannelTombstone(requiredInteger(object, "deviceId"), object.getString("ip"), |
| | | requiredInteger(object, "channelId"), requiredInteger(object, "remainingDiscoveries")); |
| | | } |
| | | } |