- Add MQTT area and zone user code support and update packages

This commit is contained in:
Ryan Wagoner 2021-07-28 20:33:06 -04:00
parent 92012fc0b7
commit a248bd4f30
6 changed files with 93 additions and 27 deletions

View file

@ -24,6 +24,17 @@ namespace OmniLinkBridge
return (b & (1 << pos)) != 0; return (b & (1 << pos)) != 0;
} }
public static (string, int) ToCommandCode(this string payload)
{
string[] payloads = payload.Split(',');
int code = 0;
if (payloads.Length > 1)
int.TryParse(payloads[1], out code);
return (payloads[0], code);
}
public static string ToSpaceTitleCase(this string phrase) public static string ToSpaceTitleCase(this string phrase)
{ {
return Regex.Replace(phrase, "(\\B[A-Z])", " $1"); return Regex.Replace(phrase, "(\\B[A-Z])", " $1");

View file

@ -38,7 +38,7 @@ namespace OmniLinkBridge.MQTT
if (type == CommandTypes.area && id <= OmniLink.Controller.Areas.Count) if (type == CommandTypes.area && id <= OmniLink.Controller.Areas.Count)
ProcessAreaReceived(OmniLink.Controller.Areas[id], topic, payload); ProcessAreaReceived(OmniLink.Controller.Areas[id], topic, payload);
else if (type == CommandTypes.zone && id > 0 && id <= OmniLink.Controller.Zones.Count) else if (type == CommandTypes.zone && id <= OmniLink.Controller.Zones.Count)
ProcessZoneReceived(OmniLink.Controller.Zones[id], topic, payload); ProcessZoneReceived(OmniLink.Controller.Zones[id], topic, payload);
else if (type == CommandTypes.unit && id > 0 && id <= OmniLink.Controller.Units.Count) else if (type == CommandTypes.unit && id > 0 && id <= OmniLink.Controller.Units.Count)
ProcessUnitReceived(OmniLink.Controller.Units[id], topic, payload); ProcessUnitReceived(OmniLink.Controller.Units[id], topic, payload);
@ -64,13 +64,16 @@ namespace OmniLinkBridge.MQTT
private void ProcessAreaReceived(clsArea area, Topic command, string payload) private void ProcessAreaReceived(clsArea area, Topic command, string payload)
{ {
int code;
(payload, code) = payload.ToCommandCode();
if (command == Topic.command && Enum.TryParse(payload, true, out AreaCommands cmd)) if (command == Topic.command && Enum.TryParse(payload, true, out AreaCommands cmd))
{ {
if (area.Number == 0) if (area.Number == 0)
log.Debug("SetArea: 0 implies all areas will be changed"); log.Debug("SetArea: 0 implies all areas will be changed");
log.Debug("SetArea: {id} to {value}", area.Number, cmd.ToString().Replace("arm_", "").Replace("_", " ")); log.Debug("SetArea: {id} to {value}", area.Number, cmd.ToString().Replace("arm_", "").Replace("_", " "));
OmniLink.SendCommand(AreaMapping[cmd], 0, (ushort)area.Number); OmniLink.SendCommand(AreaMapping[cmd], (byte)code, (ushort)area.Number);
} }
else if (command == Topic.alarm_command && area.Number > 0 && Enum.TryParse(payload, true, out AlarmCommands alarm)) else if (command == Topic.alarm_command && area.Number > 0 && Enum.TryParse(payload, true, out AlarmCommands alarm))
{ {
@ -92,10 +95,17 @@ namespace OmniLinkBridge.MQTT
private void ProcessZoneReceived(clsZone zone, Topic command, string payload) private void ProcessZoneReceived(clsZone zone, Topic command, string payload)
{ {
if (command == Topic.command && Enum.TryParse(payload, true, out ZoneCommands cmd)) int code;
(payload, code) = payload.ToCommandCode();
if (command == Topic.command && Enum.TryParse(payload, true, out ZoneCommands cmd) &&
!(zone.Number == 0 && cmd == ZoneCommands.bypass))
{ {
if (zone.Number == 0)
log.Debug("SetZone: 0 implies all zones will be restored");
log.Debug("SetZone: {id} to {value}", zone.Number, payload); log.Debug("SetZone: {id} to {value}", zone.Number, payload);
OmniLink.SendCommand(ZoneMapping[cmd], 0, (ushort)zone.Number); OmniLink.SendCommand(ZoneMapping[cmd], (byte)code, (ushort)zone.Number);
} }
} }

View file

@ -173,10 +173,10 @@
<Version>4.5.0</Version> <Version>4.5.0</Version>
</PackageReference> </PackageReference>
<PackageReference Include="MQTTnet.Extensions.ManagedClient"> <PackageReference Include="MQTTnet.Extensions.ManagedClient">
<Version>3.0.13</Version> <Version>3.0.16</Version>
</PackageReference> </PackageReference>
<PackageReference Include="Newtonsoft.Json"> <PackageReference Include="Newtonsoft.Json">
<Version>12.0.3</Version> <Version>13.0.1</Version>
</PackageReference> </PackageReference>
<PackageReference Include="Serilog"> <PackageReference Include="Serilog">
<Version>2.10.0</Version> <Version>2.10.0</Version>
@ -185,17 +185,20 @@
<Version>1.1.0</Version> <Version>1.1.0</Version>
</PackageReference> </PackageReference>
<PackageReference Include="Serilog.Sinks.Async"> <PackageReference Include="Serilog.Sinks.Async">
<Version>1.4.0</Version> <Version>1.5.0</Version>
</PackageReference> </PackageReference>
<PackageReference Include="Serilog.Sinks.Console"> <PackageReference Include="Serilog.Sinks.Console">
<Version>3.1.1</Version> <Version>4.0.0</Version>
</PackageReference> </PackageReference>
<PackageReference Include="Serilog.Sinks.File"> <PackageReference Include="Serilog.Sinks.File">
<Version>4.1.0</Version> <Version>5.0.0</Version>
</PackageReference> </PackageReference>
<PackageReference Include="Serilog.Sinks.Http"> <PackageReference Include="Serilog.Sinks.Http">
<Version>7.2.0</Version> <Version>7.2.0</Version>
</PackageReference> </PackageReference>
<PackageReference Include="System.ValueTuple">
<Version>4.5.0</Version>
</PackageReference>
</ItemGroup> </ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it. <!-- To modify your build process, add your task inside one of the targets below and uncomment it.

View file

@ -38,6 +38,23 @@ namespace OmniLinkBridgeTest
Assert.AreEqual(true, ((byte)3).IsBitSet(1)); Assert.AreEqual(true, ((byte)3).IsBitSet(1));
} }
[TestMethod]
public void TestToCommandCode()
{
string payload, command;
int code;
payload = "disarm";
(command, code) = payload.ToCommandCode();
Assert.AreEqual(command, "disarm");
Assert.AreEqual(code, 0);
payload = "disarm,1";
(command, code) = payload.ToCommandCode();
Assert.AreEqual(command, "disarm");
Assert.AreEqual(code, 1);
}
[TestMethod] [TestMethod]
public void TestParseRange() public void TestParseRange()
{ {

View file

@ -39,7 +39,7 @@ namespace OmniLinkBridgeTest
[TestMethod] [TestMethod]
public void AreaCommand() public void AreaCommand()
{ {
void check(ushort id, string payload, enuUnitCommand command) void check(ushort id, int code, string payload, enuUnitCommand command)
{ {
SendCommandEventArgs actual = null; SendCommandEventArgs actual = null;
omniLink.OnSendCommand += (sender, e) => { actual = e; }; omniLink.OnSendCommand += (sender, e) => { actual = e; };
@ -47,29 +47,35 @@ namespace OmniLinkBridgeTest
SendCommandEventArgs expected = new SendCommandEventArgs() SendCommandEventArgs expected = new SendCommandEventArgs()
{ {
Cmd = command, Cmd = command,
Par = 0, Par = (byte)code,
Pr2 = id Pr2 = id
}; };
Assert.AreEqual(expected, actual); Assert.AreEqual(expected, actual);
} }
// First area standard format // Standard format
check(1, "disarm", enuUnitCommand.SecurityOff); check(1, 0, "disarm", enuUnitCommand.SecurityOff);
check(1, "arm_home", enuUnitCommand.SecurityDay); check(1, 0, "arm_home", enuUnitCommand.SecurityDay);
check(1, "arm_away", enuUnitCommand.SecurityAway); check(1, 0, "arm_away", enuUnitCommand.SecurityAway);
check(1, "arm_night", enuUnitCommand.SecurityNight); check(1, 0, "arm_night", enuUnitCommand.SecurityNight);
check(1, "arm_home_instant", enuUnitCommand.SecurityDyi); check(1, 0, "arm_home_instant", enuUnitCommand.SecurityDyi);
check(1, "arm_night_delay", enuUnitCommand.SecurityNtd); check(1, 0, "arm_night_delay", enuUnitCommand.SecurityNtd);
check(1, "arm_vacation", enuUnitCommand.SecurityVac); check(1, 0, "arm_vacation", enuUnitCommand.SecurityVac);
// Last area with case check // Check all areas
check(8, "DISARM", enuUnitCommand.SecurityOff); check(0, 0, "disarm", enuUnitCommand.SecurityOff);
// Check with optional code
check(1, 1, "disarm,1", enuUnitCommand.SecurityOff);
// Check case insensitivity
check(8, 0, "DISARM", enuUnitCommand.SecurityOff);
} }
[TestMethod] [TestMethod]
public void ZoneCommand() public void ZoneCommand()
{ {
void check(ushort id, string payload, enuUnitCommand command) void check(ushort id, int code, string payload, enuUnitCommand command, bool ensureNull = false)
{ {
SendCommandEventArgs actual = null; SendCommandEventArgs actual = null;
omniLink.OnSendCommand += (sender, e) => { actual = e; }; omniLink.OnSendCommand += (sender, e) => { actual = e; };
@ -77,16 +83,31 @@ namespace OmniLinkBridgeTest
SendCommandEventArgs expected = new SendCommandEventArgs() SendCommandEventArgs expected = new SendCommandEventArgs()
{ {
Cmd = command, Cmd = command,
Par = 0, Par = (byte)code,
Pr2 = id Pr2 = id
}; };
if (ensureNull)
Assert.IsNull(actual);
else
Assert.AreEqual(expected, actual); Assert.AreEqual(expected, actual);
} }
check(1, "bypass", enuUnitCommand.Bypass); // Standard format
check(1, "restore", enuUnitCommand.Restore); check(1, 0, "bypass", enuUnitCommand.Bypass);
check(1, 0, "restore", enuUnitCommand.Restore);
check(2, "BYPASS", enuUnitCommand.Bypass); // Check all zones
check(0, 0, "restore", enuUnitCommand.Restore);
// Not allowed to bypass all zones
check(0, 0, "bypass", enuUnitCommand.Bypass, true);
// Check with optional code
check(1, 1, "bypass,1", enuUnitCommand.Bypass);
// Check case insensitivity
check(2, 0, "BYPASS", enuUnitCommand.Bypass);
} }
[TestMethod] [TestMethod]

View file

@ -177,6 +177,8 @@ string json
PUB omnilink/areaX/command PUB omnilink/areaX/command
string arm_home, arm_away, arm_night, disarm, arm_home_instant, arm_night_delay, arm_vacation string arm_home, arm_away, arm_night, disarm, arm_home_instant, arm_night_delay, arm_vacation
note Use area 0 for all areas
note Optionally the user code number can be specified 'disarm,1'
PUB omnilink/areaX/alarm_command PUB omnilink/areaX/alarm_command
string burglary, fire, auxiliary string burglary, fire, auxiliary
@ -201,6 +203,8 @@ int Current relative humidity
PUB omnilink/zoneX/command PUB omnilink/zoneX/command
string bypass, restore string bypass, restore
note Use zone 0 to restore all zones
note Optionally the user code number can be specified 'bypass,1'
``` ```
### Units ### Units