mirror of
https://github.com/excaliburpartners/OmniLinkBridge
synced 2024-12-22 18:52:24 +00:00
1.1.2 - Add min and max climate temperatures
- Update docker run command to use local time zone - Improve area and zone MQTT support - Add option to change MQTT prefix to support multiple instances - Add detailed zone sensor and thermostat humidity sensor - Add prefix for MQTT discovery entity name - Request zone status update on area status change
This commit is contained in:
parent
78694b386d
commit
96093fbebd
|
@ -48,7 +48,9 @@ namespace OmniLinkBridge
|
||||||
public static int mqtt_port;
|
public static int mqtt_port;
|
||||||
public static string mqtt_username;
|
public static string mqtt_username;
|
||||||
public static string mqtt_password;
|
public static string mqtt_password;
|
||||||
|
public static string mqtt_prefix;
|
||||||
public static string mqtt_discovery_prefix;
|
public static string mqtt_discovery_prefix;
|
||||||
|
public static string mqtt_discovery_name_prefix;
|
||||||
public static HashSet<int> mqtt_discovery_ignore_zones;
|
public static HashSet<int> mqtt_discovery_ignore_zones;
|
||||||
public static HashSet<int> mqtt_discovery_ignore_units;
|
public static HashSet<int> mqtt_discovery_ignore_units;
|
||||||
public static ConcurrentDictionary<int, OverrideZone> mqtt_discovery_override_zone;
|
public static ConcurrentDictionary<int, OverrideZone> mqtt_discovery_override_zone;
|
||||||
|
|
|
@ -8,6 +8,8 @@ namespace OmniLinkBridge.MQTT
|
||||||
{
|
{
|
||||||
public class Alarm : Device
|
public class Alarm : Device
|
||||||
{
|
{
|
||||||
|
public string basic_state_topic { get; set; }
|
||||||
|
|
||||||
public string command_topic { get; set; }
|
public string command_topic { get; set; }
|
||||||
|
|
||||||
//public string code { get; set; } = string.Empty;
|
//public string code { get; set; } = string.Empty;
|
||||||
|
|
|
@ -16,6 +16,9 @@ namespace OmniLinkBridge.MQTT
|
||||||
public string temperature_high_state_topic { get; set; }
|
public string temperature_high_state_topic { get; set; }
|
||||||
public string temperature_high_command_topic { get; set; }
|
public string temperature_high_command_topic { get; set; }
|
||||||
|
|
||||||
|
public string min_temp { get; set; } = "45";
|
||||||
|
public string max_temp { get; set; } = "95";
|
||||||
|
|
||||||
public string mode_state_topic { get; set; }
|
public string mode_state_topic { get; set; }
|
||||||
public string mode_command_topic { get; set; }
|
public string mode_command_topic { get; set; }
|
||||||
public List<string> modes { get; set; } = new List<string>(new string[] { "auto", "off", "cool", "heat" });
|
public List<string> modes { get; set; } = new List<string>(new string[] { "auto", "off", "cool", "heat" });
|
||||||
|
|
|
@ -12,6 +12,6 @@ namespace OmniLinkBridge.MQTT
|
||||||
|
|
||||||
public string state_topic { get; set; }
|
public string state_topic { get; set; }
|
||||||
|
|
||||||
public string availability_topic { get; set; } = "omnilink/status";
|
public string availability_topic { get; set; } = $"{Global.mqtt_prefix}/status";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,19 +11,46 @@ namespace OmniLinkBridge.MQTT
|
||||||
{
|
{
|
||||||
public static string ToTopic(this clsArea area, Topic topic)
|
public static string ToTopic(this clsArea area, Topic topic)
|
||||||
{
|
{
|
||||||
return $"omnilink/area{area.Number.ToString()}/{topic.ToString()}";
|
return $"{Global.mqtt_prefix}/area{area.Number.ToString()}/{topic.ToString()}";
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Alarm ToConfig(this clsArea area)
|
public static Alarm ToConfig(this clsArea area)
|
||||||
{
|
{
|
||||||
Alarm ret = new Alarm();
|
Alarm ret = new Alarm();
|
||||||
ret.name = area.Name;
|
ret.name = Global.mqtt_discovery_name_prefix + area.Name;
|
||||||
ret.state_topic = area.ToTopic(Topic.state);
|
ret.state_topic = area.ToTopic(Topic.basic_state);
|
||||||
ret.command_topic = area.ToTopic(Topic.command);
|
ret.command_topic = area.ToTopic(Topic.command);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static string ToState(this clsArea area)
|
public static string ToState(this clsArea area)
|
||||||
|
{
|
||||||
|
if (area.AreaBurglaryAlarmText != "OK")
|
||||||
|
return "triggered";
|
||||||
|
else if (area.ExitTimer > 0)
|
||||||
|
return "pending";
|
||||||
|
|
||||||
|
switch (area.AreaMode)
|
||||||
|
{
|
||||||
|
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";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string ToBasicState(this clsArea area)
|
||||||
{
|
{
|
||||||
if (area.AreaBurglaryAlarmText != "OK")
|
if (area.AreaBurglaryAlarmText != "OK")
|
||||||
return "triggered";
|
return "triggered";
|
||||||
|
@ -49,15 +76,15 @@ namespace OmniLinkBridge.MQTT
|
||||||
|
|
||||||
public static string ToTopic(this clsZone zone, Topic topic)
|
public static string ToTopic(this clsZone zone, Topic topic)
|
||||||
{
|
{
|
||||||
return $"omnilink/zone{zone.Number.ToString()}/{topic.ToString()}";
|
return $"{Global.mqtt_prefix}/zone{zone.Number.ToString()}/{topic.ToString()}";
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Sensor ToConfigTemp(this clsZone zone)
|
public static Sensor ToConfigTemp(this clsZone zone)
|
||||||
{
|
{
|
||||||
Sensor ret = new Sensor();
|
Sensor ret = new Sensor();
|
||||||
ret.name = zone.Name;
|
ret.name = $"{Global.mqtt_discovery_name_prefix}{zone.Name} Temp";
|
||||||
ret.device_class = Sensor.DeviceClass.temperature;
|
ret.device_class = Sensor.DeviceClass.temperature;
|
||||||
ret.state_topic = zone.ToTopic(Topic.state);
|
ret.state_topic = zone.ToTopic(Topic.current_temperature);
|
||||||
ret.unit_of_measurement = "°F";
|
ret.unit_of_measurement = "°F";
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -65,17 +92,56 @@ namespace OmniLinkBridge.MQTT
|
||||||
public static Sensor ToConfigHumidity(this clsZone zone)
|
public static Sensor ToConfigHumidity(this clsZone zone)
|
||||||
{
|
{
|
||||||
Sensor ret = new Sensor();
|
Sensor ret = new Sensor();
|
||||||
ret.name = zone.Name;
|
ret.name = $"{Global.mqtt_discovery_name_prefix}{zone.Name} Humidity";
|
||||||
ret.device_class = Sensor.DeviceClass.humidity;
|
ret.device_class = Sensor.DeviceClass.humidity;
|
||||||
ret.state_topic = zone.ToTopic(Topic.state);
|
ret.state_topic = zone.ToTopic(Topic.current_humidity);
|
||||||
ret.unit_of_measurement = "%";
|
ret.unit_of_measurement = "%";
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static Sensor ToConfigSensor(this clsZone zone)
|
||||||
|
{
|
||||||
|
Sensor ret = new Sensor();
|
||||||
|
ret.name = Global.mqtt_discovery_name_prefix + zone.Name;
|
||||||
|
|
||||||
|
switch (zone.ZoneType)
|
||||||
|
{
|
||||||
|
case enuZoneType.EntryExit:
|
||||||
|
case enuZoneType.X2EntryDelay:
|
||||||
|
case enuZoneType.X4EntryDelay:
|
||||||
|
ret.icon = "mdi:door";
|
||||||
|
break;
|
||||||
|
case enuZoneType.Perimeter:
|
||||||
|
ret.icon = "mdi:window-closed";
|
||||||
|
break;
|
||||||
|
case enuZoneType.Tamper:
|
||||||
|
ret.icon = "mdi:shield";
|
||||||
|
break;
|
||||||
|
case enuZoneType.AwayInt:
|
||||||
|
case enuZoneType.NightInt:
|
||||||
|
ret.icon = "mdi:walk";
|
||||||
|
break;
|
||||||
|
case enuZoneType.Water:
|
||||||
|
ret.icon = "mdi:water";
|
||||||
|
break;
|
||||||
|
case enuZoneType.Fire:
|
||||||
|
ret.icon = "mdi:fire";
|
||||||
|
break;
|
||||||
|
case enuZoneType.Gas:
|
||||||
|
ret.icon = "mdi:gas-cylinder";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret.value_template = @"{{ value|replace(""_"", "" "")|title }}";
|
||||||
|
|
||||||
|
ret.state_topic = zone.ToTopic(Topic.state);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
public static BinarySensor ToConfig(this clsZone zone)
|
public static BinarySensor ToConfig(this clsZone zone)
|
||||||
{
|
{
|
||||||
BinarySensor ret = new BinarySensor();
|
BinarySensor ret = new BinarySensor();
|
||||||
ret.name = zone.Name;
|
ret.name = Global.mqtt_discovery_name_prefix + zone.Name;
|
||||||
|
|
||||||
Global.mqtt_discovery_override_zone.TryGetValue(zone.Number, out OverrideZone override_zone);
|
Global.mqtt_discovery_override_zone.TryGetValue(zone.Number, out OverrideZone override_zone);
|
||||||
|
|
||||||
|
@ -114,27 +180,40 @@ namespace OmniLinkBridge.MQTT
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ret.state_topic = zone.ToTopic(Topic.state);
|
ret.state_topic = zone.ToTopic(Topic.basic_state);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static string ToState(this clsZone zone)
|
public static string ToState(this clsZone zone)
|
||||||
{
|
{
|
||||||
if (zone.IsTemperatureZone() || zone.IsHumidityZone())
|
if (zone.Status.IsBitSet(5))
|
||||||
return zone.TempText();
|
return "bypassed";
|
||||||
|
else if (zone.Status.IsBitSet(2))
|
||||||
|
return "tripped";
|
||||||
|
else if (zone.Status.IsBitSet(4))
|
||||||
|
return "armed";
|
||||||
|
else if (zone.Status.IsBitSet(1))
|
||||||
|
return "trouble";
|
||||||
|
else if (zone.Status.IsBitSet(0))
|
||||||
|
return "not_ready";
|
||||||
else
|
else
|
||||||
|
return "secure";
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string ToBasicState(this clsZone zone)
|
||||||
|
{
|
||||||
return zone.Status.IsBitSet(0) ? "ON" : "OFF";
|
return zone.Status.IsBitSet(0) ? "ON" : "OFF";
|
||||||
}
|
}
|
||||||
|
|
||||||
public static string ToTopic(this clsUnit unit, Topic topic)
|
public static string ToTopic(this clsUnit unit, Topic topic)
|
||||||
{
|
{
|
||||||
return $"omnilink/unit{unit.Number.ToString()}/{topic.ToString()}";
|
return $"{Global.mqtt_prefix}/unit{unit.Number.ToString()}/{topic.ToString()}";
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Light ToConfig(this clsUnit unit)
|
public static Light ToConfig(this clsUnit unit)
|
||||||
{
|
{
|
||||||
Light ret = new Light();
|
Light ret = new Light();
|
||||||
ret.name = unit.Name;
|
ret.name = Global.mqtt_discovery_name_prefix + unit.Name;
|
||||||
ret.state_topic = unit.ToTopic(Topic.state);
|
ret.state_topic = unit.ToTopic(Topic.state);
|
||||||
ret.command_topic = unit.ToTopic(Topic.command);
|
ret.command_topic = unit.ToTopic(Topic.command);
|
||||||
ret.brightness_state_topic = unit.ToTopic(Topic.brightness_state);
|
ret.brightness_state_topic = unit.ToTopic(Topic.brightness_state);
|
||||||
|
@ -145,7 +224,7 @@ namespace OmniLinkBridge.MQTT
|
||||||
public static Switch ToConfigSwitch(this clsUnit unit)
|
public static Switch ToConfigSwitch(this clsUnit unit)
|
||||||
{
|
{
|
||||||
Switch ret = new Switch();
|
Switch ret = new Switch();
|
||||||
ret.name = unit.Name;
|
ret.name = Global.mqtt_discovery_name_prefix + unit.Name;
|
||||||
ret.state_topic = unit.ToTopic(Topic.state);
|
ret.state_topic = unit.ToTopic(Topic.state);
|
||||||
ret.command_topic = unit.ToTopic(Topic.command);
|
ret.command_topic = unit.ToTopic(Topic.command);
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -168,13 +247,23 @@ namespace OmniLinkBridge.MQTT
|
||||||
|
|
||||||
public static string ToTopic(this clsThermostat thermostat, Topic topic)
|
public static string ToTopic(this clsThermostat thermostat, Topic topic)
|
||||||
{
|
{
|
||||||
return $"omnilink/thermostat{thermostat.Number.ToString()}/{topic.ToString()}";
|
return $"{Global.mqtt_prefix}/thermostat{thermostat.Number.ToString()}/{topic.ToString()}";
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Sensor ToConfigHumidity(this clsThermostat zone)
|
||||||
|
{
|
||||||
|
Sensor ret = new Sensor();
|
||||||
|
ret.name = Global.mqtt_discovery_name_prefix + zone.Name;
|
||||||
|
ret.device_class = Sensor.DeviceClass.humidity;
|
||||||
|
ret.state_topic = zone.ToTopic(Topic.current_humidity);
|
||||||
|
ret.unit_of_measurement = "%";
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Climate ToConfig(this clsThermostat thermostat)
|
public static Climate ToConfig(this clsThermostat thermostat)
|
||||||
{
|
{
|
||||||
Climate ret = new Climate();
|
Climate ret = new Climate();
|
||||||
ret.name = thermostat.Name;
|
ret.name = Global.mqtt_discovery_name_prefix + thermostat.Name;
|
||||||
ret.current_temperature_topic = thermostat.ToTopic(Topic.current_temperature);
|
ret.current_temperature_topic = thermostat.ToTopic(Topic.current_temperature);
|
||||||
|
|
||||||
ret.temperature_low_state_topic = thermostat.ToTopic(Topic.temperature_heat_state);
|
ret.temperature_low_state_topic = thermostat.ToTopic(Topic.temperature_heat_state);
|
||||||
|
@ -208,13 +297,13 @@ namespace OmniLinkBridge.MQTT
|
||||||
|
|
||||||
public static string ToTopic(this clsButton button, Topic topic)
|
public static string ToTopic(this clsButton button, Topic topic)
|
||||||
{
|
{
|
||||||
return $"omnilink/button{button.Number.ToString()}/{topic.ToString()}";
|
return $"{Global.mqtt_prefix}/button{button.Number.ToString()}/{topic.ToString()}";
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Switch ToConfig(this clsButton button)
|
public static Switch ToConfig(this clsButton button)
|
||||||
{
|
{
|
||||||
Switch ret = new Switch();
|
Switch ret = new Switch();
|
||||||
ret.name = button.Name;
|
ret.name = Global.mqtt_discovery_name_prefix + button.Name;
|
||||||
ret.state_topic = button.ToTopic(Topic.state);
|
ret.state_topic = button.ToTopic(Topic.state);
|
||||||
ret.command_topic = button.ToTopic(Topic.command);
|
ret.command_topic = button.ToTopic(Topic.command);
|
||||||
return ret;
|
return ret;
|
||||||
|
|
|
@ -20,7 +20,13 @@ namespace OmniLinkBridge.MQTT
|
||||||
[JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
|
[JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
|
||||||
public DeviceClass? device_class { get; set; }
|
public DeviceClass? device_class { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
|
||||||
|
public string icon { get; set; }
|
||||||
|
|
||||||
[JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
|
[JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
|
||||||
public string unit_of_measurement { get; set; }
|
public string unit_of_measurement { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
|
||||||
|
public string value_template { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,6 +25,8 @@ namespace OmniLinkBridge.MQTT
|
||||||
public static Topic state { get { return new Topic("state"); } }
|
public static Topic state { get { return new Topic("state"); } }
|
||||||
public static Topic command { get { return new Topic("command"); } }
|
public static Topic command { get { return new Topic("command"); } }
|
||||||
|
|
||||||
|
public static Topic basic_state { get { return new Topic("basic_state"); } }
|
||||||
|
|
||||||
public static Topic brightness_state { get { return new Topic("brightness_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 brightness_command { get { return new Topic("brightness_command"); } }
|
||||||
|
|
||||||
|
|
|
@ -23,7 +23,7 @@ namespace OmniLinkBridge.Modules
|
||||||
private OmniLinkII OmniLink { get; set; }
|
private OmniLinkII OmniLink { get; set; }
|
||||||
private IManagedMqttClient MqttClient { get; set; }
|
private IManagedMqttClient MqttClient { get; set; }
|
||||||
|
|
||||||
private Regex regexTopic = new Regex("omnilink/([A-Za-z]+)([0-9]+)/(.*)", RegexOptions.Compiled);
|
private Regex regexTopic = new Regex(Global.mqtt_prefix + "/([A-Za-z]+)([0-9]+)/(.*)", RegexOptions.Compiled);
|
||||||
|
|
||||||
private readonly AutoResetEvent trigger = new AutoResetEvent(false);
|
private readonly AutoResetEvent trigger = new AutoResetEvent(false);
|
||||||
|
|
||||||
|
@ -59,20 +59,20 @@ namespace OmniLinkBridge.Modules
|
||||||
|
|
||||||
MqttClient.ApplicationMessageReceived += MqttClient_ApplicationMessageReceived;
|
MqttClient.ApplicationMessageReceived += MqttClient_ApplicationMessageReceived;
|
||||||
|
|
||||||
MqttClient.SubscribeAsync(new TopicFilterBuilder().WithTopic("omnilink/+/" + Topic.command).Build());
|
MqttClient.SubscribeAsync(new TopicFilterBuilder().WithTopic($"{Global.mqtt_prefix}/+/{Topic.command}").Build());
|
||||||
MqttClient.SubscribeAsync(new TopicFilterBuilder().WithTopic("omnilink/+/" + Topic.brightness_command).Build());
|
MqttClient.SubscribeAsync(new TopicFilterBuilder().WithTopic($"{Global.mqtt_prefix}/+/{Topic.brightness_command}").Build());
|
||||||
MqttClient.SubscribeAsync(new TopicFilterBuilder().WithTopic("omnilink/+/" + Topic.temperature_heat_command).Build());
|
MqttClient.SubscribeAsync(new TopicFilterBuilder().WithTopic($"{Global.mqtt_prefix}/+/{Topic.temperature_heat_command}").Build());
|
||||||
MqttClient.SubscribeAsync(new TopicFilterBuilder().WithTopic("omnilink/+/" + Topic.temperature_cool_command).Build());
|
MqttClient.SubscribeAsync(new TopicFilterBuilder().WithTopic($"{Global.mqtt_prefix}/+/{Topic.temperature_cool_command}").Build());
|
||||||
MqttClient.SubscribeAsync(new TopicFilterBuilder().WithTopic("omnilink/+/" + Topic.humidify_command).Build());
|
MqttClient.SubscribeAsync(new TopicFilterBuilder().WithTopic($"{Global.mqtt_prefix}/+/{Topic.humidify_command}").Build());
|
||||||
MqttClient.SubscribeAsync(new TopicFilterBuilder().WithTopic("omnilink/+/" + Topic.dehumidify_command).Build());
|
MqttClient.SubscribeAsync(new TopicFilterBuilder().WithTopic($"{Global.mqtt_prefix}/+/{Topic.dehumidify_command}").Build());
|
||||||
MqttClient.SubscribeAsync(new TopicFilterBuilder().WithTopic("omnilink/+/" + Topic.mode_command).Build());
|
MqttClient.SubscribeAsync(new TopicFilterBuilder().WithTopic($"{Global.mqtt_prefix}/+/{Topic.mode_command}").Build());
|
||||||
MqttClient.SubscribeAsync(new TopicFilterBuilder().WithTopic("omnilink/+/" + Topic.fan_mode_command).Build());
|
MqttClient.SubscribeAsync(new TopicFilterBuilder().WithTopic($"{Global.mqtt_prefix}/+/{Topic.fan_mode_command}").Build());
|
||||||
MqttClient.SubscribeAsync(new TopicFilterBuilder().WithTopic("omnilink/+/" + Topic.hold_command).Build());
|
MqttClient.SubscribeAsync(new TopicFilterBuilder().WithTopic($"{Global.mqtt_prefix}/+/{Topic.hold_command}").Build());
|
||||||
|
|
||||||
// Wait until shutdown
|
// Wait until shutdown
|
||||||
trigger.WaitOne();
|
trigger.WaitOne();
|
||||||
|
|
||||||
MqttClient.PublishAsync("omnilink/status", "offline", MqttQualityOfServiceLevel.AtMostOnce, true);
|
MqttClient.PublishAsync($"{Global.mqtt_prefix}/status", "offline", MqttQualityOfServiceLevel.AtMostOnce, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void MqttClient_ApplicationMessageReceived(object sender, MqttApplicationMessageReceivedEventArgs e)
|
private void MqttClient_ApplicationMessageReceived(object sender, MqttApplicationMessageReceivedEventArgs e)
|
||||||
|
@ -90,6 +90,10 @@ namespace OmniLinkBridge.Modules
|
||||||
{
|
{
|
||||||
ProcessAreaReceived(OmniLink.Controller.Areas[areaId], match.Groups[3].Value, payload);
|
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 < 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 < OmniLink.Controller.Units.Count)
|
else if (match.Groups[1].Value == "unit" && ushort.TryParse(match.Groups[2].Value, out ushort unitId) && unitId < OmniLink.Controller.Units.Count)
|
||||||
{
|
{
|
||||||
ProcessUnitReceived(OmniLink.Controller.Units[unitId], match.Groups[3].Value, payload);
|
ProcessUnitReceived(OmniLink.Controller.Units[unitId], match.Groups[3].Value, payload);
|
||||||
|
@ -108,38 +112,58 @@ namespace OmniLinkBridge.Modules
|
||||||
{
|
{
|
||||||
if (string.Compare(command, Topic.command.ToString()) == 0)
|
if (string.Compare(command, Topic.command.ToString()) == 0)
|
||||||
{
|
{
|
||||||
switch(payload)
|
if(string.Compare(payload, "arm_home", true) == 0)
|
||||||
{
|
{
|
||||||
case "ARM_HOME":
|
|
||||||
log.Debug("SetArea: " + area.Number + " to home");
|
log.Debug("SetArea: " + area.Number + " to home");
|
||||||
OmniLink.Controller.SendCommand(enuUnitCommand.SecurityDay, 0, (ushort)area.Number);
|
OmniLink.Controller.SendCommand(enuUnitCommand.SecurityDay, 0, (ushort)area.Number);
|
||||||
break;
|
}
|
||||||
case "ARM_AWAY":
|
else if (string.Compare(payload, "arm_away", true) == 0)
|
||||||
|
{
|
||||||
log.Debug("SetArea: " + area.Number + " to away");
|
log.Debug("SetArea: " + area.Number + " to away");
|
||||||
OmniLink.Controller.SendCommand(enuUnitCommand.SecurityAway, 0, (ushort)area.Number);
|
OmniLink.Controller.SendCommand(enuUnitCommand.SecurityAway, 0, (ushort)area.Number);
|
||||||
break;
|
}
|
||||||
case "ARM_NIGHT":
|
else if (string.Compare(payload, "arm_night", true) == 0)
|
||||||
|
{
|
||||||
log.Debug("SetArea: " + area.Number + " to night");
|
log.Debug("SetArea: " + area.Number + " to night");
|
||||||
OmniLink.Controller.SendCommand(enuUnitCommand.SecurityNight, 0, (ushort)area.Number);
|
OmniLink.Controller.SendCommand(enuUnitCommand.SecurityNight, 0, (ushort)area.Number);
|
||||||
break;
|
}
|
||||||
case "DISARM":
|
else if (string.Compare(payload, "disarm", true) == 0)
|
||||||
|
{
|
||||||
log.Debug("SetArea: " + area.Number + " to disarm");
|
log.Debug("SetArea: " + area.Number + " to disarm");
|
||||||
OmniLink.Controller.SendCommand(enuUnitCommand.SecurityOff, 0, (ushort)area.Number);
|
OmniLink.Controller.SendCommand(enuUnitCommand.SecurityOff, 0, (ushort)area.Number);
|
||||||
break;
|
}
|
||||||
|
|
||||||
// The below aren't supported by Home Assistant
|
// The below aren't supported by Home Assistant
|
||||||
case "ARM_HOME_INSTANT":
|
else if (string.Compare(payload, "arm_home_instant", true) == 0)
|
||||||
|
{
|
||||||
log.Debug("SetArea: " + area.Number + " to home instant");
|
log.Debug("SetArea: " + area.Number + " to home instant");
|
||||||
OmniLink.Controller.SendCommand(enuUnitCommand.SecurityDyi, 0, (ushort)area.Number);
|
OmniLink.Controller.SendCommand(enuUnitCommand.SecurityDyi, 0, (ushort)area.Number);
|
||||||
break;
|
}
|
||||||
case "ARM_NIGHT_DELAY":
|
else if (string.Compare(payload, "arm_night_delay", true) == 0)
|
||||||
|
{
|
||||||
log.Debug("SetArea: " + area.Number + " to night delay");
|
log.Debug("SetArea: " + area.Number + " to night delay");
|
||||||
OmniLink.Controller.SendCommand(enuUnitCommand.SecurityNtd, 0, (ushort)area.Number);
|
OmniLink.Controller.SendCommand(enuUnitCommand.SecurityNtd, 0, (ushort)area.Number);
|
||||||
break;
|
}
|
||||||
case "ARM_VACATION":
|
else if (string.Compare(payload, "arm_vacation", true) == 0)
|
||||||
|
{
|
||||||
log.Debug("SetArea: " + area.Number + " to vacation");
|
log.Debug("SetArea: " + area.Number + " to vacation");
|
||||||
OmniLink.Controller.SendCommand(enuUnitCommand.SecurityVac, 0, (ushort)area.Number);
|
OmniLink.Controller.SendCommand(enuUnitCommand.SecurityVac, 0, (ushort)area.Number);
|
||||||
break;
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -232,7 +256,7 @@ namespace OmniLinkBridge.Modules
|
||||||
{
|
{
|
||||||
PublishConfig();
|
PublishConfig();
|
||||||
|
|
||||||
MqttClient.PublishAsync("omnilink/status", "online", MqttQualityOfServiceLevel.AtMostOnce, true);
|
MqttClient.PublishAsync($"{Global.mqtt_prefix}/status", "online", MqttQualityOfServiceLevel.AtMostOnce, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void PublishConfig()
|
private void PublishConfig()
|
||||||
|
@ -254,13 +278,13 @@ namespace OmniLinkBridge.Modules
|
||||||
|
|
||||||
if (area.DefaultProperties == true)
|
if (area.DefaultProperties == true)
|
||||||
{
|
{
|
||||||
MqttClient.PublishAsync($"{Global.mqtt_discovery_prefix}/alarm_control_panel/omnilink/area{i.ToString()}/config", null, MqttQualityOfServiceLevel.AtMostOnce, true);
|
MqttClient.PublishAsync($"{Global.mqtt_discovery_prefix}/alarm_control_panel/{Global.mqtt_prefix}/area{i.ToString()}/config", null, MqttQualityOfServiceLevel.AtMostOnce, true);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
PublishAreaState(area);
|
PublishAreaState(area);
|
||||||
|
|
||||||
MqttClient.PublishAsync($"{Global.mqtt_discovery_prefix}/alarm_control_panel/omnilink/area{i.ToString()}/config",
|
MqttClient.PublishAsync($"{Global.mqtt_discovery_prefix}/alarm_control_panel/{Global.mqtt_prefix}/area{i.ToString()}/config",
|
||||||
JsonConvert.SerializeObject(area.ToConfig()), MqttQualityOfServiceLevel.AtMostOnce, true);
|
JsonConvert.SerializeObject(area.ToConfig()), MqttQualityOfServiceLevel.AtMostOnce, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -275,28 +299,26 @@ namespace OmniLinkBridge.Modules
|
||||||
|
|
||||||
if (zone.DefaultProperties == true || Global.mqtt_discovery_ignore_zones.Contains(zone.Number))
|
if (zone.DefaultProperties == true || Global.mqtt_discovery_ignore_zones.Contains(zone.Number))
|
||||||
{
|
{
|
||||||
MqttClient.PublishAsync($"{Global.mqtt_discovery_prefix}/sensor/omnilink/zone{i.ToString()}/config", null, MqttQualityOfServiceLevel.AtMostOnce, true);
|
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}/binary_sensor/omnilink/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);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
PublishZoneState(zone);
|
PublishZoneState(zone);
|
||||||
|
|
||||||
if (zone.IsTemperatureZone())
|
MqttClient.PublishAsync($"{Global.mqtt_discovery_prefix}/binary_sensor/{Global.mqtt_prefix}/zone{i.ToString()}/config",
|
||||||
{
|
|
||||||
MqttClient.PublishAsync($"{Global.mqtt_discovery_prefix}/sensor/omnilink/zone{i.ToString()}/config",
|
|
||||||
JsonConvert.SerializeObject(zone.ToConfigTemp()), MqttQualityOfServiceLevel.AtMostOnce, true);
|
|
||||||
}
|
|
||||||
else if (zone.IsHumidityZone())
|
|
||||||
{
|
|
||||||
MqttClient.PublishAsync($"{Global.mqtt_discovery_prefix}/sensor/omnilink/zone{i.ToString()}/config",
|
|
||||||
JsonConvert.SerializeObject(zone.ToConfigHumidity()), MqttQualityOfServiceLevel.AtMostOnce, true);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
MqttClient.PublishAsync($"{Global.mqtt_discovery_prefix}/binary_sensor/omnilink/zone{i.ToString()}/config",
|
|
||||||
JsonConvert.SerializeObject(zone.ToConfig()), MqttQualityOfServiceLevel.AtMostOnce, true);
|
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);
|
||||||
|
|
||||||
|
if (zone.IsTemperatureZone())
|
||||||
|
MqttClient.PublishAsync($"{Global.mqtt_discovery_prefix}/sensor/{Global.mqtt_prefix}/zone{i.ToString()}temp/config",
|
||||||
|
JsonConvert.SerializeObject(zone.ToConfigTemp()), MqttQualityOfServiceLevel.AtMostOnce, true);
|
||||||
|
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -312,13 +334,13 @@ namespace OmniLinkBridge.Modules
|
||||||
|
|
||||||
if (unit.DefaultProperties == true || Global.mqtt_discovery_ignore_units.Contains(unit.Number))
|
if (unit.DefaultProperties == true || Global.mqtt_discovery_ignore_units.Contains(unit.Number))
|
||||||
{
|
{
|
||||||
MqttClient.PublishAsync($"{Global.mqtt_discovery_prefix}/{type}/omnilink/unit{i.ToString()}/config", null, MqttQualityOfServiceLevel.AtMostOnce, true);
|
MqttClient.PublishAsync($"{Global.mqtt_discovery_prefix}/{type}/{Global.mqtt_prefix}/unit{i.ToString()}/config", null, MqttQualityOfServiceLevel.AtMostOnce, true);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
PublishUnitState(unit);
|
PublishUnitState(unit);
|
||||||
|
|
||||||
MqttClient.PublishAsync($"{Global.mqtt_discovery_prefix}/{type}/omnilink/unit{i.ToString()}/config",
|
MqttClient.PublishAsync($"{Global.mqtt_discovery_prefix}/{type}/{Global.mqtt_prefix}/unit{i.ToString()}/config",
|
||||||
JsonConvert.SerializeObject(unit.ToConfig()), MqttQualityOfServiceLevel.AtMostOnce, true);
|
JsonConvert.SerializeObject(unit.ToConfig()), MqttQualityOfServiceLevel.AtMostOnce, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -333,14 +355,17 @@ namespace OmniLinkBridge.Modules
|
||||||
|
|
||||||
if (thermostat.DefaultProperties == true)
|
if (thermostat.DefaultProperties == true)
|
||||||
{
|
{
|
||||||
MqttClient.PublishAsync($"{Global.mqtt_discovery_prefix}/climate/omnilink/thermostat{i.ToString()}/config", null, MqttQualityOfServiceLevel.AtMostOnce, 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()}humidity/config", null, MqttQualityOfServiceLevel.AtMostOnce, true);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
PublishThermostatState(thermostat);
|
PublishThermostatState(thermostat);
|
||||||
|
|
||||||
MqttClient.PublishAsync($"{Global.mqtt_discovery_prefix}/climate/omnilink/thermostat{i.ToString()}/config",
|
MqttClient.PublishAsync($"{Global.mqtt_discovery_prefix}/climate/{Global.mqtt_prefix}/thermostat{i.ToString()}/config",
|
||||||
JsonConvert.SerializeObject(thermostat.ToConfig()), MqttQualityOfServiceLevel.AtMostOnce, true);
|
JsonConvert.SerializeObject(thermostat.ToConfig()), 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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -354,14 +379,14 @@ namespace OmniLinkBridge.Modules
|
||||||
|
|
||||||
if (button.DefaultProperties == true)
|
if (button.DefaultProperties == true)
|
||||||
{
|
{
|
||||||
MqttClient.PublishAsync($"{Global.mqtt_discovery_prefix}/switch/omnilink/button{i.ToString()}/config", null, MqttQualityOfServiceLevel.AtMostOnce, true);
|
MqttClient.PublishAsync($"{Global.mqtt_discovery_prefix}/switch/{Global.mqtt_prefix}/button{i.ToString()}/config", null, MqttQualityOfServiceLevel.AtMostOnce, true);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Buttons are always off
|
// Buttons are always off
|
||||||
MqttClient.PublishAsync(button.ToTopic(Topic.state), "OFF", MqttQualityOfServiceLevel.AtMostOnce, true);
|
MqttClient.PublishAsync(button.ToTopic(Topic.state), "OFF", MqttQualityOfServiceLevel.AtMostOnce, true);
|
||||||
|
|
||||||
MqttClient.PublishAsync($"{Global.mqtt_discovery_prefix}/switch/omnilink/button{i.ToString()}/config",
|
MqttClient.PublishAsync($"{Global.mqtt_discovery_prefix}/switch/{Global.mqtt_prefix}/button{i.ToString()}/config",
|
||||||
JsonConvert.SerializeObject(button.ToConfig()), MqttQualityOfServiceLevel.AtMostOnce, true);
|
JsonConvert.SerializeObject(button.ToConfig()), MqttQualityOfServiceLevel.AtMostOnce, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -369,6 +394,31 @@ namespace OmniLinkBridge.Modules
|
||||||
private void Omnilink_OnAreaStatus(object sender, AreaStatusEventArgs e)
|
private void Omnilink_OnAreaStatus(object sender, AreaStatusEventArgs e)
|
||||||
{
|
{
|
||||||
PublishAreaState(e.Area);
|
PublishAreaState(e.Area);
|
||||||
|
|
||||||
|
// Since the controller doesn't fire zone status change on area status change
|
||||||
|
// request update so armed, tripped, and secure statuses are correct
|
||||||
|
for (ushort i = 1; i < OmniLink.Controller.Zones.Count; i++)
|
||||||
|
{
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void HandleRequestZoneStatus(clsOmniLinkMessageQueueItem M, byte[] B, bool Timeout)
|
||||||
|
{
|
||||||
|
if (Timeout)
|
||||||
|
return;
|
||||||
|
|
||||||
|
clsOL2MsgExtendedStatus MSG = new clsOL2MsgExtendedStatus(OmniLink.Controller.Connection, B);
|
||||||
|
|
||||||
|
for (byte i = 0; i < MSG.ZoneStatusCount(); i++)
|
||||||
|
{
|
||||||
|
clsZone zone = OmniLink.Controller.Zones[MSG.ObjectNumber(i)];
|
||||||
|
zone.CopyExtendedStatus(MSG, i);
|
||||||
|
MqttClient.PublishAsync(zone.ToTopic(Topic.state), zone.ToState(), MqttQualityOfServiceLevel.AtMostOnce, true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Omnilink_OnZoneStatus(object sender, ZoneStatusEventArgs e)
|
private void Omnilink_OnZoneStatus(object sender, ZoneStatusEventArgs e)
|
||||||
|
@ -390,11 +440,18 @@ namespace OmniLinkBridge.Modules
|
||||||
private void PublishAreaState(clsArea area)
|
private void PublishAreaState(clsArea area)
|
||||||
{
|
{
|
||||||
MqttClient.PublishAsync(area.ToTopic(Topic.state), area.ToState(), MqttQualityOfServiceLevel.AtMostOnce, true);
|
MqttClient.PublishAsync(area.ToTopic(Topic.state), area.ToState(), MqttQualityOfServiceLevel.AtMostOnce, true);
|
||||||
|
MqttClient.PublishAsync(area.ToTopic(Topic.basic_state), area.ToBasicState(), MqttQualityOfServiceLevel.AtMostOnce, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void PublishZoneState(clsZone zone)
|
private void PublishZoneState(clsZone zone)
|
||||||
{
|
{
|
||||||
MqttClient.PublishAsync(zone.ToTopic(Topic.state), zone.ToState(), MqttQualityOfServiceLevel.AtMostOnce, true);
|
MqttClient.PublishAsync(zone.ToTopic(Topic.state), zone.ToState(), MqttQualityOfServiceLevel.AtMostOnce, true);
|
||||||
|
MqttClient.PublishAsync(zone.ToTopic(Topic.basic_state), zone.ToBasicState(), MqttQualityOfServiceLevel.AtMostOnce, true);
|
||||||
|
|
||||||
|
if(zone.IsTemperatureZone())
|
||||||
|
MqttClient.PublishAsync(zone.ToTopic(Topic.current_temperature), zone.TempText(), MqttQualityOfServiceLevel.AtMostOnce, true);
|
||||||
|
else if (zone.IsHumidityZone())
|
||||||
|
MqttClient.PublishAsync(zone.ToTopic(Topic.current_humidity), zone.TempText(), MqttQualityOfServiceLevel.AtMostOnce, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void PublishUnitState(clsUnit unit)
|
private void PublishUnitState(clsUnit unit)
|
||||||
|
|
|
@ -391,7 +391,7 @@ namespace OmniLinkBridge.Modules
|
||||||
case enuObjectType.Zone:
|
case enuObjectType.Zone:
|
||||||
Controller.Zones.CopyProperties(MSG);
|
Controller.Zones.CopyProperties(MSG);
|
||||||
|
|
||||||
if (Controller.Zones[MSG.ObjectNumber].IsTemperatureZone())
|
if (Controller.Zones[MSG.ObjectNumber].IsTemperatureZone() || Controller.Zones[MSG.ObjectNumber].IsHumidityZone())
|
||||||
Controller.Connection.Send(new clsOL2MsgRequestExtendedStatus(Controller.Connection, enuObjectType.Auxillary, MSG.ObjectNumber, MSG.ObjectNumber), HandleRequestAuxillaryStatus);
|
Controller.Connection.Send(new clsOL2MsgRequestExtendedStatus(Controller.Connection, enuObjectType.Auxillary, MSG.ObjectNumber, MSG.ObjectNumber), HandleRequestAuxillaryStatus);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -36,8 +36,15 @@ mqtt_server =
|
||||||
mqtt_port = 1883
|
mqtt_port = 1883
|
||||||
mqtt_username =
|
mqtt_username =
|
||||||
mqtt_password =
|
mqtt_password =
|
||||||
|
# If you have multiple Omni Controllers you will want to change the
|
||||||
|
# mqtt_prefix and mqtt_discovery_name_prefix to prevent collisions.
|
||||||
|
# Prefix for MQTT state / command topics
|
||||||
|
mqtt_prefix = omnilink
|
||||||
|
# Prefix for Home Assistant discovery
|
||||||
mqtt_discovery_prefix = homeassistant
|
mqtt_discovery_prefix = homeassistant
|
||||||
# specify a range of numbers like 1,2,3,5-10
|
# Prefix for Home Assistant entity names
|
||||||
|
mqtt_discovery_name_prefix =
|
||||||
|
# Specify a range of numbers like 1,2,3,5-10
|
||||||
mqtt_discovery_ignore_zones =
|
mqtt_discovery_ignore_zones =
|
||||||
mqtt_discovery_ignore_units =
|
mqtt_discovery_ignore_units =
|
||||||
# device_class must be battery, door, garage_door, gas, moisture, motion, problem, smoke, or window
|
# device_class must be battery, door, garage_door, gas, moisture, motion, problem, smoke, or window
|
||||||
|
|
|
@ -32,5 +32,5 @@ using System.Runtime.InteropServices;
|
||||||
// You can specify all the values or you can default the Build and Revision Numbers
|
// You can specify all the values or you can default the Build and Revision Numbers
|
||||||
// by using the '*' as shown below:
|
// by using the '*' as shown below:
|
||||||
// [assembly: AssemblyVersion("1.0.*")]
|
// [assembly: AssemblyVersion("1.0.*")]
|
||||||
[assembly: AssemblyVersion("1.1.1.0")]
|
[assembly: AssemblyVersion("1.1.2.0")]
|
||||||
[assembly: AssemblyFileVersion("1.1.1.0")]
|
[assembly: AssemblyFileVersion("1.1.2.0")]
|
||||||
|
|
|
@ -55,7 +55,13 @@ namespace OmniLinkBridge
|
||||||
Global.mqtt_port = ValidatePort(settings, "mqtt_port");
|
Global.mqtt_port = ValidatePort(settings, "mqtt_port");
|
||||||
Global.mqtt_username = settings["mqtt_username"];
|
Global.mqtt_username = settings["mqtt_username"];
|
||||||
Global.mqtt_password = settings["mqtt_password"];
|
Global.mqtt_password = settings["mqtt_password"];
|
||||||
Global.mqtt_discovery_prefix = settings["mqtt_discovery_prefix"];
|
Global.mqtt_prefix = settings["mqtt_prefix"] ?? "omnilink";
|
||||||
|
Global.mqtt_discovery_prefix = settings["mqtt_discovery_prefix"] ?? "homeassistant";
|
||||||
|
Global.mqtt_discovery_name_prefix = settings["mqtt_discovery_name_prefix"] ?? string.Empty;
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(Global.mqtt_discovery_name_prefix))
|
||||||
|
Global.mqtt_discovery_name_prefix = Global.mqtt_discovery_name_prefix + " ";
|
||||||
|
|
||||||
Global.mqtt_discovery_ignore_zones = ValidateRange(settings, "mqtt_discovery_ignore_zones");
|
Global.mqtt_discovery_ignore_zones = ValidateRange(settings, "mqtt_discovery_ignore_zones");
|
||||||
Global.mqtt_discovery_ignore_units = ValidateRange(settings, "mqtt_discovery_ignore_units");
|
Global.mqtt_discovery_ignore_units = ValidateRange(settings, "mqtt_discovery_ignore_units");
|
||||||
Global.mqtt_discovery_override_zone = LoadOverrideZone(settings, "mqtt_discovery_override_zone");
|
Global.mqtt_discovery_override_zone = LoadOverrideZone(settings, "mqtt_discovery_override_zone");
|
||||||
|
|
50
README.md
50
README.md
|
@ -1,8 +1,8 @@
|
||||||
# OmniLink Bridge
|
# OmniLink Bridge
|
||||||
Provides time sync, logging, web service API, and MQTT bridge for HAI/Leviton OmniPro II controllers
|
Provides time sync, logging, web service API, and MQTT bridge for HAI/Leviton OmniPro II controllers. Provides integration with Samsung SmarthThings via Web Service API and Home Assistant via MQTT.
|
||||||
|
|
||||||
## Download
|
## Download
|
||||||
You can download the [binary here](http://www.excalibur-partners.com/downloads/OmniLinkBridge_1_1_1.zip) or use docker to build an image from git.
|
You can download the [binary here](http://www.excalibur-partners.com/downloads/OmniLinkBridge_1_1_2.zip) or use docker to build an image from git.
|
||||||
|
|
||||||
## Requirements
|
## Requirements
|
||||||
- .NET Framework 4.5.2 (or Mono equivalent)
|
- .NET Framework 4.5.2 (or Mono equivalent)
|
||||||
|
@ -53,7 +53,7 @@ You can download the [binary here](http://www.excalibur-partners.com/downloads/O
|
||||||
- cp OmniLinkBridge/OmniLinkBridge.ini /opt/omnilink-bridge
|
- cp OmniLinkBridge/OmniLinkBridge.ini /opt/omnilink-bridge
|
||||||
- vim /opt/omnilink-bridge/OmniLinkBridge.ini
|
- vim /opt/omnilink-bridge/OmniLinkBridge.ini
|
||||||
3. Start docker container
|
3. Start docker container
|
||||||
- docker run -d --name="omnilink-bridge" -v /opt/omnilink-bridge:/config --net=host --restart unless-stopped omnilink-bridge
|
- docker run -d --name="omnilink-bridge" -v /opt/omnilink-bridge:/config -v /etc/localtime:/etc/localtime:ro --net=host --restart unless-stopped omnilink-bridge
|
||||||
4. Verify connectivity by looking at logs
|
4. Verify connectivity by looking at logs
|
||||||
- docker container logs omnilink-bridge
|
- docker container logs omnilink-bridge
|
||||||
|
|
||||||
|
@ -86,12 +86,38 @@ To test the API you can use your browser to view a page or PowerShell (see below
|
||||||
## MQTT
|
## MQTT
|
||||||
This module will also publish discovery topics for Home Assistant to auto configure devices.
|
This module will also publish discovery topics for Home Assistant to auto configure devices.
|
||||||
|
|
||||||
|
### Areas
|
||||||
|
```
|
||||||
SUB omnilink/areaX/state
|
SUB omnilink/areaX/state
|
||||||
|
string triggered, pending, armed_night, armed_night_delay, armed_home, armed_home_instant, armed_away, armed_vacation, disarmed
|
||||||
|
|
||||||
|
SUB omnilink/areaX/basic_state
|
||||||
string triggered, pending, armed_night, armed_home, armed_away, disarmed
|
string triggered, pending, armed_night, armed_home, armed_away, disarmed
|
||||||
|
|
||||||
PUB omnilink/areaX/command
|
PUB omnilink/areaX/command
|
||||||
string ARM_HOME, ARM_AWAY, ARM_NIGHT, DISARM, ARM_HOME_INSTANT, ARM_NIGHT_DELAY, ARM_VACATION
|
string(insensitive) arm_home, arm_away, arm_night, disarm, arm_home_instant, arm_night_delay, arm_vacation
|
||||||
|
```
|
||||||
|
|
||||||
|
### Zones
|
||||||
|
```
|
||||||
|
SUB omnilink/zoneX/state
|
||||||
|
string secure, not_ready, trouble, armed, tripped, bypassed
|
||||||
|
|
||||||
|
SUB omnilink/zoneX/basic_state
|
||||||
|
string OFF, ON
|
||||||
|
|
||||||
|
SUB omnilink/zoneX/current_temperature (optional)
|
||||||
|
int Current temperature in degrees fahrenheit
|
||||||
|
|
||||||
|
SUB omnilink/zoneX/current_humidity (optional)
|
||||||
|
int Current relative humidity
|
||||||
|
|
||||||
|
PUB omnilink/zoneX/command
|
||||||
|
string(insensitive) bypass, restore
|
||||||
|
```
|
||||||
|
|
||||||
|
### Units
|
||||||
|
```
|
||||||
SUB omnilink/unitX/state
|
SUB omnilink/unitX/state
|
||||||
PUB omnilink/unitX/command
|
PUB omnilink/unitX/command
|
||||||
string OFF, ON
|
string OFF, ON
|
||||||
|
@ -99,7 +125,10 @@ string OFF, ON
|
||||||
SUB omnilink/unitX/brightness_state
|
SUB omnilink/unitX/brightness_state
|
||||||
PUB omnilink/unitX/brightness_command
|
PUB omnilink/unitX/brightness_command
|
||||||
int Level from 0 to 100 percent
|
int Level from 0 to 100 percent
|
||||||
|
```
|
||||||
|
|
||||||
|
### Thermostats
|
||||||
|
```
|
||||||
SUB omnilink/thermostatX/current_operation
|
SUB omnilink/thermostatX/current_operation
|
||||||
string idle, cool, heat
|
string idle, cool, heat
|
||||||
|
|
||||||
|
@ -132,14 +161,27 @@ string auto, on, cycle
|
||||||
SUB omnilink/thermostatX/hold_state
|
SUB omnilink/thermostatX/hold_state
|
||||||
PUB omnilink/thermostatX/hold_command
|
PUB omnilink/thermostatX/hold_command
|
||||||
string off, hold
|
string off, hold
|
||||||
|
```
|
||||||
|
|
||||||
|
### Buttons
|
||||||
|
```
|
||||||
SUB omnilink/buttonX/state
|
SUB omnilink/buttonX/state
|
||||||
string OFF
|
string OFF
|
||||||
|
|
||||||
PUB omnilink/buttonX/command
|
PUB omnilink/buttonX/command
|
||||||
string ON
|
string ON
|
||||||
|
```
|
||||||
|
|
||||||
## Change Log
|
## Change Log
|
||||||
|
Version 1.1.2 - 2018-10-23
|
||||||
|
- Add min and max climate temperatures
|
||||||
|
- Update docker run command to use local time zone
|
||||||
|
- Improve area and zone MQTT support
|
||||||
|
- Add option to change MQTT prefix to support multiple instances
|
||||||
|
- Add detailed zone sensor and thermostat humidity sensor
|
||||||
|
- Add prefix for MQTT discovery entity name
|
||||||
|
- Request zone status update on area status change
|
||||||
|
|
||||||
Version 1.1.1 - 2018-10-18
|
Version 1.1.1 - 2018-10-18
|
||||||
- Added docker support
|
- Added docker support
|
||||||
- Save subscriptions on change
|
- Save subscriptions on change
|
||||||
|
|
Loading…
Reference in a new issue