From 85fff344b6069235b9dd0aa2e133c781ce5cee64 Mon Sep 17 00:00:00 2001 From: Chris Kaczor Date: Thu, 18 Aug 2022 12:57:45 -0400 Subject: [PATCH] Add debounce for device messages --- DeviceStatus/Service/DeviceRepository.cs | 17 +------ DeviceStatus/Service/MessageHandler.cs | 57 +++++++++++++++++++++--- DeviceStatus/Service/appsettings.json | 3 ++ 3 files changed, 55 insertions(+), 22 deletions(-) diff --git a/DeviceStatus/Service/DeviceRepository.cs b/DeviceStatus/Service/DeviceRepository.cs index b48b35d..6f5dae6 100644 --- a/DeviceStatus/Service/DeviceRepository.cs +++ b/DeviceStatus/Service/DeviceRepository.cs @@ -1,18 +1,3 @@ namespace Service; -public class DeviceRepository : Dictionary -{ - public void HandleDeviceMessage(string name, string value) - { - if (ContainsKey(name)) - { - this[name].Update(value); - } - else - { - var device = new Device(name, value); - - this[name] = device; - } - } -} \ No newline at end of file +public class DeviceRepository : Dictionary { } \ No newline at end of file diff --git a/DeviceStatus/Service/MessageHandler.cs b/DeviceStatus/Service/MessageHandler.cs index ad70618..0fbf3bf 100644 --- a/DeviceStatus/Service/MessageHandler.cs +++ b/DeviceStatus/Service/MessageHandler.cs @@ -13,12 +13,16 @@ public class MessageHandler : IHostedService private readonly IConfiguration _configuration; private readonly DeviceRepository _deviceRepository; private readonly LaundryMonitor _laundryMonitor; + private readonly Dictionary _deviceTimers = new(); + private readonly TimeSpan _deviceDelayTime; public MessageHandler(IConfiguration configuration, DeviceRepository deviceRepository, LaundryMonitor laundryMonitor) { _configuration = configuration; _deviceRepository = deviceRepository; _laundryMonitor = laundryMonitor; + + _deviceDelayTime = TimeSpan.Parse(_configuration["DeviceStatus:DelayTime"]); } public async Task StartAsync(CancellationToken cancellationToken) @@ -38,13 +42,54 @@ public class MessageHandler : IHostedService private async Task OnInterceptingPublishAsync(InterceptingPublishEventArgs arg) { - WriteLog($"{arg.ApplicationMessage.Topic}: {arg.ApplicationMessage.ConvertPayloadToString()}"); + var topic = arg.ApplicationMessage.Topic; + var payload = arg.ApplicationMessage.ConvertPayloadToString(); - _deviceRepository.HandleDeviceMessage(arg.ApplicationMessage.Topic, arg.ApplicationMessage.ConvertPayloadToString()); + WriteLog($"Topic: {topic} = {payload}"); - var device = _deviceRepository[arg.ApplicationMessage.Topic]; + var newDevice = new Device(topic, payload); - await _laundryMonitor.HandleDeviceMessage(device); + if (_deviceTimers.ContainsKey(newDevice.Name)) + await _deviceTimers[newDevice.Name].DisposeAsync(); + + if (newDevice.Status) + { + WriteLog($"{arg.ApplicationMessage.Topic}: Status true, handling immediately"); + + await HandleDeviceMessage(newDevice); + } + else + { + WriteLog($"{arg.ApplicationMessage.Topic}: Status false, setting timer"); + + _deviceTimers[newDevice.Name] = new Timer(OnDeviceTimer, newDevice, _deviceDelayTime, Timeout.InfiniteTimeSpan); + } + } + + private async void OnDeviceTimer(object? state) + { + var device = (Device)state!; + + await HandleDeviceMessage(device); + + await _deviceTimers[device.Name].DisposeAsync(); + + _deviceTimers.Remove(device.Name); + } + + private async Task HandleDeviceMessage(Device newDevice) + { + if (_deviceRepository.ContainsKey(newDevice.Name) && _deviceRepository[newDevice.Name].Status == newDevice.Status) + { + WriteLog($"Skipping device update: {newDevice.Name} = {newDevice.Status}"); + return; + } + + WriteLog($"Sending device update: {newDevice.Name} = {newDevice.Status}"); + + _deviceRepository[newDevice.Name] = newDevice; + + await _laundryMonitor.HandleDeviceMessage(newDevice); if (_hubConnection == null) return; @@ -52,9 +97,9 @@ public class MessageHandler : IHostedService try { if (_hubConnection.State == HubConnectionState.Disconnected) - _hubConnection.StartAsync().Wait(); + await _hubConnection.StartAsync(); - var json = JsonSerializer.Serialize(device); + var json = JsonSerializer.Serialize(newDevice); await _hubConnection.InvokeAsync("SendLatestStatus", json); } diff --git a/DeviceStatus/Service/appsettings.json b/DeviceStatus/Service/appsettings.json index 42f5cc5..d3f854c 100644 --- a/DeviceStatus/Service/appsettings.json +++ b/DeviceStatus/Service/appsettings.json @@ -12,5 +12,8 @@ "Telegram": { "BotToken": "", "ChatId": "" + }, + "DeviceStatus": { + "DelayTime": "00:01:00" } }