Skip to content

Commit 9d87461

Browse files
committed
feat(devices): add DeviceReachability vocabulary (enum, readings, event)
1 parent 1ce78e5 commit 9d87461

4 files changed

Lines changed: 72 additions & 0 deletions

File tree

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
namespace RustPlusBot.Abstractions.Connections;
2+
3+
/// <summary>Per-device reachability, independent of whole-server connection status.</summary>
4+
public enum DeviceReachability
5+
{
6+
/// <summary>The device read/actuated successfully.</summary>
7+
Reachable = 0,
8+
9+
/// <summary>The in-game entity no longer exists (was destroyed). Maps from <c>not_found</c>.</summary>
10+
Removed = 1,
11+
12+
/// <summary>The active player lacks building privilege / token access. Maps from <c>access_denied</c>.</summary>
13+
NoPrivilege = 2,
14+
15+
/// <summary>The device did not answer in time (timeout / unknown / other server error).</summary>
16+
NoResponse = 3,
17+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
namespace RustPlusBot.Abstractions.Connections;
2+
3+
/// <summary>A smart-switch/alarm read: on/off state plus reachability. <see cref="IsActive"/> is null unless <see cref="Reachability"/> is Reachable.</summary>
4+
/// <param name="IsActive">The device on/off state; null unless Reachable.</param>
5+
/// <param name="Reachability">The device reachability.</param>
6+
public readonly record struct DeviceReading(bool? IsActive, DeviceReachability Reachability);
7+
8+
/// <summary>A storage-monitor read: contents plus reachability. <see cref="Contents"/> is null unless <see cref="Reachability"/> is Reachable.</summary>
9+
/// <param name="Contents">The storage contents snapshot; null unless Reachable.</param>
10+
/// <param name="Reachability">The device reachability.</param>
11+
public readonly record struct StorageReading(StorageContentsSnapshot? Contents, DeviceReachability Reachability);
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
using RustPlusBot.Abstractions.Connections;
2+
3+
namespace RustPlusBot.Abstractions.Events;
4+
5+
/// <summary>Raised when a managed device's reachability changes. Device-agnostic; relays filter by entity ownership.</summary>
6+
/// <param name="GuildId">The owning guild snowflake.</param>
7+
/// <param name="ServerId">The server id.</param>
8+
/// <param name="EntityId">The in-game entity id.</param>
9+
/// <param name="Reachability">The new reachability.</param>
10+
public sealed record DeviceReachabilityChangedEvent(
11+
ulong GuildId,
12+
Guid ServerId,
13+
ulong EntityId,
14+
DeviceReachability Reachability);
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
using RustPlusBot.Abstractions.Connections;
2+
using RustPlusBot.Abstractions.Events;
3+
4+
namespace RustPlusBot.Abstractions.Tests;
5+
6+
public sealed class DeviceReachabilityVocabularyTests
7+
{
8+
[Fact]
9+
public void DeviceReachability_DefaultIsReachable() =>
10+
Assert.Equal(DeviceReachability.Reachable, default);
11+
12+
[Fact]
13+
public void DeviceReading_CarriesPayloadAndReachability()
14+
{
15+
var reading = new DeviceReading(IsActive: true, DeviceReachability.Reachable);
16+
Assert.True(reading.IsActive);
17+
Assert.Equal(DeviceReachability.Reachable, reading.Reachability);
18+
}
19+
20+
[Fact]
21+
public void Event_CarriesIdentityAndReachability()
22+
{
23+
var serverId = Guid.NewGuid();
24+
var evt = new DeviceReachabilityChangedEvent(10UL, serverId, 99UL, DeviceReachability.Removed);
25+
Assert.Equal(10UL, evt.GuildId);
26+
Assert.Equal(serverId, evt.ServerId);
27+
Assert.Equal(99UL, evt.EntityId);
28+
Assert.Equal(DeviceReachability.Removed, evt.Reachability);
29+
}
30+
}

0 commit comments

Comments
 (0)