User Tools

Site Tools


public:it:homeassistant

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revisionPrevious revision
Next revision
Previous revision
public:it:homeassistant [2021/08/19 14:32] – [Notes from Tom Dobes] philpublic:it:homeassistant [Unknown date] (current) – removed - external edit (Unknown date) 127.0.0.1
Line 1: Line 1:
-====== Home Assistant ====== 
  
-Self hosted server that allows you to control many different types of IOT devices. 
- 
-[[https://www.home-assistant.io/|Home Assistant]] 
- 
-===== HestiaPi ===== 
-Open source thermostat. 
- 
-https://hestiapi.com/ 
- 
-=====Espurna===== 
-https://github.com/xoseperez/espurna 
- 
-===== Tasmota ====== 
-Integration with Home Assistant [[https://www.home-assistant.io/integrations/tasmota/|seems to be]] in beta and uses MQTT. 
- 
- 
- 
-[[ https://www.digiblur.com/2020/07/the-tasmota-fan-controller-ive-been.html| Fan Control ]] 
- 
- 
-[[https://www.amazon.com/Required-Wireless-Requires-Schedule-Compatible/dp/B079FDTG7T|Smart light switch]] 
-==== Sonoff S31 Commands ==== 
-  * [[https://tasmota.github.io/docs/Commands/|Command Docs]] 
- 
-<code> 
-$ curl -s http://192.168.30.132/cm?cmnd=power|jq 
-{ 
-  "POWER": "ON" 
-} 
-</code> 
-<code> 
-$ curl -s http://192.168.30.132/cm?cmnd=status|jq 
-{ 
-  "Status": { 
-    "Module": 41, 
-    "DeviceName": "s31-power-2", 
-    "FriendlyName": [ 
-      "s31-power-2" 
-    ], 
-    "Topic": "tasmota_07E0AD", 
-    "ButtonTopic": "0", 
-    "Power": 1, 
-    "PowerOnState": 3, 
-    "LedState": 1, 
-    "LedMask": "FFFF", 
-    "SaveData": 1, 
-    "SaveState": 1, 
-    "SwitchTopic": "0", 
-    "SwitchMode": [ 
-      0, 
-      0, 
-      0, 
-      0, 
-      0, 
-      0, 
-      0, 
-      0 
-    ], 
-    "ButtonRetain": 0, 
-    "SwitchRetain": 0, 
-    "SensorRetain": 0, 
-    "PowerRetain": 0 
-  } 
-} 
-</code> 
-<code> 
-$ curl -s http://192.168.30.132/cm?cmnd=Power%20Off 
-{"POWER":"OFF"} 
-</code> 
-<code> 
-$ curl -s http://192.168.30.132/cm?cmnd=Power%20On  
-{"POWER":"ON"} 
-</code> 
-<code> 
-$ curl -s http://192.168.30.132/cm?cmnd=FriendlyName%20testing 
-{"FriendlyName1":"testing"} 
-</code> 
-<code> 
-$ curl -s http://192.168.30.132/cm?cmnd=Status%200|jq 
-{ 
-  "Status": { 
-    "Module": 41, 
-    "DeviceName": "s31-power-2", 
-    "FriendlyName": [ 
-      "testing" 
-    ], 
-    "Topic": "tasmota_07E0AD", 
-    "ButtonTopic": "0", 
-    "Power": 1, 
-    "PowerOnState": 3, 
-    "LedState": 1, 
-    "LedMask": "FFFF", 
-    "SaveData": 1, 
-    "SaveState": 1, 
-    "SwitchTopic": "0", 
-    "SwitchMode": [ 
-      0, 
-      0, 
-      0, 
-      0, 
-      0, 
-      0, 
-      0, 
-      0 
-    ], 
-    "ButtonRetain": 0, 
-    "SwitchRetain": 0, 
-    "SensorRetain": 0, 
-    "PowerRetain": 0 
-  }, 
-  "StatusPRM": { 
-    "Baudrate": 4800, 
-    "SerialConfig": "8E1", 
-    "GroupTopic": "tasmotas", 
-    "OtaUrl": "http://ota.tasmota.com/tasmota/release/tasmota.bin.gz", 
-    "RestartReason": "Power On", 
-    "Uptime": "0T00:19:57", 
-    "StartupUTC": "2021-01-25T21:33:18", 
-    "Sleep": 50, 
-    "CfgHolder": 4617, 
-    "BootCount": 14, 
-    "BCResetTime": "2021-01-15T02:55:01", 
-    "SaveCount": 39, 
-    "SaveAddress": "F8000" 
-  }, 
-  "StatusFWR": { 
-    "Version": "9.2.0(tasmota)", 
-    "BuildDateTime": "2020-12-21T15:03:40", 
-    "Boot": 31, 
-    "Core": "2_7_4_9", 
-    "SDK": "2.2.2-dev(38a443e)", 
-    "CpuFrequency": 80, 
-    "Hardware": "ESP8266EX", 
-    "CR": "400/699" 
-  }, 
-  "StatusLOG": { 
-    "SerialLog": 0, 
-    "WebLog": 2, 
-    "MqttLog": 2, 
-    "SysLog": 0, 
-    "LogHost": "", 
-    "LogPort": 514, 
-    "SSId": [ 
-      "PKLAN-IOT", 
-      "" 
-    ], 
-    "TelePeriod": 10, 
-    "Resolution": "558180C0", 
-    "SetOption": [ 
-      "00008009", 
-      "2805C8000100068000005A00000000000000", 
-      "00000000", 
-      "00006000", 
-      "00000000" 
-    ] 
-  }, 
-  "StatusMEM": { 
-    "ProgramSize": 586, 
-    "Free": 416, 
-    "Heap": 26, 
-    "ProgramFlashSize": 1024, 
-    "FlashSize": 4096, 
-    "FlashChipId": "1640EF", 
-    "FlashFrequency": 40, 
-    "FlashMode": 3, 
-    "Features": [ 
-      "00000809", 
-      "8FDAC787", 
-      "04368001", 
-      "000000CF", 
-      "010013C0", 
-      "C000F981", 
-      "00004004", 
-      "00001000" 
-    ], 
-    "Drivers": "1,2,3,4,5,6,7,8,9,10,12,16,18,19,20,21,22,24,26,27,29,30,35,37,45", 
-    "Sensors": "1,2,3,4,5,6" 
-  }, 
-  "StatusNET": { 
-    "Hostname": "tasmota_07E0AD-0173", 
-    "IPAddress": "192.168.30.132", 
-    "Gateway": "192.168.30.1", 
-    "Subnetmask": "255.255.255.0", 
-    "DNSServer": "192.168.1.1", 
-    "Mac": "C8:2B:96:07:E0:AD", 
-    "Webserver": 2, 
-    "WifiConfig": 4, 
-    "WifiPower": 17 
-  }, 
-  "StatusMQT": { 
-    "MqttHost": "192.168.20.207", 
-    "MqttPort": 1883, 
-    "MqttClientMask": "DVES_%06X", 
-    "MqttClient": "DVES_07E0AD", 
-    "MqttUser": "phil", 
-    "MqttCount": 0, 
-    "MAX_PACKET_SIZE": 1200, 
-    "KEEPALIVE": 30 
-  }, 
-  "StatusTIM": { 
-    "UTC": "2021-01-25T21:53:15", 
-    "Local": "2021-01-25T22:53:15", 
-    "StartDST": "2021-03-28T02:00:00", 
-    "EndDST": "2021-10-31T03:00:00", 
-    "Timezone": "+01:00", 
-    "Sunrise": "08:28", 
-    "Sunset": "17:36" 
-  }, 
-  "StatusPTH": { 
-    "PowerDelta": [ 
-      0, 
-      0, 
-      0 
-    ], 
-    "PowerLow": 0, 
-    "PowerHigh": 0, 
-    "VoltageLow": 0, 
-    "VoltageHigh": 0, 
-    "CurrentLow": 0, 
-    "CurrentHigh": 0 
-  }, 
-  "StatusSNS": { 
-    "Time": "2021-01-25T22:53:15", 
-    "ENERGY": { 
-      "TotalStartTime": "2021-01-15T02:55:01", 
-      "Total": 0, 
-      "Yesterday": 0, 
-      "Today": 0, 
-      "Power": 0, 
-      "ApparentPower": 0, 
-      "ReactivePower": 0, 
-      "Factor": 0, 
-      "Voltage": 118, 
-      "Current": 0 
-    } 
-  }, 
-  "StatusSTS": { 
-    "Time": "2021-01-25T22:53:15", 
-    "Uptime": "0T00:19:57", 
-    "UptimeSec": 1197, 
-    "Heap": 26, 
-    "SleepMode": "Dynamic", 
-    "Sleep": 50, 
-    "LoadAvg": 19, 
-    "MqttCount": 0, 
-    "POWER": "ON", 
-    "Wifi": { 
-      "AP": 1, 
-      "SSId": "PKLAN-IOT", 
-      "BSSId": "02:9F:C2:77:2D:37", 
-      "Channel": 11, 
-      "RSSI": 100, 
-      "Signal": -43, 
-      "LinkCount": 1, 
-      "Downtime": "0T00:00:03" 
-    } 
-  } 
-} 
-</code> 
-<code> 
-$ curl -s http://192.168.30.136/cm?cmnd=Status%208|jq 
-{ 
-  "StatusSNS": { 
-    "Time": "2021-01-25T22:56:32", 
-    "ENERGY": { 
-      "TotalStartTime": "2021-01-15T00:21:03", 
-      "Total": 48.545, 
-      "Yesterday": 4.492, 
-      "Today": 5.049, 
-      "Power": 380, 
-      "ApparentPower": 384, 
-      "ReactivePower": 56, 
-      "Factor": 0.99, 
-      "Voltage": 120, 
-      "Current": 3.2 
-    } 
-  } 
-} 
-</code> 
- 
- 
-Just in case I'm saving this. 
-<code> 
-import requests 
-import json 
- 
-class s31powerplug: 
- 
-  def __init__(self, target): 
-    self.target = target 
- 
-  def cmd(self, cmd): 
-    r = requests.get('http://%s/cm?cmnd=%s' % (self.target, cmd)) 
-    if r.status_code == 200: 
-      return r.json() 
-    else: 
-      return False 
- 
- 
-  def energy(self): 
-    r = self.cmd('Status%208') 
-    return r['StatusSNS']['ENERGY'] 
- 
- 
-  def network(self): 
-    r = self.cmd('Status%205') 
-    return r['StatusNET'] 
- 
- 
-  def power(self, toggle=None): 
-    if toggle is None: 
-      return self.cmd('power') 
- 
-    elif toggle: 
-      return self.cmd('power%20On') 
- 
-    else: 
-      return self.cmd('power%20Off') 
- 
-</code> 
- 
-===== MQTT ===== 
- 
-==== Notes from Tom ==== 
-if you enable websocket interface on mosquitto, you can also talk to it from a browser using javascript, which is kinda handy.  Here's the lib I've used for that -> https://github.com/mqttjs/MQTT.js 
-(basically it just encapsulates the normal MQTT protocol inside a websocket connection so that it can be used directly in a browser -- it's handy for things like dashboards that update in real-time) 
- 
- 
-I've just used curl with the API so far 
-(from shell scripts) 
-well, plus the MQTT interface via. a python library 
-this one -> https://pypi.org/project/paho-mqtt/ 
- 
- 
- 
-that's an example of a simple MQTT frontend -- I kinda cheated by doing some server-side stuff in PHP, so I provided both the PHP source as well as the final HTML it generates 
-I wrote that back in 2016, but I think it should still work with modern servers/libraries 
-lol some of this code is kinda gross, but at least it gives you the general idea 
- 
-=== relay_control.html === 
-<code> 
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 
-<html> 
-<head> 
-<title>MCP Relay Power Control</title> 
-<link rel="shortcut icon" href="../favicon-power.png" type="image/png" /> 
-<meta name="viewport" content="initial-scale = 0.5, maximum-scale = 1.0, minimum-scale = 0.5" /> 
-<style type="text/css">@import "style.css";</style> 
-</head> 
-<body> 
-<script src="../mqttws31.js" type="text/javascript"></script> 
-<script type="text/javascript"> 
-mqtt_topic = "power/relay"; 
- 
-function mqtt_connect() { 
-  console.log("MQTT connecting..."); 
-  client = new Paho.MQTT.Client('mqtt.mcp.lcl', 8000, "Web interface for computer power control from 192.168.48.217 started at Mon, 25 Jan 2021 18:45:22 -0600"); 
-  client.onConnectionLost = on_mqtt_connection_lost; 
-  client.onMessageArrived = on_mqtt_message; 
-  client.connect({onSuccess:on_mqtt_connect}); 
-} 
- 
-mqtt_connect(); 
- 
-function on_mqtt_connect() { 
-  console.log("MQTT connected."); 
-  client.subscribe(mqtt_topic + "/#"); 
-}; 
-function on_mqtt_connection_lost(response) { 
-  if (response.errorCode !== 0) { 
-    console.log("MQTT connection lost: " + response.errorMessage); 
-  } 
-  update_online(false); 
-  console.log("MQTT attempting reconnect..."); 
-  mqtt_connect(); 
-}; 
-function on_mqtt_message(msg) { 
-  console.log("MQTT received: " + msg.destinationName + " => " + msg.payloadString); 
-  if (msg.destinationName.indexOf(mqtt_topic) == 0) { 
-    var short_topic = msg.destinationName.substr(mqtt_topic.length + 1); 
-    if (short_topic == "status") { 
-      switch (msg.payloadString) { 
-        case "online": 
-          update_online(true); 
-          break; 
-        case "offline": 
-          update_online(false); 
-          break; 
-        default: 
-          console.log("WARNING: Invalid status received: " + msg.payloadString); 
-      } 
-    } else { 
-      var element = document.getElementById(short_topic); 
-      if (element) { 
-        update_element(short_topic, msg.payloadString, element); 
-      } else { 
-        console.log("INFO: Ignored MQTT message for unlisted computer: " + short_topic + " => " + msg.payloadString); 
-      } 
-    } 
-  } else { 
-    console.log("WARNING: Unrecognized MQTT message received: " + short_topic + " => " + msg.payloadString); 
-  } 
-  //client.disconnect(); 
-}; 
-function send_mqtt(device, state) { 
-  if (document.getElementById("relays").className == "online") { 
-    if (state == "off" && ! confirm("Are you sure you want to power off " + device + "?")) { 
-      return; 
-    } 
-    if (state == "on" && ! confirm("Are you sure you want to power on " + device + "?")) { 
-      return; 
-    } 
-    console.log("Sending MQTT: " + device + " => " + state); 
-    var msg = new Paho.MQTT.Message(String(state)); 
-    msg.destinationName = mqtt_topic + "/" + String(device); 
-    msg.qos = 1; 
-    msg.retained = true; 
-    client.send(msg); 
-  } else { 
-    console.log("Ignoring command while relay power controller is offline"); 
-  } 
-}; 
-function update_online(is_online) { 
-  if (is_online) { 
-    console.log("Marking display online"); 
-    document.getElementById("relays").className = "online"; 
-  } else { 
-    console.log("Marking display offline"); 
-    document.getElementById("relays").className = "offline"; 
-  } 
-}; 
-function update_element(device, status, element) { 
-  console.log("Marking status of device " + device + " as " + status); 
-  switch (status) { 
-    case "0": 
-      element.className = "off"; 
-      break; 
-    case "1": 
-      element.className = "on"; 
-      break; 
-    case "off": 
-    case "on": 
-      element.className = "pending"; 
-      break; 
-    default: 
-      element.className = ""; 
-  } 
-}; 
-function toggle_device(device) { 
-  state = document.getElementById(device).className; 
-  switch (state) { 
-    case "off": 
-      return send_mqtt(device, "on"); 
-    case "on": 
-      return send_mqtt(device, "off"); 
-    default: 
-      console.log("Not known how to toggle state " + state + " on device " + device); 
-  } 
-} 
-</script> 
-<h1>MCP Relay Power Control</h1> 
-<div id="relays" class="offline"> 
-<div class="buttonrow"><div class="button"><a id="soffit_n" href="javascript:toggle_device('soffit_n');">soffit_n</a></div><div class="button"><a id="soffit_s" href="javascript:toggle_device('soffit_s');">soffit_s</a></div><div class="button"><a id="vest_r" href="javascript:toggle_device('vest_r');">vest_r</a></div><div class="button"><a id="vest_w" href="javascript:toggle_device('vest_w');">vest_w</a></div><div class="button"><a id="console" href="javascript:toggle_device('console');">console</a></div><div class="button"><a id="cat_main" href="javascript:toggle_device('cat_main');">cat_main</a></div><div class="button"><a id="cat_rope" href="javascript:toggle_device('cat_rope');">cat_rope</a></div><div class="button"><a id="inuse" href="javascript:toggle_device('inuse');">inuse</a></div></div><div class="buttonrow"><div class="button"><a id="ds-proj-a" href="javascript:toggle_device('ds-proj-a');">ds-proj-a</a></div><div class="button"><a id="ds-proj-b" href="javascript:toggle_device('ds-proj-b');">ds-proj-b</a></div><div class="button"><a id="ds-proj-c" href="javascript:toggle_device('ds-proj-c');">ds-proj-c</a></div><div class="button"><a id="ds-proj-d" href="javascript:toggle_device('ds-proj-d');">ds-proj-d</a></div><div class="button"><a id="ds-proj-e" href="javascript:toggle_device('ds-proj-e');">ds-proj-e</a></div><div class="button"><a id="ds-proj-f" href="javascript:toggle_device('ds-proj-f');">ds-proj-f</a></div><div class="button"><a id="giftshop" href="javascript:toggle_device('giftshop');">giftshop</a></div><div class="button"><a id="waiting-sound" href="javascript:toggle_device('waiting-sound');">waiting-sound</a></div></div><div class="buttonrow"><div class="button"><a id="waiting" href="javascript:toggle_device('waiting');">waiting</a></div><div class="button"><a id="office-sound" href="javascript:toggle_device('office-sound');">office-sound</a></div><div class="button"><a id="epson-proj" href="javascript:toggle_device('epson-proj');">epson-proj</a></div><div class="button"><a id="waiting-proj" href="javascript:toggle_device('waiting-proj');">waiting-proj</a></div></div></div> 
- 
-</body> 
-</html> 
-</code> 
- 
- 
-===relay_control.php=== 
-<code> 
-<?php 
- 
-require 'power.inc.php'; 
- 
-_read_devices_csv(); 
- 
-?><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 
-<html> 
-<head> 
-<title>MCP Relay Power Control</title> 
-<link rel="shortcut icon" href="../favicon-power.png" type="image/png" /> 
-<meta name="viewport" content="initial-scale = 0.5, maximum-scale = 1.0, minimum-scale = 0.5" /> 
-<style type="text/css">@import "style.css";</style> 
-</head> 
-<body> 
-<script src="../mqttws31.js" type="text/javascript"></script> 
-<script type="text/javascript"> 
-mqtt_topic = "<?php echo MQTT_TOPIC; ?>"; 
- 
-function mqtt_connect() { 
-  console.log("MQTT connecting..."); 
-  client = new Paho.MQTT.Client('mqtt.mcp.lcl', 8000, "Web interface for computer power control from <?php echo $_SERVER['REMOTE_ADDR'] ?> started at <?php echo date('r'); ?>"); 
-  client.onConnectionLost = on_mqtt_connection_lost; 
-  client.onMessageArrived = on_mqtt_message; 
-  client.connect({onSuccess:on_mqtt_connect}); 
-} 
- 
-mqtt_connect(); 
- 
-function on_mqtt_connect() { 
-  console.log("MQTT connected."); 
-  client.subscribe(mqtt_topic + "/#"); 
-}; 
-function on_mqtt_connection_lost(response) { 
-  if (response.errorCode !== 0) { 
-    console.log("MQTT connection lost: " + response.errorMessage); 
-  } 
-  update_online(false); 
-  console.log("MQTT attempting reconnect..."); 
-  mqtt_connect(); 
-}; 
-function on_mqtt_message(msg) { 
-  console.log("MQTT received: " + msg.destinationName + " => " + msg.payloadString); 
-  if (msg.destinationName.indexOf(mqtt_topic) == 0) { 
-    var short_topic = msg.destinationName.substr(mqtt_topic.length + 1); 
-    if (short_topic == "status") { 
-      switch (msg.payloadString) { 
-        case "online": 
-          update_online(true); 
-          break; 
-        case "offline": 
-          update_online(false); 
-          break; 
-        default: 
-          console.log("WARNING: Invalid status received: " + msg.payloadString); 
-      } 
-    } else { 
-      var element = document.getElementById(short_topic); 
-      if (element) { 
-        update_element(short_topic, msg.payloadString, element); 
-      } else { 
-        console.log("INFO: Ignored MQTT message for unlisted computer: " + short_topic + " => " + msg.payloadString); 
-      } 
-    } 
-  } else { 
-    console.log("WARNING: Unrecognized MQTT message received: " + short_topic + " => " + msg.payloadString); 
-  } 
-  //client.disconnect(); 
-}; 
-function send_mqtt(device, state) { 
-  if (document.getElementById("relays").className == "online") { 
-    if (state == "off" && ! confirm("Are you sure you want to power off " + device + "?")) { 
-      return; 
-    } 
-    if (state == "on" && ! confirm("Are you sure you want to power on " + device + "?")) { 
-      return; 
-    } 
-    console.log("Sending MQTT: " + device + " => " + state); 
-    var msg = new Paho.MQTT.Message(String(state)); 
-    msg.destinationName = mqtt_topic + "/" + String(device); 
-    msg.qos = 1; 
-    msg.retained = true; 
-    client.send(msg); 
-  } else { 
-    console.log("Ignoring command while relay power controller is offline"); 
-  } 
-}; 
-function update_online(is_online) { 
-  if (is_online) { 
-    console.log("Marking display online"); 
-    document.getElementById("relays").className = "online"; 
-  } else { 
-    console.log("Marking display offline"); 
-    document.getElementById("relays").className = "offline"; 
-  } 
-}; 
-function update_element(device, status, element) { 
-  console.log("Marking status of device " + device + " as " + status); 
-  switch (status) { 
-    case "0": 
-      element.className = "off"; 
-      break; 
-    case "1": 
-      element.className = "on"; 
-      break; 
-    case "off": 
-    case "on": 
-      element.className = "pending"; 
-      break; 
-    default: 
-      element.className = ""; 
-  } 
-}; 
-function toggle_device(device) { 
-  state = document.getElementById(device).className; 
-  switch (state) { 
-    case "off": 
-      return send_mqtt(device, "on"); 
-    case "on": 
-      return send_mqtt(device, "off"); 
-    default: 
-      console.log("Not known how to toggle state " + state + " on device " + device); 
-  } 
-} 
-</script> 
-<h1>MCP Relay Power Control</h1> 
-<div id="relays" class="offline"> 
-<?php 
- 
-function print_device($device, $params) { 
-  print '<div class="button"><a id="'. $device .'" href="javascript:toggle_device(\''. $device .'\');">'. $device .'</a></div>'; 
-} 
- 
-print '<div class="buttonrow">'; 
-$i = 0; 
-foreach ($devices as $device => $params) { 
-  print_device($device, $params); 
-  if (++$i == 8) { 
-    print '</div><div class="buttonrow">'; 
-    $i = 0; 
-  } 
-} 
-print '</div>'; 
- 
-?></div> 
- 
-</body> 
-</html> 
-</code> 
- 
-====== Gear ====== 
-  * https://cloudfree.shop/ 
-    * These guys flash various plugs with [[https://tasmota.github.io/docs|Tasmota]] so you don't have to. 
public/it/homeassistant.1629401574.txt.gz · Last modified: 2021/08/19 14:32 by phil