internal static IPlcAlarmDetails ExtractDetails(ref Span <byte> span, ref int itemOffset)
        {
            var item = new S7PlcAlarmDetails
            {
                Timestamp = GetDt(span.Slice(itemOffset))
            };

            itemOffset += 8;
            ExtractAssotiatedValue(ref span, ref itemOffset, item);
            return(item);
        }
        public static List <IPlcAlarm> TranslateFromSslData(Memory <byte> memory, int size)
        {
            // We do not need the header
            var result = new List <IPlcAlarm>();
            var offset = 6;
            var span   = memory.Span;

            while (offset < size)
            {
                var item = new S7PlcAlarmItemDatagram
                {
                    Length        = span[offset++],
                    TransportSize = BinaryPrimitives.ReadUInt16BigEndian(span.Slice(offset, 2))
                };
                offset        += 2;
                item.AlarmType = span[offset++] == 4 ? AlarmMessageType.AlarmS : AlarmMessageType.Unknown;
                item.MsgNumber = BinaryPrimitives.ReadUInt32BigEndian(span.Slice(offset, 4));
                offset        += 2; // 2 is correct, we use the offset twice
                item.Id        = BinaryPrimitives.ReadUInt16BigEndian(span.Slice(offset, 2));
                offset        += 2;

                item.EventState     = span[offset++]; // 0x00 == going   0x01  == coming
                item.State          = span[offset++]; // isAck
                item.AckStateGoing  = span[offset++];
                item.AckStateComing = span[offset++]; // 0x00 == no ack  0x01  == ack

                if (size >= offset + 12)
                {
                    item.Coming = S7PlcAlarmDetails.ExtractDetails(ref span, ref offset);
                }
                if (size >= offset + 12)
                {
                    item.Going = S7PlcAlarmDetails.ExtractDetails(ref span, ref offset);
                }

                result.Add(item);
            }

            return(result);
        }
        internal static void ExtractAssotiatedValue(ref Span <byte> span, ref int itemOffset, S7PlcAlarmDetails item)
        {
            var assotiatedValue = new S7PlcAlarmAssotiatedValue
            {
                ReturnCode    = span[itemOffset++],
                TransportSize = (DataTransportSize)span[itemOffset++]
            };
            var length       = BinaryPrimitives.ReadUInt16BigEndian(span.Slice(itemOffset, 2)); itemOffset += 2;
            var lengthInByte = assotiatedValue.TransportSize <= DataTransportSize.Int ? length / 8 : length;

            assotiatedValue.Length = lengthInByte;
            assotiatedValue.Data   = new byte[lengthInByte];
            span.Slice(itemOffset, lengthInByte).CopyTo(assotiatedValue.Data.Span);
            itemOffset           += lengthInByte;
            item.AssotiatedValues = assotiatedValue;
        }
示例#4
0
        public static S7AlarmMessage TranslateFromMemory(Memory <byte> data, AlarmMessageType subfunction)
        {
            var span    = data.Span;
            var current = new S7AlarmMessage();
            var offset  = 0;

            current.Timestamp          = GetDt(span.Slice(offset)); offset += 8;
            current.FunctionIdentifier = span[offset++];
            current.NumberOfMessages   = span[offset++];

            var alarms = new List <S7PlcAlarmItemDatagram>();

            for (var i = 0; i < current.NumberOfMessages; i++)
            {
                var alarm = new S7PlcAlarmItemDatagram
                {
                    AlarmType = subfunction
                };

                //var varspec = span[offset];
                offset++;
                alarm.Length = span[offset++];

                if (alarm.Length > 0)
                {
                    var syntaxId = span[offset++];

                    switch (syntaxId)
                    {
                    case (byte)SyntaxIds.AlarmInd:
                    case (byte)SyntaxIds.AlarmAck:
                    {
                        //var numberOfAssociatedValues = span[offset];
                        offset++;
                        alarm.MsgNumber = BinaryPrimitives.ReadUInt32BigEndian(span.Slice(offset, 4));
                        offset         += 2; // 2 is correct, we use the offset twice
                        alarm.Id        = BinaryPrimitives.ReadUInt16BigEndian(span.Slice(offset, 2));
                        offset         += 2;


                        switch (subfunction)
                        {
                        case AlarmMessageType.AlarmSQ:             // ALARM_SQ
                        case AlarmMessageType.AlarmS:              // ALARM_S
                        {
                            alarm.EventState     = span[offset++]; // 0x00 == going   0x01  == coming
                            alarm.State          = span[offset++]; // isAck
                            alarm.AckStateGoing  = span[offset++];
                            alarm.AckStateComing = span[offset++]; // 0x00 == no ack  0x01  == ack

                            var details = new S7PlcAlarmDetails {
                                Timestamp = current.Timestamp
                            };
                            S7PlcAlarmDetails.ExtractAssotiatedValue(ref span, ref offset, details);

                            if (alarm.EventState == 0x00)
                            {
                                alarm.Going = details;
                            }
                            else if (alarm.EventState == 0x01)
                            {
                                alarm.Coming = details;
                            }
                        }
                        break;

                        case AlarmMessageType.AlarmAck:             // ALARM ack
                        {
                            alarm.AckStateGoing  = span[offset++];
                            alarm.AckStateComing = span[offset++];                 // 0x00 == no ack  0x01  == ack
                        }
                        break;

                        default:
                        {
                            ThrowHelper.ThrowUnknownAlarmSubfunction(subfunction);
                            break;
                        }
                        }
                        break;
                    }

                    default:
                    {
                        ThrowHelper.ThrowUnknownAlarmSyntax(syntaxId);
                        break;
                    }
                    }
                }

                alarms.Add(alarm);
            }
            current.Alarms = alarms;
            return(current);
        }