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; }
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); }