Implemented reminders to clear alarm state after 15 seconds

Signed-off-by: Paul Yuknewicz <paulyuk@Pauls-MBP-2.lan>
This commit is contained in:
Paul Yuknewicz 2023-05-22 10:53:12 -07:00
parent a3b93d848e
commit 702bbcdc81
6 changed files with 49 additions and 26 deletions

View File

@ -90,16 +90,12 @@ Expected output:
When you ran the client app:
1. A `SmartDetectorActor` is created with these properties: Id = 1, Location = "First Floor", Status = "Ready".
2. Another `SmartDetectorActor` is created with these properties: Id = 2, Location = "Second Floor", Status = "Ready".
3. The status of `SmartDetectorActor` 1 is read and printed to the console.
4. The status of `SmartDetectorActor` 2 is read and printed to the console.
5. The `DetectSmokeAsync` method of `SmartDetectorActor` 1 is called.
6. The `TriggerAlarmForAllDetectors` method of `ControllerActor` is called.
7. The `SoundAlarm` method of `SmartDetectorActor` 1 is called.
8. The `SoundAlarm` method of `SmartDetectorActor` 2 is called.
9. The status of `SmartDetectorActor` 1 is read and printed to the console.
10. The status of `SmartDetectorActor` 2 is read and printed to the console.
1. Two `SmartDetectorActor` actors are created and initialized with Id, Location, and Status="Ready"
2. The `DetectSmokeAsync` method of `SmartDetectorActor` 1 is called.
3. The `TriggerAlarmForAllDetectors` method of `ControllerActor` is called.
4. The `SoundAlarm` methods of `SmartDetectorActor` 1 and 2 are called.
5. The `ControllerActor` also creates a reminder to `ClearAlarm` after 15 seconds using `RegisterReminderAsync`
Looking at the code, `SmartDetectorActor` objects are created in the client application and initialized with object state with `ActorProxy.Create<ISmartDevice>(actorId, actorType)` and then `proxySmartDevice.SetDataAsync(data)`. These objects are re-entrant and will hold on to the state as shown by `proxySmartDevice.GetDataAsync()`.
@ -144,6 +140,25 @@ The `ControllerActor` object is used to keep track of the devices and trigger th
Console.WriteLine($"Registered devices: {string.Join(", " , deviceIds)}");
```
The `ControllerActor` internally triggers all alarms when smoke is detected, and then sets a reminder to clear all alarm states after 15 seconds.
```csharp
public async Task TriggerAlarmForAllDetectors()
{
var deviceIds = await ListRegisteredDeviceIdsAsync();
foreach (var deviceId in deviceIds)
{
// Sound the alarm on all devices
var actorId = new ActorId(deviceId);
var proxySmartDevice = ProxyFactory.CreateActorProxy<ISmartDevice>(actorId, "SmokeDetectorActor");
await proxySmartDevice.SoundAlarm();
}
// Register a reminder to refresh and clear alarm state every 15 seconds
await this.RegisterReminderAsync("AlarmRefreshReminder", null, TimeSpan.FromSeconds(15), TimeSpan.FromSeconds(15));
}
```
Additionally look at:
- `SmartDevice.Service/SmartDetectorActor.cs` which contains the implementation of the the smart device actor actions

View File

@ -57,9 +57,6 @@ class Program
var controllerActorId = new ActorId("controller");
var proxyController = ActorProxy.Create<IController>(controllerActorId, controllerActorType);
//Register reminders every 30 to clear out invalid state or alarms
await proxyController.RegisterReminder();
Console.WriteLine($"Registering the IDs of both Devices...");
await proxyController.RegisterDeviceIdsAsync(new string[]{deviceId1, deviceId2});
var deviceIds = await proxyController.ListRegisteredDeviceIdsAsync();
@ -77,8 +74,8 @@ class Program
Console.WriteLine($"Device 2 state: {storedDeviceData2}");
// Sleep for 35 seconds and observe reminders have cleared alarm state
Console.WriteLine("Sleeping for 35 seconds before observing alarm state after reminders fire");
await Task.Delay(35000);
Console.WriteLine("Sleeping for 16 seconds before checking status again to see reminders fire and clear alarms");
await Task.Delay(16000);
storedDeviceData1 = await proxySmartDevice1.GetDataAsync();
Console.WriteLine($"Device 1 state: {storedDeviceData1}");

View File

@ -6,12 +6,6 @@ public interface IController : IActor
Task RegisterDeviceIdsAsync(string[] deviceIds);
Task<string[]> ListRegisteredDeviceIdsAsync();
Task TriggerAlarmForAllDetectors();
/// <summary>
/// Registers a timer.
/// </summary>
/// <returns>A task that represents the asynchronous save operation.</returns>
Task RegisterReminder();
}
public class ControllerData

View File

@ -7,6 +7,7 @@ public interface ISmartDevice : IActor
Task<SmartDeviceData> GetDataAsync();
Task DetectSmokeAsync();
Task SoundAlarm();
Task ClearAlarm();
}
public class SmartDeviceData

View File

@ -4,7 +4,7 @@ using SmartDevice.Interfaces;
namespace SmartDevice;
internal class ControllerActor : Actor, IController
internal class ControllerActor : Actor, IController, IRemindable
{
private readonly string deviceIdsKey = "device-ids";
@ -60,12 +60,21 @@ internal class ControllerActor : Actor, IController
var proxySmartDevice = ProxyFactory.CreateActorProxy<ISmartDevice>(actorId, "SmokeDetectorActor");
await proxySmartDevice.SoundAlarm();
}
// Register a reminder to refresh and clear alarm state every 15 seconds
await this.RegisterReminderAsync("AlarmRefreshReminder", null, TimeSpan.FromSeconds(15), TimeSpan.FromSeconds(15));
}
public async Task RegisterReminder()
public async Task ReceiveReminderAsync(string reminderName, byte[] state, TimeSpan dueTime, TimeSpan period)
{
// Register a reminder to refresh alarm state every 30 seconds
await this.RegisterReminderAsync("AlarmRefreshReminder", null, TimeSpan.FromSeconds(0), TimeSpan.FromSeconds(30));
if (reminderName == "AlarmRefreshReminder") {
var deviceIds = await ListRegisteredDeviceIdsAsync();
foreach (var deviceId in deviceIds)
{
var actorId = new ActorId(deviceId);
var proxySmartDevice = ProxyFactory.CreateActorProxy<ISmartDevice>(actorId, "SmokeDetectorActor");
await proxySmartDevice.ClearAlarm();
}
}
}
}

View File

@ -81,4 +81,11 @@ internal class SmokeDetectorActor : Actor, ISmartDevice
smartDeviceData.Status = "Alarm";
await SetDataAsync(smartDeviceData);
}
public async Task ClearAlarm()
{
var smartDeviceData = await GetDataAsync();
smartDeviceData.Status = "Ready";
await SetDataAsync(smartDeviceData);
}
}