- 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;
}
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)
{
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)
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);
else if (type == CommandTypes.unit && id > 0 && id <= OmniLink.Controller.Units.Count)
ProcessUnitReceived(OmniLink.Controller.Units[id], topic, payload);
@ -64,13 +64,16 @@ namespace OmniLinkBridge.MQTT
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 (area.Number == 0)
log.Debug("SetArea: 0 implies all areas will be changed");
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))
{
@ -92,10 +95,17 @@ namespace OmniLinkBridge.MQTT
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);
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>
</PackageReference>
<PackageReference Include="MQTTnet.Extensions.ManagedClient">
<Version>3.0.13</Version>
<Version>3.0.16</Version>
</PackageReference>
<PackageReference Include="Newtonsoft.Json">
<Version>12.0.3</Version>
<Version>13.0.1</Version>
</PackageReference>
<PackageReference Include="Serilog">
<Version>2.10.0</Version>
@ -185,17 +185,20 @@
<Version>1.1.0</Version>
</PackageReference>
<PackageReference Include="Serilog.Sinks.Async">
<Version>1.4.0</Version>
<Version>1.5.0</Version>
</PackageReference>
<PackageReference Include="Serilog.Sinks.Console">
<Version>3.1.1</Version>
<Version>4.0.0</Version>
</PackageReference>
<PackageReference Include="Serilog.Sinks.File">
<Version>4.1.0</Version>
<Version>5.0.0</Version>
</PackageReference>
<PackageReference Include="Serilog.Sinks.Http">
<Version>7.2.0</Version>
</PackageReference>
<PackageReference Include="System.ValueTuple">
<Version>4.5.0</Version>
</PackageReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- 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));
}
[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]
public void TestParseRange()
{

View file

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

View file

@ -177,6 +177,8 @@ string json
PUB omnilink/areaX/command
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
string burglary, fire, auxiliary
@ -201,6 +203,8 @@ int Current relative humidity
PUB omnilink/zoneX/command
string bypass, restore
note Use zone 0 to restore all zones
note Optionally the user code number can be specified 'bypass,1'
```
### Units