package com.battery.device.api.discovery;
|
|
import java.time.Instant;
|
import java.util.List;
|
import java.util.Optional;
|
import com.battery.device.api.model.ChannelIdentity;
|
import com.battery.device.api.model.DeviceWorkStatus;
|
import com.battery.device.api.model.RealtimeSnapshot;
|
|
/** 保存未登记发现候选和正式设备的实时观测快照。 */
|
public interface DeviceDiscoveryCandidateStore
|
{
|
/** upsert 本轮检测柜观测,未返回设备保留到逻辑过期。 */
|
void recordCabinets(List<CabinetCandidate> candidates);
|
|
/** 替换指定适配器的采集器观测,使已删除模拟采集器立即消失。 */
|
void replaceCollectors(String adapterCode, List<CollectorCandidate> candidates);
|
|
/** 删除指定适配器的全部发现候选;仅供人工重置或实机联调清理。 */
|
void removeAdapter(String adapterCode);
|
|
/** 返回指定时刻尚未过期的候选和实时状态。 */
|
CandidateSnapshot snapshot(Instant now);
|
|
/** 按设备编码查询指定时刻未过期的检测柜观测;在线和登记状态由业务层校验。 */
|
default Optional<CabinetCandidate> findCabinet(String deviceCode, Instant now)
|
{
|
return snapshot(now).cabinets().stream().filter(item -> item.deviceCode().equals(deviceCode)).findFirst();
|
}
|
|
/** 按设备编码查询指定时刻未过期的采集器观测;在线和登记状态由业务层校验。 */
|
default Optional<CollectorCandidate> findCollector(String deviceCode, Instant now)
|
{
|
return snapshot(now).collectors().stream().filter(item -> item.deviceCode().equals(deviceCode)).findFirst();
|
}
|
|
record CandidateSnapshot(List<CabinetCandidate> cabinets, List<CollectorCandidate> collectors)
|
{
|
public CandidateSnapshot
|
{
|
cabinets = List.copyOf(cabinets);
|
collectors = List.copyOf(collectors);
|
}
|
}
|
|
/**
|
* 未登记的候选设备。{@code lastDataAt} 取该设备各通道最近的采样行时间,
|
* 供操作员判断哪几台设备现在真的在产出数据;它不改变候选的取舍,登记范围由操作员决定。
|
*/
|
record CabinetCandidate(String adapterCode, Long adapterId, String deviceCode, int devtype, int devid,
|
String ip, String mac, String name, String manufacturer, String model,
|
List<ChannelCandidate> channels, Instant observedAt, Instant expiresAt, Instant lastDataAt)
|
{
|
public CabinetCandidate { channels = List.copyOf(channels); }
|
public boolean online() { return channels.stream().anyMatch(ChannelCandidate::online); }
|
|
/** 兼容不含最近数据时间的既有候选。 */
|
public CabinetCandidate(String adapterCode, Long adapterId, String deviceCode, int devtype, int devid,
|
String ip, String mac, String name, String manufacturer, String model,
|
List<ChannelCandidate> channels, Instant observedAt, Instant expiresAt)
|
{
|
this(adapterCode, adapterId, deviceCode, devtype, devid, ip, mac, name, manufacturer, model,
|
channels, observedAt, expiresAt, null);
|
}
|
}
|
|
/** 通道候选;{@code lastDataAt} 是该通道来源里最近一次采样行的设备时间。 */
|
record ChannelCandidate(ChannelIdentity identity, boolean online, DeviceWorkStatus workStatus,
|
Instant observedAt, RealtimeSnapshot latestSnapshot, Instant lastDataAt)
|
{
|
/** 兼容仅有状态的旧发现候选。 */
|
public ChannelCandidate(ChannelIdentity identity, boolean online, DeviceWorkStatus workStatus,
|
Instant observedAt)
|
{
|
this(identity, online, workStatus, observedAt, null, null);
|
}
|
|
/** 兼容不含最近数据时间的既有候选。 */
|
public ChannelCandidate(ChannelIdentity identity, boolean online, DeviceWorkStatus workStatus,
|
Instant observedAt, RealtimeSnapshot latestSnapshot)
|
{
|
this(identity, online, workStatus, observedAt, latestSnapshot, null);
|
}
|
}
|
|
record CollectorCandidate(String adapterCode, String deviceCode, String ip, String mac, String name,
|
String manufacturer, String model, int channelCount, boolean online,
|
Instant observedAt, Instant expiresAt) { }
|
}
|