diff --git a/src/S7CommPlusDriver/Alarming/BrowseAlarms.cs b/src/S7CommPlusDriver/Alarming/BrowseAlarms.cs
index 6f31c4f..a7f96b5 100644
--- a/src/S7CommPlusDriver/Alarming/BrowseAlarms.cs
+++ b/src/S7CommPlusDriver/Alarming/BrowseAlarms.cs
@@ -332,6 +332,74 @@ private void GetTexts(byte[] tloa_1, byte[] tloa_2, byte[] tloa_3, byte[] tlsa,
}
}
}
+
+ ///
+ /// Reads the active program alarms from the Plc (single poll).
+ ///
+ /// Call example:
+ /// CultureInfo ci = new CultureInfo("de-DE");
+ /// var alarmList = new List();
+ /// conn.GetActiveAlarms(out alarmList, ci.LCID);
+ /// foreach (var a in alarmList)
+ /// {
+ /// Console.WriteLine(a.ToString());
+ /// }
+ ///
+ /// Contains the alarms, empty if there is no active alarm
+ /// Language id for retrieving the text entries, use language code e.g. 1031 for german
+ /// 0 on success
+ public int GetActiveAlarms(out List alarmList, int languageId)
+ {
+ int res;
+
+ alarmList = new List();
+
+ var exploreReq = new ExploreRequest(ProtocolVersion.V2);
+ exploreReq.ExploreId = Ids.NativeObjects_theAlarmSubsystem_Rid;
+ exploreReq.ExploreRequestId = Ids.AlarmSubsystem_itsUpdateRelevantDAI;
+ exploreReq.ExploreChildsRecursive = 1;
+ exploreReq.ExploreParents = 0;
+
+ // Add the requestes attributes.
+ // Request the same attributes we get from an alarm notification, so we can reuse other methods.
+ exploreReq.AddressList.Add(Ids.DAI_CPUAlarmID);
+ exploreReq.AddressList.Add(Ids.DAI_AllStatesInfo);
+ exploreReq.AddressList.Add(Ids.DAI_AlarmDomain);
+ exploreReq.AddressList.Add(Ids.DAI_Coming);
+ exploreReq.AddressList.Add(Ids.DAI_Going);
+ exploreReq.AddressList.Add(Ids.DAI_MessageType);
+ exploreReq.AddressList.Add(Ids.DAI_HmiInfo);
+ // Extra ones which we only need for compatibility with notification.
+ exploreReq.AddressList.Add(Ids.ObjectVariableTypeName);
+ exploreReq.AddressList.Add(Ids.DAI_SequenceCounter);
+ exploreReq.AddressList.Add(Ids.DAI_AlarmTexts_Rid);
+
+ res = SendS7plusFunctionObject(exploreReq);
+ if (res != 0)
+ {
+ return res;
+ }
+ m_LastError = 0;
+ WaitForNewS7plusReceived(m_ReadTimeout);
+ if (m_LastError != 0)
+ {
+ return m_LastError;
+ }
+
+ var exploreRes = ExploreResponse.DeserializeFromPdu(m_ReceivedPDU, true);
+ res = checkResponseWithIntegrity(exploreReq, exploreRes);
+ if (res != 0)
+ {
+ return res;
+ }
+
+ foreach (var obj in exploreRes.Objects)
+ {
+ alarmList.Add(AlarmsDai.FromNotificationObject(obj, languageId));
+ }
+
+ return 0;
+ }
}
public class AlarmData
diff --git a/src/S7CommPlusDriver/ClientApi/PlcTag.cs b/src/S7CommPlusDriver/ClientApi/PlcTag.cs
index 18cc628..4e83546 100644
--- a/src/S7CommPlusDriver/ClientApi/PlcTag.cs
+++ b/src/S7CommPlusDriver/ClientApi/PlcTag.cs
@@ -1,5 +1,7 @@
using System;
using System.Text;
+using System.Collections;
+using System.Collections.Generic;
namespace S7CommPlusDriver.ClientApi
{
@@ -1701,4 +1703,711 @@ public override string ToString()
return String.Format(fmt, Value.ToString(), ns);
}
}
+
+ #region Arrays
+
+ public class PlcTagBoolArray : PlcTag
+ {
+ private bool[] m_Value;
+
+ public bool[] Value
+ {
+ get { return m_Value; }
+ set { m_Value = value; }
+ }
+
+ public PlcTagBoolArray(string name, ItemAddress address, uint softdatatype) : base(name, address, softdatatype)
+ {
+ m_Value = new bool[1];
+ }
+
+ public override void ProcessReadResult(object valueObj, ulong error)
+ {
+ LastReadError = error;
+ if (CheckErrorAndType(error, valueObj, typeof(ValueBoolArray)) == 0)
+ {
+ Value = ((ValueBoolArray)valueObj).GetValue();
+
+ Quality = PlcTagQC.TAG_QUALITY_GOOD;
+ }
+ else
+ {
+ Quality = PlcTagQC.TAG_QUALITY_BAD;
+ }
+ }
+
+ public override PValue GetWriteValue()
+ {
+ return new ValueBoolArray(Value);
+ }
+
+ public override string ToString()
+ {
+ var val = new ValueBoolArray(Value);
+ return ResultString(this, val.ToString());
+ }
+ }
+
+ public class PlcTagByteArray : PlcTag
+ {
+ private byte[] m_Value;
+
+ public byte[] Value
+ {
+ get { return m_Value; }
+ set { m_Value = value; }
+ }
+
+ public PlcTagByteArray(string name, ItemAddress address, uint softdatatype) : base(name, address, softdatatype)
+ {
+ m_Value = new byte[1];
+ }
+
+ public override void ProcessReadResult(object valueObj, ulong error)
+ {
+ LastReadError = error;
+ if (CheckErrorAndType(error, valueObj, typeof(ValueByteArray)) == 0)
+ {
+ Value = ((ValueByteArray)valueObj).GetValue();
+
+ Quality = PlcTagQC.TAG_QUALITY_GOOD;
+ }
+ else
+ {
+ Quality = PlcTagQC.TAG_QUALITY_BAD;
+ }
+ }
+
+ public override PValue GetWriteValue()
+ {
+ return new ValueByteArray(Value);
+ }
+
+ public override string ToString()
+ {
+ var val = new ValueByteArray(Value);
+ return ResultString(this, val.ToString());
+ }
+ }
+
+ public class PlcTagWordArray : PlcTag
+ {
+ private ushort[] m_Value;
+
+ public ushort[] Value
+ {
+ get { return m_Value; }
+ set { m_Value = value; }
+ }
+
+ public PlcTagWordArray(string name, ItemAddress address, uint softdatatype) : base(name, address, softdatatype)
+ {
+ m_Value = new ushort[1];
+ }
+
+ public override void ProcessReadResult(object valueObj, ulong error)
+ {
+ LastReadError = error;
+ if (CheckErrorAndType(error, valueObj, typeof(ValueWordArray)) == 0)
+ {
+ Value = ((ValueWordArray)valueObj).GetValue();
+
+ Quality = PlcTagQC.TAG_QUALITY_GOOD;
+ }
+ else
+ {
+ Quality = PlcTagQC.TAG_QUALITY_BAD;
+ }
+ }
+
+ public override PValue GetWriteValue()
+ {
+ return new ValueWordArray(Value);
+ }
+
+ public override string ToString()
+ {
+ var val = new ValueWordArray(Value);
+ return ResultString(this, val.ToString());
+ }
+ }
+
+ public class PlcTagIntArray : PlcTag
+ {
+ private short[] m_Value;
+
+ public short[] Value
+ {
+ get { return m_Value; }
+ set { m_Value = value; }
+ }
+
+ public PlcTagIntArray(string name, ItemAddress address, uint softdatatype) : base(name, address, softdatatype)
+ {
+ m_Value = new short[1];
+ }
+
+ public override void ProcessReadResult(object valueObj, ulong error)
+ {
+ LastReadError = error;
+ if (CheckErrorAndType(error, valueObj, typeof(ValueIntArray)) == 0)
+ {
+ Value = ((ValueIntArray)valueObj).GetValue();
+
+ Quality = PlcTagQC.TAG_QUALITY_GOOD;
+ }
+ else
+ {
+ Quality = PlcTagQC.TAG_QUALITY_BAD;
+ }
+ }
+
+ public override PValue GetWriteValue()
+ {
+ return new ValueIntArray(Value);
+ }
+
+ public override string ToString()
+ {
+ var val = new ValueIntArray(Value);
+ return ResultString(this, val.ToString());
+ }
+ }
+
+ public class PlcTagDWordArray : PlcTag
+ {
+ private uint[] m_Value;
+
+ public uint[] Value
+ {
+ get { return m_Value; }
+ set { m_Value = value; }
+ }
+
+ public PlcTagDWordArray(string name, ItemAddress address, uint softdatatype) : base(name, address, softdatatype)
+ {
+ m_Value = new uint[1];
+ }
+
+ public override void ProcessReadResult(object valueObj, ulong error)
+ {
+ LastReadError = error;
+ if (CheckErrorAndType(error, valueObj, typeof(ValueDWordArray)) == 0)
+ {
+ Value = ((ValueDWordArray)valueObj).GetValue();
+
+ Quality = PlcTagQC.TAG_QUALITY_GOOD;
+ }
+ else
+ {
+ Quality = PlcTagQC.TAG_QUALITY_BAD;
+ }
+ }
+
+ public override PValue GetWriteValue()
+ {
+ return new ValueDWordArray(Value);
+ }
+
+ public override string ToString()
+ {
+ var val = new ValueDWordArray(Value);
+ return ResultString(this, val.ToString());
+ }
+ }
+
+ public class PlcTagDIntArray : PlcTag
+ {
+ private int[] m_Value;
+
+ public int[] Value
+ {
+ get { return m_Value; }
+ set { m_Value = value; }
+ }
+
+ public PlcTagDIntArray(string name, ItemAddress address, uint softdatatype) : base(name, address, softdatatype)
+ {
+ m_Value = new int[1];
+ }
+
+ public override void ProcessReadResult(object valueObj, ulong error)
+ {
+ LastReadError = error;
+ if (CheckErrorAndType(error, valueObj, typeof(ValueDIntArray)) == 0)
+ {
+ Value = ((ValueDIntArray)valueObj).GetValue();
+
+ Quality = PlcTagQC.TAG_QUALITY_GOOD;
+ }
+ else
+ {
+ Quality = PlcTagQC.TAG_QUALITY_BAD;
+ }
+ }
+
+ public override PValue GetWriteValue()
+ {
+ return new ValueDIntArray(Value);
+ }
+
+ public override string ToString()
+ {
+ var val = new ValueDIntArray(Value);
+ return ResultString(this, val.ToString());
+ }
+ }
+
+ public class PlcTagRealArray : PlcTag
+ {
+ private float[] m_Value;
+
+ public float[] Value
+ {
+ get { return m_Value; }
+ set { m_Value = value; }
+ }
+
+ public PlcTagRealArray(string name, ItemAddress address, uint softdatatype) : base(name, address, softdatatype)
+ {
+ m_Value = new float[1];
+ }
+
+ public override void ProcessReadResult(object valueObj, ulong error)
+ {
+ LastReadError = error;
+ if (CheckErrorAndType(error, valueObj, typeof(ValueRealArray)) == 0)
+ {
+ Value = ((ValueRealArray)valueObj).GetValue();
+
+ Quality = PlcTagQC.TAG_QUALITY_GOOD;
+ }
+ else
+ {
+ Quality = PlcTagQC.TAG_QUALITY_BAD;
+ }
+ }
+
+ public override PValue GetWriteValue()
+ {
+ return new ValueRealArray(Value);
+ }
+
+ public override string ToString()
+ {
+ var val = new ValueRealArray(Value);
+ return ResultString(this, val.ToString());
+ }
+ }
+
+ public class PlcTagUSIntArray : PlcTag
+ {
+ private byte[] m_Value;
+
+ public byte[] Value
+ {
+ get { return m_Value; }
+ set { m_Value = value; }
+ }
+
+ public PlcTagUSIntArray(string name, ItemAddress address, uint softdatatype) : base(name, address, softdatatype)
+ {
+ m_Value = new byte[1];
+ }
+
+ public override void ProcessReadResult(object valueObj, ulong error)
+ {
+ LastReadError = error;
+ if (CheckErrorAndType(error, valueObj, typeof(ValueUSIntArray)) == 0)
+ {
+ Value = ((ValueUSIntArray)valueObj).GetValue();
+
+ Quality = PlcTagQC.TAG_QUALITY_GOOD;
+ }
+ else
+ {
+ Quality = PlcTagQC.TAG_QUALITY_BAD;
+ }
+ }
+
+ public override PValue GetWriteValue()
+ {
+ return new ValueUSIntArray(Value);
+ }
+
+ public override string ToString()
+ {
+ var val = new ValueUSIntArray(Value);
+ return ResultString(this, val.ToString());
+ }
+ }
+
+ public class PlcTagUIntArray : PlcTag
+ {
+ private ushort[] m_Value;
+
+ public ushort[] Value
+ {
+ get { return m_Value; }
+ set { m_Value = value; }
+ }
+
+ public PlcTagUIntArray(string name, ItemAddress address, uint softdatatype) : base(name, address, softdatatype)
+ {
+ m_Value = new ushort[1];
+ }
+
+ public override void ProcessReadResult(object valueObj, ulong error)
+ {
+ LastReadError = error;
+ if (CheckErrorAndType(error, valueObj, typeof(ValueUIntArray)) == 0)
+ {
+ Value = ((ValueUIntArray)valueObj).GetValue();
+
+ Quality = PlcTagQC.TAG_QUALITY_GOOD;
+ }
+ else
+ {
+ Quality = PlcTagQC.TAG_QUALITY_BAD;
+ }
+ }
+
+ public override PValue GetWriteValue()
+ {
+ return new ValueUIntArray(Value);
+ }
+
+ public override string ToString()
+ {
+ var val = new ValueUIntArray(Value);
+ return ResultString(this, val.ToString());
+ }
+ }
+
+ public class PlcTagUDIntArray : PlcTag
+ {
+ private uint[] m_Value;
+
+ public uint[] Value
+ {
+ get { return m_Value; }
+ set { m_Value = value; }
+ }
+
+ public PlcTagUDIntArray(string name, ItemAddress address, uint softdatatype) : base(name, address, softdatatype)
+ {
+ m_Value = new uint[1];
+ }
+
+ public override void ProcessReadResult(object valueObj, ulong error)
+ {
+ LastReadError = error;
+ if (CheckErrorAndType(error, valueObj, typeof(ValueUDIntArray)) == 0)
+ {
+ Value = ((ValueUDIntArray)valueObj).GetValue();
+
+ Quality = PlcTagQC.TAG_QUALITY_GOOD;
+ }
+ else
+ {
+ Quality = PlcTagQC.TAG_QUALITY_BAD;
+ }
+ }
+
+ public override PValue GetWriteValue()
+ {
+ return new ValueUDIntArray(Value);
+ }
+
+ public override string ToString()
+ {
+ var val = new ValueUDIntArray(Value);
+ return ResultString(this, val.ToString());
+ }
+ }
+
+ public class PlcTagSIntArray : PlcTag
+ {
+ private sbyte[] m_Value;
+
+ public sbyte[] Value
+ {
+ get { return m_Value; }
+ set { m_Value = value; }
+ }
+
+ public PlcTagSIntArray(string name, ItemAddress address, uint softdatatype) : base(name, address, softdatatype)
+ {
+ m_Value = new sbyte[1];
+ }
+
+ public override void ProcessReadResult(object valueObj, ulong error)
+ {
+ LastReadError = error;
+ if (CheckErrorAndType(error, valueObj, typeof(ValueSIntArray)) == 0)
+ {
+ Value = ((ValueSIntArray)valueObj).GetValue();
+
+ Quality = PlcTagQC.TAG_QUALITY_GOOD;
+ }
+ else
+ {
+ Quality = PlcTagQC.TAG_QUALITY_BAD;
+ }
+ }
+
+ public override PValue GetWriteValue()
+ {
+ return new ValueSIntArray(Value);
+ }
+
+ public override string ToString()
+ {
+ var val = new ValueSIntArray(Value);
+ return ResultString(this, val.ToString());
+ }
+ }
+
+ public class PlcTagDateAndTimeArray : PlcTag
+ {
+ /* BCD coded:
+ * YYMMDDhhmmssuuuQ
+ * uuu = milliseconds
+ * Q = Weekday 1=Su, 2=Mo, 3=Tu, 4=We, 5=Th, 6=Fr, 7=Sa
+ */
+ private DateTime[] m_Value;
+
+ public DateTime[] Value
+ {
+ get
+ {
+ return m_Value;
+ }
+
+ set
+ {
+ bool dataOk = true;
+ foreach (var item in value)
+ {
+ if (item < new DateTime(1990, 1, 1) && item >= new DateTime(2090, 1, 1))
+ {
+ dataOk = false;
+ break;
+ }
+ }
+ if (dataOk)
+ {
+ m_Value = value;
+ }
+ else
+ {
+ throw new ArgumentOutOfRangeException("Value", "DateTime must be >= 1990-01-01 and < 2090-01-01");
+ }
+ }
+ }
+
+ public PlcTagDateAndTimeArray(string name, ItemAddress address, uint softdatatype) : base(name, address, softdatatype)
+ {
+ Value = new DateTime[0];
+ }
+
+ public override void ProcessReadResult(object valueObj, ulong error)
+ {
+ LastReadError = error;
+ if (CheckErrorAndType(error, valueObj, typeof(ValueUSIntArray)) == 0)
+ {
+ List dateTimes = new List();
+ var v = ((ValueUSIntArray)valueObj).GetValue();
+ int pos = 0;
+ do
+ {
+ int[] ts = new int[8];
+ for (int i = 0; i < 7; i++)
+ {
+ ts[i] = BcdByteToInt(v[pos + i]);
+ }
+ // The left nibble of the last byte contains the LSD of milliseconds,
+ // the right nibble the weekday (which we don't process here).
+ ts[7] = v[7] >> 4;
+
+ int year;
+ if (ts[0] >= 90)
+ {
+ year = 1900 + ts[0];
+ }
+ else
+ {
+ year = 2000 + ts[0];
+ }
+ var value = new DateTime(year, ts[1], ts[2], ts[3], ts[4], ts[5]);
+ value = value.AddMilliseconds(ts[6] * 10 + ts[7]);
+ dateTimes.Add(value);
+ pos += 8;
+ } while (pos < v.Length);
+ Value = dateTimes.ToArray();
+ Quality = PlcTagQC.TAG_QUALITY_GOOD;
+ }
+ else
+ {
+ Quality = PlcTagQC.TAG_QUALITY_BAD;
+ }
+ }
+
+ public override PValue GetWriteValue()
+ {
+ var byteStrings = new List();
+ foreach (var item in Value)
+ {
+ int[] ts = new int[8];
+ byte[] b = new byte[8];
+ if (item.Year < 2000)
+ {
+ // 90-99 = 1990-1999
+ ts[0] = item.Year - 1900;
+ }
+ else
+ {
+ // 00-89 = 2000-2089
+ ts[0] = item.Year - 2000;
+ }
+ ts[1] = item.Month;
+ ts[2] = item.Day;
+ ts[3] = item.Hour;
+ ts[4] = item.Minute;
+ ts[5] = item.Second;
+ ts[6] = item.Millisecond / 10;
+ ts[7] = (item.Millisecond % 10) << 4; // Don't set the weekday
+ for (int i = 0; i < 7; i++)
+ {
+ b[i] = IntToBcdByte(ts[i]);
+ }
+ b[7] = (byte)ts[7];
+ byteStrings.AddRange(b);
+ }
+ return new ValueUSIntArray(byteStrings.ToArray());
+ }
+
+ public override string ToString()
+ {
+ string s = "";
+ for (int i = 0; i < Value.Length; i++)
+ {
+ string ts = Value[i].ToString();
+ if (Value[i].Millisecond > 0)
+ {
+ ts += String.Format(".{0:D03}", Value[i].Millisecond);
+ }
+ s += String.Format("{0}", ts);
+ }
+ s += "";
+ return ResultString(this, s);
+ }
+ }
+
+
+ public class PlcTagStringArray : PlcTag
+ {
+ private string[] m_Value;
+ private byte m_MaxLength = 254;
+ private string m_Encoding = "ISO-8859-1";
+
+ public string[] Value
+ {
+ get
+ {
+ return m_Value;
+ }
+
+ set
+ {
+ bool lengthOk = true;
+ foreach (var item in value)
+ {
+ if (item.Length > m_MaxLength)
+ {
+ lengthOk = false;
+ break;
+ }
+ }
+ if (lengthOk)
+ {
+ m_Value = value;
+ }
+ else
+ {
+ throw new ArgumentOutOfRangeException("Value", "String is longer than the allowed max. length of " + m_MaxLength);
+ }
+ }
+ }
+
+ public PlcTagStringArray(string name, ItemAddress address, uint softdatatype, byte maxlength = 254) : base(name, address, softdatatype)
+ {
+ m_MaxLength = maxlength;
+ }
+
+ public override void ProcessReadResult(object valueObj, ulong error)
+ {
+ LastReadError = error;
+ if (CheckErrorAndType(error, valueObj, typeof(ValueUSIntArray)) == 0)
+ {
+ List strings = new List();
+ var v = ((ValueUSIntArray)valueObj).GetValue();
+ int pos = 0;
+ do
+ {
+ int max_len = v[pos];
+ int act_len = v[pos + 1];
+ // IEC 61131-3 states ISO-646 IRV, with optional extensions like "Latin-1 Supplement".
+ // Siemens TIA-Portal gives warnings using other than 7 Bit ASCII characters.
+ // Let the user define his local encoding via SetStringEncoding().
+ var str = Encoding.GetEncoding(m_Encoding).GetString(v, pos + 2, act_len);
+ strings.Add(str);
+ pos += max_len + 2;
+
+ } while (pos < v.Length);
+ Value = strings.ToArray();
+ Quality = PlcTagQC.TAG_QUALITY_GOOD;
+ }
+ else
+ {
+ Quality = PlcTagQC.TAG_QUALITY_BAD;
+ }
+ }
+
+ public override PValue GetWriteValue()
+ {
+ var byteStrings = new List();
+ foreach (var item in Value)
+ {
+ // Must write the complete array of MaxLength of the string (plus two bytes header).
+ byte[] sb = Encoding.GetEncoding(m_Encoding).GetBytes(item);
+ var b = new byte[m_MaxLength + 2];
+ b[0] = m_MaxLength;
+ b[1] = (byte)sb.Length;
+ for (int i = 0; i < sb.Length; i++)
+ {
+ b[i + 2] = sb[i];
+ }
+ byteStrings.AddRange(b);
+ }
+ return new ValueUSIntArray(byteStrings.ToArray());
+ }
+
+ public void SetStringEncoding(string encoding)
+ {
+ m_Encoding = encoding;
+ }
+
+ public override string ToString()
+ {
+ string s = "";
+ for (int i = 0; i < Value.Length; i++)
+ {
+ s += String.Format("{0}", Value[i]);
+ }
+ s += "";
+ return ResultString(this, s);
+ }
+ }
+ #endregion
}
\ No newline at end of file
diff --git a/src/S7CommPlusDriver/ClientApi/PlcTags.cs b/src/S7CommPlusDriver/ClientApi/PlcTags.cs
index cfaa5ea..787cae6 100644
--- a/src/S7CommPlusDriver/ClientApi/PlcTags.cs
+++ b/src/S7CommPlusDriver/ClientApi/PlcTags.cs
@@ -66,25 +66,39 @@ public static int WriteTags(this S7CommPlusConnection conn, IEnumerable
return res;
}
- public static PlcTag TagFactory(string name, ItemAddress address, uint softdatatype)
+ public static PlcTag TagFactory(string name, ItemAddress address, uint softdatatype, bool Is1Dim = false)
{
switch (softdatatype)
{
case Softdatatype.S7COMMP_SOFTDATATYPE_BOOL:
+ if (Is1Dim)
+ return new PlcTagBoolArray(name, address, softdatatype);
return new PlcTagBool(name, address, softdatatype);
case Softdatatype.S7COMMP_SOFTDATATYPE_BYTE:
+ if (Is1Dim)
+ return new PlcTagByteArray(name, address, softdatatype);
return new PlcTagByte(name, address, softdatatype);
case Softdatatype.S7COMMP_SOFTDATATYPE_CHAR:
return new PlcTagChar(name, address, softdatatype);
case Softdatatype.S7COMMP_SOFTDATATYPE_WORD:
+ if (Is1Dim)
+ return new PlcTagWordArray(name, address, softdatatype);
return new PlcTagWord(name, address, softdatatype);
case Softdatatype.S7COMMP_SOFTDATATYPE_INT:
+ if (Is1Dim)
+ return new PlcTagIntArray(name, address, softdatatype);
return new PlcTagInt(name, address, softdatatype);
case Softdatatype.S7COMMP_SOFTDATATYPE_DWORD:
+ if (Is1Dim)
+ return new PlcTagDWordArray(name, address, softdatatype);
return new PlcTagDWord(name, address, softdatatype);
case Softdatatype.S7COMMP_SOFTDATATYPE_DINT:
+ if (Is1Dim)
+ return new PlcTagDIntArray(name, address, softdatatype);
return new PlcTagDInt(name, address, softdatatype);
case Softdatatype.S7COMMP_SOFTDATATYPE_REAL:
+ if (Is1Dim)
+ return new PlcTagRealArray(name, address, softdatatype);
return new PlcTagReal(name, address, softdatatype);
case Softdatatype.S7COMMP_SOFTDATATYPE_DATE:
return new PlcTagDate(name, address, softdatatype);
@@ -95,9 +109,13 @@ public static PlcTag TagFactory(string name, ItemAddress address, uint softdatat
case Softdatatype.S7COMMP_SOFTDATATYPE_S5TIME:
return new PlcTagS5Time(name, address, softdatatype);
case Softdatatype.S7COMMP_SOFTDATATYPE_DATEANDTIME:
+ if (Is1Dim)
+ return new PlcTagDateAndTimeArray(name, address, softdatatype);
return new PlcTagDateAndTime(name, address, softdatatype);
case Softdatatype.S7COMMP_SOFTDATATYPE_STRING:
+ if (Is1Dim)
+ return new PlcTagStringArray(name, address, softdatatype);
return new PlcTagString(name, address, softdatatype);
case Softdatatype.S7COMMP_SOFTDATATYPE_POINTER:
return new PlcTagPointer(name, address, softdatatype);
@@ -115,6 +133,8 @@ public static PlcTag TagFactory(string name, ItemAddress address, uint softdatat
return new PlcTagUInt(name, address, softdatatype);
case Softdatatype.S7COMMP_SOFTDATATYPE_BBOOL:
+ if (Is1Dim)
+ return new PlcTagBoolArray(name, address, softdatatype);
return new PlcTagBool(name, address, softdatatype);
case Softdatatype.S7COMMP_SOFTDATATYPE_LREAL:
@@ -126,12 +146,20 @@ public static PlcTag TagFactory(string name, ItemAddress address, uint softdatat
case Softdatatype.S7COMMP_SOFTDATATYPE_LWORD:
return new PlcTagLWord(name, address, softdatatype);
case Softdatatype.S7COMMP_SOFTDATATYPE_USINT:
+ if (Is1Dim)
+ return new PlcTagUSIntArray(name, address, softdatatype);
return new PlcTagUSInt(name, address, softdatatype);
case Softdatatype.S7COMMP_SOFTDATATYPE_UINT:
+ if (Is1Dim)
+ return new PlcTagUIntArray(name, address, softdatatype);
return new PlcTagUInt(name, address, softdatatype);
case Softdatatype.S7COMMP_SOFTDATATYPE_UDINT:
+ if (Is1Dim)
+ return new PlcTagUDIntArray(name, address, softdatatype);
return new PlcTagUDInt(name, address, softdatatype);
case Softdatatype.S7COMMP_SOFTDATATYPE_SINT:
+ if (Is1Dim)
+ return new PlcTagSIntArray(name, address, softdatatype);
return new PlcTagSInt(name, address, softdatatype);
case Softdatatype.S7COMMP_SOFTDATATYPE_WCHAR:
diff --git a/src/S7CommPlusDriver/Core/Ids.cs b/src/S7CommPlusDriver/Core/Ids.cs
index 610ca0d..0bca5fb 100644
--- a/src/S7CommPlusDriver/Core/Ids.cs
+++ b/src/S7CommPlusDriver/Core/Ids.cs
@@ -1,85 +1,86 @@
-#region License
-/******************************************************************************
- * S7CommPlusDriver
- *
- * Copyright (C) 2023 Thomas Wiens, th.wiens@gmx.de
- *
- * This file is part of S7CommPlusDriver.
- *
- * S7CommPlusDriver is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- /****************************************************************************/
-#endregion
-
-namespace S7CommPlusDriver
-{
- public static class Ids
- {
+#region License
+/******************************************************************************
+ * S7CommPlusDriver
+ *
+ * Copyright (C) 2023 Thomas Wiens, th.wiens@gmx.de
+ *
+ * This file is part of S7CommPlusDriver.
+ *
+ * S7CommPlusDriver is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ /****************************************************************************/
+#endregion
+
+namespace S7CommPlusDriver
+{
+ public static class Ids
+ {
public const int None = 0;
- public const int NativeObjects_theASRoot_Rid = 1;
+ public const int NativeObjects_theASRoot_Rid = 1;
public const int NativeObjects_thePLCProgram_Rid = 3;
+ public const int NativeObjects_theAlarmSubsystem_Rid = 8;
public const int NativeObjects_theCPUProxy_Rid = 49;
- public const int NativeObjects_theCPUCommon_Rid = 50;
- public const int NativeObjects_theCPUexecUnit_Rid = 52;
- public const int NativeObjects_theIArea_Rid = 80;
- public const int NativeObjects_theQArea_Rid = 81;
- public const int NativeObjects_theMArea_Rid = 82;
- public const int NativeObjects_theS7Counters_Rid = 83;
- public const int NativeObjects_theS7Timers_Rid = 84;
- public const int ObjectRoot = 201;
- public const int GetNewRIDOnServer = 211;
- public const int ObjectVariableTypeParentObject = 229;
- public const int ObjectVariableTypeName = 233;
- public const int ClassSubscriptions = 255;
- public const int ClassServerSessionContainer = 284;
- public const int ObjectServerSessionContainer = 285;
- public const int ClassServerSession = 287;
- public const int ObjectNullServerSession = 288;
- public const int ServerSessionClientRID = 300;
- public const int ServerSessionRequest = 303;
- public const int ServerSessionResponse = 304;
- public const int ServerSessionVersion = 306;
- public const int LID_SessionVersionSystemPAOMString = 319;
- public const int ClassTypeInfo = 511;
- public const int ClassOMSTypeInfoContainer = 534;
- public const int ObjectOMSTypeInfoContainer = 537;
- public const int TextLibraryClassRID = 606;
- public const int TextLibraryOffsetArea = 608;
- public const int TextLibraryStringArea = 609;
- public const int ClassSubscription = 1001;
- public const int SubscriptionMissedSendings = 1002;
- public const int SubscriptionSubsystemError = 1003;
- public const int SubscriptionReferenceTriggerAndTransmitMode = 1005;
- public const int SystemLimits = 1037;
- public const int SubscriptionRouteMode = 1040;
- public const int SubscriptionActive = 1041;
- public const int Legitimate = 1846;
- public const int SubscriptionReferenceList = 1048;
- public const int SubscriptionCycleTime = 1049;
- public const int SubscriptionDelayTime = 1050;
- public const int SubscriptionDisabled = 1051;
- public const int SubscriptionCount = 1052;
- public const int SubscriptionCreditLimit = 1053;
- public const int SubscriptionTicks = 1054;
- public const int FreeItems = 1081;
- public const int SubscriptionFunctionClassId = 1082;
- public const int Filter = 1246;
- public const int FilterOperation = 1247;
- public const int AddressCount = 1249;
- public const int Address = 1250;
- public const int FilterValue = 1251;
- public const int ObjectQualifier = 1256;
- public const int ParentRID = 1257;
- public const int CompositionAID = 1258;
- public const int KeyQualifier = 1259;
- public const int TI_TComSize = 1502;
- public const int EffectiveProtectionLevel = 1842;
- public const int ActiveProtectionLevel = 1843;
- public const int CPUexecUnit_operatingStateReq = 2167;
+ public const int NativeObjects_theCPUCommon_Rid = 50;
+ public const int NativeObjects_theCPUexecUnit_Rid = 52;
+ public const int NativeObjects_theIArea_Rid = 80;
+ public const int NativeObjects_theQArea_Rid = 81;
+ public const int NativeObjects_theMArea_Rid = 82;
+ public const int NativeObjects_theS7Counters_Rid = 83;
+ public const int NativeObjects_theS7Timers_Rid = 84;
+ public const int ObjectRoot = 201;
+ public const int GetNewRIDOnServer = 211;
+ public const int ObjectVariableTypeParentObject = 229;
+ public const int ObjectVariableTypeName = 233;
+ public const int ClassSubscriptions = 255;
+ public const int ClassServerSessionContainer = 284;
+ public const int ObjectServerSessionContainer = 285;
+ public const int ClassServerSession = 287;
+ public const int ObjectNullServerSession = 288;
+ public const int ServerSessionClientRID = 300;
+ public const int ServerSessionRequest = 303;
+ public const int ServerSessionResponse = 304;
+ public const int ServerSessionVersion = 306;
+ public const int LID_SessionVersionSystemPAOMString = 319;
+ public const int ClassTypeInfo = 511;
+ public const int ClassOMSTypeInfoContainer = 534;
+ public const int ObjectOMSTypeInfoContainer = 537;
+ public const int TextLibraryClassRID = 606;
+ public const int TextLibraryOffsetArea = 608;
+ public const int TextLibraryStringArea = 609;
+ public const int ClassSubscription = 1001;
+ public const int SubscriptionMissedSendings = 1002;
+ public const int SubscriptionSubsystemError = 1003;
+ public const int SubscriptionReferenceTriggerAndTransmitMode = 1005;
+ public const int SystemLimits = 1037;
+ public const int SubscriptionRouteMode = 1040;
+ public const int SubscriptionActive = 1041;
+ public const int Legitimate = 1846;
+ public const int SubscriptionReferenceList = 1048;
+ public const int SubscriptionCycleTime = 1049;
+ public const int SubscriptionDelayTime = 1050;
+ public const int SubscriptionDisabled = 1051;
+ public const int SubscriptionCount = 1052;
+ public const int SubscriptionCreditLimit = 1053;
+ public const int SubscriptionTicks = 1054;
+ public const int FreeItems = 1081;
+ public const int SubscriptionFunctionClassId = 1082;
+ public const int Filter = 1246;
+ public const int FilterOperation = 1247;
+ public const int AddressCount = 1249;
+ public const int Address = 1250;
+ public const int FilterValue = 1251;
+ public const int ObjectQualifier = 1256;
+ public const int ParentRID = 1257;
+ public const int CompositionAID = 1258;
+ public const int KeyQualifier = 1259;
+ public const int TI_TComSize = 1502;
+ public const int EffectiveProtectionLevel = 1842;
+ public const int ActiveProtectionLevel = 1843;
+ public const int CPUexecUnit_operatingStateReq = 2167;
public const int ASRoot_ItsFolders = 2468;
- public const int PLCProgram_Class_Rid = 2520;
+ public const int PLCProgram_Class_Rid = 2520;
public const int Block_BlockNumber = 2521;
public const int Block_AutoNumbering = 2522;
public const int Block_BlockLanguage = 2523;
@@ -96,13 +97,13 @@ public static class Ids
public const int Block_FunctionalSignature = 7589;
public const int Block_AdditionalMAC = 7831;
public const int Block_FailsafeBlockInfo = 7843;
- public const int Block_FailsafeIFRHash = 7955;
- public const int ASObjectES_IdentES = 2449;
+ public const int Block_FailsafeIFRHash = 7955;
+ public const int ASObjectES_IdentES = 2449;
public const int Block_BodyDescription = 2533;
- public const int DataInterface_InterfaceDescription = 2544;
- public const int DataInterface_LineComments = 2546;
- public const int DB_ValueInitial = 2548;
- public const int DB_ValueActual = 2550;
+ public const int DataInterface_InterfaceDescription = 2544;
+ public const int DataInterface_LineComments = 2546;
+ public const int DB_ValueInitial = 2548;
+ public const int DB_ValueActual = 2550;
public const int DB_InitialChanged = 2551;
public const int DB_Class_Rid = 2574;
public const int FB_Class_Rid = 2578;
@@ -113,72 +114,73 @@ public static class Ids
public const int FunctionalObject_intRefData = 2583;
public const int FunctionalObject_NetworkComments = 2584;
public const int FunctionalObject_NetworkTitles = 2585;
- public const int FunctionalObject_CalleeList = 2586;
- public const int FunctionalObject_InterfaceSignature = 2587;
- public const int FunctionalObject_DisplayInfo = 2588;
- public const int FunctionalObject_DebugInfo = 2589;
- public const int FunctionalObject_LocalErrorhandling = 2590;
- public const int FunctionalObject_LongConstants = 2591;
+ public const int FunctionalObject_CalleeList = 2586;
+ public const int FunctionalObject_InterfaceSignature = 2587;
+ public const int FunctionalObject_DisplayInfo = 2588;
+ public const int FunctionalObject_DebugInfo = 2589;
+ public const int FunctionalObject_LocalErrorhandling = 2590;
+ public const int FunctionalObject_LongConstants = 2591;
public const int FunctionalObject_Class_Rid = 2592;
- public const int OB_StartInfoType = 2607;
- public const int OB_Class_Rid = 2610;
- public const int AlarmSubscriptionRef_AlarmDomain = 2659;
- public const int AlarmSubscriptionRef_itsAlarmSubsystem = 2660;
- public const int AlarmSubscriptionRef_Class_Rid = 2662;
- public const int DAI_CPUAlarmID = 2670;
- public const int DAI_AllStatesInfo = 2671;
- public const int DAI_AlarmDomain = 2672;
- public const int DAI_Coming = 2673;
- public const int DAI_Going = 2677;
- public const int DAI_Class_Rid = 2681;
- public const int DAI_AlarmTexts_Rid = 2715;
- public const int AS_CGS_AllStatesInfo = 3474;
- public const int AS_CGS_Timestamp = 3475;
- public const int AS_CGS_AssociatedValues = 3476;
- public const int AS_CGS_AckTimestamp = 3646;
- public const int ControllerArea_ValueInitial = 3735;
- public const int ControllerArea_ValueActual = 3736;
+ public const int OB_StartInfoType = 2607;
+ public const int OB_Class_Rid = 2610;
+ public const int AlarmSubscriptionRef_AlarmDomain = 2659;
+ public const int AlarmSubscriptionRef_itsAlarmSubsystem = 2660;
+ public const int AlarmSubscriptionRef_Class_Rid = 2662;
+ public const int AlarmSubsystem_itsUpdateRelevantDAI = 2667;
+ public const int DAI_CPUAlarmID = 2670;
+ public const int DAI_AllStatesInfo = 2671;
+ public const int DAI_AlarmDomain = 2672;
+ public const int DAI_Coming = 2673;
+ public const int DAI_Going = 2677;
+ public const int DAI_Class_Rid = 2681;
+ public const int DAI_AlarmTexts_Rid = 2715;
+ public const int AS_CGS_AllStatesInfo = 3474;
+ public const int AS_CGS_Timestamp = 3475;
+ public const int AS_CGS_AssociatedValues = 3476;
+ public const int AS_CGS_AckTimestamp = 3646;
+ public const int ControllerArea_ValueInitial = 3735;
+ public const int ControllerArea_ValueActual = 3736;
public const int ControllerArea_RuntimeModified = 3737;
- public const int UDT_Class_Rid = 3932;
+ public const int UDT_Class_Rid = 3932;
public const int DAI_MessageType = 4079;
- public const int ConstantsGlobal_Symbolics = 4275;
- public const int ASObjectES_Comment = 4288;
- public const int AlarmSubscriptionRef_AlarmDomain2 = 7731;
- public const int DAI_HmiInfo = 7813;
- public const int MultipleSTAI_Class_Rid = 7854;
- public const int MultipleSTAI_STAIs = 7859;
- public const int DAI_SequenceCounter = 7917;
- public const int AlarmSubscriptionRef_AlarmTextLanguages_Rid = 8181;
- public const int AlarmSubscriptionRef_SendAlarmTexts_Rid = 8173;
- public const int ReturnValue = 40305;
- public const int LID_LegitimationPayloadStruct = 40400;
- public const int LID_LegitimationPayloadType = 40401;
- public const int LID_LegitimationPayloadUsername = 40402;
- public const int LID_LegitimationPayloadPassword = 40403;
-
- public const uint ReleaseMngmtRoot_Rid = 2303328256;
-
- public const uint Constants = 0x8a110000;
-
- public const int TI_BOOL = 0x02000000 + 1;
- public const int TI_BYTE = 0x02000000 + 2;
- public const int TI_CHAR = 0x02000000 + 3;
- public const int TI_WORD = 0x02000000 + 4;
- public const int TI_INT = 0x02000000 + 5;
- public const int TI_DWORD = 0x02000000 + 6;
- public const int TI_DINT = 0x02000000 + 7;
- public const int TI_REAL = 0x02000000 + 8;
- public const int TI_STRING = 0x02000000 + 19;
- public const int TI_LREAL = 0x02000000 + 48;
- public const int TI_USINT = 0x02000000 + 52;
- public const int TI_UINT = 0x02000000 + 53;
- public const int TI_UDINT = 0x02000000 + 54;
- public const int TI_SINT = 0x02000000 + 55;
- public const int TI_WCHAR = 0x02000000 + 61;
- public const int TI_WSTRING = 0x02000000 + 62;
- public const int TI_STRING_START = 0x020a0000; // Start for String[0]
- public const int TI_STRING_END = 0x020affff; // End (String[65535])
- public const int TI_WSTRING_START = 0x020b0000; // Start for WString[0]
- public const int TI_WSTRING_END = 0x020bffff; // End (WString[65535])
- }
-}
+ public const int ConstantsGlobal_Symbolics = 4275;
+ public const int ASObjectES_Comment = 4288;
+ public const int AlarmSubscriptionRef_AlarmDomain2 = 7731;
+ public const int DAI_HmiInfo = 7813;
+ public const int MultipleSTAI_Class_Rid = 7854;
+ public const int MultipleSTAI_STAIs = 7859;
+ public const int DAI_SequenceCounter = 7917;
+ public const int AlarmSubscriptionRef_AlarmTextLanguages_Rid = 8181;
+ public const int AlarmSubscriptionRef_SendAlarmTexts_Rid = 8173;
+ public const int ReturnValue = 40305;
+ public const int LID_LegitimationPayloadStruct = 40400;
+ public const int LID_LegitimationPayloadType = 40401;
+ public const int LID_LegitimationPayloadUsername = 40402;
+ public const int LID_LegitimationPayloadPassword = 40403;
+
+ public const uint ReleaseMngmtRoot_Rid = 2303328256;
+
+ public const uint Constants = 0x8a110000;
+
+ public const int TI_BOOL = 0x02000000 + 1;
+ public const int TI_BYTE = 0x02000000 + 2;
+ public const int TI_CHAR = 0x02000000 + 3;
+ public const int TI_WORD = 0x02000000 + 4;
+ public const int TI_INT = 0x02000000 + 5;
+ public const int TI_DWORD = 0x02000000 + 6;
+ public const int TI_DINT = 0x02000000 + 7;
+ public const int TI_REAL = 0x02000000 + 8;
+ public const int TI_STRING = 0x02000000 + 19;
+ public const int TI_LREAL = 0x02000000 + 48;
+ public const int TI_USINT = 0x02000000 + 52;
+ public const int TI_UINT = 0x02000000 + 53;
+ public const int TI_UDINT = 0x02000000 + 54;
+ public const int TI_SINT = 0x02000000 + 55;
+ public const int TI_WCHAR = 0x02000000 + 61;
+ public const int TI_WSTRING = 0x02000000 + 62;
+ public const int TI_STRING_START = 0x020a0000; // Start for String[0]
+ public const int TI_STRING_END = 0x020affff; // End (String[65535])
+ public const int TI_WSTRING_START = 0x020b0000; // Start for WString[0]
+ public const int TI_WSTRING_END = 0x020bffff; // End (WString[65535])
+ }
+}
diff --git a/src/S7CommPlusDriver/Legitimation/Legitimation.cs b/src/S7CommPlusDriver/Legitimation/Legitimation.cs
index 41e97c7..2597d7c 100644
--- a/src/S7CommPlusDriver/Legitimation/Legitimation.cs
+++ b/src/S7CommPlusDriver/Legitimation/Legitimation.cs
@@ -8,8 +8,9 @@
using System.Text.RegularExpressions;
using System.Threading.Tasks;
-namespace S7CommPlusDriver {
- public partial class S7CommPlusConnection
+namespace S7CommPlusDriver
+{
+ public partial class S7CommPlusConnection
{
private byte[] omsSecret;
@@ -23,23 +24,55 @@ public partial class S7CommPlusConnection
/// error code (0 = ok)
private int legitimate(ValueStruct serverSession, string password, string username = "")
{
+ // S7-1214C (6ES7 214-1AG40-0XB0) 1;6ES7 214-1AG40-0XB0 ;V4.5
+ // S7-1510SP (6ES7 510-1DJ01-0AB0) 1;6ES7 510-1DJ01-0AB0;V2.9
+ // S7-1507SF (6ES7 672-7FC01-0YA0) 1;6ES7 672-7FC01-0YA0;V21.9
+
// Parse device and firmware version
+ // doc: https://cache.industry.siemens.com/dl/files/068/109769068/att_1329908/v4/109769068_UsingCertificatesWithTIAPortal_DOC_V2_1_en.pdf
+ // Certificates in the scope of PG/PC and HMI communication
+ // Starting with TIA Portal V17, PG / PC and HMI communication is secured with TLS, protecting the data exchanged between
+ // Field PGs and HMIs with SIMATIC CPUs.
+ // The CPU families that support Secure PG / HMI communication are:
+ // • S7 - 1500 controllers as of firmware version V2.9.
+ // • S7 - 1200 controllers as of firmware version V4.5.
+ // • Software controllers as of firmware version V21.9.
+ // • SIMATIC Drive controllers as of firmware version V2.9.
+ // • PLCSim and PLCSim Advanced Version V4.0.
+ // HMI components that support Secure PG/ HMI communication, as of image version V17, are:
+ // • Panels or PCs configured with WinCC Basic, Comfort and Advanced.
+ // • PCs with WinCC RT Professional.
+ // • WinCC Unified PCs and Comfort Panels.
+ // In addition, SINAMICS RT SW, as of version V6.1, and STARTDRIVE, as of version V17, support secure communication
string sessionVersionPAOMString = ((ValueWString)serverSession.GetStructElement((uint)Ids.LID_SessionVersionSystemPAOMString)).GetValue();
- Regex reVersions = new Regex("^.*;.*[17]\\s?([52]\\d\\d).+;[VS](\\d\\.\\d)$");
+ var reVersions = new Regex(
+ @"^[^;]*;[^;]*[17]\s?(\d{3}).*;[VS](\d{1,2}\.\d+)$",
+ RegexOptions.Compiled | RegexOptions.CultureInvariant | RegexOptions.IgnoreCase
+ );
Match m = reVersions.Match(sessionVersionPAOMString);
if (!m.Success)
{
Console.WriteLine("S7CommPlusConnection - Legitimate: Could not extract firmware version!");
return S7Consts.errCliFirmwareNotSupported;
}
- string deviceVersion = m.Groups[1].Value;
- string firmwareVersion = m.Groups[2].Value;
- int fwVerNo = int.Parse(firmwareVersion.Split('.')[0]) * 100;
- fwVerNo += int.Parse(firmwareVersion.Split('.')[1]);
+ string deviceVersion = m.Groups[1].Value; // e.g., "672"
+ string firmwareVersion = m.Groups[2].Value; // e.g., "21.9"
+
+ // Compute fwVerNo = major*100 + minor (e.g., "21.9" -> 2109)
+ int fwVerNo;
+ {
+ var parts = firmwareVersion.Split('.');
+ if (parts.Length < 2 || !int.TryParse(parts[0], out var major) || !int.TryParse(parts[1], out var minor))
+ {
+ Console.WriteLine($"S7CommPlusConnection - Legitimate: Invalid firmware format: {firmwareVersion}");
+ return S7Consts.errCliFirmwareNotSupported;
+ }
+ fwVerNo = (major * 100) + minor;
+ }
// Check if we have to use legacy legitimation via the firmware version
bool legacyLegitimation = false;
- if (deviceVersion.StartsWith("5"))
+ if (deviceVersion.StartsWith("5")) // S7-1500 (5xx)
{
if (fwVerNo < 209)
{
@@ -51,7 +84,11 @@ private int legitimate(ValueStruct serverSession, string password, string userna
legacyLegitimation = true;
}
}
- else if (deviceVersion.StartsWith("2"))
+ else if (sessionVersionPAOMString.Contains("50-0XB0") && deviceVersion.StartsWith("2")) //New S7-1200 G2 (example: "1;6ES7 212-1HG50-0XB0;V1.0")
+ {
+ legacyLegitimation = false;
+ }
+ else if (deviceVersion.StartsWith("2")) // S7-1200 (2xx)
{
if (fwVerNo < 403)
{
@@ -63,6 +100,15 @@ private int legitimate(ValueStruct serverSession, string password, string userna
legacyLegitimation = true;
}
}
+ else if (deviceVersion.StartsWith("6")) // S7-1507S (6xx)
+ {
+ if (fwVerNo < 2109)
+ {
+ Console.WriteLine("S7CommPlusConnection - Legitimate: Firmware version is not supported!");
+ return S7Consts.errCliFirmwareNotSupported;
+ }
+ legacyLegitimation = true;
+ }
else
{
Console.WriteLine("S7CommPlusConnection - Legitimate: Device version is not supported!");
diff --git a/src/S7CommPlusDriver/S7CommPlusConnection.cs b/src/S7CommPlusDriver/S7CommPlusConnection.cs
index 25737f8..853bfc8 100644
--- a/src/S7CommPlusDriver/S7CommPlusConnection.cs
+++ b/src/S7CommPlusDriver/S7CommPlusConnection.cs
@@ -1,4 +1,4 @@
-#region License
+#region License
/******************************************************************************
* S7CommPlusDriver
*
@@ -1080,9 +1080,17 @@ private PlcTag browsePlcTagBySymbol(uint ti_relid, ref string symbol, VarInfo va
if (idx < 0) return null;
PVartypeListElement varType = pObj.VartypeList.Elements[idx];
varInfo.AccessSequence += "." + String.Format("{0:X}", varType.LID);
+ bool is1Dim = false;
if (varType.OffsetInfoType.Is1Dim())
{
- calcAccessSeqFor1DimArray(ref symbol, varType, varInfo);
+ if (symbol == "")
+ {
+ is1Dim = true;
+ }
+ else
+ {
+ calcAccessSeqFor1DimArray(ref symbol, varType, varInfo);
+ }
}
if (varType.OffsetInfoType.IsMDim())
{
@@ -1090,6 +1098,10 @@ private PlcTag browsePlcTagBySymbol(uint ti_relid, ref string symbol, VarInfo va
}
if (varType.OffsetInfoType.HasRelation())
{
+ if (symbol.Length <= 0 && varType.Softdatatype == Softdatatype.S7COMMP_SOFTDATATYPE_DTL)
+ {
+ return PlcTags.TagFactory(varInfo.Name, new ItemAddress(varInfo.AccessSequence), varType.Softdatatype, is1Dim);
+ }
if (symbol.Length <= 0)
{
return null;
@@ -1102,7 +1114,7 @@ private PlcTag browsePlcTagBySymbol(uint ti_relid, ref string symbol, VarInfo va
}
else
{
- return PlcTags.TagFactory(varInfo.Name, new ItemAddress(varInfo.AccessSequence), varType.Softdatatype);
+ return PlcTags.TagFactory(varInfo.Name, new ItemAddress(varInfo.AccessSequence), varType.Softdatatype, is1Dim);
}
}