public async Task RunServer()
        {
            mac = GetMacAddress();
            Logger.LogAlways("Starting LoRaWAN Simulator...");

            if (!string.IsNullOrEmpty(Environment.GetEnvironmentVariable("SIMULATOR_PORT")))
            {
                PORT = Convert.ToInt32(Environment.GetEnvironmentVariable("SIMULATOR_PORT"));
                Logger.LogAlways($"Changing port to {PORT}");
            }

            // Creating the endpoint
            IPEndPoint endPoint = new IPEndPoint(IPAddress.Any, PORT);

            udpClient = new UdpClient(endPoint);

            Logger.LogAlways($"LoRaWAN Simulator started on port {PORT}");

            // send first sync
            _ = Task.Factory.StartNew(async() =>
            {
                while (true)
                {
                    var sync = new PhysicalPayload(GetRandomToken(), PhysicalIdentifier.PULL_DATA, null);
                    await UdpSendMessage(sync.GetSyncHeader(mac));
                    await Task.Delay(10000);
                }
            });

            // Reading the test configuration
            string json = System.IO.File.ReadAllText(@"testconfig.json");

            var theObjects = JsonConvert.DeserializeObject <JObject>(json);

            var rxpk = theObjects["rxpk"];

            this.gateway = new GatewayDevice(rxpk.ToString());

            var devices = theObjects["Devices"];

            // TODO: Need to create simulated devices
            foreach (var device in devices)
            {
                SimulatedDevice simulated = new SimulatedDevice(device.ToString());
                this.listDevices.Add(simulated);

                // create a new thread that will post content
                _ = Task.Factory.StartNew(async() =>
                {
                    simulated.dt = DateTimeOffset.Now;

                    while (true)
                    {
                        Random random = new Random();
                        var rand      = (random.NextDouble() - 0.5) * simulated.RandomInterval;
                        if (simulated.dt.AddSeconds(simulated.Interval + rand) < DateTimeOffset.Now)
                        {
                            // simulated.dt = DateTimeOffset.Now;
                            // check if the device is part of a group
                            // if yes, then find all the devices and make the loop all together
                            // send all the messages together
                            simulated.dt = DateTimeOffset.Now;
                            List <SimulatedDevice> devgroup = new List <SimulatedDevice>();
                            if (simulated.GroupRxpk != 0)
                            {
                                devgroup = this.listDevices.Where(x => x.GroupRxpk == simulated.GroupRxpk).ToList();
                            }
                            else
                            {
                                devgroup.Add(simulated);
                            }

                            // Debug.WriteLine(JsonConvert.SerializeObject(devgroup));
                            var msg          = "{\"rxpk\":[";
                            var devicetosend = string.Empty;

                            foreach (var simul in devgroup)
                            {
                                byte[] tosend;
                                simul.LastPayload = new PhysicalPayload(GetRandomToken(), PhysicalIdentifier.PUSH_DATA, null);

                                if (simul.LoRaDevice.IsJoined)
                                {
                                    tosend = simul.GetUnconfirmedDataUpMessage();
                                }
                                else
                                {
                                    // simulated.LastPayload = new PhysicalPayload(GetRandomToken(), PhysicalIdentifier.PUSH_DATA, null);
                                    // var header = simulated.LastPayload.GetSyncHeader(mac);
                                    tosend = simul.GetJoinRequest();

                                    // var rxpkgateway = gateway.GetMessage(tosend);
                                    //    var msg = "{\"rxpk\":[" + rxpkgateway + "]}";
                                    //    var gat = Encoding.Default.GetBytes(msg);
                                    //    byte[] data = new byte[header.Length + gat.Length];
                                    //    Array.Copy(header, data, header.Length);
                                    //    Array.Copy(gat, 0, data, header.Length, gat.Length);
                                    //    await UdpSendMessage(data);
                                }
                                var rxpkgateway = this.gateway.GetMessage(tosend);

                                msg          += rxpkgateway + ",";
                                devicetosend += simul.LoRaDevice.DevEUI + ",";
                                simul.dt      = DateTimeOffset.Now;
                            }
                            byte[] header = simulated.LastPayload.GetSyncHeader(mac);

                            // get rid of the the last ","
                            msg          = msg.Substring(0, msg.Length - 1);
                            msg         += "]}";
                            devicetosend = devicetosend.Substring(0, devicetosend.Length - 1);
                            var gat      = Encoding.Default.GetBytes(msg);
                            byte[] data  = new byte[header.Length + gat.Length];
                            Array.Copy(header, data, header.Length);
                            Array.Copy(gat, 0, data, header.Length, gat.Length);

                            await UdpSendMessage(data);
                            Logger.LogAlways(devicetosend, $"Sending data: {BitConverter.ToString(header).Replace("-", string.Empty)}{Encoding.Default.GetString(gat)}");
                        }
                    }
                });
            }

            // TODO: Need to start this in a thread
            await this.RunUdpListener();
        }
        public async Task RunServer()
        {
            mac = GetMacAddress();
            Logger.Log("Starting LoRaWAN Simulator...", Logger.LoggingLevel.Always);

            if (!string.IsNullOrEmpty(Environment.GetEnvironmentVariable("SIMULATOR_PORT")))
            {
                PORT = Convert.ToInt32(Environment.GetEnvironmentVariable("SIMULATOR_PORT"));
                Logger.Log($"Changing port to {PORT}", Logger.LoggingLevel.Always);
            }

            // Creating the endpoint
            IPEndPoint endPoint = new IPEndPoint(IPAddress.Any, PORT);

            udpClient = new UdpClient(endPoint);

            Logger.Log($"LoRaWAN Simulator started on port {PORT}", Logger.LoggingLevel.Always);
            //send first sync
            _ = Task.Factory.StartNew(async() =>
            {
                while (true)
                {
                    var sync = new PhysicalPayload(GetRandomToken(), PhysicalIdentifier.PUSH_DATA, null);
                    await UdpSendMessage(sync.GetSyncHeader(mac));
                    await Task.Delay(10000);
                }
            });
            // Reading the test configuration
            string json = System.IO.File.ReadAllText(@"testconfig.json");

            var theObjects = JsonConvert.DeserializeObject <JObject>(json);

            var rxpk = theObjects["rxpk"];

            gateway = new GatewayDevice(rxpk.ToString());

            var devices = theObjects["Devices"];

            // TODO: Need to create simulated devices
            foreach (var device in devices)
            {
                SimulatedDevice simulated = new SimulatedDevice(device.ToString());
                listDevices.Add(simulated);

                // create a new thread that will post content
                _ = Task.Factory.StartNew(async() =>
                {
                    DateTimeOffset dt = DateTimeOffset.Now;

                    while (true)
                    {
                        if (dt.AddSeconds(simulated.Interval) < DateTimeOffset.Now)
                        {
                            dt = DateTimeOffset.Now;
                            // send a message
                            if (simulated.LoRaDevice.IsJoined)
                            {
                                simulated.LastPayload = new PhysicalPayload(GetRandomToken(), PhysicalIdentifier.PUSH_DATA, null);
                                var header            = simulated.LastPayload.GetSyncHeader(mac);

                                var simdata     = simulated.GetUnconfirmedDataUpMessage();
                                var rxpkgateway = gateway.GetMessage(simdata);
                                var msg         = "{\"rxpk\":[" + rxpkgateway + "]}";

                                var gat     = Encoding.Default.GetBytes(msg);
                                byte[] data = new byte[header.Length + gat.Length];
                                Array.Copy(header, data, header.Length);
                                Array.Copy(gat, 0, data, header.Length, gat.Length);
                                Logger.Log(simulated.LoRaDevice.DevAddr, $"Sending data: {BitConverter.ToString(header).Replace("-", "")}{Encoding.Default.GetString(gat)}", Logger.LoggingLevel.Always);
                                await UdpSendMessage(data);
                            }
                            else
                            {
                                simulated.LastPayload = new PhysicalPayload(GetRandomToken(), PhysicalIdentifier.PUSH_DATA, null);
                                var header            = simulated.LastPayload.GetSyncHeader(mac);

                                var join        = simulated.GetJoinRequest();
                                var rxpkgateway = gateway.GetMessage(join);
                                var msg         = "{\"rxpk\":[" + rxpkgateway + "]}";

                                var gat     = Encoding.Default.GetBytes(msg);
                                byte[] data = new byte[header.Length + gat.Length];
                                Array.Copy(header, data, header.Length);
                                Array.Copy(gat, 0, data, header.Length, gat.Length);

                                await UdpSendMessage(data);
                            }
                        }
                    }
                });
            }



            // TODO: Need to start this in a thread
            await RunUdpListener();
        }