using System.Security.Cryptography; using System.Text.Json; using System.Text; using MQTTnet; using MQTTnet.Protocol; using Newtonsoft.Json; using System.Collections.Concurrent; namespace SimulatedTrackingDevice { internal class Program { private static readonly string BrokerIp = "127.0.0.1"; //private static readonly string BrokerIp = "localhost"; private static readonly int BrokerPort = 1883; private static readonly string Username = "emqxdevice"; private static readonly string Password = "sivan@123"; private static readonly string DevicePasswordSalt = "navis@salt"; private static readonly int secondsToReconnect = 2000; private static readonly int secondsToHealthcheck = 10000; //private static readonly int DeviceCount = 1000; private static readonly string UpdatePVTTopic = "iot/device/update_pvt"; private static readonly ConcurrentDictionary deviceTokens = new(); private static readonly ConcurrentDictionary deviceSemaphores = new(); static async Task Main(string[] args) { List deviceTasks = new(); for (int i = 1; i <= 1; i++) { string localMacAddress = $"DeviceTest{i:0000}"; deviceSemaphores[localMacAddress] = new SemaphoreSlim(1, 1); // Tạo semaphore riêng cho từng thiết bị //deviceTasks.Add(AllDevicePublish(macAddress, i)); deviceTasks.Add(SimulateDevice(localMacAddress)); await Task.Delay(50); // Tránh quá tải khi tạo quá nhiều thiết bị cùng lúc } await Task.WhenAll(deviceTasks); } private static async Task SimulateDevice(string localMacAddress) { try { var factory = new MqttClientFactory(); var mqttClient = factory.CreateMqttClient(); string token = ""; var options = new MqttClientOptionsBuilder() .WithClientId(localMacAddress) .WithTcpServer(BrokerIp, BrokerPort) .WithCredentials(Username, Password) .WithCleanSession() .Build(); mqttClient.ApplicationMessageReceivedAsync += async e => { var macAddressProperty = e.ApplicationMessage.UserProperties .FirstOrDefault(p => p.Name == "MacAddress")?.Value; if (macAddressProperty == localMacAddress) { var commandTopic = "iot/server/" + localMacAddress + "/command"; string topic = e.ApplicationMessage.Topic; string payload = Encoding.UTF8.GetString(e.ApplicationMessage.Payload); if (topic == ResponseTopic) { if (!string.IsNullOrEmpty(payload)) { var response = System.Text.Json.JsonSerializer.Deserialize(payload); token = response.AccessToken; // Unsubscribe khỏi topic response sau khi nhận token await mqttClient.UnsubscribeAsync(ResponseTopic); Console.WriteLine(localMacAddress + ": Unsubscribed from response topic"); // log file Log2File("./LogFiles/" + localMacAddress + ".txt", DateTime.UtcNow.AddHours(7).ToString("yyyy/MM/dd HH:mm:ss") + " - Received: " + payload); } } else if (topic == commandTopic) { // xu ly lenh gui tu server Console.WriteLine(localMacAddress + ": " + payload); // log file Log2File("./LogFiles/" + localMacAddress + ".txt", DateTime.UtcNow.AddHours(7).ToString("yyyy/MM/dd HH:mm:ss") + " - Received: " + payload); } } }; await mqttClient.ConnectAsync(options, CancellationToken.None); await mqttClient.SubscribeAsync(ResponseTopic, MqttQualityOfServiceLevel.AtLeastOnce); await SendRegistrationRequest(mqttClient, localMacAddress); while (string.IsNullOrEmpty(token)) { await Task.Delay(1000); } var _factory = new MqttClientFactory(); var _mqttClient = _factory.CreateMqttClient(); var _options = new MqttClientOptionsBuilder() .WithClientId(localMacAddress) .WithTcpServer(BrokerIp, BrokerPort) .WithCredentials(localMacAddress, token) .WithCleanSession() .Build(); _mqttClient.DisconnectedAsync += async (e) => { Console.WriteLine($"MQTT Disconnected. Reason: {e.ToString()}"); // Nếu lỗi có thể do token hết hạn, gửi lại request đăng ký if (e.Reason == MqttClientDisconnectReason.NotAuthorized) { Console.WriteLine("Token might be expired. Sending Register..."); } }; await _mqttClient.ConnectAsync(_options, CancellationToken.None); while (true) { await SendHealthData(_mqttClient, localMacAddress, token); await Task.Delay(10000); } } catch (Exception ex) { // log file Log2File("./LogFiles/Exceptions.txt", DateTime.UtcNow.AddHours(7).ToString("yyyy/MM/dd HH:mm:ss") + "- User: " + Username + " - " + localMacAddress + ": " + ex.ToString()); } } public static void Log2File(string filePath, string data) { try { FileInfo info = new FileInfo(filePath); try { if (info.Exists && info.Length > 10000000) // delete the file first if 10 MB { File.Delete(filePath); } } catch (Exception ex) { } using (var fs = File.Open(filePath, FileMode.Append)) { using (var sw = new StreamWriter(fs)) { sw.WriteLine(data); } } } catch (Exception ex) { } } } }