///<summary> ///Retrieves the string that indicates the level of authentication, if any. ///</summary> internal void GetAuthenticationString(List <byte> data) { //If authentication is used. if (this.Authentication != Authentication.None) { //Add sender ACSE-requirements field component. data.Add(0x8A); data.Add(2); GXCommon.SetUInt16(0x0780, data); data.Add(0x8B); data.Add(7); byte[] p = { (byte)0x60, (byte)0x85, (byte)0x74, (byte)0x05, (byte)0x08, (byte)0x02, (byte)this.Authentication }; data.AddRange(p); //Add Calling authentication information. int len = 0; if (Password != null) { len = Password.Length; } data.Add(0xAC); data.Add((byte)(2 + len)); //Add authentication information. data.Add((byte)0x80); data.Add((byte)len); if (len != 0) { data.AddRange(Password); } } }
/// <summary> /// Reserved for internal use. /// </summary> /// <param name="buff"></param> /// <param name="type"></param> /// <param name="value"></param> public static void SetData(List <byte> buff, DataType type, object value) { bool reverse = true; List <byte> tmp = new List <byte>(); //If byte array is added do not add type. if ((type == DataType.Array || type == DataType.Structure) && value is byte[]) { buff.AddRange((byte[])value); return; } if (type == DataType.None) { value = null; } else if (type == DataType.Boolean) { value = (byte)(Convert.ToBoolean(value) ? 1 : 0); } else if (type == DataType.BitString) { byte val = 0; int index = 0; if (value is string) { string str = value as string; SetObjectCount(str.Length, tmp); foreach (char it in str) { if (it == '1') { val |= (byte)(1 << index++); } else if (it == '0') { index++; } else { throw new ArgumentException("Not a bit string."); } if (index == 8) { index = 0; tmp.Add(val); val = 0; } } if (index != 0) { tmp.Add(val); } value = tmp.ToArray(); reverse = false; } else if (value is byte[]) { byte[] arr = value as byte[]; SetObjectCount(arr.Length, tmp); tmp.AddRange(arr); value = tmp.ToArray(); reverse = false; } else if (value is bool[]) { bool[] arr = value as bool[]; SetObjectCount(arr.Length, tmp); foreach (bool it in arr) { if (it) { val |= (byte)(1 << index++); } else { ++index; } if (index == 8) { index = 0; tmp.Add(val); val = 0; } } if (index != 0) { tmp.Add(val); } value = tmp.ToArray(); reverse = false; } else if (value == null) { tmp.Add(0); value = tmp.ToArray(); reverse = false; } else { throw new Exception("BitString must give as string."); } } else if (type == DataType.Int32) { value = Convert.ToInt32(value); } else if (type == DataType.UInt32) { value = Convert.ToUInt32(value); } else if (type == DataType.String) { if (value != null) { string str = value.ToString(); SetObjectCount(str.Length, tmp); tmp.AddRange(ASCIIEncoding.ASCII.GetBytes(str)); } else { SetObjectCount(0, tmp); } value = tmp.ToArray(); reverse = false; } else if (type == DataType.StringUTF8) { if (value != null) { string str = value.ToString(); byte[] tmp1 = ASCIIEncoding.UTF8.GetBytes(str); SetObjectCount(tmp1.Length, tmp); tmp.AddRange(tmp1); } else { SetObjectCount(0, tmp); } value = tmp.ToArray(); reverse = false; } else if (type == DataType.Array || type == DataType.Structure) { if (value != null) { Array arr = (Array)value; SetObjectCount(arr.Length, tmp); foreach (object it in arr) { SetData(tmp, GetValueType(it), it); } } else { SetObjectCount(0, tmp); } value = tmp.ToArray(); reverse = false; } else if (type == DataType.OctetString) { reverse = false; if (value is string) { if ((value as string) == "") { SetObjectCount(0, tmp); value = tmp.ToArray(); } else { string[] items = (value as string).Split('.'); tmp.Clear(); SetObjectCount(items.Length, tmp); foreach (string it in items) { tmp.Add(byte.Parse(it)); } value = tmp.ToArray(); } } else if (value == null) { SetObjectCount(0, tmp); value = tmp.ToArray(); } else if (value is byte[]) { SetObjectCount((value as byte[]).Length, tmp); tmp.AddRange(value as byte[]); value = tmp.ToArray(); } else if (value is GXDateTime) { value = GetDateTime(value as GXDateTime); } else if (value is DateTime) { value = GetDateTime(new GXDateTime(Convert.ToDateTime(value))); } else { value = Convert.ToString(value); } } else if (type == DataType.BinaryCodedDesimal) { if (!(value is string)) { throw new Exception("BCD value must give as string."); } string str = value.ToString().Trim(); int len = str.Length; if (len % 2 != 0) { str = "0" + str; ++len; } len /= 2; List <byte> val = new List <byte>(len); val.Add((byte)(len)); for (int pos = 0; pos != len; ++pos) { byte ch1 = byte.Parse(str.Substring(2 * pos, 1)); byte ch2 = byte.Parse(str.Substring(2 * pos + 1, 1)); val.Add((byte)(ch1 << 4 | ch2)); } reverse = false; value = val.ToArray(); } else if (type == DataType.Int8) { value = Convert.ToSByte(value); } else if (type == DataType.Int16) { value = (short)Convert.ToInt32(value); } else if (type == DataType.UInt8) { value = Convert.ToByte(value); } else if (type == DataType.UInt16) { value = Convert.ToUInt16(value); } else if (type == DataType.CompactArray) { throw new Exception("Invalid data type."); } else if (type == DataType.Int64) { value = Convert.ToInt64(value); } else if (type == DataType.UInt64) { value = Convert.ToUInt64(value); } else if (type == DataType.Enum) { value = Convert.ToByte(value); } else if (type == DataType.Float32) { value = Convert.ToSingle(value); } else if (type == DataType.Float64) { value = Convert.ToDouble(value); } else if (type == DataType.DateTime) { type = DataType.OctetString; if (value is GXDateTime) { value = GetDateTime(value as GXDateTime); } else { value = GetDateTime(new GXDateTime(Convert.ToDateTime(value))); } reverse = false; } else if (type == DataType.Date) { GXDateTime dt; if (value is GXDateTime) { dt = value as GXDateTime; } else if (value is DateTime) { dt = new GXDateTime((DateTime)value); } else { throw new Exception("Invalid date format."); } type = DataType.OctetString; //Add size tmp.Add(5); //Add year. if ((dt.Skip & DateTimeSkips.Year) != 0) { GXCommon.SetUInt16(0xFFFF, tmp); } else { GXCommon.SetUInt16((ushort)dt.Value.Year, tmp); } //Add month. if (dt.DaylightSavingsBegin) { tmp.Add(0xFE); } else if (dt.DaylightSavingsEnd) { tmp.Add(0xFD); } else if ((dt.Skip & DateTimeSkips.Month) != 0) { tmp.Add(0xFF); } else { tmp.Add((byte)dt.Value.Month); } if ((dt.Skip & DateTimeSkips.Day) != 0) { tmp.Add(0xFF); } else { tmp.Add((byte)dt.Value.Day); } //Week day is not spesified. tmp.Add(0xFF); value = tmp.ToArray(); reverse = false; } else if (type == DataType.Time) { GXDateTime dt; if (value is GXDateTime) { dt = value as GXDateTime; } else if (value is DateTime) { dt = new GXDateTime((DateTime)value); } else { throw new Exception("Invalid date format."); } type = DataType.OctetString; //Add size tmp.Add(4); //Add time. if ((dt.Skip & DateTimeSkips.Hour) != 0) { tmp.Add(0xFF); } else { tmp.Add((byte)dt.Value.Hour); } if ((dt.Skip & DateTimeSkips.Minute) != 0) { tmp.Add(0xFF); } else { tmp.Add((byte)dt.Value.Minute); } if ((dt.Skip & DateTimeSkips.Second) != 0) { tmp.Add(0xFF); } else { tmp.Add((byte)dt.Value.Second); } tmp.Add((byte)0xFF); //Hundredths of second is not used. value = tmp.ToArray(); reverse = false; } else { throw new Exception("Invalid data type."); } buff.Add((byte)type); if (value != null) { byte[] data = Gurux.Shared.GXCommon.GetAsByteArray(value); if (reverse) { Array.Reverse(data); } buff.AddRange(data); } }
static byte[] GetDateTime(GXDateTime dt) { if (dt.Value == DateTime.MinValue) { dt.Value = DateTime.SpecifyKind(new DateTime(2000, 1, 1).Date, DateTimeKind.Utc); } else if (dt.Value == DateTime.MaxValue) { dt.Value = DateTime.SpecifyKind(DateTime.Now.AddYears(1).Date, DateTimeKind.Utc); } DateTime tm; //If used normal time. if ((dt.Skip & DateTimeSkips.Devitation) == 0) { tm = dt.Value; } else //If devitation is skipped. { //If value is given as UTC time. if (TimeZone.CurrentTimeZone.GetUtcOffset(dt.Value).TotalMinutes == 0) { tm = dt.Value; } else { tm = dt.Value.ToUniversalTime(); } } List <byte> tmp = new List <byte>(); //Add size tmp.Add(12); if ((dt.Skip & DateTimeSkips.Year) == 0) { GXCommon.SetUInt16((ushort)tm.Year, tmp); } else { GXCommon.SetUInt16((ushort)0xFFFF, tmp); } if ((dt.Skip & DateTimeSkips.Month) == 0) { if (dt.DaylightSavingsBegin) { tmp.Add(0xFE); } else if (dt.DaylightSavingsEnd) { tmp.Add(0xFD); } else { tmp.Add((byte)tm.Month); } } else { tmp.Add(0xFF); } if ((dt.Skip & DateTimeSkips.Day) == 0) { tmp.Add((byte)tm.Day); } else { tmp.Add(0xFF); } //Week day is not spesified. //Standard defines. tmp.Add(0xFF); tmp.Add(0xFF); //Add time. if ((dt.Skip & DateTimeSkips.Hour) == 0) { tmp.Add((byte)tm.Hour); } else { tmp.Add(0xFF); } if ((dt.Skip & DateTimeSkips.Minute) == 0) { tmp.Add((byte)tm.Minute); } else { tmp.Add(0xFF); } if ((dt.Skip & DateTimeSkips.Second) == 0) { tmp.Add((byte)tm.Second); } else { tmp.Add(0xFF); } if ((dt.Skip & DateTimeSkips.Ms) == 0) { tmp.Add((byte)(tm.Millisecond / 10)); } else { tmp.Add((byte)0xFF); //Hundredths of second is not used. } //Add deviation. if ((dt.Skip & DateTimeSkips.Devitation) == 0) { short devitation = (short)TimeZone.CurrentTimeZone.GetUtcOffset(dt.Value).TotalMinutes; GXCommon.SetInt16(devitation, tmp); } else //deviation not used. { tmp.Add((byte)0x00); tmp.Add((byte)0x00); } //Add clock_status tmp.Add((byte)dt.Status); return(tmp.ToArray()); }
///<summary> ///Server generates AARE message. ///</summary> internal void GenerateAARE(List <byte> data, Authentication authentication, byte[] challenge, ushort maxReceivePDUSize, byte[] conformanceBlock, AssociationResult result, SourceDiagnostic diagnostic) { // Set AARE tag and length data.Add(0x61); ApplicationContextName.CodeData(data); //Result data.Add(0xA2); data.Add(3); //len data.Add(2); //Tag //Choice for result (INTEGER, universal) data.Add(1); //Len data.Add((byte)result); //ResultValue //SourceDiagnostic data.Add(0xA3); data.Add(5); //len data.Add(0xA1); //Tag data.Add(3); //len data.Add(2); //Tag //Choice for result (INTEGER, universal) data.Add(1); //Len data.Add((byte)diagnostic); //diagnostic if (diagnostic == SourceDiagnostic.AuthenticationRequired) { //Add server ACSE-requirenents field component. data.Add(0x88); data.Add(0x02); //Len. GXCommon.SetUInt16(0x0780, data); //Add tag. data.Add(0x89); data.Add(0x07);//Len data.Add(0x60); data.Add(0x85); data.Add(0x74); data.Add(0x05); data.Add(0x08); data.Add(0x02); data.Add((byte)authentication); //Add tag. data.Add(0xAA); data.Add((byte)(2 + challenge.Length)); //Len data.Add(0x80); data.Add((byte)challenge.Length); data.AddRange(challenge); } //Add User Information data.Add(0xBE); //Tag data.Add(0x10); //Length for AARQ user field data.Add(0x04); //Coding the choice for user-information (Octet STRING, universal) data.Add(0xE); //Length data.Add(GXCommon.InitialResponce); // Tag for xDLMS-Initiate response data.Add(0x00); // Usage field for the response allowed component (not used) data.Add(6); // DLMSVersioNumber data.Add(0x5F); data.Add(0x1F); data.Add(0x04); // length of the conformance block data.Add(0x00); // encoding the number of unused bits in the bit string data.AddRange(conformanceBlock); GXCommon.SetUInt16(maxReceivePDUSize, data); //VAA Name VAA name (0x0007 for LN referencing and 0xFA00 for SN) if (UseLN) { GXCommon.SetUInt16(0x0007, data); } else { GXCommon.SetUInt16(0xFA00, data); } data.Insert(1, (byte)(data.Count - 1)); }