mirror of
https://github.com/excaliburpartners/OmniLinkBridge
synced 2024-12-22 10:42:24 +00:00
1.1.9 - Add MQTT system trouble, thermostat type, and area alarm activation
This commit is contained in:
parent
85c549d5dd
commit
1cf77ba179
9
OmniLinkBridge/MQTT/AlarmCommands.cs
Normal file
9
OmniLinkBridge/MQTT/AlarmCommands.cs
Normal file
|
@ -0,0 +1,9 @@
|
|||
namespace OmniLinkBridge.MQTT
|
||||
{
|
||||
enum AlarmCommands
|
||||
{
|
||||
burglary = 1,
|
||||
fire = 2,
|
||||
auxiliary = 3
|
||||
}
|
||||
}
|
|
@ -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,7 +433,17 @@ 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)
|
||||
{
|
||||
|
|
|
@ -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>
|
||||
|
@ -168,10 +178,19 @@ namespace OmniLinkBridge.MQTT
|
|||
OmniLink.SendCommand(enuUnitCommand.SetDeHumidifySetPt, BitConverter.GetBytes(level)[0], (ushort)thermostat.Number);
|
||||
}
|
||||
else if (command == Topic.mode_command && Enum.TryParse(payload, true, out enuThermostatMode mode))
|
||||
{
|
||||
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))
|
||||
{
|
||||
log.Debug("SetThermostatFanMode: {id} to {value}", thermostat.Number, payload);
|
||||
|
|
|
@ -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,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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: " +
|
||||
|
|
21
OmniLinkBridge/OmniLink/SystemEventType.cs
Normal file
21
OmniLinkBridge/OmniLink/SystemEventType.cs
Normal 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,
|
||||
}
|
||||
}
|
|
@ -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; }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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" />
|
||||
|
|
|
@ -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")]
|
||||
|
|
|
@ -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()
|
||||
{
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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">
|
||||
|
|
20
README.md
20
README.md
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue