207 lines
7.1 KiB
C#
207 lines
7.1 KiB
C#
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 _hopCountByte;
|
||
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);
|
||
}
|
||
}
|
||
}
|
||
}
|