package com.ruoyi.system.service.impl;
|
|
import java.math.BigDecimal;
|
import java.time.Instant;
|
import java.util.LinkedHashMap;
|
import java.util.List;
|
import java.util.Map;
|
import org.springframework.dao.DuplicateKeyException;
|
import org.springframework.stereotype.Service;
|
import org.springframework.transaction.annotation.Transactional;
|
import com.ruoyi.device.model.DetectedChannel;
|
import com.ruoyi.device.model.ChannelIdentity;
|
import com.ruoyi.device.model.RealtimeSnapshot;
|
import com.ruoyi.system.domain.TDetectionCabinet;
|
import com.ruoyi.system.domain.TDetectionChannel;
|
import com.ruoyi.system.domain.TDeviceAdapter;
|
import com.ruoyi.system.domain.vo.AdapterDiscoveryResult;
|
import com.ruoyi.system.mapper.TDeviceAdapterMapper;
|
|
@Service
|
public class DeviceDiscoveryPersistenceService
|
{
|
private final TDeviceAdapterMapper mapper;
|
|
public DeviceDiscoveryPersistenceService(TDeviceAdapterMapper mapper)
|
{
|
this.mapper = mapper;
|
}
|
|
/** 在一个事务内 upsert 本轮观测事实;未返回通道保持原记录不变。 */
|
@Transactional(rollbackFor = Exception.class)
|
public AdapterDiscoveryResult persist(TDeviceAdapter adapter, List<DetectedChannel> detected,
|
Map<ChannelIdentity, RealtimeSnapshot> snapshots, Instant observedAt)
|
{
|
Map<CabinetKey, List<DetectedChannel>> cabinets = detected.stream().collect(
|
java.util.stream.Collectors.groupingBy(
|
item -> new CabinetKey(item.identity().devtype(), item.identity().devid()),
|
LinkedHashMap::new, java.util.stream.Collectors.toList()));
|
|
for (Map.Entry<CabinetKey, List<DetectedChannel>> entry : cabinets.entrySet())
|
{
|
Long cabinetId = ensureCabinet(adapter, entry.getKey(), entry.getValue(), observedAt);
|
for (DetectedChannel item : entry.getValue())
|
mapper.upsertDetectedChannel(toChannel(adapter.getAdapterId(), cabinetId, item,
|
snapshots.get(item.identity()), observedAt));
|
}
|
return new AdapterDiscoveryResult(cabinets.size(), detected.size(), observedAt);
|
}
|
|
private Long ensureCabinet(TDeviceAdapter adapter, CabinetKey key, List<DetectedChannel> channels,
|
Instant observedAt)
|
{
|
Long cabinetId = mapper.selectCabinetIdByIdentity(adapter.getAdapterId(), key.devtype(), key.devid());
|
TDetectionCabinet cabinet = new TDetectionCabinet();
|
cabinet.setCabinetId(cabinetId);
|
cabinet.setAdapterId(adapter.getAdapterId());
|
cabinet.setCabinetCode(adapter.getAdapterCode() + "-" + key.devtype() + "-" + key.devid());
|
cabinet.setCabinetName(adapter.getAdapterName() + " " + key.devtype() + "-" + key.devid());
|
cabinet.setCapacity(BigDecimal.ONE);
|
cabinet.setChannelCount(channels.size());
|
cabinet.setVendorDeviceType(key.devtype());
|
cabinet.setVendorDeviceId(key.devid());
|
cabinet.setIpAddress(channels.stream().map(DetectedChannel::serverIp).filter(value -> value != null && !value.isBlank())
|
.findFirst().orElse(null));
|
cabinet.setOnlineStatus(channels.stream().anyMatch(DetectedChannel::available) ? "ONLINE" : "OFFLINE");
|
cabinet.setLastSeenAtUtc(observedAt);
|
if (cabinetId == null)
|
{
|
try
|
{
|
mapper.insertDetectedCabinet(cabinet);
|
return cabinet.getCabinetId();
|
}
|
catch (DuplicateKeyException concurrentInsert)
|
{
|
cabinetId = mapper.selectCabinetIdByIdentity(adapter.getAdapterId(), key.devtype(), key.devid());
|
if (cabinetId == null) throw concurrentInsert;
|
cabinet.setCabinetId(cabinetId);
|
}
|
}
|
mapper.updateDetectedCabinet(cabinet);
|
return cabinetId;
|
}
|
|
private TDetectionChannel toChannel(Long adapterId, Long cabinetId, DetectedChannel detected,
|
RealtimeSnapshot snapshot, Instant observedAt)
|
{
|
TDetectionChannel channel = new TDetectionChannel();
|
channel.setAdapterId(adapterId);
|
channel.setCabinetId(cabinetId);
|
channel.setDevtype(detected.identity().devtype());
|
channel.setDevid(detected.identity().devid());
|
channel.setSubdevid(detected.identity().subdevid());
|
channel.setChlid(detected.identity().chlid());
|
channel.setDisplayNo(detected.identity().subdevid() + "-" + detected.identity().chlid());
|
channel.setOnlineStatus(detected.available() ? "ONLINE" : "OFFLINE");
|
channel.setWorkStatus(snapshot == null || snapshot.workStatus() == null
|
? "UNKNOWN" : snapshot.workStatus().name());
|
channel.setLastSeenAtUtc(observedAt);
|
channel.setStatus("0");
|
return channel;
|
}
|
|
private record CabinetKey(int devtype, int devid)
|
{
|
}
|
}
|