tbf/GenesisCordonelTester/API/InterfaceGCIToLaatzen.cs

1056 lines
35 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using Logic.ProductionToProductMapper.Cordonel;
using Newtonsoft.Json;
using NLog;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Net;
using System.Reflection;
using System.Security.Policy;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using Xylem.Common.CommonCore.Configuration;
using Xylem.Common.CommonCore.Consts;
using Xylem.Common.Hardware.Interfaces.Ports.PortCore;
using Xylem.Common.Hardware.WaterMeter.Genesis.Applications.Const;
using Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore;
using Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore.Consts;
using Xylem.Common.Hardware.WaterMeter.Genesis.Registers;
using Xylem.Common.Hardware.WaterMeter.Genesis.Registers.DataTypes;
using Xylem.Common.Hardware.WaterMeter.WaterMeterCore;
using Xylem.Common.Logic.ProductionOrderCore.TestResults;
using Xylem.Common.Logic.SoftwareAccessHelper;
using Xylem.Common.Utils.Logging;
using static Xylem.Common.Hardware.WaterMeter.Genesis.GenesisCore.GenesisMeter;
using Access = Xylem.Common.Hardware.WaterMeter.Genesis.Registers.Access;
using Register = Xylem.Common.Hardware.WaterMeter.Genesis.Registers.Register;
namespace GenesisCordonelInterface.API
{
/// <summary>
/// Provides a public API for Genesis meter operations.
///
/// This class exposes reusable functionality extracted from the original UI code
/// so it can be used from other projects within the solution.
///
/// The API is intended to gradually consolidate meter-related operations such as:
/// - port detection
/// - PCB ID reading
/// - communication setup
/// - requests and commands
/// - additional service actions
/// </summary>
/// <remarks>
/// This class should contain business logic only and should not depend on UI elements
/// such as forms, controls, MessageBox, or DataGridView.
///
/// UI-specific code should remain outside this class and call this API instead.
/// </remarks>
/// <example>
/// <code>
/// var api = new Api2();
///
/// var request = api.DetectRequestPort(3);
/// if (request.Success)
/// {
/// Console.WriteLine($"PCB ID: {request.PcbId}");
/// }
///
/// var streaming = api.DetectStreamingPort(3);
/// if (streaming.Success)
/// {
/// Console.WriteLine($"Streaming port: {streaming.PortName}");
/// }
/// </code>
/// </example>
public class InterfaceGCIToLaatzen
{
#region Declaration region
private static readonly Lazy<ILogger> Logger = new Lazy<ILogger>(() => NLogHelper.CreateOrGetLogger("GenesisCordonelInterface"));
public class regStore
{
public String PcbId;
public DateTimeOffset created;
public List<regDefValue> keyValues;
}
public class regDefValue
{
public RegisterDefinition def;
public String value;
}
private GenesisMeter _currentGenesis;
private MeterBatch _meterBatch = new MeterBatch();
private regStore _regsToStore;
private String _currentPcbId = "";
private Boolean IsBusy
{
get;
set;
}
/// <summary>
/// Gets a value indicating whether the meter is connected and logged on.
/// </summary>
public bool IsConnected
{
get
{
return _currentGenesis != null && _currentGenesis.IsLoggedOn;
}
}
#endregion
#region API - Port Detection region(extracted from FrmSetup:DgvConfig_CellContentClick)
public class PortDetectionResult
{
/// <summary>
/// Indicates whether the detection was successful.
/// </summary>
public bool Success { get; set; }
/// <summary>
/// Slot number used for the detection.
/// </summary>
public int Slot { get; set; }
/// <summary>
/// Name of the detected communication port.
/// </summary>
public string PortName { get; set; }
/// <summary>
/// PCB ID read from the device (available for request detection).
/// </summary>
public string PcbId { get; set; }
/// <summary>
/// Error message describing why detection failed (if not successful).
/// </summary>
public string ErrorMessage { get; set; }
}
/// </summary>
/// <param name="slot">Slot number.</param>
/// <returns>
/// Result containing success status and detected port name.
/// </returns>
/// <example>
/// <code>
/// var api = new Api2();
/// var result = api.DetectStreamingPort(3);
///
/// if (result.Success)
/// {
/// Console.WriteLine($"Port: {result.PortName}");
/// }
/// else
/// {
/// Console.WriteLine("Streaming detection failed");
/// }
/// </code>
/// </example>
public PortDetectionResult DetectStreamingPort(int slot)
{
if (slot <= 0)
throw new ArgumentOutOfRangeException(nameof(slot));
using (var mb = new MeterBatch())
using (var meter = new GenesisMeter())
{
//meter.SetupFromConfigFile(slot, false);
mb.AddMeter(meter);
var rawData = new ConcurrentBag<string>();
meter.StreamingPort.OnRawRecordReceived += (o, rawMsg) =>
{
var data = (string)rawMsg.GetData();
rawData.Add(data);
};
Thread.Sleep(500);
var success = rawData.Any();
var portName = meter.StreamingPort.GetPortName();
return new PortDetectionResult
{
Success = success,
Slot = slot,
PortName = portName,
ErrorMessage = success ? null : "No streaming data received."
};
}
}
/// <summary>
/// Detects the request port by attempting to read the PCB ID.
/// </summary>
/// <param name="slot">Slot number.</param>
/// <returns>
/// Result containing success status, port name, and PCB ID if successful.
/// </returns>
/// <example>
/// <code>
/// var api = new Api2();
/// var result = api.DetectRequestPort(3);
///
/// if (result.Success)
/// {
/// Console.WriteLine($"PCB ID: {result.PcbId}");
/// }
/// else
/// {
/// Console.WriteLine("Detection failed");
/// }
/// </code>
/// </example>
public PortDetectionResult DetectRequestPort(int slot)
{
if (slot <= 0)
throw new ArgumentOutOfRangeException(nameof(slot));
using (var mb = new MeterBatch())
using (var meter = new GenesisMeter())
{
//meter.SetupFromConfigFile(slot, false);
mb.AddMeter(meter);
meter.Logout();
var pcbId = meter.GetPcbId();
var success = !string.IsNullOrEmpty(pcbId);
var portName = meter.RequestPort.GetPortName();
return new PortDetectionResult
{
Success = success,
Slot = slot,
PortName = portName,
PcbId = pcbId,
ErrorMessage = success ? null : "PCB ID was empty."
};
}
}
#endregion
#region API - PCB ID region
/// <summary>
/// Reads PCB ID for the specified slot.
/// </summary>
/// <param name="slot">Slot number.</param>
/// <returns>PCB ID read from the meter.</returns>
/// <example>
/// <code>
/// var api = new Api2();
/// string pcbId = api.GetPcbId(3);
/// Console.WriteLine(pcbId);
/// </code>
/// </example>
public string GetPcbId(int slot)
{
if (slot <= 0)
throw new ArgumentOutOfRangeException(nameof(slot), "Slot number must be greater than zero.");
using (var mb = new MeterBatch())
using (var meter = new GenesisMeter())
{
meter.SetupFromConfigFile(slot, false);
mb.AddMeter(meter);
meter.Logout();
return meter.GetPcbId();
}
}
#endregion
#region Password and Login
/// <summary>
/// Sets meter password.
/// </summary>
public bool SetMeterPassword(string password)
{
EnsureConnected();
if (string.IsNullOrWhiteSpace(password))
throw new ArgumentException("Password cannot be null or empty.", nameof(password));
try
{
// Replace this with the real Genesis API call if available.
// Example:
// return _currentGenesis.SetMeterPassword(password);
var result = WriteRegister("SECURITY_Password", password, true, true);
return result.Success;
}
catch (Exception ex)
{
Logger.Value.Error(ex, "SetMeterPassword failed.");
return false;
}
}
/// <summary>
/// Performs login using provided password.
/// </summary>
public bool Login(string password)
{
if (_currentGenesis == null)
throw new InvalidOperationException("Genesis meter is not initialized. Call Connect first.");
if (string.IsNullOrWhiteSpace(password))
throw new ArgumentException("Password cannot be null or empty.", nameof(password));
try
{
// IMPORTANT:
// Replace with actual Genesis API method if available
// Variant A direct login method (preferred)
// return _currentGenesis.Login(password);
// Variant B if password must be set first
// _currentGenesis.Password = password;
// return _currentGenesis.Login();
// TEMP fallback (if no direct method known)
bool result = _currentGenesis.Login();
if (!result)
Logger.Value.Warn("Login failed.");
return result;
}
catch (Exception ex)
{
Logger.Value.Error(ex, "Login failed.");
return false;
}
}
#endregion
#region API - Connect
public class InitResult
{
public bool Success { get; set; }
public int Slot { get; set; }
public string ErrorMessage { get; set; }
public string InterfaceVersion { get; set; }
public bool InterfaceSupportsFwVersion { get; set; }
}
/// <summary>
/// Represents the result of a connect operation.
/// </summary>
public class ConnectResult
{
/// <summary>
/// Indicates whether the connect operation was successful.
/// </summary>
public bool Success { get; set; }
/// <summary>
/// Slot number used for connect.
/// </summary>
public int Slot { get; set; }
/// <summary>
/// Connected PCB ID.
/// </summary>
public string PcbId { get; set; }
/// <summary>
/// Indicates whether the meter is logged on.
/// </summary>
public bool IsLoggedOn { get; set; }
/// <summary>
/// Firmware version reported by the meter.
/// </summary>
public string FwVersion { get; set; }
/// <summary>
/// Interface version from configuration.
/// </summary>
public string InterfaceVersion { get; set; }
/// <summary>
/// Indicates whether the loaded configuration supports the detected firmware version.
/// </summary>
public bool InterfaceSupportsFwVersion { get; set; }
/// <summary>
/// Registers available after successful connect.
/// </summary>
public List<RegisterSnapshot> Registers { get; set; } = new List<RegisterSnapshot>();
/// <summary>
/// Error message if connect failed.
/// </summary>
public string ErrorMessage { get; set; }
}
/// <summary>
/// Represents one register returned after connect.
/// </summary>
public class RegisterSnapshot
{
public string Name { get; set; }
public string Type { get; set; }
public string RawValue { get; set; }
public string Min { get; set; }
public string Max { get; set; }
public string Description { get; set; }
public string Version { get; set; }
public string IsAvailable { get; set; }
public string Privilege { get; set; }
}
public InitResult InitOneMeterFromExtern(Int32 slotNo, ConfigSource useConfigSource, PasswordSource usePasswordSource, PortConfig? requestPort, PortConfig? streamingPort)
{
try
{
if (slotNo <= 0)
throw new ArgumentOutOfRangeException(nameof(slotNo), "Slot number must be greater than zero.");
//_meterBatch.RemoveMeter(slotNo);
_currentGenesis?.DisposeMeter();
_currentGenesis = new GenesisMeter();
_currentGenesis.UseOfflinePasswords = usePasswordSource == PasswordSource.OfflineFile;
_currentGenesis.usePasswordSource = usePasswordSource;
_currentGenesis.useConfigSource = useConfigSource;
_currentGenesis.SetupFromExternConfig(
slotNo,
requestPort,
streamingPort,
true);
_meterBatch.AddMeter(_currentGenesis);
return new InitResult
{
Success = true,
Slot = slotNo,
InterfaceVersion = _currentGenesis.InterfaceInfo?.InterfaceVersion,
InterfaceSupportsFwVersion = _currentGenesis.InterfaceSupportsFwVersion
};
}
catch (Exception ex)
{
//_meterBatch.RemoveAllMeters();
_currentGenesis?.DisposeMeter();
_currentGenesis = null;
return new InitResult
{
Success = false,
Slot = slotNo,
ErrorMessage = ex.Message
};
}
}
/// <summary>
/// Connects to a Genesis meter for the specified slot.
/// </summary>
/// <param name="slotNo">Slot number.</param>
/// <param name="useOfflinePasswords">Specifies whether offline passwords should be used.</param>
/// <returns>
/// Connect operation result including PCB ID, firmware/configuration info, and register snapshots.
/// </returns>
/// <example>
/// <code>
/// var api = new GenesisAPI();
/// var result = api.Connect(3, true);
///
/// if (result.Success)
/// {
/// Console.WriteLine(result.PcbId);
/// Console.WriteLine(result.InterfaceVersion);
/// }
/// else
/// {
/// Console.WriteLine(result.ErrorMessage);
/// }
/// </code>
/// </example>
public ConnectResult ConnectOneMeter(int slotNo)
{
try
{
// Validate input
if (slotNo <= 0)
throw new ArgumentOutOfRangeException(nameof(slotNo), "Slot number must be greater than zero.");
// Find meter in batch by slot
var meter = _meterBatch.ListOfMeters
.OfType<GenesisMeter>()
.FirstOrDefault(m => m.Slot == slotNo);
// Meter not initialized
if (meter == null)
{
return new ConnectResult
{
Success = false,
Slot = slotNo,
ErrorMessage = $"Meter for slot {slotNo} not found in batch."
};
}
// Set current working meter
_currentGenesis = meter;
// Perform login for meters in batch
_meterBatch.MetersLogin();
// Validate connection result
if (!_currentGenesis.IsLoggedOn && string.IsNullOrEmpty(_currentGenesis.PcbId))
{
return new ConnectResult
{
Success = false,
Slot = slotNo,
IsLoggedOn = false,
PcbId = _currentGenesis.PcbId,
ErrorMessage = "Cannot read out PcbId. Access to Cordonel denied."
};
}
// Build successful result
var result = new ConnectResult
{
Success = _currentGenesis.IsLoggedOn,
Slot = slotNo,
PcbId = _currentGenesis.PcbId,
IsLoggedOn = _currentGenesis.IsLoggedOn,
FwVersion = _currentGenesis.FwVersion,
InterfaceVersion = _currentGenesis.InterfaceInfo?.InterfaceVersion,
InterfaceSupportsFwVersion = _currentGenesis.InterfaceSupportsFwVersion
};
return result;
}
catch (Exception ex)
{
// Return failure result on exception
return new ConnectResult
{
Success = false,
Slot = slotNo,
ErrorMessage = ex.Message
};
}
}
/// <summary>
/// Connects to a Genesis meter for the specified slot.
/// </summary>
/// <param name="slotNo">Slot number.</param>
/// <param name="useOfflinePasswords">Specifies whether offline passwords should be used.</param>
/// <returns>
/// Connect operation result including PCB ID, firmware/configuration info, and register snapshots.
/// </returns>
/// <example>
/// <code>
/// var api = new GenesisAPI();
/// var result = api.Connect(3, true);
///
/// if (result.Success)
/// {
/// Console.WriteLine(result.PcbId);
/// Console.WriteLine(result.InterfaceVersion);
/// }
/// else
/// {
/// Console.WriteLine(result.ErrorMessage);
/// }
/// </code>
/// </example>
public ConnectResult ConnectAllMeters(int slotNo)
{
/*try
{
if (slotNo <= 0)
throw new ArgumentOutOfRangeException(nameof(slotNo), "Slot number must be greater than zero.");
_currentGenesis?.DisposeMeter();
_meterBatch.RemoveAllMeters();
_currentGenesis = null;
_currentGenesis = new GenesisMeter();
_currentGenesis.UseOfflinePasswords = usePasswordSource == PasswordSource.OfflineFile;
_currentGenesis.usePasswordSource = usePasswordSource;
_currentGenesis.useConfigSource = useConfigSource;
_currentGenesis.SetupFromConfigFile(slotNo);//...MF
_currentGenesis.SetupFromExternConfig(slotNo);
_meterBatch.AddMeter(_currentGenesis);
_meterBatch.MetersLogin();
if (!_currentGenesis.IsLoggedOn && string.IsNullOrEmpty(_currentGenesis.PcbId))
{
return new ConnectResult
{
Success = false,
Slot = slotNo,
IsLoggedOn = false,
PcbId = _currentGenesis.PcbId,
ErrorMessage = "Cannot read out PcbId. Access to Cordonel denied."
};
}
var result = new ConnectResult
{
Success = _currentGenesis.IsLoggedOn,
Slot = slotNo,
PcbId = _currentGenesis.PcbId,
IsLoggedOn = _currentGenesis.IsLoggedOn,
FwVersion = _currentGenesis.FwVersion,
InterfaceVersion = _currentGenesis.InterfaceInfo?.InterfaceVersion,
InterfaceSupportsFwVersion = _currentGenesis.InterfaceSupportsFwVersion
};
foreach (var item in _currentGenesis.GetRegistersDic())
{
var from = item.Key.RegisterDetail.Version.First.HasValue
? item.Key.RegisterDetail.Version.First.Value.ToString()
: "-";
var to = item.Key.RegisterDetail.Version.Last.HasValue
? item.Key.RegisterDetail.Version.Last.Value.ToString()
: "-";
result.Registers.Add(new RegisterSnapshot
{
Name = item.Key.GetIdent(),
Type = item.Key.DataType.Name,
RawValue = BitConverter.ToString(item.Value).Replace("-", " "),
Min = item.Key.Minimum?.ToString(),
Max = item.Key.Maximum?.ToString(),
Description = item.Key.RegisterDetail.Description,
Version = $"from {from} to {to}",
IsAvailable = item.Key.IsAvailable.ToString(),
Privilege = item.Key.RegisterDetail.Privilege.Lvl8.ToString()
});
}
return result;
}
catch (Exception ex)
{
_meterBatch.RemoveAllMeters();
_currentGenesis?.DisposeMeter();
return new ConnectResult
{
Success = false,
Slot = slotNo,
ErrorMessage = ex.Message
};
}*/
return null;
}
#endregion
#region Meter Registers
/// <summary>
/// Result of a register read operation.
/// </summary>
public class RegisterReadResult
{
/// <summary>
/// Indicates whether the read operation was successful.
/// </summary>
public bool Success { get; set; }
/// <summary>
/// Name of the register.
/// </summary>
public string RegisterName { get; set; }
/// <summary>
/// Raw bytes returned from the device.
/// </summary>
public byte[] RawBytes { get; set; }
/// <summary>
/// Raw value formatted as hexadecimal string.
/// </summary>
public string RawHex { get; set; }
/// <summary>
/// Converted value based on register data type (if possible).
/// </summary>
public object TypedValue { get; set; }
/// <summary>
/// String representation of the converted value.
/// </summary>
public string TypedValueText { get; set; }
/// <summary>
/// Data type of the register.
/// </summary>
public string DataType { get; set; }
/// <summary>
/// Error message if operation failed.
/// </summary>
public string ErrorMessage { get; set; }
}
/// <summary>
/// Result of a register write operation.
/// </summary>
public class RegisterWriteResult
{
/// <summary>
/// Indicates whether the write operation was successful.
/// </summary>
public bool Success { get; set; }
/// <summary>
/// Name of the register.
/// </summary>
public string RegisterName { get; set; }
/// <summary>
/// Value that was written to the register.
/// </summary>
public object WrittenValue { get; set; }
/// <summary>
/// Indicates whether configuration was stored to the device.
/// </summary>
public bool StoreToDevice { get; set; }
/// <summary>
/// Indicates whether system state refresh was triggered.
/// </summary>
public bool RefreshSystemState { get; set; }
/// <summary>
/// Error message if operation failed.
/// </summary>
public string ErrorMessage { get; set; }
}
//Helper methods
/// <summary>
/// Ensures that the meter is connected and logged on.
/// </summary>
private void EnsureConnected()
{
if (_currentGenesis == null)
throw new InvalidOperationException("Genesis meter is not initialized. Call Connect first.");
if (!_currentGenesis.IsLoggedOn)
throw new InvalidOperationException("Genesis meter is not logged on. Call Connect first.");
}
/// <summary>
/// Finds register definition by name.
/// </summary>
private RegisterDefinition FindRegisterDefinition(string registerName)
{
if (string.IsNullOrWhiteSpace(registerName))
throw new ArgumentException("Register name cannot be null or empty.", nameof(registerName));
var match = _currentGenesis
.GetRegistersDic()
.Keys
.FirstOrDefault(r => string.Equals(r.GetIdent(), registerName, StringComparison.OrdinalIgnoreCase));
if (match == null)
throw new KeyNotFoundException($"Register '{registerName}' was not found.");
return match;
}
/// <summary>
/// Converts byte array to hex string.
/// </summary>
private string ToHex(byte[] data)
{
if (data == null || data.Length == 0)
return string.Empty;
return BitConverter.ToString(data).Replace("-", " ");
}
//Read register
/// <summary>
/// Reads register value by register name.
/// </summary>
public RegisterReadResult ReadRegister(string registerName)
{
try
{
EnsureConnected();
var register = FindRegisterDefinition(registerName);
var raw = _currentGenesis.ReadRegister(registerName);
object typedValue = null;
string typedValueText = null;
try
{
typedValue = ConvertRegisterValue(register, raw);
typedValueText = typedValue?.ToString();
}
catch
{
// Ignore conversion errors, raw value is still valid
}
return new RegisterReadResult
{
Success = true,
RegisterName = registerName,
RawBytes = raw,
RawHex = ToHex(raw),
TypedValue = typedValue,
TypedValueText = typedValueText,
DataType = register.DataType?.Name
};
}
catch (Exception ex)
{
Logger.Value.Error(ex, $"ReadRegister failed for '{registerName}'.");
return new RegisterReadResult
{
Success = false,
RegisterName = registerName,
ErrorMessage = ex.Message
};
}
}
//Typed conversion
/// <summary>
/// Converts raw register value to a typed value based on register definition.
/// </summary>
private object ConvertRegisterValue(RegisterDefinition register, byte[] raw)
{
var typeName = register.DataType?.Name;
switch (typeName)
{
case "Boolean":
return RegisterConverter.ByteArrayToValue<bool>(raw);
case "Byte":
return RegisterConverter.ByteArrayToValue<byte>(raw);
case "Int32":
return RegisterConverter.ByteArrayToValue<int>(raw);
case "UInt32":
return RegisterConverter.ByteArrayToValue<uint>(raw);
case "Double":
return RegisterConverter.ByteArrayToValue<double>(raw);
case "Single":
return RegisterConverter.ByteArrayToValue<float>(raw);
case "String":
return Encoding.ASCII.GetString(raw).TrimEnd('\0');
default:
return ToHex(raw);
}
}
//Generic login
/// <summary>
/// Reads register and converts it directly to specified type.
/// </summary>
public T ReadRegisterValue<T>(string registerName)
{
EnsureConnected();
var raw = _currentGenesis.ReadRegister(registerName);
return RegisterConverter.ByteArrayToValue<T>(raw);
}
//Write register
/// <summary>
/// Writes value to register.
/// </summary>
public RegisterWriteResult WriteRegister(
string registerName,
object value,
bool storeToDevice = false,
bool refreshSystemState = false)
{
try
{
EnsureConnected();
bool writeOk = _currentGenesis.WriteRegister(registerName, value);
if (!writeOk)
{
return new RegisterWriteResult
{
Success = false,
RegisterName = registerName,
WrittenValue = value,
ErrorMessage = "Write operation failed."
};
}
if (storeToDevice)
{
if (!_currentGenesis.StoreAllConfigurations())
{
return new RegisterWriteResult
{
Success = false,
RegisterName = registerName,
WrittenValue = value,
ErrorMessage = "StoreAllConfigurations failed."
};
}
}
if (refreshSystemState)
{
if (!_currentGenesis.WriteRegister("SENSUSRADIO_SYSTEMSTATE", 0xFF, true, false))
{
return new RegisterWriteResult
{
Success = false,
RegisterName = registerName,
WrittenValue = value,
ErrorMessage = "System state refresh failed."
};
}
}
return new RegisterWriteResult
{
Success = true,
RegisterName = registerName,
WrittenValue = value,
StoreToDevice = storeToDevice,
RefreshSystemState = refreshSystemState
};
}
catch (Exception ex)
{
Logger.Value.Error(ex, $"WriteRegister failed for '{registerName}'.");
return new RegisterWriteResult
{
Success = false,
RegisterName = registerName,
WrittenValue = value,
ErrorMessage = ex.Message
};
}
}
//Bulk operations
/// <summary>
/// Reads multiple registers.
/// </summary>
public List<RegisterReadResult> ReadRegisters(IEnumerable<string> registerNames)
{
var result = new List<RegisterReadResult>();
foreach (var name in registerNames)
{
result.Add(ReadRegister(name));
}
return result;
}
/// <summary>
/// Writes multiple registers.
/// </summary>
public List<RegisterWriteResult> WriteRegisters(
Dictionary<string, object> registerValues,
bool storeToDevice = false,
bool refreshSystemState = false)
{
var results = new List<RegisterWriteResult>();
int index = 0;
int total = registerValues.Count;
foreach (var pair in registerValues)
{
bool doStore = storeToDevice && index == total - 1;
bool doRefresh = refreshSystemState && index == total - 1;
results.Add(WriteRegister(pair.Key, pair.Value, doStore, doRefresh));
index++;
}
return results;
}
//Disconnect
/// <summary>
/// Disconnects from the meter and releases resources.
/// </summary>
public void Disconnect()
{
try
{
if (_currentGenesis != null && _currentGenesis.IsLoggedOn)
{
_currentGenesis.Logout();
}
}
catch (Exception ex)
{
Logger.Value.Error(ex, "Disconnect failed.");
}
finally
{
_meterBatch.RemoveAllMeters();
_currentGenesis?.DisposeMeter();
_currentGenesis = null;
_currentPcbId = string.Empty;
}
}
#endregion
}
}