2026-04-23 07:09:27 +00:00
|
|
|
|
using System;
|
|
|
|
|
|
using System.Collections.Generic;
|
2026-04-27 14:40:42 +00:00
|
|
|
|
using System.IO.Ports;
|
2026-04-27 05:57:16 +00:00
|
|
|
|
using System.Threading;
|
|
|
|
|
|
using System.Threading.Tasks;
|
2026-04-23 07:09:27 +00:00
|
|
|
|
|
|
|
|
|
|
namespace GenesisCordonelInterface.API
|
|
|
|
|
|
{
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Outside-facing facade for Genesis Cordonel Interface.
|
|
|
|
|
|
/// Exposes only selected operations intended for external callers.
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public class InterfaceOutsideToGCI
|
|
|
|
|
|
{
|
|
|
|
|
|
private readonly InterfaceGCIToLaatzen _innerMeterAPI;
|
|
|
|
|
|
|
2026-04-27 05:57:16 +00:00
|
|
|
|
public event Action<List<InterfaceGCIToLaatzen.MeterBatchDebugStatus>> MeterBatchStatusChanged;
|
|
|
|
|
|
|
2026-04-23 07:09:27 +00:00
|
|
|
|
public InterfaceOutsideToGCI()
|
|
|
|
|
|
{
|
|
|
|
|
|
_innerMeterAPI = new InterfaceGCIToLaatzen();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-04-27 14:40:42 +00:00
|
|
|
|
#region ================================== PORT DETECTION ==================================
|
2026-04-27 05:57:16 +00:00
|
|
|
|
|
|
|
|
|
|
public InterfaceGCIToLaatzen.PortDetectionResult DetectStreamingPort(int slot)
|
2026-04-23 07:09:27 +00:00
|
|
|
|
{
|
2026-04-27 05:57:16 +00:00
|
|
|
|
var result = _innerMeterAPI.DetectStreamingPort(slot);
|
|
|
|
|
|
RaiseMeterBatchStatusChanged();
|
|
|
|
|
|
return result;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public async Task<InterfaceGCIToLaatzen.PortDetectionResult> DetectStreamingPortAsync(
|
|
|
|
|
|
int slot,
|
|
|
|
|
|
CancellationToken token = default(CancellationToken))
|
|
|
|
|
|
{
|
|
|
|
|
|
var result = await _innerMeterAPI.DetectStreamingPortAsync(slot, token);
|
|
|
|
|
|
RaiseMeterBatchStatusChanged();
|
|
|
|
|
|
return result;
|
2026-04-23 07:09:27 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
2026-04-27 05:57:16 +00:00
|
|
|
|
public InterfaceGCIToLaatzen.PortDetectionResult DetectRequestPort(int slot)
|
2026-04-23 07:09:27 +00:00
|
|
|
|
{
|
2026-04-27 05:57:16 +00:00
|
|
|
|
var result = _innerMeterAPI.DetectRequestPort(slot);
|
|
|
|
|
|
RaiseMeterBatchStatusChanged();
|
|
|
|
|
|
return result;
|
2026-04-23 07:09:27 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
2026-04-27 05:57:16 +00:00
|
|
|
|
public async Task<InterfaceGCIToLaatzen.PortDetectionResult> DetectRequestPortAsync(
|
|
|
|
|
|
int slot,
|
|
|
|
|
|
CancellationToken token = default(CancellationToken))
|
|
|
|
|
|
{
|
|
|
|
|
|
var result = await _innerMeterAPI.DetectRequestPortAsync(slot, token);
|
|
|
|
|
|
RaiseMeterBatchStatusChanged();
|
|
|
|
|
|
return result;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
2026-04-27 14:40:42 +00:00
|
|
|
|
#region ================================== INIT ==================================
|
2026-04-27 05:57:16 +00:00
|
|
|
|
|
2026-04-27 14:40:42 +00:00
|
|
|
|
public async Task<GciPublicModels.GciInitSlotResult> InitSlotAsync(GciPublicModels.GciInitSlotRequest request, CancellationToken token = default)
|
2026-04-27 05:57:16 +00:00
|
|
|
|
{
|
2026-04-27 14:40:42 +00:00
|
|
|
|
if (request == null)
|
|
|
|
|
|
throw new ArgumentNullException(nameof(request));
|
2026-04-27 05:57:16 +00:00
|
|
|
|
|
|
|
|
|
|
var result = await _innerMeterAPI.InitOneMeterFromExternAsync(
|
2026-04-27 14:40:42 +00:00
|
|
|
|
request.SlotId,
|
|
|
|
|
|
GciPublicModels.MapConfigSource(request.ConfigSource),
|
|
|
|
|
|
GciPublicModels.MapPasswordSource(request.PasswordSource),
|
|
|
|
|
|
GciPublicModels.MapPort(request.RequestPort),
|
|
|
|
|
|
GciPublicModels.MapPort(request.StreamingPort),
|
2026-04-27 05:57:16 +00:00
|
|
|
|
token);
|
|
|
|
|
|
|
|
|
|
|
|
RaiseMeterBatchStatusChanged();
|
2026-04-27 14:40:42 +00:00
|
|
|
|
|
2026-04-27 05:57:16 +00:00
|
|
|
|
return result;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-04-27 14:40:42 +00:00
|
|
|
|
public async Task<GciPublicModels.GciSlotInfo> GetSlotAsync(
|
|
|
|
|
|
int slotId,
|
|
|
|
|
|
CancellationToken token = default)
|
2026-04-27 05:57:16 +00:00
|
|
|
|
{
|
2026-04-27 14:40:42 +00:00
|
|
|
|
if (slotId <= 0)
|
|
|
|
|
|
throw new ArgumentException("Invalid slot id.");
|
|
|
|
|
|
|
|
|
|
|
|
var result = await _innerMeterAPI.GetOneMeterInfo(slotId, token);
|
|
|
|
|
|
|
|
|
|
|
|
return result;
|
2026-04-27 05:57:16 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
2026-04-27 14:40:42 +00:00
|
|
|
|
public async Task<GciPublicModels.GciCleanSlotsResult> CleanSlotsAsync(
|
|
|
|
|
|
CancellationToken token = default)
|
2026-04-27 05:57:16 +00:00
|
|
|
|
{
|
2026-04-27 14:40:42 +00:00
|
|
|
|
var result = await _innerMeterAPI.CleanSlotsAsync(token);
|
2026-04-27 05:57:16 +00:00
|
|
|
|
|
2026-04-27 14:40:42 +00:00
|
|
|
|
RaiseMeterBatchStatusChanged();
|
|
|
|
|
|
|
|
|
|
|
|
return result;
|
|
|
|
|
|
}
|
2026-04-27 05:57:16 +00:00
|
|
|
|
#endregion
|
|
|
|
|
|
|
2026-04-27 14:40:42 +00:00
|
|
|
|
#region ================================== CONNECTION ==================================
|
2026-04-27 05:57:16 +00:00
|
|
|
|
|
2026-04-27 14:40:42 +00:00
|
|
|
|
public async Task<GciPublicModels.GciConnectResult> ConnectOneSlotAsync(
|
|
|
|
|
|
int slot,
|
|
|
|
|
|
CancellationToken token = default)
|
2026-04-23 07:09:27 +00:00
|
|
|
|
{
|
2026-04-27 14:40:42 +00:00
|
|
|
|
GciPublicModels.GciConnectResult result = await _innerMeterAPI.ConnectOneSlotAsync(slot, token);
|
|
|
|
|
|
|
2026-04-27 05:57:16 +00:00
|
|
|
|
RaiseMeterBatchStatusChanged();
|
2026-04-27 14:40:42 +00:00
|
|
|
|
|
2026-04-27 05:57:16 +00:00
|
|
|
|
return result;
|
2026-04-23 07:09:27 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
2026-04-27 14:40:42 +00:00
|
|
|
|
public async Task<GciPublicModels.GciDisconnectResult> DisconnectAsync(
|
|
|
|
|
|
int slot,
|
|
|
|
|
|
CancellationToken token = default)
|
2026-04-23 07:09:27 +00:00
|
|
|
|
{
|
2026-04-27 14:40:42 +00:00
|
|
|
|
if (slot <= 0)
|
|
|
|
|
|
throw new ArgumentException("Invalid slot id.");
|
|
|
|
|
|
|
|
|
|
|
|
var result = await _innerMeterAPI.DisconnectAsync(slot, token);
|
|
|
|
|
|
|
2026-04-27 05:57:16 +00:00
|
|
|
|
RaiseMeterBatchStatusChanged();
|
2026-04-27 14:40:42 +00:00
|
|
|
|
|
2026-04-27 05:57:16 +00:00
|
|
|
|
return result;
|
2026-04-23 07:09:27 +00:00
|
|
|
|
}
|
2026-04-27 14:40:42 +00:00
|
|
|
|
#endregion
|
2026-04-23 07:09:27 +00:00
|
|
|
|
|
2026-04-27 14:40:42 +00:00
|
|
|
|
#region ================================== PCB ==================================
|
|
|
|
|
|
public async Task<GciPublicModels.GciGetPcbIdResult> GetPcbIdAsync(
|
|
|
|
|
|
int slot,
|
|
|
|
|
|
CancellationToken token = default)
|
2026-04-23 07:09:27 +00:00
|
|
|
|
{
|
2026-04-27 14:40:42 +00:00
|
|
|
|
if (slot <= 0)
|
|
|
|
|
|
throw new ArgumentException("Invalid slot id.");
|
2026-04-23 07:09:27 +00:00
|
|
|
|
|
2026-04-27 14:40:42 +00:00
|
|
|
|
var result = await _innerMeterAPI.GetPcbIdAsync(slot, token);
|
2026-04-27 05:57:16 +00:00
|
|
|
|
|
2026-04-27 14:40:42 +00:00
|
|
|
|
return result;
|
|
|
|
|
|
}
|
2026-04-27 05:57:16 +00:00
|
|
|
|
#endregion
|
|
|
|
|
|
|
2026-04-27 14:40:42 +00:00
|
|
|
|
#region ================================== READ ==================================
|
2026-04-27 05:57:16 +00:00
|
|
|
|
// ----------------------------------------------------
|
|
|
|
|
|
|
|
|
|
|
|
public InterfaceGCIToLaatzen.RegisterReadResult ReadRegister(
|
|
|
|
|
|
int slot,
|
|
|
|
|
|
string registerName)
|
|
|
|
|
|
{
|
|
|
|
|
|
return _innerMeterAPI.ReadRegister(slot, registerName);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public Task<InterfaceGCIToLaatzen.RegisterReadResult> ReadRegisterAsync(
|
|
|
|
|
|
int slot,
|
|
|
|
|
|
string registerName,
|
|
|
|
|
|
CancellationToken token = default(CancellationToken))
|
|
|
|
|
|
{
|
|
|
|
|
|
return _innerMeterAPI.ReadRegisterAsync(slot, registerName, token);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// ----------------------------------------------------
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
2026-04-27 14:40:42 +00:00
|
|
|
|
#region ================================== WRITE ==================================
|
2026-04-27 05:57:16 +00:00
|
|
|
|
// ----------------------------------------------------
|
|
|
|
|
|
|
|
|
|
|
|
public async Task<InterfaceGCIToLaatzen.RegisterWriteResult> WriteRegisterAsync(
|
|
|
|
|
|
int slot,
|
|
|
|
|
|
string registerName,
|
|
|
|
|
|
object value,
|
|
|
|
|
|
bool storeToDevice = false,
|
|
|
|
|
|
bool refreshSystemState = false)
|
2026-04-23 07:09:27 +00:00
|
|
|
|
{
|
2026-04-27 05:57:16 +00:00
|
|
|
|
var result = await _innerMeterAPI.WriteRegisterAsync(
|
|
|
|
|
|
slot,
|
|
|
|
|
|
registerName,
|
|
|
|
|
|
value,
|
|
|
|
|
|
storeToDevice,
|
|
|
|
|
|
refreshSystemState);
|
|
|
|
|
|
|
|
|
|
|
|
RaiseMeterBatchStatusChanged();
|
|
|
|
|
|
return result;
|
2026-04-23 07:09:27 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public InterfaceGCIToLaatzen.RegisterWriteResult WriteRegister(
|
2026-04-27 05:57:16 +00:00
|
|
|
|
int slot,
|
2026-04-23 07:09:27 +00:00
|
|
|
|
string registerName,
|
|
|
|
|
|
object value,
|
|
|
|
|
|
bool storeToDevice = false,
|
|
|
|
|
|
bool refreshSystemState = false)
|
|
|
|
|
|
{
|
2026-04-27 05:57:16 +00:00
|
|
|
|
var result = _innerMeterAPI.WriteRegister(
|
|
|
|
|
|
slot,
|
|
|
|
|
|
registerName,
|
|
|
|
|
|
value,
|
|
|
|
|
|
storeToDevice,
|
|
|
|
|
|
refreshSystemState);
|
|
|
|
|
|
|
|
|
|
|
|
RaiseMeterBatchStatusChanged();
|
|
|
|
|
|
return result;
|
2026-04-23 07:09:27 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
2026-04-27 05:57:16 +00:00
|
|
|
|
public async Task<bool> SetMeterPasswordAsync(int slot, string password)
|
2026-04-23 07:09:27 +00:00
|
|
|
|
{
|
2026-04-27 05:57:16 +00:00
|
|
|
|
var result = await _innerMeterAPI.SetMeterPasswordAsync(slot, password);
|
|
|
|
|
|
RaiseMeterBatchStatusChanged();
|
|
|
|
|
|
return result;
|
2026-04-23 07:09:27 +00:00
|
|
|
|
}
|
2026-04-27 05:57:16 +00:00
|
|
|
|
|
|
|
|
|
|
public bool SetMeterPassword(int slot, string password)
|
|
|
|
|
|
{
|
|
|
|
|
|
var result = _innerMeterAPI.SetMeterPassword(slot, password);
|
|
|
|
|
|
RaiseMeterBatchStatusChanged();
|
|
|
|
|
|
return result;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// ----------------------------------------------------
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
2026-04-27 14:40:42 +00:00
|
|
|
|
#region ================================== DEBUG STATUS ==================================
|
2026-04-27 05:57:16 +00:00
|
|
|
|
// ----------------------------------------------------
|
|
|
|
|
|
|
|
|
|
|
|
public List<InterfaceGCIToLaatzen.WorkerDebugStatus> GetWorkerDebugStatuses()
|
|
|
|
|
|
{
|
|
|
|
|
|
return _innerMeterAPI.GetWorkerDebugStatuses();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public List<InterfaceGCIToLaatzen.MeterBatchDebugStatus> GetMeterBatchDebugStatuses()
|
|
|
|
|
|
{
|
|
|
|
|
|
return _innerMeterAPI.GetMeterBatchDebugStatuses();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public void RaiseMeterBatchStatusChanged()
|
|
|
|
|
|
{
|
|
|
|
|
|
var statuses = GetMeterBatchDebugStatuses();
|
|
|
|
|
|
|
|
|
|
|
|
var handler = MeterBatchStatusChanged;
|
|
|
|
|
|
if (handler != null)
|
|
|
|
|
|
handler(statuses);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// ----------------------------------------------------
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
2026-04-27 14:40:42 +00:00
|
|
|
|
#region ================================== SLOT SELECTION ==================================
|
2026-04-27 05:57:16 +00:00
|
|
|
|
// ----------------------------------------------------
|
|
|
|
|
|
|
|
|
|
|
|
public void SetSlotSelected(int slot, bool selected)
|
|
|
|
|
|
{
|
|
|
|
|
|
_innerMeterAPI.SetSlotSelected(slot, selected);
|
|
|
|
|
|
RaiseMeterBatchStatusChanged();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public bool IsSlotSelected(int slot)
|
|
|
|
|
|
{
|
|
|
|
|
|
return _innerMeterAPI.IsSlotSelected(slot);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public List<int> GetSelectedSlots()
|
|
|
|
|
|
{
|
|
|
|
|
|
return _innerMeterAPI.GetSelectedSlots();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// ----------------------------------------------------
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
2026-04-27 14:40:42 +00:00
|
|
|
|
#region ================================== SLOT PORT CONFIG ==================================
|
2026-04-27 05:57:16 +00:00
|
|
|
|
// ----------------------------------------------------
|
|
|
|
|
|
|
2026-04-27 14:40:42 +00:00
|
|
|
|
/*public void SetSlotRequestPort(int slot, string portName)
|
2026-04-27 05:57:16 +00:00
|
|
|
|
{
|
|
|
|
|
|
lock (_portLock)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (string.IsNullOrWhiteSpace(portName))
|
|
|
|
|
|
{
|
|
|
|
|
|
_requestPorts.Remove(slot);
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
2026-04-27 14:40:42 +00:00
|
|
|
|
_requestPorts[slot] = new GciPortConfig
|
2026-04-27 05:57:16 +00:00
|
|
|
|
{
|
|
|
|
|
|
PortName = portName,
|
|
|
|
|
|
Type = "Serial"
|
|
|
|
|
|
};
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
RaiseMeterBatchStatusChanged();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public void SetSlotStreamingPort(int slot, string portName)
|
|
|
|
|
|
{
|
|
|
|
|
|
lock (_portLock)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (string.IsNullOrWhiteSpace(portName))
|
|
|
|
|
|
{
|
|
|
|
|
|
_streamingPorts.Remove(slot);
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
2026-04-27 14:40:42 +00:00
|
|
|
|
_streamingPorts[slot] = new GciPortConfig
|
2026-04-27 05:57:16 +00:00
|
|
|
|
{
|
|
|
|
|
|
PortName = portName,
|
|
|
|
|
|
Type = "Serial"
|
|
|
|
|
|
};
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
RaiseMeterBatchStatusChanged();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-04-27 14:40:42 +00:00
|
|
|
|
public GciPortConfig? GetSlotRequestPort(int slot)
|
2026-04-27 05:57:16 +00:00
|
|
|
|
{
|
|
|
|
|
|
lock (_portLock)
|
|
|
|
|
|
{
|
2026-04-27 14:40:42 +00:00
|
|
|
|
GciPortConfig port;
|
2026-04-27 05:57:16 +00:00
|
|
|
|
if (_requestPorts.TryGetValue(slot, out port))
|
|
|
|
|
|
return port;
|
|
|
|
|
|
|
|
|
|
|
|
return null;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-04-27 14:40:42 +00:00
|
|
|
|
public GciPortConfig? GetSlotStreamingPort(int slot)
|
2026-04-27 05:57:16 +00:00
|
|
|
|
{
|
|
|
|
|
|
lock (_portLock)
|
|
|
|
|
|
{
|
2026-04-27 14:40:42 +00:00
|
|
|
|
GciPortConfig port;
|
2026-04-27 05:57:16 +00:00
|
|
|
|
if (_streamingPorts.TryGetValue(slot, out port))
|
|
|
|
|
|
return port;
|
|
|
|
|
|
|
|
|
|
|
|
return null;
|
|
|
|
|
|
}
|
2026-04-27 14:40:42 +00:00
|
|
|
|
}*/
|
2026-04-27 05:57:16 +00:00
|
|
|
|
|
|
|
|
|
|
// ----------------------------------------------------
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
2026-04-27 14:40:42 +00:00
|
|
|
|
#region ================================== METER BATCH SETUP ==================================
|
2026-04-27 05:57:16 +00:00
|
|
|
|
// ----------------------------------------------------
|
|
|
|
|
|
|
|
|
|
|
|
public void ReloadSlotSetup()
|
|
|
|
|
|
{
|
|
|
|
|
|
_innerMeterAPI.ReloadSlotSetup();
|
|
|
|
|
|
RaiseMeterBatchStatusChanged();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public void SaveSlotSetup(List<InterfaceGCIToLaatzen.MeterBatchDebugStatus> data)
|
|
|
|
|
|
{
|
|
|
|
|
|
_innerMeterAPI.SaveSlotSetup(data);
|
|
|
|
|
|
RaiseMeterBatchStatusChanged();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// ----------------------------------------------------
|
|
|
|
|
|
#endregion
|
2026-04-23 07:09:27 +00:00
|
|
|
|
}
|
|
|
|
|
|
}
|