/// <summary> /// Constructor. /// </summary> /// <param name="forTarget"></param> /// <param name="forCommand"></param> /// <param name="forType"></param> public GXDLMSLongTransaction(ValueEventArgs[] forTargets, Command forCommand, GXByteBuffer forData) { targets = forTargets; command = forCommand; data = new GXByteBuffer(); data.Set(forData.Data, forData.Position, forData.Size - forData.Position); }
internal static void SetValue(GXByteBuffer buff, object data) { GXByteBuffer tmp = new GXByteBuffer(); tmp.Add(data); buff.Add((byte)tmp.Size); buff.Set(tmp.Array()); }
///<summary> ///Retrieves the string that indicates the level of authentication, if any. ///</summary> private static void GetAuthenticationString(GXDLMSSettings settings, GXByteBuffer data) { //If authentication is used. if (settings.Authentication != Authentication.None) { //Add sender ACSE-requirements field component. data.SetUInt8((byte)BerType.Context | (byte)PduType.SenderAcseRequirements); data.SetUInt8(2); data.SetUInt8(BerType.BitString | BerType.OctetString); data.SetUInt8(0x80); data.SetUInt8((byte)BerType.Context | (byte)PduType.MechanismName); //Len data.SetUInt8(7); // OBJECT IDENTIFIER byte[] p = { (byte)0x60, (byte)0x85, (byte)0x74, (byte)0x05, (byte)0x08, (byte)0x02, (byte)settings.Authentication }; data.Set(p); //Add Calling authentication information. int len = 0; byte[] callingAuthenticationValue = null; if (settings.Authentication == Authentication.Low) { if (settings.Password != null) { callingAuthenticationValue = settings.Password; len = callingAuthenticationValue.Length; } } else { callingAuthenticationValue = settings.CtoSChallenge; len = callingAuthenticationValue.Length; } //0xAC data.SetUInt8((byte)BerType.Context | (byte)BerType.Constructed | (byte)PduType.CallingAuthenticationValue); //Len data.SetUInt8((byte)(2 + len)); //Add authentication information. data.SetUInt8((byte)BerType.Context); //Len. data.SetUInt8((byte)len); if (len != 0) { data.Set(callingAuthenticationValue); } } }
///<summary> ///Convert ASCII string to DLMS bytes. ///</summary> ///<param name="buff"> ///Byte buffer where data is write. ///</param> ///<param name="value"> ///Added value. ///</param> private static void SetString(GXByteBuffer buff, object value) { if (value != null) { string str = Convert.ToString(value); SetObjectCount(str.Length, buff); buff.Set(ASCIIEncoding.ASCII.GetBytes(str)); } else { buff.SetUInt8(0); } }
object IGXDLMSBase.GetValue(GXDLMSSettings settings, int index, int selector, object parameters) { if (index == 1) { return(this.LogicalName); } if (index == 2) { return(GetObjects()); } if (index == 3) { GXByteBuffer data = new GXByteBuffer(); data.SetUInt8((byte)DataType.Array); //Add count data.SetUInt8(2); data.SetUInt8((byte)DataType.UInt8); data.SetUInt16(ClientSAP); data.SetUInt8((byte)DataType.UInt16); data.SetUInt16(ServerSAP); return(data.Array()); } if (index == 4) { GXByteBuffer data = new GXByteBuffer(); data.SetUInt8((byte)DataType.Structure); //Add count data.SetUInt8(0x7); GXCommon.SetData(data, DataType.UInt8, ApplicationContextName.JointIsoCtt); GXCommon.SetData(data, DataType.UInt8, ApplicationContextName.Country); GXCommon.SetData(data, DataType.UInt16, ApplicationContextName.CountryName); GXCommon.SetData(data, DataType.UInt8, ApplicationContextName.IdentifiedOrganization); GXCommon.SetData(data, DataType.UInt8, ApplicationContextName.DlmsUA); GXCommon.SetData(data, DataType.UInt8, ApplicationContextName.ApplicationContext); GXCommon.SetData(data, DataType.UInt8, ApplicationContextName.ContextId); return(data.Array()); } if (index == 5) { GXByteBuffer data = new GXByteBuffer(); data.SetUInt8((byte)DataType.Structure); data.SetUInt8(6); GXCommon.SetData(data, DataType.BitString, XDLMSContextInfo.Conformance); GXCommon.SetData(data, DataType.UInt16, XDLMSContextInfo.MaxReceivePduSize); GXCommon.SetData(data, DataType.UInt16, XDLMSContextInfo.MaxSendPpuSize); GXCommon.SetData(data, DataType.UInt8, XDLMSContextInfo.DlmsVersionNumber); GXCommon.SetData(data, DataType.Int8, XDLMSContextInfo.QualityOfService); GXCommon.SetData(data, DataType.OctetString, XDLMSContextInfo.CypheringInfo); return(data.Array()); } if (index == 6) { GXByteBuffer data = new GXByteBuffer(); data.SetUInt8((byte)DataType.Structure); //Add count data.SetUInt8(0x7); GXCommon.SetData(data, DataType.UInt8, AuthenticationMechanismMame.JointIsoCtt); GXCommon.SetData(data, DataType.UInt8, AuthenticationMechanismMame.Country); GXCommon.SetData(data, DataType.UInt16, AuthenticationMechanismMame.CountryName); GXCommon.SetData(data, DataType.UInt8, AuthenticationMechanismMame.IdentifiedOrganization); GXCommon.SetData(data, DataType.UInt8, AuthenticationMechanismMame.DlmsUA); GXCommon.SetData(data, DataType.UInt8, AuthenticationMechanismMame.AuthenticationMechanismName); GXCommon.SetData(data, DataType.UInt8, AuthenticationMechanismMame.MechanismId); return(data.Array()); } if (index == 7) { return(Secret); } if (index == 8) { return(AssociationStatus); } if (index == 9) { if (SecuritySetupReference == null) { return(null); } return(ASCIIEncoding.ASCII.GetBytes(SecuritySetupReference)); } throw new ArgumentException("GetValue failed. Invalid attribute index."); }
object IGXDLMSBase.GetValue(GXDLMSSettings settings, ValueEventArgs e) { if (e.Index == 1) { return(GXCommon.LogicalNameToBytes(LogicalName)); } if (e.Index == 2) { return(GetObjects(settings, e).Array()); } if (e.Index == 3) { GXByteBuffer data = new GXByteBuffer(); data.SetUInt8((byte)DataType.Structure); //Add count data.SetUInt8(2); data.SetUInt8((byte)DataType.Int8); data.SetUInt8(ClientSAP); data.SetUInt8((byte)DataType.UInt16); data.SetUInt16(ServerSAP); return(data.Array()); } if (e.Index == 4) { GXByteBuffer data = new GXByteBuffer(); data.SetUInt8((byte)DataType.Structure); //Add count data.SetUInt8(0x7); GXCommon.SetData(settings, data, DataType.UInt8, ApplicationContextName.JointIsoCtt); GXCommon.SetData(settings, data, DataType.UInt8, ApplicationContextName.Country); GXCommon.SetData(settings, data, DataType.UInt16, ApplicationContextName.CountryName); GXCommon.SetData(settings, data, DataType.UInt8, ApplicationContextName.IdentifiedOrganization); GXCommon.SetData(settings, data, DataType.UInt8, ApplicationContextName.DlmsUA); GXCommon.SetData(settings, data, DataType.UInt8, ApplicationContextName.ApplicationContext); GXCommon.SetData(settings, data, DataType.UInt8, ApplicationContextName.ContextId); return(data.Array()); } if (e.Index == 5) { GXByteBuffer data = new GXByteBuffer(); data.SetUInt8((byte)DataType.Structure); data.SetUInt8(6); GXByteBuffer bb = new GXByteBuffer(); bb.SetUInt32((UInt32)XDLMSContextInfo.Conformance); GXCommon.SetData(settings, data, DataType.BitString, bb.SubArray(1, 3)); GXCommon.SetData(settings, data, DataType.UInt16, XDLMSContextInfo.MaxReceivePduSize); GXCommon.SetData(settings, data, DataType.UInt16, XDLMSContextInfo.MaxSendPduSize); GXCommon.SetData(settings, data, DataType.UInt8, XDLMSContextInfo.DlmsVersionNumber); GXCommon.SetData(settings, data, DataType.Int8, XDLMSContextInfo.QualityOfService); GXCommon.SetData(settings, data, DataType.OctetString, XDLMSContextInfo.CypheringInfo); return(data.Array()); } if (e.Index == 6) { GXByteBuffer data = new GXByteBuffer(); data.SetUInt8((byte)DataType.Structure); //Add count data.SetUInt8(0x7); GXCommon.SetData(settings, data, DataType.UInt8, AuthenticationMechanismName.JointIsoCtt); GXCommon.SetData(settings, data, DataType.UInt8, AuthenticationMechanismName.Country); GXCommon.SetData(settings, data, DataType.UInt16, AuthenticationMechanismName.CountryName); GXCommon.SetData(settings, data, DataType.UInt8, AuthenticationMechanismName.IdentifiedOrganization); GXCommon.SetData(settings, data, DataType.UInt8, AuthenticationMechanismName.DlmsUA); GXCommon.SetData(settings, data, DataType.UInt8, AuthenticationMechanismName.AuthenticationMechanismName); GXCommon.SetData(settings, data, DataType.UInt8, AuthenticationMechanismName.MechanismId); return(data.Array()); } if (e.Index == 7) { return(Secret); } if (e.Index == 8) { return(AssociationStatus); } if (e.Index == 9) { return(GXCommon.LogicalNameToBytes(SecuritySetupReference)); } if (e.Index == 10) { return(GetUserList(settings, e).Array()); } if (e.Index == 11) { GXByteBuffer data = new GXByteBuffer(); data.SetUInt8((byte)DataType.Structure); //Add structure size. data.SetUInt8(2); GXCommon.SetData(settings, data, DataType.UInt8, CurrentUser.Key); GXCommon.SetData(settings, data, DataType.String, CurrentUser.Value); return(data.Array()); } e.Error = ErrorCode.ReadWriteDenied; return(null); }
private void GetAccessRights(GXDLMSSettings settings, GXDLMSObject item, GXByteBuffer data) { data.SetUInt8((byte)DataType.Structure); data.SetUInt8((byte)3); GXCommon.SetData(settings, data, DataType.UInt16, item.ShortName); data.SetUInt8((byte)DataType.Array); data.SetUInt8((byte)item.Attributes.Count); foreach (GXDLMSAttributeSettings att in item.Attributes) { data.SetUInt8((byte)DataType.Structure); //attribute_access_item data.SetUInt8((byte)3); GXCommon.SetData(settings, data, DataType.Int8, att.Index); GXCommon.SetData(settings, data, DataType.Enum, att.Access); GXCommon.SetData(settings, data, DataType.None, null); } data.SetUInt8((byte)DataType.Array); data.SetUInt8((byte)item.MethodAttributes.Count); foreach (GXDLMSAttributeSettings it in item.MethodAttributes) { data.SetUInt8((byte)DataType.Structure); //attribute_access_item data.SetUInt8((byte)2); GXCommon.SetData(settings, data, DataType.Int8, it.Index); GXCommon.SetData(settings, data, DataType.Enum, it.MethodAccess); } }
/// <summary> /// Add ASN1 object to byte buffer. /// </summary> /// <param name="bb">Byte buffer where ANS1 object is serialized. </param> /// <param name="target">ANS1 object </param> /// <returns>Size of object. </returns> private static int GetBytes(GXByteBuffer bb, object target) { GXByteBuffer tmp; string str; int start = bb.Size; int cnt = 0; if (target is GXAsn1Context) { tmp = new GXByteBuffer(); foreach (object it in ((GXAsn1Context)target)) { cnt += GetBytes(tmp, it); } start = bb.Size; bb.SetUInt8(BerType.Constructed | BerType.Context); GXCommon.SetObjectCount(cnt, bb); cnt += bb.Size - start; bb.Set(tmp); return(cnt); } else if (target is object[]) { tmp = new GXByteBuffer(); foreach (object it in (object[])target) { cnt += GetBytes(tmp, it); } start = bb.Size; bb.SetUInt8(BerType.Constructed | BerType.Sequence); GXCommon.SetObjectCount(cnt, bb); cnt += bb.Size - start; bb.Set(tmp); return(cnt); } else if (target is string) { bb.SetUInt8(BerType.PrintableString); GXCommon.SetObjectCount(((string)target).Length, bb); bb.Add(target); } else if (target is sbyte) { bb.SetUInt8((byte)BerType.Integer); GXCommon.SetObjectCount(1, bb); bb.Add(target); } else if (target is short) { bb.SetUInt8((byte)BerType.Integer); GXCommon.SetObjectCount(2, bb); bb.Add(target); } else if (target is int) { bb.SetUInt8((byte)BerType.Integer); GXCommon.SetObjectCount(4, bb); bb.Add(target); } else if (target is GXAsn1Integer) { bb.SetUInt8((byte)BerType.Integer); byte[] b = ((GXAsn1Integer)target).Value; GXCommon.SetObjectCount(b.Length, bb); bb.Add(b); } else if (target is long) { bb.SetUInt8((byte)BerType.Integer); GXCommon.SetObjectCount(8, bb); bb.Add(target); } else if (target is byte[]) { bb.SetUInt8(BerType.OctetString); GXCommon.SetObjectCount(((byte[])target).Length, bb); bb.Add(target); } else if (target == null) { bb.SetUInt8(BerType.Null); GXCommon.SetObjectCount(0, bb); } else if (target is bool) { bb.SetUInt8(BerType.Boolean); bb.SetUInt8(1); if ((bool)target) { bb.SetUInt8(255); } else { bb.SetUInt8(0); } } else if (target is GXAsn1ObjectIdentifier) { bb.SetUInt8(BerType.ObjectIdentifier); byte[] t = ((GXAsn1ObjectIdentifier)target).Encoded; GXCommon.SetObjectCount(t.Length, bb); bb.Add(t); } else if (target is KeyValuePair <object, object> ) { KeyValuePair <object, object> e = (KeyValuePair <object, object>)target; GXByteBuffer tmp2 = new GXByteBuffer(); if (e.Value != null) { tmp = new GXByteBuffer(); cnt += GetBytes(tmp2, e.Key); cnt += GetBytes(tmp2, e.Value); tmp.SetUInt8(BerType.Constructed | BerType.Sequence); GXCommon.SetObjectCount(cnt, tmp); tmp.Set(tmp2); } else { GetBytes(tmp2, (e.Key as List <object>)[0]); tmp = tmp2; } // Update len. cnt = bb.Size; bb.SetUInt8(BerType.Constructed | BerType.Set); GXCommon.SetObjectCount(tmp.Size, bb); bb.Set(tmp); return(bb.Size - cnt); } else if (target is GXAsn1Utf8String) { bb.SetUInt8(BerType.Utf8StringTag); str = target.ToString(); GXCommon.SetObjectCount(str.Length, bb); bb.Add(str); } else if (target is GXAsn1Ia5String) { bb.SetUInt8(BerType.Ia5String); str = target.ToString(); GXCommon.SetObjectCount(str.Length, bb); bb.Add(str); } else if (target is GXAsn1BitString) { GXAsn1BitString bs = (GXAsn1BitString)target; bb.SetUInt8(BerType.BitString); GXCommon.SetObjectCount(1 + bs.Value.Length, bb); bb.SetUInt8((byte)bs.PadBits); bb.Add(bs.Value); } else if (target is GXAsn1PublicKey) { GXAsn1PublicKey bs = (GXAsn1PublicKey)target; bb.SetUInt8(BerType.BitString); // Size is 64 bytes + padding and uncompressed point indicator. GXCommon.SetObjectCount(66, bb); // Add padding. bb.SetUInt8(0); // prefixed with the uncompressed point indicator 04 bb.SetUInt8(4); bb.Add(bs.Value); // Count is type + size + 64 bytes + padding + uncompressed point // indicator. return(68); } else if (target is DateTime) { // Save date time in UTC. bb.SetUInt8(BerType.UtcTime); str = DateToString((DateTime)target); bb.SetUInt8((byte)str.Length); bb.Add(str); } else if (target is GXAsn1Sequence || target is IList) { tmp = new GXByteBuffer(); foreach (object it in (IList)target) { cnt += GetBytes(tmp, it); } start = bb.Size; bb.SetUInt8(BerType.Constructed | BerType.Sequence); GXCommon.SetObjectCount(cnt, bb); cnt += bb.Size - start; bb.Set(tmp); return(cnt); } else { throw new ArgumentException("Invalid type: " + target.GetType().ToString()); } return(bb.Size - start); }
object IGXDLMSBase.GetValue(GXDLMSSettings settings, ValueEventArgs e) { if (e.Index == 1) { return(GXCommon.LogicalNameToBytes(LogicalName)); } if (e.Index == 2) { //If client set new value. if (!settings.IsServer && Scaler != 1 && CurrentAverageValue != null) { Type type = null; if (CurrentAverageValue != null) { type = CurrentAverageValue.GetType(); } object tmp; tmp = Convert.ToDouble(CurrentAverageValue) / Scaler; if (type != null) { tmp = Convert.ChangeType(tmp, type); } return(tmp); } return(CurrentAverageValue); } if (e.Index == 3) { //If client set new value. if (!settings.IsServer && Scaler != 1 && LastAverageValue != null) { DataType dt = base.GetDataType(3); if (dt == DataType.None && LastAverageValue != null) { dt = GXCommon.GetDLMSDataType(LastAverageValue.GetType()); } object tmp; tmp = Convert.ToDouble(LastAverageValue) / Scaler; if (dt != DataType.None) { tmp = Convert.ChangeType(tmp, GXCommon.GetDataType(dt)); } return(tmp); } return(LastAverageValue); } if (e.Index == 4) { GXByteBuffer data = new GXByteBuffer(); data.SetUInt8((byte)DataType.Structure); data.SetUInt8(2); GXCommon.SetData(settings, data, DataType.Int8, scaler); GXCommon.SetData(settings, data, DataType.Enum, Unit); return(data.Array()); } if (e.Index == 5) { return(Status); } if (e.Index == 6) { return(CaptureTime); } if (e.Index == 7) { return(StartTimeCurrent); } if (e.Index == 8) { return(Period); } if (e.Index == 9) { return(NumberOfPeriods); } e.Error = ErrorCode.ReadWriteDenied; return(null); }
///<summary> ///Get data from DLMS frame. ///</summary> ///<param name="settings">DLMS settings.</param> ///<param name="data">Received data.</param> ///<param name="info"> Data info.</param> ///<returns>Parsed object.</returns> /// public static object GetData(GXDLMSSettings settings, GXByteBuffer data, GXDataInfo info) { object value = null; int startIndex = data.Position; if (data.Position == data.Size) { info.Complete = false; return null; } info.Complete = true; bool knownType = info.Type != DataType.None; // Get data type if it is unknown. if (!knownType) { info.Type = (DataType)data.GetUInt8(); } if (info.Type == DataType.None) { if (info.xml != null) { info.xml.AppendLine("<" + info.xml.GetDataType(info.Type) + " />"); } return value; } if (data.Position == data.Size) { info.Complete = false; return null; } switch (info.Type) { case DataType.Array: case DataType.Structure: value = GetArray(data, info, startIndex); break; case DataType.Boolean: value = GetBoolean(data, info); break; case DataType.BitString: value = GetBitString(data, info); break; case DataType.Int32: value = GetInt32(data, info); break; case DataType.UInt32: value = GetUInt32(data, info); break; case DataType.String: value = GetString(data, info, knownType); break; case DataType.StringUTF8: value = GetUtfString(data, info, knownType); break; case DataType.OctetString: value = GetOctetString(data, info, knownType); break; case DataType.Bcd: value = GetBcd(data, info, knownType); break; case DataType.Int8: value = GetInt8(data, info); break; case DataType.Int16: value = GetInt16(data, info); break; case DataType.UInt8: value = GetUInt8(data, info); break; case DataType.UInt16: value = GetUInt16(data, info); break; case DataType.CompactArray: throw new Exception("Invalid data type."); case DataType.Int64: value = GetInt64(data, info); break; case DataType.UInt64: value = GetUInt64(data, info); break; case DataType.Enum: value = GetEnum(data, info); break; case DataType.Float32: value = Getfloat(data, info); break; case DataType.Float64: value = GetDouble(data, info); break; case DataType.DateTime: value = GetDateTime(settings, data, info); break; case DataType.Date: value = GetDate(data, info); break; case DataType.Time: value = GetTime(data, info); break; default: throw new Exception("Invalid data type."); } return value; }
/// <summary> /// Decrypt data. /// </summary> /// <param name="p">Decryption parameters</param> /// <returns>Decrypted data.</returns> public static byte[] DecryptAesGcm(AesGcmParameter p, GXByteBuffer data) { if (data == null || data.Size < 2) { throw new ArgumentOutOfRangeException("cryptedData"); } int len; Command cmd = (Command)data.GetUInt8(); switch (cmd) { case Command.GloGeneralCiphering: len = GXCommon.GetObjectCount(data); p.SystemTitle = new byte[len]; data.Get(p.SystemTitle); break; case Command.GloInitiateRequest: case Command.GloInitiateResponse: case Command.GloReadRequest: case Command.GloReadResponse: case Command.GloWriteRequest: case Command.GloWriteResponse: case Command.GloGetRequest: case Command.GloGetResponse: case Command.GloSetRequest: case Command.GloSetResponse: case Command.GloMethodRequest: case Command.GloMethodResponse: case Command.GloEventNotificationRequest: break; default: throw new ArgumentOutOfRangeException("cryptedData"); } len = Gurux.DLMS.Internal.GXCommon.GetObjectCount(data); p.Security = (Gurux.DLMS.Enums.Security)data.GetUInt8(); p.FrameCounter = data.GetUInt32(); System.Diagnostics.Debug.WriteLine("Decrypt settings: " + p.ToString()); System.Diagnostics.Debug.WriteLine("Encrypted: " + GXCommon.ToHex(data.Array(), true)); byte[] tag = new byte[12]; byte[] encryptedData; int length; if (p.Security == Gurux.DLMS.Enums.Security.Authentication) { length = data.Size - data.Position - 12; encryptedData = new byte[length]; data.Get(encryptedData); data.Get(tag); // Check tag. EncryptAesGcm(p, encryptedData); if (!GXDLMSChipperingStream.TagsEquals(tag, p.CountTag)) { throw new GXDLMSException("Decrypt failed. Invalid tag."); } return encryptedData; } byte[] ciphertext = null; if (p.Security == Gurux.DLMS.Enums.Security.Encryption) { length = data.Size - data.Position; ciphertext = new byte[length]; data.Get(ciphertext); } else if (p.Security == Gurux.DLMS.Enums.Security.AuthenticationEncryption) { length = data.Size - data.Position - 12; ciphertext = new byte[length]; data.Get(ciphertext); data.Get(tag); } byte[] aad = GetAuthenticatedData(p.Security, p.AuthenticationKey, data.Array()); byte[] iv = GetNonse(p.FrameCounter, p.SystemTitle); GXDLMSChipperingStream gcm = new GXDLMSChipperingStream(p.Security, true, p.BlockCipherKey, aad, iv, tag); gcm.Write(ciphertext); return gcm.FlushFinalBlock(); }
/// <summary> /// Set item count. /// </summary> /// <param name="count"></param> /// <param name="buff"></param> internal static void SetObjectCount(int count, GXByteBuffer buff) { if (count < 0x80) { buff.SetUInt8((byte)count); } else if (count < 0x100) { buff.SetUInt8(0x81); buff.SetUInt8((byte)count); } else if (count < 0x10000) { buff.SetUInt8(0x82); buff.SetUInt16((UInt16)count); } else { buff.SetUInt8(0x84); buff.SetUInt32((UInt32)count); } }
/// <summary> /// Get object count. If first byte is 0x80 or higger it will tell bytes count. /// </summary> /// <param name="data">Received data.</param> /// <returns>Object count.</returns> public static int GetObjectCount(GXByteBuffer data) { int cnt = data.GetUInt8(); if (cnt > 0x80) { if (cnt == 0x81) { return data.GetUInt8(); } else if (cnt == 0x82) { return data.GetUInt16(); } else if (cnt == 0x84) { return (int)data.GetUInt32(); } else { throw new System.ArgumentException("Invalid count."); } } return cnt; }
/// <summary> /// Add string to byte buffer. /// </summary> /// <param name="value">String to add.</param> /// <param name="bb">Byte buffer where string is added.</param> public static void AddString(string value, GXByteBuffer bb) { bb.SetUInt8((byte)DataType.OctetString); if (value == null) { GXCommon.SetObjectCount(0, bb); } else { GXCommon.SetObjectCount(value.Length, bb); bb.Set(ASCIIEncoding.ASCII.GetBytes(value)); } }
/// <summary> /// Get HDLC address from byte array. /// </summary> /// <param name="GXByteBuffer">Byte array.</param> /// <returns>HDLC address.</returns> public static int GetHDLCAddress(GXByteBuffer buff) { int size = 0; for (int pos = buff.Position; pos != buff.Size; ++pos) { ++size; if ((buff.GetUInt8(pos) & 0x1) == 1) { break; } } if (size == 1) { return (byte)((buff.GetUInt8() & 0xFE) >> 1); } else if (size == 2) { size = buff.GetUInt16(); size = ((size & 0xFE) >> 1) | ((size & 0xFE00) >> 2); return size; } else if (size == 4) { UInt32 tmp = buff.GetUInt32(); tmp = ((tmp & 0xFE) >> 1) | ((tmp & 0xFE00) >> 2) | ((tmp & 0xFE0000) >> 3) | ((tmp & 0xFE000000) >> 4); return (int)tmp; } throw new ArgumentException("Wrong size."); }
///<summary> ///Convert Bit string to DLMS bytes. ///</summary> ///<param name="buff"> ///Byte buffer where data is write. ///</param> ///<param name="value"> ///Added value. ///</param> private static void SetBitString(GXByteBuffer buff, object value) { if (value is string) { GXByteBuffer tmp = new GXByteBuffer(); byte val = 0; int index = 0; string str = ((string)value); SetObjectCount(str.Length, buff); foreach (char it in str.Reverse()) { if (it == '1') { val |= (byte)(1 << index); ++index; } else if (it == '0') { ++index; } else { throw new Exception("Not a bit string."); } if (index == 8) { index = 0; tmp.SetUInt8(val); val = 0; } } if (index != 0) { tmp.SetUInt8(val); } for (int pos = tmp.Size - 1; pos != -1; --pos) { buff.SetUInt8(tmp.GetUInt8(pos)); } } else if (value is sbyte[]) { byte[] arr = (byte[])value; SetObjectCount(arr.Length, buff); buff.Set(arr); } else if (value == null) { buff.SetUInt8(0); } else { throw new Exception("BitString must give as string."); } }
object IGXDLMSBase.GetValue(GXDLMSSettings settings, ValueEventArgs e) { if (e.Index == 1) { return(GXCommon.LogicalNameToBytes(LogicalName)); } else if (e.Index == 2) { return(InitiatorElectricalPhase); } else if (e.Index == 3) { return(DeltaElectricalPhase); } else if (e.Index == 4) { return(MaxReceivingGain); } else if (e.Index == 5) { return(MaxTransmittingGain); } else if (e.Index == 6) { return(SearchInitiatorThreshold); } else if (e.Index == 7) { GXByteBuffer bb = new GXByteBuffer(); bb.SetUInt8(DataType.Structure); bb.SetUInt8(2); GXCommon.SetData(settings, bb, DataType.UInt32, MarkFrequency); GXCommon.SetData(settings, bb, DataType.UInt32, SpaceFrequency); return(bb.Array()); } else if (e.Index == 8) { return(MacAddress); } else if (e.Index == 9) { GXByteBuffer bb = new GXByteBuffer(); bb.SetUInt8(DataType.Array); if (MacGroupAddresses == null) { bb.SetUInt8(0); } else { GXCommon.SetObjectCount(MacGroupAddresses.Length, bb); foreach (UInt16 it in MacGroupAddresses) { GXCommon.SetData(settings, bb, DataType.UInt16, it); } } return(bb.Array()); } else if (e.Index == 10) { return(Repeater); } else if (e.Index == 11) { return(RepeaterStatus); } else if (e.Index == 12) { return(MinDeltaCredit); } else if (e.Index == 13) { return(InitiatorMacAddress); } else if (e.Index == 14) { return(SynchronizationLocked); } else if (e.Index == 15) { return(TransmissionSpeed); } e.Error = ErrorCode.ReadWriteDenied; return(null); }
///<summary> ///Get array from DLMS data. ///</summary> ///<param name="buff"> ///Received DLMS data. ///</param> ///<param name="info"> ///Data info. ///</param> ///<param name="index"> ///starting index. ///</param> ///<returns>Object array. ///</returns> private static object GetArray(GXByteBuffer buff, GXDataInfo info, int index) { object value; if (info.Count == 0) { info.Count = GXCommon.GetObjectCount(buff); } if (info.xml != null) { info.xml.AppendStartTag(GXDLMS.DATA_TYPE_OFFSET | (int)info.Type, "Qty", info.xml.IntegerToHex(info.Count, 2)); } int size = buff.Size - buff.Position; if (info.Count != 0 && size < 1) { info.Complete = false; return null; } int startIndex = index; List<object> arr = new List<object>(info.Count - info.Index); // Position where last row was found. Cache uses this info. int pos = info.Index; for (; pos != info.Count; ++pos) { GXDataInfo info2 = new GXDataInfo(); info2.xml = info.xml; object tmp = GetData(null, buff, info2); if (!info2.Complete) { buff.Position = (UInt16)startIndex; info.Complete = false; break; } else { if (info2.Count == info2.Index) { startIndex = buff.Position; arr.Add(tmp); } } } if (info.xml != null) { info.xml.AppendEndTag(GXDLMS.DATA_TYPE_OFFSET + (int)info.Type); } info.Index = pos; value = arr.ToArray(); return value; }
/// <summary> /// Read DLMS Data from the device. /// </summary> /// <param name="data">Data to send.</param> /// <returns>Received data.</returns> public void ReadDLMSPacket(byte[] data, GXReplyData reply) { if (data == null && !reply.IsStreaming()) { return; } GXReplyData notify = new GXReplyData(); reply.Error = 0; object eop = (byte)0x7E; //In network connection terminator is not used. if (Client.InterfaceType == InterfaceType.WRAPPER && Media is GXNet) { eop = null; } int pos = 0; bool succeeded = false; ReceiveParameters <byte[]> p = new ReceiveParameters <byte[]>() { Eop = eop, WaitTime = WaitTime, }; if (eop == null) { p.Count = 8; } else { p.Count = 5; } GXByteBuffer rd = new GXByteBuffer(); lock (Media.Synchronous) { while (!succeeded && pos != 3) { if (!reply.IsStreaming()) { WriteTrace("TX:\t" + DateTime.Now.ToLongTimeString() + "\t" + GXCommon.ToHex(data, true)); Media.Send(data, null); } succeeded = Media.Receive(p); if (!succeeded) { if (++pos >= RetryCount) { throw new Exception("Failed to receive reply from the device in given time."); } //If Eop is not set read one byte at time. if (p.Eop == null) { p.Count = 1; } //Try to read again... System.Diagnostics.Debug.WriteLine("Data send failed. Try to resend " + pos.ToString() + "/3"); } } rd = new GXByteBuffer(p.Reply); try { pos = 0; //Loop until whole COSEM packet is received. while (!Client.GetData(rd, reply, notify)) { p.Reply = null; if (notify.Data.Data != null) { //Handle notify. if (!notify.IsMoreData) { //Show received push message as XML. string xml; GXDLMSTranslator t = new GXDLMSTranslator(TranslatorOutputType.SimpleXml); t.DataToXml(notify.Data, out xml); Console.WriteLine(xml); notify.Clear(); } continue; } else if (p.Eop == null) { p.Count = Client.GetFrameSize(rd); } while (!Media.Receive(p)) { if (++pos >= RetryCount) { throw new Exception("Failed to receive reply from the device in given time."); } //If echo. if (rd == null || rd.Size == data.Length) { Media.Send(data, null); } //Try to read again... System.Diagnostics.Debug.WriteLine("Data send failed. Try to resend " + pos.ToString() + "/3"); } rd.Set(p.Reply); } } catch (Exception ex) { WriteTrace("RX:\t" + DateTime.Now.ToLongTimeString() + "\t" + rd); throw ex; } } WriteTrace("RX:\t" + DateTime.Now.ToLongTimeString() + "\t" + rd); if (reply.Error != 0) { if (reply.Error == (short)ErrorCode.Rejected) { Thread.Sleep(1000); ReadDLMSPacket(data, reply); } } }
///<summary> ///Get time from DLMS data. ///</summary> ///<param name="buff"> ///Received DLMS data. ///</param> ///<param name="info"> ///Data info. ///</param> ///<returns> ///Parsed time. ///</returns> private static object GetTime(GXByteBuffer buff, GXDataInfo info) { object value; if (buff.Size - buff.Position < 4) { // If there is not enough data available. info.Complete = false; return null; } if (info.xml != null) { info.xml.AppendLine(info.xml.GetDataType(info.Type), "Value", GXCommon.ToHex(buff.Data, false, buff.Position, 4)); } // Get time. int hour = buff.GetUInt8(); int minute = buff.GetUInt8(); int second = buff.GetUInt8(); int ms = buff.GetUInt8(); if (ms != 0xFF) { ms *= 10; } GXTime dt = new GXTime(hour, minute, second, ms); value = dt; return value; }
object IGXDLMSBase.GetValue(GXDLMSSettings settings, ValueEventArgs e) { if (e.Index == 1) { return(this.LogicalName); } if (e.Index == 2) { GXByteBuffer data = new GXByteBuffer(); data.SetUInt8((byte)DataType.Array); data.SetUInt8((byte)Entries.Count); /* * foreach (GXScheduleEntry it in Entries) * { * data.SetUInt8((byte)DataType.Structure); * data.SetUInt8(10); * //Add index. * data.SetUInt8((byte)DataType.UInt8); * data.SetUInt8(it.Index); * //Add enable. * data.SetUInt8((byte)DataType.Boolean); * data.SetUInt8((byte) (it.Enable ? 1 : 0)); * * //Add logical Name. * data.SetUInt8((byte)DataType.OctetString); * data.SetUInt8((byte) it.LogicalName.Length); * //TODO: data.SetUInt8((byte)it.LogicalName.Length); * * //Add script selector. * data.SetUInt8((byte)DataType.UInt8); * data.SetUInt8(it.ScriptSelector); * * //Add switch time. * ret = var_setDateTime(&tmp, &se->switchTime); * if (ret != 0) * { * var_clear(&tmp); * break; * } * ret = var_getBytes(&tmp, &value->byteArr); * var_clear(&tmp); * if (ret != 0) * { * break; * } * //Add validity window. * data.SetUInt8((byte)DataType.UInt8); * data.SetUInt8(it.ValidityWindow); * * //Add exec week days. * ba_setUInt8(&value->byteArr, DLMS_DATA_TYPE_BIT_STRING); * setObjectCount(se->execWeekdays.size, &value->byteArr); * ba_addRange(&value->byteArr, se->execWeekdays.data, bit_getByteCount(se->execWeekdays.size)); * * //Add exec spec days. * ba_setUInt8(&value->byteArr, DLMS_DATA_TYPE_BIT_STRING); * setObjectCount(se->execSpecDays.size, &value->byteArr); * ba_addRange(&value->byteArr, se->execSpecDays.data, bit_getByteCount(se->execSpecDays.size)); * * //Add begin date. * ret = var_setDateTime(&tmp, &se->beginDate); * if (ret != 0) * { * var_clear(&tmp); * break; * } * ret = var_getBytes(&tmp, &value->byteArr); * var_clear(&tmp); * if (ret != 0) * { * break; * } * //Add end date. * ret = var_setDateTime(&tmp, &se->endDate); * if (ret != 0) * { * var_clear(&tmp); * break; * } * ret = var_getBytes(&tmp, &value->byteArr); * var_clear(&tmp); * if (ret != 0) * { * break; * } * } * */ return(data.Array()); } e.Error = ErrorCode.ReadWriteDenied; return(null); }
///<summary> ///Get date from DLMS data. ///</summary> ///<param name="buff"> ///Received DLMS data. ///</param> ///<param name="info"> ///Data info. ///</param> ///<returns> ///Parsed date. ///</returns> private static object GetDate(GXByteBuffer buff, GXDataInfo info) { object value; if (buff.Size - buff.Position < 5) { // If there is not enough data available. info.Complete = false; return null; } if (info.xml != null) { info.xml.AppendLine(info.xml.GetDataType(info.Type), "Value", GXCommon.ToHex(buff.Data, false, buff.Position, 5)); } // Get year. int year = buff.GetUInt16(); // Get month int month = buff.GetUInt8(); // Get day int day = buff.GetUInt8(); GXDate dt = new GXDate(year, month, day); // Skip week day if (buff.GetUInt8() == 0xFF) { dt.Skip |= DateTimeSkips.DayOfWeek; } value = dt; return value; }
object IGXDLMSBase.GetValue(GXDLMSSettings settings, ValueEventArgs e) { if (e.Index == 1) { return(GXCommon.LogicalNameToBytes(LogicalName)); } if (e.Index == 2) { if (APN != null) { return(ASCIIEncoding.ASCII.GetBytes(APN)); } return(null); } if (e.Index == 3) { return(PINCode); } if (e.Index == 4) { GXByteBuffer data = new GXByteBuffer(); data.SetUInt8((byte)DataType.Structure); //Add count data.SetUInt8((byte)2); data.SetUInt8((byte)DataType.Structure); data.SetUInt8((byte)5); if (DefaultQualityOfService != null) { GXCommon.SetData(settings, data, DataType.UInt8, DefaultQualityOfService.Precedence); GXCommon.SetData(settings, data, DataType.UInt8, DefaultQualityOfService.Delay); GXCommon.SetData(settings, data, DataType.UInt8, DefaultQualityOfService.Reliability); GXCommon.SetData(settings, data, DataType.UInt8, DefaultQualityOfService.PeakThroughput); GXCommon.SetData(settings, data, DataType.UInt8, DefaultQualityOfService.MeanThroughput); } else { GXCommon.SetData(settings, data, DataType.UInt8, 0); GXCommon.SetData(settings, data, DataType.UInt8, 0); GXCommon.SetData(settings, data, DataType.UInt8, 0); GXCommon.SetData(settings, data, DataType.UInt8, 0); GXCommon.SetData(settings, data, DataType.UInt8, 0); } data.SetUInt8((byte)DataType.Structure); data.SetUInt8((byte)5); if (RequestedQualityOfService != null) { GXCommon.SetData(settings, data, DataType.UInt8, RequestedQualityOfService.Precedence); GXCommon.SetData(settings, data, DataType.UInt8, RequestedQualityOfService.Delay); GXCommon.SetData(settings, data, DataType.UInt8, RequestedQualityOfService.Reliability); GXCommon.SetData(settings, data, DataType.UInt8, RequestedQualityOfService.PeakThroughput); GXCommon.SetData(settings, data, DataType.UInt8, RequestedQualityOfService.MeanThroughput); } else { GXCommon.SetData(settings, data, DataType.UInt8, 0); GXCommon.SetData(settings, data, DataType.UInt8, 0); GXCommon.SetData(settings, data, DataType.UInt8, 0); GXCommon.SetData(settings, data, DataType.UInt8, 0); GXCommon.SetData(settings, data, DataType.UInt8, 0); } return(data.Array()); } e.Error = ErrorCode.ReadWriteDenied; return(null); }
///<summary> ///Get date and time from DLMS data. ///</summary> ///<param name="settings">DLMS settings.</param> ///<param name="buff">Received DLMS data.</param> ///<param name="info">Data info.</param> ///<returns> ///Parsed date and time. ///</returns> private static object GetDateTime(GXDLMSSettings settings, GXByteBuffer buff, GXDataInfo info) { // If there is not enough data available. if (buff.Size - buff.Position < 12) { //If time. if (buff.Size - buff.Position < 5) { return GetTime(buff, info); } //If date. else if (buff.Size - buff.Position < 6) { return GetDate(buff, info); } info.Complete = false; return null; } if (info.xml != null) { info.xml.AppendLine(info.xml.GetDataType(info.Type), "Value", GXCommon.ToHex(buff.Data, false, buff.Position, 12)); } GXDateTime dt = new GXDateTime(); //Get year. int year = buff.GetUInt16(); if (year == 0xFFFF || year == 0) { year = DateTime.Now.Year; dt.Skip |= DateTimeSkips.Year; } //Get month int month = buff.GetUInt8(); if (month == 0 || month == 0xFF || month == 0xFE || month == 0xFD) { month = 1; dt.Skip |= DateTimeSkips.Month; } int day = buff.GetUInt8(); 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 if (buff.GetUInt8() == 0xFF) { dt.Skip |= DateTimeSkips.DayOfWeek; } //Get time. int hours = buff.GetUInt8(); if (hours == 0xFF) { hours = 0; dt.Skip |= DateTimeSkips.Hour; } int minutes = buff.GetUInt8(); if (minutes == 0xFF) { minutes = 0; dt.Skip |= DateTimeSkips.Minute; } int seconds = buff.GetUInt8(); if (seconds == 0xFF) { seconds = 0; dt.Skip |= DateTimeSkips.Second; } int milliseconds = buff.GetUInt8(); if (milliseconds != 0xFF) { milliseconds *= 10; } else { milliseconds = 0; dt.Skip |= DateTimeSkips.Ms; } int deviation = buff.GetInt16(); dt.Status = (ClockStatus)buff.GetUInt8(); if (settings != null && settings.UtcTimeZone) { deviation = -deviation; } dt.Deviation = deviation; //0x8000 == -32768 //deviation = -1 if skipped. if (deviation != -1 && deviation != -32768 && year != 1 && (dt.Skip & DateTimeSkips.Year) == 0) { dt.Value = new DateTimeOffset(new DateTime(year, month, day, hours, minutes, seconds, milliseconds), new TimeSpan(0, -deviation, 0)); } else //Use current time if deviation is not defined. { dt.Skip |= DateTimeSkips.Devitation; DateTime tmp = new DateTime(year, month, day, hours, minutes, seconds, milliseconds, DateTimeKind.Local); dt.Value = new DateTimeOffset(tmp, TimeZoneInfo.Local.GetUtcOffset(tmp)); } return dt; }
byte[] IGXDLMSBase.Invoke(GXDLMSSettings settings, ValueEventArgs e) { //Check reply_to_HLS_authentication if (e.Index == 1) { UInt32 ic = 0; byte[] secret; if (settings.Authentication == Authentication.HighGMAC) { secret = settings.SourceSystemTitle; GXByteBuffer bb = new GXByteBuffer(e.Parameters as byte[]); bb.GetUInt8(); ic = bb.GetUInt32(); } else { secret = Secret; } byte[] serverChallenge = GXSecure.Secure(settings, settings.Cipher, ic, settings.StoCChallenge, secret); byte[] clientChallenge = (byte[])e.Parameters; if (serverChallenge != null && clientChallenge != null && GXCommon.Compare(serverChallenge, clientChallenge)) { if (settings.Authentication == Authentication.HighGMAC) { secret = settings.Cipher.SystemTitle; ic = settings.Cipher.InvocationCounter; } else { secret = Secret; } settings.Connected = ConnectionState.Dlms; AssociationStatus = AssociationStatus.Associated; return(GXSecure.Secure(settings, settings.Cipher, ic, settings.CtoSChallenge, secret)); } else //If the password does not match. { AssociationStatus = AssociationStatus.NonAssociated; settings.Connected &= ~ConnectionState.Dlms; return(null); } } else if (e.Index == 2) { byte[] tmp = e.Parameters as byte[]; if (tmp == null || tmp.Length == 0) { e.Error = ErrorCode.ReadWriteDenied; } else { Secret = tmp; } } else if (e.Index == 3) { //Add COSEM object. GXDLMSObject obj = GetObject(settings, e.Parameters as object[]); //Unknown objects are not add. if (obj is IGXDLMSBase) { if (ObjectList.FindByLN(obj.ObjectType, obj.LogicalName) == null) { ObjectList.Add(obj); } if (settings.Objects.FindByLN(obj.ObjectType, obj.LogicalName) == null) { settings.Objects.Add(obj); } } } else if (e.Index == 4) { //Remove COSEM object. GXDLMSObject obj = GetObject(settings, e.Parameters as object[]); //Unknown objects are not removed. if (obj is IGXDLMSBase) { GXDLMSObject t = ObjectList.FindByLN(obj.ObjectType, obj.LogicalName); if (t != null) { ObjectList.Remove(t); } //Item is not removed from all objects. It might be that use wants remove object only from association view. } } else if (e.Index == 5) { object[] tmp = e.Parameters as object[]; if (tmp == null || tmp.Length != 2) { e.Error = ErrorCode.ReadWriteDenied; } else { UserList.Add(new KeyValuePair <byte, string>(Convert.ToByte(tmp[0]), Convert.ToString(tmp[1]))); } } else if (e.Index == 6) { object[] tmp = e.Parameters as object[]; if (tmp == null || tmp.Length != 2) { e.Error = ErrorCode.ReadWriteDenied; } else { UserList.Remove(new KeyValuePair <byte, string>(Convert.ToByte(tmp[0]), Convert.ToString(tmp[1]))); } } else { e.Error = ErrorCode.ReadWriteDenied; } return(null); }
///<summary> ///Get float value from DLMS data. ///</summary> ///<param name="buff"> ///Received DLMS data. ///</param> ///<param name="info"> ///Data info. ///</param> ///<returns> ///Parsed float value. ///</returns> private static object Getfloat(GXByteBuffer buff, GXDataInfo info) { // If there is not enough data available. if (buff.Size - buff.Position < 4) { info.Complete = false; return null; } float value = buff.GetFloat(); if (info.xml != null) { GXByteBuffer tmp = new GXByteBuffer(); SetData(null, tmp, DataType.Float32, value); info.xml.AppendLine(info.xml.GetDataType(info.Type), "Value", GXCommon.ToHex(tmp.Data, false, 1, tmp.Size - 1)); } return value; }
///<summary> ///Convert Octet string to DLMS bytes. ///</summary> ///<param name="buff"> ///Byte buffer where data is write. ///</param> ///<param name="value"> ///Added value. ///</param> private static void SetOctetString(GXByteBuffer buff, object value) { // Example Logical name is octet string, so do not change to // string... if (value is string) { string[] items = ((string)value).Split('.'); // If data is string. if (items.Length == 1) { byte[] tmp = ASCIIEncoding.ASCII.GetBytes((string)value); SetObjectCount(tmp.Length, buff); buff.Set(tmp); } else { SetObjectCount(items.Length, buff); foreach (string it in items) { buff.SetUInt8(Convert.ToByte(it)); } } } else if (value is sbyte[]) { SetObjectCount(((byte[])value).Length, buff); buff.Set((byte[])value); } else if (value == null) { SetObjectCount(0, buff); } else { throw new Exception("Invalid data type."); } }
///<summary> ///Get UInt16 value from DLMS data. ///</summary> ///<param name="buff"> ///Received DLMS data. ///</param> ///<param name="info"> ///Data info. ///</param> ///<returns> ///Parsed UInt16 value. ///</returns> private static object GetUInt16(GXByteBuffer buff, GXDataInfo info) { // If there is not enough data available. if (buff.Size - buff.Position < 2) { info.Complete = false; return null; } UInt16 value = buff.GetUInt16(); if (info.xml != null) { info.xml.AppendLine(info.xml.GetDataType(info.Type), "Value", info.xml.IntegerToHex(value, 4)); } return value; }
object IGXDLMSBase.GetValue(GXDLMSSettings settings, ValueEventArgs e) { if (ObjectList == null) { ObjectList = new GXDLMSObjectCollection(); } if (e.Index == 1) { return this.LogicalName; } else if (e.Index == 2) { return GetObjects(settings, e).Array(); } else if (e.Index == 3) { bool lnExists = ObjectList.FindBySN(this.ShortName) != null; //Add count int cnt = ObjectList.Count; if (!lnExists) { ++cnt; } GXByteBuffer data = new GXByteBuffer(); data.SetUInt8((byte)DataType.Array); GXCommon.SetObjectCount(cnt, data); foreach (GXDLMSObject it in ObjectList) { GetAccessRights(settings, it, data); } if (!lnExists) { GetAccessRights(settings, this, data); } return data.Array(); } else if (e.Index == 4) { GXByteBuffer data = new GXByteBuffer(); GXCommon.SetData(settings, data, DataType.OctetString, SecuritySetupReference); return data.Array(); } e.Error = ErrorCode.ReadWriteDenied; return null; }
/// <summary> /// Decrypt data. /// </summary> /// <param name="p">Decryption parameters</param> /// <returns>Decrypted data.</returns> public static byte[] DecryptAesGcm(AesGcmParameter p, GXByteBuffer data) { if (data == null || data.Size < 2) { throw new ArgumentOutOfRangeException("cryptedData"); } byte[] tmp; int len; Command cmd = (Command)data.GetUInt8(); switch (cmd) { case Command.GeneralGloCiphering: case Command.GeneralDedCiphering: len = GXCommon.GetObjectCount(data); if (len != 0) { p.SystemTitle = new byte[len]; data.Get(p.SystemTitle); if (p.Xml != null && p.Xml.Comments) { p.Xml.AppendComment(GXCommon.SystemTitleToString(Standard.DLMS, p.SystemTitle, true)); } } if (p.SystemTitle == null || p.SystemTitle.Length != 8) { if (p.Xml == null) { throw new ArgumentNullException("Invalid sender system title."); } else { p.Xml.AppendComment("Invalid sender system title."); } } break; case Command.GeneralCiphering: case Command.GloInitiateRequest: case Command.GloInitiateResponse: case Command.GloReadRequest: case Command.GloReadResponse: case Command.GloWriteRequest: case Command.GloWriteResponse: case Command.GloGetRequest: case Command.GloGetResponse: case Command.GloSetRequest: case Command.GloSetResponse: case Command.GloMethodRequest: case Command.GloMethodResponse: case Command.GloEventNotification: case Command.DedInitiateRequest: case Command.DedInitiateResponse: case Command.DedGetRequest: case Command.DedGetResponse: case Command.DedSetRequest: case Command.DedSetResponse: case Command.DedMethodRequest: case Command.DedMethodResponse: case Command.DedEventNotification: case Command.DedReadRequest: case Command.DedReadResponse: case Command.DedWriteRequest: case Command.DedWriteResponse: case Command.GloConfirmedServiceError: case Command.DedConfirmedServiceError: break; default: throw new ArgumentOutOfRangeException("cryptedData"); } int value = 0; GXPrivateKey key = null; GXPublicKey pub = null; GXByteBuffer transactionId = null; if (cmd == Command.GeneralCiphering) { transactionId = new GXByteBuffer(); len = GXCommon.GetObjectCount(data); GXCommon.SetObjectCount(len, transactionId); transactionId.Set(data, len); p.TransactionId = transactionId.GetUInt64(1); len = GXCommon.GetObjectCount(data); if (len != 0) { tmp = new byte[len]; data.Get(tmp); p.SystemTitle = tmp; } if (p.SystemTitle == null || p.SystemTitle.Length != 8) { if (p.Xml == null) { throw new ArgumentNullException("Invalid sender system title."); } else { p.Xml.AppendComment("Invalid sender system title."); } } len = GXCommon.GetObjectCount(data); tmp = new byte[len]; data.Get(tmp); p.RecipientSystemTitle = tmp; // Get date time. len = GXCommon.GetObjectCount(data); if (len != 0) { tmp = new byte[len]; data.Get(tmp); p.DateTime = tmp; } // other-information len = data.GetUInt8(); if (len != 0) { tmp = new byte[len]; data.Get(tmp); p.OtherInformation = tmp; } // KeyInfo OPTIONAL len = data.GetUInt8(); // AgreedKey CHOICE tag. data.GetUInt8(); // key-parameters len = data.GetUInt8(); value = data.GetUInt8(); p.KeyParameters = value; if (value == (int)KeyAgreementScheme.OnePassDiffieHellman) { // key-ciphered-data len = GXCommon.GetObjectCount(data); GXByteBuffer bb = new GXByteBuffer(); bb.Set(data, len); if (p.Xml != null) { p.KeyCipheredData = bb.Array(); //Find key agreement key using subject. string subject = GXAsn1Converter.SystemTitleToSubject(p.SystemTitle); foreach (KeyValuePair <GXPkcs8, GXx509Certificate> it in p.Settings.Keys) { if (it.Key != null && it.Value.KeyUsage == ASN.Enums.KeyUsage.KeyAgreement && it.Value.Subject.Contains(subject)) { key = it.Key.PrivateKey; //Get recipient Ephemeral public key. subject = GXAsn1Converter.SystemTitleToSubject(p.RecipientSystemTitle); foreach (KeyValuePair <GXPkcs8, GXx509Certificate> it2 in p.Settings.Keys) { if (it2.Value != null && it2.Value.KeyUsage == ASN.Enums.KeyUsage.KeyAgreement && it2.Value.Subject.Contains(subject)) { pub = it2.Value.PublicKey; break; } } break; } } if (key == null) { //Find key agreement key using subject. subject = GXAsn1Converter.SystemTitleToSubject(p.RecipientSystemTitle); foreach (KeyValuePair <GXPkcs8, GXx509Certificate> it in p.Settings.Keys) { if (it.Key != null && it.Value.KeyUsage == ASN.Enums.KeyUsage.KeyAgreement && it.Value.Subject.Contains(subject)) { key = it.Key.PrivateKey; break; } } } } else { key = p.Settings.Cipher.KeyAgreementKeyPair.Key; } if (key != null && pub == null) { //Get Ephemeral public key. int keySize = len / 2; pub = GXPublicKey.FromRawBytes(bb.SubArray(0, keySize)); } } else if (value == (int)KeyAgreementScheme.StaticUnifiedModel) { len = GXCommon.GetObjectCount(data); if (len != 0) { throw new ArgumentException("Invalid key parameters"); } if (p.Xml != null) { //Find key agreement key using subject. string subject = GXAsn1Converter.SystemTitleToSubject(p.RecipientSystemTitle); foreach (KeyValuePair <GXPkcs8, GXx509Certificate> it in p.Settings.Keys) { if (it.Value.KeyUsage == ASN.Enums.KeyUsage.KeyAgreement && it.Value.Subject.Contains(subject)) { key = it.Key.PrivateKey; break; } } if (key != null) { //Find key agreement key using subject. subject = GXAsn1Converter.SystemTitleToSubject(p.Settings.SourceSystemTitle); foreach (KeyValuePair <GXPkcs8, GXx509Certificate> it in p.Settings.Keys) { if (it.Value.KeyUsage == ASN.Enums.KeyUsage.KeyAgreement && it.Value.Subject.Contains(subject)) { pub = it.Value.PublicKey; break; } } } } else { key = p.Settings.Cipher.KeyAgreementKeyPair.Key; pub = p.Settings.Cipher.KeyAgreementKeyPair.Value; } } else { throw new ArgumentException("key-parameters"); } } len = GXCommon.GetObjectCount(data); if (len > data.Available) { throw new Exception("Not enought data."); } p.CipheredContent = data.Remaining(); byte sc = data.GetUInt8(); p.SecuritySuite = (SecuritySuite)(sc & 0x3); p.Security = (Security)(sc & 0x30); if ((sc & 0x80) != 0) { System.Diagnostics.Debug.WriteLine("Compression is used."); } if ((sc & 0x40) != 0) { System.Diagnostics.Debug.WriteLine("Error: Key_Set is used."); } if ((sc & 0x20) != 0) { System.Diagnostics.Debug.WriteLine("Encryption is applied."); } if (key != null) { if (value == (int)KeyAgreementScheme.OnePassDiffieHellman) { GXEcdsa c = new GXEcdsa(key); //Get Ephemeral signing key and verify it. byte[] z = c.GenerateSecret(pub); System.Diagnostics.Debug.WriteLine("Originator ephemeral public key: " + pub.ToHex()); System.Diagnostics.Debug.WriteLine("Recipient private agreement key: " + key.ToHex()); System.Diagnostics.Debug.WriteLine("Shared secret:" + GXCommon.ToHex(z, true)); GXByteBuffer kdf = new GXByteBuffer(); kdf.Set(GXSecure.GenerateKDF(p.SecuritySuite, z, p.SecuritySuite == SecuritySuite.Ecdsa256 ? AlgorithmId.AesGcm128 : AlgorithmId.AesGcm256, p.SystemTitle, p.RecipientSystemTitle, null, null)); System.Diagnostics.Debug.WriteLine("KDF:" + kdf.ToString()); p.BlockCipherKey = kdf.SubArray(0, 16); } else if (value == (int)KeyAgreementScheme.StaticUnifiedModel) { GXEcdsa c = new GXEcdsa(key); byte[] z = c.GenerateSecret(pub); System.Diagnostics.Debug.WriteLine("Shared secret:" + GXCommon.ToHex(z, true)); GXByteBuffer kdf = new GXByteBuffer(); kdf.Set(GXSecure.GenerateKDF(p.SecuritySuite, z, p.SecuritySuite == SecuritySuite.Ecdsa256 ? AlgorithmId.AesGcm128 : AlgorithmId.AesGcm256, p.SystemTitle, transactionId.Array(), p.RecipientSystemTitle, null)); System.Diagnostics.Debug.WriteLine("KDF:" + kdf.ToString()); p.BlockCipherKey = kdf.SubArray(0, 16); } else { throw new ArgumentOutOfRangeException("Invalid Key-id value."); } } UInt32 invocationCounter = data.GetUInt32(); p.InvocationCounter = invocationCounter; System.Diagnostics.Debug.WriteLine("Decrypt settings: " + p.ToString()); System.Diagnostics.Debug.WriteLine("Encrypted: " + GXCommon.ToHex(data.Data, false, data.Position, data.Size - data.Position)); byte[] tag = new byte[12]; byte[] encryptedData; int length; if (p.Security == Security.Authentication) { length = data.Size - data.Position - 12; encryptedData = new byte[length]; data.Get(encryptedData); data.Get(tag); // Check tag. EncryptAesGcm(p, encryptedData); if (!GXDLMSChipperingStream.TagsEquals(tag, p.CountTag)) { if (p.Xml == null) { throw new GXDLMSException("Decrypt failed. Invalid tag."); } else { p.Xml.AppendComment("Decrypt failed. Invalid tag."); } } return(encryptedData); } byte[] ciphertext = null; if (p.Security == Security.Encryption) { length = data.Size - data.Position; ciphertext = new byte[length]; data.Get(ciphertext); } else if (p.Security == Security.AuthenticationEncryption) { length = data.Size - data.Position - 12; ciphertext = new byte[length]; data.Get(ciphertext); data.Get(tag); } byte[] aad = GetAuthenticatedData(p, ciphertext), iv = GetNonse(invocationCounter, p.SystemTitle); GXDLMSChipperingStream gcm = new GXDLMSChipperingStream(p.Security, true, p.BlockCipherKey, aad, iv, tag); gcm.Write(ciphertext); byte[] decrypted = gcm.FlushFinalBlock(); System.Diagnostics.Debug.WriteLine("Decrypted: " + GXCommon.ToHex(decrypted, true)); if (p.Security != Security.Encryption) { if (!GXCommon.Compare(gcm.GetTag(), tag)) { if (p.Xml == null) { throw new Exception("Decrypt failed. Invalid authentication tag."); } p.Xml.AppendComment("Decrypt failed. Invalid authentication tag."); } } return(decrypted); }
/// <summary> /// Constructor value. /// </summary> /// <param name="value">Byte array Data in MSB format.</param> public GXBigInteger(GXByteBuffer value) { FromByteBuffer(value); }
static internal byte[] EncryptAesGcm(AesGcmParameter param, byte[] plainText) { System.Diagnostics.Debug.WriteLine("Encrypt settings: " + param.ToString()); param.CountTag = null; GXByteBuffer data = new GXByteBuffer(); if (param.Type == CountType.Packet) { data.SetUInt8((byte)((byte)param.Security | (byte)param.SecuritySuite)); } byte[] tmp = BitConverter.GetBytes((UInt32)param.InvocationCounter).Reverse().ToArray(); byte[] aad = GetAuthenticatedData(param, plainText); GXDLMSChipperingStream gcm = new GXDLMSChipperingStream(param.Security, true, param.BlockCipherKey, aad, GetNonse((UInt32)param.InvocationCounter, param.SystemTitle), null); // Encrypt the secret message if (param.Security != Security.Authentication) { gcm.Write(plainText); } byte[] ciphertext = gcm.FlushFinalBlock(); if (param.Security == Security.Authentication) { if (param.Type == CountType.Packet) { data.Set(tmp); } if ((param.Type & CountType.Data) != 0) { data.Set(plainText); } if ((param.Type & CountType.Tag) != 0) { param.CountTag = gcm.GetTag(); data.Set(param.CountTag); } } else if (param.Security == Security.Encryption) { if (param.Type == CountType.Packet) { data.Set(tmp); } data.Set(ciphertext); } else if (param.Security == Security.AuthenticationEncryption) { if (param.Type == CountType.Packet) { data.Set(tmp); } if ((param.Type & CountType.Data) != 0) { data.Set(ciphertext); } if ((param.Type & CountType.Tag) != 0) { param.CountTag = gcm.GetTag(); data.Set(param.CountTag); } } else { throw new ArgumentOutOfRangeException("security"); } if (param.Type == CountType.Packet) { GXByteBuffer tmp2 = new GXByteBuffer((ushort)(10 + data.Size)); tmp2.SetUInt8(param.Tag); if (param.Tag == (int)Command.GeneralGloCiphering || param.Tag == (int)Command.GeneralDedCiphering || param.Tag == (int)Command.DataNotification) { if (!param.IgnoreSystemTitle) { GXCommon.SetObjectCount(param.SystemTitle.Length, tmp2); tmp2.Set(param.SystemTitle); } else { tmp2.SetUInt8(0); } } GXCommon.SetObjectCount(data.Size, tmp2); tmp2.Set(data.Array()); return(tmp2.Array()); } byte[] crypted = data.Array(); System.Diagnostics.Debug.WriteLine("Crypted: " + GXCommon.ToHex(crypted, true)); return(crypted); }
void IGXDLMSBase.SetValue(GXDLMSSettings settings, int index, object value) { if (index == 1) { if (value is string) { LogicalName = value.ToString(); } else { LogicalName = GXDLMSClient.ChangeType((byte[])value, DataType.OctetString).ToString(); } } else if (index == 2) { ObjectList.Clear(); if (value != null) { foreach (Object[] item in (Object[])value) { ObjectType type = (ObjectType)Convert.ToInt32(item[0]); int version = Convert.ToInt32(item[1]); String ln = GXDLMSObject.ToLogicalName((byte[])item[2]); GXDLMSObject obj = null; if (settings.Objects != null) { obj = settings.Objects.FindByLN(type, ln); } if (obj == null) { obj = Gurux.DLMS.GXDLMSClient.CreateObject(type); obj.LogicalName = ln; obj.Version = version; } //Unknown objects are not shown. if (obj is IGXDLMSBase) { UpdateAccessRights(obj, (Object[])item[3]); ObjectList.Add(obj); } } } } else if (index == 3) { if (value != null) { ClientSAP = Convert.ToByte(((Object[])value)[0]); ServerSAP = Convert.ToUInt16(((Object[])value)[1]); } } else if (index == 4) { //Value of the object identifier encoded in BER if (value is byte[]) { GXByteBuffer arr = new GXByteBuffer(value as byte[]); if (arr.GetUInt8(0) == 0x60) { ApplicationContextName.JointIsoCtt = 0; ++arr.Position; ApplicationContextName.Country = 0; ++arr.Position; ApplicationContextName.CountryName = 0; ++arr.Position; ApplicationContextName.IdentifiedOrganization = arr.GetUInt8(); ApplicationContextName.DlmsUA = arr.GetUInt8(); ApplicationContextName.ApplicationContext = arr.GetUInt8(); ApplicationContextName.ContextId = arr.GetUInt8(); } else { //Get Tag and Len. if (arr.GetUInt8() != (int)BerType.Integer && arr.GetUInt8() != 7) { throw new ArgumentOutOfRangeException(); } //Get tag if (arr.GetUInt8() != 0x11) { throw new ArgumentOutOfRangeException(); } ApplicationContextName.JointIsoCtt = arr.GetUInt8(); //Get tag if (arr.GetUInt8() != 0x11) { throw new ArgumentOutOfRangeException(); } ApplicationContextName.Country = arr.GetUInt8(); //Get tag if (arr.GetUInt8() != 0x12) { throw new ArgumentOutOfRangeException(); } ApplicationContextName.CountryName = arr.GetUInt16(); //Get tag if (arr.GetUInt8() != 0x11) { throw new ArgumentOutOfRangeException(); } ApplicationContextName.IdentifiedOrganization = arr.GetUInt8(); //Get tag if (arr.GetUInt8() != 0x11) { throw new ArgumentOutOfRangeException(); } ApplicationContextName.DlmsUA = arr.GetUInt8(); //Get tag if (arr.GetUInt8() != 0x11) { throw new ArgumentOutOfRangeException(); } ApplicationContextName.ApplicationContext = arr.GetUInt8(); //Get tag if (arr.GetUInt8() != 0x11) { throw new ArgumentOutOfRangeException(); } ApplicationContextName.ContextId = arr.GetUInt8(); } } else if (value != null) { Object[] arr = (Object[])value; ApplicationContextName.JointIsoCtt = Convert.ToByte(arr[0]); ApplicationContextName.Country = Convert.ToByte(arr[1]); ApplicationContextName.CountryName = Convert.ToUInt16(arr[2]); ApplicationContextName.IdentifiedOrganization = Convert.ToByte(arr[3]); ApplicationContextName.DlmsUA = Convert.ToByte(arr[4]); ApplicationContextName.ApplicationContext = Convert.ToByte(arr[5]); ApplicationContextName.ContextId = Convert.ToByte(arr[6]); } } else if (index == 5) { if (value != null) { Object[] arr = (Object[])value; XDLMSContextInfo.Conformance = arr[0].ToString(); XDLMSContextInfo.MaxReceivePduSize = Convert.ToUInt16(arr[1]); XDLMSContextInfo.MaxSendPpuSize = Convert.ToUInt16(arr[2]); XDLMSContextInfo.DlmsVersionNumber = Convert.ToByte(arr[3]); XDLMSContextInfo.QualityOfService = Convert.ToSByte(arr[4]); XDLMSContextInfo.CypheringInfo = (byte[])arr[5]; } } else if (index == 6) { //Value of the object identifier encoded in BER if (value is byte[]) { GXByteBuffer arr = new GXByteBuffer(value as byte[]); if (arr.GetUInt8(0) == 0x60) { AuthenticationMechanismMame.JointIsoCtt = 0; ++arr.Position; AuthenticationMechanismMame.Country = 0; ++arr.Position; AuthenticationMechanismMame.CountryName = 0; ++arr.Position; AuthenticationMechanismMame.IdentifiedOrganization = arr.GetUInt8(); AuthenticationMechanismMame.DlmsUA = arr.GetUInt8(); AuthenticationMechanismMame.AuthenticationMechanismName = arr.GetUInt8(); AuthenticationMechanismMame.MechanismId = (Authentication)arr.GetUInt8(); } else { //Get Tag and Len. if (arr.GetUInt8() != (int)BerType.Integer && arr.GetUInt8() != 7) { throw new ArgumentOutOfRangeException(); } //Get tag if (arr.GetUInt8() != 0x11) { throw new ArgumentOutOfRangeException(); } AuthenticationMechanismMame.JointIsoCtt = arr.GetUInt8(); //Get tag if (arr.GetUInt8() != 0x11) { throw new ArgumentOutOfRangeException(); } AuthenticationMechanismMame.Country = arr.GetUInt8(); //Get tag if (arr.GetUInt8() != 0x12) { throw new ArgumentOutOfRangeException(); } AuthenticationMechanismMame.CountryName = arr.GetUInt16(); //Get tag if (arr.GetUInt8() != 0x11) { throw new ArgumentOutOfRangeException(); } AuthenticationMechanismMame.IdentifiedOrganization = arr.GetUInt8(); //Get tag if (arr.GetUInt8() != 0x11) { throw new ArgumentOutOfRangeException(); } AuthenticationMechanismMame.DlmsUA = arr.GetUInt8(); //Get tag if (arr.GetUInt8() != 0x11) { throw new ArgumentOutOfRangeException(); } AuthenticationMechanismMame.AuthenticationMechanismName = arr.GetUInt8(); //Get tag if (arr.GetUInt8() != 0x11) { throw new ArgumentOutOfRangeException(); } AuthenticationMechanismMame.MechanismId = (Authentication)arr.GetUInt8(); } } else if (value != null) { Object[] arr = (Object[])value; AuthenticationMechanismMame.JointIsoCtt = Convert.ToByte(arr[0]); AuthenticationMechanismMame.Country = Convert.ToByte(arr[1]); AuthenticationMechanismMame.CountryName = Convert.ToUInt16(arr[2]); AuthenticationMechanismMame.IdentifiedOrganization = Convert.ToByte(arr[3]); AuthenticationMechanismMame.DlmsUA = Convert.ToByte(arr[4]); AuthenticationMechanismMame.AuthenticationMechanismName = Convert.ToByte(arr[5]); AuthenticationMechanismMame.MechanismId = (Authentication)Convert.ToByte(arr[6]); } } else if (index == 7) { Secret = (byte[])value; } else if (index == 8) { if (value == null) { AssociationStatus = AssociationStatus.NonAssociated; } else { AssociationStatus = (AssociationStatus)Convert.ToInt32(value); } } else if (index == 9) { SecuritySetupReference = GXDLMSClient.ChangeType((byte[])value, DataType.OctetString).ToString(); } else { throw new ArgumentException("SetValue failed. Invalid attribute index."); } }
object IGXDLMSBase.GetValue(GXDLMSSettings settings, ValueEventArgs e) { if (e.Index == 1) { return(GXCommon.LogicalNameToBytes(LogicalName)); } if (e.Index == 2) { return(MaxHops); } if (e.Index == 3) { return(WeakLqiValue); } if (e.Index == 4) { return(SecurityLevel); } if (e.Index == 5) { GXByteBuffer bb = new GXByteBuffer(); bb.SetUInt8((byte)DataType.Array); if (PrefixTable == null) { bb.SetUInt8(0); } else { GXCommon.SetObjectCount(PrefixTable.Length, bb); foreach (var it in PrefixTable) { GXCommon.SetData(settings, bb, GXDLMSConverter.GetDLMSDataType(it), it); } } return(bb.Array()); } if (e.Index == 6) { GXByteBuffer bb = new GXByteBuffer(); bb.SetUInt8((byte)DataType.Array); if (RoutingConfiguration == null) { bb.SetUInt8(0); } else { GXCommon.SetObjectCount(RoutingConfiguration.Count, bb); foreach (GXDLMSRoutingConfiguration it in RoutingConfiguration) { bb.SetUInt8((byte)DataType.Structure); bb.SetUInt8(14); GXCommon.SetData(settings, bb, DataType.UInt8, it.NetTraversalTime); GXCommon.SetData(settings, bb, DataType.UInt16, it.RoutingTableEntryTtl); GXCommon.SetData(settings, bb, DataType.UInt8, it.Kr); GXCommon.SetData(settings, bb, DataType.UInt8, it.Km); GXCommon.SetData(settings, bb, DataType.UInt8, it.Kc); GXCommon.SetData(settings, bb, DataType.UInt8, it.Kq); GXCommon.SetData(settings, bb, DataType.UInt8, it.Kh); GXCommon.SetData(settings, bb, DataType.UInt8, it.Krt); GXCommon.SetData(settings, bb, DataType.UInt8, it.RreqRetries); GXCommon.SetData(settings, bb, DataType.UInt8, it.RreqRerrWait); GXCommon.SetData(settings, bb, DataType.UInt16, it.BlacklistTableEntryTtl); GXCommon.SetData(settings, bb, DataType.Boolean, it.UnicastRreqGenEnable); GXCommon.SetData(settings, bb, DataType.Boolean, it.RlcEnabled); GXCommon.SetData(settings, bb, DataType.UInt8, it.AddRevLinkCost); } } return(bb.Array()); } if (e.Index == 7) { return(BroadcastLogTableEntryTtl); } if (e.Index == 8) { GXByteBuffer bb = new GXByteBuffer(); bb.SetUInt8((byte)DataType.Array); if (RoutingTable == null) { bb.SetUInt8(0); } else { GXCommon.SetObjectCount(RoutingTable.Count, bb); foreach (GXDLMSRoutingTable it in RoutingTable) { bb.SetUInt8((byte)DataType.Structure); bb.SetUInt8(6); GXCommon.SetData(settings, bb, DataType.UInt16, it.DestinationAddress); GXCommon.SetData(settings, bb, DataType.UInt16, it.NextHopAddress); GXCommon.SetData(settings, bb, DataType.UInt16, it.RouteCost); GXCommon.SetData(settings, bb, DataType.UInt8, it.HopCount); GXCommon.SetData(settings, bb, DataType.UInt8, it.WeakLinkCount); GXCommon.SetData(settings, bb, DataType.UInt16, it.ValidTime); } } return(bb.Array()); } if (e.Index == 9) { GXByteBuffer bb = new GXByteBuffer(); bb.SetUInt8((byte)DataType.Array); if (ContextInformationTable == null) { bb.SetUInt8(0); } else { GXCommon.SetObjectCount(ContextInformationTable.Count, bb); foreach (GXDLMSContextInformationTable it in ContextInformationTable) { bb.SetUInt8((byte)DataType.Structure); bb.SetUInt8(5); GXCommon.SetData(settings, bb, DataType.BitString, it.CID); if (it.Context == null) { GXCommon.SetData(settings, bb, DataType.UInt8, 0); } else { GXCommon.SetData(settings, bb, DataType.UInt8, it.Context.Length); } GXCommon.SetData(settings, bb, DataType.OctetString, it.Context); GXCommon.SetData(settings, bb, DataType.Boolean, it.Compression); GXCommon.SetData(settings, bb, DataType.UInt16, it.ValidLifetime); } } return(bb.Array()); } if (e.Index == 10) { GXByteBuffer bb = new GXByteBuffer(); bb.SetUInt8((byte)DataType.Array); if (BlacklistTable == null) { bb.SetUInt8(0); } else { GXCommon.SetObjectCount(BlacklistTable.Count, bb); foreach (var it in BlacklistTable) { bb.SetUInt8((byte)DataType.Structure); bb.SetUInt8(2); GXCommon.SetData(settings, bb, DataType.UInt16, it.Key); GXCommon.SetData(settings, bb, DataType.UInt16, it.Value); } } return(bb.Array()); } if (e.Index == 11) { GXByteBuffer bb = new GXByteBuffer(); bb.SetUInt8((byte)DataType.Array); if (BroadcastLogTable == null) { bb.SetUInt8(0); } else { GXCommon.SetObjectCount(BroadcastLogTable.Count, bb); foreach (GXDLMSBroadcastLogTable it in BroadcastLogTable) { bb.SetUInt8((byte)DataType.Structure); bb.SetUInt8(3); GXCommon.SetData(settings, bb, DataType.UInt16, it.SourceAddress); GXCommon.SetData(settings, bb, DataType.UInt8, it.SequenceNumber); GXCommon.SetData(settings, bb, DataType.UInt16, it.ValidTime); } } return(bb.Array()); } if (e.Index == 12) { GXByteBuffer bb = new GXByteBuffer(); bb.SetUInt8((byte)DataType.Array); if (GroupTable == null) { bb.SetUInt8(0); } else { GXCommon.SetObjectCount(GroupTable.Length, bb); foreach (UInt16 it in GroupTable) { GXCommon.SetData(settings, bb, DataType.UInt16, it); } } return(bb.Array()); } if (e.Index == 13) { return(MaxJoinWaitTime); } if (e.Index == 14) { return(PathDiscoveryTime); } if (e.Index == 15) { return(ActiveKeyIndex); } if (e.Index == 16) { return(MetricType); } if (e.Index == 17) { return(CoordShortAddress); } if (e.Index == 18) { return(DisableDefaultRouting); } if (e.Index == 19) { return(DeviceType); } e.Error = ErrorCode.ReadWriteDenied; return(null); }
object IGXDLMSBase.GetValue(GXDLMSSettings settings, ValueEventArgs e) { GXByteBuffer bb; switch (e.Index) { case 1: return(GXCommon.LogicalNameToBytes(LogicalName)); case 2: if (string.IsNullOrEmpty(Operator)) { return(null); } return(ASCIIEncoding.ASCII.GetBytes(Operator)); case 3: return(Status); case 4: return(CircuitSwitchStatus); case 5: return(PacketSwitchStatus); case 6: bb = new GXByteBuffer(); bb.SetUInt8(DataType.Structure); if (Version == 0) { bb.SetUInt8(4); GXCommon.SetData(settings, bb, DataType.UInt16, CellInfo.CellId); } else { bb.SetUInt8(7); GXCommon.SetData(settings, bb, DataType.UInt32, CellInfo.CellId); } GXCommon.SetData(settings, bb, DataType.UInt16, CellInfo.LocationId); GXCommon.SetData(settings, bb, DataType.UInt8, CellInfo.SignalQuality); GXCommon.SetData(settings, bb, DataType.UInt8, CellInfo.Ber); if (Version > 0) { GXCommon.SetData(settings, bb, DataType.UInt16, CellInfo.MobileCountryCode); GXCommon.SetData(settings, bb, DataType.UInt16, CellInfo.MobileNetworkCode); GXCommon.SetData(settings, bb, DataType.UInt32, CellInfo.ChannelNumber); } return(bb.Array()); case 7: bb = new GXByteBuffer(); bb.SetUInt8(DataType.Array); if (AdjacentCells == null) { bb.SetUInt8(0); } else { bb.SetUInt8((byte)AdjacentCells.Count); } foreach (AdjacentCell it in AdjacentCells) { bb.SetUInt8(DataType.Structure); bb.SetUInt8(2); GXCommon.SetData(settings, bb, Version == 0 ? DataType.UInt16 : DataType.UInt32, it.CellId); GXCommon.SetData(settings, bb, DataType.UInt8, it.SignalQuality); } return(bb.Array()); case 8: return(CaptureTime); } e.Error = ErrorCode.ReadWriteDenied; return(null); }
/// <summary> /// Import server settings and COSEM objects from GXDLMSDirector trace. /// </summary> /// <param name="server">Server where settings are updated.</param> /// <param name="data">GXDLMSDirector trace in byte array.</param> public static void Import(GXDLMSServer server, byte[] data) { GXDLMSTranslator translator = new GXDLMSTranslator(TranslatorOutputType.StandardXml); translator.CompletePdu = true; translator.PduOnly = true; translator.OmitXmlNameSpace = translator.OmitXmlDeclaration = true; XmlDocument doc = new XmlDocument(); List <ValueEventArgs> targets = new List <ValueEventArgs>(); GXDLMSSettings settings = new GXDLMSSettings(true); GXByteBuffer pdu = new GXByteBuffer(); GXByteBuffer bb = new GXByteBuffer(data); server.InterfaceType = GXDLMSTranslator.GetDlmsFraming(bb); bool lastBlock = true; GXByteBuffer val = new DLMS.GXByteBuffer(); while (translator.FindNextFrame(bb, pdu, server.InterfaceType)) { String xml = translator.MessageToXml(bb); if (xml != "") { doc.LoadXml(xml); foreach (XmlNode node in doc.ChildNodes[doc.ChildNodes.Count - 1].ChildNodes) { string name = doc.ChildNodes[doc.ChildNodes.Count - 1].Name; if (name == "get-request") { server.UseLogicalNameReferencing = true; GetLN(settings.Objects, targets, node.ChildNodes); } else if (name == "read-request") { List <short> items = GetSN(node.ChildNodes); server.UseLogicalNameReferencing = false; foreach (short it in items) { GXSNInfo i = GXDLMSSNCommandHandler.FindSNObject(settings.Objects, Convert.ToUInt16((it) & 0xFFFF)); targets.Add(new ValueEventArgs(i.Item, i.Index, 0, null)); } } else if (name == "read-response" || name == "get-response") { if (targets != null) { List <string> items; if (server.UseLogicalNameReferencing) { items = GetLNValues(doc.ChildNodes[doc.ChildNodes.Count - 1].ChildNodes); } else { items = GetSNValues(doc.ChildNodes[doc.ChildNodes.Count - 1].ChildNodes); } int pos = 0; foreach (string it in items) { if ("read-write-denied".Equals(it) || "scope-of-access-violated".Equals(it) || "object-unavailable".Equals(it)) { ValueEventArgs ve = targets[pos]; ve.Target.SetAccess(ve.Index, AccessMode.NoAccess); continue; } try { if (server.UseLogicalNameReferencing) { lastBlock = IsLastBlock(doc.ChildNodes[doc.ChildNodes.Count - 1].ChildNodes); } val.Set(translator.XmlToData(it)); if (lastBlock) { if (settings.Objects.Count == 0) { GXDLMSClient c = new GXDLMSClient(); c.UseLogicalNameReferencing = server.UseLogicalNameReferencing; settings.Objects = c.ParseObjects(val, true); //Update OBIS code description. GXDLMSConverter converter = new GXDLMSConverter(); converter.UpdateOBISCodeInformation(settings.Objects); } else { ValueEventArgs ve = targets[pos]; GXDataInfo info = new GXDataInfo(); ve.Value = GXCommon.GetData(server.Settings, val, info); if (ve.Value is byte[]) { DataType tp = ve.Target.GetUIDataType(ve.Index); if (tp != DataType.None) { ve.Value = GXDLMSClient.ChangeType((byte[])ve.Value, tp, false); } } ((IGXDLMSBase)ve.Target).SetValue(settings, ve); } val.Clear(); } } catch (Exception) { ValueEventArgs ve = targets[pos]; ve.Target.SetAccess(ve.Index, AccessMode.NoAccess); } ++pos; } if (lastBlock) { targets.Clear(); } } } } } } server.Items.Clear(); server.Items.AddRange(settings.Objects); }
private static byte[] GetAuthenticatedData(Gurux.DLMS.Enums.Security security, byte[] AuthenticationKey, byte[] plainText) { if (security == Gurux.DLMS.Enums.Security.Authentication) { GXByteBuffer tmp2 = new GXByteBuffer(); tmp2.SetUInt8((byte)security); tmp2.Set(AuthenticationKey); tmp2.Set(plainText); return tmp2.Array(); } else if (security == Gurux.DLMS.Enums.Security.Encryption) { return AuthenticationKey; } else if (security == Gurux.DLMS.Enums.Security.AuthenticationEncryption) { GXByteBuffer tmp2 = new GXByteBuffer(); tmp2.SetUInt8((byte)security); tmp2.Set(AuthenticationKey); return tmp2.Array(); } return null; }
object IGXDLMSBase.GetValue(GXDLMSSettings settings, ValueEventArgs e) { if (e.Index == 1) { return this.LogicalName; } if (e.Index == 2) { return (byte)Mode; } if (e.Index == 3) { int cnt = ListeningWindow.Count; GXByteBuffer data = new GXByteBuffer(); data.SetUInt8((byte)DataType.Array); //Add count GXCommon.SetObjectCount(cnt, data); if (cnt != 0) { foreach (var it in ListeningWindow) { data.SetUInt8((byte)DataType.Structure); data.SetUInt8((byte)2); //Count GXCommon.SetData(settings, data, DataType.OctetString, it.Key); //start_time GXCommon.SetData(settings, data, DataType.OctetString, it.Value); //end_time } } return data.Array(); } if (e.Index == 4) { return Status; } if (e.Index == 5) { return NumberOfCalls; } if (e.Index == 6) { GXByteBuffer data = new GXByteBuffer(); data.SetUInt8((byte)DataType.Structure); //Add count GXCommon.SetObjectCount(2, data); GXCommon.SetData(settings, data, DataType.UInt8, NumberOfRingsInListeningWindow); GXCommon.SetData(settings, data, DataType.UInt8, NumberOfRingsOutListeningWindow); return data.Array(); } e.Error = ErrorCode.ReadWriteDenied; return null; }
static internal byte[] EncryptAesGcm(AesGcmParameter param, byte[] plainText) { System.Diagnostics.Debug.WriteLine("Encrypt settings: " + param.ToString()); param.CountTag = null; GXByteBuffer data = new GXByteBuffer(); if (param.Type == CountType.Packet) { data.SetUInt8((byte)param.Security); } byte[] tmp = BitConverter.GetBytes(param.FrameCounter).Reverse().ToArray(); byte[] aad = GetAuthenticatedData(param.Security, param.AuthenticationKey, plainText); GXDLMSChipperingStream gcm = new GXDLMSChipperingStream(param.Security, true, param.BlockCipherKey, aad, GetNonse(param.FrameCounter, param.SystemTitle), null); // Encrypt the secret message if (param.Security != Gurux.DLMS.Enums.Security.Authentication) { gcm.Write(plainText); } byte[] ciphertext = gcm.FlushFinalBlock(); if (param.Security == Gurux.DLMS.Enums.Security.Authentication) { if (param.Type == CountType.Packet) { data.Set(tmp); } if ((param.Type & CountType.Data) != 0) { data.Set(plainText); } if ((param.Type & CountType.Tag) != 0) { param.CountTag = gcm.GetTag(); data.Set(param.CountTag); } } else if (param.Security == Gurux.DLMS.Enums.Security.Encryption) { if (param.Type == CountType.Packet) { data.Set(tmp); } data.Set(ciphertext); } else if (param.Security == Gurux.DLMS.Enums.Security.AuthenticationEncryption) { if (param.Type == CountType.Packet) { data.Set(tmp); } if ((param.Type & CountType.Data) != 0) { data.Set(ciphertext); } if ((param.Type & CountType.Tag) != 0) { param.CountTag = gcm.GetTag(); data.Set(param.CountTag); } } else { throw new ArgumentOutOfRangeException("security"); } if (param.Type == CountType.Packet) { GXByteBuffer tmp2 = new GXByteBuffer((ushort)(10 + data.Size)); tmp2.SetUInt8(param.Tag); GXCommon.SetObjectCount(data.Size, tmp2); tmp2.Set(data.Array()); return tmp2.Array(); } byte[] crypted = data.Array(); System.Diagnostics.Debug.WriteLine("Crypted: " + GXCommon.ToHex(crypted, true)); return crypted; }
object IGXDLMSBase.GetValue(GXDLMSSettings settings, ValueEventArgs e) { if (e.Index == 1) { return(GXCommon.LogicalNameToBytes(LogicalName)); } if (e.Index == 2) { return(GXCommon.LogicalNameToBytes(DataLinkLayerReference)); } if (e.Index == 3) { return(FromAddressString(IPAddress)); } if (e.Index == 4) { GXByteBuffer data = new GXByteBuffer(); data.SetUInt8((byte)DataType.Array); if (MulticastIPAddress == null) { //Object count is zero. data.SetUInt8(0); } else { GXCommon.SetObjectCount(MulticastIPAddress.Length, data); foreach (string it in MulticastIPAddress) { GXCommon.SetData(settings, data, DataType.UInt32, FromAddressString(it)); } } return(data.Array()); } if (e.Index == 5) { GXByteBuffer data = new GXByteBuffer(); data.SetUInt8((byte)DataType.Array); if (IPOptions == null) { //Object count is zero. data.SetUInt8(0); } else { GXCommon.SetObjectCount(IPOptions.Length, data); foreach (GXDLMSIp4SetupIpOption it in IPOptions) { data.SetUInt8((byte)DataType.Structure); data.SetUInt8(3); GXCommon.SetData(settings, data, DataType.UInt8, it.Type); GXCommon.SetData(settings, data, DataType.UInt8, it.Length); GXCommon.SetData(settings, data, DataType.OctetString, it.Data); } } return(data.Array()); } if (e.Index == 6) { //If subnet mask is not given. return(FromAddressString(SubnetMask)); } if (e.Index == 7) { return(FromAddressString(GatewayIPAddress)); } if (e.Index == 8) { return(this.UseDHCP); } if (e.Index == 9) { return(FromAddressString(PrimaryDNSAddress)); } if (e.Index == 10) { return(FromAddressString(SecondaryDNSAddress)); } e.Error = ErrorCode.ReadWriteDenied; return(null); }
private static void GetValue(GXByteBuffer bb, IList <object> objects, GXAsn1Settings s) { int len; short type; IList <object> tmp; byte[] tmp2; type = bb.GetUInt8(); len = GXCommon.GetObjectCount(bb); if (len > bb.Available) { throw new OutOfMemoryException("GXAsn1Converter.GetValue"); } int connectPos = 0; if (s != null) { connectPos = s.XmlLength; } int start = bb.Position; string tagString = null; if (s != null) { s.AppendSpaces(); if (type == (byte)BerType.Integer) { if (len == 1 || len == 2 || len == 4 || len == 8) { tagString = s.GetTag((short)-len); } else { tagString = s.GetTag((byte)BerType.Integer); } } else { tagString = s.GetTag(type); } s.Append("<" + tagString + ">"); } switch (type) { case (byte)(BerType.Constructed | BerType.Context): case ((byte)(BerType.Constructed | BerType.Context) | 1): case ((byte)(BerType.Constructed | BerType.Context) | 2): case ((byte)(BerType.Constructed | BerType.Context) | 3): if (s != null) { s.Increase(); } tmp = new GXAsn1Context(); ((GXAsn1Context)tmp).Index = type & 0xF; objects.Add(tmp); while (bb.Position < start + len) { GetValue(bb, tmp, s); } if (s != null) { s.Decrease(); } break; case (byte)(BerType.Constructed | BerType.Sequence): if (s != null) { s.Increase(); } tmp = new GXAsn1Sequence(); objects.Add(tmp); int cnt = 0; while (bb.Position < start + len) { ++cnt; GetValue(bb, tmp, s); } if (s != null) { // Append comment. s.AppendComment(connectPos, Convert.ToString(cnt) + " elements."); s.Decrease(); } break; case (byte)(BerType.Constructed | BerType.Set): if (s != null) { s.Increase(); } tmp = new List <object>(); GetValue(bb, tmp, s); if (tmp[0] is GXAsn1Sequence) { tmp = (GXAsn1Sequence)tmp[0]; objects.Add(new KeyValuePair <object, object>(tmp[0], tmp[1])); } else { KeyValuePair <object, object> e = new KeyValuePair <object, object>(tmp, null); objects.Add(e); } if (s != null) { s.Decrease(); } break; case (byte)BerType.ObjectIdentifier: GXAsn1ObjectIdentifier oi = new GXAsn1ObjectIdentifier(bb, len); objects.Add(oi); if (s != null) { string str = oi.Description; if (str != null) { s.AppendComment(connectPos, str); } s.Append(oi.ToString()); } break; case (byte)BerType.PrintableString: objects.Add(bb.GetString(len)); if (s != null) { s.Append(Convert.ToString(objects[objects.Count - 1])); } break; case (byte)BerType.Utf8StringTag: objects.Add(new GXAsn1Utf8String(bb.GetString(bb.Position, len))); bb.Position = bb.Position + len; if (s != null) { s.Append(Convert.ToString(objects[objects.Count - 1])); } break; case (byte)BerType.Ia5String: objects.Add(new GXAsn1Ia5String(bb.GetString(len))); if (s != null) { s.Append(Convert.ToString(objects[objects.Count - 1])); } break; case (byte)BerType.Integer: if (len == 1) { objects.Add(bb.GetInt8()); } else if (len == 2) { objects.Add(bb.GetInt16()); } else if (len == 4) { objects.Add(bb.GetInt32()); } else { tmp2 = new byte[len]; bb.Get(tmp2); objects.Add(new GXAsn1Integer(tmp2)); } if (s != null) { s.Append(Convert.ToString(objects[objects.Count - 1])); } break; case (byte)BerType.Null: objects.Add(null); break; case (byte)BerType.BitString: GXAsn1BitString tmp3 = new GXAsn1BitString(bb.SubArray(bb.Position, len)); objects.Add(tmp3); bb.Position = bb.Position + len; if (s != null) { // Append comment. s.AppendComment(connectPos, Convert.ToString(tmp3.Length) + " bit."); s.Append(tmp3.asString()); } break; case (byte)BerType.UtcTime: tmp2 = new byte[len]; bb.Get(tmp2); objects.Add(GetUtcTime(ASCIIEncoding.ASCII.GetString(tmp2))); if (s != null) { s.Append(((DateTimeOffset)objects[objects.Count - 1]).UtcDateTime.ToString("yyyy-MM-dd HH:mm", CultureInfo.InvariantCulture)); } break; case (byte)BerType.GeneralizedTime: tmp2 = new byte[len]; bb.Get(tmp2); objects.Add(GXCommon.GetGeneralizedTime(ASCIIEncoding.ASCII.GetString(tmp2))); if (s != null) { s.Append(Convert.ToString(objects[objects.Count - 1])); } break; case (byte)BerType.Context: case (byte)BerType.Context | 1: tmp2 = new byte[len]; bb.Get(tmp2); objects.Add(tmp2); if (s != null) { s.Append(GXCommon.ToHex(tmp2, false)); } break; case (byte)BerType.OctetString: int t = bb.GetUInt8(bb.Position); switch (t) { case (byte)(BerType.Constructed | BerType.Sequence): case (byte)BerType.BitString: if (s != null) { s.Increase(); } GetValue(bb, objects, s); if (s != null) { s.Decrease(); } break; default: tmp2 = new byte[len]; bb.Get(tmp2); objects.Add(tmp2); if (s != null) { s.Append(GXCommon.ToHex(tmp2, false)); } break; } break; case (byte)BerType.Boolean: bool b = bb.GetUInt8() != 0; objects.Add(b); if (s != null) { s.Append(Convert.ToString(b)); } break; default: throw new System.ArgumentException("Invalid type: " + type); } if (s != null) { s.Append("</" + tagString + ">\r\n"); } }
object IGXDLMSBase.GetValue(GXDLMSSettings settings, ValueEventArgs e) { if (e.Index == 1) { return(GXCommon.LogicalNameToBytes(LogicalName)); } if (e.Index == 2) { return(GXCommon.LogicalNameToBytes(PHYReference)); } if (e.Index == 3) { GXByteBuffer data = new GXByteBuffer(); data.SetUInt8((byte)DataType.Array); if (LCPOptions == null) { data.SetUInt8(0); } else { data.SetUInt8((byte)LCPOptions.Length); foreach (GXDLMSPppSetupLcpOption it in LCPOptions) { data.SetUInt8((byte)DataType.Structure); data.SetUInt8((byte)3); GXCommon.SetData(settings, data, DataType.UInt8, it.Type); GXCommon.SetData(settings, data, DataType.UInt8, it.Length); GXCommon.SetData(settings, data, GXCommon.GetValueType(it.Data), it.Data); } } return(data.Array()); } if (e.Index == 4) { GXByteBuffer data = new GXByteBuffer(); data.SetUInt8((byte)DataType.Array); if (IPCPOptions == null) { data.SetUInt8(0); } else { data.SetUInt8((byte)IPCPOptions.Length); foreach (GXDLMSPppSetupIPCPOption it in IPCPOptions) { data.SetUInt8((byte)DataType.Structure); data.SetUInt8((byte)3); GXCommon.SetData(settings, data, DataType.UInt8, it.Type); GXCommon.SetData(settings, data, DataType.UInt8, it.Length); GXCommon.SetData(settings, data, GXCommon.GetValueType(it.Data), it.Data); } } return(data.Array()); } else if (e.Index == 5) { GXByteBuffer data = new GXByteBuffer(); data.SetUInt8((byte)DataType.Structure); data.SetUInt8(2); GXCommon.SetData(settings, data, DataType.OctetString, UserName); GXCommon.SetData(settings, data, DataType.OctetString, Password); return(data.Array()); } e.Error = ErrorCode.ReadWriteDenied; return(null); }
/// <summary> /// Convert ASN.1 PDU bytes to XML. /// </summary> /// <param name="value">Bytes to convert. </param> /// <returns> Converted XML. </returns> public static string PduToXml(GXByteBuffer value) { return(PduToXml(value, false)); }
object IGXDLMSBase.GetValue(GXDLMSSettings settings, ValueEventArgs e) { GXByteBuffer buff = new GXByteBuffer(); object ret; switch (e.Index) { case 1: ret = GXCommon.LogicalNameToBytes(LogicalName); break; case 2: ret = GetPushObjectList(settings); break; case 3: buff.SetUInt8(DataType.Structure); buff.SetUInt8(3); GXCommon.SetData(settings, buff, DataType.Enum, Service); if (Destination != null) { GXCommon.SetData(settings, buff, DataType.OctetString, ASCIIEncoding.ASCII.GetBytes(Destination)); } else { GXCommon.SetData(settings, buff, DataType.OctetString, null); } GXCommon.SetData(settings, buff, DataType.Enum, Message); ret = buff.Array(); break; case 4: buff.SetUInt8(DataType.Array); GXCommon.SetObjectCount(CommunicationWindow.Count, buff); foreach (KeyValuePair <GXDateTime, GXDateTime> it in CommunicationWindow) { buff.SetUInt8(DataType.Structure); buff.SetUInt8(2); GXCommon.SetData(settings, buff, DataType.OctetString, it.Key); GXCommon.SetData(settings, buff, DataType.OctetString, it.Value); } ret = buff.Array(); break; case 5: ret = RandomisationStartInterval; break; case 6: ret = NumberOfRetries; break; case 7: ret = RepetitionDelay; break; default: e.Error = ErrorCode.ReadWriteDenied; ret = null; break; } return(ret); }
private void Init(byte[] data) { Attributes = new List <KeyValuePair <PkcsObjectIdentifier, object[]> >(); GXAsn1Sequence seq = (GXAsn1Sequence)GXAsn1Converter.FromByteArray(data); if (seq.Count < 3) { throw new System.ArgumentException("Wrong number of elements in sequence."); } ///////////////////////////// // CertificationRequestInfo ::= SEQUENCE { // version INTEGER { v1(0) } (v1,...), // subject Name, // subjectPKInfo SubjectPublicKeyInfo{{ PKInfoAlgorithms }}, // attributes [0] Attributes{{ CRIAttributes }} // } GXAsn1Sequence reqInfo = (GXAsn1Sequence)seq[0]; Version = (CertificateVersion)(sbyte)reqInfo[0]; Subject = GXAsn1Converter.GetSubject((GXAsn1Sequence)reqInfo[1]); // subject Public key info. GXAsn1Sequence subjectPKInfo = (GXAsn1Sequence)reqInfo[2]; if (reqInfo.Count > 3) { //PkcsObjectIdentifier foreach (GXAsn1Sequence it in (GXAsn1Context)reqInfo[3]) { List <object> values = new List <object>(); foreach (object v in (List <object>)((KeyValuePair <object, object>)it[1]).Key) { values.Add(v); } Attributes.Add(new KeyValuePair <PkcsObjectIdentifier, object[]>(PkcsObjectIdentifierConverter.FromString(it[0].ToString()), values.ToArray())); } } GXAsn1Sequence tmp = (GXAsn1Sequence)subjectPKInfo[0]; Algorithm = X9ObjectIdentifierConverter.FromString(tmp[0].ToString()); if (Algorithm != X9ObjectIdentifier.IdECPublicKey) { object algorithm = Algorithm; if (Algorithm == X9ObjectIdentifier.None) { algorithm = PkcsObjectIdentifierConverter.FromString(tmp[0].ToString()); if ((PkcsObjectIdentifier)algorithm == PkcsObjectIdentifier.None) { algorithm = tmp[0].ToString(); } } throw new Exception("Invalid PKCS #10 certificate algorithm. " + algorithm); } PublicKey = GXPublicKey.FromRawBytes(((GXAsn1BitString)subjectPKInfo[1]).Value); GXEcdsa.Validate(PublicKey); ///////////////////////////// // signatureAlgorithm GXAsn1Sequence sign = (GXAsn1Sequence)seq[1]; SignatureAlgorithm = HashAlgorithmConverter.FromString(sign[0].ToString()); if (SignatureAlgorithm != HashAlgorithm.Sha256WithEcdsa && SignatureAlgorithm != HashAlgorithm.Sha384WithEcdsa) { throw new GXDLMSCertificateException("Invalid signature algorithm. " + sign[0].ToString()); } if (sign.Count != 1) { SignatureParameters = sign[1]; } ///////////////////////////// // signature Signature = ((GXAsn1BitString)seq[2]).Value; GXEcdsa e = new GXEcdsa(PublicKey); GXAsn1Sequence tmp2 = (GXAsn1Sequence)GXAsn1Converter.FromByteArray(Signature); GXByteBuffer bb = new GXByteBuffer(); int size = SignatureAlgorithm == HashAlgorithm.Sha256WithEcdsa ? 32 : 48; //Some implementations might add extra byte. It must removed. bb.Set(((GXAsn1Integer)tmp2[0]).Value, ((GXAsn1Integer)tmp2[0]).Value.Length == size ? 0 : 1, size); bb.Set(((GXAsn1Integer)tmp2[1]).Value, ((GXAsn1Integer)tmp2[1]).Value.Length == size ? 0 : 1, size); if (!e.Verify(bb.Array(), GXAsn1Converter.ToByteArray(reqInfo))) { throw new ArgumentException("Invalid Signature."); } }
///<summary> /// Chipher text. ///</summary> ///<param name="settings"> ///DLMS settings. ///</param> ///<param name="cipher"> ///Cipher. ///</param> ///<param name="ic"> ///Invocation counter. ///</param> ///<param name="data"> ///Text to chipher. ///</param> ///<param name="secret"> ///Secret. ///</param> ///<returns> ///Chiphered text. ///</returns> public static byte[] Secure(GXDLMSSettings settings, GXICipher cipher, UInt32 ic, byte[] data, byte[] secret) { byte[] tmp; if (settings.Authentication == Authentication.High) { int len = secret.Length; if (len % 16 != 0) { len += 16 - (secret.Length % 16); } byte[] p = new byte[len]; byte[] s = new byte[16]; byte[] x = new byte[16]; int i; data.CopyTo(p, 0); secret.CopyTo(s, 0); for (i = 0; i < p.Length; i += 16) { Buffer.BlockCopy(p, i, x, 0, 16); GXAes128.Encrypt(x, s); Buffer.BlockCopy(x, 0, p, i, 16); } Buffer.BlockCopy(p, 0, x, 0, 16); return(x); } // Get server Challenge. GXByteBuffer challenge = new GXByteBuffer(); // Get shared secret if (settings.Authentication == Authentication.HighGMAC) { challenge.Set(data); } else { challenge.Set(data); challenge.Set(secret); } tmp = challenge.Array(); if (settings.Authentication == Authentication.HighMD5) { #if !WINDOWS_UWP using (MD5 md5Hash = MD5.Create()) { tmp = md5Hash.ComputeHash(tmp); return(tmp); } #endif } else if (settings.Authentication == Authentication.HighSHA1) { #if !WINDOWS_UWP using (SHA1 sha = new SHA1CryptoServiceProvider()) { tmp = sha.ComputeHash(tmp); return(tmp); } #endif } else if (settings.Authentication == Authentication.HighSHA256) { //Windows UWP, IOS ad Android don't support this. #if !WINDOWS_UWP && !__IOS__ && !__ANDROID__ using (SHA256 sha = new SHA256CryptoServiceProvider()) { tmp = sha.ComputeHash(tmp); return(tmp); } #endif } else if (settings.Authentication == Authentication.HighGMAC) { //SC is always Security.Authentication. AesGcmParameter p = new AesGcmParameter(0, Enums.Security.Authentication, ic, secret, cipher.BlockCipherKey, cipher.AuthenticationKey); p.Type = CountType.Tag; challenge.Clear(); challenge.SetUInt8((byte)Enums.Security.Authentication); challenge.SetUInt32((UInt32)p.InvocationCounter); challenge.Set(GXDLMSChippering.EncryptAesGcm(p, tmp)); tmp = challenge.Array(); return(tmp); } return(data); }
///<summary> /// Chipher text. ///</summary> ///<param name="settings"> ///DLMS settings. ///</param> ///<param name="cipher"> ///Cipher. ///</param> ///<param name="ic"> ///Invocation counter. ///</param> ///<param name="data"> ///Text to chipher. ///</param> ///<param name="secret"> ///Secret. ///</param> ///<returns> ///Chiphered text. ///</returns> public static byte[] Secure(GXDLMSSettings settings, GXICipher cipher, UInt32 ic, byte[] data, byte[] secret) { byte[] tmp; if (settings.Authentication == Authentication.High) { int len = secret.Length; if (len % 16 != 0) { len += 16 - (secret.Length % 16); } byte[] p = new byte[len]; byte[] s = new byte[16]; byte[] x = new byte[16]; int i; data.CopyTo(p, 0); secret.CopyTo(s, 0); for (i = 0; i < p.Length; i += 16) { Buffer.BlockCopy(p, i, x, 0, 16); GXAes128.Encrypt(x, s); Buffer.BlockCopy(x, 0, p, i, 16); } Buffer.BlockCopy(p, 0, x, 0, 16); return x; } // Get server Challenge. GXByteBuffer challenge = new GXByteBuffer(); // Get shared secret if (settings.Authentication == Authentication.HighGMAC) { challenge.Set(data); } else { challenge.Set(data); challenge.Set(secret); } tmp = challenge.Array(); if (settings.Authentication == Authentication.HighMD5) { using (MD5 md5Hash = MD5.Create()) { tmp = md5Hash.ComputeHash(tmp); return tmp; } } else if (settings.Authentication == Authentication.HighSHA1) { using (SHA1 sha = new SHA1CryptoServiceProvider()) { tmp = sha.ComputeHash(tmp); return tmp; } } else if (settings.Authentication == Authentication.HighGMAC) { //SC is always Security.Authentication. AesGcmParameter p = new AesGcmParameter(0, Security.Authentication, ic, secret, cipher.BlockCipherKey, cipher.AuthenticationKey); p.Type = CountType.Tag; challenge.Clear(); challenge.SetUInt8((byte)Security.Authentication); challenge.SetUInt32(p.FrameCounter); challenge.Set(GXDLMSChippering.EncryptAesGcm(p, tmp)); tmp = challenge.Array(); return tmp; } return data; }
void IGXDLMSBase.SetValue(GXDLMSSettings settings, ValueEventArgs e) { if (e.Index == 1) { LogicalName = GXCommon.ToLogicalName(e.Value); } else if (e.Index == 2) { if (e.Value is byte[] v) { if (IsSec() || !GXByteBuffer.IsAsciiString(v)) { CalendarNameActive = GXCommon.ToHex(v, false); } else { CalendarNameActive = ASCIIEncoding.ASCII.GetString(v); } } else { CalendarNameActive = Convert.ToString(e.Value); } } else if (e.Index == 3) { SeasonProfileActive = SetSeasonProfile(settings, e.Value); } else if (e.Index == 4) { WeekProfileTableActive = SetWeekProfileTable(settings, e.Value); } else if (e.Index == 5) { DayProfileTableActive = SetDayProfileTable(settings, e.Value); } else if (e.Index == 6) { if (e.Value is byte[] v) { if (IsSec() || !GXByteBuffer.IsAsciiString(v)) { CalendarNamePassive = GXCommon.ToHex(v, false); } else { CalendarNamePassive = ASCIIEncoding.ASCII.GetString(v); } } else { CalendarNamePassive = Convert.ToString(e.Value); } } else if (e.Index == 7) { SeasonProfilePassive = SetSeasonProfile(settings, e.Value); } else if (e.Index == 8) { WeekProfileTablePassive = SetWeekProfileTable(settings, e.Value); } else if (e.Index == 9) { DayProfileTablePassive = SetDayProfileTable(settings, e.Value); } else if (e.Index == 10) { if (e.Value is byte[]) { Time = (GXDateTime)GXDLMSClient.ChangeType((byte[])e.Value, DataType.DateTime, settings.UseUtc2NormalTime); } else { Time = new GXDateTime(Convert.ToDateTime(e.Value)); } } else { e.Error = ErrorCode.ReadWriteDenied; } }
private void GetAccessRights(GXDLMSSettings settings, GXDLMSObject item, GXDLMSServer server, GXByteBuffer data) { data.SetUInt8((byte)DataType.Structure); data.SetUInt8((byte)2); data.SetUInt8((byte)DataType.Array); int cnt = (item as IGXDLMSBase).GetAttributeCount(); data.SetUInt8((byte)cnt); ValueEventArgs e; if (server != null) { e = new DLMS.ValueEventArgs(server, item, 0, 0, null); } else { e = new DLMS.ValueEventArgs(settings, item, 0, 0, null); } for (int pos = 0; pos != cnt; ++pos) { e.Index = pos + 1; AccessMode m; if (server != null) { m = server.NotifyGetAttributeAccess(e); } else { m = AccessMode.ReadWrite; } //attribute_access_item data.SetUInt8((byte)DataType.Structure); data.SetUInt8((byte)3); GXCommon.SetData(settings, data, DataType.Int8, e.Index); GXCommon.SetData(settings, data, DataType.Enum, m); GXCommon.SetData(settings, data, DataType.None, null); } data.SetUInt8((byte)DataType.Array); cnt = (item as IGXDLMSBase).GetMethodCount(); data.SetUInt8((byte)cnt); for (int pos = 0; pos != cnt; ++pos) { e.Index = pos + 1; MethodAccessMode m; if (server != null) { m = server.NotifyGetMethodAccess(e); } else { m = MethodAccessMode.Access; } //attribute_access_item data.SetUInt8((byte)DataType.Structure); data.SetUInt8((byte)2); GXCommon.SetData(settings, data, DataType.Int8, pos + 1); GXCommon.SetData(settings, data, DataType.Enum, m); } }
object IGXDLMSBase.GetValue(GXDLMSSettings settings, ValueEventArgs e) { if (e.Index == 1) { return(GXCommon.LogicalNameToBytes(LogicalName)); } GXByteBuffer buff = new GXByteBuffer(); if (e.Index == 2) { buff.SetUInt8(DataType.Array); GXCommon.SetObjectCount(PushObjectList.Count, buff); foreach (KeyValuePair <GXDLMSObject, GXDLMSCaptureObject> it in PushObjectList) { buff.SetUInt8(DataType.Structure); buff.SetUInt8(4); GXCommon.SetData(settings, buff, DataType.UInt16, it.Key.ObjectType); GXCommon.SetData(settings, buff, DataType.OctetString, GXCommon.LogicalNameToBytes(it.Key.LogicalName)); GXCommon.SetData(settings, buff, DataType.Int8, it.Value.AttributeIndex); GXCommon.SetData(settings, buff, DataType.UInt16, it.Value.DataIndex); } return(buff.Array()); } if (e.Index == 3) { buff.SetUInt8(DataType.Structure); buff.SetUInt8(3); GXCommon.SetData(settings, buff, DataType.UInt8, Service); if (Destination != null) { GXCommon.SetData(settings, buff, DataType.OctetString, ASCIIEncoding.ASCII.GetBytes(Destination)); } else { GXCommon.SetData(settings, buff, DataType.OctetString, null); } GXCommon.SetData(settings, buff, DataType.UInt8, Message); return(buff.Array()); } if (e.Index == 4) { buff.SetUInt8(DataType.Array); GXCommon.SetObjectCount(CommunicationWindow.Count, buff); foreach (KeyValuePair <GXDateTime, GXDateTime> it in CommunicationWindow) { buff.SetUInt8(DataType.Structure); buff.SetUInt8(2); GXCommon.SetData(settings, buff, DataType.OctetString, it.Key); GXCommon.SetData(settings, buff, DataType.OctetString, it.Value); } return(buff.Array()); } if (e.Index == 5) { return(RandomisationStartInterval); } if (e.Index == 6) { return(NumberOfRetries); } if (e.Index == 7) { return(RepetitionDelay); } e.Error = ErrorCode.ReadWriteDenied; return(null); }
void IGXDLMSBase.SetValue(GXDLMSSettings settings, ValueEventArgs e) { if (e.Index == 1) { LogicalName = GXCommon.ToLogicalName(e.Value); } else if (e.Index == 2) { ObjectList.Clear(); if (e.Value != null) { foreach (Object[] item in (Object[])e.Value) { GXDLMSObject obj = GetObject(settings, item); //Unknown objects are not shown. if (obj is IGXDLMSBase) { ObjectList.Add(obj); } } } } else if (e.Index == 3) { if (e.Value != null) { ClientSAP = Convert.ToByte(((Object[])e.Value)[0]); ServerSAP = Convert.ToUInt16(((Object[])e.Value)[1]); } } else if (e.Index == 4) { //Value of the object identifier encoded in BER if (e.Value is byte[]) { GXByteBuffer arr = new GXByteBuffer(e.Value as byte[]); if (arr.GetUInt8(0) == 0x60) { ApplicationContextName.JointIsoCtt = arr.GetUInt8(); ApplicationContextName.Country = arr.GetUInt8(); ApplicationContextName.CountryName = arr.GetUInt8(); ApplicationContextName.IdentifiedOrganization = arr.GetUInt8(); ApplicationContextName.DlmsUA = arr.GetUInt8(); ApplicationContextName.ApplicationContext = arr.GetUInt8(); ApplicationContextName.ContextId = (ApplicationContextName)arr.GetUInt8(); } else { //Get Tag and Len. if (arr.GetUInt8() != (int)BerType.Integer && arr.GetUInt8() != 7) { throw new ArgumentOutOfRangeException(); } //Get tag if (arr.GetUInt8() != 0x11) { throw new ArgumentOutOfRangeException(); } ApplicationContextName.JointIsoCtt = arr.GetUInt8(); //Get tag if (arr.GetUInt8() != 0x11) { throw new ArgumentOutOfRangeException(); } ApplicationContextName.Country = arr.GetUInt8(); //Get tag if (arr.GetUInt8() != 0x12) { throw new ArgumentOutOfRangeException(); } ApplicationContextName.CountryName = arr.GetUInt16(); //Get tag if (arr.GetUInt8() != 0x11) { throw new ArgumentOutOfRangeException(); } ApplicationContextName.IdentifiedOrganization = arr.GetUInt8(); //Get tag if (arr.GetUInt8() != 0x11) { throw new ArgumentOutOfRangeException(); } ApplicationContextName.DlmsUA = arr.GetUInt8(); //Get tag if (arr.GetUInt8() != 0x11) { throw new ArgumentOutOfRangeException(); } ApplicationContextName.ApplicationContext = arr.GetUInt8(); //Get tag if (arr.GetUInt8() != 0x11) { throw new ArgumentOutOfRangeException(); } ApplicationContextName.ContextId = (ApplicationContextName)arr.GetUInt8(); } } else if (e.Value != null) { Object[] arr = (Object[])e.Value; ApplicationContextName.JointIsoCtt = Convert.ToByte(arr[0]); ApplicationContextName.Country = Convert.ToByte(arr[1]); ApplicationContextName.CountryName = Convert.ToUInt16(arr[2]); ApplicationContextName.IdentifiedOrganization = Convert.ToByte(arr[3]); ApplicationContextName.DlmsUA = Convert.ToByte(arr[4]); ApplicationContextName.ApplicationContext = Convert.ToByte(arr[5]); ApplicationContextName.ContextId = (ApplicationContextName)Convert.ToByte(arr[6]); } } else if (e.Index == 5) { if (e.Value != null) { Object[] arr = (Object[])e.Value; GXByteBuffer bb = new GXByteBuffer(); GXCommon.SetBitString(bb, arr[0]); bb.SetUInt8(0, 0); XDLMSContextInfo.Conformance = (Conformance)bb.GetUInt32(); XDLMSContextInfo.MaxReceivePduSize = Convert.ToUInt16(arr[1]); XDLMSContextInfo.MaxSendPduSize = Convert.ToUInt16(arr[2]); XDLMSContextInfo.DlmsVersionNumber = Convert.ToByte(arr[3]); XDLMSContextInfo.QualityOfService = Convert.ToSByte(arr[4]); XDLMSContextInfo.CypheringInfo = (byte[])arr[5]; } } else if (e.Index == 6) { //Value of the object identifier encoded in BER if (e.Value is byte[]) { GXByteBuffer arr = new GXByteBuffer(e.Value as byte[]); if (arr.GetUInt8(0) == 0x60) { AuthenticationMechanismName.JointIsoCtt = arr.GetUInt8(); AuthenticationMechanismName.Country = arr.GetUInt8(); AuthenticationMechanismName.CountryName = arr.GetUInt8(); AuthenticationMechanismName.IdentifiedOrganization = arr.GetUInt8(); AuthenticationMechanismName.DlmsUA = arr.GetUInt8(); AuthenticationMechanismName.AuthenticationMechanismName = arr.GetUInt8(); AuthenticationMechanismName.MechanismId = (Authentication)arr.GetUInt8(); } else { //Get Tag and Len. if (arr.GetUInt8() != (int)BerType.Integer && arr.GetUInt8() != 7) { throw new ArgumentOutOfRangeException(); } //Get tag if (arr.GetUInt8() != 0x11) { throw new ArgumentOutOfRangeException(); } AuthenticationMechanismName.JointIsoCtt = arr.GetUInt8(); //Get tag if (arr.GetUInt8() != 0x11) { throw new ArgumentOutOfRangeException(); } AuthenticationMechanismName.Country = arr.GetUInt8(); //Get tag if (arr.GetUInt8() != 0x12) { throw new ArgumentOutOfRangeException(); } AuthenticationMechanismName.CountryName = arr.GetUInt16(); //Get tag if (arr.GetUInt8() != 0x11) { throw new ArgumentOutOfRangeException(); } AuthenticationMechanismName.IdentifiedOrganization = arr.GetUInt8(); //Get tag if (arr.GetUInt8() != 0x11) { throw new ArgumentOutOfRangeException(); } AuthenticationMechanismName.DlmsUA = arr.GetUInt8(); //Get tag if (arr.GetUInt8() != 0x11) { throw new ArgumentOutOfRangeException(); } AuthenticationMechanismName.AuthenticationMechanismName = arr.GetUInt8(); //Get tag if (arr.GetUInt8() != 0x11) { throw new ArgumentOutOfRangeException(); } AuthenticationMechanismName.MechanismId = (Authentication)arr.GetUInt8(); } } else if (e.Value != null) { Object[] arr = (Object[])e.Value; AuthenticationMechanismName.JointIsoCtt = Convert.ToByte(arr[0]); AuthenticationMechanismName.Country = Convert.ToByte(arr[1]); AuthenticationMechanismName.CountryName = Convert.ToUInt16(arr[2]); AuthenticationMechanismName.IdentifiedOrganization = Convert.ToByte(arr[3]); AuthenticationMechanismName.DlmsUA = Convert.ToByte(arr[4]); AuthenticationMechanismName.AuthenticationMechanismName = Convert.ToByte(arr[5]); AuthenticationMechanismName.MechanismId = (Authentication)Convert.ToByte(arr[6]); } } else if (e.Index == 7) { Secret = (byte[])e.Value; } else if (e.Index == 8) { if (e.Value == null) { AssociationStatus = AssociationStatus.NonAssociated; } else { AssociationStatus = (AssociationStatus)Convert.ToInt32(e.Value); } } else if (e.Index == 9) { SecuritySetupReference = GXCommon.ToLogicalName(e.Value); } else if (e.Index == 10) { UserList.Clear(); if (e.Value != null) { foreach (Object[] item in (Object[])e.Value) { UserList.Add(new KeyValuePair <byte, string>(Convert.ToByte(item[0]), Convert.ToString(item[1]))); } } } else if (e.Index == 11) { if (e.Value != null) { Object[] tmp = (Object[])e.Value; CurrentUser = new KeyValuePair <byte, string>(Convert.ToByte(tmp[0]), Convert.ToString(tmp[1])); } else { CurrentUser = new KeyValuePair <byte, string>(0, null); } } else { e.Error = ErrorCode.ReadWriteDenied; } }
object IGXDLMSBase.GetValue(GXDLMSSettings settings, ValueEventArgs e) { object ret; switch (e.Index) { case 1: ret = GXCommon.LogicalNameToBytes(LogicalName); break; case 2: ret = InitiatorElectricalPhase; break; case 3: ret = DeltaElectricalPhase; break; case 4: ret = MaxReceivingGain; break; case 5: ret = MaxTransmittingGain; break; case 6: ret = SearchInitiatorThreshold; break; case 7: { GXByteBuffer bb = new GXByteBuffer(); bb.SetUInt8(DataType.Structure); bb.SetUInt8(2); GXCommon.SetData(settings, bb, DataType.UInt32, MarkFrequency); GXCommon.SetData(settings, bb, DataType.UInt32, SpaceFrequency); ret = bb.Array(); break; } case 8: ret = MacAddress; break; case 9: { GXByteBuffer bb = new GXByteBuffer(); bb.SetUInt8(DataType.Array); if (MacGroupAddresses == null) { bb.SetUInt8(0); } else { GXCommon.SetObjectCount(MacGroupAddresses.Length, bb); foreach (ushort it in MacGroupAddresses) { GXCommon.SetData(settings, bb, DataType.UInt16, it); } } ret = bb.Array(); break; } case 10: ret = Repeater; break; case 11: ret = RepeaterStatus; break; case 12: ret = MinDeltaCredit; break; case 13: ret = InitiatorMacAddress; break; case 14: ret = SynchronizationLocked; break; case 15: ret = TransmissionSpeed; break; default: e.Error = ErrorCode.ReadWriteDenied; ret = null; break; } return(ret); }
byte[] IGXDLMSBase.Invoke(GXDLMSSettings settings, ValueEventArgs e) { //Check reply_to_HLS_authentication if (e.Index == 8) { UInt32 ic = 0; byte[] secret; if (settings.Authentication == Authentication.HighGMAC) { secret = settings.SourceSystemTitle; GXByteBuffer bb = new GXByteBuffer(e.Parameters as byte[]); bb.GetUInt8(); ic = bb.GetUInt32(); } else { secret = HlsSecret; } byte[] serverChallenge = GXSecure.Secure(settings, settings.Cipher, ic, settings.StoCChallenge, secret); byte[] clientChallenge = (byte[])e.Parameters; if (GXCommon.Compare(serverChallenge, clientChallenge)) { if (settings.Authentication == Authentication.HighGMAC) { secret = settings.Cipher.SystemTitle; ic = settings.Cipher.FrameCounter; } else { secret = HlsSecret; } settings.Connected = true; return GXSecure.Secure(settings, settings.Cipher, ic, settings.CtoSChallenge, secret); } else { // If the password does not match. settings.Connected = false; return null; } } else { e.Error = ErrorCode.ReadWriteDenied; return null; } }
Gurux.DLMS.Enums.Security GXICipher.Decrypt(byte[] title, GXByteBuffer data) { AesGcmParameter p = new AesGcmParameter(title, BlockCipherKey, AuthenticationKey); byte[] tmp = GXDLMSChippering.DecryptAesGcm(p, data); data.Clear(); data.Set(tmp); return p.Security; }
/// <summary> /// Returns Association View. /// </summary> private GXByteBuffer GetObjects(GXDLMSSettings settings, ValueEventArgs e) { int cnt = ObjectList.Count; GXByteBuffer data = new GXByteBuffer(); //Add count only for first time. if (settings.Index == 0) { settings.Count = (UInt16)cnt; data.SetUInt8((byte)DataType.Array); GXCommon.SetObjectCount(cnt, data); } ushort pos = 0; foreach (GXDLMSObject it in ObjectList) { ++pos; if (!(pos <= settings.Index)) { data.SetUInt8((byte)DataType.Structure); //Count data.SetUInt8((byte)4); //base address. GXCommon.SetData(settings, data, DataType.Int16, it.ShortName); //ClassID GXCommon.SetData(settings, data, DataType.UInt16, it.ObjectType); //Version GXCommon.SetData(settings, data, DataType.UInt8, 0); //LN GXCommon.SetData(settings, data, DataType.OctetString, it.LogicalName); ++settings.Index; //If PDU is full. if (!e.SkipMaxPduSize && data.Size >= settings.MaxPduSize) { break; } } } return data; }
///<summary> ///Convert Array to DLMS bytes. ///</summary> ///<param name="buff"> ///Byte buffer where data is write. ///</param> ///<param name="value"> ///Added value. ///</param> private static void SetArray(GXDLMSSettings settings, GXByteBuffer buff, object value) { if (value != null) { object[] arr = (object[])value; SetObjectCount(arr.Length, buff); foreach (object it in arr) { SetData(settings, buff, GetValueType(it), it); } } else { SetObjectCount(0, buff); } }
object IGXDLMSBase.GetValue(GXDLMSSettings settings, ValueEventArgs e) { if (e.Index == 1) { return(this.LogicalName); } else if (e.Index == 2) { GXByteBuffer data = new GXByteBuffer(); data.SetUInt8((byte)DataType.Structure); data.SetUInt8(3); if (MonitoredValue == null) { GXCommon.SetData(settings, data, DataType.Int16, 0); GXCommon.SetData(settings, data, DataType.OctetString, "0.0.0.0.0.0"); GXCommon.SetData(settings, data, DataType.UInt8, 0); } else { GXCommon.SetData(settings, data, DataType.Int16, MonitoredValue.ObjectType); GXCommon.SetData(settings, data, DataType.OctetString, MonitoredValue.LogicalName); GXCommon.SetData(settings, data, DataType.UInt8, MonitoredAttributeIndex); } return(data.Array()); } else if (e.Index == 3) { return(ThresholdActive); } else if (e.Index == 4) { return(ThresholdNormal); } else if (e.Index == 5) { return(ThresholdEmergency); } else if (e.Index == 6) { return(MinOverThresholdDuration); } else if (e.Index == 7) { return(MinUnderThresholdDuration); } else if (e.Index == 8) { GXByteBuffer data = new GXByteBuffer(); data.SetUInt8((byte)DataType.Structure); data.SetUInt8(3); GXCommon.SetData(settings, data, DataType.UInt16, EmergencyProfile.ID); GXCommon.SetData(settings, data, DataType.OctetString, EmergencyProfile.ActivationTime); GXCommon.SetData(settings, data, DataType.UInt32, EmergencyProfile.Duration); return(data.Array()); } else if (e.Index == 9) { GXByteBuffer data = new GXByteBuffer(); data.SetUInt8((byte)DataType.Array); if (EmergencyProfileGroupIDs == null) { data.SetUInt8(0); } else { data.SetUInt8((byte)EmergencyProfileGroupIDs.Length); foreach (object it in EmergencyProfileGroupIDs) { GXCommon.SetData(settings, data, DataType.UInt16, it); } } return(data.Array()); } else if (e.Index == 10) { return(EmergencyProfileActive); } else if (e.Index == 11) { GXByteBuffer data = new GXByteBuffer(); data.SetUInt8((byte)DataType.Structure); data.SetUInt8(2); data.SetUInt8((byte)DataType.Structure); data.SetUInt8(2); GXCommon.SetData(settings, data, DataType.OctetString, ActionOverThreshold.LogicalName); GXCommon.SetData(settings, data, DataType.UInt16, ActionOverThreshold.ScriptSelector); data.SetUInt8((byte)DataType.Structure); data.SetUInt8(2); GXCommon.SetData(settings, data, DataType.OctetString, ActionUnderThreshold.LogicalName); GXCommon.SetData(settings, data, DataType.UInt16, ActionUnderThreshold.ScriptSelector); return(data.Array()); } e.Error = ErrorCode.ReadWriteDenied; return(null); }
///<summary> ///Convert UTC string to DLMS bytes. ///</summary> ///<param name="buff"> ///Byte buffer where data is write. ///</param> ///<param name="value"> ///Added value. ///</param> private static void SetUtcString(GXByteBuffer buff, object value) { if (value != null) { byte[] tmp = ASCIIEncoding.UTF8.GetBytes(Convert.ToString(value)); SetObjectCount(tmp.Length, buff); buff.Set(tmp); } else { buff.SetUInt8(0); } }
/// <summary> /// Import server settings and COSEM objects from GXDLMSDirector trace. /// </summary> /// <param name="server">Server where settings are updated.</param> /// <param name="data">GXDLMSDirector trace in byte array.</param> public static void Import(GXDLMSServer server, byte[] data) { GXDLMSTranslator translator = new GXDLMSTranslator(TranslatorOutputType.StandardXml); translator.CompletePdu = true; translator.PduOnly = true; XmlDocument doc = new XmlDocument(); List<ValueEventArgs> targets = new List<ValueEventArgs>(); GXDLMSSettings settings = new GXDLMSSettings(true); GXByteBuffer pdu = new GXByteBuffer(); GXByteBuffer bb = new GXByteBuffer(data); server.InterfaceType = GXDLMSTranslator.GetDlmsFraming(bb); bool lastBlock = true; GXByteBuffer val = new DLMS.GXByteBuffer(); while (translator.FindNextFrame(bb, pdu, server.InterfaceType)) { String xml = translator.MessageToXml(bb); if (xml != "") { doc.LoadXml(xml); foreach (XmlNode node in doc.ChildNodes[doc.ChildNodes.Count - 1].ChildNodes) { if (node.Name == "x:get-request") { server.UseLogicalNameReferencing = true; GetLN(settings.Objects, targets, node.ChildNodes); } else if (node.Name == "x:readRequest") { List<short> items = GetSN(node.ChildNodes); server.UseLogicalNameReferencing = false; foreach (short it in items) { GXSNInfo i = GXDLMSSNCommandHandler.FindSNObject(settings.Objects, Convert.ToUInt16((it) & 0xFFFF)); targets.Add(new ValueEventArgs(i.Item, i.Index, 0, null)); } } else if (node.Name == "x:readResponse" || node.Name == "x:get-response") { if (targets != null) { List<string> items; if (server.UseLogicalNameReferencing) { items = GetLNValues(node.ChildNodes); } else { items = GetSNValues(node.ChildNodes); } int pos = 0; foreach (string it in items) { if ("read-write-denied".Equals(it) || "scope-of-access-violated".Equals(it) || "object-unavailable".Equals(it)) { ValueEventArgs ve = targets[pos]; ve.Target.SetAccess(ve.Index, AccessMode.NoAccess); continue; } try { if (server.UseLogicalNameReferencing) { lastBlock = IsLastBlock(node.ChildNodes); } val.Set(translator.XmlToData(it)); if (lastBlock) { if (settings.Objects.Count == 0) { GXDLMSClient c = new GXDLMSClient(); c.UseLogicalNameReferencing = server.UseLogicalNameReferencing; settings.Objects = c.ParseObjects(val, true); //Update OBIS code description. GXDLMSConverter converter = new GXDLMSConverter(); converter.UpdateOBISCodeInformation(settings.Objects); } else { ValueEventArgs ve = targets[pos]; GXDataInfo info = new GXDataInfo(); ve.Value = GXCommon.GetData(server.Settings, val, info); if (ve.Value is byte[]) { DataType tp = ve.Target.GetUIDataType(ve.Index); if (tp != DataType.None) { ve.Value = GXDLMSClient.ChangeType((byte[])ve.Value, tp); } } ((IGXDLMSBase)ve.Target).SetValue(settings, ve); } val.Clear(); } } catch (Exception) { ValueEventArgs ve = targets[pos]; ve.Target.SetAccess(ve.Index, AccessMode.NoAccess); } ++pos; } if (lastBlock) { targets.Clear(); } } } } } } server.Items.Clear(); server.Items.AddRange(settings.Objects); }
object IGXDLMSBase.GetValue(GXDLMSSettings settings, ValueEventArgs e) { if (e.Index == 1) { return(GXCommon.LogicalNameToBytes(LogicalName)); } if (e.Index == 2) { return(ShortAddress); } if (e.Index == 3) { return(RcCoord); } if (e.Index == 4) { return(PANId); } if (e.Index == 5) { GXByteBuffer bb = new GXByteBuffer(); bb.SetUInt8((byte)DataType.Array); if (KeyTable == null) { bb.SetUInt8(0); } else { GXCommon.SetObjectCount(KeyTable.Count, bb); foreach (GXKeyValuePair <byte, byte[]> it in KeyTable) { bb.SetUInt8((byte)DataType.Structure); bb.SetUInt8(2); GXCommon.SetData(settings, bb, DataType.UInt8, it.Key); GXCommon.SetData(settings, bb, DataType.UInt8, it.Value); } } return(bb.Array()); } if (e.Index == 6) { return(FrameCounter); } if (e.Index == 7) { return(ToneMask); } if (e.Index == 8) { return(TmrTtl); } if (e.Index == 9) { return(MaxFrameRetries); } if (e.Index == 10) { return(NeighbourTableEntryTtl); } if (e.Index == 11) { GXByteBuffer bb = new GXByteBuffer(); bb.SetUInt8((byte)DataType.Array); if (NeighbourTable == null) { bb.SetUInt8(0); } else { GXCommon.SetObjectCount(NeighbourTable.Length, bb); foreach (GXDLMSNeighbourTable it in NeighbourTable) { bb.SetUInt8((byte)DataType.Structure); bb.SetUInt8(11); GXCommon.SetData(settings, bb, DataType.UInt16, it.ShortAddress); GXCommon.SetData(settings, bb, DataType.Boolean, it.Enabled); GXCommon.SetData(settings, bb, DataType.BitString, it.ToneMap); GXCommon.SetData(settings, bb, DataType.Enum, it.Modulation); GXCommon.SetData(settings, bb, DataType.Int8, it.TxGain); GXCommon.SetData(settings, bb, DataType.Enum, it.TxRes); GXCommon.SetData(settings, bb, DataType.BitString, it.TxCoeff); GXCommon.SetData(settings, bb, DataType.UInt8, it.Lqi); GXCommon.SetData(settings, bb, DataType.Int8, it.PhaseDifferential); GXCommon.SetData(settings, bb, DataType.UInt8, it.TMRValidTime); GXCommon.SetData(settings, bb, DataType.UInt8, it.NeighbourValidTime); } } return(bb.Array()); } if (e.Index == 12) { return(HighPriorityWindowSize); } if (e.Index == 13) { return(CscmFairnessLimit); } if (e.Index == 14) { return(BeaconRandomizationWindowLength); } if (e.Index == 15) { return(A); } if (e.Index == 16) { return(K); } if (e.Index == 17) { return(MinCwAttempts); } if (e.Index == 18) { return(CenelecLegacyMode); } if (e.Index == 19) { return(FccLegacyMode); } if (e.Index == 20) { return(MaxBe); } if (e.Index == 21) { return(MaxCsmaBackoffs); } if (e.Index == 22) { return(MinBe); } e.Error = ErrorCode.ReadWriteDenied; return(null); }