- Add Home Assistant MQTT device registry support

This commit is contained in:
Ryan Wagoner 2019-11-05 22:47:24 -05:00
parent a1b15cd08b
commit a891363539
6 changed files with 67 additions and 19 deletions

View file

@ -1,4 +1,5 @@
using Newtonsoft.Json; using Newtonsoft.Json;
using OmniLinkBridge.Modules;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
@ -9,11 +10,16 @@ namespace OmniLinkBridge.MQTT
{ {
public class Device public class Device
{ {
public string unique_id { get; set; }
public string name { get; set; } public string name { get; set; }
[JsonProperty(NullValueHandling = NullValueHandling.Ignore)] [JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
public string state_topic { get; set; } public string state_topic { get; set; }
public string availability_topic { get; set; } = $"{Global.mqtt_prefix}/status"; public string availability_topic { get; set; } = $"{Global.mqtt_prefix}/status";
[JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
public DeviceRegistry device { get; set; } = MQTTModule.MqttDeviceRegistry;
} }
} }

View file

@ -0,0 +1,17 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace OmniLinkBridge.MQTT
{
public class DeviceRegistry
{
public string identifiers { get; set; }
public string name { get; set; }
public string sw_version { get; set; }
public string model { get; set; }
public string manufacturer { get; set; }
}
}

View file

@ -18,6 +18,7 @@ namespace OmniLinkBridge.MQTT
public static Alarm ToConfig(this clsArea area) public static Alarm ToConfig(this clsArea area)
{ {
Alarm ret = new Alarm(); Alarm ret = new Alarm();
ret.unique_id = $"{Global.mqtt_prefix}area{area.Number.ToString()}";
ret.name = Global.mqtt_discovery_name_prefix + area.Name; ret.name = Global.mqtt_discovery_name_prefix + area.Name;
ret.state_topic = area.ToTopic(Topic.basic_state); ret.state_topic = area.ToTopic(Topic.basic_state);
ret.command_topic = area.ToTopic(Topic.command); ret.command_topic = area.ToTopic(Topic.command);
@ -82,6 +83,7 @@ namespace OmniLinkBridge.MQTT
public static BinarySensor ToConfigBurglary(this clsArea area) public static BinarySensor ToConfigBurglary(this clsArea area)
{ {
BinarySensor ret = new BinarySensor(); BinarySensor ret = new BinarySensor();
ret.unique_id = $"{Global.mqtt_prefix}area{area.Number.ToString()}burglary";
ret.name = $"{Global.mqtt_discovery_name_prefix}{area.Name} Burglary"; ret.name = $"{Global.mqtt_discovery_name_prefix}{area.Name} Burglary";
ret.device_class = BinarySensor.DeviceClass.safety; ret.device_class = BinarySensor.DeviceClass.safety;
ret.state_topic = area.ToTopic(Topic.json_state); ret.state_topic = area.ToTopic(Topic.json_state);
@ -92,6 +94,7 @@ namespace OmniLinkBridge.MQTT
public static BinarySensor ToConfigFire(this clsArea area) public static BinarySensor ToConfigFire(this clsArea area)
{ {
BinarySensor ret = new BinarySensor(); BinarySensor ret = new BinarySensor();
ret.unique_id = $"{Global.mqtt_prefix}area{area.Number.ToString()}fire";
ret.name = $"{Global.mqtt_discovery_name_prefix}{area.Name} Fire"; ret.name = $"{Global.mqtt_discovery_name_prefix}{area.Name} Fire";
ret.device_class = BinarySensor.DeviceClass.smoke; ret.device_class = BinarySensor.DeviceClass.smoke;
ret.state_topic = area.ToTopic(Topic.json_state); ret.state_topic = area.ToTopic(Topic.json_state);
@ -102,6 +105,7 @@ namespace OmniLinkBridge.MQTT
public static BinarySensor ToConfigGas(this clsArea area) public static BinarySensor ToConfigGas(this clsArea area)
{ {
BinarySensor ret = new BinarySensor(); BinarySensor ret = new BinarySensor();
ret.unique_id = $"{Global.mqtt_prefix}area{area.Number.ToString()}gas";
ret.name = $"{Global.mqtt_discovery_name_prefix}{area.Name} Gas"; ret.name = $"{Global.mqtt_discovery_name_prefix}{area.Name} Gas";
ret.device_class = BinarySensor.DeviceClass.gas; ret.device_class = BinarySensor.DeviceClass.gas;
ret.state_topic = area.ToTopic(Topic.json_state); ret.state_topic = area.ToTopic(Topic.json_state);
@ -112,6 +116,7 @@ namespace OmniLinkBridge.MQTT
public static BinarySensor ToConfigAux(this clsArea area) public static BinarySensor ToConfigAux(this clsArea area)
{ {
BinarySensor ret = new BinarySensor(); BinarySensor ret = new BinarySensor();
ret.unique_id = $"{Global.mqtt_prefix}area{area.Number.ToString()}auxiliary";
ret.name = $"{Global.mqtt_discovery_name_prefix}{area.Name} Auxiliary"; ret.name = $"{Global.mqtt_discovery_name_prefix}{area.Name} Auxiliary";
ret.device_class = BinarySensor.DeviceClass.problem; ret.device_class = BinarySensor.DeviceClass.problem;
ret.state_topic = area.ToTopic(Topic.json_state); ret.state_topic = area.ToTopic(Topic.json_state);
@ -122,6 +127,7 @@ namespace OmniLinkBridge.MQTT
public static BinarySensor ToConfigFreeze(this clsArea area) public static BinarySensor ToConfigFreeze(this clsArea area)
{ {
BinarySensor ret = new BinarySensor(); BinarySensor ret = new BinarySensor();
ret.unique_id = $"{Global.mqtt_prefix}area{area.Number.ToString()}freeze";
ret.name = $"{Global.mqtt_discovery_name_prefix}{area.Name} Freeze"; ret.name = $"{Global.mqtt_discovery_name_prefix}{area.Name} Freeze";
ret.device_class = BinarySensor.DeviceClass.cold; ret.device_class = BinarySensor.DeviceClass.cold;
ret.state_topic = area.ToTopic(Topic.json_state); ret.state_topic = area.ToTopic(Topic.json_state);
@ -132,6 +138,7 @@ namespace OmniLinkBridge.MQTT
public static BinarySensor ToConfigWater(this clsArea area) public static BinarySensor ToConfigWater(this clsArea area)
{ {
BinarySensor ret = new BinarySensor(); BinarySensor ret = new BinarySensor();
ret.unique_id = $"{Global.mqtt_prefix}area{area.Number.ToString()}water";
ret.name = $"{Global.mqtt_discovery_name_prefix}{area.Name} Water"; ret.name = $"{Global.mqtt_discovery_name_prefix}{area.Name} Water";
ret.device_class = BinarySensor.DeviceClass.moisture; ret.device_class = BinarySensor.DeviceClass.moisture;
ret.state_topic = area.ToTopic(Topic.json_state); ret.state_topic = area.ToTopic(Topic.json_state);
@ -142,6 +149,7 @@ namespace OmniLinkBridge.MQTT
public static BinarySensor ToConfigDuress(this clsArea area) public static BinarySensor ToConfigDuress(this clsArea area)
{ {
BinarySensor ret = new BinarySensor(); BinarySensor ret = new BinarySensor();
ret.unique_id = $"{Global.mqtt_prefix}area{area.Number.ToString()}duress";
ret.name = $"{Global.mqtt_discovery_name_prefix}{area.Name} Duress"; ret.name = $"{Global.mqtt_discovery_name_prefix}{area.Name} Duress";
ret.device_class = BinarySensor.DeviceClass.safety; ret.device_class = BinarySensor.DeviceClass.safety;
ret.state_topic = area.ToTopic(Topic.json_state); ret.state_topic = area.ToTopic(Topic.json_state);
@ -152,6 +160,7 @@ namespace OmniLinkBridge.MQTT
public static BinarySensor ToConfigTemp(this clsArea area) public static BinarySensor ToConfigTemp(this clsArea area)
{ {
BinarySensor ret = new BinarySensor(); BinarySensor ret = new BinarySensor();
ret.unique_id = $"{Global.mqtt_prefix}area{area.Number.ToString()}temp";
ret.name = $"{Global.mqtt_discovery_name_prefix}{area.Name} Temp"; ret.name = $"{Global.mqtt_discovery_name_prefix}{area.Name} Temp";
ret.device_class = BinarySensor.DeviceClass.heat; ret.device_class = BinarySensor.DeviceClass.heat;
ret.state_topic = area.ToTopic(Topic.json_state); ret.state_topic = area.ToTopic(Topic.json_state);
@ -211,6 +220,7 @@ namespace OmniLinkBridge.MQTT
public static Sensor ToConfigTemp(this clsZone zone, enuTempFormat format) public static Sensor ToConfigTemp(this clsZone zone, enuTempFormat format)
{ {
Sensor ret = new Sensor(); Sensor ret = new Sensor();
ret.unique_id = $"{Global.mqtt_prefix}zone{zone.Number.ToString()}temp";
ret.name = $"{Global.mqtt_discovery_name_prefix}{zone.Name} Temp"; 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.current_temperature); ret.state_topic = zone.ToTopic(Topic.current_temperature);
@ -221,6 +231,7 @@ 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.unique_id = $"{Global.mqtt_prefix}zone{zone.Number.ToString()}humidity";
ret.name = $"{Global.mqtt_discovery_name_prefix}{zone.Name} Humidity"; 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.current_humidity); ret.state_topic = zone.ToTopic(Topic.current_humidity);
@ -231,6 +242,7 @@ namespace OmniLinkBridge.MQTT
public static Sensor ToConfigSensor(this clsZone zone) public static Sensor ToConfigSensor(this clsZone zone)
{ {
Sensor ret = new Sensor(); Sensor ret = new Sensor();
ret.unique_id = $"{Global.mqtt_prefix}zone{zone.Number.ToString()}";
ret.name = Global.mqtt_discovery_name_prefix + zone.Name; ret.name = Global.mqtt_discovery_name_prefix + zone.Name;
switch (zone.ZoneType) switch (zone.ZoneType)
@ -270,6 +282,7 @@ namespace OmniLinkBridge.MQTT
public static BinarySensor ToConfig(this clsZone zone) public static BinarySensor ToConfig(this clsZone zone)
{ {
BinarySensor ret = new BinarySensor(); BinarySensor ret = new BinarySensor();
ret.unique_id = $"{Global.mqtt_prefix}zone{zone.Number.ToString()}binary";
ret.name = Global.mqtt_discovery_name_prefix + 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);
@ -342,6 +355,7 @@ namespace OmniLinkBridge.MQTT
public static Light ToConfig(this clsUnit unit) public static Light ToConfig(this clsUnit unit)
{ {
Light ret = new Light(); Light ret = new Light();
ret.unique_id = $"{Global.mqtt_prefix}unit{unit.Number.ToString()}light";
ret.name = Global.mqtt_discovery_name_prefix + 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);
@ -353,6 +367,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.unique_id = $"{Global.mqtt_prefix}unit{unit.Number.ToString()}switch";
ret.name = Global.mqtt_discovery_name_prefix + 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);
@ -379,22 +394,24 @@ namespace OmniLinkBridge.MQTT
return $"{Global.mqtt_prefix}/thermostat{thermostat.Number.ToString()}/{topic.ToString()}"; return $"{Global.mqtt_prefix}/thermostat{thermostat.Number.ToString()}/{topic.ToString()}";
} }
public static Sensor ToConfigTemp(this clsThermostat zone, enuTempFormat format) public static Sensor ToConfigTemp(this clsThermostat thermostat, enuTempFormat format)
{ {
Sensor ret = new Sensor(); Sensor ret = new Sensor();
ret.name = $"{Global.mqtt_discovery_name_prefix}{zone.Name} Temp"; ret.unique_id = $"{Global.mqtt_prefix}thermostat{thermostat.Number.ToString()}temp";
ret.name = $"{Global.mqtt_discovery_name_prefix}{thermostat.Name} Temp";
ret.device_class = Sensor.DeviceClass.temperature; ret.device_class = Sensor.DeviceClass.temperature;
ret.state_topic = zone.ToTopic(Topic.current_temperature); ret.state_topic = thermostat.ToTopic(Topic.current_temperature);
ret.unit_of_measurement = (format == enuTempFormat.Fahrenheit ? "°F" : "°C"); ret.unit_of_measurement = (format == enuTempFormat.Fahrenheit ? "°F" : "°C");
return ret; return ret;
} }
public static Sensor ToConfigHumidity(this clsThermostat zone) public static Sensor ToConfigHumidity(this clsThermostat thermostat)
{ {
Sensor ret = new Sensor(); Sensor ret = new Sensor();
ret.name = $"{Global.mqtt_discovery_name_prefix}{zone.Name} Humidity"; ret.unique_id = $"{Global.mqtt_prefix}thermostat{thermostat.Number.ToString()}humidity";
ret.name = $"{Global.mqtt_discovery_name_prefix}{thermostat.Name} Humidity";
ret.device_class = Sensor.DeviceClass.humidity; ret.device_class = Sensor.DeviceClass.humidity;
ret.state_topic = zone.ToTopic(Topic.current_humidity); ret.state_topic = thermostat.ToTopic(Topic.current_humidity);
ret.unit_of_measurement = "%"; ret.unit_of_measurement = "%";
return ret; return ret;
} }
@ -409,6 +426,7 @@ namespace OmniLinkBridge.MQTT
ret.max_temp = "35"; ret.max_temp = "35";
} }
ret.unique_id = $"{Global.mqtt_prefix}thermostat{thermostat.Number.ToString()}";
ret.name = Global.mqtt_discovery_name_prefix + 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);
@ -449,6 +467,7 @@ namespace OmniLinkBridge.MQTT
public static Switch ToConfig(this clsButton button) public static Switch ToConfig(this clsButton button)
{ {
Switch ret = new Switch(); Switch ret = new Switch();
ret.unique_id = $"{Global.mqtt_prefix}button{button.Number.ToString()}";
ret.name = Global.mqtt_discovery_name_prefix + 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);

View file

@ -20,6 +20,8 @@ namespace OmniLinkBridge.Modules
{ {
private static ILog log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); private static ILog log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
public static DeviceRegistry MqttDeviceRegistry { get; set; }
private OmniLinkII OmniLink { get; set; } private OmniLinkII OmniLink { get; set; }
private IManagedMqttClient MqttClient { get; set; } private IManagedMqttClient MqttClient { get; set; }
private bool ControllerConnected { get; set; } private bool ControllerConnected { get; set; }
@ -57,6 +59,15 @@ namespace OmniLinkBridge.Modules
{ {
log.Debug("Connected"); log.Debug("Connected");
MqttDeviceRegistry = new DeviceRegistry()
{
identifiers = Global.mqtt_prefix,
name = Global.mqtt_prefix,
sw_version = $"{OmniLink.Controller.GetVersionText()} - OmniLinkBridge {Assembly.GetExecutingAssembly().GetName().Version.ToString()}",
model = OmniLink.Controller.GetModelText(),
manufacturer = "Leviton"
};
// For the initial connection wait for the controller connected event to publish config // For the initial connection wait for the controller connected event to publish config
// For subsequent connections publish config immediately // For subsequent connections publish config immediately
if(ControllerConnected) if(ControllerConnected)

View file

@ -81,6 +81,7 @@
<Compile Include="MQTT\BinarySensor.cs" /> <Compile Include="MQTT\BinarySensor.cs" />
<Compile Include="MQTT\Device.cs" /> <Compile Include="MQTT\Device.cs" />
<Compile Include="MQTT\Climate.cs" /> <Compile Include="MQTT\Climate.cs" />
<Compile Include="MQTT\DeviceRegistry.cs" />
<Compile Include="MQTT\OverrideZone.cs" /> <Compile Include="MQTT\OverrideZone.cs" />
<Compile Include="MQTT\Switch.cs" /> <Compile Include="MQTT\Switch.cs" />
<Compile Include="MQTT\Light.cs" /> <Compile Include="MQTT\Light.cs" />

View file

@ -85,15 +85,7 @@ To test the API you can use your browser to view a page or PowerShell (see below
- Invoke-WebRequest -Uri "http://localhost:8000/SetUnit" -Method POST -ContentType "application/json" -Body (convertto-json -InputObject @{"id"=1;"value"=100}) -UseBasicParsing - Invoke-WebRequest -Uri "http://localhost:8000/SetUnit" -Method POST -ContentType "application/json" -Body (convertto-json -InputObject @{"id"=1;"value"=100}) -UseBasicParsing
## MQTT ## MQTT
This module will also publish discovery topics for Home Assistant to auto configure devices. As of writing you will need to add a custom_component override in your Home Assistant config directory for the following pull requests. This module will also publish discovery topics for Home Assistant to auto configure devices.
- [Add target temperature low high to MQTT climate](https://github.com/home-assistant/home-assistant/pull/17391/)
- [Add night arm mode to MQTT alarm control panel](https://github.com/home-assistant/home-assistant/pull/17390/)
```
mkdir -p custom_components/mqtt
wget https://raw.githubusercontent.com/home-assistant/home-assistant/dcfcca77d72b0c35cda9950a69f621b4e8cff81b/homeassistant/components/climate/mqtt.py -O custom_components/mqtt/climate.py
wget https://raw.githubusercontent.com/home-assistant/home-assistant/fa2510f58b40cfea2974530658ee011d984db6c7/homeassistant/components/alarm_control_panel/mqtt.py -O custom_components/mqtt/alarm_control_panel.py
```
### Areas ### Areas
``` ```
@ -182,12 +174,14 @@ string ON
``` ```
## Change Log ## Change Log
Version 1.1.4 - 2019-10-28 Version 1.1.4 - 2019-11-06
- Utilize controller temperature format - Utilize controller temperature format
- Ignore invalid temperature for thermostats - Don't publish invalid thermostat temperatures
- Always enable first area to fix Omni LTe and Omni IIe - Always enable first area to support Omni LTe and Omni IIe
- Fix MQTT id validation and add notice for areas - Fix MQTT id validation and add notice for publishing to area 0
- Fix missing last area, zone, unit, thermostat, and button
- Fix compatibility with Home Assistant 0.95.4 MQTT extra keys - Fix compatibility with Home Assistant 0.95.4 MQTT extra keys
- Add Home Assistant MQTT device registry support
Version 1.1.3 - 2019-02-10 Version 1.1.3 - 2019-02-10
- Publish config when reconnecting to MQTT - Publish config when reconnecting to MQTT