UPDATE: the logic in the js function is not quite right yet. I will post the correct version after further testing. I’ve messed up something in the if else if statement.
I wanted to have Alexa announce Dexcom G6 Blood Glucose level on-demand and when high or low.
The on-demand announcement does not require a Skill and uses only the node-red-contrib-amazon-echo pallette.
Make a “fake” light and discover it in the Alexa app. Create a routine to invoke the on function of the light. I suppose one could say: “Alexa, turn on Dexcom”. But “Alexa, what’s my blood sugar?” sounds better.
The fake light sends the “on” message to retrieve the current bg value and sends that to the notify Alexa. There is also a delay to send the light off command back to Alexa, so she doesn’t think that the light is already on, or always on.
That was the easy part.
Having Alexa announce on HA-State Change node got a bit more complicated.
There are essentially 5 combinations: normal, first high, sustained high, first low, and sustained low.
Normal bg values are ignored.
The difference between first and sustained is based on bg value being high/low and for a duration (2 hours high / 20 minutes low). The timer is invaluable to suppress further announcements AFTER the first announcement. I don’t need to know every 5 minutes that I’ve got a blood glucose event! Just a reminder to check again after taking corrective action(s).
Obviously, after a correction, a duration of time passes before desiring to know current bg value.
The other conditional is home vs not_home for my person in HA. No need to announce anything if I’m not home to hear.
I’m sure this isn’t finished yet, and I will continue to tweak as necessary.
But I wanted to share, because I hadn’t found anything quite like this when I was searching.
[{"id":"c4bca5dce2cfa066","type":"subflow","name":"Glucose Logic","info":"","category":"","in":[{"x":60,"y":90,"wires":[{"id":"fe09567a3d979fdb"}]}],"out":[{"x":540,"y":90,"wires":[{"id":"60516074ad6d4c12","port":0}]}],"env":[],"meta":{},"color":"#DDAA99"},{"id":"fe09567a3d979fdb","type":"api-current-state","z":"c4bca5dce2cfa066","name":"Glucose Value","server":"19e06289.dada3d","version":2,"outputs":1,"halt_if":"","halt_if_type":"str","halt_if_compare":"is","entity_id":"sensor.dexcom_glucose_value","state_type":"num","blockInputOverrides":false,"outputProperties":[{"property":"payload","propertyType":"msg","value":"","valueType":"entityState"},{"property":"data","propertyType":"msg","value":"","valueType":"entity"}],"override_topic":false,"state_location":"payload","override_payload":"msg","entity_location":"data","override_data":"msg","x":210,"y":90,"wires":[["60516074ad6d4c12"]]},{"id":"60516074ad6d4c12","type":"function","z":"c4bca5dce2cfa066","name":"high or low?","func":"var bg = msg.data.state;\n\nif (bg < 5.0) {\n msg.bg = {\n \"bg_state\" : \"low\",\n \"bg\" : bg\n }\n return msg;\n}\n\nif (bg >= 11.0) {\n msg.bg = {\n \"bg_state\" : \"high\",\n \"bg\" : bg\n }\n return msg;\n}\n\nif (bg >= 5.0 && bg < 11.0) {\n msg.bg = {\n \"bg_state\" : \"normal\",\n \"bg\" : bg\n }\n return msg;\n}\n\n","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":400,"y":90,"wires":[[]]},{"id":"a2c98a6ea52a48d9","type":"tab","label":"Dexcom","disabled":false,"info":""},{"id":"5604e44f3e298273","type":"group","z":"a2c98a6ea52a48d9","name":"Announce BG Events","style":{"fill":"#bfc7d7","label":true,"color":"#ff0000"},"nodes":["f90b6cc0512181a7","0e4a27e861732290","b273b80afdf1c009","dbd7b0bec2dd3fde","494e60774fa68223","90282257ae7a7348","21e755caad8eeffe"],"x":64,"y":394,"w":982,"h":247},{"id":"ed8b2cf5deecfb75","type":"group","z":"a2c98a6ea52a48d9","name":"Alexa Dexcom Light Routine","style":{"fill":"#bfdbef","label":true,"color":"#3f93cf"},"nodes":["9b7f264716a21ec1","a6e38bab64360584","75d3404140239634","71a7b969e91fa6b4","28187768adc0889c","763e40bed6358cc1","c48a65c2e37fa9c0","b5c5dec1ccaf0f3a"],"x":64,"y":49,"w":1212,"h":172},{"id":"aaa4a57205bd6a61","type":"api-call-service","z":"a2c98a6ea52a48d9","name":"Alexa Announce","server":"19e06289.dada3d","version":3,"debugenabled":false,"service_domain":"notify","service":"alexa_media_kitchen","entityId":"","data":"{\"data\":{\"type\":\"announce\"},\"message\":\"Michael's blood glucose is {{bg.bg}}, which is {{bg.bg_state}}. {{bg.message}}\"}","dataType":"json","mergecontext":"","mustacheAltTags":false,"outputProperties":[],"queue":"none","x":470,"y":300,"wires":[[]]},{"id":"a6e38bab64360584","type":"amazon-echo-device","z":"a2c98a6ea52a48d9","g":"ed8b2cf5deecfb75","name":"Dexcom","topic":"","x":350,"y":90,"wires":[["75d3404140239634"]]},{"id":"9b7f264716a21ec1","type":"link in","z":"a2c98a6ea52a48d9","g":"ed8b2cf5deecfb75","name":"Alexa talks to HAL","links":["be564bd7.ec5368"],"x":180,"y":90,"wires":[["a6e38bab64360584"]],"l":true},{"id":"75d3404140239634","type":"switch","z":"a2c98a6ea52a48d9","g":"ed8b2cf5deecfb75","name":"retrieve bg value","property":"payload","propertyType":"msg","rules":[{"t":"eq","v":"on","vt":"str"}],"checkall":"true","repair":false,"outputs":1,"x":550,"y":90,"wires":[["71a7b969e91fa6b4","28187768adc0889c"]]},{"id":"71a7b969e91fa6b4","type":"delay","z":"a2c98a6ea52a48d9","g":"ed8b2cf5deecfb75","name":"turn off in Alexa","pauseType":"delay","timeout":"1","timeoutUnits":"seconds","rate":"1","nbRateUnits":"1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"allowrate":false,"x":550,"y":180,"wires":[["763e40bed6358cc1"]]},{"id":"763e40bed6358cc1","type":"function","z":"a2c98a6ea52a48d9","g":"ed8b2cf5deecfb75","name":"Dexcom Alexa NodeID","func":"msg.nodeid=\"a6e38bab64360584\";\n\nvar alexa_id = msg.nodeid;\n\nmsg.payload = {\n on: false,\n nodeid: alexa_id\n}\n\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":810,"y":180,"wires":[["b5c5dec1ccaf0f3a"]]},{"id":"c48a65c2e37fa9c0","type":"link out","z":"a2c98a6ea52a48d9","g":"ed8b2cf5deecfb75","name":"Dexcom Announce","links":["ca36204d9e4fe957"],"x":1160,"y":90,"wires":[],"l":true},{"id":"ca36204d9e4fe957","type":"link in","z":"a2c98a6ea52a48d9","name":"Dexcom Announce","links":["c48a65c2e37fa9c0","95463530d5b57b3e","21e755caad8eeffe"],"x":210,"y":300,"wires":[["aaa4a57205bd6a61"]],"l":true},{"id":"b5c5dec1ccaf0f3a","type":"link out","z":"a2c98a6ea52a48d9","g":"ed8b2cf5deecfb75","name":"Dexcom \"light\" OFF to Alexa","links":["6728bba2.6521c4"],"x":1130,"y":180,"wires":[],"l":true},{"id":"f90b6cc0512181a7","type":"trigger-state","z":"a2c98a6ea52a48d9","g":"5604e44f3e298273","name":"Dexcom State","server":"19e06289.dada3d","version":0,"exposeToHomeAssistant":false,"haConfig":[{"property":"name","value":""},{"property":"icon","value":""}],"entityid":"sensor.dexcom_glucose_value","entityidfiltertype":"exact","debugenabled":false,"constraints":[{"targetType":"entity_id","targetValue":"person.michael","propertyType":"current_state","comparatorType":"is","comparatorValueDatatype":"str","comparatorValue":"home","propertyValue":"new_state.state"}],"outputs":4,"customoutputs":[{"messageType":"payload","messageValue":"on","messageValueType":"str","comparatorPropertyType":"current_state","comparatorType":">","comparatorValue":"11.0","comparatorValueDataType":"num","comparatorPropertyValue":"new_state.state"},{"messageType":"payload","messageValue":"on","messageValueType":"str","comparatorPropertyType":"current_state","comparatorType":"<","comparatorValue":"5","comparatorValueDataType":"num","comparatorPropertyValue":"new_state.state"}],"outputinitially":true,"state_type":"str","x":170,"y":450,"wires":[[],[],["0e4a27e861732290","b273b80afdf1c009"],["0e4a27e861732290","dbd7b0bec2dd3fde"]],"outputLabels":["at home","","high bg","low bg"]},{"id":"494e60774fa68223","type":"function","z":"a2c98a6ea52a48d9","g":"5604e44f3e298273","name":"first high or low?","func":"var old_state = msg.data.event.old_state.state;\nvar new_state = msg.data.event.new_state.state;\nvar bg = new_state;\n\nvar high_timer = flow.get(\"high_timer\");\nvar low_timer = flow.get(\"low_timer\");\n\nmsg.high_timer_status = high_timer;\nmsg.low_timer_status = low_timer;\n\n\nif ((old_state < 11) && (new_state >= 11) && (high_timer == \"on\")){\n msg.bg = {\n \"bg\" : bg,\n \"bg_state\" : \"high\",\n \"message\" : \"This is a new high event.\"\n }\n return msg;\n}\n\nelse if ((old_state >= 11) && (new_state >= 11) && (high_timer == \"off\")){\n msg.bg = {\n \"bg\" : bg,\n \"bg_state\" : \"high\",\n \"message\" : \"This is a sustained high event.\"\n }\n return msg;\n}\n\nelse if ((old_state >= 5) && (new_state < 5) && (low_timer == \"on\")){\n msg.bg = {\n \"bg\" : bg,\n \"bg_state\" : \"low\",\n \"message\" : \"This is a new low event.\"\n }\n return msg;\n}\n\nelse if ((old_state < 5) && (new_state < 5) && (low_timer == \"off\")){\n msg.bg = {\n \"bg\" : bg,\n \"bg_state\" : \"low\",\n \"message\" : \"This is a sustained low event.\"\n }\n return msg;\n}\n\nelse {\n msg.bg = {\n \"bg\" : bg,\n \"bg_state\" : \"normal\",\n \"message\" : \"Blood glucose is normal.\"\n }\n return msg;\n}","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":690,"y":600,"wires":[["21e755caad8eeffe"]],"outputLabels":["high bg"]},{"id":"95463530d5b57b3e","type":"link out","z":"a2c98a6ea52a48d9","name":"Dexcom Announce","links":["ca36204d9e4fe957"],"x":780,"y":960,"wires":[],"l":true},{"id":"28187768adc0889c","type":"subflow:c4bca5dce2cfa066","z":"a2c98a6ea52a48d9","g":"ed8b2cf5deecfb75","name":"Glucose Logic","env":[],"x":820,"y":90,"wires":[["c48a65c2e37fa9c0"]]},{"id":"21e755caad8eeffe","type":"link out","z":"a2c98a6ea52a48d9","g":"5604e44f3e298273","name":"Dexcom Announce","links":["ca36204d9e4fe957"],"x":930,"y":600,"wires":[],"l":true},{"id":"b273b80afdf1c009","type":"eztimer","z":"a2c98a6ea52a48d9","g":"5604e44f3e298273","name":"high_bg","debug":false,"autoname":" + 02:00:00","tag":"bg_timer","topic":"high_timer","suspended":false,"sendEventsOnSuspend":false,"latLongSource":"haZone","latLongHaZone":"zone.home","lat":"your_lat_here","lon":"your_long_here","timerType":"1","startupMessage":false,"ontype":"9","ontimesun":"dawn","ontimetod":"17:00","onpropertytype":"msg","onproperty":"payload","onvaluetype":"num","onvalue":1,"onoffset":0,"onrandomoffset":0,"onsuppressrepeats":true,"offtype":"3","offtimesun":"dusk","offtimetod":"dusk","offduration":"02:00:00","offpropertytype":"msg","offproperty":"payload","offvaluetype":"num","offvalue":0,"offoffset":0,"offrandomoffset":0,"offsuppressrepeats":false,"resend":false,"resendInterval":"0s","mon":true,"tue":true,"wed":true,"thu":true,"fri":true,"sat":true,"sun":true,"x":450,"y":450,"wires":[["90282257ae7a7348"]]},{"id":"dbd7b0bec2dd3fde","type":"eztimer","z":"a2c98a6ea52a48d9","g":"5604e44f3e298273","name":"low_bg","debug":false,"autoname":" + 00:20:00","tag":"low_bg","topic":"low_timer","suspended":false,"sendEventsOnSuspend":false,"latLongSource":"haZone","latLongHaZone":"zone.home","lat":"your_lat_here","lon":"your_lon_here","timerType":"1","startupMessage":false,"ontype":"9","ontimesun":"dawn","ontimetod":"17:00","onpropertytype":"msg","onproperty":"payload","onvaluetype":"num","onvalue":1,"onoffset":0,"onrandomoffset":0,"onsuppressrepeats":true,"offtype":"3","offtimesun":"dusk","offtimetod":"dusk","offduration":"00:20:00","offpropertytype":"msg","offproperty":"payload","offvaluetype":"num","offvalue":0,"offoffset":0,"offrandomoffset":0,"offsuppressrepeats":false,"resend":false,"resendInterval":"0s","mon":true,"tue":true,"wed":true,"thu":true,"fri":true,"sat":true,"sun":true,"x":450,"y":510,"wires":[["90282257ae7a7348"]]},{"id":"35d709d445182dce","type":"debug","z":"a2c98a6ea52a48d9","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":560,"y":810,"wires":[]},{"id":"edc649f6362ab85e","type":"function","z":"a2c98a6ea52a48d9","name":"testing timer flow set","func":"var high_timer_status = flow.get(\"high_timer\");\nvar low_timer_status = flow.get(\"low_timer\");\n\nmsg.high_timer_status = high_timer_status;\nmsg.low_timer_status = low_timer_status;\n\n return msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":370,"y":810,"wires":[["35d709d445182dce"]]},{"id":"54c03a01cd72bfd8","type":"inject","z":"a2c98a6ea52a48d9","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":180,"y":810,"wires":[["edc649f6362ab85e"]]},{"id":"90282257ae7a7348","type":"function","z":"a2c98a6ea52a48d9","g":"5604e44f3e298273","name":"set bg_timer status","func":"var topic = msg.topic;\nvar timer = msg.payload;\n\nif ((topic == \"high_timer\") && (timer == 1)){\n flow.set(\"high_timer\",\"on\");\n \n msg = {\n \"timer\" : \"high bg timer on\",\n \"_payload\" : \"on\"\n }\n \n return msg;\n}\n\nelse if ((topic == \"high_timer\") && (timer == 0)){\n flow.set(\"high_timer\",\"off\");\n \n msg = {\n \"timer\" : \"high bg timer off\",\n \"_payload\" : \"off\"\n }\n\n \n return msg;\n}\n\nelse if ((topic == \"low_timer\") && (timer == 1)){\n flow.set(\"low_timer\",\"on\");\n \n msg = {\n \"timer\" : \"low bg timer on\",\n \"_payload\" : \"on\"\n }\n \n return msg;\n}\n\nelse if ((topic == \"low_timer\") && (timer == 0)){\n flow.set(\"low_timer\",\"off\");\n \n msg = {\n \"timer\" : \"low bg timer on\",\n \"_payload\" : \"off\"\n }\n \n return msg;\n}","outputs":1,"noerr":0,"initialize":"// Code added here will be run once\n// whenever the node is started.\n\nflow.set(\"high_timer\",\"off\");\nflow.set(\"low_timer\",\"off\");","finalize":"","libs":[],"x":690,"y":480,"wires":[[]]},{"id":"0e4a27e861732290","type":"delay","z":"a2c98a6ea52a48d9","g":"5604e44f3e298273","name":"delay 3s","pauseType":"delay","timeout":"3","timeoutUnits":"seconds","rate":"1","nbRateUnits":"1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"allowrate":false,"x":450,"y":600,"wires":[["494e60774fa68223"]]},{"id":"19e06289.dada3d","type":"server","name":"Home Assistant","version":1,"legacy":false,"addon":true,"rejectUnauthorizedCerts":true,"ha_boolean":"y|yes|true|on|home|open","connectionDelay":true,"cacheJson":true}]