mirror of
https://github.com/excaliburpartners/OmniLinkBridge
synced 2024-12-22 10:42:24 +00:00
- Refactor MQTT parser and add unit tests
This commit is contained in:
parent
dbad9ea3ce
commit
cb24322bef
|
@ -1,10 +1,4 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace OmniLinkBridge.MQTT
|
||||
namespace OmniLinkBridge.MQTT
|
||||
{
|
||||
public class Alarm : Device
|
||||
{
|
||||
|
|
14
OmniLinkBridge/MQTT/AreaCommands.cs
Normal file
14
OmniLinkBridge/MQTT/AreaCommands.cs
Normal file
|
@ -0,0 +1,14 @@
|
|||
namespace OmniLinkBridge.MQTT
|
||||
{
|
||||
enum AreaCommands
|
||||
{
|
||||
disarm,
|
||||
arm_home,
|
||||
arm_away,
|
||||
arm_night,
|
||||
// The below aren't supported by Home Assistant
|
||||
arm_home_instant,
|
||||
arm_night_delay,
|
||||
arm_vacation
|
||||
}
|
||||
}
|
|
@ -1,10 +1,4 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace OmniLinkBridge.MQTT
|
||||
namespace OmniLinkBridge.MQTT
|
||||
{
|
||||
public class AreaState
|
||||
{
|
||||
|
|
|
@ -1,10 +1,5 @@
|
|||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Converters;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace OmniLinkBridge.MQTT
|
||||
{
|
||||
|
|
|
@ -1,8 +1,4 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace OmniLinkBridge.MQTT
|
||||
{
|
||||
|
|
11
OmniLinkBridge/MQTT/CommandTypes.cs
Normal file
11
OmniLinkBridge/MQTT/CommandTypes.cs
Normal file
|
@ -0,0 +1,11 @@
|
|||
namespace OmniLinkBridge.MQTT
|
||||
{
|
||||
enum CommandTypes
|
||||
{
|
||||
area,
|
||||
zone,
|
||||
unit,
|
||||
thermostat,
|
||||
button
|
||||
}
|
||||
}
|
|
@ -1,10 +1,5 @@
|
|||
using Newtonsoft.Json;
|
||||
using OmniLinkBridge.Modules;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace OmniLinkBridge.MQTT
|
||||
{
|
||||
|
|
|
@ -1,10 +1,4 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace OmniLinkBridge.MQTT
|
||||
namespace OmniLinkBridge.MQTT
|
||||
{
|
||||
public class DeviceRegistry
|
||||
{
|
||||
|
|
|
@ -1,10 +1,4 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace OmniLinkBridge.MQTT
|
||||
namespace OmniLinkBridge.MQTT
|
||||
{
|
||||
public class Light : Device
|
||||
{
|
||||
|
|
|
@ -1,9 +1,4 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using HAI_Shared;
|
||||
using HAI_Shared;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace OmniLinkBridge.MQTT
|
||||
|
@ -376,7 +371,7 @@ namespace OmniLinkBridge.MQTT
|
|||
|
||||
public static string ToState(this clsUnit unit)
|
||||
{
|
||||
return unit.Status == 0 || unit.Status == 100 ? "OFF" : "ON";
|
||||
return unit.Status == 0 || unit.Status == 100 ? UnitCommands.OFF.ToString() : UnitCommands.ON.ToString();
|
||||
}
|
||||
|
||||
public static int ToBrightnessState(this clsUnit unit)
|
||||
|
|
185
OmniLinkBridge/MQTT/MessageProcessor.cs
Normal file
185
OmniLinkBridge/MQTT/MessageProcessor.cs
Normal file
|
@ -0,0 +1,185 @@
|
|||
using HAI_Shared;
|
||||
using log4net;
|
||||
using OmniLinkBridge.OmniLink;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace OmniLinkBridge.MQTT
|
||||
{
|
||||
public class MessageProcessor
|
||||
{
|
||||
private static ILog log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||
|
||||
private readonly Regex regexTopic = new Regex(Global.mqtt_prefix + "/([A-Za-z]+)([0-9]+)/(.*)", RegexOptions.Compiled);
|
||||
|
||||
private IOmniLinkII OmniLink { get; set; }
|
||||
|
||||
public MessageProcessor(IOmniLinkII omni)
|
||||
{
|
||||
OmniLink = omni;
|
||||
}
|
||||
|
||||
public void Process(string messageTopic, string payload)
|
||||
{
|
||||
Match match = regexTopic.Match(messageTopic);
|
||||
|
||||
if (!match.Success)
|
||||
return;
|
||||
|
||||
if (!Enum.TryParse(match.Groups[1].Value, true, out CommandTypes type)
|
||||
|| !Enum.TryParse(match.Groups[3].Value, true, out Topic topic)
|
||||
|| !ushort.TryParse(match.Groups[2].Value, out ushort id))
|
||||
return;
|
||||
|
||||
log.Debug($"Received: Type: {type.ToString()}, Id: {id}, Command: {topic.ToString()}, Value: {payload}");
|
||||
|
||||
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)
|
||||
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);
|
||||
else if (type == CommandTypes.thermostat && id > 0 && id <= OmniLink.Controller.Thermostats.Count)
|
||||
ProcessThermostatReceived(OmniLink.Controller.Thermostats[id], topic, payload);
|
||||
else if (type == CommandTypes.button && id > 0 && id <= OmniLink.Controller.Buttons.Count)
|
||||
ProcessButtonReceived(OmniLink.Controller.Buttons[id], topic, payload);
|
||||
}
|
||||
|
||||
private IDictionary<AreaCommands, enuUnitCommand> AreaMapping = new Dictionary<AreaCommands, enuUnitCommand>
|
||||
{
|
||||
{ AreaCommands.disarm, enuUnitCommand.SecurityOff },
|
||||
{ AreaCommands.arm_home, enuUnitCommand.SecurityDay },
|
||||
{ AreaCommands.arm_away, enuUnitCommand.SecurityAway },
|
||||
{ AreaCommands.arm_night, enuUnitCommand.SecurityNight },
|
||||
// The below aren't supported by Home Assistant
|
||||
{ AreaCommands.arm_home_instant, enuUnitCommand.SecurityDyi },
|
||||
{ AreaCommands.arm_night_delay, enuUnitCommand.SecurityNtd },
|
||||
{ AreaCommands.arm_vacation, enuUnitCommand.SecurityVac },
|
||||
};
|
||||
|
||||
private void ProcessAreaReceived(clsArea area, Topic command, string payload)
|
||||
{
|
||||
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: " + area.Number + " to " + cmd.ToString().Replace("arm_", "").Replace("_", " "));
|
||||
OmniLink.SendCommand(AreaMapping[cmd], 0, (ushort)area.Number);
|
||||
}
|
||||
}
|
||||
|
||||
private IDictionary<ZoneCommands, enuUnitCommand> ZoneMapping = new Dictionary<ZoneCommands, enuUnitCommand>
|
||||
{
|
||||
{ ZoneCommands.restore, enuUnitCommand.Restore },
|
||||
{ ZoneCommands.bypass, enuUnitCommand.Bypass },
|
||||
};
|
||||
|
||||
private void ProcessZoneReceived(clsZone zone, Topic command, string payload)
|
||||
{
|
||||
if (command == Topic.command && Enum.TryParse(payload, true, out ZoneCommands cmd))
|
||||
{
|
||||
log.Debug("SetZone: " + zone.Number + " to " + payload);
|
||||
OmniLink.SendCommand(ZoneMapping[cmd], 0, (ushort)zone.Number);
|
||||
}
|
||||
}
|
||||
|
||||
private IDictionary<UnitCommands, enuUnitCommand> UnitMapping = new Dictionary<UnitCommands, enuUnitCommand>
|
||||
{
|
||||
{ UnitCommands.OFF, enuUnitCommand.Off },
|
||||
{ UnitCommands.ON, enuUnitCommand.On }
|
||||
};
|
||||
|
||||
private void ProcessUnitReceived(clsUnit unit, Topic command, string payload)
|
||||
{
|
||||
if (command == Topic.command && Enum.TryParse(payload, true, out UnitCommands cmd))
|
||||
{
|
||||
if (string.Compare(unit.ToState(), cmd.ToString()) != 0)
|
||||
{
|
||||
log.Debug("SetUnit: " + unit.Number + " to " + cmd.ToString());
|
||||
OmniLink.SendCommand(UnitMapping[cmd], 0, (ushort)unit.Number);
|
||||
}
|
||||
}
|
||||
else if (command == Topic.brightness_command && int.TryParse(payload, out int unitValue))
|
||||
{
|
||||
log.Debug("SetUnit: " + unit.Number + " to " + payload + "%");
|
||||
|
||||
OmniLink.SendCommand(enuUnitCommand.Level, BitConverter.GetBytes(unitValue)[0], (ushort)unit.Number);
|
||||
|
||||
// Force status change instead of waiting on controller to update
|
||||
// Home Assistant sends brightness immediately followed by ON,
|
||||
// which will cause light to go to 100% brightness
|
||||
unit.Status = (byte)(100 + unitValue);
|
||||
}
|
||||
}
|
||||
|
||||
private void ProcessThermostatReceived(clsThermostat thermostat, Topic command, string payload)
|
||||
{
|
||||
if (command == Topic.temperature_heat_command && double.TryParse(payload, out double tempLow))
|
||||
{
|
||||
string tempUnit = "C";
|
||||
if (OmniLink.Controller.TempFormat == enuTempFormat.Fahrenheit)
|
||||
{
|
||||
tempLow = tempLow.ToCelsius();
|
||||
tempUnit = "F";
|
||||
}
|
||||
|
||||
int temp = tempLow.ToOmniTemp();
|
||||
log.Debug("SetThermostatHeatSetpoint: " + thermostat.Number + " to " + payload + tempUnit + "(" + temp + ")");
|
||||
OmniLink.SendCommand(enuUnitCommand.SetLowSetPt, BitConverter.GetBytes(temp)[0], (ushort)thermostat.Number);
|
||||
}
|
||||
else if (command == Topic.temperature_cool_command && double.TryParse(payload, out double tempHigh))
|
||||
{
|
||||
string tempUnit = "C";
|
||||
if (OmniLink.Controller.TempFormat == enuTempFormat.Fahrenheit)
|
||||
{
|
||||
tempHigh = tempHigh.ToCelsius();
|
||||
tempUnit = "F";
|
||||
}
|
||||
|
||||
int temp = tempHigh.ToOmniTemp();
|
||||
log.Debug("SetThermostatCoolSetpoint: " + thermostat.Number + " to " + payload + tempUnit + "(" + temp + ")");
|
||||
OmniLink.SendCommand(enuUnitCommand.SetHighSetPt, BitConverter.GetBytes(temp)[0], (ushort)thermostat.Number);
|
||||
}
|
||||
else if (command == Topic.humidify_command && double.TryParse(payload, out double humidify))
|
||||
{
|
||||
// Humidity is reported where Fahrenheit temperatures 0-100 correspond to 0-100% relative humidity
|
||||
int level = humidify.ToCelsius().ToOmniTemp();
|
||||
log.Debug("SetThermostatHumidifySetpoint: " + thermostat.Number + " to " + payload + "% (" + level + ")");
|
||||
OmniLink.SendCommand(enuUnitCommand.SetHumidifySetPt, BitConverter.GetBytes(level)[0], (ushort)thermostat.Number);
|
||||
}
|
||||
else if (command == Topic.dehumidify_command && double.TryParse(payload, out double dehumidify))
|
||||
{
|
||||
int level = dehumidify.ToCelsius().ToOmniTemp();
|
||||
log.Debug("SetThermostatDehumidifySetpoint: " + thermostat.Number + " to " + payload + "% (" + level + ")");
|
||||
OmniLink.SendCommand(enuUnitCommand.SetDeHumidifySetPt, BitConverter.GetBytes(level)[0], (ushort)thermostat.Number);
|
||||
}
|
||||
else if (command == Topic.mode_command && Enum.TryParse(payload, true, out enuThermostatMode mode))
|
||||
{
|
||||
log.Debug("SetThermostatMode: " + thermostat.Number + " to " + payload);
|
||||
OmniLink.SendCommand(enuUnitCommand.Mode, BitConverter.GetBytes((int)mode)[0], (ushort)thermostat.Number);
|
||||
}
|
||||
else if (command == Topic.fan_mode_command && Enum.TryParse(payload, true, out enuThermostatFanMode fanMode))
|
||||
{
|
||||
log.Debug("SetThermostatFanMode: " + thermostat.Number + " to " + payload);
|
||||
OmniLink.SendCommand(enuUnitCommand.Fan, BitConverter.GetBytes((int)fanMode)[0], (ushort)thermostat.Number);
|
||||
}
|
||||
else if (command == Topic.hold_command && Enum.TryParse(payload, true, out enuThermostatHoldMode holdMode))
|
||||
{
|
||||
log.Debug("SetThermostatHold: " + thermostat.Number + " to " + payload);
|
||||
OmniLink.SendCommand(enuUnitCommand.Hold, BitConverter.GetBytes((int)holdMode)[0], (ushort)thermostat.Number);
|
||||
}
|
||||
}
|
||||
|
||||
private void ProcessButtonReceived(clsButton button, Topic command, string payload)
|
||||
{
|
||||
if (command == Topic.command && Enum.TryParse(payload, true, out UnitCommands cmd) && cmd == UnitCommands.ON)
|
||||
{
|
||||
log.Debug("PushButton: " + button.Number);
|
||||
OmniLink.SendCommand(enuUnitCommand.Button, 0, (ushort)button.Number);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,10 +1,4 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace OmniLinkBridge.MQTT
|
||||
namespace OmniLinkBridge.MQTT
|
||||
{
|
||||
public class OverrideZone
|
||||
{
|
||||
|
|
|
@ -1,10 +1,5 @@
|
|||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Converters;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace OmniLinkBridge.MQTT
|
||||
{
|
||||
|
|
|
@ -1,10 +1,4 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace OmniLinkBridge.MQTT
|
||||
namespace OmniLinkBridge.MQTT
|
||||
{
|
||||
public class Switch : Device
|
||||
{
|
||||
|
|
29
OmniLinkBridge/MQTT/Topic.cs
Normal file
29
OmniLinkBridge/MQTT/Topic.cs
Normal file
|
@ -0,0 +1,29 @@
|
|||
namespace OmniLinkBridge.MQTT
|
||||
{
|
||||
public enum Topic
|
||||
{
|
||||
state,
|
||||
command,
|
||||
basic_state,
|
||||
json_state,
|
||||
brightness_state,
|
||||
brightness_command,
|
||||
current_operation,
|
||||
current_temperature,
|
||||
current_humidity,
|
||||
temperature_heat_state,
|
||||
temperature_heat_command,
|
||||
temperature_cool_state,
|
||||
temperature_cool_command,
|
||||
humidify_state,
|
||||
humidify_command,
|
||||
dehumidify_state,
|
||||
dehumidify_command,
|
||||
mode_state,
|
||||
mode_command,
|
||||
fan_mode_state,
|
||||
fan_mode_command,
|
||||
hold_state,
|
||||
hold_command
|
||||
}
|
||||
}
|
|
@ -1,59 +0,0 @@
|
|||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Converters;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace OmniLinkBridge.MQTT
|
||||
{
|
||||
public class Topic
|
||||
{
|
||||
public string Value { get; private set; }
|
||||
|
||||
private Topic(string value)
|
||||
{
|
||||
Value = value;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return Value;
|
||||
}
|
||||
|
||||
public static Topic state { get { return new Topic("state"); } }
|
||||
public static Topic command { get { return new Topic("command"); } }
|
||||
|
||||
public static Topic basic_state { get { return new Topic("basic_state"); } }
|
||||
public static Topic json_state { get { return new Topic("json_state"); } }
|
||||
|
||||
public static Topic brightness_state { get { return new Topic("brightness_state"); } }
|
||||
public static Topic brightness_command { get { return new Topic("brightness_command"); } }
|
||||
|
||||
public static Topic current_operation { get { return new Topic("current_operation"); } }
|
||||
public static Topic current_temperature { get { return new Topic("current_temperature"); } }
|
||||
public static Topic current_humidity { get { return new Topic("current_humidity"); } }
|
||||
|
||||
public static Topic temperature_heat_state { get { return new Topic("temperature_heat_state"); } }
|
||||
public static Topic temperature_heat_command { get { return new Topic("temperature_heat_command"); } }
|
||||
|
||||
public static Topic temperature_cool_state { get { return new Topic("temperature_cool_state"); } }
|
||||
public static Topic temperature_cool_command { get { return new Topic("temperature_cool_command"); } }
|
||||
|
||||
public static Topic humidify_state { get { return new Topic("humidify_state"); } }
|
||||
public static Topic humidify_command { get { return new Topic("humidify_command"); } }
|
||||
|
||||
public static Topic dehumidify_state { get { return new Topic("dehumidify_state"); } }
|
||||
public static Topic dehumidify_command { get { return new Topic("dehumidify_command"); } }
|
||||
|
||||
public static Topic mode_state { get { return new Topic("mode_state"); } }
|
||||
public static Topic mode_command { get { return new Topic("mode_command"); } }
|
||||
|
||||
public static Topic fan_mode_state { get { return new Topic("fan_mode_state"); } }
|
||||
public static Topic fan_mode_command { get { return new Topic("fan_mode_command"); } }
|
||||
|
||||
public static Topic hold_state { get { return new Topic("hold_state"); } }
|
||||
public static Topic hold_command { get { return new Topic("hold_command"); } }
|
||||
}
|
||||
}
|
8
OmniLinkBridge/MQTT/UnitCommands.cs
Normal file
8
OmniLinkBridge/MQTT/UnitCommands.cs
Normal file
|
@ -0,0 +1,8 @@
|
|||
namespace OmniLinkBridge.MQTT
|
||||
{
|
||||
enum UnitCommands
|
||||
{
|
||||
OFF,
|
||||
ON
|
||||
}
|
||||
}
|
8
OmniLinkBridge/MQTT/ZoneCommands.cs
Normal file
8
OmniLinkBridge/MQTT/ZoneCommands.cs
Normal file
|
@ -0,0 +1,8 @@
|
|||
namespace OmniLinkBridge.MQTT
|
||||
{
|
||||
enum ZoneCommands
|
||||
{
|
||||
restore,
|
||||
bypass,
|
||||
}
|
||||
}
|
|
@ -8,10 +8,11 @@ using Newtonsoft.Json;
|
|||
using OmniLinkBridge.MQTT;
|
||||
using OmniLinkBridge.OmniLink;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace OmniLinkBridge.Modules
|
||||
{
|
||||
|
@ -25,7 +26,7 @@ namespace OmniLinkBridge.Modules
|
|||
private IManagedMqttClient MqttClient { get; set; }
|
||||
private bool ControllerConnected { get; set; }
|
||||
|
||||
private Regex regexTopic = new Regex(Global.mqtt_prefix + "/([A-Za-z]+)([0-9]+)/(.*)", RegexOptions.Compiled);
|
||||
private MessageProcessor MessageProcessor { get; set; }
|
||||
|
||||
private readonly AutoResetEvent trigger = new AutoResetEvent(false);
|
||||
|
||||
|
@ -38,6 +39,8 @@ namespace OmniLinkBridge.Modules
|
|||
OmniLink.OnZoneStatus += Omnilink_OnZoneStatus;
|
||||
OmniLink.OnUnitStatus += Omnilink_OnUnitStatus;
|
||||
OmniLink.OnThermostatStatus += Omnilink_OnThermostatStatus;
|
||||
|
||||
MessageProcessor = new MessageProcessor(omni);
|
||||
}
|
||||
|
||||
public void Startup()
|
||||
|
@ -89,218 +92,35 @@ namespace OmniLinkBridge.Modules
|
|||
|
||||
MqttClient.ApplicationMessageReceived += MqttClient_ApplicationMessageReceived;
|
||||
|
||||
MqttClient.SubscribeAsync(new TopicFilterBuilder().WithTopic($"{Global.mqtt_prefix}/+/{Topic.command}").Build());
|
||||
MqttClient.SubscribeAsync(new TopicFilterBuilder().WithTopic($"{Global.mqtt_prefix}/+/{Topic.brightness_command}").Build());
|
||||
MqttClient.SubscribeAsync(new TopicFilterBuilder().WithTopic($"{Global.mqtt_prefix}/+/{Topic.temperature_heat_command}").Build());
|
||||
MqttClient.SubscribeAsync(new TopicFilterBuilder().WithTopic($"{Global.mqtt_prefix}/+/{Topic.temperature_cool_command}").Build());
|
||||
MqttClient.SubscribeAsync(new TopicFilterBuilder().WithTopic($"{Global.mqtt_prefix}/+/{Topic.humidify_command}").Build());
|
||||
MqttClient.SubscribeAsync(new TopicFilterBuilder().WithTopic($"{Global.mqtt_prefix}/+/{Topic.dehumidify_command}").Build());
|
||||
MqttClient.SubscribeAsync(new TopicFilterBuilder().WithTopic($"{Global.mqtt_prefix}/+/{Topic.mode_command}").Build());
|
||||
MqttClient.SubscribeAsync(new TopicFilterBuilder().WithTopic($"{Global.mqtt_prefix}/+/{Topic.fan_mode_command}").Build());
|
||||
MqttClient.SubscribeAsync(new TopicFilterBuilder().WithTopic($"{Global.mqtt_prefix}/+/{Topic.hold_command}").Build());
|
||||
// Subscribe to notifications for these command topics
|
||||
List<Topic> toSubscribe = new List<Topic>()
|
||||
{
|
||||
Topic.command,
|
||||
Topic.brightness_command,
|
||||
Topic.temperature_heat_command,
|
||||
Topic.temperature_cool_command,
|
||||
Topic.humidify_command,
|
||||
Topic.dehumidify_command,
|
||||
Topic.mode_command,
|
||||
Topic.fan_mode_command,
|
||||
Topic.hold_command
|
||||
};
|
||||
|
||||
toSubscribe.ForEach((command) => MqttClient.SubscribeAsync(
|
||||
new TopicFilterBuilder().WithTopic($"{Global.mqtt_prefix}/+/{command.ToString()}").Build()));
|
||||
|
||||
// Wait until shutdown
|
||||
trigger.WaitOne();
|
||||
|
||||
log.Debug("Publishing controller offline");
|
||||
MqttClient.PublishAsync($"{Global.mqtt_prefix}/status", "offline", MqttQualityOfServiceLevel.AtMostOnce, true);
|
||||
PublishAsync($"{Global.mqtt_prefix}/status", "offline");
|
||||
|
||||
MqttClient.StopAsync();
|
||||
}
|
||||
|
||||
private void MqttClient_ApplicationMessageReceived(object sender, MqttApplicationMessageReceivedEventArgs e)
|
||||
{
|
||||
Match match = regexTopic.Match(e.ApplicationMessage.Topic);
|
||||
|
||||
if (!match.Success)
|
||||
return;
|
||||
|
||||
string payload = Encoding.UTF8.GetString(e.ApplicationMessage.Payload);
|
||||
|
||||
log.Debug($"Received: Type: {match.Groups[1].Value}, Id: {match.Groups[2].Value}, Command: {match.Groups[3].Value}, Value: {payload}");
|
||||
|
||||
if (match.Groups[1].Value == "area" && ushort.TryParse(match.Groups[2].Value, out ushort areaId) &&
|
||||
areaId <= OmniLink.Controller.Areas.Count)
|
||||
{
|
||||
if(areaId == 0)
|
||||
log.Debug("SetArea: 0 implies all areas will be changed");
|
||||
|
||||
ProcessAreaReceived(OmniLink.Controller.Areas[areaId], match.Groups[3].Value, payload);
|
||||
}
|
||||
if (match.Groups[1].Value == "zone" && ushort.TryParse(match.Groups[2].Value, out ushort zoneId) &&
|
||||
zoneId > 0 && zoneId <= OmniLink.Controller.Zones.Count)
|
||||
{
|
||||
ProcessZoneReceived(OmniLink.Controller.Zones[zoneId], match.Groups[3].Value, payload);
|
||||
}
|
||||
else if (match.Groups[1].Value == "unit" && ushort.TryParse(match.Groups[2].Value, out ushort unitId) &&
|
||||
unitId > 0 && unitId <= OmniLink.Controller.Units.Count)
|
||||
{
|
||||
ProcessUnitReceived(OmniLink.Controller.Units[unitId], match.Groups[3].Value, payload);
|
||||
}
|
||||
else if (match.Groups[1].Value == "thermostat" && ushort.TryParse(match.Groups[2].Value, out ushort thermostatId) &&
|
||||
thermostatId > 0 && thermostatId <= OmniLink.Controller.Thermostats.Count)
|
||||
{
|
||||
ProcessThermostatReceived(OmniLink.Controller.Thermostats[thermostatId], match.Groups[3].Value, payload);
|
||||
}
|
||||
else if (match.Groups[1].Value == "button" && ushort.TryParse(match.Groups[2].Value, out ushort buttonId) &&
|
||||
buttonId > 0 && buttonId <= OmniLink.Controller.Buttons.Count)
|
||||
{
|
||||
ProcessButtonReceived(OmniLink.Controller.Buttons[buttonId], match.Groups[3].Value, payload);
|
||||
}
|
||||
}
|
||||
|
||||
private void ProcessAreaReceived(clsArea area, string command, string payload)
|
||||
{
|
||||
if (string.Compare(command, Topic.command.ToString()) == 0)
|
||||
{
|
||||
if(string.Compare(payload, "arm_home", true) == 0)
|
||||
{
|
||||
log.Debug("SetArea: " + area.Number + " to home");
|
||||
OmniLink.Controller.SendCommand(enuUnitCommand.SecurityDay, 0, (ushort)area.Number);
|
||||
}
|
||||
else if (string.Compare(payload, "arm_away", true) == 0)
|
||||
{
|
||||
log.Debug("SetArea: " + area.Number + " to away");
|
||||
OmniLink.Controller.SendCommand(enuUnitCommand.SecurityAway, 0, (ushort)area.Number);
|
||||
}
|
||||
else if (string.Compare(payload, "arm_night", true) == 0)
|
||||
{
|
||||
log.Debug("SetArea: " + area.Number + " to night");
|
||||
OmniLink.Controller.SendCommand(enuUnitCommand.SecurityNight, 0, (ushort)area.Number);
|
||||
}
|
||||
else if (string.Compare(payload, "disarm", true) == 0)
|
||||
{
|
||||
log.Debug("SetArea: " + area.Number + " to disarm");
|
||||
OmniLink.Controller.SendCommand(enuUnitCommand.SecurityOff, 0, (ushort)area.Number);
|
||||
}
|
||||
// The below aren't supported by Home Assistant
|
||||
else if (string.Compare(payload, "arm_home_instant", true) == 0)
|
||||
{
|
||||
log.Debug("SetArea: " + area.Number + " to home instant");
|
||||
OmniLink.Controller.SendCommand(enuUnitCommand.SecurityDyi, 0, (ushort)area.Number);
|
||||
}
|
||||
else if (string.Compare(payload, "arm_night_delay", true) == 0)
|
||||
{
|
||||
log.Debug("SetArea: " + area.Number + " to night delay");
|
||||
OmniLink.Controller.SendCommand(enuUnitCommand.SecurityNtd, 0, (ushort)area.Number);
|
||||
}
|
||||
else if (string.Compare(payload, "arm_vacation", true) == 0)
|
||||
{
|
||||
log.Debug("SetArea: " + area.Number + " to vacation");
|
||||
OmniLink.Controller.SendCommand(enuUnitCommand.SecurityVac, 0, (ushort)area.Number);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void ProcessZoneReceived(clsZone zone, string command, string payload)
|
||||
{
|
||||
if (string.Compare(command, Topic.command.ToString()) == 0)
|
||||
{
|
||||
if (string.Compare(payload, "bypass", true) == 0)
|
||||
{
|
||||
log.Debug("SetZone: " + zone.Number + " to " + payload);
|
||||
OmniLink.Controller.SendCommand(enuUnitCommand.Bypass, 0, (ushort)zone.Number);
|
||||
}
|
||||
else if (string.Compare(payload, "restore", true) == 0)
|
||||
{
|
||||
log.Debug("SetZone: " + zone.Number + " to " + payload);
|
||||
OmniLink.Controller.SendCommand(enuUnitCommand.Restore, 0, (ushort)zone.Number);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void ProcessUnitReceived(clsUnit unit, string command, string payload)
|
||||
{
|
||||
if (string.Compare(command, Topic.command.ToString()) == 0 && (payload == "ON" || payload == "OFF"))
|
||||
{
|
||||
if (unit.ToState() != payload)
|
||||
{
|
||||
log.Debug("SetUnit: " + unit.Number + " to " + payload);
|
||||
|
||||
if (payload == "ON")
|
||||
OmniLink.Controller.SendCommand(enuUnitCommand.On, 0, (ushort)unit.Number);
|
||||
else
|
||||
OmniLink.Controller.SendCommand(enuUnitCommand.Off, 0, (ushort)unit.Number);
|
||||
}
|
||||
}
|
||||
else if (string.Compare(command, Topic.brightness_command.ToString()) == 0 && Int32.TryParse(payload, out int unitValue))
|
||||
{
|
||||
log.Debug("SetUnit: " + unit.Number + " to " + payload + "%");
|
||||
|
||||
OmniLink.Controller.SendCommand(enuUnitCommand.Level, BitConverter.GetBytes(unitValue)[0], (ushort)unit.Number);
|
||||
|
||||
// Force status change instead of waiting on controller to update
|
||||
// Home Assistant sends brightness immediately followed by ON,
|
||||
// which will cause light to go to 100% brightness
|
||||
unit.Status = (byte)(100 + unitValue);
|
||||
}
|
||||
}
|
||||
|
||||
private void ProcessThermostatReceived(clsThermostat thermostat, string command, string payload)
|
||||
{
|
||||
if (string.Compare(command, Topic.temperature_heat_command.ToString()) == 0 && double.TryParse(payload, out double tempLow))
|
||||
{
|
||||
string tempUnit = "C";
|
||||
if (OmniLink.Controller.TempFormat == enuTempFormat.Fahrenheit)
|
||||
{
|
||||
tempLow = tempLow.ToCelsius();
|
||||
tempUnit = "F";
|
||||
}
|
||||
|
||||
int temp = tempLow.ToOmniTemp();
|
||||
log.Debug("SetThermostatHeatSetpoint: " + thermostat.Number + " to " + payload + tempUnit + "(" + temp + ")");
|
||||
OmniLink.Controller.SendCommand(enuUnitCommand.SetLowSetPt, BitConverter.GetBytes(temp)[0], (ushort)thermostat.Number);
|
||||
}
|
||||
else if (string.Compare(command, Topic.temperature_cool_command.ToString()) == 0 && double.TryParse(payload, out double tempHigh))
|
||||
{
|
||||
string tempUnit = "C";
|
||||
if (OmniLink.Controller.TempFormat == enuTempFormat.Fahrenheit)
|
||||
{
|
||||
tempHigh = tempHigh.ToCelsius();
|
||||
tempUnit = "F";
|
||||
}
|
||||
|
||||
int temp = tempHigh.ToOmniTemp();
|
||||
log.Debug("SetThermostatCoolSetpoint: " + thermostat.Number + " to " + payload + tempUnit + "(" + temp + ")");
|
||||
OmniLink.Controller.SendCommand(enuUnitCommand.SetHighSetPt, BitConverter.GetBytes(temp)[0], (ushort)thermostat.Number);
|
||||
}
|
||||
else if (string.Compare(command, Topic.humidify_command.ToString()) == 0 && double.TryParse(payload, out double humidify))
|
||||
{
|
||||
// Humidity is reported where Fahrenheit temperatures 0-100 correspond to 0-100% relative humidity
|
||||
int level = humidify.ToCelsius().ToOmniTemp();
|
||||
log.Debug("SetThermostatHumidifySetpoint: " + thermostat.Number + " to " + payload + "% (" + level + ")");
|
||||
OmniLink.Controller.SendCommand(enuUnitCommand.SetHumidifySetPt, BitConverter.GetBytes(level)[0], (ushort)thermostat.Number);
|
||||
}
|
||||
else if (string.Compare(command, Topic.dehumidify_command.ToString()) == 0 && double.TryParse(payload, out double dehumidify))
|
||||
{
|
||||
int level = dehumidify.ToCelsius().ToOmniTemp();
|
||||
log.Debug("SetThermostatDehumidifySetpoint: " + thermostat.Number + " to " + payload + "% (" + level + ")");
|
||||
OmniLink.Controller.SendCommand(enuUnitCommand.SetDeHumidifySetPt, BitConverter.GetBytes(level)[0], (ushort)thermostat.Number);
|
||||
}
|
||||
else if (string.Compare(command, Topic.mode_command.ToString()) == 0 && Enum.TryParse(payload, true, out enuThermostatMode mode))
|
||||
{
|
||||
log.Debug("SetThermostatMode: " + thermostat.Number + " to " + payload);
|
||||
OmniLink.Controller.SendCommand(enuUnitCommand.Mode, BitConverter.GetBytes((int)mode)[0], (ushort)thermostat.Number);
|
||||
}
|
||||
else if (string.Compare(command, Topic.fan_mode_command.ToString()) == 0 && Enum.TryParse(payload, true, out enuThermostatFanMode fanMode))
|
||||
{
|
||||
log.Debug("SetThermostatFanMode: " + thermostat.Number + " to " + payload);
|
||||
OmniLink.Controller.SendCommand(enuUnitCommand.Fan, BitConverter.GetBytes((int)fanMode)[0], (ushort)thermostat.Number);
|
||||
}
|
||||
else if (string.Compare(command, Topic.hold_command.ToString()) == 0 && Enum.TryParse(payload, true, out enuThermostatHoldMode holdMode))
|
||||
{
|
||||
log.Debug("SetThermostatHold: " + thermostat.Number + " to " + payload);
|
||||
OmniLink.Controller.SendCommand(enuUnitCommand.Hold, BitConverter.GetBytes((int)holdMode)[0], (ushort)thermostat.Number);
|
||||
}
|
||||
}
|
||||
|
||||
private void ProcessButtonReceived(clsButton button, string command, string payload)
|
||||
{
|
||||
if (string.Compare(command, Topic.command.ToString()) == 0 && payload == "ON")
|
||||
{
|
||||
log.Debug("PushButton: " + button.Number);
|
||||
OmniLink.Controller.SendCommand(enuUnitCommand.Button, 0, (ushort)button.Number);
|
||||
}
|
||||
MessageProcessor.Process(e.ApplicationMessage.Topic, Encoding.UTF8.GetString(e.ApplicationMessage.Payload));
|
||||
}
|
||||
|
||||
public void Shutdown()
|
||||
|
@ -323,7 +143,7 @@ namespace OmniLinkBridge.Modules
|
|||
if (MqttClient.IsConnected)
|
||||
{
|
||||
log.Debug("Publishing controller offline");
|
||||
MqttClient.PublishAsync($"{Global.mqtt_prefix}/status", "offline", MqttQualityOfServiceLevel.AtMostOnce, true);
|
||||
PublishAsync($"{Global.mqtt_prefix}/status", "offline");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -336,7 +156,9 @@ namespace OmniLinkBridge.Modules
|
|||
PublishButtons();
|
||||
|
||||
log.Debug("Publishing controller online");
|
||||
MqttClient.PublishAsync($"{Global.mqtt_prefix}/status", "online", MqttQualityOfServiceLevel.AtMostOnce, true);
|
||||
PublishAsync($"{Global.mqtt_prefix}/status", "online");
|
||||
PublishAsync($"{Global.mqtt_prefix}/model", OmniLink.Controller.GetModelText());
|
||||
PublishAsync($"{Global.mqtt_prefix}/version", OmniLink.Controller.GetVersionText());
|
||||
}
|
||||
|
||||
private void PublishAreas()
|
||||
|
@ -351,38 +173,38 @@ namespace OmniLinkBridge.Modules
|
|||
// (configured for 1 area). To workaround ignore default properties for the first area.
|
||||
if (i > 1 && area.DefaultProperties == true)
|
||||
{
|
||||
MqttClient.PublishAsync($"{Global.mqtt_discovery_prefix}/alarm_control_panel/{Global.mqtt_prefix}/area{i.ToString()}/config", null, MqttQualityOfServiceLevel.AtMostOnce, true);
|
||||
MqttClient.PublishAsync($"{Global.mqtt_discovery_prefix}/binary_sensor/{Global.mqtt_prefix}/area{i.ToString()}burglary/config", null, MqttQualityOfServiceLevel.AtMostOnce, true);
|
||||
MqttClient.PublishAsync($"{Global.mqtt_discovery_prefix}/binary_sensor/{Global.mqtt_prefix}/area{i.ToString()}fire/config", null, MqttQualityOfServiceLevel.AtMostOnce, true);
|
||||
MqttClient.PublishAsync($"{Global.mqtt_discovery_prefix}/binary_sensor/{Global.mqtt_prefix}/area{i.ToString()}gas/config", null, MqttQualityOfServiceLevel.AtMostOnce, true);
|
||||
MqttClient.PublishAsync($"{Global.mqtt_discovery_prefix}/binary_sensor/{Global.mqtt_prefix}/area{i.ToString()}aux/config", null, MqttQualityOfServiceLevel.AtMostOnce, true);
|
||||
MqttClient.PublishAsync($"{Global.mqtt_discovery_prefix}/binary_sensor/{Global.mqtt_prefix}/area{i.ToString()}freeze/config", null, MqttQualityOfServiceLevel.AtMostOnce, true);
|
||||
MqttClient.PublishAsync($"{Global.mqtt_discovery_prefix}/binary_sensor/{Global.mqtt_prefix}/area{i.ToString()}water/config", null, MqttQualityOfServiceLevel.AtMostOnce, true);
|
||||
MqttClient.PublishAsync($"{Global.mqtt_discovery_prefix}/binary_sensor/{Global.mqtt_prefix}/area{i.ToString()}duress/config", null, MqttQualityOfServiceLevel.AtMostOnce, true);
|
||||
MqttClient.PublishAsync($"{Global.mqtt_discovery_prefix}/binary_sensor/{Global.mqtt_prefix}/area{i.ToString()}temp/config", null, MqttQualityOfServiceLevel.AtMostOnce, true);
|
||||
PublishAsync($"{Global.mqtt_discovery_prefix}/alarm_control_panel/{Global.mqtt_prefix}/area{i.ToString()}/config", null);
|
||||
PublishAsync($"{Global.mqtt_discovery_prefix}/binary_sensor/{Global.mqtt_prefix}/area{i.ToString()}burglary/config", null);
|
||||
PublishAsync($"{Global.mqtt_discovery_prefix}/binary_sensor/{Global.mqtt_prefix}/area{i.ToString()}fire/config", null);
|
||||
PublishAsync($"{Global.mqtt_discovery_prefix}/binary_sensor/{Global.mqtt_prefix}/area{i.ToString()}gas/config", null);
|
||||
PublishAsync($"{Global.mqtt_discovery_prefix}/binary_sensor/{Global.mqtt_prefix}/area{i.ToString()}aux/config", null);
|
||||
PublishAsync($"{Global.mqtt_discovery_prefix}/binary_sensor/{Global.mqtt_prefix}/area{i.ToString()}freeze/config", null);
|
||||
PublishAsync($"{Global.mqtt_discovery_prefix}/binary_sensor/{Global.mqtt_prefix}/area{i.ToString()}water/config", null);
|
||||
PublishAsync($"{Global.mqtt_discovery_prefix}/binary_sensor/{Global.mqtt_prefix}/area{i.ToString()}duress/config", null);
|
||||
PublishAsync($"{Global.mqtt_discovery_prefix}/binary_sensor/{Global.mqtt_prefix}/area{i.ToString()}temp/config", null);
|
||||
continue;
|
||||
}
|
||||
|
||||
PublishAreaState(area);
|
||||
|
||||
MqttClient.PublishAsync($"{Global.mqtt_discovery_prefix}/alarm_control_panel/{Global.mqtt_prefix}/area{i.ToString()}/config",
|
||||
JsonConvert.SerializeObject(area.ToConfig()), MqttQualityOfServiceLevel.AtMostOnce, true);
|
||||
MqttClient.PublishAsync($"{Global.mqtt_discovery_prefix}/binary_sensor/{Global.mqtt_prefix}/area{i.ToString()}burglary/config",
|
||||
JsonConvert.SerializeObject(area.ToConfigBurglary()), MqttQualityOfServiceLevel.AtMostOnce, true);
|
||||
MqttClient.PublishAsync($"{Global.mqtt_discovery_prefix}/binary_sensor/{Global.mqtt_prefix}/area{i.ToString()}fire/config",
|
||||
JsonConvert.SerializeObject(area.ToConfigFire()), MqttQualityOfServiceLevel.AtMostOnce, true);
|
||||
MqttClient.PublishAsync($"{Global.mqtt_discovery_prefix}/binary_sensor/{Global.mqtt_prefix}/area{i.ToString()}gas/config",
|
||||
JsonConvert.SerializeObject(area.ToConfigGas()), MqttQualityOfServiceLevel.AtMostOnce, true);
|
||||
MqttClient.PublishAsync($"{Global.mqtt_discovery_prefix}/binary_sensor/{Global.mqtt_prefix}/area{i.ToString()}aux/config",
|
||||
JsonConvert.SerializeObject(area.ToConfigAux()), MqttQualityOfServiceLevel.AtMostOnce, true);
|
||||
MqttClient.PublishAsync($"{Global.mqtt_discovery_prefix}/binary_sensor/{Global.mqtt_prefix}/area{i.ToString()}freeze/config",
|
||||
JsonConvert.SerializeObject(area.ToConfigFreeze()), MqttQualityOfServiceLevel.AtMostOnce, true);
|
||||
MqttClient.PublishAsync($"{Global.mqtt_discovery_prefix}/binary_sensor/{Global.mqtt_prefix}/area{i.ToString()}water/config",
|
||||
JsonConvert.SerializeObject(area.ToConfigWater()), MqttQualityOfServiceLevel.AtMostOnce, true);
|
||||
MqttClient.PublishAsync($"{Global.mqtt_discovery_prefix}/binary_sensor/{Global.mqtt_prefix}/area{i.ToString()}duress/config",
|
||||
JsonConvert.SerializeObject(area.ToConfigDuress()), MqttQualityOfServiceLevel.AtMostOnce, true);
|
||||
MqttClient.PublishAsync($"{Global.mqtt_discovery_prefix}/binary_sensor/{Global.mqtt_prefix}/area{i.ToString()}temp/config",
|
||||
JsonConvert.SerializeObject(area.ToConfigTemp()), MqttQualityOfServiceLevel.AtMostOnce, true);
|
||||
PublishAsync($"{Global.mqtt_discovery_prefix}/alarm_control_panel/{Global.mqtt_prefix}/area{i.ToString()}/config",
|
||||
JsonConvert.SerializeObject(area.ToConfig()));
|
||||
PublishAsync($"{Global.mqtt_discovery_prefix}/binary_sensor/{Global.mqtt_prefix}/area{i.ToString()}burglary/config",
|
||||
JsonConvert.SerializeObject(area.ToConfigBurglary()));
|
||||
PublishAsync($"{Global.mqtt_discovery_prefix}/binary_sensor/{Global.mqtt_prefix}/area{i.ToString()}fire/config",
|
||||
JsonConvert.SerializeObject(area.ToConfigFire()));
|
||||
PublishAsync($"{Global.mqtt_discovery_prefix}/binary_sensor/{Global.mqtt_prefix}/area{i.ToString()}gas/config",
|
||||
JsonConvert.SerializeObject(area.ToConfigGas()));
|
||||
PublishAsync($"{Global.mqtt_discovery_prefix}/binary_sensor/{Global.mqtt_prefix}/area{i.ToString()}aux/config",
|
||||
JsonConvert.SerializeObject(area.ToConfigAux()));
|
||||
PublishAsync($"{Global.mqtt_discovery_prefix}/binary_sensor/{Global.mqtt_prefix}/area{i.ToString()}freeze/config",
|
||||
JsonConvert.SerializeObject(area.ToConfigFreeze()));
|
||||
PublishAsync($"{Global.mqtt_discovery_prefix}/binary_sensor/{Global.mqtt_prefix}/area{i.ToString()}water/config",
|
||||
JsonConvert.SerializeObject(area.ToConfigWater()));
|
||||
PublishAsync($"{Global.mqtt_discovery_prefix}/binary_sensor/{Global.mqtt_prefix}/area{i.ToString()}duress/config",
|
||||
JsonConvert.SerializeObject(area.ToConfigDuress()));
|
||||
PublishAsync($"{Global.mqtt_discovery_prefix}/binary_sensor/{Global.mqtt_prefix}/area{i.ToString()}temp/config",
|
||||
JsonConvert.SerializeObject(area.ToConfigTemp()));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -396,26 +218,26 @@ namespace OmniLinkBridge.Modules
|
|||
|
||||
if (zone.DefaultProperties == true || Global.mqtt_discovery_ignore_zones.Contains(zone.Number))
|
||||
{
|
||||
MqttClient.PublishAsync($"{Global.mqtt_discovery_prefix}/binary_sensor/{Global.mqtt_prefix}/zone{i.ToString()}/config", null, MqttQualityOfServiceLevel.AtMostOnce, true);
|
||||
MqttClient.PublishAsync($"{Global.mqtt_discovery_prefix}/sensor/{Global.mqtt_prefix}/zone{i.ToString()}/config", null, MqttQualityOfServiceLevel.AtMostOnce, true);
|
||||
MqttClient.PublishAsync($"{Global.mqtt_discovery_prefix}/sensor/{Global.mqtt_prefix}/zone{i.ToString()}temp/config", null, MqttQualityOfServiceLevel.AtMostOnce, true);
|
||||
MqttClient.PublishAsync($"{Global.mqtt_discovery_prefix}/sensor/{Global.mqtt_prefix}/zone{i.ToString()}humidity/config", null, MqttQualityOfServiceLevel.AtMostOnce, true);
|
||||
PublishAsync($"{Global.mqtt_discovery_prefix}/binary_sensor/{Global.mqtt_prefix}/zone{i.ToString()}/config", null);
|
||||
PublishAsync($"{Global.mqtt_discovery_prefix}/sensor/{Global.mqtt_prefix}/zone{i.ToString()}/config", null);
|
||||
PublishAsync($"{Global.mqtt_discovery_prefix}/sensor/{Global.mqtt_prefix}/zone{i.ToString()}temp/config", null);
|
||||
PublishAsync($"{Global.mqtt_discovery_prefix}/sensor/{Global.mqtt_prefix}/zone{i.ToString()}humidity/config", null);
|
||||
continue;
|
||||
}
|
||||
|
||||
PublishZoneState(zone);
|
||||
|
||||
MqttClient.PublishAsync($"{Global.mqtt_discovery_prefix}/binary_sensor/{Global.mqtt_prefix}/zone{i.ToString()}/config",
|
||||
JsonConvert.SerializeObject(zone.ToConfig()), MqttQualityOfServiceLevel.AtMostOnce, true);
|
||||
MqttClient.PublishAsync($"{Global.mqtt_discovery_prefix}/sensor/{Global.mqtt_prefix}/zone{i.ToString()}/config",
|
||||
JsonConvert.SerializeObject(zone.ToConfigSensor()), MqttQualityOfServiceLevel.AtMostOnce, true);
|
||||
PublishAsync($"{Global.mqtt_discovery_prefix}/binary_sensor/{Global.mqtt_prefix}/zone{i.ToString()}/config",
|
||||
JsonConvert.SerializeObject(zone.ToConfig()));
|
||||
PublishAsync($"{Global.mqtt_discovery_prefix}/sensor/{Global.mqtt_prefix}/zone{i.ToString()}/config",
|
||||
JsonConvert.SerializeObject(zone.ToConfigSensor()));
|
||||
|
||||
if (zone.IsTemperatureZone())
|
||||
MqttClient.PublishAsync($"{Global.mqtt_discovery_prefix}/sensor/{Global.mqtt_prefix}/zone{i.ToString()}temp/config",
|
||||
JsonConvert.SerializeObject(zone.ToConfigTemp(OmniLink.Controller.TempFormat)), MqttQualityOfServiceLevel.AtMostOnce, true);
|
||||
PublishAsync($"{Global.mqtt_discovery_prefix}/sensor/{Global.mqtt_prefix}/zone{i.ToString()}temp/config",
|
||||
JsonConvert.SerializeObject(zone.ToConfigTemp(OmniLink.Controller.TempFormat)));
|
||||
else if (zone.IsHumidityZone())
|
||||
MqttClient.PublishAsync($"{Global.mqtt_discovery_prefix}/sensor/{Global.mqtt_prefix}/zone{i.ToString()}humidity/config",
|
||||
JsonConvert.SerializeObject(zone.ToConfigHumidity()), MqttQualityOfServiceLevel.AtMostOnce, true);
|
||||
PublishAsync($"{Global.mqtt_discovery_prefix}/sensor/{Global.mqtt_prefix}/zone{i.ToString()}humidity/config",
|
||||
JsonConvert.SerializeObject(zone.ToConfigHumidity()));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -430,18 +252,18 @@ namespace OmniLinkBridge.Modules
|
|||
if (unit.DefaultProperties == true || Global.mqtt_discovery_ignore_units.Contains(unit.Number))
|
||||
{
|
||||
string type = i < 385 ? "light" : "switch";
|
||||
MqttClient.PublishAsync($"{Global.mqtt_discovery_prefix}/{type}/{Global.mqtt_prefix}/unit{i.ToString()}/config", null, MqttQualityOfServiceLevel.AtMostOnce, true);
|
||||
PublishAsync($"{Global.mqtt_discovery_prefix}/{type}/{Global.mqtt_prefix}/unit{i.ToString()}/config", null);
|
||||
continue;
|
||||
}
|
||||
|
||||
PublishUnitState(unit);
|
||||
|
||||
if(i < 385)
|
||||
MqttClient.PublishAsync($"{Global.mqtt_discovery_prefix}/light/{Global.mqtt_prefix}/unit{i.ToString()}/config",
|
||||
JsonConvert.SerializeObject(unit.ToConfig()), MqttQualityOfServiceLevel.AtMostOnce, true);
|
||||
PublishAsync($"{Global.mqtt_discovery_prefix}/light/{Global.mqtt_prefix}/unit{i.ToString()}/config",
|
||||
JsonConvert.SerializeObject(unit.ToConfig()));
|
||||
else
|
||||
MqttClient.PublishAsync($"{Global.mqtt_discovery_prefix}/switch/{Global.mqtt_prefix}/unit{i.ToString()}/config",
|
||||
JsonConvert.SerializeObject(unit.ToConfigSwitch()), MqttQualityOfServiceLevel.AtMostOnce, true);
|
||||
PublishAsync($"{Global.mqtt_discovery_prefix}/switch/{Global.mqtt_prefix}/unit{i.ToString()}/config",
|
||||
JsonConvert.SerializeObject(unit.ToConfigSwitch()));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -455,20 +277,20 @@ namespace OmniLinkBridge.Modules
|
|||
|
||||
if (thermostat.DefaultProperties == true)
|
||||
{
|
||||
MqttClient.PublishAsync($"{Global.mqtt_discovery_prefix}/climate/{Global.mqtt_prefix}/thermostat{i.ToString()}/config", null, MqttQualityOfServiceLevel.AtMostOnce, true);
|
||||
MqttClient.PublishAsync($"{Global.mqtt_discovery_prefix}/sensor/{Global.mqtt_prefix}/thermostat{i.ToString()}temp/config", null, MqttQualityOfServiceLevel.AtMostOnce, true);
|
||||
MqttClient.PublishAsync($"{Global.mqtt_discovery_prefix}/sensor/{Global.mqtt_prefix}/thermostat{i.ToString()}humidity/config", null, MqttQualityOfServiceLevel.AtMostOnce, true);
|
||||
PublishAsync($"{Global.mqtt_discovery_prefix}/climate/{Global.mqtt_prefix}/thermostat{i.ToString()}/config", null);
|
||||
PublishAsync($"{Global.mqtt_discovery_prefix}/sensor/{Global.mqtt_prefix}/thermostat{i.ToString()}temp/config", null);
|
||||
PublishAsync($"{Global.mqtt_discovery_prefix}/sensor/{Global.mqtt_prefix}/thermostat{i.ToString()}humidity/config", null);
|
||||
continue;
|
||||
}
|
||||
|
||||
PublishThermostatState(thermostat);
|
||||
|
||||
MqttClient.PublishAsync($"{Global.mqtt_discovery_prefix}/climate/{Global.mqtt_prefix}/thermostat{i.ToString()}/config",
|
||||
JsonConvert.SerializeObject(thermostat.ToConfig(OmniLink.Controller.TempFormat)), MqttQualityOfServiceLevel.AtMostOnce, true);
|
||||
MqttClient.PublishAsync($"{Global.mqtt_discovery_prefix}/sensor/{Global.mqtt_prefix}/thermostat{i.ToString()}temp/config",
|
||||
JsonConvert.SerializeObject(thermostat.ToConfigTemp(OmniLink.Controller.TempFormat)), MqttQualityOfServiceLevel.AtMostOnce, true);
|
||||
MqttClient.PublishAsync($"{Global.mqtt_discovery_prefix}/sensor/{Global.mqtt_prefix}/thermostat{i.ToString()}humidity/config",
|
||||
JsonConvert.SerializeObject(thermostat.ToConfigHumidity()), MqttQualityOfServiceLevel.AtMostOnce, true);
|
||||
PublishAsync($"{Global.mqtt_discovery_prefix}/climate/{Global.mqtt_prefix}/thermostat{i.ToString()}/config",
|
||||
JsonConvert.SerializeObject(thermostat.ToConfig(OmniLink.Controller.TempFormat)));
|
||||
PublishAsync($"{Global.mqtt_discovery_prefix}/sensor/{Global.mqtt_prefix}/thermostat{i.ToString()}temp/config",
|
||||
JsonConvert.SerializeObject(thermostat.ToConfigTemp(OmniLink.Controller.TempFormat)));
|
||||
PublishAsync($"{Global.mqtt_discovery_prefix}/sensor/{Global.mqtt_prefix}/thermostat{i.ToString()}humidity/config",
|
||||
JsonConvert.SerializeObject(thermostat.ToConfigHumidity()));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -482,15 +304,15 @@ namespace OmniLinkBridge.Modules
|
|||
|
||||
if (button.DefaultProperties == true)
|
||||
{
|
||||
MqttClient.PublishAsync($"{Global.mqtt_discovery_prefix}/switch/{Global.mqtt_prefix}/button{i.ToString()}/config", null, MqttQualityOfServiceLevel.AtMostOnce, true);
|
||||
PublishAsync($"{Global.mqtt_discovery_prefix}/switch/{Global.mqtt_prefix}/button{i.ToString()}/config", null);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Buttons are always off
|
||||
MqttClient.PublishAsync(button.ToTopic(Topic.state), "OFF", MqttQualityOfServiceLevel.AtMostOnce, true);
|
||||
PublishAsync(button.ToTopic(Topic.state), "OFF");
|
||||
|
||||
MqttClient.PublishAsync($"{Global.mqtt_discovery_prefix}/switch/{Global.mqtt_prefix}/button{i.ToString()}/config",
|
||||
JsonConvert.SerializeObject(button.ToConfig()), MqttQualityOfServiceLevel.AtMostOnce, true);
|
||||
PublishAsync($"{Global.mqtt_discovery_prefix}/switch/{Global.mqtt_prefix}/button{i.ToString()}/config",
|
||||
JsonConvert.SerializeObject(button.ToConfig()));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -508,7 +330,8 @@ namespace OmniLinkBridge.Modules
|
|||
clsZone zone = OmniLink.Controller.Zones[i];
|
||||
|
||||
if (zone.DefaultProperties == false && zone.Area == e.Area.Number)
|
||||
OmniLink.Controller.Connection.Send(new clsOL2MsgRequestExtendedStatus(OmniLink.Controller.Connection, enuObjectType.Zone, i, i), HandleRequestZoneStatus);
|
||||
OmniLink.Controller.Connection.Send(new clsOL2MsgRequestExtendedStatus(
|
||||
OmniLink.Controller.Connection, enuObjectType.Zone, i, i), HandleRequestZoneStatus);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -523,7 +346,7 @@ namespace OmniLinkBridge.Modules
|
|||
{
|
||||
clsZone zone = OmniLink.Controller.Zones[MSG.ObjectNumber(i)];
|
||||
zone.CopyExtendedStatus(MSG, i);
|
||||
MqttClient.PublishAsync(zone.ToTopic(Topic.state), zone.ToState(), MqttQualityOfServiceLevel.AtMostOnce, true);
|
||||
PublishAsync(zone.ToTopic(Topic.state), zone.ToState());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -556,42 +379,47 @@ namespace OmniLinkBridge.Modules
|
|||
|
||||
private void PublishAreaState(clsArea area)
|
||||
{
|
||||
MqttClient.PublishAsync(area.ToTopic(Topic.state), area.ToState(), MqttQualityOfServiceLevel.AtMostOnce, true);
|
||||
MqttClient.PublishAsync(area.ToTopic(Topic.basic_state), area.ToBasicState(), MqttQualityOfServiceLevel.AtMostOnce, true);
|
||||
MqttClient.PublishAsync(area.ToTopic(Topic.json_state), area.ToJsonState(), MqttQualityOfServiceLevel.AtMostOnce, true);
|
||||
PublishAsync(area.ToTopic(Topic.state), area.ToState());
|
||||
PublishAsync(area.ToTopic(Topic.basic_state), area.ToBasicState());
|
||||
PublishAsync(area.ToTopic(Topic.json_state), area.ToJsonState());
|
||||
}
|
||||
|
||||
private void PublishZoneState(clsZone zone)
|
||||
{
|
||||
MqttClient.PublishAsync(zone.ToTopic(Topic.state), zone.ToState(), MqttQualityOfServiceLevel.AtMostOnce, true);
|
||||
MqttClient.PublishAsync(zone.ToTopic(Topic.basic_state), zone.ToBasicState(), MqttQualityOfServiceLevel.AtMostOnce, true);
|
||||
PublishAsync(zone.ToTopic(Topic.state), zone.ToState());
|
||||
PublishAsync(zone.ToTopic(Topic.basic_state), zone.ToBasicState());
|
||||
|
||||
if(zone.IsTemperatureZone())
|
||||
MqttClient.PublishAsync(zone.ToTopic(Topic.current_temperature), zone.TempText(), MqttQualityOfServiceLevel.AtMostOnce, true);
|
||||
PublishAsync(zone.ToTopic(Topic.current_temperature), zone.TempText());
|
||||
else if (zone.IsHumidityZone())
|
||||
MqttClient.PublishAsync(zone.ToTopic(Topic.current_humidity), zone.TempText(), MqttQualityOfServiceLevel.AtMostOnce, true);
|
||||
PublishAsync(zone.ToTopic(Topic.current_humidity), zone.TempText());
|
||||
}
|
||||
|
||||
private void PublishUnitState(clsUnit unit)
|
||||
{
|
||||
MqttClient.PublishAsync(unit.ToTopic(Topic.state), unit.ToState(), MqttQualityOfServiceLevel.AtMostOnce, true);
|
||||
PublishAsync(unit.ToTopic(Topic.state), unit.ToState());
|
||||
|
||||
if(unit.Number < 385)
|
||||
MqttClient.PublishAsync(unit.ToTopic(Topic.brightness_state), unit.ToBrightnessState().ToString(), MqttQualityOfServiceLevel.AtMostOnce, true);
|
||||
PublishAsync(unit.ToTopic(Topic.brightness_state), unit.ToBrightnessState().ToString());
|
||||
}
|
||||
|
||||
private void PublishThermostatState(clsThermostat thermostat)
|
||||
{
|
||||
MqttClient.PublishAsync(thermostat.ToTopic(Topic.current_operation), thermostat.ToOperationState(), MqttQualityOfServiceLevel.AtMostOnce, true);
|
||||
MqttClient.PublishAsync(thermostat.ToTopic(Topic.current_temperature), thermostat.TempText(), MqttQualityOfServiceLevel.AtMostOnce, true);
|
||||
MqttClient.PublishAsync(thermostat.ToTopic(Topic.current_humidity), thermostat.HumidityText(), MqttQualityOfServiceLevel.AtMostOnce, true);
|
||||
MqttClient.PublishAsync(thermostat.ToTopic(Topic.temperature_heat_state), thermostat.HeatSetpointText(), MqttQualityOfServiceLevel.AtMostOnce, true);
|
||||
MqttClient.PublishAsync(thermostat.ToTopic(Topic.temperature_cool_state), thermostat.CoolSetpointText(), MqttQualityOfServiceLevel.AtMostOnce, true);
|
||||
MqttClient.PublishAsync(thermostat.ToTopic(Topic.humidify_state), thermostat.HumidifySetpointText(), MqttQualityOfServiceLevel.AtMostOnce, true);
|
||||
MqttClient.PublishAsync(thermostat.ToTopic(Topic.dehumidify_state), thermostat.DehumidifySetpointText(), MqttQualityOfServiceLevel.AtMostOnce, true);
|
||||
MqttClient.PublishAsync(thermostat.ToTopic(Topic.mode_state), thermostat.ModeText().ToLower(), MqttQualityOfServiceLevel.AtMostOnce, true);
|
||||
MqttClient.PublishAsync(thermostat.ToTopic(Topic.fan_mode_state), thermostat.FanModeText().ToLower(), MqttQualityOfServiceLevel.AtMostOnce, true);
|
||||
MqttClient.PublishAsync(thermostat.ToTopic(Topic.hold_state), thermostat.HoldStatusText().ToLower(), MqttQualityOfServiceLevel.AtMostOnce, true);
|
||||
PublishAsync(thermostat.ToTopic(Topic.current_operation), thermostat.ToOperationState());
|
||||
PublishAsync(thermostat.ToTopic(Topic.current_temperature), thermostat.TempText());
|
||||
PublishAsync(thermostat.ToTopic(Topic.current_humidity), thermostat.HumidityText());
|
||||
PublishAsync(thermostat.ToTopic(Topic.temperature_heat_state), thermostat.HeatSetpointText());
|
||||
PublishAsync(thermostat.ToTopic(Topic.temperature_cool_state), thermostat.CoolSetpointText());
|
||||
PublishAsync(thermostat.ToTopic(Topic.humidify_state), thermostat.HumidifySetpointText());
|
||||
PublishAsync(thermostat.ToTopic(Topic.dehumidify_state), thermostat.DehumidifySetpointText());
|
||||
PublishAsync(thermostat.ToTopic(Topic.mode_state), thermostat.ModeText().ToLower());
|
||||
PublishAsync(thermostat.ToTopic(Topic.fan_mode_state), thermostat.FanModeText().ToLower());
|
||||
PublishAsync(thermostat.ToTopic(Topic.hold_state), thermostat.HoldStatusText().ToLower());
|
||||
}
|
||||
|
||||
private Task PublishAsync(string topic, string payload)
|
||||
{
|
||||
return MqttClient.PublishAsync(topic, payload, MqttQualityOfServiceLevel.AtMostOnce, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,7 +10,7 @@ using System.Threading.Tasks;
|
|||
|
||||
namespace OmniLinkBridge.Modules
|
||||
{
|
||||
public class OmniLinkII : IModule
|
||||
public class OmniLinkII : IModule, IOmniLinkII
|
||||
{
|
||||
private static ILog log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||
|
||||
|
@ -73,6 +73,11 @@ namespace OmniLinkBridge.Modules
|
|||
trigger.Set();
|
||||
}
|
||||
|
||||
public bool SendCommand(enuUnitCommand Cmd, byte Par, ushort Pr2)
|
||||
{
|
||||
return Controller.SendCommand(Cmd, Par, Pr2);
|
||||
}
|
||||
|
||||
#region Connection
|
||||
private void Connect()
|
||||
{
|
||||
|
|
11
OmniLinkBridge/OmniLink/IOmniLinkII.cs
Normal file
11
OmniLinkBridge/OmniLink/IOmniLinkII.cs
Normal file
|
@ -0,0 +1,11 @@
|
|||
using HAI_Shared;
|
||||
|
||||
namespace OmniLinkBridge.OmniLink
|
||||
{
|
||||
public interface IOmniLinkII
|
||||
{
|
||||
clsHAC Controller { get; }
|
||||
|
||||
bool SendCommand(enuUnitCommand Cmd, byte Par, ushort Pr2);
|
||||
}
|
||||
}
|
|
@ -77,22 +77,28 @@
|
|||
<Compile Include="CoreServer.cs" />
|
||||
<Compile Include="Modules\TimeSyncModule.cs" />
|
||||
<Compile Include="MQTT\Alarm.cs" />
|
||||
<Compile Include="MQTT\AreaCommands.cs" />
|
||||
<Compile Include="MQTT\AreaState.cs" />
|
||||
<Compile Include="MQTT\BinarySensor.cs" />
|
||||
<Compile Include="MQTT\CommandTypes.cs" />
|
||||
<Compile Include="MQTT\Device.cs" />
|
||||
<Compile Include="MQTT\Climate.cs" />
|
||||
<Compile Include="MQTT\DeviceRegistry.cs" />
|
||||
<Compile Include="MQTT\MessageProcessor.cs" />
|
||||
<Compile Include="MQTT\OverrideZone.cs" />
|
||||
<Compile Include="MQTT\Switch.cs" />
|
||||
<Compile Include="MQTT\Light.cs" />
|
||||
<Compile Include="MQTT\MappingExtensions.cs" />
|
||||
<Compile Include="MQTT\Sensor.cs" />
|
||||
<Compile Include="MQTT\Topics.cs" />
|
||||
<Compile Include="MQTT\Topic.cs" />
|
||||
<Compile Include="MQTT\UnitCommands.cs" />
|
||||
<Compile Include="MQTT\ZoneCommands.cs" />
|
||||
<Compile Include="Notifications\EmailNotification.cs" />
|
||||
<Compile Include="Notifications\INotification.cs" />
|
||||
<Compile Include="Notifications\Notification.cs" />
|
||||
<Compile Include="Notifications\NotificationPriority.cs" />
|
||||
<Compile Include="Notifications\PushoverNotification.cs" />
|
||||
<Compile Include="OmniLink\IOmniLinkII.cs" />
|
||||
<Compile Include="OmniLink\UnitStatusEventArgs.cs" />
|
||||
<Compile Include="OmniLink\ThermostatStatusEventArgs.cs" />
|
||||
<Compile Include="OmniLink\MessageStatusEventArgs.cs" />
|
||||
|
|
159
OmniLinkBridgeTest/MQTTTest.cs
Normal file
159
OmniLinkBridgeTest/MQTTTest.cs
Normal file
|
@ -0,0 +1,159 @@
|
|||
using System;
|
||||
using System.Text;
|
||||
using System.Collections.Generic;
|
||||
using HAI_Shared;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using OmniLinkBridge.MQTT;
|
||||
using OmniLinkBridgeTest.Mock;
|
||||
|
||||
namespace OmniLinkBridgeTest
|
||||
{
|
||||
[TestClass]
|
||||
public class MQTTTest
|
||||
{
|
||||
MockOmniLinkII omniLink;
|
||||
MessageProcessor messageProcessor;
|
||||
|
||||
[TestInitialize]
|
||||
public void Initialize()
|
||||
{
|
||||
omniLink = new MockOmniLinkII();
|
||||
messageProcessor = new MessageProcessor(omniLink);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void AreaCommandInvalid()
|
||||
{
|
||||
SendCommandEventArgs actual = null;
|
||||
omniLink.OnSendCommand += (sender, e) => { actual = e; };
|
||||
|
||||
// Invalid command
|
||||
messageProcessor.Process($"omnilink/area1/command", "disarmed");
|
||||
Assert.IsNull(actual);
|
||||
|
||||
// Out of range
|
||||
messageProcessor.Process($"omnilink/area9/command", "disarm");
|
||||
Assert.IsNull(actual);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void AreaCommand()
|
||||
{
|
||||
void check(ushort id, string payload, enuUnitCommand command)
|
||||
{
|
||||
SendCommandEventArgs actual = null;
|
||||
omniLink.OnSendCommand += (sender, e) => { actual = e; };
|
||||
messageProcessor.Process($"omnilink/area{id}/command", payload);
|
||||
SendCommandEventArgs expected = new SendCommandEventArgs()
|
||||
{
|
||||
Cmd = command,
|
||||
Par = 0,
|
||||
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);
|
||||
|
||||
// Last area with case check
|
||||
check(8, "DISARM", enuUnitCommand.SecurityOff);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ZoneCommand()
|
||||
{
|
||||
void check(ushort id, string payload, enuUnitCommand command)
|
||||
{
|
||||
SendCommandEventArgs actual = null;
|
||||
omniLink.OnSendCommand += (sender, e) => { actual = e; };
|
||||
messageProcessor.Process($"omnilink/zone{id}/command", payload);
|
||||
SendCommandEventArgs expected = new SendCommandEventArgs()
|
||||
{
|
||||
Cmd = command,
|
||||
Par = 0,
|
||||
Pr2 = id
|
||||
};
|
||||
Assert.AreEqual(expected, actual);
|
||||
}
|
||||
|
||||
check(1, "bypass", enuUnitCommand.Bypass);
|
||||
check(1, "restore", enuUnitCommand.Restore);
|
||||
|
||||
check(2, "BYPASS", enuUnitCommand.Bypass);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void UnitCommand()
|
||||
{
|
||||
void check(ushort id, string payload, enuUnitCommand command)
|
||||
{
|
||||
SendCommandEventArgs actual = null;
|
||||
omniLink.OnSendCommand += (sender, e) => { actual = e; };
|
||||
messageProcessor.Process($"omnilink/unit{id}/command", payload);
|
||||
SendCommandEventArgs expected = new SendCommandEventArgs()
|
||||
{
|
||||
Cmd = command,
|
||||
Par = 0,
|
||||
Pr2 = id
|
||||
};
|
||||
Assert.AreEqual(expected, actual);
|
||||
}
|
||||
|
||||
check(1, "ON", enuUnitCommand.On);
|
||||
omniLink.Controller.Units[1].Status = 1;
|
||||
check(1, "OFF", enuUnitCommand.Off);
|
||||
|
||||
check(2, "on", enuUnitCommand.On);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void UnitLevelCommand()
|
||||
{
|
||||
void check(ushort id, string payload, enuUnitCommand command, int level)
|
||||
{
|
||||
SendCommandEventArgs actual = null;
|
||||
omniLink.OnSendCommand += (sender, e) => { actual = e; };
|
||||
messageProcessor.Process($"omnilink/unit{id}/brightness_command", payload);
|
||||
SendCommandEventArgs expected = new SendCommandEventArgs()
|
||||
{
|
||||
Cmd = command,
|
||||
Par = (byte)level,
|
||||
Pr2 = id
|
||||
};
|
||||
Assert.AreEqual(expected, actual);
|
||||
}
|
||||
|
||||
check(1, "50", enuUnitCommand.Level, 50);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ButtonCommand()
|
||||
{
|
||||
void check(ushort id, string payload, enuUnitCommand command)
|
||||
{
|
||||
SendCommandEventArgs actual = null;
|
||||
omniLink.OnSendCommand += (sender, e) => { actual = e; };
|
||||
messageProcessor.Process($"omnilink/button{id}/command", payload);
|
||||
SendCommandEventArgs expected = new SendCommandEventArgs()
|
||||
{
|
||||
Cmd = command,
|
||||
Par = 0,
|
||||
Pr2 = id
|
||||
};
|
||||
Assert.AreEqual(expected, actual);
|
||||
}
|
||||
|
||||
check(1, "ON", enuUnitCommand.Button);
|
||||
check(1, "on", enuUnitCommand.Button);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
30
OmniLinkBridgeTest/Mock/MockOmniLinkII.cs
Normal file
30
OmniLinkBridgeTest/Mock/MockOmniLinkII.cs
Normal file
|
@ -0,0 +1,30 @@
|
|||
using HAI_Shared;
|
||||
using OmniLinkBridge.OmniLink;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace OmniLinkBridgeTest.Mock
|
||||
{
|
||||
class MockOmniLinkII : IOmniLinkII
|
||||
{
|
||||
public clsHAC Controller { get; private set; }
|
||||
|
||||
public event EventHandler<SendCommandEventArgs> OnSendCommand;
|
||||
|
||||
public MockOmniLinkII()
|
||||
{
|
||||
Controller = new clsHAC();
|
||||
Controller.Model = enuModel.OMNI_PRO_II;
|
||||
Controller.TempFormat = enuTempFormat.Fahrenheit;
|
||||
}
|
||||
|
||||
public bool SendCommand(enuUnitCommand Cmd, byte Par, ushort Pr2)
|
||||
{
|
||||
OnSendCommand?.Invoke(null, new SendCommandEventArgs() { Cmd = Cmd, Par = Par, Pr2 = Pr2 });
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
33
OmniLinkBridgeTest/Mock/SendCommandEventArgs.cs
Normal file
33
OmniLinkBridgeTest/Mock/SendCommandEventArgs.cs
Normal file
|
@ -0,0 +1,33 @@
|
|||
using HAI_Shared;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace OmniLinkBridgeTest.Mock
|
||||
{
|
||||
public class SendCommandEventArgs : EventArgs
|
||||
{
|
||||
public enuUnitCommand Cmd;
|
||||
public byte Par;
|
||||
public ushort Pr2;
|
||||
|
||||
public override bool Equals(object other)
|
||||
{
|
||||
var toCompareWith = other as SendCommandEventArgs;
|
||||
|
||||
if (toCompareWith == null)
|
||||
return false;
|
||||
|
||||
return this.Cmd == toCompareWith.Cmd &&
|
||||
this.Par == toCompareWith.Par &&
|
||||
this.Pr2 == toCompareWith.Pr2;
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return base.GetHashCode();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -39,12 +39,19 @@
|
|||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="HAI.Controller, Version=3.11.4.17, Culture=neutral, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\OmniLinkBridge\HAI.Controller.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="AssemblyTestHarness.cs" />
|
||||
<Compile Include="ExtensionTest.cs" />
|
||||
<Compile Include="Mock\MockOmniLinkII.cs" />
|
||||
<Compile Include="Mock\SendCommandEventArgs.cs" />
|
||||
<Compile Include="MQTTTest.cs" />
|
||||
<Compile Include="NotificationTest.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
</ItemGroup>
|
||||
|
|
Loading…
Reference in a new issue