|
function normalizeMac(originalMac) { |
|
let mac = ''; |
|
for (let i = 0; i < originalMac.length; i = i + 2) { |
|
mac += originalMac.substring(i, i + 2) |
|
if (i < originalMac.length) { |
|
mac += ':' |
|
} |
|
} |
|
return mac; |
|
} |
|
|
|
const info = Shelly.getDeviceInfo(); |
|
const mqtt = Shelly.getComponentConfig("mqtt"); |
|
|
|
const baseConfig = { |
|
'~': mqtt.topic_prefix, |
|
origin: { |
|
name: 'shelly-ha-mqtt-auto-discovery', |
|
sw_version: '0.1', |
|
support_url: 'https://gist.github.com/jeremiehuchet/84e8dc96573e37200c2ab3bd4e013729', |
|
}, |
|
device: { |
|
configuration_url: 'http://' + mqtt.client_id, |
|
connections: [ |
|
['mac', normalizeMac(info.mac)] |
|
], |
|
hw_version: info.gen, |
|
identifiers: [ |
|
info.id |
|
], |
|
manufacturer: 'Shelly', |
|
model: info.model, |
|
name: info.name, |
|
sw_version: info.fw_id |
|
}, |
|
availability: [ |
|
{ |
|
topic: '~/online', |
|
payload_available: 'true', |
|
payload_not_available: 'false', |
|
} |
|
], |
|
}; |
|
|
|
const coverConfig = Object.assign({ |
|
command_topic: '~/rpc', |
|
device_class: 'shutter', |
|
name: 'Cover', |
|
payload_close: JSON.stringify({ |
|
id: 0, |
|
src: mqtt.topic_prefix, |
|
method: 'Cover.Close', |
|
params: { |
|
id: 0, |
|
}, |
|
}), |
|
payload_open: JSON.stringify({ |
|
id: 0, |
|
src: mqtt.topic_prefix, |
|
method: 'Cover.Open', |
|
params: { |
|
id: 0, |
|
}, |
|
}), |
|
payload_stop: JSON.stringify({ |
|
id: 0, |
|
src: mqtt.topic_prefix, |
|
method: 'Cover.Stop', |
|
params: { |
|
id: 0, |
|
}, |
|
}), |
|
position_closed: 0, |
|
position_open: 100, |
|
position_template: '{{ value_json.current_pos | int }}', |
|
position_topic: '~/status/cover:0', |
|
retain: true, |
|
set_position_template: JSON.stringify({ |
|
id: 0, |
|
src: mqtt.topic_prefix, |
|
method: 'Cover.GoToPosition', |
|
params: { |
|
id: 0, |
|
pos: '{{ position }}', |
|
}, |
|
}), |
|
set_position_topic: '~/rpc', |
|
state_closed: 'closed', |
|
state_closing: 'closing', |
|
state_open: 'open', |
|
state_opening: 'opening', |
|
state_stopped: 'stopped', |
|
state_topic: '~/status/cover:0', |
|
unique_id: info.id, |
|
value_template: '{{ value_json.state }}', |
|
}, baseConfig); |
|
|
|
const deviceTempConfig = Object.assign({ |
|
device_class: 'temperature', |
|
name: 'Device temperature', |
|
entity_category: 'diagnostic', |
|
icon: 'mdi:thermometer', |
|
unique_id: info.id + '_device_temp', |
|
state_class: 'measurement', |
|
state_topic: '~/status/cover:0', |
|
value_template: '{{ value_json.temperature.tC }}', |
|
unit_of_measurement: '°C', |
|
}, baseConfig); |
|
|
|
const restartRequiredConfig = Object.assign({ |
|
name: 'Restart required', |
|
icon: 'mdi:power-standby', |
|
entity_category: 'diagnostic', |
|
unique_id: info.id + '_restart_required', |
|
state_class: 'measurement', |
|
state_topic: '~/status/sys', |
|
value_template: '{{ value_json.restart_required }}', |
|
payload_on: true, |
|
payload_off: false, |
|
}, baseConfig); |
|
|
|
const lastRestartConfig = Object.assign({ |
|
name: 'Last restart', |
|
entity_category: 'diagnostic', |
|
unique_id: info.id + '_last_restart', |
|
state_class: 'measurement', |
|
state_topic: '~/status/sys', |
|
value_template: '{{ ( as_timestamp(now()) - value_json.uptime ) | timestamp_local }}', |
|
}, baseConfig); |
|
|
|
const wifiSignalStrengthConfig = Object.assign({ |
|
entity_category: 'diagnostic', |
|
device_class: 'timestamp', |
|
state_topic: '~/status/wifi', |
|
device_class: 'signal_strength', |
|
name: 'Wifi signal strength', |
|
unique_id: info.id + '_wifi_rssi', |
|
state_class: 'measurement', |
|
value_template: '{{ value_json.rssi }}', |
|
unit_of_measurement: 'dBm', |
|
}, baseConfig); |
|
|
|
const wifiSsidConfig = Object.assign({ |
|
entity_category: 'diagnostic', |
|
state_topic: '~/status/wifi', |
|
name: 'Wifi SSID', |
|
unique_id: info.id + '_wifi_ssid', |
|
icon: 'mdi:wifi-settings', |
|
value_template: '{{ value_json.ssid }}', |
|
}, baseConfig); |
|
|
|
const wifiIpConfig = Object.assign({ |
|
entity_category: 'diagnostic', |
|
state_topic: '~/status/wifi', |
|
name: 'Wifi IP address', |
|
unique_id: info.id + '_wifi_ip', |
|
icon: 'mdi:ip-outline', |
|
value_template: '{{ value_json.sta_ip }}', |
|
}, baseConfig); |
|
|
|
const apowerConfig = Object.assign({ |
|
entity_category: 'diagnostic', |
|
device_class: 'power', |
|
state_class: 'measurement', |
|
state_topic: '~/status/cover:0', |
|
name: 'Power', |
|
unique_id: info.id + '_apower', |
|
value_template: '{{ value_json.apower }}', |
|
unit_of_measurement: 'W', |
|
suggested_display_precision: 1, |
|
}, baseConfig); |
|
|
|
const voltageConfig = Object.assign({ |
|
entity_category: 'diagnostic', |
|
device_class: 'voltage', |
|
state_class: 'measurement', |
|
state_topic: '~/status/cover:0', |
|
name: 'Voltage', |
|
unique_id: info.id + '_voltage', |
|
value_template: '{{ value_json.voltage }}', |
|
unit_of_measurement: 'V', |
|
suggested_display_precision: 1, |
|
}, baseConfig); |
|
|
|
const currentConfig = Object.assign({ |
|
entity_category: 'diagnostic', |
|
device_class: 'current', |
|
state_class: 'measurement', |
|
state_topic: '~/status/cover:0', |
|
name: 'Current', |
|
unique_id: info.id + '_current', |
|
value_template: '{{ value_json.current }}', |
|
unit_of_measurement: 'A', |
|
suggested_display_precision: 1, |
|
}, baseConfig); |
|
|
|
const frequencyConfig = Object.assign({ |
|
entity_category: 'diagnostic', |
|
device_class: 'frequency', |
|
state_class: 'measurement', |
|
state_topic: '~/status/cover:0', |
|
name: 'Frequency', |
|
unique_id: info.id + '_frequency', |
|
value_template: '{{ value_json.freq }}', |
|
unit_of_measurement: 'Hz', |
|
}, baseConfig); |
|
|
|
const aenergyConfig = Object.assign({ |
|
entity_category: 'diagnostic', |
|
device_class: 'energy', |
|
state_class: 'total_increasing', |
|
state_topic: '~/status/cover:0', |
|
name: 'Energy', |
|
unique_id: info.id + '_aenergy', |
|
value_template: '{{ value_json.aenergy.total }}', |
|
unit_of_measurement: 'Wh', |
|
suggested_display_precision: 1, |
|
}, baseConfig); |
|
|
|
const powerFactorConfig = Object.assign({ |
|
entity_category: 'diagnostic', |
|
device_class: 'power_factor', |
|
state_class: 'measurement', |
|
state_topic: '~/status/cover:0', |
|
name: 'Energy', |
|
unique_id: info.id + '_power_factor', |
|
value_template: '{{ value_json.pf * 100 }}', |
|
unit_of_measurement: '%', |
|
suggested_display_precision: 0, |
|
}, baseConfig); |
|
|
|
function publish(topic, discoveryPayload) { |
|
MQTT.publish(topic, JSON.stringify(discoveryPayload)); |
|
//console.log('HA MQTT auto-discovery published on ' + topic, discoveryPayload); |
|
} |
|
|
|
function announce() { |
|
publish('homeassistant/cover/' + info.id + '/config', coverConfig); |
|
publish('homeassistant/sensor/' + info.id + '_device_temp/config', deviceTempConfig); |
|
publish('homeassistant/binary_sensor/' + info.id + '_restart_required/config', restartRequiredConfig); |
|
publish('homeassistant/sensor/' + info.id + '_wifi_rssi/config', wifiSignalStrengthConfig); |
|
publish('homeassistant/sensor/' + info.id + '_wifi_ssid/config', wifiSsidConfig); |
|
publish('homeassistant/sensor/' + info.id + '_wifi_ip/config', wifiIpConfig); |
|
publish('homeassistant/sensor/' + info.id + '_last_restart/config', lastRestartConfig); |
|
publish('homeassistant/sensor/' + info.id + '_apower/config', apowerConfig); |
|
publish('homeassistant/sensor/' + info.id + '_voltage/config', voltageConfig); |
|
publish('homeassistant/sensor/' + info.id + '_current/config', currentConfig); |
|
publish('homeassistant/sensor/' + info.id + '_frequency/config', frequencyConfig); |
|
publish('homeassistant/sensor/' + info.id + '_aenergy/config', aenergyConfig); |
|
publish('homeassistant/sensor/' + info.id + '_power_factor/config', powerFactorConfig); |
|
} |
|
|
|
function listenHomeAssistantStatusUpdates() { |
|
if (MQTT.isConnected()) { |
|
console.log('Subscribing to HomeAssistant status'); |
|
MQTT.subscribe('homeassistant/status', function(topic, payload) { |
|
console.log('HomeAssistant is ' + payload); |
|
if (payload.toLowerCase() === 'online') { |
|
announce(); |
|
} |
|
}); |
|
} else { |
|
console.log('Waiting one more second for MQTT connection'); |
|
Timer.set(1000, false, listenHomeAssistantStatusUpdates); |
|
} |
|
} |
|
|
|
MQTT.setDisconnectHandler(function() { |
|
console.log('MQTT connection lost'); |
|
listenHomeAssistantStatusUpdates(); |
|
}); |
|
|
|
announce(); |
|
listenHomeAssistantStatusUpdates(); |
|
|
|
// 20 * 60 * 60 * 1000 + 20 * 60 * 1000 |
|
const every_twenty_hours_and_twenty_minutes = 72000000; |
|
Timer.set(every_twenty_hours_and_twenty_minutes, true, announce); |