| | |
| | | import com.alibaba.fastjson2.JSONObject; |
| | | import com.battery.device.simulator.BtsSimulatorStateStore; |
| | | import com.battery.device.simulator.BtsSimulatorStateStore.BtsDeviceProfile; |
| | | import com.battery.device.simulator.BtsSimulatorStateStore.ChannelConfiguration; |
| | | import com.battery.device.simulator.BtsSimulatorStateStore.SimulatorPlanStep; |
| | | import com.battery.device.api.model.DeviceWorkStatus; |
| | | |
| | | /** 将开发模拟器完整状态写入 Redis,主状态不设置普通 TTL。 */ |
| | |
| | | this.redisTemplate = redisTemplate; |
| | | } |
| | | |
| | | /** 读取模拟器主状态,不存在时原子写入默认拓扑;并发初始化时以 Redis 中先写入的那份为准。 */ |
| | | @Override |
| | | public SimulatorState loadOrInitialize(SimulatorState defaultState) |
| | | { |
| | |
| | | return restoreState(stored); |
| | | } |
| | | |
| | | /** 整体覆盖模拟器主状态;该键不设普通 TTL。 */ |
| | | @Override |
| | | public void save(SimulatorState state) |
| | | { |
| | | redisTemplate.opsForValue().set(STATE_KEY, JSON.toJSONString(state)); |
| | | } |
| | | |
| | | /** 读取短期保留的最近请求;键不存在时返回空列表。 */ |
| | | @Override |
| | | public List<RecentRequest> loadRecentRequests() |
| | | { |
| | |
| | | return List.copyOf(JSON.parseArray(stored.toString(), RecentRequest.class)); |
| | | } |
| | | |
| | | /** 覆盖保存最近请求,整键按小时级 TTL 自动过期。 */ |
| | | @Override |
| | | public void saveRecentRequests(List<RecentRequest> requests) |
| | | { |
| | |
| | | RECENT_REQUESTS_TTL_HOURS, TimeUnit.HOURS); |
| | | } |
| | | |
| | | /** 人工重置:删除最近请求并写回默认主状态。 */ |
| | | @Override |
| | | public void reset(SimulatorState defaultState) |
| | | { |
| | |
| | | JSONObject object = jsonObject(value); |
| | | String workStatus = object.getString("workStatus"); |
| | | if (workStatus == null) throw new IllegalStateException("Missing BTS simulator state field: workStatus"); |
| | | JSONObject configuration = object.getJSONObject("configuration"); |
| | | return new ChannelState(requiredInteger(object, "channelId"), object.getBooleanValue("online"), |
| | | DeviceWorkStatus.valueOf(workStatus), object.getObject("configuration", ChannelConfiguration.class)); |
| | | DeviceWorkStatus.valueOf(workStatus), channelConfiguration(configuration)); |
| | | } |
| | | |
| | | /** Redis 通用反序列化会把泛型 steps 恢复为 JSONObject,不能让 record 构造器直接强转。 */ |
| | | private ChannelConfiguration channelConfiguration(JSONObject object) |
| | | { |
| | | if (object == null) return null; |
| | | JSONArray configuredSteps = requiredArray(object, "steps"); |
| | | List<SimulatorPlanStep> steps = new ArrayList<>(); |
| | | configuredSteps.forEach(item -> { |
| | | JSONObject step = jsonObject(item); |
| | | steps.add(new SimulatorPlanStep(step.getString("name"), step.getString("stepType"), |
| | | step.getDoubleValue("durationSeconds"), step.getDoubleValue("voltageV"))); |
| | | }); |
| | | return new ChannelConfiguration(requiredDecimal(object, "currentA"), requiredDecimal(object, "voltageV"), |
| | | requiredDecimal(object, "capacityAh"), requiredDecimal(object, "energyWh"), |
| | | requiredInteger(object, "cycleNo"), requiredInteger(object, "stepNo"), |
| | | requiredInteger(object, "plannedCycleCount"), object.getLongValue("totalTimeSeconds"), |
| | | object.getLongValue("relativeTimeSeconds"), steps); |
| | | } |
| | | |
| | | private ChannelTombstone channelTombstone(Object value) |