private static GetUInt16 ( GXByteBuffer buff, GXDataInfo info ) : object | ||
buff | GXByteBuffer | ///Received DLMS data. /// |
info | GXDataInfo | ///Data info. /// |
return | object |
/// <summary> /// Reserved for internal use. /// </summary> internal static object GetData(byte[] buff, ref int pos, ActionType action, out int count, out int index, ref DataType type, ref int cachePosition) { count = 0; index = 0; object value = null; if (pos == buff.Length) { pos = -1; return(null); } bool knownType = type != DataType.None; if (!knownType) { type = (DataType)buff[pos++]; } if (type == DataType.None) { return(value); } if (pos == buff.Length) { pos = -1; return(null); } int size = buff.Length - pos; if (type == DataType.Array || type == DataType.Structure) { count = GXCommon.GetObjectCount(buff, ref pos); if (action == ActionType.Count) { return(value); //Don't go further. Only object's count is resolved. } if (cachePosition > pos) { pos = cachePosition; } size = buff.Length - pos; if (count != 0 && size < 1) { pos = -1; return(null); } List <object> arr = new List <object>(count); for (index = 0; index != count; ++index) { DataType itemType = DataType.None; int colCount, colIndex; int tmpPos = 0; object tmp = GetData(buff, ref pos, ActionType.None, out colCount, out colIndex, ref itemType, ref tmpPos); if (colCount == colIndex && pos != -1) { arr.Add(tmp); } if (pos == -1) { break; } else { cachePosition = pos; } } if (index == count && pos != -1) { cachePosition = buff.Length; } value = arr.ToArray(); } else if (type == DataType.Boolean) { value = buff[pos++] != 0; } else if (type == DataType.BitString) { int oldPos = pos; int cnt = GetObjectCount(buff, ref pos); size -= pos - oldPos; double t = cnt; t /= 8; if (cnt % 8 != 0) { ++t; } int byteCnt = (int)Math.Floor(t); if (size < byteCnt) //If there is not enough data available. { pos = -1; return(null); } string str = ""; while (cnt > 0) { str += ToBitString(buff[pos++], cnt); cnt -= 8; } value = str; } else if (type == DataType.Int32) { if (size < 4) //If there is not enough data available. { pos = -1; return(null); } value = GXCommon.GetInt32(buff, ref pos); } else if (type == DataType.UInt32) { if (size < 4) //If there is not enough data available. { pos = -1; return(null); } value = GXCommon.GetUInt32(buff, ref pos); } else if (type == DataType.StringUTF8) { int len = 0; if (knownType) { len = buff.Length; } else { len = GXCommon.GetObjectCount(buff, ref pos); if (buff.Length - pos < len) //If there is not enough data available. { pos = -1; return(null); } } if (len > 0) { value = ASCIIEncoding.UTF8.GetString(GXCommon.RawData(buff, ref pos, len)); } else { value = ""; } } else if (type == DataType.String) { int len = 0; if (knownType) { len = buff.Length; } else { len = GXCommon.GetObjectCount(buff, ref pos); if (buff.Length - pos < len) //If there is not enough data available. { pos = -1; return(null); } } if (len > 0) { bool octetString = false; if (knownType) { //Check that this is not octet string. foreach (byte it in buff) { if (it != 0 && it < 0x20) { octetString = true; break; } } } if (octetString) { StringBuilder sb = new StringBuilder(3 * buff.Length); foreach (byte it in buff) { sb.Append(it); sb.Append('.'); } sb.Remove(sb.Length - 1, 1); value = sb.ToString(); } else { //Remove '\0' from string if used. while (len > 0 && buff[len - 1] == 0) { --len; } value = ASCIIEncoding.ASCII.GetString(GXCommon.RawData(buff, ref pos, len)); } } } //Example Logical name is octet string, so do not change to string... else if (type == DataType.OctetString) { int len = 0; if (knownType) { len = buff.Length; } else { len = GXCommon.GetObjectCount(buff, ref pos); if (buff.Length - pos < len) //If there is not enough data available. { pos = -1; return(null); } } value = GXCommon.RawData(buff, ref pos, len); } else if (type == DataType.BinaryCodedDesimal) { int len; if (knownType) { len = buff.Length; } else { len = GXCommon.GetObjectCount(buff, ref pos); } StringBuilder bcd = new StringBuilder(len * 2); for (int a = 0; a != len; ++a) { int idHigh = buff[pos] >> 4; int idLow = buff[pos] & 0x0F; ++pos; bcd.Append(string.Format("{0}{1}", idHigh, idLow)); } return(bcd.ToString()); } else if (type == DataType.Int8) { value = (sbyte)buff[pos++]; } else if (type == DataType.Int16) { if (size < 2) //If there is not enough data available. { pos = -1; return(null); } value = GXCommon.GetInt16(buff, ref pos); } else if (type == DataType.UInt8) { value = buff[pos++]; } else if (type == DataType.UInt16) { if (size < 2) //If there is not enough data available. { pos = -1; return(null); } value = GXCommon.GetUInt16(buff, ref pos); } else if (type == DataType.CompactArray) { throw new Exception("Invalid data type."); } else if (type == DataType.Int64) { if (size < 8) //If there is not enough data available. { pos = -1; return(null); } value = GXCommon.GetInt64(buff, ref pos); } else if (type == DataType.UInt64) { if (size < 8) //If there is not enough data available. { pos = -1; return(null); } value = GXCommon.GetUInt64(buff, ref pos); } else if (type == DataType.Enum) { if (size < 1) //If there is not enough data available. { pos = -1; return(null); } value = buff[pos++]; } else if (type == DataType.Float32) { if (size < 4) //If there is not enough data available. { pos = -1; return(null); } value = GXCommon.ToFloat(buff, ref pos); } else if (type == DataType.Float64) { if (size < 8) //If there is not enough data available. { pos = -1; return(null); } value = GXCommon.ToDouble(buff, ref pos); } else if (type == DataType.DateTime) { if (size < 12) //If there is not enough data available. { pos = -1; return(null); } GXDateTime dt = new GXDateTime(); //Get year. int year = GXCommon.GetUInt16(buff, ref pos); if (year == 0xFFFF || year == 0) { year = DateTime.MinValue.Year; dt.Skip |= DateTimeSkips.Year; } //Get month int month = buff[pos++]; if (month == 0 || month == 0xFF || month == 0xFE || month == 0xFD) { month = 1; dt.Skip |= DateTimeSkips.Month; } int day = buff[pos++]; if (day < 1 || day == 0xFF) { day = 1; dt.Skip |= DateTimeSkips.Day; } else if (day == 0xFD || day == 0xFE) { day = DateTime.DaysInMonth(year, month) + (sbyte)day + 2; } //Skip week day ++pos; //Get time. int hours = buff[pos++]; if (hours == 0xFF) { hours = 0; dt.Skip |= DateTimeSkips.Hour; } int minutes = buff[pos++]; if (minutes == 0xFF) { minutes = 0; dt.Skip |= DateTimeSkips.Minute; } int seconds = buff[pos++]; if (seconds == 0xFF) { seconds = 0; dt.Skip |= DateTimeSkips.Second; } int milliseconds = buff[pos++]; if (milliseconds != 0xFF && milliseconds != 0) { milliseconds *= 10; } else { milliseconds = 0; dt.Skip |= DateTimeSkips.Ms; } int deviation = GXCommon.GetInt16(buff, ref pos); dt.Status = (ClockStatus)buff[pos++]; if ((deviation & 0xFFFF) != 0x8000 && year != 1) { dt.Value = DateTime.SpecifyKind(new DateTime(year, month, day, hours, minutes, seconds, milliseconds), DateTimeKind.Utc); dt.Value = dt.Value.AddMinutes(deviation); dt.Value = dt.Value.ToLocalTime(); } else //Use current time if deviation is not defined. { dt.Value = new DateTime(year, month, day, hours, minutes, seconds, milliseconds); } value = dt; } else if (type == DataType.Date) { if (size < 5) //If there is not enough data available. { pos = 0xFF; return(null); } //Get year. int year = GXCommon.GetUInt16(buff, ref pos); //IskraEmeco meter returns bytes in wrong order. if (year != 0xFFFF && year > 2100) { pos -= 2; year = buff[pos++] | buff[pos++] << 8; //If Actaris SL 7000 and ACE 6000 returns invalid date. if (year == 0x5C13) { year = -1; } } //Get month int month = buff[pos++]; int day = buff[pos++]; //Skip week day int DayOfWeek = buff[pos++]; //If day of week are not used. GXDateTime dt = new GXDateTime(year, month, day, -1, -1, 1, -1); return(dt); } else if (type == DataType.Time) { if (size < 4) //If there is not enough data available. { pos = -1; return(null); } //Get time. int hours = buff[pos++]; int minutes = buff[pos++]; int seconds = buff[pos++]; int milliseconds = buff[pos++]; GXDateTime dt = new GXDateTime(-1, -1, -1, hours, minutes, seconds, milliseconds); value = dt; } else { throw new Exception("Invalid data type."); } return(value); }
///<summary> ///EncodeData ///</summary> internal void EncodeData(byte[] buff, ref int index) { // Get AARE tag and length int tag = buff[index++]; if (tag != 0x61 && tag != 0x60 && tag != 0x81 && tag != 0x80) { throw new Exception("Invalid tag."); } int len = buff[index++]; int size = buff.Length - index; if (len > size) { throw new Exception("Not enough data."); } while (index < buff.Length) { tag = buff[index]; if (tag == 0xA1) { ApplicationContextName.EncodeData(buff, ref index); } else if (tag == 0xBE) { if (ResultValue != AssociationResult.Accepted && ResultDiagnosticValue != SourceDiagnostic.None) { return; } UserInformation.EncodeData(buff, ref index); } else if (tag == 0xA2) //Result { tag = buff[index++]; len = buff[index++]; //Choice for result (INTEGER, universal) tag = buff[index++]; len = buff[index++]; ResultValue = (AssociationResult)buff[index++]; } else if (tag == 0xA3) //SourceDiagnostic { tag = buff[index++]; len = buff[index++]; // ACSE service user tag. tag = buff[index++]; len = buff[index++]; // Result source diagnostic component. tag = buff[index++]; len = buff[index++]; ResultDiagnosticValue = (SourceDiagnostic)buff[index++]; } else if (tag == 0x8A || tag == 0x88) //Authentication. { tag = buff[index++]; //Get sender ACSE-requirements field component. if (buff[index++] != 2) { throw new Exception("Invalid tag."); } int val = GXCommon.GetUInt16(buff, ref index); if (val != 0x0780 && val != 0x0680) { throw new Exception("Invalid tag."); } } else if (tag == 0xAA) //Server Challenge. { tag = buff[index++]; len = buff[index++]; ++index; len = buff[index++]; //Get challenge and save it to the PW. Password = new byte[len]; Array.Copy(buff, index, Password, 0, len); index += len; } else if (tag == 0xAC) //Password. { tag = buff[index++]; len = buff[index++]; //Get authentication information. if (buff[index++] != 0x80) { throw new Exception("Invalid tag."); } len = buff[index++]; //Get password. Password = new byte[len]; Array.Copy(buff, index, Password, 0, len); index += len; } else if (tag == 0x8B || tag == 0x89) //Authentication. { tag = buff[index++]; len = buff[index++]; if (buff[index++] != 0x60) { throw new Exception("Invalid tag."); } if (buff[index++] != 0x85) { throw new Exception("Invalid tag."); } if (buff[index++] != 0x74) { throw new Exception("Invalid tag."); } if (buff[index++] != 0x05) { throw new Exception("Invalid tag."); } if (buff[index++] != 0x08) { throw new Exception("Invalid tag."); } if (buff[index++] != 0x02) { throw new Exception("Invalid tag."); } int tmp = buff[index++]; if (tmp < 0 || tmp > 5) { throw new Exception("Invalid tag."); } Authentication = (Authentication)tmp; } //Unknown tags. else { tag = buff[index++]; len = buff[index++]; if (Tags != null) { GXDLMSTag tmp = new GXDLMSTag(); tmp.ID = tag; tmp.Data = new byte[len]; tmp.Data = GXCommon.Swap(buff, index, len); Tags.Add(tmp); } index += len; } } }