Exemple #1
0
 /// <summary>
 /// Constructor.
 /// </summary>
 /// <param name="client">DLMS Client.</param>
 /// <param name="media">Media.</param>
 public GXDLMSReader(GXDLMSSecureClient client, IGXMedia media, ILogger logger)
 {
     if (logger.IsEnabled(LogLevel.Trace) || logger.IsEnabled(LogLevel.Debug))
     {
         Trace = TraceLevel.Verbose;
     }
     else if (logger.IsEnabled(LogLevel.Information))
     {
         Trace = TraceLevel.Info;
     }
     else if (logger.IsEnabled(LogLevel.Warning))
     {
         Trace = TraceLevel.Warning;
     }
     else if (logger.IsEnabled(LogLevel.Error) || logger.IsEnabled(LogLevel.Critical))
     {
         Trace = TraceLevel.Error;
     }
     else
     {
         Trace = TraceLevel.Off;
     }
     Media   = media;
     Client  = client;
     _logger = logger;
 }
Exemple #2
0
 /// <summary>
 /// Constructor.
 /// </summary>
 /// <param name="client">DLMS Client.</param>
 /// <param name="media">Media.</param>
 public GXDLMSReader(GXDLMSSecureClient client, IGXMedia media, TraceLevel trace, ILogger logger)
 {
     Trace   = trace;
     Media   = media;
     Client  = client;
     _logger = logger;
 }
 /// <summary>
 /// Constructor.
 /// </summary>
 /// <param name="client">DLMS Client.</param>
 /// <param name="media">Media.</param>
 /// <param name="trace">Trace level.</param>
 /// <param name="invocationCounter">Logical name of invocation counter.</param>
 /// <param name="iec">Is optical head used.</param>
 public GXDLMSReader(GXDLMSSecureClient client, IGXMedia media, TraceLevel trace, string invocationCounter)
 {
     Trace             = trace;
     Media             = media;
     Client            = client;
     InvocationCounter = invocationCounter;
 }
        /// <summary>
        /// Agree on global unicast encryption key.
        /// </summary>
        /// <param name="client"> DLMS client that is used to generate action.</param>
        /// <param name="key"> List of keys.</param>
        /// <returns>Generated action.</returns>
        public byte[][] KeyAgreement(GXDLMSSecureClient client)
        {
            if (Version == 0)
            {
                throw new ArgumentException("Public and private key isn't implemented for version 0.");
            }
            if (client.Ciphering.EphemeralKeyPair.Value == null)
            {
                throw new ArgumentException("Invalid Ephemeral key.");
            }
            if (client.Ciphering.SigningKeyPair.Value == null)
            {
                throw new ArgumentException("Invalid Signiture key.");
            }
            GXByteBuffer bb = new GXByteBuffer();

            //Add Ephemeral public key.
            bb.Set(client.Ciphering.EphemeralKeyPair.Value.RawValue, 1, client.Ciphering.EphemeralKeyPair.Value.RawValue.Length - 1);
            //Add signature.
            byte[] sign = GXSecure.GetEphemeralPublicKeySignature(0, client.Ciphering.EphemeralKeyPair.Value,
                                                                  client.Ciphering.SigningKeyPair.Key);
            bb.Set(sign);
            List <KeyValuePair <GlobalKeyType, byte[]> > list = new List <KeyValuePair <GlobalKeyType, byte[]> >();

            list.Add(new KeyValuePair <GlobalKeyType, byte[]>(GlobalKeyType.UnicastEncryption, bb.Array()));
            return(KeyAgreement(client, list));
        }
        byte[] IGXDLMSBase.Invoke(GXDLMSSettings settings, ValueEventArgs e)
        {
            if (e.Index == 1)
            {
                if (Version == 0)
                {
                    SecurityPolicy0 = (SecurityPolicy0)e.Parameters;
                }
                else
                {
                    SecurityPolicy = (SecurityPolicy)e.Parameters;
                }
            }
            else if (e.Index == 2)
            {
                try
                {
                    foreach (List <object> item in e.Parameters as List <object> )
                    {
                        GlobalKeyType type = (GlobalKeyType)Convert.ToInt32(item[0]);
                        byte[]        data = (byte[])item[1];
                        switch (type)
                        {
                        case GlobalKeyType.UnicastEncryption:
                            settings.Cipher.BlockCipherKey = GXDLMSSecureClient.Decrypt(settings.Kek, data);
                            break;

                        case GlobalKeyType.BroadcastEncryption:
                            //Invalid type
                            e.Error = ErrorCode.ReadWriteDenied;
                            break;

                        case GlobalKeyType.Authentication:
                            //if settings.Cipher is null non secure server is used.
                            settings.Cipher.AuthenticationKey = GXDLMSSecureClient.Decrypt(settings.Kek, data);
                            break;

                        case GlobalKeyType.Kek:
                            settings.Kek = GXDLMSSecureClient.Decrypt(settings.Kek, data);
                            break;

                        default:
                            //Invalid type
                            e.Error = ErrorCode.ReadWriteDenied;
                            break;
                        }
                    }
                }
                catch (Exception)
                {
                    e.Error = ErrorCode.ReadWriteDenied;
                }
            }
            else
            {
                e.Error = ErrorCode.ReadWriteDenied;
            }
            //Return standard reply.
            return(null);
        }
 /// <summary>
 /// Constructor.
 /// </summary>
 /// <param name="client">DLMS Client.</param>
 /// <param name="media">Media.</param>
 /// <param name="trace">Trace level.</param>
 /// <param name="invocationCounter">Logical name of invocation counter.</param>
 /// <param name="iec">Is optical head used.</param>
 public GXDLMSReader(GXDLMSSecureClient client, IGXMedia media, TraceLevel trace, string invocationCounter, bool useOpticalHead)
 {
     Trace             = trace;
     Media             = media;
     Client            = client;
     InvocationCounter = invocationCounter;
     UseOpticalHead    = useOpticalHead;
 }
Exemple #7
0
 public GXNotifyClient(bool useLogicalNameReferencing, int interfaceType, string systemTitle, string blockCipherKey)
 {
     Notify = new GXReplyData();
     Reply  = new GXByteBuffer();
     Client = new GXDLMSSecureClient(useLogicalNameReferencing, -1, -1, Authentication.None, null, (InterfaceType)interfaceType);
     Client.Ciphering.SystemTitle    = GXCommon.HexToBytes(systemTitle);
     Client.Ciphering.BlockCipherKey = GXCommon.HexToBytes(blockCipherKey);
     DataReceived = DateTime.MinValue;
 }
Exemple #8
0
 /// <summary>
 /// Constructor.
 /// </summary>
 public GXCommunicatation(GXDLMSSecureClient dlms, IGXMedia media, bool initializeIEC, Authentication authentication, string password)
 {
     Client                = dlms;
     Media                 = media;
     InitializeIEC         = initializeIEC;
     Client.Authentication = authentication;
     Client.Password       = ASCIIEncoding.ASCII.GetBytes(password);
     //Delete trace file if exists.
     if (File.Exists("trace.txt"))
     {
         File.Delete("trace.txt");
     }
 }
Exemple #9
0
 /// <summary>
 /// Constructor.
 /// </summary>
 /// <param name="client">DLMS Client.</param>
 /// <param name="media">Media.</param>
 /// <param name="logger">Logger.</param>
 /// <param name="trace">Trace level.</param>
 public GXDLMSReader(
     GXDLMSSecureClient client,
     IGXMedia media,
     ILogger logger,
     TraceLevel trace,
     int wt,
     int retry,
     UInt64 deviceId)
 {
     WaitTime   = wt * 1000;
     RetryCount = retry;
     Trace      = trace;
     Media      = media;
     Client     = client;
     _logger    = logger;
     DeviceId   = deviceId;
 }
Exemple #10
0
 public void Close()
 {
     if (Media != null && Client != null)
     {
         try
         {
             Console.WriteLine("Disconnecting from the meter.");
             GXReplyData reply = new GXReplyData();
             ReadDLMSPacket(Client.DisconnectRequest(), reply);
             Media.Close();
         }
         catch
         {
         }
         Media  = null;
         Client = null;
     }
 }
Exemple #11
0
        byte[] IGXDLMSBase.Invoke(GXDLMSSettings settings, ValueEventArgs e)
        {
            if (e.Index == 2)
            {
                foreach (object tmp in e.Parameters as object[])
                {
                    object[]      item = tmp as object[];
                    GlobalKeyType type = (GlobalKeyType)Convert.ToInt32(item[0]);
                    byte[]        data = (byte[])item[1];
                    switch (type)
                    {
                    case GlobalKeyType.UnicastEncryption:
                    case GlobalKeyType.BroadcastEncryption:
                        //Invalid type
                        e.Error = ErrorCode.ReadWriteDenied;
                        break;

                    case GlobalKeyType.Authentication:
                        //if settings.Cipher is null non secure server is used.
                        settings.Cipher.AuthenticationKey = GXDLMSSecureClient.Decrypt(settings.Kek, data);
                        break;

                    case GlobalKeyType.Kek:
                        settings.Kek = GXDLMSSecureClient.Decrypt(settings.Kek, data);
                        break;

                    default:
                        //Invalid type
                        e.Error = ErrorCode.ReadWriteDenied;
                        break;
                    }
                }
                //Return standard reply.
                return(null);
            }
            else
            {
                e.Error = ErrorCode.ReadWriteDenied;
                return(null);
            }
        }
Exemple #12
0
        /// <summary>
        /// Updates one or more global keys.
        /// </summary>
        /// <param name="client">DLMS client that is used to generate action.</param>
        /// <param name="kek">Master key, also known as Key Encrypting Key.</param>
        /// <param name="list">List of Global key types and keys.</param>
        /// <returns>Generated action.</returns>
        public byte[][] GlobalKeyTransfer(GXDLMSClient client, byte[] kek, List <KeyValuePair <GlobalKeyType, byte[]> > list)
        {
            if (list == null || list.Count == 0)
            {
                throw new ArgumentException("Invalid list. It is empty.");
            }
            GXByteBuffer bb = new GXByteBuffer();

            bb.SetUInt8(DataType.Array);
            bb.SetUInt8((byte)list.Count);
            byte[] tmp;
            foreach (KeyValuePair <GlobalKeyType, byte[]> it in list)
            {
                bb.SetUInt8(DataType.Structure);
                bb.SetUInt8(2);
                GXCommon.SetData(client.Settings, bb, DataType.Enum, it.Key);
                tmp = GXDLMSSecureClient.Encrypt(kek, it.Value);
                GXCommon.SetData(client.Settings, bb, DataType.OctetString, tmp);
            }
            return(client.Method(this, 2, bb.Array(), DataType.Array));
        }
Exemple #13
0
        /// <summary>
        /// Start to use new keys after reply is generated.
        /// </summary>
        /// <param name="settings">DLMS settings.</param>
        /// <param name="e"></param>
        internal void ApplyKeys(GXDLMSSettings settings, ValueEventArgs e)
        {
            try
            {
                foreach (List <object> item in e.Parameters as List <object> )
                {
                    GlobalKeyType type = (GlobalKeyType)Convert.ToInt32(item[0]);
                    byte[]        data = (byte[])item[1];
                    switch (type)
                    {
                    case GlobalKeyType.UnicastEncryption:
                        settings.Cipher.BlockCipherKey = GXDLMSSecureClient.Decrypt(settings.Kek, data);
                        break;

                    case GlobalKeyType.BroadcastEncryption:
                        //Invalid type
                        e.Error = ErrorCode.ReadWriteDenied;
                        break;

                    case GlobalKeyType.Authentication:
                        //if settings.Cipher is null non secure server is used.
                        settings.Cipher.AuthenticationKey = GXDLMSSecureClient.Decrypt(settings.Kek, data);
                        break;

                    case GlobalKeyType.Kek:
                        settings.Kek = GXDLMSSecureClient.Decrypt(settings.Kek, data);
                        break;

                    default:
                        //Invalid type
                        e.Error = ErrorCode.ReadWriteDenied;
                        break;
                    }
                }
            }
            catch (Exception)
            {
                e.Error = ErrorCode.ReadWriteDenied;
            }
        }
Exemple #14
0
 /// <summary>
 /// Close connection to the meter.
 /// </summary>
 public void Close()
 {
     if (Media != null && Client != null)
     {
         try
         {
             if (Trace > TraceLevel.Info)
             {
                 Console.WriteLine("Disconnecting from the meter.");
             }
             GXReplyData reply = new GXReplyData();
             try
             {
                 if ((Client.ConnectionState & ConnectionState.Dlms) != 0 &&
                     (Client.InterfaceType == InterfaceType.WRAPPER ||
                      Client.Ciphering.Security != (byte)Security.None))
                 {
                     ReadDataBlock(Client.ReleaseRequest(), reply);
                 }
             }
             catch (Exception ex)
             {
                 //All meters don't support Release.
                 Console.WriteLine("Release failed. " + ex.Message);
             }
             reply.Clear();
             if (Client.ConnectionState != 0)
             {
                 ReadDLMSPacket(Client.DisconnectRequest(), reply);
             }
             Media.Close();
         }
         catch
         {
         }
         Media  = null;
         Client = null;
     }
 }
 /// <summary>
 /// Close connection to the meter.
 /// </summary>
 public void Close()
 {
     if (Media != null && Client != null)
     {
         try
         {
             if (Trace > TraceLevel.Info)
             {
                 Console.WriteLine("Disconnecting from the meter.");
             }
             GXReplyData reply = new GXReplyData();
             try
             {
                 //Release is call only for secured connections.
                 //All meters are not supporting Release and it's causing problems.
                 if (Client.InterfaceType == InterfaceType.WRAPPER ||
                     (Client.InterfaceType == InterfaceType.HDLC && Client.Ciphering.Security != (byte)Security.None))
                 {
                     ReadDataBlock(Client.ReleaseRequest(), reply);
                 }
             }
             catch (Exception ex)
             {
                 //All meters don't support Release.
                 Console.WriteLine("Release failed. " + ex.Message);
             }
             reply.Clear();
             ReadDLMSPacket(Client.DisconnectRequest(), reply);
             Media.Close();
         }
         catch
         {
         }
         Media  = null;
         Client = null;
     }
 }
Exemple #16
0
        private async void DoWork(object ínfo)
        {
            //Give some time DB server to start up.
            Thread.Sleep(1000);
            GetNextTaskResponse ret = null;

            System.Net.Http.HttpResponseMessage response;
            //Don't wait reply. It might that DB server is not up yet.
            if (ínfo != null)
            {
                using (response = await client.PostAsJsonAsync(Startup.ServerAddress + "/api/reader/AddReader", new AddReader()
                {
                    Reader = ínfo as GXReaderInfo
                }))
                {
                    Helpers.CheckStatus(response);
                }
            }
            _logger.LogInformation("Reader Service is started.");
            while (!_cancellationToken.IsCancellationRequested)
            {
                try
                {
                    using (response = await client.PostAsJsonAsync(Startup.ServerAddress + "/api/task/GetNextTask", new GetNextTask()))
                    {
                        Helpers.CheckStatus(response);
                        ret = await response.Content.ReadAsAsync <GetNextTaskResponse>();
                    }
                    if (ret.Tasks != null)
                    {
                        int                pos = 0;
                        GXDevice           dev;
                        GXDLMSSecureClient cl;
                        using (response = await client.PostAsJsonAsync(Startup.ServerAddress + "/api/device/ListDevices", new ListDevices()
                        {
                            Ids = new[] { ret.Tasks[0].Object.DeviceId }
                        }))
                        {
                            Helpers.CheckStatus(response);
                            ListDevicesResponse r = await response.Content.ReadAsAsync <ListDevicesResponse>();

                            if (r.Devices == null || r.Devices.Length == 0)
                            {
                                continue;
                            }
                            dev = r.Devices[0];
                        }
                        IGXMedia media;
                        if (string.Compare(dev.MediaType, typeof(GXNet).FullName, true) == 0)
                        {
                            media = new GXNet();
                        }
                        else if (string.Compare(dev.MediaType, typeof(GXSerial).FullName, true) == 0)
                        {
                            media = new GXSerial();
                        }
                        else if (string.Compare(dev.MediaType, typeof(GXTerminal).FullName, true) == 0)
                        {
                            media = new GXTerminal();
                        }
                        else
                        {
                            Type type = Type.GetType(dev.MediaType);
                            if (type == null)
                            {
                                string ns = "";
                                pos = dev.MediaType.LastIndexOf('.');
                                if (pos != -1)
                                {
                                    ns = dev.MediaType.Substring(0, pos);
                                }
                                foreach (Assembly assembly in AppDomain.CurrentDomain.GetAssemblies())
                                {
                                    if (assembly.GetName().Name == ns)
                                    {
                                        if (assembly.GetType(dev.MediaType, false, true) != null)
                                        {
                                            type = assembly.GetType(dev.MediaType);
                                        }
                                    }
                                }
                            }
                            if (type == null)
                            {
                                throw new Exception("Invalid media type: " + dev.MediaType);
                            }
                            media = (IGXMedia)Activator.CreateInstance(type);
                        }
                        if (media == null)
                        {
                            throw new Exception("Unknown media type '" + dev.MediaType + "'.");
                        }
                        media.Settings = dev.MediaSettings;
                        GXDLMSReader reader;
                        //Read frame counter from the meter.
                        if (dev.Security != 0)
                        {
                            cl = new GXDLMSSecureClient(dev.UseLogicalNameReferencing, 16, dev.PhysicalAddress,
                                                        Authentication.None, null, (InterfaceType)dev.InterfaceType);
                            reader = new GXDLMSReader(cl, media, _logger);
                            media.Open();
                            reader.InitializeConnection();
                            //Read Innovation counter.
                            GXDLMSData d = new GXDLMSData(dev.FrameCounter);
                            reader.Read(d, 2);
                            dev.InvocationCounter = 1 + Convert.ToUInt32(d.Value);
                            reader.Disconnect();
                            media.Close();
                        }
                        cl = new GXDLMSSecureClient(dev.UseLogicalNameReferencing, dev.ClientAddress, dev.PhysicalAddress,
                                                    (Authentication)dev.Authentication, dev.Password, (InterfaceType)dev.InterfaceType);
                        if (dev.HexPassword != null && dev.HexPassword.Length != 0)
                        {
                            cl.Password = dev.HexPassword;
                        }
                        cl.UseUtc2NormalTime     = dev.UtcTimeZone;
                        cl.Standard              = dev.Standard;
                        cl.Ciphering.SystemTitle = GXCommon.HexToBytes(dev.ClientSystemTitle);
                        if (cl.Ciphering.SystemTitle != null && cl.Ciphering.SystemTitle.Length == 0)
                        {
                            cl.Ciphering.SystemTitle = null;
                        }
                        cl.Ciphering.BlockCipherKey = GXCommon.HexToBytes(dev.BlockCipherKey);
                        if (cl.Ciphering.BlockCipherKey != null && cl.Ciphering.BlockCipherKey.Length == 0)
                        {
                            cl.Ciphering.BlockCipherKey = null;
                        }
                        cl.Ciphering.AuthenticationKey = GXCommon.HexToBytes(dev.AuthenticationKey);
                        if (cl.Ciphering.AuthenticationKey != null && cl.Ciphering.AuthenticationKey.Length == 0)
                        {
                            cl.Ciphering.AuthenticationKey = null;
                        }
                        cl.ServerSystemTitle = GXCommon.HexToBytes(dev.DeviceSystemTitle);
                        if (cl.ServerSystemTitle != null && cl.ServerSystemTitle.Length == 0)
                        {
                            cl.ServerSystemTitle = null;
                        }
                        cl.Ciphering.InvocationCounter = dev.InvocationCounter;
                        cl.Ciphering.Security          = (Security)dev.Security;
                        reader = new GXDLMSReader(cl, media, _logger);
                        media.Open();
                        reader.InitializeConnection();
                        pos = 0;
                        int count = ret.Tasks.Length;
                        foreach (GXTask task in ret.Tasks)
                        {
                            ++pos;
                            try
                            {
                                GXDLMSObject obj = GXDLMSClient.CreateObject((ObjectType)task.Object.ObjectType);
                                obj.LogicalName = task.Object.LogicalName;
                                obj.ShortName   = task.Object.ShortName;
                                if (task.TaskType == TaskType.Write)
                                {
                                    if (obj.LogicalName == "0.0.1.1.0.255" && task.Index == 2)
                                    {
                                        cl.UpdateValue(obj, task.Index, GXDateTime.ToUnixTime(DateTime.UtcNow));
                                    }
                                    else
                                    {
                                        cl.UpdateValue(obj, task.Index, GXDLMSTranslator.XmlToValue(task.Data));
                                    }
                                    reader.Write(obj, task.Index);
                                }
                                else if (task.TaskType == TaskType.Action)
                                {
                                    reader.Method(obj, task.Index, GXDLMSTranslator.XmlToValue(task.Data), DataType.None);
                                }
                                else if (task.TaskType == TaskType.Read)
                                {
                                    //Reading the meter.
                                    if (task.Object.Attributes[0].DataType != 0)
                                    {
                                        obj.SetDataType(task.Index, (DataType)task.Object.Attributes[0].DataType);
                                    }
                                    if (task.Object.Attributes[0].UIDataType != 0)
                                    {
                                        obj.SetUIDataType(task.Index, (DataType)task.Object.Attributes[0].UIDataType);
                                    }
                                    Reader.Read(_logger, client, reader, task, media, obj);
                                    if (task.Object.Attributes[0].DataType == 0)
                                    {
                                        task.Object.Attributes[0].DataType = (int)obj.GetDataType(task.Index);
                                        if (task.Object.Attributes[0].UIDataType == 0)
                                        {
                                            task.Object.Attributes[0].UIDataType = (int)obj.GetUIDataType(task.Index);
                                        }
                                        UpdateDatatype u = new UpdateDatatype()
                                        {
                                            Items = new GXAttribute[] { task.Object.Attributes[0] }
                                        };
                                        response = client.PostAsJsonAsync(Startup.ServerAddress + "/api/Object/UpdateDatatype", u).Result;
                                        Helpers.CheckStatus(response);
                                    }
                                }
                            }
                            catch (Exception ex)
                            {
                                task.Result = ex.Message;
                                AddError error = new AddError();
                                error.Error = new GXError()
                                {
                                    DeviceId = dev.Id,
                                    Error    = "Failed to " + task.TaskType + " " + task.Object.LogicalName + ":" + task.Index + ". " + ex.Message
                                };
                                _logger.LogError(error.Error.Error);
                                using (response = await client.PostAsJsonAsync(Startup.ServerAddress + "/api/error/AddError", error))
                                {
                                    Helpers.CheckStatus(response);
                                    await response.Content.ReadAsAsync <AddErrorResponse>();
                                }
                            }
                            task.End = DateTime.Now;
                            //Close connection after last task is executed.
                            //This must done because there might be new task to execute.
                            if (count == pos)
                            {
                                try
                                {
                                    reader.Close();
                                }
                                catch (Exception ex)
                                {
                                    task.Result = ex.Message;
                                    AddError error = new AddError();
                                    error.Error = new GXError()
                                    {
                                        DeviceId = dev.Id,
                                        Error    = "Failed to close the connection. " + ex.Message
                                    };
                                    _logger.LogError(error.Error.Error);
                                    using (response = await client.PostAsJsonAsync(Startup.ServerAddress + "/api/error/AddError", error))
                                    {
                                        Helpers.CheckStatus(response);
                                        await response.Content.ReadAsAsync <AddErrorResponse>();
                                    }
                                }
                            }
                            //Update execution time.
                            response = client.PostAsJsonAsync(Startup.ServerAddress + "/api/task/TaskReady", new TaskReady()
                            {
                                Tasks = new GXTask[] { task }
                            }).Result;
                            Helpers.CheckStatus(response);
                        }
                    }
                    else
                    {
                        try
                        {
                            using (response = await client.PostAsJsonAsync(Startup.ServerAddress + "/api/task/WaitChange", new WaitChange()
                            {
                                Change = TargetType.Tasks, Time = lastUpdated, WaitTime = _waitTime
                            }))
                            {
                                Helpers.CheckStatus(response);
                                {
                                    WaitChangeResponse r = await response.Content.ReadAsAsync <WaitChangeResponse>();

                                    if (r.Time > lastUpdated)
                                    {
                                        lastUpdated = r.Time;
                                    }
                                }
                            }
                        }
                        catch (Exception ex)
                        {
                            if (!_cancellationToken.IsCancellationRequested)
                            {
                                break;
                            }
                            _cancellationToken.WaitHandle.WaitOne(TimeSpan.FromSeconds(10));
                        }
                    }
                }
                catch (Exception ex)
                {
                    //If app is closing.
                    if (_cancellationToken.IsCancellationRequested)
                    {
                        break;
                    }
                    if (ret == null)
                    {
                        _logger.LogError("Failed to connect to the DB server.");
                    }
                    else
                    {
                        AddError error = new AddError();
                        error.Error = new GXError()
                        {
                            DeviceId = ret.Tasks[0].Object.DeviceId,
                            Error    = "Failed to " + ret.Tasks[0].TaskType + " " + ret.Tasks[0].Object.LogicalName + ":" + ret.Tasks[0].Index + ". " + ex.Message
                        };
                        using (response = await client.PostAsJsonAsync(Startup.ServerAddress + "/api/error/AddError", error))
                        {
                            if (ret.Tasks != null)
                            {
                                DateTime now = DateTime.Now;
                                foreach (GXTask it in ret.Tasks)
                                {
                                    it.Result = ex.Message;
                                    it.End    = now;
                                }
                                response = await client.PostAsJsonAsync(Startup.ServerAddress + "/api/task/TaskReady", new TaskReady()
                                {
                                    Tasks = ret.Tasks
                                });
                            }
                        }
                    }
                    _logger.LogError(ex.Message);
                }
            }
        }
 /// <summary>
 /// Update ephemeral keys.
 /// </summary>
 /// <param name="value"></param>
 /// <returns>List of Parsed key id and GUAK. This is for debugging purpose.</returns>
 public List <KeyValuePair <GlobalKeyType, byte[]> > UpdateEphemeralKeys(GXDLMSSecureClient client, byte[] value)
 {
     return(UpdateEphemeralKeys(client, new GXByteBuffer(value)));
 }
        /// <summary>
        /// Update ephemeral keys.
        /// </summary>
        /// <param name="client">DLMS Client.</param>
        /// <param name="value">Received reply from the server.</param>
        /// <returns>List of Parsed key id and GUAK. This is for debugging purpose.</returns>
        public List <KeyValuePair <GlobalKeyType, byte[]> > UpdateEphemeralKeys(GXDLMSSecureClient client, GXByteBuffer value)
        {
            if (client == null)
            {
                throw new ArgumentNullException(nameof(client));
            }
            if (value.GetUInt8() != (byte)DataType.Array)
            {
                throw new ArgumentOutOfRangeException("Invalid tag.");
            }
            GXEcdsa c     = new GXEcdsa(client.Ciphering.EphemeralKeyPair.Key);
            int     count = GXCommon.GetObjectCount(value);
            List <KeyValuePair <GlobalKeyType, byte[]> > list = new List <KeyValuePair <GlobalKeyType, byte[]> >();

            for (int pos = 0; pos != count; ++pos)
            {
                if (value.GetUInt8() != (byte)DataType.Structure)
                {
                    throw new ArgumentOutOfRangeException("Invalid tag.");
                }
                if (value.GetUInt8() != 2)
                {
                    throw new ArgumentOutOfRangeException("Invalid length.");
                }
                if (value.GetUInt8() != (byte)DataType.Enum)
                {
                    throw new ArgumentOutOfRangeException("Invalid key id data type.");
                }
                int keyId = value.GetUInt8();
                if (keyId > 4)
                {
                    throw new ArgumentOutOfRangeException("Invalid key type.");
                }
                if (value.GetUInt8() != (byte)DataType.OctetString)
                {
                    throw new ArgumentOutOfRangeException("Invalid tag.");
                }
                if (GXCommon.GetObjectCount(value) != 128)
                {
                    throw new ArgumentOutOfRangeException("Invalid length.");
                }
                //Get ephemeral public key server.
                GXByteBuffer key = new GXByteBuffer();
                key.SetUInt8(4);
                key.Set(value, 64);
                GXPublicKey targetEphemeralKey = GXPublicKey.FromRawBytes(key.Array());
                //Get ephemeral public key signature server.
                byte[] signature = new byte[64];
                value.Get(signature);
                key.SetUInt8(0, (byte)keyId);
                //Verify signature.
                if (!GXSecure.ValidateEphemeralPublicKeySignature(key.Array(), signature, client.Ciphering.SigningKeyPair.Value))
                {
                    throw new GXDLMSCipherException("Invalid signature.");
                }
                byte[] z = c.GenerateSecret(targetEphemeralKey);
                System.Diagnostics.Debug.WriteLine("Shared secret:" + GXCommon.ToHex(z, true));
                GXByteBuffer kdf = new GXByteBuffer();
                kdf.Set(GXSecure.GenerateKDF(client.SecuritySuite, z,
                                             AlgorithmId.AesGcm128,
                                             client.Ciphering.SystemTitle,
                                             client.Settings.SourceSystemTitle, null, null));
                System.Diagnostics.Debug.WriteLine("KDF:" + kdf.ToString());
                list.Add(new KeyValuePair <GlobalKeyType, byte[]>((GlobalKeyType)keyId, kdf.SubArray(0, 16)));
            }
            //Update ephemeral keys.
            foreach (KeyValuePair <GlobalKeyType, byte[]> it in list)
            {
                switch (it.Key)
                {
                case GlobalKeyType.UnicastEncryption:
                    client.Settings.EphemeralBlockCipherKey = it.Value;
                    break;

                case GlobalKeyType.BroadcastEncryption:
                    client.Settings.EphemeralBroadcastBlockCipherKey = it.Value;
                    break;

                case GlobalKeyType.Authentication:
                    client.Settings.EphemeralAuthenticationKey = it.Value;
                    break;

                case GlobalKeyType.Kek:
                    client.Settings.EphemeralKek = it.Value;
                    break;
                }
            }
            return(list);
        }
        byte[] IGXDLMSBase.Invoke(GXDLMSSettings settings, ValueEventArgs e)
        {
            if (e.Index == 1)
            {
                SecurityPolicy = (SecurityPolicy)e.Parameters;
            }
            else if (e.Index == 2)
            {
                try
                {
                    foreach (List <object> item in e.Parameters as List <object> )
                    {
                        GlobalKeyType type = (GlobalKeyType)Convert.ToInt32(item[0]);
                        byte[]        data = (byte[])item[1];
                        //if settings.Cipher is null non secure server is used.
                        //Keys are take in action after reply is generated.
                        switch (type)
                        {
                        case GlobalKeyType.UnicastEncryption:
                            GXDLMSSecureClient.Decrypt(settings.Kek, data);
                            break;

                        case GlobalKeyType.BroadcastEncryption:
                            //Invalid type
                            e.Error = ErrorCode.ReadWriteDenied;
                            break;

                        case GlobalKeyType.Authentication:
                            GXDLMSSecureClient.Decrypt(settings.Kek, data);
                            break;

                        case GlobalKeyType.Kek:
                            GXDLMSSecureClient.Decrypt(settings.Kek, data);
                            break;

                        default:
                            //Invalid type
                            e.Error = ErrorCode.ReadWriteDenied;
                            break;
                        }
                    }
                }
                catch (Exception)
                {
                    e.Error = ErrorCode.ReadWriteDenied;
                }
            }
            else if (e.Index == 3)
            {
                // key_agreement
                try
                {
                    List <Object> tmp   = (List <Object>)(e.Parameters as List <Object>)[0];
                    byte          keyId = (byte)tmp[0];
                    if (keyId != 0)
                    {
                        e.Error = ErrorCode.InconsistentClass;
                    }
                    else
                    {
                        byte[] data = (byte[])tmp[0];
                        // ephemeral public key
                        GXByteBuffer data2 = new GXByteBuffer(65);
                        data2.SetUInt8(keyId);
                        data2.Set(data, 0, 64);
                        GXByteBuffer sign = new GXByteBuffer();
                        sign.Set(data, 64, 64);
                        GXPublicKey pk      = null;
                        string      subject = SystemTitleToSubject(settings.SourceSystemTitle);
                        foreach (GXx509Certificate it in settings.Cipher.Certificates)
                        {
                            if ((it.KeyUsage & KeyUsage.DigitalSignature) != 0 && it.Subject == subject)
                            {
                                pk = it.PublicKey;
                                break;
                            }
                        }
                        if (pk == null) //TODO:|| !GXSecure.ValidateEphemeralPublicKeySignature(data2.Array(), sign.Array(), pk))
                        {
                            e.Error = ErrorCode.InconsistentClass;
                            settings.TargetEphemeralKey = null;
                        }
                        else
                        {
                            settings.TargetEphemeralKey = GXPublicKey.FromRawBytes(data2.SubArray(1, 64));
                            // Generate ephemeral keys.
                            KeyValuePair <GXPrivateKey, GXPublicKey> eKpS = settings.Cipher.EphemeralKeyPair;
                            if (eKpS.Key == null)
                            {
                                eKpS = GXEcdsa.GenerateKeyPair(GetEcc(SecuritySuite));
                                settings.Cipher.EphemeralKeyPair = eKpS;
                            }
                            // Generate shared secret.
                            return(null);
                        }
                    }
                }
                catch (Exception)
                {
                    e.Error = ErrorCode.InconsistentClass;
                }
            }
            else if (e.Index == 4)
            {
                // generate_key_pair
                CertificateType key = (CertificateType)(int)e.Parameters;
                KeyValuePair <GXPrivateKey, GXPublicKey> value = GXEcdsa.GenerateKeyPair(GetEcc(SecuritySuite));
                switch (key)
                {
                case CertificateType.DigitalSignature:
                    settings.Cipher.SigningKeyPair = value;
                    break;

                case CertificateType.KeyAgreement:
                    settings.Cipher.KeyAgreementKeyPair = value;
                    break;

                default:
                    e.Error = ErrorCode.InconsistentClass;
                    break;
                }
            }
            else if (e.Index == 5)
            {
                // generate_certificate_request
                CertificateType key = (CertificateType)(int)e.Parameters;
                try
                {
                    KeyValuePair <GXPrivateKey, GXPublicKey> kp = default(KeyValuePair <GXPrivateKey, GXPublicKey>);
                    switch (key)
                    {
                    case CertificateType.DigitalSignature:
                        kp = settings.Cipher.SigningKeyPair;
                        break;

                    case CertificateType.KeyAgreement:
                        kp = settings.Cipher.KeyAgreementKeyPair;
                        break;

                    default:
                        break;
                    }
                    if (kp.Key != null)
                    {
                        GXPkcs10 pkc10 = GXPkcs10.CreateCertificateSigningRequest(kp, SystemTitleToSubject(settings.Cipher.SystemTitle));
                        return(pkc10.Encoded);
                    }
                    else
                    {
                        e.Error = ErrorCode.ReadWriteDenied;
                    }
                }
                catch (Exception)
                {
                    e.Error = ErrorCode.ReadWriteDenied;
                }
            }
            else if (e.Index == 6)
            {
                // import_certificate
                GXx509Certificate cert = new GXx509Certificate((byte[])e.Parameters);
                if (cert.KeyUsage == 0)
                {
                    // At least one bit must be used.
                    e.Error = ErrorCode.InconsistentClass;
                }
                else
                {
                    settings.Cipher.Certificates.Add(cert);
                }
            }
            else if (e.Index == 7)
            {
                // export_certificate
                List <Object>     tmp  = (List <Object>)e.Parameters;
                short             type = (short)tmp[0];
                GXx509Certificate cert = null;
                lock (settings.Cipher.Certificates)
                {
                    if (type == 0)
                    {
                        tmp  = (List <Object>)tmp[1];
                        cert = FindCertificateByEntity(settings, (CertificateEntity)tmp[0], (CertificateType)tmp[1], (byte[])tmp[2]);
                    }
                    else if (type == 1)
                    {
                        tmp  = (List <Object>)tmp[1];
                        cert = FindCertificateBySerial(settings, (byte[])tmp[1], ASCIIEncoding.ASCII.GetString((byte[])tmp[2]));
                    }
                    if (cert == null)
                    {
                        e.Error = ErrorCode.InconsistentClass;
                    }
                    else
                    {
                        return(cert.Encoded);
                    }
                }
            }
            else if (e.Index == 8)
            {
                // remove_certificate
                List <Object>     tmp  = (List <Object>)((List <object>)e.Parameters)[0];
                short             type = (short)tmp[0];
                GXx509Certificate cert = null;
                lock (settings.Cipher.Certificates)
                {
                    if (type == 0)
                    {
                        cert = FindCertificateByEntity(settings, (CertificateEntity)tmp[1], (CertificateType)tmp[2], (byte[])tmp[3]);
                    }
                    else if (type == 1)
                    {
                        cert = FindCertificateBySerial(settings, (byte[])tmp[1], ASCIIEncoding.ASCII.GetString((byte[])tmp[2]));
                    }
                    if (cert == null)
                    {
                        e.Error = ErrorCode.InconsistentClass;
                    }
                    else
                    {
                        settings.Cipher.Certificates.Remove(cert);
                    }
                }
            }
            else
            {
                e.Error = ErrorCode.ReadWriteDenied;
            }
            //Return standard reply.
            return(null);
        }
        /// <summary>
        /// Constructor.
        /// </summary>
        public GXDLMSDevice()
        {
            GXDLMSSecureClient client = new GXDLMSSecureClient();

            Objects = client.Objects;
        }
Exemple #21
0
        static void Main(string[] args)
        {
            IGXMedia          media = null;
            GXCommunicatation comm  = null;

            try
            {
                TextWriter logFile = new StreamWriter(File.Open("LogFile.txt", FileMode.Create));
                ////////////////////////////////////////
                //Handle command line parameters.
                String         sn, client = "", server = "", id = "", host = "", port = "", pw = "";
                bool           trace = false, iec = true;
                bool           hdlc = true, ln = true;
                Authentication auth = Authentication.None;
                foreach (string it in args)
                {
                    String item = it.Trim().ToLower();
                    if (string.Compare(item, "/u", true) == 0)//Update
                    {
                        //Get latest manufacturer settings from Gurux web server.
                        GXManufacturerCollection.UpdateManufactureSettings();
                    }
                    else if (item.StartsWith("/sn="))//Serial number.
                    {
                        sn = item.Replace("/sn=", "");
                    }
                    else if (string.Compare(item, "/wrapper", true) == 0)//Wrapper is used.
                    {
                        hdlc = false;
                    }
                    else if (item.StartsWith("/r="))//referencing
                    {
                        id = item.Replace("/r=", "");
                    }
                    else if (item.StartsWith("/m="))//Manufacturer
                    {
                        id = item.Replace("/m=", "");
                    }
                    else if (item.StartsWith("/client="))//Client address
                    {
                        client = item.Replace("/client=", "");
                    }
                    else if (item.StartsWith("/server="))//Server address
                    {
                        server = item.Replace("/server=", "");
                    }
                    else if (item.StartsWith("/h=")) //Host
                    {
                        host = item.Replace("/h=", "");
                    }
                    else if (item.StartsWith("/p="))// TCP/IP Port
                    {
                        media = new Gurux.Net.GXNet();
                        port  = item.Replace("/p=", "");
                    }
                    else if (item.StartsWith("/sp="))//Serial Port
                    {
                        port  = item.Replace("/sp=", "");
                        media = new GXSerial();
                    }
                    else if (item.StartsWith("/t"))//Are messages traced.
                    {
                        trace = true;
                    }
                    else if (item.StartsWith("/s="))//Start
                    {
                        String tmp = item.Replace("/s=", "");
                        iec = string.Compare(tmp, "dlms", true) != 0;
                    }
                    else if (item.StartsWith("/a="))//Authentication
                    {
                        auth = (Authentication)Enum.Parse(typeof(Authentication), it.Trim().Replace("/a=", ""));
                    }
                    else if (item.StartsWith("/pw="))//Password
                    {
                        pw = it.Trim().Replace("/pw=", "");
                    }
                    else
                    {
                        ShowHelp();
                        return;
                    }
                }
                if (string.IsNullOrEmpty(id) || string.IsNullOrEmpty(port) || (media is GXNet && string.IsNullOrEmpty(host)))
                {
                    ShowHelp();
                    return;
                }
                ////////////////////////////////////////
                //Initialize connection settings.
                if (media is GXSerial)
                {
                    GXSerial serial = media as GXSerial;
                    serial.PortName = port;
                    if (iec)
                    {
                        serial.BaudRate = 300;
                        serial.DataBits = 7;
                        serial.Parity   = System.IO.Ports.Parity.Even;
                        serial.StopBits = System.IO.Ports.StopBits.One;
                    }
                    else
                    {
                        serial.BaudRate = 9600;
                        serial.DataBits = 8;
                        serial.Parity   = System.IO.Ports.Parity.None;
                        serial.StopBits = System.IO.Ports.StopBits.One;
                    }
                }
                else if (media is GXNet)
                {
                    Gurux.Net.GXNet net = media as GXNet;
                    net.Port     = Convert.ToInt32(port);
                    net.HostName = host;
                    net.Protocol = Gurux.Net.NetworkType.Tcp;
                }
                else
                {
                    throw new Exception("Unknown media type.");
                }
                ////////////////////////////////////////
                //Update manufacturer depended settings.
                GXManufacturerCollection Manufacturers = new GXManufacturerCollection();
                GXManufacturerCollection.ReadManufacturerSettings(Manufacturers);
                GXManufacturer man = Manufacturers.FindByIdentification(id);
                if (man == null)
                {
                    throw new Exception("Unknown manufacturer: " + id);
                }
                GXDLMSSecureClient dlms = new GXDLMSSecureClient();
                //Update Obis code list so we can get right descriptions to the objects.
                dlms.CustomObisCodes = man.ObisCodes;
                comm       = new GXCommunicatation(dlms, media, iec, auth, pw);
                comm.Trace = trace;
                comm.InitializeConnection(man);
                GXDLMSObjectCollection objects = null;
                string path = host.Replace('.', '_') + "_" + port.ToString() + ".xml";

                List <Type> extraTypes = new List <Type>(Gurux.DLMS.GXDLMSClient.GetObjectTypes());
                extraTypes.Add(typeof(GXDLMSAttributeSettings));
                extraTypes.Add(typeof(GXDLMSAttribute));
                XmlSerializer x = new XmlSerializer(typeof(GXDLMSObjectCollection), extraTypes.ToArray());
                //You can save association view, but make sure that it is not change.
                //Save Association view to the cache so it is not needed to retrieve every time.

                /*
                 * if (File.Exists(path))
                 * {
                 *  try
                 *  {
                 *      using (Stream stream = File.Open(path, FileMode.Open))
                 *      {
                 *          Console.WriteLine("Get available objects from the cache.");
                 *          objects = x.Deserialize(stream) as GXDLMSObjectCollection;
                 *          stream.Close();
                 *      }
                 *  }
                 *  catch (Exception ex)
                 *  {
                 *      if (File.Exists(path))
                 *      {
                 *          File.Delete(path);
                 *      }
                 *      throw ex;
                 *  }
                 * }
                 * else
                 */
                {
                    Console.WriteLine("Get available objects from the device.");
                    objects = comm.GetAssociationView();
                    GXDLMSObjectCollection objs = objects.GetObjects(new ObjectType[] { ObjectType.Register, ObjectType.ExtendedRegister, ObjectType.DemandRegister });
                    Console.WriteLine("Read scalers and units from the device.");
                    if ((dlms.NegotiatedConformance & Conformance.MultipleReferences) != 0)
                    {
                        List <KeyValuePair <GXDLMSObject, int> > list = new List <KeyValuePair <GXDLMSObject, int> >();
                        foreach (GXDLMSObject it in objs)
                        {
                            if (it is GXDLMSRegister)
                            {
                                list.Add(new KeyValuePair <GXDLMSObject, int>(it, 3));
                            }
                            if (it is GXDLMSDemandRegister)
                            {
                                list.Add(new KeyValuePair <GXDLMSObject, int>(it, 4));
                            }
                        }
                        comm.ReadList(list);
                    }
                    else
                    {
                        //Read values one by one.
                        foreach (GXDLMSObject it in objs)
                        {
                            try
                            {
                                if (it is GXDLMSRegister)
                                {
                                    Console.WriteLine(it.Name);
                                    comm.Read(it, 3);
                                }
                                if (it is GXDLMSDemandRegister)
                                {
                                    Console.WriteLine(it.Name);
                                    comm.Read(it, 4);
                                }
                            }
                            catch
                            {
                                //Actaric SL7000 can return error here. Continue reading.
                            }
                        }
                    }
                    //Read Profile Generic columns first.
                    foreach (GXDLMSObject it in objects.GetObjects(ObjectType.ProfileGeneric))
                    {
                        try
                        {
                            Console.WriteLine(it.Name);
                            comm.Read(it, 3);
                            GXDLMSObject[] cols = (it as GXDLMSProfileGeneric).GetCaptureObject();
                            TraceLine(logFile, "Profile Generic " + it.Name + " Columns:");
                            StringBuilder sb    = new StringBuilder();
                            bool          First = true;
                            foreach (GXDLMSObject col in cols)
                            {
                                if (!First)
                                {
                                    sb.Append(" | ");
                                }
                                First = false;
                                sb.Append(col.Name);
                                sb.Append(" ");
                                sb.Append(col.Description);
                            }
                            TraceLine(logFile, sb.ToString());
                        }
                        catch (Exception ex)
                        {
                            TraceLine(logFile, "Err! Failed to read columns:" + ex.Message);
                            //Continue reading.
                        }
                    }
                    try
                    {
                        using (Stream stream = File.Open(path, FileMode.Create))
                        {
                            TextWriter writer = new StreamWriter(stream);
                            x.Serialize(writer, objects);
                            writer.Close();
                            stream.Close();
                        }
                    }
                    catch (Exception ex)
                    {
                        if (File.Exists(path))
                        {
                            File.Delete(path);
                        }
                        throw ex;
                    }
                    Console.WriteLine("--- Available objects ---");
                    foreach (GXDLMSObject it in objects)
                    {
                        Console.WriteLine(it.Name + " " + it.Description);
                    }
                }
                foreach (GXDLMSObject it in objects)
                {
                    // Profile generics are read later because they are special cases.
                    // (There might be so lots of data and we so not want waste time to read all the data.)
                    if (it is GXDLMSProfileGeneric)
                    {
                        continue;
                    }
                    if (!(it is IGXDLMSBase))
                    {
                        //If interface is not implemented.
                        //Example manufacturer spesific interface.
                        Console.WriteLine("Unknown Interface: " + it.ObjectType.ToString());
                        continue;
                    }
                    TraceLine(logFile, "-------- Reading " + it.GetType().Name + " " + it.Name + " " + it.Description);
                    foreach (int pos in (it as IGXDLMSBase).GetAttributeIndexToRead())
                    {
                        try
                        {
                            object val = comm.Read(it, pos);
                            //If data is array.
                            if (val is byte[])
                            {
                                val = GXCommon.ToHex((byte[])val, true);
                            }
                            else if (val is Array)
                            {
                                string str = "";
                                for (int pos2 = 0; pos2 != (val as Array).Length; ++pos2)
                                {
                                    if (str != "")
                                    {
                                        str += ", ";
                                    }
                                    if ((val as Array).GetValue(pos2) is byte[])
                                    {
                                        str += GXCommon.ToHex((byte[])(val as Array).GetValue(pos2), true);
                                    }
                                    else
                                    {
                                        str += (val as Array).GetValue(pos2).ToString();
                                    }
                                }
                                val = str;
                            }
                            else if (val is System.Collections.IList)
                            {
                                string str   = "[";
                                bool   empty = true;
                                foreach (object it2 in val as System.Collections.IList)
                                {
                                    if (!empty)
                                    {
                                        str += ", ";
                                    }
                                    empty = false;
                                    if (it2 is byte[])
                                    {
                                        str += GXCommon.ToHex((byte[])it2, true);
                                    }
                                    else
                                    {
                                        str += it2.ToString();
                                    }
                                }
                                str += "]";
                                val  = str;
                            }
                            TraceLine(logFile, "Index: " + pos + " Value: " + val);
                        }
                        catch (Exception ex)
                        {
                            TraceLine(logFile, "Error! Index: " + pos + " " + ex.Message);
                        }
                    }
                }
                //Find profile generics and read them.
                foreach (GXDLMSObject it in objects.GetObjects(ObjectType.ProfileGeneric))
                {
                    TraceLine(logFile, "-------- Reading " + it.GetType().Name + " " + it.Name + " " + it.Description);
                    long entriesInUse = Convert.ToInt64(comm.Read(it, 7));
                    long entries      = Convert.ToInt64(comm.Read(it, 8));
                    TraceLine(logFile, "Entries: " + entriesInUse + "/" + entries);
                    //If there are no columns or rows.
                    if (entriesInUse == 0 || (it as GXDLMSProfileGeneric).CaptureObjects.Count == 0)
                    {
                        continue;
                    }
                    //All meters are not supporting parameterized read.
                    if ((dlms.NegotiatedConformance & (Conformance.ParameterizedAccess | Conformance.SelectiveAccess)) != 0)
                    {
                        try
                        {
                            //Read first row from Profile Generic.
                            object[]      rows = comm.ReadRowsByEntry(it as GXDLMSProfileGeneric, 1, 1);
                            StringBuilder sb   = new StringBuilder();
                            foreach (object[] row in rows)
                            {
                                foreach (object cell in row)
                                {
                                    if (cell is byte[])
                                    {
                                        sb.Append(GXCommon.ToHex((byte[])cell, true));
                                    }
                                    else
                                    {
                                        sb.Append(Convert.ToString(cell));
                                    }
                                    sb.Append(" | ");
                                }
                                sb.Append("\r\n");
                            }
                            Trace(logFile, sb.ToString());
                        }
                        catch (Exception ex)
                        {
                            TraceLine(logFile, "Error! Failed to read first row: " + ex.Message);
                            //Continue reading.
                        }
                    }
                    //All meters are not supporting parameterized read.
                    if ((dlms.NegotiatedConformance & (Conformance.ParameterizedAccess | Conformance.SelectiveAccess)) != 0)
                    {
                        try
                        {
                            //Read last day from Profile Generic.
                            object[]      rows = comm.ReadRowsByRange(it as GXDLMSProfileGeneric, DateTime.Now.Date, DateTime.MaxValue);
                            StringBuilder sb   = new StringBuilder();
                            foreach (object[] row in rows)
                            {
                                foreach (object cell in row)
                                {
                                    if (cell is byte[])
                                    {
                                        sb.Append(GXCommon.ToHex((byte[])cell, true));
                                    }
                                    else
                                    {
                                        sb.Append(Convert.ToString(cell));
                                    }
                                    sb.Append(" | ");
                                }
                                sb.Append("\r\n");
                            }
                            Trace(logFile, sb.ToString());
                        }
                        catch (Exception ex)
                        {
                            TraceLine(logFile, "Error! Failed to read last day: " + ex.Message);
                            //Continue reading.
                        }
                    }
                }
                logFile.Flush();
                logFile.Close();
            }
            catch (Exception ex)
            {
                if (comm != null)
                {
                    comm.Close();
                }
                Console.WriteLine(ex.Message);
                if (!System.Diagnostics.Debugger.IsAttached)
                {
                    Console.ReadKey();
                }
            }
            finally
            {
                if (comm != null)
                {
                    comm.Close();
                }
                if (System.Diagnostics.Debugger.IsAttached)
                {
                    Console.WriteLine("Ended. Press any key to continue.");
                    Console.ReadKey();
                }
            }
        }
Exemple #22
0
 /// <summary>
 /// Constructor.
 /// </summary>
 /// <param name="client">DLMS Client.</param>
 /// <param name="media">Media.</param>
 public GXDLMSReader(GXDLMSSecureClient client, IGXMedia media, TraceLevel trace)
 {
     Trace  = trace;
     Media  = media;
     Client = client;
 }
        /// <summary>
        /// Read data from the meter.
        /// </summary>
        private static void ReadMeter(object parameter)
        {
            GXDLMSReader reader = null;

            System.Net.Http.HttpClient httpClient = Helpers.client;
            using (GXNet media = (GXNet)parameter)
            {
                try
                {
                    var config = new ConfigurationBuilder()
                                 .SetBasePath(Directory.GetCurrentDirectory())
                                 .AddJsonFile("appsettings.json", optional: true)
                                 .Build();
                    ListenerOptions        listener = config.GetSection("Listener").Get <ListenerOptions>();
                    GXDLMSObjectCollection objects  = new GXDLMSObjectCollection();
                    GXDLMSSecureClient     client   = new GXDLMSSecureClient(listener.UseLogicalNameReferencing, listener.ClientAddress, listener.ServerAddress, (Authentication)listener.Authentication, listener.Password, (InterfaceType)listener.Interface);
                    reader = new GXDLMSReader(client, media, _logger);
                    GXDLMSData ldn = new GXDLMSData("0.0.42.0.0.255");
                    ldn.SetUIDataType(2, DataType.String);
                    reader.InitializeConnection();
                    reader.Read(ldn, 2);
                    Console.WriteLine("Meter connected: " + ldn.Value);
                    //Find device.
                    GXDevice            dev  = null;
                    ListDevicesResponse devs = null;
                    {
                        using (System.Net.Http.HttpResponseMessage response = httpClient.PostAsJsonAsync(Startup.ServerAddress + "/api/device/ListDevices", new ListDevices()
                        {
                            Name = (string)ldn.Value
                        }).Result)
                        {
                            Helpers.CheckStatus(response);
                            devs = response.Content.ReadAsAsync <ListDevicesResponse>().Result;
                        }
                        //If device is unknown.
                        if (devs.Devices.Length == 0)
                        {
                            if (listener.DefaultDeviceTemplate == 0)
                            {
                                string str = "Unknown Meter try to connect to the Gurux.DLMS.AMI server: " + ldn.Value;
                                Console.WriteLine(str);
                                AddSystemError info = new AddSystemError();
                                info.Error = new GXSystemError()
                                {
                                    Error = str
                                };
                                using (System.Net.Http.HttpResponseMessage response = httpClient.PostAsJsonAsync(Startup.ServerAddress + "/api/SystemError/AddSystemError", info).Result)
                                {
                                    Helpers.CheckStatus(response);
                                }
                                return;
                            }
                            ListDeviceTemplates lt = new ListDeviceTemplates()
                            {
                                Ids = new UInt64[] { listener.DefaultDeviceTemplate }
                            };
                            using (System.Net.Http.HttpResponseMessage response = httpClient.PostAsJsonAsync(Startup.ServerAddress + "/api/template/ListDeviceTemplates", lt).Result)
                            {
                                Helpers.CheckStatus(response);
                                ListDeviceTemplatesResponse ret = response.Content.ReadAsAsync <ListDeviceTemplatesResponse>().Result;
                                if (ret.Devices.Length != 1)
                                {
                                    throw new Exception("DefaultDeviceTemplate value is invalid: " + listener.DefaultDeviceTemplate);
                                }
                                dev = new GXDevice();
                                GXDevice.Copy(dev, ret.Devices[0]);
                                dev.Name         = Convert.ToString(ldn.Value);
                                dev.TemplateId   = listener.DefaultDeviceTemplate;
                                dev.Manufacturer = ret.Devices[0].Name;
                            }
                            dev.Dynamic = true;
                            UpdateDevice update = new UpdateDevice();
                            update.Device = dev;
                            using (System.Net.Http.HttpResponseMessage response = httpClient.PostAsJsonAsync(Startup.ServerAddress + "/api/device/UpdateDevice", update).Result)
                            {
                                Helpers.CheckStatus(response);
                                UpdateDeviceResponse r = response.Content.ReadAsAsync <UpdateDeviceResponse>().Result;
                                dev.Id = r.DeviceId;
                            }
                            using (System.Net.Http.HttpResponseMessage response = httpClient.PostAsJsonAsync(Startup.ServerAddress + "/api/device/ListDevices", new ListDevices()
                            {
                                Ids = new UInt64[] { dev.Id }
                            }).Result)
                            {
                                Helpers.CheckStatus(response);
                                devs = response.Content.ReadAsAsync <ListDevicesResponse>().Result;
                            }
                        }
                        else if (devs.Devices.Length != 1)
                        {
                            throw new Exception("There are multiple devices with same name: " + ldn.Value);
                        }
                        else
                        {
                            dev = devs.Devices[0];
                            if (dev.Security != Security.None)
                            {
                                Console.WriteLine("Reading frame counter.");
                                GXDLMSData fc = new GXDLMSData(listener.InvocationCounter);
                                reader.Read(fc, 2);
                                dev.InvocationCounter = 1 + Convert.ToUInt32(fc.Value);
                                Console.WriteLine("Device ID: " + dev.Id + " LDN: " + (string)ldn.Value);
                                Console.WriteLine("Frame counter: " + dev.FrameCounter);
                            }
                            GetNextTaskResponse ret;
                            using (System.Net.Http.HttpResponseMessage response = httpClient.PostAsJsonAsync(Startup.ServerAddress + "/api/task/GetNextTask", new GetNextTask()
                            {
                                Listener = true, DeviceId = dev.Id
                            }).Result)
                            {
                                Helpers.CheckStatus(response);
                                ret = response.Content.ReadAsAsync <GetNextTaskResponse>().Result;
                            }
                            if (ret.Tasks == null || ret.Tasks.Length == 0)
                            {
                                Console.WriteLine("No tasks to execute");
                            }
                            else
                            {
                                Console.WriteLine("Task count: " + ret.Tasks.Length);
                                if (client.ClientAddress != dev.ClientAddress || dev.Security != Security.None)
                                {
                                    reader.Release();
                                    reader.Disconnect();
                                    client             = new GXDLMSSecureClient(dev.UseLogicalNameReferencing, dev.ClientAddress, dev.PhysicalAddress, (Authentication)dev.Authentication, dev.Password, dev.InterfaceType);
                                    client.UtcTimeZone = dev.UtcTimeZone;
                                    client.Standard    = (Standard)dev.Standard;
                                    if (dev.Conformance != 0)
                                    {
                                        client.ProposedConformance = (Conformance)dev.Conformance;
                                    }
                                    client.Priority                    = dev.Priority;
                                    client.ServiceClass                = dev.ServiceClass;
                                    client.Ciphering.SystemTitle       = GXCommon.HexToBytes(dev.ClientSystemTitle);
                                    client.Ciphering.BlockCipherKey    = GXCommon.HexToBytes(dev.BlockCipherKey);
                                    client.Ciphering.AuthenticationKey = GXCommon.HexToBytes(dev.AuthenticationKey);
                                    client.ServerSystemTitle           = GXCommon.HexToBytes(dev.DeviceSystemTitle);
                                    client.Ciphering.InvocationCounter = dev.InvocationCounter;
                                    client.Ciphering.Security          = (Security)dev.Security;
                                    reader = new GXDLMSReader(client, media, _logger);
                                    reader.InitializeConnection();
                                }
                                List <GXValue> values = new List <GXValue>();
                                foreach (GXTask task in ret.Tasks)
                                {
                                    GXDLMSObject obj = GXDLMSClient.CreateObject((ObjectType)task.Object.ObjectType);
                                    obj.LogicalName = task.Object.LogicalName;
                                    try
                                    {
                                        if (task.TaskType == TaskType.Write)
                                        {
                                            if (obj.LogicalName == "0.0.1.1.0.255" && task.Index == 2)
                                            {
                                                client.UpdateValue(obj, task.Index, GXDateTime.ToUnixTime(DateTime.UtcNow));
                                            }
                                            else
                                            {
                                                client.UpdateValue(obj, task.Index, GXDLMSTranslator.XmlToValue(task.Data));
                                            }
                                            reader.Write(obj, task.Index);
                                        }
                                        else if (task.TaskType == TaskType.Action)
                                        {
                                            reader.Method(obj, task.Index, GXDLMSTranslator.XmlToValue(task.Data), DataType.None);
                                        }
                                        else if (task.TaskType == TaskType.Read)
                                        {
                                            Reader.Reader.Read(null, httpClient, reader, task, media, obj);
                                        }
                                    }
                                    catch (Exception ex)
                                    {
                                        task.Result = ex.Message;
                                        AddError error = new AddError();
                                        error.Error = new GXError()
                                        {
                                            DeviceId = dev.Id,
                                            Error    = "Failed to " + task.TaskType + " " + task.Object.LogicalName + ":" + task.Index + ". " + ex.Message
                                        };
                                        using (System.Net.Http.HttpResponseMessage response = httpClient.PostAsJsonAsync(Startup.ServerAddress + "/api/error/AddError", error).Result)
                                        {
                                            Helpers.CheckStatus(response);
                                            response.Content.ReadAsAsync <AddErrorResponse>();
                                        }
                                    }
                                    using (System.Net.Http.HttpResponseMessage response = httpClient.PostAsJsonAsync(Startup.ServerAddress + "/api/task/TaskReady", new TaskReady()
                                    {
                                        Tasks = new GXTask[] { task }
                                    }).Result)
                                    {
                                        Helpers.CheckStatus(response);
                                    }
                                }
                            }
                        }
                    }
                }
                catch (Exception ex)
                {
                    try
                    {
                        AddSystemError info = new AddSystemError();
                        info.Error = new GXSystemError()
                        {
                            Error = ex.Message
                        };
                        using (System.Net.Http.HttpResponseMessage response = httpClient.PostAsJsonAsync(Startup.ServerAddress + "/api/SystemError/AddSystemError", info).Result)
                        {
                            Helpers.CheckStatus(response);
                        }
                    }
                    catch (Exception ex2)
                    {
                    }
                }
                finally
                {
                    if (reader != null)
                    {
                        reader.Close();
                    }
                }
            }
        }
 public GXDLMSCommunicator(GXDLMSDevice parent, Gurux.Common.IGXMedia media)
 {
     this.parent = parent;
     this.media  = media;
     client      = new GXDLMSSecureClient();
 }