1.1.9 - Add MQTT system trouble, thermostat type, and area alarm activation

This commit is contained in:
Ryan Wagoner 2020-11-05 21:59:30 -05:00
parent 85c549d5dd
commit 1cf77ba179
16 changed files with 331 additions and 103 deletions

View file

@ -0,0 +1,9 @@
namespace OmniLinkBridge.MQTT
{
enum AlarmCommands
{
burglary = 1,
fire = 2,
auxiliary = 3
}
}

View file

@ -1,5 +1,6 @@
using HAI_Shared;
using Newtonsoft.Json;
using System.Collections.Generic;
namespace OmniLinkBridge.MQTT
{
@ -31,24 +32,16 @@ namespace OmniLinkBridge.MQTT
else if (area.ExitTimer > 0)
return "pending";
switch (area.AreaMode)
return area.AreaMode switch
{
case enuSecurityMode.Night:
return "armed_night";
case enuSecurityMode.NightDly:
return "armed_night_delay";
case enuSecurityMode.Day:
return "armed_home";
case enuSecurityMode.DayInst:
return "armed_home_instant";
case enuSecurityMode.Away:
return "armed_away";
case enuSecurityMode.Vacation:
return "armed_vacation";
case enuSecurityMode.Off:
default:
return "disarmed";
}
enuSecurityMode.Night => "armed_night",
enuSecurityMode.NightDly => "armed_night_delay",
enuSecurityMode.Day => "armed_home",
enuSecurityMode.DayInst => "armed_home_instant",
enuSecurityMode.Away => "armed_away",
enuSecurityMode.Vacation => "armed_vacation",
_ => "disarmed",
};
}
public static string ToBasicState(this clsArea area)
@ -196,32 +189,16 @@ namespace OmniLinkBridge.MQTT
temperature_alarm = area.AreaAlarms.IsBitSet(7)
};
switch (area.AreaMode)
state.mode = area.AreaMode switch
{
case enuSecurityMode.Night:
state.mode = "night";
break;
case enuSecurityMode.NightDly:
state.mode = "night_delay";
break;
case enuSecurityMode.Day:
state.mode = "home";
break;
case enuSecurityMode.DayInst:
state.mode = "home_instant";
break;
case enuSecurityMode.Away:
state.mode = "away";
break;
case enuSecurityMode.Vacation:
state.mode = "vacation";
break;
case enuSecurityMode.Off:
default:
state.mode = "off";
break;
}
enuSecurityMode.Night => "night",
enuSecurityMode.NightDly => "night_delay",
enuSecurityMode.Day => "home",
enuSecurityMode.DayInst => "home_instant",
enuSecurityMode.Away => "away",
enuSecurityMode.Vacation => "vacation",
_ => "off",
};
return JsonConvert.SerializeObject(state);
}
@ -456,9 +433,19 @@ namespace OmniLinkBridge.MQTT
public static Climate ToConfig(this clsThermostat thermostat, enuTempFormat format)
{
Climate ret = new Climate();
Climate ret = new Climate
{
modes = thermostat.Type switch
{
enuThermostatType.AutoHeatCool => new List<string>(new string[] { "auto", "off", "cool", "heat" }),
enuThermostatType.HeatCool => new List<string>(new string[] { "off", "cool", "heat" }),
enuThermostatType.HeatOnly => new List<string>(new string[] { "off", "heat" }),
enuThermostatType.CoolOnly => new List<string>(new string[] { "off", "cool" }),
_ => new List<string>(new string[] { "off" }),
}
};
if(format == enuTempFormat.Celsius)
if (format == enuTempFormat.Celsius)
{
ret.min_temp = "7";
ret.max_temp = "35";

View file

@ -72,6 +72,16 @@ namespace OmniLinkBridge.MQTT
log.Debug("SetArea: {id} to {value}", area.Number, cmd.ToString().Replace("arm_", "").Replace("_", " "));
OmniLink.SendCommand(AreaMapping[cmd], 0, (ushort)area.Number);
}
else if (command == Topic.alarm_command && area.Number > 0 && Enum.TryParse(payload, true, out AlarmCommands alarm))
{
log.Debug("SetAreaAlarm: {id} to {value}", area.Number, payload);
OmniLink.Controller.Connection.Send(new clsOL2MsgActivateKeypadEmg(OmniLink.Controller.Connection)
{
Area = (byte)area.Number,
EmgType = (byte)alarm
}, (M, B, Timeout) => { });
}
}
private static readonly IDictionary<ZoneCommands, enuUnitCommand> ZoneMapping = new Dictionary<ZoneCommands, enuUnitCommand>
@ -169,8 +179,17 @@ namespace OmniLinkBridge.MQTT
}
else if (command == Topic.mode_command && Enum.TryParse(payload, true, out enuThermostatMode mode))
{
log.Debug("SetThermostatMode: {id} to {value}", thermostat.Number, payload);
OmniLink.SendCommand(enuUnitCommand.Mode, BitConverter.GetBytes((int)mode)[0], (ushort)thermostat.Number);
if (thermostat.Type == enuThermostatType.AutoHeatCool ||
(thermostat.Type == enuThermostatType.HeatCool && mode != enuThermostatMode.Auto) ||
(thermostat.Type == enuThermostatType.CoolOnly &&
(mode == enuThermostatMode.Off || mode == enuThermostatMode.Cool)) ||
(thermostat.Type == enuThermostatType.HeatOnly &&
(mode == enuThermostatMode.Off || mode == enuThermostatMode.Heat || mode == enuThermostatMode.E_Heat)) ||
mode == enuThermostatMode.Off)
{
log.Debug("SetThermostatMode: {id} to {value}", thermostat.Number, 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))
{

View file

@ -5,6 +5,7 @@
name,
state,
command,
alarm_command,
basic_state,
json_state,
brightness_state,
@ -27,6 +28,6 @@
fan_mode_state,
fan_mode_command,
hold_state,
hold_command
hold_command,
}
}

View file

@ -298,7 +298,7 @@ namespace OmniLinkBridge.Modules
VALUES ('" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + "','" + e.Type.ToString() + "','" + e.Value + "')");
if (Global.verbose_event)
log.Verbose("SystemEvent {name} {status}", e.Type.ToString(), e.Value);
log.Verbose("SystemEvent {name}, Status: {status}", e.Type.ToString(), e.Value);
if (e.SendNotification)
Notification.Notify("SystemEvent", e.Type.ToString() + " " + e.Value);

View file

@ -47,6 +47,7 @@ namespace OmniLinkBridge.Modules
OmniLink.OnThermostatStatus += Omnilink_OnThermostatStatus;
OmniLink.OnButtonStatus += OmniLink_OnButtonStatus;
OmniLink.OnMessageStatus += OmniLink_OnMessageStatus;
OmniLink.OnSystemStatus += OmniLink_OnSystemStatus;
MessageProcessor = new MessageProcessor(omni);
}
@ -105,6 +106,7 @@ namespace OmniLinkBridge.Modules
List<Topic> toSubscribe = new List<Topic>()
{
Topic.command,
Topic.alarm_command,
Topic.brightness_command,
Topic.scene_command,
Topic.temperature_heat_command,
@ -117,7 +119,7 @@ namespace OmniLinkBridge.Modules
};
toSubscribe.ForEach((command) => MqttClient.SubscribeAsync(
new TopicFilterBuilder().WithTopic($"{Global.mqtt_prefix}/+/{command}").Build()));
new MqttTopicFilterBuilder().WithTopic($"{Global.mqtt_prefix}/+/{command}").Build()));
// Wait until shutdown
trigger.WaitOne();
@ -156,6 +158,7 @@ namespace OmniLinkBridge.Modules
private void PublishConfig()
{
PublishSystem();
PublishAreas();
PublishZones();
PublishUnits();
@ -168,6 +171,41 @@ namespace OmniLinkBridge.Modules
PublishAsync($"{Global.mqtt_prefix}/version", OmniLink.Controller.GetVersionText());
}
private void PublishSystem()
{
log.Debug("Publishing {type}", "system");
PublishAsync($"{Global.mqtt_discovery_prefix}/binary_sensor/{Global.mqtt_prefix}/system_phone/config",
JsonConvert.SerializeObject(SystemTroubleConfig("phone", "Phone")));
PublishAsync($"{Global.mqtt_discovery_prefix}/binary_sensor/{Global.mqtt_prefix}/system_ac/config",
JsonConvert.SerializeObject(SystemTroubleConfig("ac", "AC")));
PublishAsync($"{Global.mqtt_discovery_prefix}/binary_sensor/{Global.mqtt_prefix}/system_battery/config",
JsonConvert.SerializeObject(SystemTroubleConfig("battery", "Battery")));
PublishAsync($"{Global.mqtt_discovery_prefix}/binary_sensor/{Global.mqtt_prefix}/system_dcm/config",
JsonConvert.SerializeObject(SystemTroubleConfig("dcm", "DCM")));
PublishAsync(SystemTroubleTopic("phone"), OmniLink.TroublePhone ? "trouble" : "secure");
PublishAsync(SystemTroubleTopic("ac"), OmniLink.TroubleAC ? "trouble" : "secure");
PublishAsync(SystemTroubleTopic("battery"), OmniLink.TroubleBattery ? "trouble" : "secure");
PublishAsync(SystemTroubleTopic("dcn"), OmniLink.TroubleDCM ? "trouble" : "secure");
}
public string SystemTroubleTopic(string type)
{
return $"{Global.mqtt_prefix}/system/{type}/{Topic.state}";
}
public BinarySensor SystemTroubleConfig(string type, string name)
{
return new BinarySensor
{
unique_id = $"{Global.mqtt_prefix}system{type}",
name = $"{Global.mqtt_discovery_name_prefix} System {name}",
state_topic = SystemTroubleTopic(type),
device_class = BinarySensor.DeviceClass.problem
};
}
private void PublishAreas()
{
log.Debug("Publishing {type}", "areas");
@ -441,6 +479,21 @@ namespace OmniLinkBridge.Modules
PublishMessageState(e.Message);
}
private void OmniLink_OnSystemStatus(object sender, SystemStatusEventArgs e)
{
if (!MqttClient.IsConnected)
return;
if(e.Type == SystemEventType.Phone)
PublishAsync(SystemTroubleTopic("phone"), e.Trouble ? "trouble" : "secure");
else if (e.Type == SystemEventType.AC)
PublishAsync(SystemTroubleTopic("ac"), e.Trouble ? "trouble" : "secure");
else if (e.Type == SystemEventType.Button)
PublishAsync(SystemTroubleTopic("battery"), e.Trouble ? "trouble" : "secure");
else if (e.Type == SystemEventType.DCM)
PublishAsync(SystemTroubleTopic("dcm"), e.Trouble ? "trouble" : "secure");
}
private void PublishAreaState(clsArea area)
{
PublishAsync(area.ToTopic(Topic.state), area.ToState());

View file

@ -21,6 +21,11 @@ namespace OmniLinkBridge.Modules
public clsHAC Controller { get; private set; }
private DateTime retry = DateTime.MinValue;
public bool TroublePhone { get; set; }
public bool TroubleAC { get; set; }
public bool TroubleBattery { get; set; }
public bool TroubleDCM { get; set; }
// Thermostats
private readonly Dictionary<ushort, DateTime> tstats = new Dictionary<ushort, DateTime>();
private readonly System.Timers.Timer tstat_timer = new System.Timers.Timer();
@ -254,6 +259,7 @@ namespace OmniLinkBridge.Modules
log.Debug("Retrieving named units");
await GetSystemFormats();
await GetSystemTroubles();
await GetNamed(enuObjectType.Area);
await GetNamed(enuObjectType.Zone);
await GetNamed(enuObjectType.Thermostat);
@ -266,7 +272,20 @@ namespace OmniLinkBridge.Modules
{
log.Debug("Waiting for system formats");
clsOL2MsgRequestSystemFormats MSG = new clsOL2MsgRequestSystemFormats(Controller.Connection);
var MSG = new clsOL2MsgRequestSystemFormats(Controller.Connection);
Controller.Connection.Send(MSG, HandleNamedPropertiesResponse);
await Task.Run(() =>
{
nameWait.WaitOne(new TimeSpan(0, 0, 10));
});
}
private async Task GetSystemTroubles()
{
log.Debug("Waiting for system troubles");
var MSG = new clsOL2MsgRequestSystemTroubles(Controller.Connection);
Controller.Connection.Send(MSG, HandleNamedPropertiesResponse);
await Task.Run(() =>
@ -289,7 +308,7 @@ namespace OmniLinkBridge.Modules
private void GetNextNamed(enuObjectType type, int ix)
{
clsOL2MsgRequestProperties MSG = new clsOL2MsgRequestProperties(Controller.Connection)
var MSG = new clsOL2MsgRequestProperties(Controller.Connection)
{
ObjectType = type,
IndexNumber = (UInt16)ix,
@ -315,16 +334,26 @@ namespace OmniLinkBridge.Modules
nameWait.Set();
break;
case enuOmniLink2MessageType.SystemFormats:
clsOL2MsgSystemFormats MSG2 = new clsOL2MsgSystemFormats(Controller.Connection, B);
var systemFormats = new clsOL2MsgSystemFormats(Controller.Connection, B);
Controller.DateFormat = MSG2.Date;
Controller.TimeFormat = MSG2.Time;
Controller.TempFormat = MSG2.Temp;
Controller.DateFormat = systemFormats.Date;
Controller.TimeFormat = systemFormats.Time;
Controller.TempFormat = systemFormats.Temp;
using (LogContext.PushProperty("Telemetry", "TemperatureFormat"))
log.Debug("Temperature format is {TemperatureFormat}",
(Controller.TempFormat == enuTempFormat.Fahrenheit ? "Fahrenheit" : "Celsius"));
nameWait.Set();
break;
case enuOmniLink2MessageType.SystemTroubles:
var systemTroubles = new clsOL2MsgSystemTroubles(Controller.Connection, B);
TroublePhone = systemTroubles.Contains(enuTroubles.PhoneLine);
TroubleAC = systemTroubles.Contains(enuTroubles.AC);
TroubleBattery = systemTroubles.Contains(enuTroubles.BatteryLow);
TroubleDCM = systemTroubles.Contains(enuTroubles.DCM);
nameWait.Set();
break;
case enuOmniLink2MessageType.Properties:
@ -473,7 +502,7 @@ namespace OmniLinkBridge.Modules
if (MSG.SystemEvent >= 1 && MSG.SystemEvent <= 255)
{
eventargs.Type = enuEventType.USER_MACRO_BUTTON;
eventargs.Type = SystemEventType.Button;
eventargs.Value = ((int)MSG.SystemEvent).ToString() + " " + Controller.Buttons[MSG.SystemEvent].Name;
OnSystemStatus?.Invoke(this, eventargs);
@ -484,87 +513,103 @@ namespace OmniLinkBridge.Modules
Button = Controller.Buttons[MSG.SystemEvent]
});
}
else if (MSG.SystemEvent >= 768 && MSG.SystemEvent <= 771)
else if (MSG.SystemEvent >= (ushort)enuEventType.PHONE_LINE_DEAD &&
MSG.SystemEvent <= (ushort)enuEventType.PHONE_LINE_ON_HOOK)
{
eventargs.Type = enuEventType.PHONE_;
eventargs.Type = SystemEventType.Phone;
if (MSG.SystemEvent == 768)
if (MSG.SystemEvent == (ushort)enuEventType.PHONE_)
{
eventargs.Value = "DEAD";
eventargs.Trouble = true;
eventargs.SendNotification = true;
}
else if (MSG.SystemEvent == 769)
else if (MSG.SystemEvent == (ushort)enuEventType.PHONE_LINE_RING)
eventargs.Value = "RING";
else if (MSG.SystemEvent == 770)
else if (MSG.SystemEvent == (ushort)enuEventType.PHONE_LINE_OFF_HOOK)
eventargs.Value = "OFF HOOK";
else if (MSG.SystemEvent == 771)
else if (MSG.SystemEvent == (ushort)enuEventType.PHONE_LINE_ON_HOOK)
eventargs.Value = "ON HOOK";
OnSystemStatus?.Invoke(this, eventargs);
}
else if (MSG.SystemEvent >= 772 && MSG.SystemEvent <= 773)
else if (MSG.SystemEvent >= (ushort)enuEventType.AC_POWER_OFF &&
MSG.SystemEvent <= (ushort)enuEventType.AC_POWER_RESTORED)
{
eventargs.Type = enuEventType.AC_POWER_;
eventargs.Type = SystemEventType.AC;
eventargs.SendNotification = true;
if (MSG.SystemEvent == 772)
if (MSG.SystemEvent == (ushort)enuEventType.AC_POWER_OFF)
{
eventargs.Value = "OFF";
else if (MSG.SystemEvent == 773)
eventargs.Trouble = true;
}
else if (MSG.SystemEvent == (ushort)enuEventType.AC_POWER_RESTORED)
eventargs.Value = "RESTORED";
OnSystemStatus?.Invoke(this, eventargs);
}
else if (MSG.SystemEvent >= 774 && MSG.SystemEvent <= 775)
else if (MSG.SystemEvent >= (ushort)enuEventType.BATTERY_LOW &&
MSG.SystemEvent <= (ushort)enuEventType.BATTERY_OK)
{
eventargs.Type = enuEventType.BATTERY_;
eventargs.Type = SystemEventType.Battery;
eventargs.SendNotification = true;
if (MSG.SystemEvent == 774)
if (MSG.SystemEvent == (ushort)enuEventType.BATTERY_LOW)
{
eventargs.Value = "LOW";
else if (MSG.SystemEvent == 775)
eventargs.Trouble = true;
}
else if (MSG.SystemEvent == (ushort)enuEventType.BATTERY_OK)
eventargs.Value = "OK";
OnSystemStatus?.Invoke(this, eventargs);
}
else if (MSG.SystemEvent >= 776 && MSG.SystemEvent <= 777)
else if (MSG.SystemEvent >= (ushort)enuEventType.DCM_TROUBLE &&
MSG.SystemEvent <= (ushort)enuEventType.DCM_OK)
{
eventargs.Type = enuEventType.DCM_;
eventargs.Type = SystemEventType.DCM;
eventargs.SendNotification = true;
if (MSG.SystemEvent == 776)
if (MSG.SystemEvent == (ushort)enuEventType.DCM_TROUBLE)
{
eventargs.Value = "TROUBLE";
else if (MSG.SystemEvent == 777)
eventargs.Trouble = true;
}
else if (MSG.SystemEvent == (ushort)enuEventType.DCM_OK)
eventargs.Value = "OK";
OnSystemStatus?.Invoke(this, eventargs);
}
else if (MSG.SystemEvent >= 778 && MSG.SystemEvent <= 781)
else if (MSG.SystemEvent >= (ushort)enuEventType.ENERGY_COST_LOW &&
MSG.SystemEvent <= (ushort)enuEventType.ENERGY_COST_CRITICAL)
{
eventargs.Type = enuEventType.ENERGY_COST_;
eventargs.Type = SystemEventType.EnergyCost;
if (MSG.SystemEvent == 778)
if (MSG.SystemEvent == (ushort)enuEventType.ENERGY_COST_LOW)
eventargs.Value = "LOW";
else if (MSG.SystemEvent == 779)
else if (MSG.SystemEvent == (ushort)enuEventType.ENERGY_COST_MID)
eventargs.Value = "MID";
else if (MSG.SystemEvent == 780)
else if (MSG.SystemEvent == (ushort)enuEventType.ENERGY_COST_HIGH)
eventargs.Value = "HIGH";
else if (MSG.SystemEvent == 781)
else if (MSG.SystemEvent == (ushort)enuEventType.ENERGY_COST_CRITICAL)
eventargs.Value = "CRITICAL";
OnSystemStatus?.Invoke(this, eventargs);
}
else if (MSG.SystemEvent >= 782 && MSG.SystemEvent <= 787)
{
eventargs.Type = enuEventType.CAMERA;
eventargs.Type = SystemEventType.Camera;
eventargs.Value = (MSG.SystemEvent - 781).ToString();
OnSystemStatus?.Invoke(this, eventargs);
}
else if (MSG.SystemEvent >= 61440 && MSG.SystemEvent <= 64511)
{
eventargs.Type = enuEventType.SWITCH_PRESS;
int state = (int)MSG.Data[1] - 240;
int id = (int)MSG.Data[2];
eventargs.Type = SystemEventType.SwitchPress;
int state = MSG.Data[1] - 240;
int id = MSG.Data[2];
eventargs.Value = "Unit: " + id + ", State: " + state;
@ -572,9 +617,9 @@ namespace OmniLinkBridge.Modules
}
else if (MSG.SystemEvent >= 64512 && MSG.SystemEvent <= 65535)
{
eventargs.Type = enuEventType.UPB_LINK;
int state = (int)MSG.Data[1] - 252;
int id = (int)MSG.Data[2];
eventargs.Type = SystemEventType.UPBLink;
int state = MSG.Data[1] - 252;
int id = MSG.Data[2];
eventargs.Value = "Link: " + id + ", State: " + state;
@ -587,7 +632,7 @@ namespace OmniLinkBridge.Modules
sb.Append(MSG.Data[i].ToString() + " ");
log.Debug("Unhandled SystemEvent Raw: {raw}, Num: {num}", sb.ToString(), MSG.SystemEvent);
int num = ((int)MSG.MessageLength - 1) / 2;
int num = (MSG.MessageLength - 1) / 2;
for (int i = 0; i < num; i++)
{
log.Debug("Unhandled SystemEvent: " +

View file

@ -0,0 +1,21 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace OmniLinkBridge.OmniLink
{
public enum SystemEventType
{
Button,
Phone,
AC,
Battery,
DCM,
EnergyCost,
Camera,
SwitchPress,
UPBLink,
}
}

View file

@ -5,8 +5,9 @@ namespace OmniLinkBridge.OmniLink
{
public class SystemStatusEventArgs : EventArgs
{
public enuEventType Type { get; set; }
public SystemEventType Type { get; set; }
public string Value { get; set; }
public bool Trouble { get; set; }
public bool SendNotification { get; set; }
}
}

View file

@ -24,6 +24,7 @@
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<Prefer32Bit>false</Prefer32Bit>
<LangVersion>8.0</LangVersion>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
<PlatformTarget>x86</PlatformTarget>
@ -34,6 +35,7 @@
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<Prefer32Bit>false</Prefer32Bit>
<LangVersion>8.0</LangVersion>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|AnyCPU'">
<DebugSymbols>true</DebugSymbols>
@ -44,6 +46,7 @@
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
<NoWarn>IDE1006</NoWarn>
<LangVersion>8.0</LangVersion>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|AnyCPU'">
<OutputPath>bin\Release\</OutputPath>
@ -54,6 +57,7 @@
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
<NoWarn>IDE1006</NoWarn>
<LangVersion>8.0</LangVersion>
</PropertyGroup>
<PropertyGroup>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
@ -79,6 +83,7 @@
<Compile Include="CoreServer.cs" />
<Compile Include="Modules\TimeSyncModule.cs" />
<Compile Include="MQTT\Alarm.cs" />
<Compile Include="MQTT\AlarmCommands.cs" />
<Compile Include="MQTT\AreaCommands.cs" />
<Compile Include="MQTT\AreaState.cs" />
<Compile Include="MQTT\BinarySensor.cs" />
@ -103,6 +108,7 @@
<Compile Include="Notifications\PushoverNotification.cs" />
<Compile Include="OmniLink\ButtonStatusEventArgs.cs" />
<Compile Include="OmniLink\IOmniLinkII.cs" />
<Compile Include="OmniLink\SystemEventType.cs" />
<Compile Include="OmniLink\UnitStatusEventArgs.cs" />
<Compile Include="OmniLink\ThermostatStatusEventArgs.cs" />
<Compile Include="OmniLink\MessageStatusEventArgs.cs" />
@ -167,13 +173,13 @@
<Version>4.5.0</Version>
</PackageReference>
<PackageReference Include="MQTTnet.Extensions.ManagedClient">
<Version>3.0.8</Version>
<Version>3.0.13</Version>
</PackageReference>
<PackageReference Include="Newtonsoft.Json">
<Version>12.0.3</Version>
</PackageReference>
<PackageReference Include="Serilog">
<Version>2.9.0</Version>
<Version>2.10.0</Version>
</PackageReference>
<PackageReference Include="Serilog.Formatting.Compact">
<Version>1.1.0</Version>
@ -188,7 +194,7 @@
<Version>4.1.0</Version>
</PackageReference>
<PackageReference Include="Serilog.Sinks.Http">
<Version>5.2.0</Version>
<Version>7.2.0</Version>
</PackageReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />

View file

@ -32,5 +32,5 @@ using System.Runtime.InteropServices;
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.1.8.0")]
[assembly: AssemblyFileVersion("1.1.8.0")]
[assembly: AssemblyVersion("1.1.9.0")]
[assembly: AssemblyFileVersion("1.1.9.0")]

View file

@ -133,6 +133,70 @@ namespace OmniLinkBridgeTest
check(1, "50", enuUnitCommand.Level, 50);
}
[TestMethod]
public void ThermostatModeCommandInvalid()
{
SendCommandEventArgs actual = null;
omniLink.OnSendCommand += (sender, e) => { actual = e; };
omniLink.Controller.Thermostats[1].Type = enuThermostatType.HeatCool;
messageProcessor.Process($"omnilink/thermostat1/mode_command", "auto");
Assert.IsNull(actual);
omniLink.Controller.Thermostats[1].Type = enuThermostatType.CoolOnly;
messageProcessor.Process($"omnilink/thermostat1/mode_command", "auto");
Assert.IsNull(actual);
messageProcessor.Process($"omnilink/thermostat1/mode_command", "heat");
Assert.IsNull(actual);
omniLink.Controller.Thermostats[1].Type = enuThermostatType.HeatOnly;
messageProcessor.Process($"omnilink/thermostat1/mode_command", "auto");
Assert.IsNull(actual);
messageProcessor.Process($"omnilink/thermostat1/mode_command", "cool");
Assert.IsNull(actual);
}
[TestMethod]
public void ThermostatModeCommand()
{
void check(ushort id, string payload, enuUnitCommand command, int mode)
{
SendCommandEventArgs actual = null;
omniLink.OnSendCommand += (sender, e) => { actual = e; };
messageProcessor.Process($"omnilink/thermostat{id}/mode_command", payload);
SendCommandEventArgs expected = new SendCommandEventArgs()
{
Cmd = command,
Par = (byte)mode,
Pr2 = id
};
Assert.AreEqual(expected, actual);
}
omniLink.Controller.Thermostats[1].Type = enuThermostatType.AutoHeatCool;
check(1, "auto", enuUnitCommand.Mode, (int)enuThermostatMode.Auto);
check(1, "cool", enuUnitCommand.Mode, (int)enuThermostatMode.Cool);
check(1, "heat", enuUnitCommand.Mode, (int)enuThermostatMode.Heat);
check(1, "off", enuUnitCommand.Mode, (int)enuThermostatMode.Off);
omniLink.Controller.Thermostats[1].Type = enuThermostatType.HeatCool;
check(1, "cool", enuUnitCommand.Mode, (int)enuThermostatMode.Cool);
check(1, "heat", enuUnitCommand.Mode, (int)enuThermostatMode.Heat);
check(1, "off", enuUnitCommand.Mode, (int)enuThermostatMode.Off);
omniLink.Controller.Thermostats[1].Type = enuThermostatType.CoolOnly;
check(1, "cool", enuUnitCommand.Mode, (int)enuThermostatMode.Cool);
check(1, "off", enuUnitCommand.Mode, (int)enuThermostatMode.Off);
omniLink.Controller.Thermostats[1].Type = enuThermostatType.HeatOnly;
check(1, "heat", enuUnitCommand.Mode, (int)enuThermostatMode.Heat);
check(1, "off", enuUnitCommand.Mode, (int)enuThermostatMode.Off);
}
[TestMethod]
public void ButtonCommand()
{

View file

@ -16,9 +16,11 @@ namespace OmniLinkBridgeTest.Mock
public MockOmniLinkII()
{
Controller = new clsHAC();
Controller.Model = enuModel.OMNI_PRO_II;
Controller.TempFormat = enuTempFormat.Fahrenheit;
Controller = new clsHAC
{
Model = enuModel.OMNI_PRO_II,
TempFormat = enuTempFormat.Fahrenheit
};
}
public bool SendCommand(enuUnitCommand Cmd, byte Par, ushort Pr2)

View file

@ -15,14 +15,12 @@ namespace OmniLinkBridgeTest.Mock
public override bool Equals(object other)
{
var toCompareWith = other as SendCommandEventArgs;
if (toCompareWith == null)
if (!(other is SendCommandEventArgs toCompareWith))
return false;
return this.Cmd == toCompareWith.Cmd &&
this.Par == toCompareWith.Par &&
this.Pr2 == toCompareWith.Pr2;
return Cmd == toCompareWith.Cmd &&
Par == toCompareWith.Par &&
Pr2 == toCompareWith.Pr2;
}
public override int GetHashCode()

View file

@ -29,6 +29,7 @@
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<LangVersion>8.0</LangVersion>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
@ -37,6 +38,7 @@
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<LangVersion>8.0</LangVersion>
</PropertyGroup>
<ItemGroup>
<Reference Include="HAI.Controller, Version=3.11.4.17, Culture=neutral, processorArchitecture=MSIL">

View file

@ -146,6 +146,20 @@ systemctl start omnilinkbridge.service
```
## MQTT
### System
```
SUB omnilink/system/phone/state
string secure, trouble
SUB omnilink/system/ac/state
string secure, trouble
SUB omnilink/system/battery/state
string secure, trouble
SUB omnilink/system/dcm/state
string secure, trouble
```
### Areas
```
@ -158,8 +172,14 @@ string triggered, pending, armed_night, armed_night_delay, armed_home, armed_hom
SUB omnilink/areaX/basic_state
string triggered, pending, armed_night, armed_home, armed_away, disarmed
SUB omnilink/areaX/json_state
string json
PUB omnilink/areaX/command
string arm_home, arm_away, arm_night, disarm, arm_home_instant, arm_night_delay, arm_vacation
PUB omnilink/areaX/alarm_command
string burglary, fire, auxiliary
```
### Zones