Example - Tasmota wall Switch with Humidity/Temp/Dewpoint (Martin Jerry US-SS02) #528
glasscake
started this conversation in
Show and tell
Replies: 0 comments
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
-
This is an example of my flow for martin jerry wall switches. There is blocking functionality to stop input loops. It also allows outside inputs (button on device, Tasmota interface, other automation) with feedback to homekit. This example flow has the device set up as a switch with a child temp, humidity, and "auto exhaust fan" I am currently using these as switches for exhaust fans in bathrooms. They could also be broken out into a separate thermostat. Temperature seems to be accurate for the room at least within 1 degrees of ambient
Inside the "Auto Exhaust" node you can edit "dewpoint_Delta" This is the min delta in Fahrenheit between the room's current temperature and the dewpoint of the room. IE: Dewpoint of the room = 70f, Current Temp = 80f, Delta = 10f -> Auto exhaust turns on. This is to try to purge the room of hot humid air and prevent water damage from bathrooms caused by showers.
You can also edit "min_secconds_on" This is acting like a deadband and prevents the exhaust fan from rapidly switching when close to the delta.
Node "Auto Exhaust" is set up as default on in "Characteristics" this can be changed. When Autoexhaust is on the auto exhaust functionality will work otherwise it is disabled
I am currently using a 2-second repeat input on "get all Tasmota state". When implementing multiple devices just use one "get all Tasmota state" for all Tasmota devices.
Amazon Link: https://www.amazon.com/dp/B0C7L49BXL?psc=1&ref=ppx_yo2ov_dt_b_product_details
https://www.martinjerry.com/us-ss02
My recommended Tasmota settings:
BackLog MqttHost (YourMQTTIp); MqttUser (your MQTT Login)t; MqttPassword (Your MQTT PW); PowerRetain 1; SetOption53 1; SetOption41 20; Topic (Your mqtt topic); Hostname (your hostname)
Do note if you have a router that handles tasmota devices well drop "SetOption41". If you're noticing a lot of dropped connections renable it.
Example flow:
[ { "id": "a29ae63dcf2e9499", "type": "homekit-service", "z": "c16b8cbf103f2790", "isParent": true, "hostType": "0", "bridge": "", "accessoryId": "", "parentService": "", "name": "Your HK Humidity Switch", "serviceName": "Fan", "topic": "", "filter": false, "manufacturer": "NRCHKB", "model": "1.5.0", "serialNo": "Default Serial Number", "firmwareRev": "1.5.0", "hardwareRev": "1.5.0", "softwareRev": "1.5.0", "cameraConfigVideoProcessor": "ffmpeg", "cameraConfigSource": "", "cameraConfigStillImageSource": "", "cameraConfigMaxStreams": 2, "cameraConfigMaxWidth": 1280, "cameraConfigMaxHeight": 720, "cameraConfigMaxFPS": 10, "cameraConfigMaxBitrate": 300, "cameraConfigVideoCodec": "libx264", "cameraConfigAudioCodec": "libfdk_aac", "cameraConfigAudio": false, "cameraConfigPacketSize": 1316, "cameraConfigVerticalFlip": false, "cameraConfigHorizontalFlip": false, "cameraConfigMapVideo": "0:0", "cameraConfigMapAudio": "0:1", "cameraConfigVideoFilter": "scale=1280:720", "cameraConfigAdditionalCommandLine": "-tune zerolatency", "cameraConfigDebug": false, "cameraConfigSnapshotOutput": "disabled", "cameraConfigInterfaceName": "", "characteristicProperties": "{}", "waitForSetupMsg": false, "outputs": 2, "x": 1250, "y": 1140, "wires": [ [ "f5ce0d7bd799bc38", "7db32528bf7f76fc" ], [] ] }, { "id": "347ef00f9deed475", "type": "mqtt in", "z": "c16b8cbf103f2790", "name": "", "topic": "stat/YOUR_TASMOTA/RESULT", "qos": "2", "datatype": "auto-detect", "broker": "", "nl": false, "rap": true, "rh": 0, "inputs": 0, "x": 370, "y": 1140, "wires": [ [ "d3f4e4f16291cc98" ] ] }, { "id": "f5ce0d7bd799bc38", "type": "function", "z": "c16b8cbf103f2790", "name": "HomeKit to MQTT", "func": "if(msg.payload.On != null)\n{\n if(msg.payload.On == true)\n {\n return {payload:true};\n }\n return [{payload:false},null];\n}\nreturn null,null;", "outputs": 1, "noerr": 0, "initialize": "", "finalize": "", "libs": [], "x": 1490, "y": 1140, "wires": [ [ "c92ab4c4ca49ac94" ] ] }, { "id": "c92ab4c4ca49ac94", "type": "mqtt out", "z": "c16b8cbf103f2790", "name": "", "topic": "cmnd/YOUR_TASMOTA/Power", "qos": "", "retain": "", "respTopic": "", "contentType": "", "userProps": "", "correl": "", "expiry": "", "broker": "", "x": 1730, "y": 1140, "wires": [] }, { "id": "58e7bb0acf39084d", "type": "comment", "z": "c16b8cbf103f2790", "name": "NRB Humidity Single Switch", "info": "", "x": 360, "y": 1040, "wires": [] }, { "id": "2f102dc6db5957b6", "type": "mqtt out", "z": "c16b8cbf103f2790", "name": "", "topic": "cmnd/YOUR_TASMOTA/Status", "qos": "1", "retain": "", "respTopic": "", "contentType": "", "userProps": "", "correl": "", "expiry": "", "broker": "", "x": 370, "y": 1240, "wires": [] }, { "id": "a296b5682be8255c", "type": "mqtt in", "z": "c16b8cbf103f2790", "name": "", "topic": "stat/YOUR_TASMOTA/STATUS8", "qos": "2", "datatype": "auto-detect", "broker": "", "nl": false, "rap": true, "rh": 0, "inputs": 0, "x": 370, "y": 1200, "wires": [ [ "e6b7816dda43f513", "96e96394d4b40a98", "afc1e587060b7d05", "29dcd22d0171c0c1" ] ] }, { "id": "82bda076a73b76b7", "type": "function", "z": "c16b8cbf103f2790", "name": "inject status 8", "func": "msg.payload = 8;\nreturn msg;", "outputs": 1, "noerr": 0, "initialize": "", "finalize": "", "libs": [], "x": 300, "y": 1280, "wires": [ [ "2f102dc6db5957b6" ] ] }, { "id": "5bc9d15f1426a9e9", "type": "homekit-service", "z": "c16b8cbf103f2790", "isParent": false, "hostType": "0", "bridge": "bf58291f61a32484", "accessoryId": "", "parentService": "eb3c8a9a00234a21", "name": "Temp", "serviceName": "TemperatureSensor", "topic": "", "filter": false, "manufacturer": "NRCHKB", "model": "1.5.0", "serialNo": "Default Serial Number", "firmwareRev": "1.5.0", "hardwareRev": "1.5.0", "softwareRev": "1.5.0", "cameraConfigVideoProcessor": "ffmpeg", "cameraConfigSource": "", "cameraConfigStillImageSource": "", "cameraConfigMaxStreams": 2, "cameraConfigMaxWidth": 1280, "cameraConfigMaxHeight": 720, "cameraConfigMaxFPS": 10, "cameraConfigMaxBitrate": 300, "cameraConfigVideoCodec": "libx264", "cameraConfigAudioCodec": "libfdk_aac", "cameraConfigAudio": false, "cameraConfigPacketSize": 1316, "cameraConfigVerticalFlip": false, "cameraConfigHorizontalFlip": false, "cameraConfigMapVideo": "0:0", "cameraConfigMapAudio": "0:1", "cameraConfigVideoFilter": "scale=1280:720", "cameraConfigAdditionalCommandLine": "-tune zerolatency", "cameraConfigDebug": false, "cameraConfigSnapshotOutput": "disabled", "cameraConfigInterfaceName": "", "characteristicProperties": "{}", "waitForSetupMsg": false, "outputs": 2, "x": 1210, "y": 1240, "wires": [ [], [] ] }, { "id": "20d5427f8314262c", "type": "homekit-service", "z": "c16b8cbf103f2790", "isParent": false, "hostType": "0", "bridge": "bf58291f61a32484", "accessoryId": "", "parentService": "eb3c8a9a00234a21", "name": "Auto Exhaust", "serviceName": "Switch", "topic": "", "filter": false, "manufacturer": "NRCHKB", "model": "1.5.0", "serialNo": "Default Serial Number", "firmwareRev": "1.5.0", "hardwareRev": "1.5.0", "softwareRev": "1.5.0", "cameraConfigVideoProcessor": "ffmpeg", "cameraConfigSource": "", "cameraConfigStillImageSource": "", "cameraConfigMaxStreams": 2, "cameraConfigMaxWidth": 1280, "cameraConfigMaxHeight": 720, "cameraConfigMaxFPS": 10, "cameraConfigMaxBitrate": 300, "cameraConfigVideoCodec": "libx264", "cameraConfigAudioCodec": "libfdk_aac", "cameraConfigAudio": false, "cameraConfigPacketSize": 1316, "cameraConfigVerticalFlip": false, "cameraConfigHorizontalFlip": false, "cameraConfigMapVideo": "0:0", "cameraConfigMapAudio": "0:1", "cameraConfigVideoFilter": "scale=1280:720", "cameraConfigAdditionalCommandLine": "-tune zerolatency", "cameraConfigDebug": false, "cameraConfigSnapshotOutput": "disabled", "cameraConfigInterfaceName": "", "characteristicProperties": "{\"On\":true}", "waitForSetupMsg": false, "outputs": 2, "x": 1230, "y": 1200, "wires": [ [], [] ] }, { "id": "12a23ac0a1d40f5e", "type": "homekit-service", "z": "c16b8cbf103f2790", "isParent": false, "hostType": "0", "bridge": "bf58291f61a32484", "accessoryId": "", "parentService": "eb3c8a9a00234a21", "name": "Humidity", "serviceName": "HumiditySensor", "topic": "", "filter": false, "manufacturer": "NRCHKB", "model": "1.5.0", "serialNo": "Default Serial Number", "firmwareRev": "1.5.0", "hardwareRev": "1.5.0", "softwareRev": "1.5.0", "cameraConfigVideoProcessor": "ffmpeg", "cameraConfigSource": "", "cameraConfigStillImageSource": "", "cameraConfigMaxStreams": 2, "cameraConfigMaxWidth": 1280, "cameraConfigMaxHeight": 720, "cameraConfigMaxFPS": 10, "cameraConfigMaxBitrate": 300, "cameraConfigVideoCodec": "libx264", "cameraConfigAudioCodec": "libfdk_aac", "cameraConfigAudio": false, "cameraConfigPacketSize": 1316, "cameraConfigVerticalFlip": false, "cameraConfigHorizontalFlip": false, "cameraConfigMapVideo": "0:0", "cameraConfigMapAudio": "0:1", "cameraConfigVideoFilter": "scale=1280:720", "cameraConfigAdditionalCommandLine": "-tune zerolatency", "cameraConfigDebug": false, "cameraConfigSnapshotOutput": "disabled", "cameraConfigInterfaceName": "", "characteristicProperties": "{}", "waitForSetupMsg": false, "outputs": 2, "x": 1220, "y": 1280, "wires": [ [], [] ] }, { "id": "e6b7816dda43f513", "type": "function", "z": "c16b8cbf103f2790", "name": "MQTT - Temp/Humidity", "func": "if (msg.payload.StatusSNS.AHT2X != null) {\n msg.mqtt = msg.payload;\n var msg1 = {}\n msg1.payload = {\n \"CurrentTemperature\":\n ((msg.mqtt.StatusSNS.AHT2X.Temperature - 32)/1.8)\n }\n var msg2 = {}\n msg2.payload = {\n \"CurrentRelativeHumidity\": msg.mqtt.StatusSNS.AHT2X.Humidity\n }\n return [msg1,msg2];\n}\n\n\nreturn [null,null];", "outputs": 2, "noerr": 0, "initialize": "", "finalize": "", "libs": [], "x": 910, "y": 1240, "wires": [ [ "5bc9d15f1426a9e9" ], [ "12a23ac0a1d40f5e" ] ] }, { "id": "96e96394d4b40a98", "type": "homekit-status", "z": "c16b8cbf103f2790", "serviceNodeId": "35b0ea3fbd1d7913", "name": "Status Auto Exhaust", "outputs": 1, "x": 640, "y": 1360, "wires": [ [ "de3f607834f8c8ed" ] ] }, { "id": "29dcd22d0171c0c1", "type": "function", "z": "c16b8cbf103f2790", "name": "Auto Exhuast", "func": "\nvar dewpoint_Delta = 20\nvar min_secconds_on = 120\n\nif (msg.payload.StatusSNS != null) {\n context.set('humidity', msg.payload.StatusSNS.AHT2X.Humidity);\n context.set('dewpoint', msg.payload.StatusSNS.AHT2X.DewPoint);\n context.set('temp', msg.payload.StatusSNS.AHT2X.Temperature);\n return null;\n}\n\nif (msg.payload.AutoExhaust != null)\n{\n context.set('AutoExhaust', msg.payload.AutoExhaust)\n return null;\n}\n\nif (msg.payload.FanState != null) {\n context.set('FanState', msg.payload.FanState)\n return null;\n}\n\nvar sensor = {\n \"humidity\": context.get('humidity'),\n \"dewpoint\": context.get('dewpoint'),\n \"temp\": context.get('temp')\n};\n\n\nif (sensor == null )\n{\n node.warn(\"sensor null\");\n return null;\n}\n\nvar Fanstate = context.get('FanState');\nvar AutoExhaust = context.get('AutoExhaust');\n\n//check if the auto exhaust is on\nif (AutoExhaust == false) {\n //node.warn(\"Autoexhaust off\");\n return null;\n}\n\n\nmsg = {};\nmsg.payload = {};\nvar d = new Date();\nvar curtime = d.getTime();\nvar offtime = context.get('offtime');\nvar min_time_elapsed = context.get('min-on-time-elapsed');\n\nvar debug = {};\ndebug.payload =\n{\n 'offtimeF': new Date(offtime) ,\n 'current_timeF': new Date(curtime),\n 'offtime': offtime,\n 'current_time': curtime,\n 'elapsed': min_time_elapsed,\n 'results': null\n}\n\n//the difference between dewpoint and current temp\n//set this below current temp to try to prevent dew from forming\nif (sensor.dewpoint >= sensor.temp - dewpoint_Delta || (offtime != 0 && min_time_elapsed == false))\n{\n if (offtime == 0) \n {\n context.set('offtime', curtime + min_secconds_on*1000);\n offtime = context.get('offtime');\n }\n if (min_time_elapsed == false)\n {\n //the min ontime in seconds\n if (curtime > offtime)\n {\n context.set('min-on-time-elapsed', true)\n }\n }\n debug.payload.results = true;\n msg.payload.On = true;\n}\n//send the off message\nelse if (min_time_elapsed == true && Fanstate == true)\n{\n debug.payload.results = false;\n msg.payload.On = false;\n}\n\n//check to make sure the fan actually turned off\nif( min_time_elapsed == true && Fanstate == false)\n{\n context.set('offtime', 0);\n context.set('min-on-time-elapsed', false)\n}\n\ndebug.payload.results = msg.payload.On\n\nreturn [msg,debug];", "outputs": 2, "noerr": 0, "initialize": "// Code added here will be run once\n// whenever the node is started.\n//context.set('offtime', 0);\n//context.set('min-on-time-elapsed', false)", "finalize": "", "libs": [], "x": 1030, "y": 1340, "wires": [ [ "a29ae63dcf2e9499" ], [ "085d684483e6b7e1" ] ] }, { "id": "085d684483e6b7e1", "type": "debug", "z": "c16b8cbf103f2790", "name": "debug 6", "active": false, "tosidebar": true, "console": false, "tostatus": false, "complete": "payload", "targetType": "msg", "statusVal": "", "statusType": "auto", "x": 1240, "y": 1340, "wires": [] }, { "id": "afc1e587060b7d05", "type": "homekit-status", "z": "c16b8cbf103f2790", "serviceNodeId": "eb3c8a9a00234a21", "name": "Status Fan State", "outputs": 1, "x": 630, "y": 1400, "wires": [ [ "b28382955720a4e5" ] ] }, { "id": "de3f607834f8c8ed", "type": "function", "z": "c16b8cbf103f2790", "name": "Extract Data", "func": "\nvar backup = msg.payload\nmsg = {}\nmsg.payload = \n{\n \"AutoExhaust\": backup.characteristics[1].value\n}\n\nreturn msg;", "outputs": 1, "noerr": 0, "initialize": "", "finalize": "", "libs": [], "x": 830, "y": 1360, "wires": [ [ "29dcd22d0171c0c1" ] ] }, { "id": "b28382955720a4e5", "type": "function", "z": "c16b8cbf103f2790", "name": "Extract Data", "func": "\nvar backup = msg.payload\nmsg = {}\nmsg.payload = \n{\n \"FanState\": backup.characteristics[1].value\n}\n\nreturn msg;", "outputs": 1, "noerr": 0, "initialize": "", "finalize": "", "libs": [], "x": 810, "y": 1400, "wires": [ [ "29dcd22d0171c0c1" ] ] }, { "id": "270c684db2b86926", "type": "inject", "z": "c16b8cbf103f2790", "name": "", "props": [ { "p": "payload" } ], "repeat": "3", "crontab": "", "once": true, "onceDelay": 0.1, "topic": "", "payload": "", "payloadType": "date", "x": 830, "y": 1440, "wires": [ [ "29dcd22d0171c0c1" ] ] }, { "id": "f4024a26b3a29199", "type": "function", "z": "c16b8cbf103f2790", "name": "MQTT - Homekit Plug", "func": "\n//translate the mqtt to homekit\n\nif (msg.payload.POWER != null) {\n msg.mqtt = msg.payload;\n msg.payload = {\n \"On\": false\n }\n if (msg.mqtt.POWER == \"ON\") {\n msg.payload.On = true\n }\n return msg;\n}\n\n\nreturn null;", "outputs": 1, "noerr": 0, "initialize": "", "finalize": "", "libs": [], "x": 980, "y": 1140, "wires": [ [ "a29ae63dcf2e9499" ] ] }, { "id": "8481af04ee2b053e", "type": "function", "z": "c16b8cbf103f2790", "name": "Block", "func": "//block all messages until the device has updated itself\n//this also stops loops and other odd issues\n\n//initalize into passing\nif (context.get('blocking') == null) {\n node.status({ fill: \"green\", shape: \"dot\", text: \"passing\" });\n context.set('blocking', false)\n return null\n}\n\n//is this a homekit message\nif (msg.payload.type == 1)\n{\n //that means the homekit service is sending data to the device\n //block all messages untill the device responds on mqtt\n context.set('blocking', true)\n //save what the message was so we confirm it is correct\n context.set('status', msg.payload.On)\n node.status({ fill: \"red\", shape: \"dot\", text: \"blocking\" });\n return null\n}\n\nif (msg.payload.type == 0)\n{\n //this is an mqtt response, lets see if the response matches the set status\n //translate mqtt to bool\n var power = false\n if (msg.payload.POWER == \"ON\")\n {\n power = true\n }\n //check if they match\n if( context.get('status') == power)\n {\n //they match, disable blocking\n context.set('blocking', false)\n node.status({ fill: \"green\", shape: \"dot\", text: \"passing\" });\n }\n}\n\n//get the current blocking state\nvar blocking = context.get('blocking')\n\nif (blocking == true)\n{\n return null\n}\n\nreturn msg;", "outputs": 1, "noerr": 0, "initialize": "", "finalize": "", "libs": [], "x": 790, "y": 1140, "wires": [ [ "f4024a26b3a29199" ] ] }, { "id": "7db32528bf7f76fc", "type": "function", "z": "c16b8cbf103f2790", "name": "Set Type", "func": "//let the block know if this is a homekit message\n\nmsg.payload.type = 1\nreturn msg;", "outputs": 1, "noerr": 0, "initialize": "", "finalize": "", "libs": [], "x": 980, "y": 1200, "wires": [ [ "8481af04ee2b053e" ] ] }, { "id": "d3f4e4f16291cc98", "type": "function", "z": "c16b8cbf103f2790", "name": "Set Type", "func": "//let the block know this is an mqtt message\n\nmsg.payload.type = 0\nreturn msg;", "outputs": 1, "noerr": 0, "initialize": "", "finalize": "", "libs": [], "x": 620, "y": 1140, "wires": [ [ "8481af04ee2b053e" ] ] }, { "id": "77f784e897f67411", "type": "mqtt out", "z": "c16b8cbf103f2790", "name": "Get all tasmotas state", "topic": "cmnd/tasmotas/STATE", "qos": "", "retain": "", "respTopic": "", "contentType": "", "userProps": "", "correl": "", "expiry": "", "broker": "", "x": 400, "y": 1100, "wires": [] }, { "id": "33f35c43712cd8d7", "type": "inject", "z": "c16b8cbf103f2790", "name": "", "props": [ { "p": "payload" }, { "p": "topic", "vt": "str" } ], "repeat": "", "crontab": "", "once": false, "onceDelay": 0.1, "topic": "", "payload": "", "payloadType": "date", "x": 140, "y": 1100, "wires": [ [ "77f784e897f67411", "82bda076a73b76b7" ] ] }, { "id": "bf58291f61a32484", "type": "homekit-bridge", "bridgeName": "NRB Front Room", "pinCode": "075-42-132", "port": "", "advertiser": "bonjour-hap", "allowInsecureRequest": false, "manufacturer": "NRCHKB", "model": "1.5.0", "serialNo": "Default Serial Number", "firmwareRev": "1.5.0", "hardwareRev": "1.5.0", "softwareRev": "1.5.0", "customMdnsConfig": false, "mdnsMulticast": true, "mdnsInterface": "", "mdnsPort": "", "mdnsIp": "", "mdnsTtl": "", "mdnsLoopback": true, "mdnsReuseAddr": true, "allowMessagePassthrough": true } ]
Beta Was this translation helpful? Give feedback.
All reactions