Пример #1
0
        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));
            }
        }
Пример #2
0
        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();
            }
        }
Пример #3
0
        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());
            }
        }
Пример #4
0
        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);
        }
Пример #5
0
        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);
        }
Пример #6
0
        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));
            }
        }
Пример #7
0
        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();
        }
Пример #8
0
        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();
            }
        }
Пример #9
0
        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());
            }
        }
Пример #10
0
        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");
                }
            }
        }