Skip to content

Instantly share code, notes, and snippets.

@bassicrob
Last active March 8, 2022 09:28
Show Gist options
  • Save bassicrob/19b6a16bba2bac1961b2bbc22d380d71 to your computer and use it in GitHub Desktop.
Save bassicrob/19b6a16bba2bac1961b2bbc22d380d71 to your computer and use it in GitHub Desktop.
HA Node Red Flow
[
{
"id": "43f03a36.8fbb04",
"type": "tab",
"label": "Beer Stats",
"disabled": false,
"info": "This node copied from:\nhttps://gist.github.com/bassicrob/19b6a16bba2bac1961b2bbc22d380d71\n\nSee my other gists for TiltPi flow to publish the required data to MQTT, and Lovelace card view.\n\nCheers!!"
},
{
"id": "a4a624df.14dbc8",
"type": "function",
"z": "43f03a36.8fbb04",
"name": "ABV Calc",
"func": "var beer_og = msg.payload.beer_og\nvar beer_cg = msg.payload.beer_specific_gravity\nvar x = beer_og-beer_cg\n\nvar beer_abv = (x*131.25).toFixed(2);\nmsg.payload = Number(beer_abv)\nreturn msg;",
"outputs": 1,
"noerr": 0,
"x": 820,
"y": 480,
"wires": [
[
"d4e4ddf0.bbc45",
"7f35f8d7.844598"
]
]
},
{
"id": "d4e4ddf0.bbc45",
"type": "debug",
"z": "43f03a36.8fbb04",
"name": "",
"active": false,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "false",
"x": 1010,
"y": 400,
"wires": []
},
{
"id": "4ecc807d.cdb6",
"type": "server-state-changed",
"z": "43f03a36.8fbb04",
"name": "Beer SG Current",
"server": "4a95221.a64d7dc",
"version": 1,
"exposeToHomeAssistant": false,
"haConfig": [
{
"property": "name",
"value": ""
},
{
"property": "icon",
"value": ""
}
],
"entityidfilter": "sensor.beer_specific_gravity",
"entityidfiltertype": "exact",
"outputinitially": true,
"state_type": "num",
"haltifstate": "",
"halt_if_type": "str",
"halt_if_compare": "is",
"outputs": 1,
"output_only_on_state_change": true,
"x": 210,
"y": 480,
"wires": [
[
"1db9d60e.2b3b8a"
]
]
},
{
"id": "737fb7d3.3bcef8",
"type": "server-state-changed",
"z": "43f03a36.8fbb04",
"name": "Beer OG",
"server": "4a95221.a64d7dc",
"version": 1,
"exposeToHomeAssistant": false,
"haConfig": [
{
"property": "name",
"value": ""
},
{
"property": "icon",
"value": ""
}
],
"entityidfilter": "input_number.beer_og",
"entityidfiltertype": "exact",
"outputinitially": true,
"state_type": "num",
"haltifstate": "",
"halt_if_type": "str",
"halt_if_compare": "is",
"outputs": 1,
"output_only_on_state_change": true,
"x": 200,
"y": 540,
"wires": [
[
"5d29086b.fa16e8"
]
]
},
{
"id": "a50d2331.d7079",
"type": "debug",
"z": "43f03a36.8fbb04",
"name": "",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "false",
"x": 990,
"y": 620,
"wires": []
},
{
"id": "e0e1ca6d.458968",
"type": "inject",
"z": "43f03a36.8fbb04",
"name": "",
"topic": "",
"payload": "1.061",
"payloadType": "num",
"repeat": "",
"crontab": "",
"once": false,
"onceDelay": 0.1,
"x": 250,
"y": 620,
"wires": [
[
"8863699b.96e0a8"
]
]
},
{
"id": "8863699b.96e0a8",
"type": "change",
"z": "43f03a36.8fbb04",
"name": "",
"rules": [
{
"t": "move",
"p": "payload",
"pt": "msg",
"to": "payload.beer_specific_gravity",
"tot": "msg"
}
],
"action": "",
"property": "",
"from": "",
"to": "",
"reg": false,
"x": 490,
"y": 460,
"wires": [
[
"499d473a.64fba8"
]
]
},
{
"id": "5d29086b.fa16e8",
"type": "change",
"z": "43f03a36.8fbb04",
"name": "",
"rules": [
{
"t": "move",
"p": "payload",
"pt": "msg",
"to": "payload.beer_og",
"tot": "msg"
}
],
"action": "",
"property": "",
"from": "",
"to": "",
"reg": false,
"x": 490,
"y": 500,
"wires": [
[
"499d473a.64fba8"
]
]
},
{
"id": "499d473a.64fba8",
"type": "join",
"z": "43f03a36.8fbb04",
"name": "",
"mode": "custom",
"build": "merged",
"property": "payload",
"propertyType": "msg",
"key": "topic",
"joiner": "\\n",
"joinerType": "str",
"accumulate": true,
"timeout": "",
"count": "2",
"reduceRight": false,
"reduceExp": "",
"reduceInit": "",
"reduceInitType": "",
"reduceFixup": "",
"x": 660,
"y": 480,
"wires": [
[
"a4a624df.14dbc8",
"7c34023a.e867fc"
]
]
},
{
"id": "7f35f8d7.844598",
"type": "mqtt out",
"z": "43f03a36.8fbb04",
"name": "",
"topic": "beer/abv/",
"qos": "",
"retain": "",
"broker": "4a3476ef.967ca8",
"x": 980,
"y": 480,
"wires": []
},
{
"id": "1db9d60e.2b3b8a",
"type": "traffic",
"z": "43f03a36.8fbb04",
"name": "",
"property_allow": "payload",
"filter_allow": "start",
"ignore_case_allow": true,
"negate_allow": false,
"send_allow": false,
"property_stop": "payload",
"filter_stop": "stop",
"ignore_case_stop": true,
"negate_stop": false,
"send_stop": false,
"default_start": false,
"differ": false,
"x": 470,
"y": 380,
"wires": [
[
"8863699b.96e0a8"
]
]
},
{
"id": "72d5420f.aa19ec",
"type": "inject",
"z": "43f03a36.8fbb04",
"name": "",
"topic": "",
"payload": "start",
"payloadType": "str",
"repeat": "",
"crontab": "",
"once": false,
"onceDelay": 0.1,
"x": 150,
"y": 360,
"wires": [
[
"1db9d60e.2b3b8a"
]
]
},
{
"id": "66a8c367.bfd94c",
"type": "inject",
"z": "43f03a36.8fbb04",
"name": "",
"topic": "",
"payload": "stop",
"payloadType": "str",
"repeat": "",
"crontab": "",
"once": false,
"onceDelay": 0.1,
"x": 150,
"y": 320,
"wires": [
[
"1db9d60e.2b3b8a"
]
]
},
{
"id": "52046b5c.97e3f4",
"type": "server-state-changed",
"z": "43f03a36.8fbb04",
"name": "Enable Logging",
"server": "4a95221.a64d7dc",
"version": 1,
"exposeToHomeAssistant": false,
"haConfig": [
{
"property": "name",
"value": ""
},
{
"property": "icon",
"value": ""
}
],
"entityidfilter": "switch.beer_logging",
"entityidfiltertype": "exact",
"outputinitially": true,
"state_type": "str",
"haltifstate": "",
"halt_if_type": "str",
"halt_if_compare": "is",
"outputs": 1,
"output_only_on_state_change": true,
"x": 120,
"y": 400,
"wires": [
[
"2f800f36.d40ca"
]
]
},
{
"id": "6a00937b.8c4abc",
"type": "mqtt in",
"z": "43f03a36.8fbb04",
"name": "",
"topic": "beer/logging/state/",
"qos": "2",
"datatype": "utf8",
"broker": "4a3476ef.967ca8",
"x": 110,
"y": 260,
"wires": [
[
"1db9d60e.2b3b8a"
]
]
},
{
"id": "da7bcf24.3fbdb",
"type": "comment",
"z": "43f03a36.8fbb04",
"name": "ABV = (og – fg) * 131.25",
"info": "",
"x": 810,
"y": 520,
"wires": []
},
{
"id": "1e37df5e.26ec21",
"type": "comment",
"z": "43f03a36.8fbb04",
"name": "Att = (og – fg) / (og-1)",
"info": "",
"x": 800,
"y": 640,
"wires": []
},
{
"id": "7c34023a.e867fc",
"type": "function",
"z": "43f03a36.8fbb04",
"name": "Attenuation Calc",
"func": "var beer_og = msg.payload.beer_og\nvar beer_cg = msg.payload.beer_specific_gravity\nvar x = beer_og-beer_cg\n\nvar beer_att = ((x/(beer_og-1))*100).toFixed(2);\nmsg.payload = Number(beer_att)\nreturn msg;",
"outputs": 1,
"noerr": 0,
"x": 840,
"y": 580,
"wires": [
[
"a50d2331.d7079",
"bc4ef9f5.a0cd88"
]
]
},
{
"id": "9acccf37.e2cb7",
"type": "inject",
"z": "43f03a36.8fbb04",
"name": "",
"topic": "",
"payload": "1.061",
"payloadType": "num",
"repeat": "",
"crontab": "",
"once": false,
"onceDelay": 0.1,
"x": 270,
"y": 680,
"wires": [
[
"5d29086b.fa16e8"
]
]
},
{
"id": "bc4ef9f5.a0cd88",
"type": "mqtt out",
"z": "43f03a36.8fbb04",
"name": "",
"topic": "beer/att/",
"qos": "",
"retain": "",
"broker": "4a3476ef.967ca8",
"x": 1020,
"y": 580,
"wires": []
},
{
"id": "2f800f36.d40ca",
"type": "change",
"z": "43f03a36.8fbb04",
"name": "Start Stop",
"rules": [
{
"t": "change",
"p": "payload",
"pt": "msg",
"from": "on",
"fromt": "str",
"to": "start",
"tot": "str"
},
{
"t": "change",
"p": "payload",
"pt": "msg",
"from": "off",
"fromt": "str",
"to": "stop",
"tot": "str"
}
],
"action": "",
"property": "",
"from": "",
"to": "",
"reg": false,
"x": 280,
"y": 400,
"wires": [
[
"1db9d60e.2b3b8a"
]
]
},
{
"id": "4a95221.a64d7dc",
"type": "server",
"z": "",
"name": "Home Assistant",
"legacy": false,
"rejectUnauthorizedCerts": true,
"ha_boolean": "",
"connectionDelay": false,
"cacheJson": true
},
{
"id": "4a3476ef.967ca8",
"type": "mqtt-broker",
"z": "",
"name": "",
"broker": "192.168.10.33",
"port": "1883",
"clientid": "",
"usetls": false,
"compatmode": true,
"keepalive": "60",
"cleansession": true,
"birthTopic": "",
"birthQos": "0",
"birthPayload": "",
"closeTopic": "",
"closeQos": "0",
"closePayload": "",
"willTopic": "",
"willQos": "0",
"willPayload": ""
}
]
@hapklaar
Copy link

hapklaar commented Apr 18, 2020

Hi there! I found your writeup on reddit and would like to try it out on my HA installation before my next brew :). I'm completely out of my depth with Node-RED for now. Do you have some sort of guide as to how I can get data from my Tilt via TiltPi into HA with what you have made? I already got Mosquitto set up in HA, receiving info from my Tasmota plugs.

What I did so far: I edited broker info then imported this flow into TiltPi's NR via clipboard import. It shows as a separate 'Beer Stats' flow in the NR GUI. Gave me some warning about unrecognised types (server & server-state-change) and warns again when I try to deploy. After deployment it notifies flows stopped because of these errors about missing node types. Clueless what to do next....

Hope to hear from you soon!

edit: got a little further after I found those missing types were provided by the home-assistant-websocket node. After installing that and adding the nodered add-on to HA, I now see a new mqtt client connected :)
1587220195: New client connected from 192.168.111.116 as mqtt_35cfade4.8a76d2 (p1, c1, k60).

Going to try and figure out what to do next...

@hapklaar
Copy link

Ah I seem to be getting the hang of Node-RED now :) Everything works!

I forgot a few things, will sum them up for the next one that has to deal with this:

  • Import Flow1 into Node-RED on TiltPi
  • Create a new link node on both Main and Flow1 flows, then connect them
  • Double click one of the mqtt nodes, then configure the server to point to your Mosquitto broker on HA. Don't forget authentication @ security tab and disable MQTT 3.1 support (in my case). Click update.
  • Deploy
  • Enter details in configuration.yaml, under sensors section
  • Install Node-RED add-on in HA from Supervisor, then import Beer Stats flow there. I made a mistake to import this one @ TiltPi as well. That's not required and as such it's also not needed to install home-assistant-websocket node there.
  • Double click any of the 'Beer*' state nodes, configure Server and select 'I use the Home Assistant Add-on'
  • Deploy
  • Enjoy

@bassicrob
Copy link
Author

Very cool! Glad to see you have it working. I've thought about simplifying this with what I've learned playing with HA, but this still just works. Next step is to brew some beer!
Including the reddit link for future reference: https://www.reddit.com/r/homeassistant/comments/b2e0ja/tiltpi_to_homeassistant_integration_via_nodered/

My current view:
Screenshot_20200418-130037_Home Assistant

@hapklaar
Copy link

Ah that's nice. Could you share the yaml of that view with me? How do you calculate the attenuation? And what does Beer Logging do? :)

@bassicrob
Copy link
Author

bassicrob commented Apr 18, 2020

The Lovelace card is this gist here: https://gist.github.com/bassicrob/7247065218290bf3551d40b16252132d
EDIT: This is a conditional card - only shows when the TiltPi is sending packets. I unplug my TiltPi when not fermenting, hence the beer_name sensor goes to 'unknown' after an hour or so and the card disappears from my Lovelace

I've since added an attenuation function node in the HA node-red flow.
image

image

var beer_og = msg.payload.beer_og
var beer_cg = msg.payload.beer_specific_gravity
var x = beer_og-beer_cg

var beer_att = ((x/(beer_og-1))*100).toFixed(2);
msg.payload = Number(beer_att)
return msg;

The beer logging is an MQTT switch that publishes Start or Stop to beer/logging/state/ and triggers a Traffic Light node in the beginning of the flow. This allows me to configure the Tilt (reset name from last brew), let the liquid settle after moving the fermentor to its resting location, and set my OG in HA from the input_number. Allows for cleaner graphs in the UI that are meaningful rather than a mess. I use the Tilt really to monitor when primary fermentation is complete, and that the yeast starts working in the first 24-36 hours. This step makes things look pretty ;) I will update the gist as well. Thanks for reminding me and glad others can enjoy it as well! Cheers!!

@hapklaar
Copy link

Thanks so much for sharing, really appreciate it! Hope your Isolation IPA turns out great ;)

@IainPHay
Copy link

Absolutely love what you have done here! I had started work on this myself and was using a homeassistant camera card to pull the graph from the google sheet but this implementation is just fabulous. Great work sir!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment