Files
UCS_schermsoftware/UCS.Stentofon/ACDP.cs
Martijn Scheepers 0b4de30068 stentofon werkt niet
2021-06-07 09:06:34 +02:00

207 lines
7.1 KiB
C#
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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 System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using UCS.Stentofon.Types;
namespace UCS.Stentofon
{
//https://wiki.zenitel.com/wiki/Application_Layer_(AlphaCom_Data_Protocol)
//https://wiki.zenitel.com/wiki/Broadcast_messages_(ACDP)
public class ACDP
{
private static readonly NLog.Logger Errorlog = NLog.LogManager.GetLogger("Stentofon");
//--- Networklayer ---
public UINT1 SourceNode { get; set; }
public UINT1 SourceDevice { get; set; }
public UINT1 DestinationNode { get; set; }
public UINT1 DestinationDevice { get; set; }
private UINT1 _hop­CountByte;
public uint OptionSize { get; set; }
public uint HopCounter { get; set; }
public List<UINT1> Options { get; set; }
//--- Application Header ---
public UINT1 MessageClass { get; set; }
//--- AlphaCom class messages ---
//Value identifying receivers reference.
//The purpose of this field is that an external system shall be able to recognise responses to data commands.
//The external system can select any suitable reference code, and all messages returned from the exchange will contain this reference.
public UINT2 MessageReference { get; set; }
//Range 0x0000-0x6FFF: Standard application messages
//Range 0x7000-0x7BFF: Site specific(engineering use) values
//Range 0x7C00-0x7FFF: Reserved
//Range 0x8000-0x8FFF: AlphaNet audio control messages
public UINT2 MessageId
{
get
{
if (ApplicationMessage != null)
{
return new UINT2((ushort)ApplicationMessage.MessageType);
}
return new UINT2((ushort)Messages.MessageTypes.DPMT_INVALID);
}
}
//Application message
public Messages.IACDPMessage ApplicationMessage { get; set; }
public ACDP()
{
}
public string Serialize()
{
StringBuilder sb = new StringBuilder();
SourceNode.Serialize(ref sb);
SourceDevice.Serialize(ref sb);
DestinationNode.Serialize(ref sb);
DestinationDevice.Serialize(ref sb);
_hopCountByte = Helpers.CreateHopCountByte(OptionSize, HopCounter);
_hopCountByte.Serialize(ref sb);
if (OptionSize > 0)
{
foreach (var option in Options)
{
option.Serialize(ref sb);
}
}
MessageClass.Serialize(ref sb);
MessageReference.Serialize(ref sb);
MessageId.Serialize(ref sb);
ApplicationMessage?.Serialize(ref sb);
string message = sb.ToString();
return $"{message}={ACDPChecksum.CalcCheckSum(ref message):X2}";
}
public int Deserialize(ref string msg)
{
if (msg.Length < 16 )
{
Errorlog.Error($"Message to short - {msg}");
return -1;
}
if (!msg.Contains('='))
{
Errorlog.Error($"Checksum error (no '=') - {msg}");
return -1;
}
byte checksum = Convert.ToByte(msg.Substring(msg.IndexOf('=') + 1, 2), 16);
if (ACDPChecksum.CalcCheckSum(ref msg) != checksum)
{
Errorlog.Error($"Checksum error - {msg}");
return -1;
}
//Networklayer
int idx = 0;
SourceNode = new UINT1(ref msg, ref idx);
SourceDevice = new UINT1(ref msg, ref idx);
DestinationNode = new UINT1(ref msg, ref idx);
DestinationDevice = new UINT1(ref msg, ref idx);
_hopCountByte = new UINT1(ref msg, ref idx);
OptionSize = Helpers.GetOptionSize(_hopCountByte.Value);
HopCounter = Helpers.GetHopCount(_hopCountByte.Value);
Options = new List<UINT1>();
for (int i = 0; i < OptionSize; i++)
{
UINT1 option = new UINT1(ref msg, ref idx);
Options.Add(option);
}
//Application Layer
MessageClass = new UINT1(ref msg, ref idx);
if (MessageClass.Value == 'A') //AlphaCom Message
{
MessageReference = new UINT2(ref msg, ref idx);
UINT2 messageId = new UINT2(ref msg, ref idx);
if (messageId.Value < 0x7000)
{
Messages.MessageTypes messageIdType = (Messages.MessageTypes)messageId.Value;
ApplicationMessage = Messages.ACDPMessageInvoker.GetMessage(messageIdType);
if (ApplicationMessage != null)
{
ApplicationMessage.Deserialize(ref msg, ref idx);
}
else
{
Debug.WriteLine($"Unhandled standard application message {messageIdType} - {msg}");
Errorlog.Error($"Unhandled standard application message {messageIdType} - {msg}");
return -1;
}
}
else
{
Debug.WriteLine($"Unhandled other message {messageId.Value} - {msg}");
Errorlog.Error($"Unhandled other message {messageId.Value} - {msg}");
return -1;
}
}
else
{
//Other message type log debug
Debug.WriteLine($"Unhandled message class {MessageClass.Value} - {msg}");
Errorlog.Error($"Unhandled message class {MessageClass.Value} - {msg}");
return -1;
}
return idx;
}
public void ToLogString(ref StringBuilder sb)
{
sb.Append("SrcNode=");
SourceNode?.ToLogString(ref sb);
sb.Append(" SrcDev=");
SourceDevice?.ToLogString(ref sb);
sb.Append(" DstNode=");
DestinationNode?.ToLogString(ref sb);
sb.Append(" DstDev=");
DestinationDevice?.ToLogString(ref sb);
sb.Append(" OptionSize=");
sb.Append(OptionSize.ToString());
sb.Append(" HopCnt=");
sb.Append(HopCounter.ToString());
if (OptionSize > 0)
{
foreach (var option in Options)
{
sb.Append(" Option=");
option.ToLogString(ref sb);
}
}
sb.Append(" MsgClass=");
MessageClass?.ToLogString(ref sb);
sb.Append(" MsgRef=");
MessageReference?.ToLogString(ref sb);
if (ApplicationMessage != null)
{
sb.Append(" MsgId=");
sb.Append(ApplicationMessage.MessageType);
sb.Append(" AppMsg=");
ApplicationMessage.ToLogString(ref sb);
}
}
}
}