private void ProcessCloseResponse() { SMLType type = SMLType.Unknown; int length = 0; ProcessNextType(out type, out length); if (type != SMLType.List) { throw new InvalidDataException("Expected list"); } if (length != 1) { throw new InvalidDataException("Expected list length of 1"); } // process SML signature (optional) ProcessNextType(out type, out length); if (type != SMLType.Empty) { if (type != SMLType.OctetString) { throw new InvalidDataException("Expected string"); } string clientID = BitConverter.ToString(_reader.ReadBytes(length)); } }
private void ProcessValList() { SMLType type = SMLType.Unknown; int length = 0; ProcessNextType(out type, out length); if (type != SMLType.List) { throw new InvalidDataException("Expected list"); } for (int i = 0; i < length; i++) { ProcessListEntry(); } }
private void ProcessTime() { SMLType type = SMLType.Unknown; int length = 0; ProcessNextType(out type, out length); if (type != SMLType.Empty) { if (type != SMLType.List) { throw new InvalidDataException("Expected list"); } if (length != 2) { throw new InvalidDataException("Expected list length of 2"); } ProcessNextType(out type, out length); if (type != SMLType.Unsigned) { throw new InvalidDataException("Expected unsigned"); } if (length != 1) { throw new InvalidDataException("Expected unsigned length of 1"); } byte secIndex = _reader.ReadByte(); ProcessNextType(out type, out length); if (type != SMLType.Unsigned) { throw new InvalidDataException("Expected unsigned"); } if (length != 4) { throw new InvalidDataException("Expected unsigned length of 4"); } uint timeStamp = Utils.ByteSwap(_reader.ReadUInt32()); } }
private bool ProcessNextType(out SMLType type, out int length) { byte byteRead = _reader.ReadByte(); // check if we came across an EoM marker if (byteRead == SMLConstants.EndOfMessageMarker) { type = SMLType.Unknown; length = 0; return(false); } type = (SMLType)((byteRead & SMLConstants.TypeMask) >> 4); length = byteRead & SMLConstants.LengthMask; if ((byteRead & SMLConstants.ExtraByteMask) != 0) { // read the extra length byte byte extaLength = _reader.ReadByte(); length = (length << 4) | extaLength; } // list types don't count the type byte as part of the length, while all others do if (type != SMLType.List) { length--; } // special case: an empty optional field is encoded as an empty string if ((type == SMLType.OctetString) && (length == 0)) { type = SMLType.Empty; } return(true); }
private bool ProcessNextType(out SMLType type, out int length) { byte byteRead = _reader.ReadByte(); // check if we came across an EoM marker if (byteRead == Constants.EndOfMessageMarker) { type = SMLType.Unknown; length = 0; return(false); } if ((byteRead & Constants.ExtraByteMask) != 0) { throw new NotImplementedException("Multi-byte length is not supported"); } // special case: an empty optional field is encoded with 0x01 if (byteRead == 0x01) { type = SMLType.Empty; length = 0; return(true); } type = (SMLType)((byteRead & Constants.TypeMask) >> 4); length = byteRead & Constants.LengthMask; // list types don't count the type byte as part of the length, while all others do if (type != SMLType.List) { length--; } return(true); }
private void ProcessListEntry() { SMLType type = SMLType.Unknown; int length = 0; ProcessNextType(out type, out length); if (type != SMLType.List) { throw new InvalidDataException("Expected list"); } if (length != 7) { throw new InvalidDataException("Expected list length of 7"); } // process object name ProcessNextType(out type, out length); if (type != SMLType.OctetString) { throw new InvalidDataException("Expected string"); } string OBISID = BitConverter.ToString(_reader.ReadBytes(length)); // process status (optional) ProcessNextType(out type, out length); if (type != SMLType.Empty) { if (type != SMLType.Unsigned) { throw new InvalidDataException("Expected unsigned"); } byte[] status = _reader.ReadBytes(length); } // process valTime (optional) ProcessTime(); // process unit (optional) ProcessNextType(out type, out length); byte unit = 0; if (type != SMLType.Empty) { if (type != SMLType.Unsigned) { throw new InvalidDataException("Expected unsigned"); } if (length != 1) { throw new InvalidDataException("Expected length of 1"); } unit = _reader.ReadByte(); if (((OBISID == SMLConstants.PositiveActiveEnergyTotal) || (OBISID == SMLConstants.NegativeActiveEnergyTotal)) && (unit != SMLConstants.WattHours)) { throw new InvalidDataException("Expected watt-hours for units"); } } // process scaler (optional) ProcessNextType(out type, out length); sbyte scaler = 0; if (type != SMLType.Empty) { if (type != SMLType.Integer) { throw new InvalidDataException("Expected integer"); } if (length != 1) { throw new InvalidDataException("Expected length of 1"); } scaler = (sbyte)_reader.ReadByte(); } // process value ProcessNextType(out type, out length); switch (type) { case SMLType.OctetString: string value = BitConverter.ToString(_reader.ReadBytes(length)); break; case SMLType.Integer: long int64 = 0; if (length == 8) { int64 = (long)Utils.ByteSwap((ulong)_reader.ReadInt64()); } if (length == 4) { int64 = (int)Utils.ByteSwap((uint)_reader.ReadInt32()); } if (length == 2) { int64 = (short)Utils.ByteSwap((ushort)_reader.ReadInt16()); } if (length == 1) { int64 = (sbyte)_reader.ReadByte(); } if (OBISID == SMLConstants.PositiveActiveEnergyTotal) { Meter.EnergyPurchased = int64 * Math.Pow(10, scaler) / 1000; // in kWh } if (OBISID == SMLConstants.NegativeActiveEnergyTotal) { Meter.EnergySold = int64 * Math.Pow(10, scaler) / 1000; // in kWh } if (OBISID == SMLConstants.ActivePowerTotal) { Meter.CurrentPower = int64 * Math.Pow(10, scaler); // in Watts } break; case SMLType.Unsigned: ulong uint64 = 0; if (length == 8) { uint64 = Utils.ByteSwap(_reader.ReadUInt64()); } if (length == 4) { uint64 = Utils.ByteSwap(_reader.ReadUInt32()); } if (length == 2) { uint64 = Utils.ByteSwap(_reader.ReadUInt16()); } if (length == 1) { uint64 = _reader.ReadByte(); } if (OBISID == SMLConstants.PositiveActiveEnergyTotal) { Meter.EnergyPurchased = uint64 * Math.Pow(10, scaler) / 1000; // in kWh } if (OBISID == SMLConstants.NegativeActiveEnergyTotal) { Meter.EnergySold = uint64 * Math.Pow(10, scaler) / 1000; // in kWh } if (OBISID == SMLConstants.ActivePowerTotal) { Meter.CurrentPower = uint64 * Math.Pow(10, scaler); // in Watts } break; default: throw new NotImplementedException(); } // process value signature (optional) ProcessNextType(out type, out length); if (type != SMLType.Empty) { if (type != SMLType.OctetString) { throw new InvalidDataException("Expected string"); } string clientID = BitConverter.ToString(_reader.ReadBytes(length)); } }
private void ProcessGetListResponse() { SMLType type = SMLType.Unknown; int length = 0; ProcessNextType(out type, out length); if (type != SMLType.List) { throw new InvalidDataException("Expected list"); } if (length != 7) { throw new InvalidDataException("Expected list length of 7"); } // process client ID (optional) ProcessNextType(out type, out length); if (type != SMLType.Empty) { if (type != SMLType.OctetString) { throw new InvalidDataException("Expected string"); } string clientID = BitConverter.ToString(_reader.ReadBytes(length)); } // process server ID ProcessNextType(out type, out length); if (type != SMLType.OctetString) { throw new InvalidDataException("Expected string"); } string serverID = BitConverter.ToString(_reader.ReadBytes(length)); // process list name (optional) ProcessNextType(out type, out length); if (type != SMLType.Empty) { if (type != SMLType.OctetString) { throw new InvalidDataException("Expected string"); } string listName = BitConverter.ToString(_reader.ReadBytes(length)); } // process act sensor time (optional) ProcessTime(); // process val list ProcessValList(); // process list signature (optinal) ProcessNextType(out type, out length); if (type != SMLType.Empty) { if (type != SMLType.OctetString) { throw new InvalidDataException("Expected string"); } string clientID = BitConverter.ToString(_reader.ReadBytes(length)); } // process gateway time (optional) ProcessTime(); }
private void ProcessOpenResponse() { SMLType type = SMLType.Unknown; int length = 0; ProcessNextType(out type, out length); if (type != SMLType.List) { throw new InvalidDataException("Expected list"); } if (length != 6) { throw new InvalidDataException("Expected list length of 6"); } // process codepage (optional) ProcessNextType(out type, out length); if (type != SMLType.Empty) { if (type != SMLType.OctetString) { throw new InvalidDataException("Expected string"); } string codePage = BitConverter.ToString(_reader.ReadBytes(length)); } // process client ID (optional) ProcessNextType(out type, out length); if (type != SMLType.Empty) { if (type != SMLType.OctetString) { throw new InvalidDataException("Expected string"); } string clientID = BitConverter.ToString(_reader.ReadBytes(length)); } // process file ID ProcessNextType(out type, out length); if (type != SMLType.OctetString) { throw new InvalidDataException("Expected string"); } string fileID = BitConverter.ToString(_reader.ReadBytes(length)); // process server ID ProcessNextType(out type, out length); if (type != SMLType.OctetString) { throw new InvalidDataException("Expected string"); } string serverID = BitConverter.ToString(_reader.ReadBytes(length)); // process ref time (optional) ProcessTime(); // process SML version (optional) ProcessNextType(out type, out length); if (type != SMLType.Empty) { if (type != SMLType.Unsigned) { throw new InvalidDataException("Expected unsigned"); } if (length != 1) { throw new InvalidDataException("Expected unsigned length of 1"); } byte smlVersion = _reader.ReadByte(); } }
private void ProcessSMLMessageBody() { SMLType type = SMLType.Unknown; int length = 0; ProcessNextType(out type, out length); if (type != SMLType.List) { throw new InvalidDataException("Expected list"); } if (length != 2) { throw new InvalidDataException("Expected list length of 2"); } // process command ProcessNextType(out type, out length); if (type != SMLType.Unsigned) { throw new InvalidDataException("Expected command as unsigned"); } if (length != 2) { throw new InvalidDataException("Expected command length of 2"); } ushort command = Utils.ByteSwap(_reader.ReadUInt16()); switch (command) { case SMLConstants.PublicOpenReq: throw new NotImplementedException(); case SMLConstants.PublicOpenRes: ProcessOpenResponse(); break; case SMLConstants.PublicCloseReq: throw new NotImplementedException(); case SMLConstants.PublicCloseRes: ProcessCloseResponse(); break; case SMLConstants.GetProfilePackReq: throw new NotImplementedException(); case SMLConstants.GetProfilePackRes: throw new NotImplementedException(); case SMLConstants.GetProfileListReq: throw new NotImplementedException(); case SMLConstants.GetProfileListRes: throw new NotImplementedException(); case SMLConstants.GetProcParameterReq: throw new NotImplementedException(); case SMLConstants.GetProcParameterRes: throw new NotImplementedException(); case SMLConstants.SetProcParameterRes: throw new NotImplementedException(); case SMLConstants.GetListReq: throw new NotImplementedException(); case SMLConstants.GetListRes: ProcessGetListResponse(); break; case SMLConstants.GetCosemReq: throw new NotImplementedException(); case SMLConstants.GetCosemRes: throw new NotImplementedException(); case SMLConstants.SetCosemReq: throw new NotImplementedException(); case SMLConstants.SetCosemRes: throw new NotImplementedException(); case SMLConstants.ActionCosemReq: throw new NotImplementedException(); case SMLConstants.ActionCosemRes: throw new NotImplementedException(); case SMLConstants.AttentionRes: throw new NotImplementedException(); default: throw new InvalidDataException("Unknown command received: " + command.ToString()); } }
private void ProcessSMLMessages() { SMLType type = SMLType.Unknown; int length = 0; while (true) { // an SML message has 6 list elements if (!ProcessNextType(out type, out length)) { // no more SML messages break; } if (type != SMLType.List) { throw new InvalidDataException("Expected list"); } if (length != 6) { throw new InvalidDataException("Expected 6 elements in SML message"); } // process transaction ID ProcessNextType(out type, out length); if (type != SMLType.OctetString) { throw new InvalidDataException("Expected string"); } string transactionId = BitConverter.ToString(_reader.ReadBytes(length)); // process group ID ProcessNextType(out type, out length); if (type != SMLType.Unsigned) { throw new InvalidDataException("Expected group ID as unsigned"); } if (length != 1) { throw new InvalidDataException("Expected group ID length of 1"); } byte groupNo = _reader.ReadByte(); // process abort flag ProcessNextType(out type, out length); if (type != SMLType.Unsigned) { throw new InvalidDataException("Expected abort flag as unsigned"); } if (length != 1) { throw new InvalidDataException("Expected abort flag length of 1"); } byte abortFlag = _reader.ReadByte(); if (abortFlag != 0x00) { Debug.WriteLine("Abort received"); return; } // process message body ProcessSMLMessageBody(); // process CRC ProcessNextType(out type, out length); if (type != SMLType.Unsigned) { throw new InvalidDataException("Expected CRC16 as unsigned"); } if (length != 2) { throw new InvalidDataException("Expected CRC16 length of 2"); } ushort CRC16 = Utils.ByteSwap(_reader.ReadUInt16()); // process end of message if (_reader.ReadByte() != SMLConstants.EndOfMessageMarker) { throw new InvalidDataException("Expected end of message flag"); } } }