mirror of
https://github.com/ckaczor/HomeMonitor.git
synced 2026-01-13 17:22:54 -05:00
Add alerts when devices reconnect after stopping
This commit is contained in:
@@ -193,4 +193,5 @@
|
||||
</TypePattern>
|
||||
</Patterns></s:String>
|
||||
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002EMemberReordering_002EMigrations_002ECSharpFileLayoutPatternRemoveIsAttributeUpgrade/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=Kaczor/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=mqtt/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>
|
||||
@@ -100,12 +100,23 @@ public class Database(IConfiguration configuration)
|
||||
return await connection.QueryFirstOrDefaultAsync<Device>(query, new { Name = deviceName }).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
public async Task SetDeviceLastUpdatedAsync(string deviceName, DateTimeOffset? lastUpdated)
|
||||
public async Task<bool> SetDeviceLastUpdatedAsync(string deviceName, DateTimeOffset? lastUpdated)
|
||||
{
|
||||
await using var connection = CreateConnection();
|
||||
|
||||
var query = ResourceReader.GetString("ChrisKaczor.HomeMonitor.Environment.Service.Data.Queries.SetDeviceLastUpdated.psql");
|
||||
|
||||
await connection.ExecuteAsync(query, new { Name = deviceName, LastUpdated = lastUpdated }).ConfigureAwait(false);
|
||||
var stoppedReporting = await connection.QueryFirstAsync<bool>(query, new { Name = deviceName, LastUpdated = lastUpdated }).ConfigureAwait(false);
|
||||
|
||||
return stoppedReporting;
|
||||
}
|
||||
|
||||
public async Task SetDeviceStoppedReportingAsync(string deviceName, bool stoppedReporting)
|
||||
{
|
||||
await using var connection = CreateConnection();
|
||||
|
||||
var query = ResourceReader.GetString("ChrisKaczor.HomeMonitor.Environment.Service.Data.Queries.SetDeviceStoppedReporting.psql");
|
||||
|
||||
await connection.ExecuteAsync(query, new { Name = deviceName, StoppedReporting = stoppedReporting }).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
@@ -1,11 +1,16 @@
|
||||
INSERT INTO device(
|
||||
name,
|
||||
last_updated
|
||||
last_updated,
|
||||
stopped_reporting
|
||||
)
|
||||
VALUES (
|
||||
@Name,
|
||||
@LastUpdated
|
||||
@LastUpdated,
|
||||
false
|
||||
)
|
||||
ON CONFLICT (name)
|
||||
DO UPDATE
|
||||
SET last_updated = EXCLUDED.last_updated
|
||||
SET last_updated = EXCLUDED.last_updated,
|
||||
stopped_reporting = false
|
||||
RETURNING
|
||||
(SELECT stopped_reporting FROM device WHERE name = @Name);
|
||||
@@ -0,0 +1,6 @@
|
||||
UPDATE
|
||||
device
|
||||
SET
|
||||
stopped_reporting = @StoppedReporting
|
||||
WHERE
|
||||
name = @Name;
|
||||
@@ -0,0 +1,4 @@
|
||||
ALTER TABLE
|
||||
device
|
||||
ADD COLUMN
|
||||
stopped_reporting boolean NOT NULL DEFAULT false;
|
||||
@@ -1,26 +1,21 @@
|
||||
using ChrisKaczor.HomeMonitor.Environment.Service.Data;
|
||||
using RestSharp;
|
||||
|
||||
namespace ChrisKaczor.HomeMonitor.Environment.Service;
|
||||
|
||||
public class DeviceCheckService(Database _database, IConfiguration _configuration) : IHostedService
|
||||
public class DeviceCheckService(Database database, IConfiguration configuration, TelegramSender telegramSender) : IHostedService
|
||||
{
|
||||
private Timer? _timer;
|
||||
private TimeSpan _warningInterval;
|
||||
|
||||
private readonly string _botToken = _configuration["Telegram:BotToken"]!;
|
||||
private readonly string _chatId = _configuration["Telegram:PersonalChatId"]!;
|
||||
private readonly RestClient _restClient = new();
|
||||
|
||||
public Task StartAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
WriteLog("DeviceCheckService started");
|
||||
|
||||
_warningInterval = TimeSpan.Parse(_configuration["Environment:DeviceWarningInterval"]!);
|
||||
_warningInterval = TimeSpan.Parse(configuration["Environment:DeviceWarningInterval"]!);
|
||||
|
||||
var checkInterval = TimeSpan.Parse(_configuration["Environment:DeviceCheckInterval"]!);
|
||||
var checkInterval = TimeSpan.Parse(configuration["Environment:DeviceCheckInterval"]!);
|
||||
|
||||
_timer = new Timer((state) => DoWork().Wait(), null, TimeSpan.Zero, checkInterval);
|
||||
_timer = new Timer(_ => DoWork().Wait(cancellationToken), null, TimeSpan.Zero, checkInterval);
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
@@ -29,7 +24,7 @@ public class DeviceCheckService(Database _database, IConfiguration _configuratio
|
||||
{
|
||||
WriteLog("Checking devices started");
|
||||
|
||||
var devices = await _database.GetDevicesAsync();
|
||||
var devices = await database.GetDevicesAsync();
|
||||
|
||||
foreach (var device in devices)
|
||||
{
|
||||
@@ -50,11 +45,9 @@ public class DeviceCheckService(Database _database, IConfiguration _configuratio
|
||||
|
||||
if (message.Length > 0)
|
||||
{
|
||||
var encodedMessage = Uri.EscapeDataString(message);
|
||||
await database.SetDeviceStoppedReportingAsync(device.Name, true);
|
||||
|
||||
var restRequest = new RestRequest($"https://api.telegram.org/bot{_botToken}/sendMessage?chat_id={_chatId}&text={encodedMessage}");
|
||||
|
||||
await _restClient.GetAsync(restRequest);
|
||||
await telegramSender.SendMessageAsync(message);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -17,11 +17,13 @@ public class MessageHandler : IHostedService
|
||||
private readonly MqttFactory _mqttFactory;
|
||||
private readonly string _topic;
|
||||
private readonly HubConnection? _hubConnection;
|
||||
private readonly TelegramSender _telegramSender;
|
||||
|
||||
public MessageHandler(IConfiguration configuration, Database database)
|
||||
public MessageHandler(IConfiguration configuration, Database database, TelegramSender telegramSender)
|
||||
{
|
||||
_configuration = configuration;
|
||||
_database = database;
|
||||
_telegramSender = telegramSender;
|
||||
|
||||
_topic = _configuration["Mqtt:Topic"] ?? string.Empty;
|
||||
|
||||
@@ -77,9 +79,16 @@ public class MessageHandler : IHostedService
|
||||
|
||||
await _database.StoreMessageAsync(message);
|
||||
|
||||
await _database.SetDeviceLastUpdatedAsync(message.Name, message.Timestamp);
|
||||
var hadStoppedReporting = await _database.SetDeviceLastUpdatedAsync(message.Name, message.Timestamp);
|
||||
|
||||
await SendMessage(message);
|
||||
|
||||
if (hadStoppedReporting)
|
||||
{
|
||||
var telegramMessage = $"Device now reporting: {message.Name}";
|
||||
|
||||
await _telegramSender.SendMessageAsync(telegramMessage);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task SendMessage(DeviceMessage message)
|
||||
|
||||
@@ -19,6 +19,7 @@ public static class Program
|
||||
builder.Services.AddControllers();
|
||||
|
||||
builder.Services.AddTransient<Database>();
|
||||
builder.Services.AddTransient<TelegramSender>();
|
||||
builder.Services.AddHostedService<MessageHandler>();
|
||||
builder.Services.AddHostedService<DeviceCheckService>();
|
||||
|
||||
|
||||
@@ -28,8 +28,10 @@
|
||||
<EmbeddedResource Include="Data\Queries\CreateReading.psql" />
|
||||
<EmbeddedResource Include="Data\Queries\GetDevices.psql" />
|
||||
<EmbeddedResource Include="Data\Queries\GetDevice.psql" />
|
||||
<EmbeddedResource Include="Data\Queries\SetDeviceStoppedReporting.psql" />
|
||||
<EmbeddedResource Include="Data\Queries\SetDeviceLastUpdated.psql" />
|
||||
<EmbeddedResource Include="Data\Schema\1-Initial Schema.psql" />
|
||||
<EmbeddedResource Include="Data\Schema\3-Device Table - StoppedReporting.psql" />
|
||||
<EmbeddedResource Include="Data\Schema\2-Device Table.psql" />
|
||||
</ItemGroup>
|
||||
|
||||
@@ -40,7 +42,7 @@
|
||||
<PackageReference Include="JetBrains.Annotations" Version="2023.3.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.SignalR.Client" Version="8.0.1" />
|
||||
<PackageReference Include="MQTTnet.AspNetCore" Version="4.3.3.952" />
|
||||
<PackageReference Include="RestSharp" Version="111.1.0" />
|
||||
<PackageReference Include="RestSharp" Version="112.1.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
19
Environment/Service/TelegramSender.cs
Normal file
19
Environment/Service/TelegramSender.cs
Normal file
@@ -0,0 +1,19 @@
|
||||
using RestSharp;
|
||||
|
||||
namespace ChrisKaczor.HomeMonitor.Environment.Service;
|
||||
|
||||
public class TelegramSender(IConfiguration configuration)
|
||||
{
|
||||
private readonly string _botToken = configuration["Telegram:BotToken"]!;
|
||||
private readonly string _chatId = configuration["Telegram:PersonalChatId"]!;
|
||||
private readonly RestClient _restClient = new();
|
||||
|
||||
public async Task SendMessageAsync(string message)
|
||||
{
|
||||
var encodedMessage = Uri.EscapeDataString(message);
|
||||
|
||||
var restRequest = new RestRequest($"https://api.telegram.org/bot{_botToken}/sendMessage?chat_id={_chatId}&text={encodedMessage}");
|
||||
|
||||
await _restClient.GetAsync(restRequest);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user