168 lines
6.9 KiB
C#
168 lines
6.9 KiB
C#
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<string, string> deviceTokens = new();
|
|
private static readonly ConcurrentDictionary<string, SemaphoreSlim> deviceSemaphores = new();
|
|
|
|
static async Task Main(string[] args)
|
|
{
|
|
List<Task> 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<DeviceRegisterResponse>(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)
|
|
{
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|