-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
The discovery logic is implemented and presents and interface that the modules need to implement in order to get their entities being exported to Home Assistant
- Loading branch information
1 parent
5c1a8d4
commit 888f259
Showing
4 changed files
with
261 additions
and
6 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,126 @@ | ||
package homeassistant | ||
|
||
// Interface to expose the endpoints to update any MQTT config needed by the | ||
// Home Assistant discovery package. | ||
type MqttConfig interface { | ||
// Returns a pointer to the device object for any modification required. | ||
GetDevice() *Device | ||
// Adds a new entry on the list of Availability topics. | ||
AddAvailability(Availability) MqttConfig | ||
// Get name of the entity. | ||
GetName() string | ||
// Set name for the entity. | ||
SetName(string) MqttConfig | ||
} | ||
|
||
// Structure that encapsulates the information for the device exposed in | ||
// Home Assistant. | ||
type Device struct { | ||
ConfigurationUrl string `json:"configuration_url"` | ||
Identifiers []string `json:"identifiers"` | ||
Manufacturer string `json:"manufacturer"` | ||
Model string `json:"model"` | ||
Name string `json:"name"` | ||
} | ||
|
||
// Structure that encapsulates the information to retrieve availability of | ||
// devices and entities. | ||
type Availability struct { | ||
Topic string `json:"topic"` | ||
PayloadAvailable string `json:"payload_available,omitempty"` | ||
PayloadNotAvailable string `json:"payload_not_available,omitempty"` | ||
} | ||
|
||
// Base config for all MQTT discovery configs. | ||
type BaseConfig struct { | ||
Device Device `json:"device"` | ||
Name string `json:"name"` | ||
UniqueId string `json:"unique_id"` | ||
Retain bool `json:"retain"` | ||
Availability []Availability `json:"availability"` | ||
AvailabilityMode string `json:"availability_mode"` | ||
QoS int `json:"qos"` | ||
} | ||
|
||
// Returns a pointer to the device object. | ||
func (c *BaseConfig) GetDevice() *Device { | ||
return &c.Device | ||
} | ||
|
||
// Adds a new entry on the list of Availability topics. | ||
func (c *BaseConfig) AddAvailability(availability Availability) MqttConfig { | ||
c.Availability = append(c.Availability, availability) | ||
return c | ||
} | ||
|
||
// Get the name of the entity in the configuration. | ||
func (c *BaseConfig) GetName() string { | ||
return c.Name | ||
} | ||
|
||
// Set the name for the entity in the configuration. | ||
func (c *BaseConfig) SetName(name string) MqttConfig { | ||
c.Name = name | ||
return c | ||
} | ||
|
||
// Light configuration: | ||
// https://www.home-assistant.io/integrations/light.mqtt/ | ||
type LightMqttConfig struct { | ||
BaseConfig | ||
CommandTopic string `json:"command_topic,omitempty"` | ||
StateTopic string `json:"state_topic,omitempty"` | ||
PayloadOn string `json:"payload_on,omitempty"` | ||
PayloadOff string `json:"payload_off,omitempty"` | ||
OnCommandType string `json:"on_command_type,omitempty"` | ||
BrightnessScale int `json:"brigthness_scale,omitempty"` | ||
BrightnessStateTopic string `json:"brightness_state_topic,omitempty"` | ||
BrightnessCommandTopic string `json:"brightness_command_topic,omitempty"` | ||
} | ||
|
||
// Cover configuration: | ||
// https://www.home-assistant.io/integrations/cover.mqtt/ | ||
type CoverConfig struct { | ||
BaseConfig | ||
StateTopic string `json:"state_topic,omitempty"` | ||
StateClosed string `json:"state_closed,omitempty"` | ||
StateOpen string `json:"state_open,omitempty"` | ||
CommandTopic string `json:"command_topic,omitempty"` | ||
PayloadClose string `json:"payload_close,omitempty"` | ||
PayloadOpen string `json:"payload_open,omitempty"` | ||
PayloadStop string `json:"payload_stop,omitempty"` | ||
PositionTopic string `json:"position_topic,omitempty"` | ||
SetPositionTopic string `json:"set_position_topic,omitempty"` | ||
PositionTemplate string `json:"position_template,omitempty"` | ||
} | ||
|
||
// Sensor configuration: | ||
// https://www.home-assistant.io/integrations/sensor.mqtt/ | ||
type SensorConfig struct { | ||
BaseConfig | ||
StateTopic string `json:"state_topic,omitempty"` | ||
UnitOfMeasurement string `json:"unit_of_measurement,omitempty"` | ||
DeviceClass string `json:"device_class,omitempty"` | ||
Icon string `json:"icon,omitempty"` | ||
} | ||
|
||
// Scene configuration: | ||
// https://www.home-assistant.io/integrations/scene.mqtt/ | ||
type SceneConfig struct { | ||
BaseConfig | ||
CommandTopic string `json:"command_topic,omitempty"` | ||
PayloadOn string `json:"payload_on,omitempty"` | ||
Icon string `json:"icon,omitempty"` | ||
EnabledByDefault bool `json:"enabled_by_default,omitempty"` | ||
} | ||
|
||
// Device Trigger configuration: | ||
// https://www.home-assistant.io/integrations/device_trigger.mqtt/ | ||
type DeviceTriggerConfig struct { | ||
BaseConfig | ||
AutomationType string `json:"automation_type"` | ||
Payload string `json:"payload,omitempty"` | ||
Topic string `json:"topic"` | ||
Type string `json:"type"` | ||
Subtype string `json:"subtype"` | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,97 @@ | ||
package homeassistant | ||
|
||
import ( | ||
"encoding/json" | ||
"fmt" | ||
"path" | ||
|
||
"github.com/gaetancollaud/digitalstrom-mqtt/pkg/config" | ||
"github.com/gaetancollaud/digitalstrom-mqtt/pkg/mqtt" | ||
"github.com/gaetancollaud/digitalstrom-mqtt/pkg/utils" | ||
) | ||
|
||
type Domain string | ||
|
||
const ( | ||
Sensor Domain = "sensor" | ||
Light Domain = "light" | ||
DeviceAutomation Domain = "device_automation" | ||
Cover Domain = "cover" | ||
) | ||
|
||
type DiscoveryConfig struct { | ||
Domain Domain | ||
DeviceId string | ||
ObjectId string | ||
Config MqttConfig | ||
} | ||
|
||
type HomeAssistantDiscoveryInterface interface { | ||
// Returns the list of Home Assitant MQTT entities that each module would | ||
// be exporting for discovery. | ||
// This will be run after the method Start is called and therefore it can | ||
// assume that the logic there will be run. | ||
GetHomeAssistantEntities() ([]DiscoveryConfig, error) | ||
} | ||
|
||
type HomeAssistantDiscovery struct { | ||
mqttClient mqtt.Client | ||
config *config.ConfigHomeAssistant | ||
|
||
discoveryConfigs []DiscoveryConfig | ||
} | ||
|
||
func NewHomeAssistantDiscovery(mqttClient mqtt.Client, config *config.ConfigHomeAssistant) *HomeAssistantDiscovery { | ||
return &HomeAssistantDiscovery{ | ||
mqttClient: mqttClient, | ||
config: config, | ||
discoveryConfigs: []DiscoveryConfig{}, | ||
} | ||
} | ||
|
||
func (hass *HomeAssistantDiscovery) AddConfigs(configs []DiscoveryConfig) { | ||
systemAvailability := Availability{ | ||
Topic: hass.mqttClient.ServerStatusTopic(), | ||
PayloadAvailable: mqtt.Online, | ||
PayloadNotAvailable: mqtt.Offline, | ||
} | ||
for _, config := range configs { | ||
entityName := config.Config.GetName() | ||
config.Config. | ||
SetName( | ||
utils.RemoveRegexp( | ||
entityName, | ||
hass.config.RemoveRegexpFromName)). | ||
AddAvailability(systemAvailability) | ||
// Update the config with some generic attributes for all | ||
// configurations. | ||
device := config.Config.GetDevice() | ||
device.Manufacturer = "DigitalStrom" | ||
device.ConfigurationUrl = "https://" + hass.config.DigitalStromHost | ||
|
||
hass.discoveryConfigs = append(hass.discoveryConfigs, config) | ||
} | ||
} | ||
|
||
func (hass *HomeAssistantDiscovery) PublishDiscoveryMessages() error { | ||
if !hass.config.DiscoveryEnabled { | ||
return nil | ||
} | ||
|
||
for _, config := range hass.discoveryConfigs { | ||
topic := path.Join( | ||
hass.config.DiscoveryTopicPrefix, | ||
string(config.Domain), | ||
config.DeviceId, | ||
config.ObjectId, | ||
"config") | ||
json, err := json.Marshal(config.Config) | ||
if err != nil { | ||
return fmt.Errorf("error serializing dicovery config to JSON: %w", err) | ||
} | ||
if err := hass.mqttClient.Publish(topic, json); err != nil { | ||
return fmt.Errorf("error publishing discovery message to MQTT: %w", err) | ||
} | ||
} | ||
return nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters