1 文件已复制
1个文件已删除
42 文件已重命名
10个文件已添加
32个文件已修改
| | |
| | | /ruoyi-admin/target/ |
| | | /ruoyi-common/target/ |
| | | /ruoyi-device/target/ |
| | | /battery-business/target/ |
| | | /battery-device-api/target/ |
| | | /battery-device-bts/target/ |
| | | /battery-device-simulator/target/ |
| | | /ruoyi-framework/target/ |
| | | /ruoyi-generator/target/ |
| | | /ruoyi-quartz/target/ |
| New file |
| | |
| | | <?xml version="1.0" encoding="UTF-8"?> |
| | | <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" |
| | | xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> |
| | | <modelVersion>4.0.0</modelVersion> |
| | | <parent><groupId>com.ruoyi</groupId><artifactId>ruoyi</artifactId><version>3.9.2</version></parent> |
| | | <groupId>com.battery</groupId><artifactId>battery-business</artifactId> |
| | | <description>电池检测业务模块</description> |
| | | <dependencies> |
| | | <dependency><groupId>com.battery</groupId><artifactId>battery-device-api</artifactId></dependency> |
| | | <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency> |
| | | </dependencies> |
| | | </project> |
| New file |
| | |
| | | package com.battery.business; |
| | | |
| | | /** 电池检测业务模块入口标记;业务实现按能力继续放在本模块内。 */ |
| | | public final class BatteryBusinessModule |
| | | { |
| | | private BatteryBusinessModule() { } |
| | | } |
| New file |
| | |
| | | package com.battery.business; |
| | | |
| | | import static org.junit.jupiter.api.Assertions.assertNotNull; |
| | | import static org.junit.jupiter.api.Assertions.assertThrows; |
| | | import org.junit.jupiter.api.Test; |
| | | |
| | | class BatteryBusinessModuleTest |
| | | { |
| | | @Test |
| | | void businessModuleExposesOnlyVendorNeutralDeviceContract() |
| | | { |
| | | assertNotNull(BatteryBusinessModule.class); |
| | | assertNotNull(com.battery.device.api.DeviceAdapter.class); |
| | | assertThrows(ClassNotFoundException.class, |
| | | () -> Class.forName("com.battery.device.bts.BtsXmlCodec")); |
| | | } |
| | | } |
| New file |
| | |
| | | package com.battery.business; |
| | | |
| | | import static org.junit.jupiter.api.Assertions.assertFalse; |
| | | import java.nio.file.Files; |
| | | import java.nio.file.Path; |
| | | import org.junit.jupiter.api.Test; |
| | | |
| | | /** 防止业务模块在骨架阶段意外引入具体设备实现。 */ |
| | | class ModuleDependencyContractTest |
| | | { |
| | | @Test |
| | | void businessPomKeepsVendorImplementationsOutOfItsDependencies() throws Exception |
| | | { |
| | | Path pom = Path.of("pom.xml"); |
| | | if (!Files.exists(pom)) pom = Path.of("battery-business", "pom.xml"); |
| | | String text = Files.readString(pom); |
| | | assertFalse(text.contains("battery-device-bts")); |
| | | assertFalse(text.contains("battery-device-simulator")); |
| | | assertFalse(text.contains("spring-boot-starter-data-redis")); |
| | | } |
| | | } |
| New file |
| | |
| | | <?xml version="1.0" encoding="UTF-8"?> |
| | | <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" |
| | | xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> |
| | | <modelVersion>4.0.0</modelVersion> |
| | | <parent><groupId>com.ruoyi</groupId><artifactId>ruoyi</artifactId><version>3.9.2</version></parent> |
| | | <groupId>com.battery</groupId><artifactId>battery-device-api</artifactId> |
| | | <description>厂商无关设备观测契约与模型</description> |
| | | <dependencies> |
| | | <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency> |
| | | </dependencies> |
| | | </project> |
| File was renamed from ruoyi-device/src/main/java/com/ruoyi/device/api/DeviceAdapter.java |
| | |
| | | package com.ruoyi.device.api; |
| | | package com.battery.device.api; |
| | | |
| | | import java.util.List; |
| | | import java.util.Map; |
| | | import java.util.Set; |
| | | import com.ruoyi.device.model.AdapterCapabilities; |
| | | import com.ruoyi.device.model.ChannelIdentity; |
| | | import com.ruoyi.device.model.DetectedChannel; |
| | | import com.ruoyi.device.model.DeviceControlCommand; |
| | | import com.ruoyi.device.model.HistoryAvailability; |
| | | import com.ruoyi.device.model.HistoryPage; |
| | | import com.ruoyi.device.model.RealtimeSnapshot; |
| | | import com.battery.device.model.AdapterCapabilities; |
| | | import com.battery.device.model.ChannelIdentity; |
| | | import com.battery.device.model.DetectedChannel; |
| | | import com.battery.device.model.DeviceControlCommand; |
| | | import com.battery.device.model.HistoryAvailability; |
| | | import com.battery.device.model.HistoryPage; |
| | | import com.battery.device.model.RealtimeSnapshot; |
| | | |
| | | public interface DeviceAdapter extends AutoCloseable |
| | | { |
| File was renamed from ruoyi-device/src/main/java/com/ruoyi/device/api/DeviceAdapterException.java |
| | |
| | | package com.ruoyi.device.api; |
| | | package com.battery.device.api; |
| | | |
| | | public class DeviceAdapterException extends RuntimeException |
| | | { |
| New file |
| | |
| | | package com.battery.device.api; |
| | | |
| | | import java.util.List; |
| | | import java.util.Map; |
| | | import java.util.Set; |
| | | import com.battery.device.model.AdapterCapabilities; |
| | | import com.battery.device.model.ChannelIdentity; |
| | | import com.battery.device.model.DetectedChannel; |
| | | import com.battery.device.model.HistoryAvailability; |
| | | import com.battery.device.model.HistoryPage; |
| | | import com.battery.device.model.RealtimeSnapshot; |
| | | |
| | | /** 没有启用具体设备实现时使用的空适配器,不连接外部设备。 */ |
| | | public final class NoopDeviceAdapter implements DeviceAdapter |
| | | { |
| | | private final String adapterCode; |
| | | |
| | | public NoopDeviceAdapter(String adapterCode) |
| | | { |
| | | this.adapterCode = adapterCode == null || adapterCode.isBlank() ? "noop" : adapterCode; |
| | | } |
| | | |
| | | @Override public String adapterCode() { return adapterCode; } |
| | | |
| | | @Override public AdapterCapabilities capabilities() |
| | | { |
| | | return new AdapterCapabilities(true, true, false, false); |
| | | } |
| | | |
| | | @Override public List<DetectedChannel> discoverChannels() { return List.of(); } |
| | | |
| | | @Override public Map<ChannelIdentity, RealtimeSnapshot> inquire(Set<ChannelIdentity> channels) |
| | | { |
| | | return Map.of(); |
| | | } |
| | | |
| | | @Override public List<HistoryAvailability> inquireHistory(Set<ChannelIdentity> channels) |
| | | { |
| | | return List.of(); |
| | | } |
| | | |
| | | @Override public HistoryPage downloadHistory(ChannelIdentity channel, String btsTestId, |
| | | long startPosition, int limit) |
| | | { |
| | | return new HistoryPage(channel, btsTestId, startPosition, startPosition, List.of()); |
| | | } |
| | | } |
| New file |
| | |
| | | package com.battery.device.api; |
| | | |
| | | import com.battery.device.registry.AdapterInstanceConfig; |
| | | import com.battery.device.registry.DeviceAdapterFactory; |
| | | |
| | | /** 为默认启动路径提供不产生外部副作用的设备实现。 */ |
| | | public final class NoopDeviceAdapterFactory implements DeviceAdapterFactory |
| | | { |
| | | @Override public String adapterType() { return "NOOP"; } |
| | | |
| | | @Override public DeviceAdapter create(AdapterInstanceConfig config) |
| | | { |
| | | return new NoopDeviceAdapter(config.adapterCode()); |
| | | } |
| | | } |
| File was renamed from ruoyi-device/src/main/java/com/ruoyi/device/discovery/DeviceDiscoveryCandidateStore.java |
| | |
| | | package com.ruoyi.device.discovery; |
| | | package com.battery.device.discovery; |
| | | |
| | | import java.time.Instant; |
| | | import java.util.List; |
| | | import java.util.Optional; |
| | | import com.ruoyi.device.model.ChannelIdentity; |
| | | import com.ruoyi.device.model.DeviceWorkStatus; |
| | | import com.ruoyi.device.model.RealtimeSnapshot; |
| | | import com.battery.device.model.ChannelIdentity; |
| | | import com.battery.device.model.DeviceWorkStatus; |
| | | import com.battery.device.model.RealtimeSnapshot; |
| | | |
| | | /** 保存未登记发现候选和正式设备的实时观测快照。 */ |
| | | public interface DeviceDiscoveryCandidateStore |
| File was renamed from ruoyi-device/src/main/java/com/ruoyi/device/discovery/InMemoryDeviceDiscoveryCandidateStore.java |
| | |
| | | package com.ruoyi.device.discovery; |
| | | package com.battery.device.discovery; |
| | | |
| | | import java.time.Instant; |
| | | import java.util.LinkedHashMap; |
| File was renamed from ruoyi-device/src/main/java/com/ruoyi/device/model/AdapterCapabilities.java |
| | |
| | | package com.ruoyi.device.model; |
| | | package com.battery.device.model; |
| | | |
| | | public record AdapterCapabilities( |
| | | boolean discovery, |
| File was renamed from ruoyi-device/src/main/java/com/ruoyi/device/model/ChannelIdentity.java |
| | |
| | | package com.ruoyi.device.model; |
| | | package com.battery.device.model; |
| | | |
| | | import java.util.Objects; |
| | | |
| File was renamed from ruoyi-device/src/main/java/com/ruoyi/device/model/DetectedChannel.java |
| | |
| | | package com.ruoyi.device.model; |
| | | package com.battery.device.model; |
| | | |
| | | public record DetectedChannel(ChannelIdentity identity, String serverIp, boolean available, |
| | | DetectedDeviceMetadata deviceMetadata) |
| File was renamed from ruoyi-device/src/main/java/com/ruoyi/device/model/DetectedDeviceMetadata.java |
| | |
| | | package com.ruoyi.device.model; |
| | | package com.battery.device.model; |
| | | |
| | | /** 设备发现响应可选携带的展示元数据;空值表示协议未提供。 */ |
| | | public record DetectedDeviceMetadata(String name, String manufacturer, String model, String macAddress) |
| File was renamed from ruoyi-device/src/main/java/com/ruoyi/device/model/DeviceControlCommand.java |
| | |
| | | package com.ruoyi.device.model; |
| | | package com.battery.device.model; |
| | | |
| | | public enum DeviceControlCommand |
| | | { |
| File was renamed from ruoyi-device/src/main/java/com/ruoyi/device/model/DeviceWorkStatus.java |
| | |
| | | package com.ruoyi.device.model; |
| | | package com.battery.device.model; |
| | | |
| | | import java.util.Locale; |
| | | |
| File was renamed from ruoyi-device/src/main/java/com/ruoyi/device/model/HistoryAvailability.java |
| | |
| | | package com.ruoyi.device.model; |
| | | package com.battery.device.model; |
| | | |
| | | import java.util.Objects; |
| | | |
| File was renamed from ruoyi-device/src/main/java/com/ruoyi/device/model/HistoryPage.java |
| | |
| | | package com.ruoyi.device.model; |
| | | package com.battery.device.model; |
| | | |
| | | import java.util.List; |
| | | |
| File was renamed from ruoyi-device/src/main/java/com/ruoyi/device/model/HistorySample.java |
| | |
| | | package com.ruoyi.device.model; |
| | | package com.battery.device.model; |
| | | |
| | | import java.math.BigDecimal; |
| | | import java.time.Instant; |
| File was renamed from ruoyi-device/src/main/java/com/ruoyi/device/model/Measurement.java |
| | |
| | | package com.ruoyi.device.model; |
| | | package com.battery.device.model; |
| | | |
| | | import java.math.BigDecimal; |
| | | |
| File was renamed from ruoyi-device/src/main/java/com/ruoyi/device/model/RealtimeSnapshot.java |
| | |
| | | package com.ruoyi.device.model; |
| | | package com.battery.device.model; |
| | | |
| | | import java.math.BigDecimal; |
| | | import java.time.Instant; |
| File was renamed from ruoyi-device/src/main/java/com/ruoyi/device/registry/AdapterInstanceConfig.java |
| | |
| | | package com.ruoyi.device.registry; |
| | | package com.battery.device.registry; |
| | | |
| | | import java.time.ZoneId; |
| | | import java.util.Locale; |
| | | import java.util.Objects; |
| | | import com.ruoyi.device.model.AdapterCapabilities; |
| | | import com.battery.device.model.AdapterCapabilities; |
| | | |
| | | /** 设备适配器实例的运行时配置。 */ |
| | | public record AdapterInstanceConfig( |
| File was renamed from ruoyi-device/src/main/java/com/ruoyi/device/registry/AdapterRegistryException.java |
| | |
| | | package com.ruoyi.device.registry; |
| | | package com.battery.device.registry; |
| | | |
| | | /** 适配器运行时注册失败。 */ |
| | | public final class AdapterRegistryException extends RuntimeException |
| File was renamed from ruoyi-device/src/main/java/com/ruoyi/device/registry/DeviceAdapterFactory.java |
| | |
| | | package com.ruoyi.device.registry; |
| | | package com.battery.device.registry; |
| | | |
| | | import com.ruoyi.device.api.DeviceAdapter; |
| | | import com.battery.device.api.DeviceAdapter; |
| | | |
| | | /** 按适配器类型构造厂商协议实现。 */ |
| | | public interface DeviceAdapterFactory |
| File was renamed from ruoyi-device/src/main/java/com/ruoyi/device/registry/DeviceAdapterRegistry.java |
| | |
| | | package com.ruoyi.device.registry; |
| | | package com.battery.device.registry; |
| | | |
| | | import java.util.HashMap; |
| | | import java.util.List; |
| | |
| | | import java.util.Objects; |
| | | import java.util.concurrent.locks.ReentrantLock; |
| | | import java.util.function.Function; |
| | | import com.ruoyi.device.api.DeviceAdapter; |
| | | import com.battery.device.api.DeviceAdapter; |
| | | |
| | | /** 管理启用设备适配器的运行时实例及其会话生命周期。 */ |
| | | public final class DeviceAdapterRegistry implements AutoCloseable |
| File was renamed from ruoyi-device/src/test/java/com/ruoyi/device/registry/DeviceAdapterRegistryTest.java |
| | |
| | | package com.ruoyi.device.registry; |
| | | package com.battery.device.registry; |
| | | |
| | | import static org.junit.jupiter.api.Assertions.assertFalse; |
| | | import static org.junit.jupiter.api.Assertions.assertSame; |
| | |
| | | import java.util.concurrent.TimeUnit; |
| | | import java.util.concurrent.atomic.AtomicBoolean; |
| | | import org.junit.jupiter.api.Test; |
| | | import com.ruoyi.device.api.DeviceAdapter; |
| | | import com.ruoyi.device.model.AdapterCapabilities; |
| | | import com.ruoyi.device.model.ChannelIdentity; |
| | | import com.ruoyi.device.model.DeviceControlCommand; |
| | | import com.battery.device.api.DeviceAdapter; |
| | | import com.battery.device.model.AdapterCapabilities; |
| | | import com.battery.device.model.ChannelIdentity; |
| | | import com.battery.device.model.DeviceControlCommand; |
| | | |
| | | class DeviceAdapterRegistryTest |
| | | { |
| | |
| | | } |
| | | |
| | | @Override |
| | | public List<com.ruoyi.device.model.DetectedChannel> discoverChannels() |
| | | public List<com.battery.device.model.DetectedChannel> discoverChannels() |
| | | { |
| | | return List.of(); |
| | | } |
| | | |
| | | @Override |
| | | public java.util.Map<ChannelIdentity, com.ruoyi.device.model.RealtimeSnapshot> inquire( |
| | | public java.util.Map<ChannelIdentity, com.battery.device.model.RealtimeSnapshot> inquire( |
| | | java.util.Set<ChannelIdentity> channels) |
| | | { |
| | | return java.util.Map.of(); |
| | | } |
| | | |
| | | @Override |
| | | public List<com.ruoyi.device.model.HistoryAvailability> inquireHistory( |
| | | public List<com.battery.device.model.HistoryAvailability> inquireHistory( |
| | | java.util.Set<ChannelIdentity> channels) |
| | | { |
| | | return List.of(); |
| | | } |
| | | |
| | | @Override |
| | | public com.ruoyi.device.model.HistoryPage downloadHistory(ChannelIdentity channel, |
| | | public com.battery.device.model.HistoryPage downloadHistory(ChannelIdentity channel, |
| | | String btsTestId, long startPosition, int limit) |
| | | { |
| | | throw new UnsupportedOperationException(); |
| New file |
| | |
| | | <?xml version="1.0" encoding="UTF-8"?> |
| | | <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" |
| | | xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> |
| | | <modelVersion>4.0.0</modelVersion> |
| | | <parent><groupId>com.ruoyi</groupId><artifactId>ruoyi</artifactId><version>3.9.2</version></parent> |
| | | <groupId>com.battery</groupId><artifactId>battery-device-bts</artifactId> |
| | | <description>BTS 协议设备实现</description> |
| | | <dependencies> |
| | | <dependency><groupId>com.battery</groupId><artifactId>battery-device-api</artifactId></dependency> |
| | | <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency> |
| | | </dependencies> |
| | | </project> |
| File was renamed from ruoyi-device/src/main/java/com/ruoyi/device/bts/BtsDeviceAdapter.java |
| | |
| | | package com.ruoyi.device.bts; |
| | | package com.battery.device.bts; |
| | | |
| | | import java.time.Instant; |
| | | import java.util.List; |
| | | import java.util.Map; |
| | | import java.util.Set; |
| | | import com.ruoyi.device.api.DeviceAdapter; |
| | | import com.ruoyi.device.model.AdapterCapabilities; |
| | | import com.ruoyi.device.model.ChannelIdentity; |
| | | import com.ruoyi.device.model.DetectedChannel; |
| | | import com.ruoyi.device.model.HistoryAvailability; |
| | | import com.ruoyi.device.model.HistoryPage; |
| | | import com.ruoyi.device.model.RealtimeSnapshot; |
| | | import com.battery.device.api.DeviceAdapter; |
| | | import com.battery.device.model.AdapterCapabilities; |
| | | import com.battery.device.model.ChannelIdentity; |
| | | import com.battery.device.model.DetectedChannel; |
| | | import com.battery.device.model.HistoryAvailability; |
| | | import com.battery.device.model.HistoryPage; |
| | | import com.battery.device.model.RealtimeSnapshot; |
| | | |
| | | public final class BtsDeviceAdapter implements DeviceAdapter |
| | | { |
| File was renamed from ruoyi-device/src/main/java/com/ruoyi/device/bts/BtsDeviceAdapterFactory.java |
| | |
| | | package com.ruoyi.device.bts; |
| | | package com.battery.device.bts; |
| | | |
| | | import java.time.Duration; |
| | | import java.time.ZoneId; |
| | | import com.ruoyi.device.api.DeviceAdapter; |
| | | import com.ruoyi.device.registry.AdapterInstanceConfig; |
| | | import com.ruoyi.device.registry.DeviceAdapterFactory; |
| | | import com.battery.device.api.DeviceAdapter; |
| | | import com.battery.device.registry.AdapterInstanceConfig; |
| | | import com.battery.device.registry.DeviceAdapterFactory; |
| | | |
| | | /** 根据数据库配置构造 BTS 只读适配器。 */ |
| | | public final class BtsDeviceAdapterFactory implements DeviceAdapterFactory |
| File was renamed from ruoyi-device/src/main/java/com/ruoyi/device/bts/BtsFrameReader.java |
| | |
| | | package com.ruoyi.device.bts; |
| | | package com.battery.device.bts; |
| | | |
| | | import java.io.ByteArrayOutputStream; |
| | | import java.io.EOFException; |
| File was renamed from ruoyi-device/src/main/java/com/ruoyi/device/bts/BtsProtocolException.java |
| | |
| | | package com.ruoyi.device.bts; |
| | | package com.battery.device.bts; |
| | | |
| | | import com.ruoyi.device.api.DeviceAdapterException; |
| | | import com.battery.device.api.DeviceAdapterException; |
| | | |
| | | public class BtsProtocolException extends DeviceAdapterException |
| | | { |
| File was renamed from ruoyi-device/src/main/java/com/ruoyi/device/bts/BtsTcpTransport.java |
| | |
| | | package com.ruoyi.device.bts; |
| | | package com.battery.device.bts; |
| | | |
| | | import java.io.EOFException; |
| | | import java.io.IOException; |
| File was renamed from ruoyi-device/src/main/java/com/ruoyi/device/bts/BtsTransport.java |
| | |
| | | package com.ruoyi.device.bts; |
| | | package com.battery.device.bts; |
| | | |
| | | public interface BtsTransport extends AutoCloseable |
| | | { |
| File was renamed from ruoyi-device/src/main/java/com/ruoyi/device/bts/BtsTransportException.java |
| | |
| | | package com.ruoyi.device.bts; |
| | | package com.battery.device.bts; |
| | | |
| | | import com.ruoyi.device.api.DeviceAdapterException; |
| | | import com.battery.device.api.DeviceAdapterException; |
| | | |
| | | /** |
| | | * 表示可供调度与恢复逻辑分类处理的 BTS TCP 传输失败。 |
| File was renamed from ruoyi-device/src/main/java/com/ruoyi/device/bts/BtsXmlCodec.java |
| | |
| | | package com.ruoyi.device.bts; |
| | | package com.battery.device.bts; |
| | | |
| | | import java.io.StringReader; |
| | | import java.math.BigDecimal; |
| | |
| | | import org.w3c.dom.NodeList; |
| | | import org.xml.sax.InputSource; |
| | | import org.xml.sax.helpers.DefaultHandler; |
| | | import com.ruoyi.device.model.ChannelIdentity; |
| | | import com.ruoyi.device.model.DetectedChannel; |
| | | import com.ruoyi.device.model.DetectedDeviceMetadata; |
| | | import com.ruoyi.device.model.DeviceWorkStatus; |
| | | import com.ruoyi.device.model.HistoryAvailability; |
| | | import com.ruoyi.device.model.HistoryPage; |
| | | import com.ruoyi.device.model.HistorySample; |
| | | import com.ruoyi.device.model.Measurement; |
| | | import com.ruoyi.device.model.RealtimeSnapshot; |
| | | import com.battery.device.model.ChannelIdentity; |
| | | import com.battery.device.model.DetectedChannel; |
| | | import com.battery.device.model.DetectedDeviceMetadata; |
| | | import com.battery.device.model.DeviceWorkStatus; |
| | | import com.battery.device.model.HistoryAvailability; |
| | | import com.battery.device.model.HistoryPage; |
| | | import com.battery.device.model.HistorySample; |
| | | import com.battery.device.model.Measurement; |
| | | import com.battery.device.model.RealtimeSnapshot; |
| | | |
| | | public final class BtsXmlCodec |
| | | { |
| File was renamed from ruoyi-device/src/test/java/com/ruoyi/device/bts/BtsDeviceAdapterContractTest.java |
| | |
| | | package com.ruoyi.device.bts; |
| | | package com.battery.device.bts; |
| | | |
| | | import static org.junit.jupiter.api.Assertions.assertEquals; |
| | | import static org.junit.jupiter.api.Assertions.assertFalse; |
| | |
| | | import java.time.ZoneId; |
| | | import java.util.Set; |
| | | import org.junit.jupiter.api.Test; |
| | | import com.ruoyi.device.api.DeviceAdapter; |
| | | import com.ruoyi.device.model.ChannelIdentity; |
| | | import com.ruoyi.device.model.DeviceControlCommand; |
| | | import com.ruoyi.device.model.DeviceWorkStatus; |
| | | import com.battery.device.api.DeviceAdapter; |
| | | import com.battery.device.model.ChannelIdentity; |
| | | import com.battery.device.model.DeviceControlCommand; |
| | | import com.battery.device.model.DeviceWorkStatus; |
| | | |
| | | class BtsDeviceAdapterContractTest |
| | | { |
| File was renamed from ruoyi-device/src/test/java/com/ruoyi/device/registry/BtsDeviceAdapterFactoryContractTest.java |
| | |
| | | package com.ruoyi.device.registry; |
| | | package com.battery.device.bts; |
| | | |
| | | import static org.junit.jupiter.api.Assertions.assertEquals; |
| | | import static org.junit.jupiter.api.Assertions.assertFalse; |
| | | import static org.junit.jupiter.api.Assertions.assertThrows; |
| | | import java.util.List; |
| | | import org.junit.jupiter.api.Test; |
| | | import com.ruoyi.device.bts.BtsDeviceAdapterFactory; |
| | | import com.ruoyi.device.bts.ScriptedBtsTcpSimulator; |
| | | import com.ruoyi.device.model.AdapterCapabilities; |
| | | import com.battery.device.bts.BtsDeviceAdapterFactory; |
| | | import com.battery.device.bts.ScriptedBtsTcpSimulator; |
| | | import com.battery.device.model.AdapterCapabilities; |
| | | import com.battery.device.registry.AdapterInstanceConfig; |
| | | import com.battery.device.registry.DeviceAdapterRegistry; |
| | | |
| | | class BtsDeviceAdapterFactoryContractTest |
| | | { |
| File was renamed from ruoyi-device/src/test/java/com/ruoyi/device/bts/BtsTcpTransportTest.java |
| | |
| | | package com.ruoyi.device.bts; |
| | | package com.battery.device.bts; |
| | | |
| | | import static org.junit.jupiter.api.Assertions.assertEquals; |
| | | import static org.junit.jupiter.api.Assertions.assertThrows; |
| File was renamed from ruoyi-device/src/test/java/com/ruoyi/device/bts/BtsXmlCodecTest.java |
| | |
| | | package com.ruoyi.device.bts; |
| | | package com.battery.device.bts; |
| | | |
| | | import static org.junit.jupiter.api.Assertions.assertEquals; |
| | | import static org.junit.jupiter.api.Assertions.assertFalse; |
| | |
| | | import java.util.Map; |
| | | import java.util.Set; |
| | | import org.junit.jupiter.api.Test; |
| | | import com.ruoyi.device.model.ChannelIdentity; |
| | | import com.ruoyi.device.model.DeviceWorkStatus; |
| | | import com.ruoyi.device.model.HistoryPage; |
| | | import com.ruoyi.device.model.HistoryAvailability; |
| | | import com.ruoyi.device.model.RealtimeSnapshot; |
| | | import com.battery.device.model.ChannelIdentity; |
| | | import com.battery.device.model.DeviceWorkStatus; |
| | | import com.battery.device.model.HistoryPage; |
| | | import com.battery.device.model.HistoryAvailability; |
| | | import com.battery.device.model.RealtimeSnapshot; |
| | | |
| | | class BtsXmlCodecTest |
| | | { |
| File was renamed from ruoyi-device/src/main/java/com/ruoyi/device/bts/ScriptedBtsTcpSimulator.java |
| | |
| | | package com.ruoyi.device.bts; |
| | | package com.battery.device.bts; |
| | | |
| | | import java.io.IOException; |
| | | import java.io.InputStream; |
| New file |
| | |
| | | <?xml version="1.0" encoding="UTF-8"?> |
| | | <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" |
| | | xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> |
| | | <modelVersion>4.0.0</modelVersion> |
| | | <parent><groupId>com.ruoyi</groupId><artifactId>ruoyi</artifactId><version>3.9.2</version></parent> |
| | | <groupId>com.battery</groupId><artifactId>battery-device-simulator</artifactId> |
| | | <description>开发设备模拟器实现</description> |
| | | <dependencies> |
| | | <dependency><groupId>com.battery</groupId><artifactId>battery-device-api</artifactId></dependency> |
| | | <!-- 仅测试复用协议客户端验证模拟器边界,生产依赖方向仍保持单向。 --> |
| | | <dependency><groupId>com.battery</groupId><artifactId>battery-device-bts</artifactId><scope>test</scope></dependency> |
| | | <dependency><groupId>com.alibaba.fastjson2</groupId><artifactId>fastjson2</artifactId><scope>test</scope></dependency> |
| | | <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency> |
| | | </dependencies> |
| | | </project> |
| File was renamed from ruoyi-device/src/main/java/com/ruoyi/device/bts/BtsDevelopmentSimulator.java |
| | |
| | | package com.ruoyi.device.bts; |
| | | package com.battery.device.simulator; |
| | | |
| | | import java.io.IOException; |
| | | import java.io.StringReader; |
| | |
| | | import javax.xml.stream.XMLInputFactory; |
| | | import javax.xml.stream.XMLStreamConstants; |
| | | import javax.xml.stream.XMLStreamReader; |
| | | import com.ruoyi.device.model.DeviceWorkStatus; |
| | | import com.ruoyi.device.simulator.BtsSimulatorStateStore; |
| | | import com.ruoyi.device.simulator.BtsSimulatorStateStore.ChannelState; |
| | | import com.ruoyi.device.simulator.BtsSimulatorStateStore.ChannelTombstone; |
| | | import com.ruoyi.device.simulator.BtsSimulatorStateStore.CollectorChannelState; |
| | | import com.ruoyi.device.simulator.BtsSimulatorStateStore.CollectorHistoryAppend; |
| | | import com.ruoyi.device.simulator.BtsSimulatorStateStore.CollectorHistoryFaults; |
| | | import com.ruoyi.device.simulator.BtsSimulatorStateStore.CollectorMeasurementRecord; |
| | | import com.ruoyi.device.simulator.BtsSimulatorStateStore.CollectorMetricState; |
| | | import com.ruoyi.device.simulator.BtsSimulatorStateStore.CollectorRealtimeMeasurement; |
| | | import com.ruoyi.device.simulator.BtsSimulatorStateStore.CollectorState; |
| | | import com.ruoyi.device.simulator.BtsSimulatorStateStore.DeviceState; |
| | | import com.ruoyi.device.simulator.BtsSimulatorStateStore.BtsDeviceProfile; |
| | | import com.ruoyi.device.simulator.BtsSimulatorStateStore.BtsHistoryRecord; |
| | | import com.ruoyi.device.simulator.BtsSimulatorStateStore.BtsPlaybackState; |
| | | import com.ruoyi.device.simulator.BtsSimulatorStateStore.RecentRequest; |
| | | import com.ruoyi.device.simulator.BtsSimulatorStateStore.SimulatorState; |
| | | import com.ruoyi.device.simulator.InMemoryBtsSimulatorStateStore; |
| | | import com.ruoyi.device.simulator.DevelopmentCollectorSimulation; |
| | | import com.ruoyi.device.simulator.DevelopmentCollectorSimulation.CollectorAdvance; |
| | | import com.ruoyi.device.simulator.DevelopmentCollectorSimulation.CollectorHistoryPage; |
| | | import com.ruoyi.device.simulator.DevelopmentCollectorSimulation.CollectorRealtimeSnapshot; |
| | | import com.battery.device.model.DeviceWorkStatus; |
| | | import com.battery.device.simulator.BtsSimulatorStateStore; |
| | | import com.battery.device.simulator.BtsSimulatorStateStore.ChannelState; |
| | | import com.battery.device.simulator.BtsSimulatorStateStore.ChannelTombstone; |
| | | import com.battery.device.simulator.BtsSimulatorStateStore.CollectorChannelState; |
| | | import com.battery.device.simulator.BtsSimulatorStateStore.CollectorHistoryAppend; |
| | | import com.battery.device.simulator.BtsSimulatorStateStore.CollectorHistoryFaults; |
| | | import com.battery.device.simulator.BtsSimulatorStateStore.CollectorMeasurementRecord; |
| | | import com.battery.device.simulator.BtsSimulatorStateStore.CollectorMetricState; |
| | | import com.battery.device.simulator.BtsSimulatorStateStore.CollectorRealtimeMeasurement; |
| | | import com.battery.device.simulator.BtsSimulatorStateStore.CollectorState; |
| | | import com.battery.device.simulator.BtsSimulatorStateStore.DeviceState; |
| | | import com.battery.device.simulator.BtsSimulatorStateStore.BtsDeviceProfile; |
| | | import com.battery.device.simulator.BtsSimulatorStateStore.BtsHistoryRecord; |
| | | import com.battery.device.simulator.BtsSimulatorStateStore.BtsPlaybackState; |
| | | import com.battery.device.simulator.BtsSimulatorStateStore.RecentRequest; |
| | | import com.battery.device.simulator.BtsSimulatorStateStore.SimulatorState; |
| | | import com.battery.device.simulator.InMemoryBtsSimulatorStateStore; |
| | | import com.battery.device.simulator.DevelopmentCollectorSimulation; |
| | | import com.battery.device.simulator.DevelopmentCollectorSimulation.CollectorAdvance; |
| | | import com.battery.device.simulator.DevelopmentCollectorSimulation.CollectorHistoryPage; |
| | | import com.battery.device.simulator.DevelopmentCollectorSimulation.CollectorRealtimeSnapshot; |
| | | |
| | | /** 提供由开发后端托管的临时只读 BTS 模拟端点。 */ |
| | | public final class BtsDevelopmentSimulator implements AutoCloseable |
| File was renamed from ruoyi-device/src/main/java/com/ruoyi/device/bts/BtsExcelFixture.java |
| | |
| | | package com.ruoyi.device.bts; |
| | | package com.battery.device.simulator; |
| | | |
| | | import java.io.BufferedReader; |
| | | import java.io.ByteArrayInputStream; |
| File was renamed from ruoyi-device/src/main/java/com/ruoyi/device/simulator/BtsSimulatorStateStore.java |
| | |
| | | package com.ruoyi.device.simulator; |
| | | package com.battery.device.simulator; |
| | | |
| | | import java.math.BigDecimal; |
| | | import java.time.Instant; |
| | | import java.util.List; |
| | | import com.ruoyi.device.model.DeviceWorkStatus; |
| | | import com.battery.device.model.DeviceWorkStatus; |
| | | |
| | | /** 持久化开发模拟器配置;实现必须在返回前确认写入成功。 */ |
| | | public interface BtsSimulatorStateStore |
| File was renamed from ruoyi-device/src/main/java/com/ruoyi/device/simulator/DevelopmentCollectorSimulation.java |
| | |
| | | package com.ruoyi.device.simulator; |
| | | package com.battery.device.simulator; |
| | | |
| | | import java.math.BigDecimal; |
| | | import java.time.Instant; |
| | |
| | | import java.util.List; |
| | | import java.util.Map; |
| | | import java.util.Set; |
| | | import com.ruoyi.device.simulator.BtsSimulatorStateStore.CollectorChannelState; |
| | | import com.ruoyi.device.simulator.BtsSimulatorStateStore.CollectorHistoryFaults; |
| | | import com.ruoyi.device.simulator.BtsSimulatorStateStore.CollectorMeasurementRecord; |
| | | import com.ruoyi.device.simulator.BtsSimulatorStateStore.CollectorMetricState; |
| | | import com.ruoyi.device.simulator.BtsSimulatorStateStore.CollectorRealtimeMeasurement; |
| | | import com.ruoyi.device.simulator.BtsSimulatorStateStore.CollectorState; |
| | | import com.battery.device.simulator.BtsSimulatorStateStore.CollectorChannelState; |
| | | import com.battery.device.simulator.BtsSimulatorStateStore.CollectorHistoryFaults; |
| | | import com.battery.device.simulator.BtsSimulatorStateStore.CollectorMeasurementRecord; |
| | | import com.battery.device.simulator.BtsSimulatorStateStore.CollectorMetricState; |
| | | import com.battery.device.simulator.BtsSimulatorStateStore.CollectorRealtimeMeasurement; |
| | | import com.battery.device.simulator.BtsSimulatorStateStore.CollectorState; |
| | | |
| | | /** 实现第一版开发采集器的独立采样与故障注入合同。 */ |
| | | public final class DevelopmentCollectorSimulation |
| File was renamed from ruoyi-device/src/main/java/com/ruoyi/device/simulator/InMemoryBtsSimulatorStateStore.java |
| | |
| | | package com.ruoyi.device.simulator; |
| | | package com.battery.device.simulator; |
| | | |
| | | import java.util.ArrayList; |
| | | import java.util.LinkedHashMap; |
| | | import java.util.List; |
| | | import java.util.Map; |
| | | import com.ruoyi.device.simulator.BtsSimulatorStateStore.CollectorHistoryAppend; |
| | | import com.ruoyi.device.simulator.BtsSimulatorStateStore.CollectorHistoryBatch; |
| | | import com.ruoyi.device.simulator.BtsSimulatorStateStore.CollectorMeasurementRecord; |
| | | import com.ruoyi.device.simulator.BtsSimulatorStateStore.BtsHistoryRecord; |
| | | import com.ruoyi.device.simulator.BtsSimulatorStateStore.BtsHistoryBatch; |
| | | import com.ruoyi.device.simulator.BtsSimulatorStateStore.RecentRequest; |
| | | import com.ruoyi.device.simulator.BtsSimulatorStateStore.SimulatorState; |
| | | import com.ruoyi.device.simulator.BtsSimulatorStateStore.BtsPlaybackState; |
| | | import com.battery.device.simulator.BtsSimulatorStateStore.CollectorHistoryAppend; |
| | | import com.battery.device.simulator.BtsSimulatorStateStore.CollectorHistoryBatch; |
| | | import com.battery.device.simulator.BtsSimulatorStateStore.CollectorMeasurementRecord; |
| | | import com.battery.device.simulator.BtsSimulatorStateStore.BtsHistoryRecord; |
| | | import com.battery.device.simulator.BtsSimulatorStateStore.BtsHistoryBatch; |
| | | import com.battery.device.simulator.BtsSimulatorStateStore.RecentRequest; |
| | | import com.battery.device.simulator.BtsSimulatorStateStore.SimulatorState; |
| | | import com.battery.device.simulator.BtsSimulatorStateStore.BtsPlaybackState; |
| | | |
| | | /** 测试和独立协议合同使用的内存状态存储。 */ |
| | | public final class InMemoryBtsSimulatorStateStore implements BtsSimulatorStateStore |
copy from ruoyi-device/src/main/java/com/ruoyi/device/bts/ScriptedBtsTcpSimulator.java
copy to battery-device-simulator/src/main/java/com/battery/device/simulator/ScriptedBtsTcpSimulator.java
| File was copied from ruoyi-device/src/main/java/com/ruoyi/device/bts/ScriptedBtsTcpSimulator.java |
| | |
| | | package com.ruoyi.device.bts; |
| | | package com.battery.device.simulator; |
| | | |
| | | import java.io.IOException; |
| | | import java.io.InputStream; |
| | |
| | | |
| | | private String readFrame(InputStream input) throws IOException |
| | | { |
| | | return new String(BtsFrameReader.read(input, Integer.MAX_VALUE), StandardCharsets.UTF_8); |
| | | return new String(readFrameBytes(input), StandardCharsets.UTF_8); |
| | | } |
| | | |
| | | private byte[] readFrameBytes(InputStream input) throws IOException |
| | | { |
| | | java.io.ByteArrayOutputStream bytes = new java.io.ByteArrayOutputStream(); |
| | | byte[] delimiter = FRAME_END; |
| | | int matched = 0; |
| | | while (true) |
| | | { |
| | | int current = input.read(); |
| | | if (current < 0) throw new java.io.EOFException("BTS frame ended before delimiter"); |
| | | if ((byte) current == delimiter[matched]) |
| | | { |
| | | matched++; |
| | | if (matched == delimiter.length) return bytes.toByteArray(); |
| | | continue; |
| | | } |
| | | if (matched > 0) |
| | | { |
| | | for (int i = 0; i < matched; i++) bytes.write(delimiter[i]); |
| | | matched = 0; |
| | | if ((byte) current == delimiter[0]) |
| | | { |
| | | matched = 1; |
| | | continue; |
| | | } |
| | | } |
| | | bytes.write(current); |
| | | } |
| | | } |
| | | |
| | | @Override |
| File was renamed from ruoyi-device/src/test/java/com/ruoyi/device/contract/DiscoveryCandidateStoreContractTest.java |
| | |
| | | package com.ruoyi.device.contract; |
| | | package com.battery.device.contract; |
| | | |
| | | import static org.junit.jupiter.api.Assertions.assertEquals; |
| | | import java.time.Instant; |
| | | import java.util.List; |
| | | import org.junit.jupiter.api.Test; |
| | | import com.ruoyi.device.discovery.DeviceDiscoveryCandidateStore.CabinetCandidate; |
| | | import com.ruoyi.device.discovery.DeviceDiscoveryCandidateStore.ChannelCandidate; |
| | | import com.ruoyi.device.discovery.DeviceDiscoveryCandidateStore.CollectorCandidate; |
| | | import com.ruoyi.device.discovery.InMemoryDeviceDiscoveryCandidateStore; |
| | | import com.ruoyi.device.model.ChannelIdentity; |
| | | import com.ruoyi.device.model.DeviceWorkStatus; |
| | | import com.battery.device.discovery.DeviceDiscoveryCandidateStore.CabinetCandidate; |
| | | import com.battery.device.discovery.DeviceDiscoveryCandidateStore.ChannelCandidate; |
| | | import com.battery.device.discovery.DeviceDiscoveryCandidateStore.CollectorCandidate; |
| | | import com.battery.device.discovery.InMemoryDeviceDiscoveryCandidateStore; |
| | | import com.battery.device.model.ChannelIdentity; |
| | | import com.battery.device.model.DeviceWorkStatus; |
| | | |
| | | class DiscoveryCandidateStoreContractTest |
| | | { |
| File was renamed from ruoyi-device/src/test/java/com/ruoyi/device/contract/SimulatorPublicContractTest.java |
| | |
| | | package com.ruoyi.device.contract; |
| | | package com.battery.device.contract; |
| | | |
| | | import static org.junit.jupiter.api.Assertions.assertEquals; |
| | | import static org.junit.jupiter.api.Assertions.assertNotEquals; |
| | |
| | | import java.util.Set; |
| | | import org.junit.jupiter.api.Test; |
| | | import com.alibaba.fastjson2.JSON; |
| | | import com.ruoyi.device.api.DeviceAdapter; |
| | | import com.ruoyi.device.bts.BtsDevelopmentSimulator; |
| | | import com.ruoyi.device.bts.BtsDeviceAdapter; |
| | | import com.ruoyi.device.bts.BtsXmlCodec; |
| | | import com.ruoyi.device.bts.BtsTcpTransport; |
| | | import com.ruoyi.device.bts.ScriptedBtsTcpSimulator; |
| | | import com.ruoyi.device.model.DetectedChannel; |
| | | import com.ruoyi.device.model.DeviceWorkStatus; |
| | | import com.ruoyi.device.simulator.BtsSimulatorStateStore; |
| | | import com.ruoyi.device.simulator.BtsSimulatorStateStore.ChannelState; |
| | | import com.ruoyi.device.simulator.BtsSimulatorStateStore.CollectorChannelState; |
| | | import com.ruoyi.device.simulator.BtsSimulatorStateStore.CollectorHistoryAppend; |
| | | import com.ruoyi.device.simulator.BtsSimulatorStateStore.CollectorHistoryBatch; |
| | | import com.ruoyi.device.simulator.BtsSimulatorStateStore.CollectorHistoryFaults; |
| | | import com.ruoyi.device.simulator.BtsSimulatorStateStore.CollectorMeasurementRecord; |
| | | import com.ruoyi.device.simulator.BtsSimulatorStateStore.CollectorMetricState; |
| | | import com.ruoyi.device.simulator.BtsSimulatorStateStore.CollectorState; |
| | | import com.ruoyi.device.simulator.BtsSimulatorStateStore.DeviceState; |
| | | import com.ruoyi.device.simulator.BtsSimulatorStateStore.SimulatorState; |
| | | import com.ruoyi.device.simulator.BtsSimulatorStateStore.RecentRequest; |
| | | import com.ruoyi.device.simulator.InMemoryBtsSimulatorStateStore; |
| | | import com.battery.device.api.DeviceAdapter; |
| | | import com.battery.device.simulator.BtsDevelopmentSimulator; |
| | | import com.battery.device.bts.BtsDeviceAdapter; |
| | | import com.battery.device.bts.BtsXmlCodec; |
| | | import com.battery.device.bts.BtsTcpTransport; |
| | | import com.battery.device.simulator.ScriptedBtsTcpSimulator; |
| | | import com.battery.device.model.DetectedChannel; |
| | | import com.battery.device.model.DeviceWorkStatus; |
| | | import com.battery.device.simulator.BtsSimulatorStateStore; |
| | | import com.battery.device.simulator.BtsSimulatorStateStore.ChannelState; |
| | | import com.battery.device.simulator.BtsSimulatorStateStore.CollectorChannelState; |
| | | import com.battery.device.simulator.BtsSimulatorStateStore.CollectorHistoryAppend; |
| | | import com.battery.device.simulator.BtsSimulatorStateStore.CollectorHistoryBatch; |
| | | import com.battery.device.simulator.BtsSimulatorStateStore.CollectorHistoryFaults; |
| | | import com.battery.device.simulator.BtsSimulatorStateStore.CollectorMeasurementRecord; |
| | | import com.battery.device.simulator.BtsSimulatorStateStore.CollectorMetricState; |
| | | import com.battery.device.simulator.BtsSimulatorStateStore.CollectorState; |
| | | import com.battery.device.simulator.BtsSimulatorStateStore.DeviceState; |
| | | import com.battery.device.simulator.BtsSimulatorStateStore.SimulatorState; |
| | | import com.battery.device.simulator.BtsSimulatorStateStore.RecentRequest; |
| | | import com.battery.device.simulator.InMemoryBtsSimulatorStateStore; |
| | | |
| | | class SimulatorPublicContractTest |
| | | { |
| | |
| | | |
| | | var first = simulator.collectorHistory(1, 0, 17); |
| | | var second = simulator.collectorHistory(1, first.nextOffset(), 1000); |
| | | List<com.ruoyi.device.simulator.BtsSimulatorStateStore.CollectorMeasurementRecord> records = |
| | | List<com.battery.device.simulator.BtsSimulatorStateStore.CollectorMeasurementRecord> records = |
| | | new java.util.ArrayList<>(first.records()); |
| | | records.addAll(second.records()); |
| | | |
| | |
| | | assertEquals(1, firstDiscovery.stream().map(channel -> channel.identity().devid()).distinct().count()); |
| | | assertEquals(4, firstDiscovery.stream().filter(channel -> channel.available()).count()); |
| | | |
| | | Set<com.ruoyi.device.model.ChannelIdentity> channels = firstDiscovery.stream() |
| | | Set<com.battery.device.model.ChannelIdentity> channels = firstDiscovery.stream() |
| | | .map(channel -> channel.identity()) |
| | | .collect(java.util.stream.Collectors.toSet()); |
| | | var firstObservation = adapter.inquire(channels); |
| | |
| | | .filter(device -> device.deviceId() == tDevice || device.deviceId() == tnDevice) |
| | | .mapToInt(device -> device.channels().size()).sum() / 2); |
| | | |
| | | Set<com.ruoyi.device.model.ChannelIdentity> channel = tChannels.stream() |
| | | Set<com.battery.device.model.ChannelIdentity> channel = tChannels.stream() |
| | | .map(DetectedChannel::identity).filter(identity -> identity.chlid() == 1) |
| | | .collect(java.util.stream.Collectors.toSet()); |
| | | var first = adapter.inquire(channel).values().iterator().next(); |
| | |
| | | simulator.updateChannel(1, 2, false, DeviceWorkStatus.PAUSED); |
| | | |
| | | var discovered = adapter.discoverChannels(); |
| | | Set<com.ruoyi.device.model.ChannelIdentity> available = discovered.stream() |
| | | Set<com.battery.device.model.ChannelIdentity> available = discovered.stream() |
| | | .filter(channel -> channel.available()) |
| | | .map(channel -> channel.identity()) |
| | | .collect(java.util.stream.Collectors.toSet()); |
| File was renamed from ruoyi-device/src/test/java/com/ruoyi/device/bts/BtsDevelopmentSimulatorHistoryContractTest.java |
| | |
| | | package com.ruoyi.device.bts; |
| | | package com.battery.device.simulator; |
| | | |
| | | import static org.junit.jupiter.api.Assertions.assertEquals; |
| | | import static org.junit.jupiter.api.Assertions.assertFalse; |
| | | import java.time.Duration; |
| | | import java.time.ZoneId; |
| | | import org.junit.jupiter.api.Test; |
| | | import com.ruoyi.device.model.DeviceWorkStatus; |
| | | import com.ruoyi.device.simulator.InMemoryBtsSimulatorStateStore; |
| | | import com.battery.device.model.DeviceWorkStatus; |
| | | import com.battery.device.bts.BtsDeviceAdapter; |
| | | import com.battery.device.bts.BtsTcpTransport; |
| | | import com.battery.device.bts.BtsXmlCodec; |
| | | import com.battery.device.simulator.InMemoryBtsSimulatorStateStore; |
| | | |
| | | /** Ticket13:开发检测柜历史合同与实时快照保持两条独立路径。 */ |
| | | class BtsDevelopmentSimulatorHistoryContractTest |
| File was renamed from ruoyi-device/src/test/java/com/ruoyi/device/bts/BtsDevelopmentSimulatorRecordStepCycleTest.java |
| | |
| | | package com.ruoyi.device.bts; |
| | | package com.battery.device.simulator; |
| | | |
| | | import static org.junit.jupiter.api.Assertions.assertEquals; |
| | | import static org.junit.jupiter.api.Assertions.assertFalse; |
| | | import static org.junit.jupiter.api.Assertions.assertTrue; |
| | | import java.time.Instant; |
| | | import org.junit.jupiter.api.Test; |
| | | import com.ruoyi.device.model.DeviceWorkStatus; |
| | | import com.ruoyi.device.simulator.BtsSimulatorStateStore.BtsPlaybackState; |
| | | import com.ruoyi.device.simulator.InMemoryBtsSimulatorStateStore; |
| | | import com.battery.device.model.DeviceWorkStatus; |
| | | import com.battery.device.bts.BtsDeviceAdapter; |
| | | import com.battery.device.bts.BtsTcpTransport; |
| | | import com.battery.device.bts.BtsXmlCodec; |
| | | import com.battery.device.simulator.BtsSimulatorStateStore.BtsPlaybackState; |
| | | import com.battery.device.simulator.InMemoryBtsSimulatorStateStore; |
| | | |
| | | /** Ticket21:检测柜 record、step、cycle 生命周期和播放控制合同。 */ |
| | | class BtsDevelopmentSimulatorRecordStepCycleTest |
| | |
| | | <version>${ruoyi.version}</version> |
| | | </dependency> |
| | | |
| | | <!-- 设备适配模块 --> |
| | | <dependency> |
| | | <groupId>com.ruoyi</groupId> |
| | | <artifactId>ruoyi-device</artifactId> |
| | | <groupId>com.battery</groupId> |
| | | <artifactId>battery-business</artifactId> |
| | | <version>${ruoyi.version}</version> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>com.battery</groupId> |
| | | <artifactId>battery-device-api</artifactId> |
| | | <version>${ruoyi.version}</version> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>com.battery</groupId> |
| | | <artifactId>battery-device-bts</artifactId> |
| | | <version>${ruoyi.version}</version> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>com.battery</groupId> |
| | | <artifactId>battery-device-simulator</artifactId> |
| | | <version>${ruoyi.version}</version> |
| | | </dependency> |
| | | |
| | |
| | | <module>ruoyi-admin</module> |
| | | <module>ruoyi-framework</module> |
| | | <module>ruoyi-system</module> |
| | | <module>ruoyi-device</module> |
| | | <module>battery-business</module> |
| | | <module>battery-device-api</module> |
| | | <module>battery-device-bts</module> |
| | | <module>battery-device-simulator</module> |
| | | <module>ruoyi-quartz</module> |
| | | <module>ruoyi-generator</module> |
| | | <module>ruoyi-common</module> |
| | |
| | | <artifactId>ruoyi-framework</artifactId> |
| | | </dependency> |
| | | |
| | | <!-- 设备适配模块 --> |
| | | <!-- 自研业务与设备模块 --> |
| | | <dependency> |
| | | <groupId>com.ruoyi</groupId> |
| | | <artifactId>ruoyi-device</artifactId> |
| | | <groupId>com.battery</groupId> |
| | | <artifactId>battery-business</artifactId> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>com.battery</groupId> |
| | | <artifactId>battery-device-api</artifactId> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>com.battery</groupId> |
| | | <artifactId>battery-device-bts</artifactId> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>com.battery</groupId> |
| | | <artifactId>battery-device-simulator</artifactId> |
| | | </dependency> |
| | | |
| | | <!-- 定时任务--> |
| | |
| | | import java.util.Set; |
| | | import java.time.Instant; |
| | | import org.springframework.stereotype.Service; |
| | | import com.ruoyi.device.discovery.DeviceDiscoveryCandidateStore; |
| | | import com.battery.device.discovery.DeviceDiscoveryCandidateStore; |
| | | import com.ruoyi.system.domain.vo.DiscoveredCollectorVo; |
| | | import com.ruoyi.system.service.ICollectorDiscoveryService; |
| | | import com.ruoyi.system.service.ITCollectorService; |
| | |
| | | import org.springframework.scheduling.annotation.Scheduled; |
| | | import org.springframework.stereotype.Component; |
| | | import org.springframework.context.annotation.Profile; |
| | | import com.ruoyi.device.bts.BtsDevelopmentSimulator; |
| | | import com.battery.device.simulator.BtsDevelopmentSimulator; |
| | | |
| | | /** 按各采集器配置频率推进开发模拟测量,不参与正式测试数据持久化。 */ |
| | | @Component |
| | |
| | | import org.springframework.scheduling.annotation.Scheduled; |
| | | import org.springframework.stereotype.Component; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import com.ruoyi.device.bts.BtsDevelopmentSimulator; |
| | | import com.ruoyi.device.discovery.DeviceDiscoveryCandidateStore; |
| | | import com.ruoyi.device.discovery.DeviceDiscoveryCandidateStore.CollectorCandidate; |
| | | import org.springframework.context.annotation.Profile; |
| | | import com.battery.device.simulator.BtsDevelopmentSimulator; |
| | | import com.battery.device.discovery.DeviceDiscoveryCandidateStore; |
| | | import com.battery.device.discovery.DeviceDiscoveryCandidateStore.CollectorCandidate; |
| | | import com.ruoyi.system.mapper.TCollectorMapper; |
| | | |
| | | /** 将模拟采集器的发现写入 Redis,并同步已登记采集器的实时在线事实。 */ |
| | | @Component |
| | | @Profile("dev-simulator") |
| | | public class DevelopmentCollectorStatusSynchronizer |
| | | { |
| | | private final BtsDevelopmentSimulator simulator; |
| | |
| | | import org.springframework.scheduling.annotation.Scheduled; |
| | | import org.springframework.stereotype.Component; |
| | | import org.springframework.context.annotation.Profile; |
| | | import com.ruoyi.device.bts.BtsDevelopmentSimulator; |
| | | import com.ruoyi.device.registry.DeviceAdapterRegistry; |
| | | import com.battery.device.simulator.BtsDevelopmentSimulator; |
| | | import com.battery.device.registry.DeviceAdapterRegistry; |
| | | import com.ruoyi.system.service.impl.DeviceDiscoveryPersistenceService; |
| | | import com.ruoyi.system.service.impl.DeviceDiscoveryPersistenceService.DiscoverySource; |
| | | |
| | |
| | | import org.springframework.beans.factory.annotation.Value; |
| | | import org.springframework.context.annotation.Bean; |
| | | import org.springframework.context.annotation.Configuration; |
| | | import org.springframework.context.annotation.Profile; |
| | | import org.springframework.scheduling.annotation.EnableScheduling; |
| | | import com.ruoyi.device.bts.BtsDeviceAdapterFactory; |
| | | import com.ruoyi.device.bts.BtsDevelopmentSimulator; |
| | | import com.ruoyi.device.model.AdapterCapabilities; |
| | | import com.ruoyi.device.registry.AdapterInstanceConfig; |
| | | import com.ruoyi.device.registry.DeviceAdapterRegistry; |
| | | import com.ruoyi.device.simulator.BtsSimulatorStateStore; |
| | | import com.battery.device.api.NoopDeviceAdapterFactory; |
| | | import com.battery.device.bts.BtsDeviceAdapterFactory; |
| | | import com.battery.device.simulator.BtsDevelopmentSimulator; |
| | | import com.battery.device.model.AdapterCapabilities; |
| | | import com.battery.device.registry.AdapterInstanceConfig; |
| | | import com.battery.device.registry.DeviceAdapterRegistry; |
| | | import com.battery.device.simulator.BtsSimulatorStateStore; |
| | | |
| | | /** 装配单进程设备适配器运行时。 */ |
| | | @Configuration |
| | |
| | | public class DeviceAdapterRuntimeConfig |
| | | { |
| | | @Bean(destroyMethod = "close") |
| | | @Profile("!dev-simulator & !bts") |
| | | public DeviceAdapterRegistry noopDeviceAdapterRegistry() |
| | | { |
| | | return new DeviceAdapterRegistry(List.of(new NoopDeviceAdapterFactory())); |
| | | } |
| | | |
| | | @Bean(destroyMethod = "close") |
| | | @Profile({ "dev-simulator", "bts" }) |
| | | public DeviceAdapterRegistry deviceAdapterRegistry() |
| | | { |
| | | return new DeviceAdapterRegistry(List.of(new BtsDeviceAdapterFactory())); |
| | | } |
| | | |
| | | @Bean(destroyMethod = "close") |
| | | @Profile("dev-simulator") |
| | | public BtsDevelopmentSimulator btsDevelopmentSimulator(BtsSimulatorStateStore stateStore, |
| | | @Value("${battery.dev-simulator.port:15020}") int simulatorPort) throws IOException |
| | | { |
| | |
| | | } |
| | | |
| | | @Bean |
| | | @Profile("dev-simulator") |
| | | public ApplicationRunner registerDevelopmentSimulatorAdapter(DeviceAdapterRegistry registry, |
| | | @Value("${battery.dev-simulator.port:15020}") int simulatorPort) |
| | | { |
| | |
| | | import org.springframework.data.redis.core.SessionCallback; |
| | | import org.springframework.data.redis.core.RedisTemplate; |
| | | import org.springframework.stereotype.Component; |
| | | import org.springframework.context.annotation.Profile; |
| | | 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.simulator.BtsSimulatorStateStore.BtsDeviceProfile; |
| | | import com.ruoyi.device.simulator.BtsSimulatorStateStore.BtsHistoryBatch; |
| | | import com.ruoyi.device.simulator.BtsSimulatorStateStore.BtsHistoryRecord; |
| | | import com.ruoyi.device.simulator.BtsSimulatorStateStore.BtsPlaybackState; |
| | | import com.ruoyi.device.model.DeviceWorkStatus; |
| | | import com.battery.device.simulator.BtsSimulatorStateStore; |
| | | import com.battery.device.simulator.BtsSimulatorStateStore.BtsDeviceProfile; |
| | | import com.battery.device.simulator.BtsSimulatorStateStore.BtsHistoryBatch; |
| | | import com.battery.device.simulator.BtsSimulatorStateStore.BtsHistoryRecord; |
| | | import com.battery.device.simulator.BtsSimulatorStateStore.BtsPlaybackState; |
| | | import com.battery.device.model.DeviceWorkStatus; |
| | | |
| | | /** 将开发模拟器完整状态写入 Redis,主状态不设置普通 TTL。 */ |
| | | @Component |
| | | @Profile("dev-simulator") |
| | | public class RedisBtsSimulatorStateStore implements BtsSimulatorStateStore |
| | | { |
| | | static final String STATE_KEY = "dev:bts-simulator:state:v1"; |
| | |
| | | import com.alibaba.fastjson2.JSON; |
| | | import com.alibaba.fastjson2.JSONArray; |
| | | import com.alibaba.fastjson2.JSONObject; |
| | | import com.ruoyi.device.discovery.DeviceDiscoveryCandidateStore; |
| | | import com.ruoyi.device.model.ChannelIdentity; |
| | | import com.ruoyi.device.model.DeviceWorkStatus; |
| | | import com.ruoyi.device.model.RealtimeSnapshot; |
| | | import com.battery.device.discovery.DeviceDiscoveryCandidateStore; |
| | | import com.battery.device.model.ChannelIdentity; |
| | | import com.battery.device.model.DeviceWorkStatus; |
| | | import com.battery.device.model.RealtimeSnapshot; |
| | | |
| | | /** 保存发现候选和实时状态;条目按 expiresAt 逻辑过期,Redis key 本身不设短 TTL。 */ |
| | | @Component |
| | |
| | | import org.springframework.web.bind.annotation.RestController; |
| | | import org.springframework.web.server.ResponseStatusException; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.context.annotation.Profile; |
| | | import com.ruoyi.common.annotation.Anonymous; |
| | | import com.ruoyi.device.bts.BtsDevelopmentSimulator; |
| | | import com.ruoyi.device.bts.BtsDevelopmentSimulator.StateSnapshot; |
| | | import com.ruoyi.device.discovery.DeviceDiscoveryCandidateStore; |
| | | import com.ruoyi.device.model.DeviceWorkStatus; |
| | | import com.ruoyi.device.simulator.BtsSimulatorStateStore.CollectorHistoryFaults; |
| | | import com.ruoyi.device.simulator.BtsSimulatorStateStore.CollectorMetricState; |
| | | import com.ruoyi.device.simulator.DevelopmentCollectorSimulation.CollectorHistoryPage; |
| | | import com.ruoyi.device.simulator.DevelopmentCollectorSimulation.CollectorRealtimeSnapshot; |
| | | import com.ruoyi.device.bts.BtsDevelopmentSimulator.PlaybackSnapshot; |
| | | import com.battery.device.simulator.BtsDevelopmentSimulator; |
| | | import com.battery.device.simulator.BtsDevelopmentSimulator.StateSnapshot; |
| | | import com.battery.device.discovery.DeviceDiscoveryCandidateStore; |
| | | import com.battery.device.model.DeviceWorkStatus; |
| | | import com.battery.device.simulator.BtsSimulatorStateStore.CollectorHistoryFaults; |
| | | import com.battery.device.simulator.BtsSimulatorStateStore.CollectorMetricState; |
| | | import com.battery.device.simulator.DevelopmentCollectorSimulation.CollectorHistoryPage; |
| | | import com.battery.device.simulator.DevelopmentCollectorSimulation.CollectorRealtimeSnapshot; |
| | | import com.battery.device.simulator.BtsDevelopmentSimulator.PlaybackSnapshot; |
| | | |
| | | /** 本机临时 BTS 模拟器控制 API。 */ |
| | | @Anonymous |
| | | @RestController |
| | | @Profile("dev-simulator") |
| | | public class BtsDevelopmentSimulatorController |
| | | { |
| | | private final BtsDevelopmentSimulator simulator; |
| | |
| | | } |
| | | |
| | | @GetMapping("/dev/bts-simulator/devices/{deviceId}/channels/{channelId}/records") |
| | | public List<com.ruoyi.device.simulator.BtsSimulatorStateStore.BtsHistoryRecord> btsRecords( |
| | | public List<com.battery.device.simulator.BtsSimulatorStateStore.BtsHistoryRecord> btsRecords( |
| | | @PathVariable int deviceId, @PathVariable int channelId) |
| | | { |
| | | try { return simulator.btsRecords(deviceId, channelId); } |
| | |
| | | # 国际化资源文件路径 |
| | | basename: i18n/messages |
| | | profiles: |
| | | # 仓库默认启动用于本机联调;真实设备部署必须覆盖并移除 dev-simulator。 |
| | | active: druid,dev-simulator |
| | | # 默认不连接任何设备;本机演示时显式追加 dev-simulator。 |
| | | active: druid |
| | | # 文件上传 |
| | | servlet: |
| | | multipart: |
| | |
| | | import static org.junit.jupiter.api.Assertions.assertTrue; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.junit.jupiter.api.Test; |
| | | import com.ruoyi.device.bts.BtsDevelopmentSimulator; |
| | | import com.ruoyi.device.discovery.InMemoryDeviceDiscoveryCandidateStore; |
| | | import com.battery.device.simulator.BtsDevelopmentSimulator; |
| | | import com.battery.device.discovery.InMemoryDeviceDiscoveryCandidateStore; |
| | | import com.ruoyi.system.mapper.TCollectorMapper; |
| | | import static org.mockito.Mockito.mock; |
| | | import static org.mockito.Mockito.verify; |
| | |
| | | class DevelopmentSimulatorProfileContractTest |
| | | { |
| | | @Test |
| | | void enablesSimulatorSchedulingForDefaultDevelopmentStartup() throws Exception |
| | | void usesNoDeviceProfileByDefault() throws Exception |
| | | { |
| | | var sources = new YamlPropertySourceLoader().load("application", new ClassPathResource("application.yml")); |
| | | Object profiles = sources.get(0).getProperty("spring.profiles.active"); |
| | | |
| | | assertEquals(List.of("druid", "dev-simulator"), List.of(String.valueOf(profiles).split(","))); |
| | | assertEquals(List.of("druid"), List.of(String.valueOf(profiles).split(","))); |
| | | } |
| | | } |
| | |
| | | import org.junit.jupiter.api.Test; |
| | | import org.springframework.boot.DefaultApplicationArguments; |
| | | import org.mockito.ArgumentCaptor; |
| | | import com.ruoyi.device.registry.AdapterInstanceConfig; |
| | | import com.ruoyi.device.registry.DeviceAdapterRegistry; |
| | | import com.battery.device.registry.AdapterInstanceConfig; |
| | | import com.battery.device.registry.DeviceAdapterRegistry; |
| | | |
| | | class DeviceAdapterRuntimeConfigTest |
| | | { |
| New file |
| | |
| | | package com.ruoyi.config; |
| | | |
| | | import static org.junit.jupiter.api.Assertions.assertInstanceOf; |
| | | import static org.junit.jupiter.api.Assertions.assertFalse; |
| | | import org.junit.jupiter.api.Test; |
| | | import org.springframework.context.annotation.AnnotationConfigApplicationContext; |
| | | import com.battery.device.api.NoopDeviceAdapter; |
| | | import com.battery.device.registry.DeviceAdapterRegistry; |
| | | |
| | | class DeviceAdapterRuntimeNoopStartupTest |
| | | { |
| | | @Test |
| | | void startsWithoutDeviceProfileUsingNoopRegistry() |
| | | { |
| | | try (AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext()) |
| | | { |
| | | context.register(DeviceAdapterRuntimeConfig.class); |
| | | context.refresh(); |
| | | DeviceAdapterRegistry registry = context.getBean(DeviceAdapterRegistry.class); |
| | | assertFalse(registry.contains("dev-sim")); |
| | | registry.synchronize(new com.battery.device.registry.AdapterInstanceConfig( |
| | | "noop-check", "NOOP", "127.0.0.1", 1, 1000, "Asia/Hong_Kong", |
| | | true, new com.battery.device.model.AdapterCapabilities(true, true, false, false))); |
| | | var adapter = registry.execute("noop-check", value -> value); |
| | | assertInstanceOf(NoopDeviceAdapter.class, adapter); |
| | | } |
| | | } |
| | | } |
| | |
| | | import org.springframework.data.redis.core.ValueOperations; |
| | | import com.alibaba.fastjson2.JSON; |
| | | import com.alibaba.fastjson2.JSONObject; |
| | | import com.ruoyi.device.model.DeviceWorkStatus; |
| | | import com.ruoyi.device.bts.BtsDevelopmentSimulator; |
| | | import com.ruoyi.device.simulator.BtsSimulatorStateStore.ChannelState; |
| | | import com.ruoyi.device.simulator.BtsSimulatorStateStore.ChannelTombstone; |
| | | import com.ruoyi.device.simulator.BtsSimulatorStateStore.CollectorState; |
| | | import com.ruoyi.device.simulator.BtsSimulatorStateStore.DeviceState; |
| | | import com.ruoyi.device.simulator.BtsSimulatorStateStore.SimulatorState; |
| | | import com.ruoyi.device.discovery.DeviceDiscoveryCandidateStore.CabinetCandidate; |
| | | import com.ruoyi.device.discovery.DeviceDiscoveryCandidateStore.ChannelCandidate; |
| | | import com.ruoyi.device.discovery.DeviceDiscoveryCandidateStore.CollectorCandidate; |
| | | import com.ruoyi.device.model.ChannelIdentity; |
| | | import com.battery.device.model.DeviceWorkStatus; |
| | | import com.battery.device.simulator.BtsDevelopmentSimulator; |
| | | import com.battery.device.simulator.BtsSimulatorStateStore.ChannelState; |
| | | import com.battery.device.simulator.BtsSimulatorStateStore.ChannelTombstone; |
| | | import com.battery.device.simulator.BtsSimulatorStateStore.CollectorState; |
| | | import com.battery.device.simulator.BtsSimulatorStateStore.DeviceState; |
| | | import com.battery.device.simulator.BtsSimulatorStateStore.SimulatorState; |
| | | import com.battery.device.discovery.DeviceDiscoveryCandidateStore.CabinetCandidate; |
| | | import com.battery.device.discovery.DeviceDiscoveryCandidateStore.ChannelCandidate; |
| | | import com.battery.device.discovery.DeviceDiscoveryCandidateStore.CollectorCandidate; |
| | | import com.battery.device.model.ChannelIdentity; |
| | | import com.ruoyi.framework.config.FastJson2JsonRedisSerializer; |
| | | |
| | | class RedisStateStoreTest |
| | |
| | | RedisBtsSimulatorStateStore store = store(stored); |
| | | SimulatorState current = state(1, "127.0.0.2"); |
| | | store.loadOrInitialize(current); |
| | | var record = new com.ruoyi.device.simulator.BtsSimulatorStateStore.CollectorMeasurementRecord( |
| | | var record = new com.battery.device.simulator.BtsSimulatorStateStore.CollectorMeasurementRecord( |
| | | "dev-sim", "dev-sim-collector-1", "S-01", 1L, |
| | | java.time.Instant.parse("2026-08-29T05:00:00Z"), "2026-08-29 13:00:00.000", |
| | | java.time.Instant.parse("2026-08-29T05:00:00Z"), "temperature", |
| | | new java.math.BigDecimal("25.1"), "℃"); |
| | | store.save(current, List.of( |
| | | new com.ruoyi.device.simulator.BtsSimulatorStateStore.CollectorHistoryAppend( |
| | | new com.battery.device.simulator.BtsSimulatorStateStore.CollectorHistoryAppend( |
| | | "dev-sim-collector-1", List.of(record)))); |
| | | SimulatorState next = state(7, "127.0.0.9"); |
| | | |
| | |
| | | RedisBtsSimulatorStateStore store = new RedisBtsSimulatorStateStore(redis); |
| | | SimulatorState current = state(1, "127.0.0.2"); |
| | | store.loadOrInitialize(current); |
| | | var record = new com.ruoyi.device.simulator.BtsSimulatorStateStore.CollectorMeasurementRecord( |
| | | var record = new com.battery.device.simulator.BtsSimulatorStateStore.CollectorMeasurementRecord( |
| | | "dev-sim", "dev-sim-collector-1", "S-01", 1L, |
| | | java.time.Instant.parse("2026-08-29T05:00:00Z"), "2026-08-29 13:00:00.000", |
| | | java.time.Instant.parse("2026-08-29T05:00:00Z"), "temperature", |
| | | new java.math.BigDecimal("25.1"), "℃"); |
| | | store.save(current, List.of( |
| | | new com.ruoyi.device.simulator.BtsSimulatorStateStore.CollectorHistoryAppend( |
| | | new com.battery.device.simulator.BtsSimulatorStateStore.CollectorHistoryAppend( |
| | | "dev-sim-collector-1", java.util.Collections.nCopies(1010, record)))); |
| | | ListOperations<Object, Object> lists = redis.opsForList(); |
| | | clearInvocations(lists); |
| | |
| | | import org.junit.jupiter.api.Test; |
| | | import com.ruoyi.config.DevelopmentCollectorDiscoveryService; |
| | | import com.ruoyi.config.DevelopmentCollectorStatusSynchronizer; |
| | | import com.ruoyi.device.bts.BtsDevelopmentSimulator; |
| | | import com.ruoyi.device.discovery.InMemoryDeviceDiscoveryCandidateStore; |
| | | import com.battery.device.simulator.BtsDevelopmentSimulator; |
| | | import com.battery.device.discovery.InMemoryDeviceDiscoveryCandidateStore; |
| | | import com.ruoyi.system.domain.vo.DiscoveredCollectorVo; |
| | | import com.ruoyi.system.mapper.TCollectorMapper; |
| | | import com.ruoyi.system.service.ITCollectorService; |
| | |
| | | import org.mockito.junit.jupiter.MockitoExtension; |
| | | import org.springframework.context.annotation.AnnotationConfigApplicationContext; |
| | | import com.ruoyi.common.exception.ServiceException; |
| | | import com.ruoyi.device.api.DeviceAdapter; |
| | | import com.ruoyi.device.api.DeviceAdapterException; |
| | | import com.ruoyi.device.discovery.InMemoryDeviceDiscoveryCandidateStore; |
| | | import com.ruoyi.device.discovery.DeviceDiscoveryCandidateStore; |
| | | import com.ruoyi.device.model.ChannelIdentity; |
| | | import com.ruoyi.device.model.DetectedChannel; |
| | | import com.ruoyi.device.model.DetectedDeviceMetadata; |
| | | import com.ruoyi.device.model.DeviceWorkStatus; |
| | | import com.ruoyi.device.model.RealtimeSnapshot; |
| | | import com.ruoyi.device.registry.DeviceAdapterRegistry; |
| | | import com.battery.device.api.DeviceAdapter; |
| | | import com.battery.device.api.DeviceAdapterException; |
| | | import com.battery.device.discovery.InMemoryDeviceDiscoveryCandidateStore; |
| | | import com.battery.device.discovery.DeviceDiscoveryCandidateStore; |
| | | import com.battery.device.model.ChannelIdentity; |
| | | import com.battery.device.model.DetectedChannel; |
| | | import com.battery.device.model.DetectedDeviceMetadata; |
| | | import com.battery.device.model.DeviceWorkStatus; |
| | | import com.battery.device.model.RealtimeSnapshot; |
| | | import com.battery.device.registry.DeviceAdapterRegistry; |
| | | import com.ruoyi.system.domain.TDetectionCabinet; |
| | | import com.ruoyi.system.domain.TDetectionChannel; |
| | | import com.ruoyi.system.domain.TDeviceAdapter; |
| | |
| | | import java.util.function.Function; |
| | | import org.junit.jupiter.api.Test; |
| | | import org.mockito.Mockito; |
| | | import com.ruoyi.device.api.DeviceAdapter; |
| | | import com.ruoyi.device.discovery.InMemoryDeviceDiscoveryCandidateStore; |
| | | import com.ruoyi.device.model.ChannelIdentity; |
| | | import com.ruoyi.device.model.DetectedChannel; |
| | | import com.ruoyi.device.registry.DeviceAdapterRegistry; |
| | | import com.battery.device.api.DeviceAdapter; |
| | | import com.battery.device.discovery.InMemoryDeviceDiscoveryCandidateStore; |
| | | import com.battery.device.model.ChannelIdentity; |
| | | import com.battery.device.model.DetectedChannel; |
| | | import com.battery.device.registry.DeviceAdapterRegistry; |
| | | import com.ruoyi.system.mapper.TDetectionCabinetMapper; |
| | | import com.ruoyi.system.mapper.TTestMapper; |
| | | |
| | |
| | | import com.ruoyi.common.exception.ServiceException; |
| | | import com.ruoyi.system.domain.TCollector; |
| | | import com.ruoyi.system.mapper.TCollectorMapper; |
| | | import com.ruoyi.device.discovery.InMemoryDeviceDiscoveryCandidateStore; |
| | | import com.ruoyi.device.discovery.DeviceDiscoveryCandidateStore.CollectorCandidate; |
| | | import com.battery.device.discovery.InMemoryDeviceDiscoveryCandidateStore; |
| | | import com.battery.device.discovery.DeviceDiscoveryCandidateStore.CollectorCandidate; |
| | | |
| | | /** |
| | | * 采集器 Service 单元测试。 |
| | |
| | | import com.ruoyi.system.domain.TDetectionCabinet; |
| | | import com.ruoyi.system.domain.vo.DiscoveredCabinetVo; |
| | | import com.ruoyi.system.mapper.TDetectionCabinetMapper; |
| | | import com.ruoyi.device.discovery.InMemoryDeviceDiscoveryCandidateStore; |
| | | import com.ruoyi.device.discovery.DeviceDiscoveryCandidateStore.CabinetCandidate; |
| | | import com.ruoyi.device.discovery.DeviceDiscoveryCandidateStore.ChannelCandidate; |
| | | import com.ruoyi.device.model.ChannelIdentity; |
| | | import com.ruoyi.device.model.DeviceWorkStatus; |
| | | import com.battery.device.discovery.InMemoryDeviceDiscoveryCandidateStore; |
| | | import com.battery.device.discovery.DeviceDiscoveryCandidateStore.CabinetCandidate; |
| | | import com.battery.device.discovery.DeviceDiscoveryCandidateStore.ChannelCandidate; |
| | | import com.battery.device.model.ChannelIdentity; |
| | | import com.battery.device.model.DeviceWorkStatus; |
| | | |
| | | /** |
| | | * 检测柜业务层单元测试,验证字段规范化、状态限制及唯一性校验等关键规则。 |
| | |
| | | import org.junit.jupiter.api.Test; |
| | | import org.springframework.web.context.request.async.AsyncRequestNotUsableException; |
| | | import org.springframework.web.servlet.mvc.method.annotation.SseEmitter; |
| | | import com.ruoyi.device.bts.BtsDevelopmentSimulator; |
| | | import com.ruoyi.device.discovery.DeviceDiscoveryCandidateStore; |
| | | import com.ruoyi.device.model.ChannelIdentity; |
| | | import com.ruoyi.device.model.DeviceWorkStatus; |
| | | import com.ruoyi.device.model.RealtimeSnapshot; |
| | | import com.battery.device.simulator.BtsDevelopmentSimulator; |
| | | import com.battery.device.discovery.DeviceDiscoveryCandidateStore; |
| | | import com.battery.device.model.ChannelIdentity; |
| | | import com.battery.device.model.DeviceWorkStatus; |
| | | import com.battery.device.model.RealtimeSnapshot; |
| | | import com.ruoyi.system.domain.TTest; |
| | | import com.ruoyi.system.domain.TTestBattery; |
| | | import com.ruoyi.system.domain.TTestChannelBinding; |
| | |
| | | import java.util.List; |
| | | import java.math.BigDecimal; |
| | | import org.junit.jupiter.api.Test; |
| | | import com.ruoyi.device.bts.BtsDevelopmentSimulator; |
| | | import com.ruoyi.device.simulator.BtsSimulatorStateStore.BtsHistoryRecord; |
| | | import com.ruoyi.device.simulator.BtsSimulatorStateStore.CollectorRealtimeMeasurement; |
| | | import com.ruoyi.device.simulator.DevelopmentCollectorSimulation.CollectorRealtimeSnapshot; |
| | | import com.battery.device.simulator.BtsDevelopmentSimulator; |
| | | import com.battery.device.simulator.BtsSimulatorStateStore.BtsHistoryRecord; |
| | | import com.battery.device.simulator.BtsSimulatorStateStore.CollectorRealtimeMeasurement; |
| | | import com.battery.device.simulator.DevelopmentCollectorSimulation.CollectorRealtimeSnapshot; |
| | | import com.ruoyi.system.domain.TTestCollectorChannel; |
| | | import com.ruoyi.system.domain.TTest; |
| | | import com.ruoyi.system.domain.TTestBattery; |
| | |
| | | import org.springframework.web.bind.annotation.GetMapping; |
| | | import org.springframework.web.server.ResponseStatusException; |
| | | import com.ruoyi.common.annotation.Anonymous; |
| | | import com.ruoyi.device.bts.BtsDevelopmentSimulator; |
| | | import com.ruoyi.device.discovery.DeviceDiscoveryCandidateStore.CabinetCandidate; |
| | | import com.ruoyi.device.discovery.DeviceDiscoveryCandidateStore.ChannelCandidate; |
| | | import com.ruoyi.device.discovery.InMemoryDeviceDiscoveryCandidateStore; |
| | | import com.ruoyi.device.model.ChannelIdentity; |
| | | import com.ruoyi.device.model.DeviceWorkStatus; |
| | | import com.battery.device.simulator.BtsDevelopmentSimulator; |
| | | import com.battery.device.discovery.DeviceDiscoveryCandidateStore.CabinetCandidate; |
| | | import com.battery.device.discovery.DeviceDiscoveryCandidateStore.ChannelCandidate; |
| | | import com.battery.device.discovery.InMemoryDeviceDiscoveryCandidateStore; |
| | | import com.battery.device.model.ChannelIdentity; |
| | | import com.battery.device.model.DeviceWorkStatus; |
| | | import com.ruoyi.web.config.BtsDevelopmentSimulatorWebConfig; |
| | | import com.ruoyi.config.DevelopmentCollectorStatusSynchronizer; |
| | | |
| | |
| | | |
| | | <!-- 厂商无关设备适配契约 --> |
| | | <dependency> |
| | | <groupId>com.ruoyi</groupId> |
| | | <artifactId>ruoyi-device</artifactId> |
| | | <groupId>com.battery</groupId> |
| | | <artifactId>battery-device-api</artifactId> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>com.battery</groupId> |
| | | <artifactId>battery-device-simulator</artifactId> |
| | | </dependency> |
| | | |
| | | <!-- 通用工具--> |
| | |
| | | |
| | | import org.springframework.boot.context.event.ApplicationReadyEvent; |
| | | import org.springframework.context.event.EventListener; |
| | | import org.springframework.context.annotation.Profile; |
| | | import org.springframework.scheduling.annotation.Scheduled; |
| | | import org.springframework.stereotype.Component; |
| | | import com.ruoyi.system.service.IDeviceAdapterService; |
| | | |
| | | /** 在单采集进程内恢复启用实例,并按各自周期执行只读发现。 */ |
| | | @Component |
| | | @Profile({ "dev-simulator", "bts" }) |
| | | public class DeviceAdapterRuntimeCoordinator |
| | | { |
| | | private final IDeviceAdapterService service; |
| | |
| | | import com.alibaba.fastjson2.JSONObject; |
| | | import com.ruoyi.common.exception.ServiceException; |
| | | import com.ruoyi.common.utils.StringUtils; |
| | | import com.ruoyi.device.api.DeviceAdapterException; |
| | | import com.ruoyi.device.bts.BtsDevelopmentSimulator; |
| | | import com.ruoyi.device.discovery.DeviceDiscoveryCandidateStore; |
| | | import com.ruoyi.device.model.AdapterCapabilities; |
| | | import com.ruoyi.device.registry.AdapterInstanceConfig; |
| | | import com.ruoyi.device.registry.AdapterRegistryException; |
| | | import com.ruoyi.device.registry.DeviceAdapterRegistry; |
| | | import com.battery.device.api.DeviceAdapterException; |
| | | import com.battery.device.simulator.BtsDevelopmentSimulator; |
| | | import com.battery.device.discovery.DeviceDiscoveryCandidateStore; |
| | | import com.battery.device.model.AdapterCapabilities; |
| | | import com.battery.device.registry.AdapterInstanceConfig; |
| | | import com.battery.device.registry.AdapterRegistryException; |
| | | import com.battery.device.registry.DeviceAdapterRegistry; |
| | | import com.ruoyi.system.domain.TDetectionChannel; |
| | | import com.ruoyi.system.domain.TDeviceAdapter; |
| | | import com.ruoyi.system.domain.vo.AdapterDiscoveryResult; |
| | |
| | | import java.util.List; |
| | | import java.util.Map; |
| | | import java.util.Set; |
| | | import com.ruoyi.device.discovery.DeviceDiscoveryCandidateStore; |
| | | import com.ruoyi.device.discovery.DeviceDiscoveryCandidateStore.CabinetCandidate; |
| | | import com.ruoyi.device.discovery.DeviceDiscoveryCandidateStore.ChannelCandidate; |
| | | import com.ruoyi.device.model.ChannelIdentity; |
| | | import com.ruoyi.device.model.DetectedChannel; |
| | | import com.ruoyi.device.model.DetectedDeviceMetadata; |
| | | import com.ruoyi.device.model.DeviceWorkStatus; |
| | | import com.ruoyi.device.model.RealtimeSnapshot; |
| | | import com.ruoyi.device.registry.DeviceAdapterRegistry; |
| | | import com.battery.device.discovery.DeviceDiscoveryCandidateStore; |
| | | import com.battery.device.discovery.DeviceDiscoveryCandidateStore.CabinetCandidate; |
| | | import com.battery.device.discovery.DeviceDiscoveryCandidateStore.ChannelCandidate; |
| | | import com.battery.device.model.ChannelIdentity; |
| | | import com.battery.device.model.DetectedChannel; |
| | | import com.battery.device.model.DetectedDeviceMetadata; |
| | | import com.battery.device.model.DeviceWorkStatus; |
| | | import com.battery.device.model.RealtimeSnapshot; |
| | | import com.battery.device.registry.DeviceAdapterRegistry; |
| | | import com.ruoyi.system.domain.TDetectionChannel; |
| | | import com.ruoyi.system.domain.vo.AdapterDiscoveryResult; |
| | | import com.ruoyi.system.mapper.TDetectionCabinetMapper; |
| | |
| | | import com.ruoyi.system.domain.TCollector; |
| | | import com.ruoyi.system.mapper.TCollectorMapper; |
| | | import com.ruoyi.system.service.ITCollectorService; |
| | | import com.ruoyi.device.discovery.DeviceDiscoveryCandidateStore; |
| | | import com.ruoyi.device.discovery.DeviceDiscoveryCandidateStore.CollectorCandidate; |
| | | import com.battery.device.discovery.DeviceDiscoveryCandidateStore; |
| | | import com.battery.device.discovery.DeviceDiscoveryCandidateStore.CollectorCandidate; |
| | | |
| | | /** |
| | | * 采集器 Service 实现。 |
| | |
| | | import com.ruoyi.system.domain.vo.DiscoveredCabinetVo; |
| | | import com.ruoyi.system.mapper.TDetectionCabinetMapper; |
| | | import com.ruoyi.system.service.ITDetectionCabinetService; |
| | | import com.ruoyi.device.discovery.DeviceDiscoveryCandidateStore; |
| | | import com.ruoyi.device.discovery.DeviceDiscoveryCandidateStore.CabinetCandidate; |
| | | import com.ruoyi.device.model.DeviceWorkStatus; |
| | | import com.battery.device.discovery.DeviceDiscoveryCandidateStore; |
| | | import com.battery.device.discovery.DeviceDiscoveryCandidateStore.CabinetCandidate; |
| | | import com.battery.device.model.DeviceWorkStatus; |
| | | |
| | | /** |
| | | * 检测柜 Service 业务层处理 |
| | |
| | | import jakarta.annotation.PreDestroy; |
| | | import org.springframework.stereotype.Service; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.lang.Nullable; |
| | | import org.springframework.web.servlet.mvc.method.annotation.SseEmitter; |
| | | import com.ruoyi.device.bts.BtsDevelopmentSimulator; |
| | | import com.ruoyi.device.bts.BtsDevelopmentSimulator.CollectorSnapshot; |
| | | import com.ruoyi.device.discovery.DeviceDiscoveryCandidateStore; |
| | | import com.ruoyi.device.discovery.DeviceDiscoveryCandidateStore.CabinetCandidate; |
| | | import com.ruoyi.device.discovery.DeviceDiscoveryCandidateStore.ChannelCandidate; |
| | | import com.ruoyi.device.model.Measurement; |
| | | import com.battery.device.simulator.BtsDevelopmentSimulator; |
| | | import com.battery.device.simulator.BtsDevelopmentSimulator.CollectorSnapshot; |
| | | import com.battery.device.discovery.DeviceDiscoveryCandidateStore; |
| | | import com.battery.device.discovery.DeviceDiscoveryCandidateStore.CabinetCandidate; |
| | | import com.battery.device.discovery.DeviceDiscoveryCandidateStore.ChannelCandidate; |
| | | import com.battery.device.model.Measurement; |
| | | import com.ruoyi.system.domain.TTest; |
| | | import com.ruoyi.system.domain.TTestBattery; |
| | | import com.ruoyi.system.service.ITestLiveService; |
| | |
| | | |
| | | @Autowired |
| | | public TTestLiveServiceImpl(ITTestService tests, DeviceDiscoveryCandidateStore candidates, |
| | | BtsDevelopmentSimulator simulator, TTestMapper mapper) |
| | | @Nullable BtsDevelopmentSimulator simulator, TTestMapper mapper) |
| | | { this.tests = tests; this.candidates = candidates; this.simulator = simulator; this.mapper = mapper; } |
| | | |
| | | public TTestLiveServiceImpl(ITTestService tests, DeviceDiscoveryCandidateStore candidates, |
| | |
| | | |
| | | private TestPlanSnapshot detectorTestPlan(TTest test) |
| | | { |
| | | if (simulator == null) return null; |
| | | if (test.getBatteries() == null) return null; |
| | | for (TTestBattery battery : test.getBatteries()) |
| | | { |
| | |
| | | |
| | | private LiveSource collectorSource(TTestBattery battery) |
| | | { |
| | | if (simulator == null) return new LiveSource("COLLECTOR", battery.getCollectorId(), battery.getBatteryNo(), |
| | | "OFFLINE", Map.of()); |
| | | for (CollectorSnapshot collector : simulator.snapshot().collectors()) if (collector.collectorId() == battery.getCollectorId()) |
| | | { |
| | | Map<String, Object> value = new LinkedHashMap<>(); |
| | |
| | | import com.alibaba.fastjson2.JSON; |
| | | import org.springframework.stereotype.Service; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.lang.Nullable; |
| | | import org.springframework.transaction.annotation.Transactional; |
| | | import com.ruoyi.device.bts.BtsDevelopmentSimulator; |
| | | import com.ruoyi.device.simulator.BtsSimulatorStateStore.BtsHistoryRecord; |
| | | import com.ruoyi.device.simulator.BtsSimulatorStateStore.CollectorRealtimeMeasurement; |
| | | import com.ruoyi.device.simulator.DevelopmentCollectorSimulation.CollectorRealtimeSnapshot; |
| | | import com.battery.device.simulator.BtsDevelopmentSimulator; |
| | | import com.battery.device.simulator.BtsSimulatorStateStore.BtsHistoryRecord; |
| | | import com.battery.device.simulator.BtsSimulatorStateStore.CollectorRealtimeMeasurement; |
| | | import com.battery.device.simulator.DevelopmentCollectorSimulation.CollectorRealtimeSnapshot; |
| | | import com.ruoyi.system.domain.TTest; |
| | | import com.ruoyi.system.domain.TTestBattery; |
| | | import com.ruoyi.system.domain.TTestChannelBinding; |
| | |
| | | private final Map<Long, Instant> lastRawCaptureAt = new java.util.concurrent.ConcurrentHashMap<>(); |
| | | |
| | | @Autowired |
| | | public TestDataReceptionServiceImpl(TTestMapper mapper, ITTestService tests, BtsDevelopmentSimulator simulator, |
| | | public TestDataReceptionServiceImpl(TTestMapper mapper, ITTestService tests, @Nullable BtsDevelopmentSimulator simulator, |
| | | TestWarningExceptionService warningExceptions) |
| | | { |
| | | this.mapper = mapper; |
| | |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public void captureDevelopmentRealtimeSnapshots() |
| | | { |
| | | if (simulator == null) return; |
| | | List<Long> testIds = mapper.selectReceivingTestIds(); |
| | | if (testIds == null) return; |
| | | Date now = new Date(); |
| | |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public void captureDevelopmentCabinetRecords() |
| | | { |
| | | if (simulator == null) return; |
| | | List<Long> testIds = mapper.selectReceivingTestIds(); |
| | | if (testIds == null) return; |
| | | for (Long testId : testIds) |
| | |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public void captureDevelopmentCollectorMeasurements() |
| | | { |
| | | if (simulator == null) return; |
| | | List<Long> testIds = mapper.selectReceivingTestIds(); |
| | | if (testIds == null) return; |
| | | for (Long testId : testIds) |