tbf/TBF/Rig/TestMethods/iPerlCommunication/communication/RadioService.cs
Michal Buzik 55d2381e8a Mexico - read additional parameters and store to DB, ver. 3.9.3135.0
Add support for reading and handling additional common parameters in OptoHeadTest. Extend RadioService and related classes with enhanced parsing and validation logic. Update UI and constants for functionality integration.
2026-08-12 16:20:16 +02:00

593 lines
19 KiB
C#

using System;
using System.Text;
using log4net;
using TBF.Rig.TestMethods.iPerlCommunication.communication.C4.diagnosticLed;
using TBF.Rig.TestMethods.iPerlCommunication.communication.C4.IperlHatProtocol;
using TBF.Rig.TestMethods.iPerlCommunication.communication.C4.protocolCommons;
using TBF.Rig.TestMethods.iPerlCommunication.communication.C4.wiredProtocol;
using TBF.Rig.TestMethods.iPerlCommunication.communication.Utils;
using TBF.Rig.TestMethods.iPerlCommunication.iPerlHead;
namespace TBF.Rig.TestMethods.iPerlCommunication.communication
{
public class RadioService
{
private static readonly ILog log = LogManager.GetLogger(typeof(RadioService));
static string okResponse = "Command complete, no errors";
static string errorResponse = "Unable to execute";
private ISerialDriver serialDriver;
public RadioService(SerialDriver serialDriver)
{
this.serialDriver = serialDriver;
log.Debug("RadioService created with serialDriver= " + serialDriver + "");
}
public RadioService(ISerialDriver serialDriver)
{
this.serialDriver = serialDriver;
log.Debug("RadioService created with serialDriver= " + serialDriver + "");
}
public string ReadRequest_PCB(ref IperlHead iHead)
{
if (!serialDriver.IsOpen())
{
serialDriver.Open();
}
var request = new IperlHatFrameBuilder()
.RequestResponse(true)
.AddCommand(ProtocolCommand.ViewFactoryId)
.BuildBytes();
byte[] rawData = serialDriver.SendAndWait(request, 10000);
if (rawData == null)
return null;
// parse rawData
var parser = new IperlHatFrameParser();
IperlHatResponse decoded = parser.Parse(rawData);
if (decoded.IsOk)
{
string asciiPayload = decoded.GetAsciiPayload();
if (iHead.ConfigStruct != null) // store mechanism
{
iHead.ConfigStruct.PCBNumberString = asciiPayload;
}
return asciiPayload;
}
return null;
}
public ProtocolStatuses GetActivityStatusMode(IperlHead iHead)
{
if (!serialDriver.IsOpen())
serialDriver.Open();
var request = new IperlHatFrameBuilder()
.RequestResponse(true)
.AddCommand(ProtocolCommand.ViewState)
.BuildBytes();
byte[] rawData = serialDriver.SendAndWait(request, 10000);
if (rawData == null)
return ProtocolStatuses.Unknown;
var parser = new IperlHatFrameParser();
IperlHatResponse decoded = parser.Parse(rawData);
if (!decoded.IsOk)
return ProtocolStatuses.Unknown;
ProtocolStatuses statusMode = decoded.GetResponse<ProtocolStatuses>(out bool isOK);
if (!isOK)
return ProtocolStatuses.Unknown; // wrong payload
return statusMode;
}
public DiagnosticLedState SetOptoStatusMode(IperlHead iHead, DiagnosticLedState opthoStatusMode)
{
if (!serialDriver.IsOpen())
serialDriver.Open();
var request = new IperlHatFrameBuilder()
.RequestResponse(true)
.AddDeviceCommand(ProtocolDeviceSubCommand.SetDiagnosticLEDState)
.AddPayload(opthoStatusMode)
.BuildBytes();
byte[] rawData = serialDriver.SendAndWait(request, 10000);
if (rawData == null)
return DiagnosticLedState.StatusUnknown;
var parser = new IperlHatFrameParser();
IperlHatResponse decoded = parser.Parse(rawData);
log.Debug("SetOptoStatusMode isOK: " + decoded.IsOk);
// if is response ok - it set it correctly
if (!decoded.IsOk)
return DiagnosticLedState.StatusUnknown;
return opthoStatusMode;
}
private static ushort SafeIntToUShort(int value)
{
if (value < ushort.MinValue || value > ushort.MaxValue)
return 0xFD; // your error code
return (ushort)value;
}
public string GetVersion(IperlHead iHead)
{
if (!serialDriver.IsOpen())
{
serialDriver.Open();
}
byte[] request = new IperlHatFrameBuilder()
.RequestResponse(true)
.AddCommand(ProtocolCommand.Question)
.AddPayload(IperlHatProtocolConstants.Version)
.BuildBytes();
byte[] rawData = serialDriver.SendAndWait(request, 10000);
if (rawData == null)
return "";
// parse rawData
var parser = new IperlHatFrameParser();
IperlHatResponse decoded = parser.Parse(rawData);
log.Debug("GetVersion isOK: " + decoded.IsOk);
if (decoded.IsOk)
{
return decoded.GetAsciiPayload();
}
return "";
}
public VersionTypeResult SetViewVersionAndType(IperlHead iHead)
{
if (!serialDriver.IsOpen())
{
serialDriver.Open();
}
byte[] request = new IperlHatFrameBuilder()
.RequestResponse(true)
.AddCommand(ProtocolCommand.ViewVersionAndType)
.BuildBytes();
byte[] rawData = serialDriver.SendAndWait(request, 5000);
if (rawData == null || rawData.Length == 0)
{
log.Warn("SetViewVersionAndType: No response received.");
return null;
}
try
{
var parser = new IperlHatFrameParser();
IperlHatResponse decoded = parser.Parse(rawData);
log.Debug("SetViewVersionAndType isOK: " + decoded.IsOk);
if (!decoded.IsOk)
{
log.Warn("SetViewVersionAndType: Device returned NOK response.");
return null;
}
if (decoded.Payload == null || decoded.Payload.Length == 0)
{
log.Warn("SetViewVersionAndType: Response payload is empty.");
return null;
}
string payloadText = Encoding.ASCII
.GetString(decoded.Payload)
.Trim('\0', '\r', '\n', ' ');
log.Debug("SetViewVersionAndType payload: " + payloadText);
VersionTypeResult result = VersionTypeResult.ParseVersionTypePayload(payloadText);
if (result == null)
{
log.Warn(
"SetViewVersionAndType: Unable to parse response payload: " +
payloadText);
return null;
}
log.Debug("SetViewVersionAndType result: " + result);
return result;
}
catch (FormatException ex)
{
log.Error("SetViewVersionAndType: Invalid response frame.", ex);
return null;
}
catch (Exception ex)
{
log.Error("SetViewVersionAndType failed.", ex);
return null;
}
}
public ReadingUnits? ViewReadingUnits(IperlHead iHead)
{
if (!serialDriver.IsOpen())
{
serialDriver.Open();
}
byte[] request = new IperlHatFrameBuilder()
.RequestResponse(true)
.AddCommand(ProtocolCommand.ViewReadingUnits)
.BuildBytes();
byte[] rawData = serialDriver.SendAndWait(request, 5000);
if (rawData == null || rawData.Length == 0)
{
log.Warn("ViewReadingUnits: No response received.");
return null;
}
try
{
var parser = new IperlHatFrameParser();
IperlHatResponse decoded = parser.Parse(rawData);
log.Debug("ViewReadingUnits isOK: " + decoded.IsOk);
if (!decoded.IsOk)
{
log.Warn("ViewReadingUnits: Device returned NOK response.");
return null;
}
ReadingUnits readingUnits =
decoded.GetResponse<ReadingUnits>(out bool responseOk);
if (!responseOk)
{
string payload = BitConverter.ToString(decoded.Payload);
log.Warn(
"ViewReadingUnits: Invalid response payload. Payload=" +
payload);
return null;
}
log.Debug(
$"ViewReadingUnits: {readingUnits} " +
$"(0x{Convert.ToByte(readingUnits):X2})");
return readingUnits;
}
catch (FormatException ex)
{
log.Error("ViewReadingUnits: Invalid response frame.", ex);
return null;
}
catch (Exception ex)
{
log.Error("ViewReadingUnits failed.", ex);
return null;
}
}
public FlipMode? ViewFlipMode(IperlHead iHead)
{
if (!serialDriver.IsOpen())
{
serialDriver.Open();
}
byte[] request = new IperlHatFrameBuilder()
.RequestResponse(true)
.AddDeviceCommand(ProtocolDeviceSubCommand.ViewFlipMode)
.BuildBytes();
byte[] rawData = serialDriver.SendAndWait(request, 5000);
if (rawData == null || rawData.Length == 0)
{
log.Warn( "ViewFlipMode: No response received.");
return null;
}
try
{
var parser = new IperlHatFrameParser();
IperlHatResponse decoded = parser.Parse(rawData);
log.Debug( "ViewFlipMode isOK: " + decoded.IsOk);
if (!decoded.IsOk)
{
log.Warn( "ViewFlipMode: Device returned NOK response.");
return null;
}
if (decoded.Payload == null || decoded.Payload.Length != 1)
{
log.Warn( "ViewFlipMode: Invalid payload. Expected exactly one byte. Payload="
+ BitConverter.ToString( decoded.Payload ?? new byte[0]));
return null;
}
byte rawValue = decoded.Payload[0];
if (!Enum.IsDefined( typeof(FlipMode), rawValue))
{
log.Warn( $"ViewFlipMode: Unknown value. Value=0x{rawValue:X2}");
return null;
}
FlipMode flipMode = (FlipMode)rawValue;
log.Debug( $"ViewFlipMode: {flipMode} " + $"(0x{rawValue:X2})");
return flipMode;
}
catch (FormatException ex)
{
log.Error( "ViewFlipMode: Invalid response frame.", ex);
return null;
}
catch (Exception ex)
{
log.Error( "ViewFlipMode failed.", ex);
return null;
}
}
public CalibrationFactorResult ViewCalibration( IperlHead iHead)
{
if (!serialDriver.IsOpen())
{
serialDriver.Open();
}
byte[] request = new IperlHatFrameBuilder()
.RequestResponse(true)
.AddDeviceCommand( ProtocolDeviceSubCommand.ViewCalibration)
.BuildBytes();
byte[] rawData = serialDriver.SendAndWait(request, 5000);
if (rawData == null || rawData.Length == 0)
{
log.Warn( "ViewCalibration: No response received.");
return null;
}
try
{
var parser = new IperlHatFrameParser();
IperlHatResponse decoded = parser.Parse(rawData);
log.Debug( "ViewCalibration isOK: " + decoded.IsOk);
if (!decoded.IsOk)
{
log.Warn( "ViewCalibration: Device returned NOK response.");
return null;
}
if (decoded.Payload == null || decoded.Payload.Length != 2)
{
log.Warn( "ViewCalibration: Invalid payload. Expected two-byte little-endian value. Payload=" +
BitConverter.ToString( decoded.Payload ?? new byte[0]));
return null;
}
ushort calibrationFactor = (ushort)( decoded.Payload[0] | (decoded.Payload[1] << 8));
double percentage = calibrationFactor * 100.0 / 4096.0;
var result = new CalibrationFactorResult
{
RawValue = calibrationFactor,
Percentage = percentage,
CorrectionPercentage = percentage - 100.0
};
log.Debug( "ViewCalibration result: " + result);
return result;
}
catch (FormatException ex)
{
log.Error( "ViewCalibration: Invalid response frame.", ex);
return null;
}
catch (Exception ex)
{
log.Error("ViewCalibration failed.", ex);
return null;
}
}
// ----------------------
public bool SetActivityMode_Active(IperlHead iHead)
{
if (!serialDriver.IsOpen())
{
serialDriver.Open();
}
//Set State to Active 02
byte[] request = new IperlHatFrameBuilder()
.RequestResponse(true)
.AddCommand(ProtocolCommand.SetState)
.AddSubCommand(ProtocolStatuses.Active) // Active
.BuildBytes();
byte[] rawData = serialDriver.SendAndWait(request, 5000);
if (rawData == null)
return false;
// parse rawData
var parser = new IperlHatFrameParser();
IperlHatResponse decoded = parser.Parse(rawData);
log.Debug("SetActivityMode_Active isOK: " + decoded.IsOk);
if (decoded.IsOk && iHead.ConfigStruct != null)
{
iHead.ConfigStruct.StatusMode = ProtocolStatuses.Active;
}
return decoded.IsOk;
}
public bool SetActivityMode_Idle(IperlHead iHead)
{
if (!serialDriver.IsOpen())
{
serialDriver.Open();
}
//Set Activity State Idle 01
byte[] request = new IperlHatFrameBuilder()
.RequestResponse(true)
.AddCommand(ProtocolCommand.SetState)
.AddSubCommand(ProtocolStatuses.Idle)
.BuildBytes();
byte[] rawData = serialDriver.SendAndWait(request, 5000);
if (rawData == null)
return false;
// parse rawData
var parser = new IperlHatFrameParser();
IperlHatResponse decoded = parser.Parse(rawData);
log.Debug("SetActivityMode_Idle isOK: " + decoded.IsOk);
if (decoded.IsOk && iHead.ConfigStruct != null)
{
iHead.ConfigStruct.StatusMode = ProtocolStatuses.Idle;
}
return decoded.IsOk;
}
public bool SetOptTestMode(IperlHead iHead)
{
if (!serialDriver.IsOpen())
{
serialDriver.Open();
}
//Set LED to state 7
var request = new IperlHatFrameBuilder()
.RequestResponse(true)
.AddDeviceCommand(ProtocolDeviceSubCommand.SetDiagnosticLEDState)
.AddPayload(DiagnosticLedState.State7)
.BuildBytes();
byte[] rawData = serialDriver.SendAndWait(request, 5000);
if (rawData == null)
return false;
// parse rawData
var parser = new IperlHatFrameParser();
IperlHatResponse decoded = parser.Parse(rawData);
bool isOk = decoded.IsOk;
log.Debug("SetOptTestMode isOK: " + isOk);
if (decoded.IsOk && iHead.ConfigStruct != null)
{
iHead.ConfigStruct.OpthoStatusMode = DiagnosticLedState.State7;
}
return isOk;
}
/// <summary>
/// stop data streaming by LED
/// </summary>
/// <param name="iHead"></param>
/// <returns></returns>
public bool SetOptActiveMode(IperlHead iHead)
{
if (!serialDriver.IsOpen())
{
serialDriver.Open();
}
//Set LED to state 1
var request = new IperlHatFrameBuilder()
.RequestResponse(true)
.AddDeviceCommand(ProtocolDeviceSubCommand.SetDiagnosticLEDState)
.AddPayload(DiagnosticLedState.StateOFF)
.BuildBytes();
byte[] rawData = serialDriver.SendAndWait(request, 5000);
if (rawData == null)
return false;
// parse rawData
var parser = new IperlHatFrameParser();
IperlHatResponse decoded = parser.Parse(rawData);
log.Debug("SetOptActiveMode isOK: " + decoded.IsOk);
if (decoded.IsOk && iHead.ConfigStruct != null)
{
iHead.ConfigStruct.OpthoStatusMode = DiagnosticLedState.StateOFF;
}
return decoded.IsOk;
}
public string GetUnit(IperlHead iperlHead)
{
if (!serialDriver.IsOpen())
{
serialDriver.Open();
}
var request = new IperlHatFrameBuilder()
.RequestResponse(true)
.AddCommand(ProtocolCommand.ViewFactoryId)
.BuildBytes();
byte[] rawData = serialDriver.SendAndWait(request, 10000);
if (rawData == null)
return null;
// parse rawData
var parser = new IperlHatFrameParser();
IperlHatResponse decoded = parser.Parse(rawData);
if (decoded.IsOk)
{
string asciiPayload = decoded.GetAsciiPayload();
if (iperlHead.ConfigStruct != null) // store mechanism
{
iperlHead.ConfigStruct.Unit = asciiPayload;
}
return asciiPayload;
}
return null;
}
}
}