Find here a 'how to' for a use case of 'ntfy'.
'ntfy' is a way to send a notification in case you want to be informed about any issue rising up.
Up to now I used some email notification. It runs out of the box in nr, so it is easy to use. But I was looking for a smarter way, because you either need a dedicated email address for smarthome messages, or you increase the number of 'spam' in your productive account.
For those who want use their individual 'ntfy' server at home this post might be helpful.
I've found here a very good start for the usage of 'ntfy' in nr.
A function I missed is to send notifications from nr to my 'ntfy' server with user name and password set.
Imagine my (fake) setup is like this:
Server: https://myntfy.example.com
My user name: ntfy_user
My password: my_ntfy_password
After installing 'ntfy' in your home environment you probably know that it is possible to send messages using 'curl' form the CLI:
curl -d "Important Message" -u ntfy_user:my_ntfy_password ntfy.example.com/ntfy_topic
But how do I pass user and password if I want to use nr?
The solution is to add the topic 'Authorization' to the 'headers' object. 'Authorization' expects a code based on 'base64' as parameter. You can get this, at least on linux systems, via the CLI:
~$ echo -n 'ntfy_user:my_ntfy_password' | base64
bnRmeV91c2VyOm15X250ZnlfcGFzc3dvcmQ=
~$
So adding
let headers = {
'Title': title,
'Priority': priority,
'Tags': tags,
'Authorization': 'Basic bnRmeV91c2VyOm15X250ZnlfcGFzc3dvcmQ='
}
to the function within the subflow mentioned in the link above will be the solution for this special user with this special password.
Much smarter is to add an entry for user and password in the configuration of the subflow, beside 'server', 'topic' and all the others.
And then make something like this:
...
let user = env.get("user");
let password = env.get("password");
let Authorization = "";
if (user != "" && password != "") {
Authorization = 'Basic ' + new Buffer(user + ':' + password).toString('base64');
}
let headers = {
'Title': title,
'Priority': priority,
'Tags': tags,
'Authorization': Authorization
}
...
and you are done.
These are my modified nodes based on kitori's link above:
[{"id":"2fa00c98ec58c282","type":"subflow","name":"ntfy publish","info":"","category":"","in":[{"x":60,"y":80,"wires":[{"id":"f5615ba774f12910"}]}],"out":[{"x":800,"y":80,"wires":[{"id":"93bf5eeaec8ee2c9","port":0}]}],"env":[{"name":"server","type":"str","value":"https://ntfy.example.com"},{"name":"user","type":"str","value":""},{"name":"password","type":"str","value":""},{"name":"topic","type":"str","value":"smarthome"},{"name":"title","type":"str","value":""},{"name":"priority","type":"str","value":"3","ui":{"type":"select","opts":{"opts":[{"l":{"de":"Max priority"},"v":"5"},{"l":{"de":"High priority"},"v":"4"},{"l":{"de":"Default priority"},"v":"3"},{"l":{"de":"Low priority"},"v":"2"},{"l":{"de":"Min priority"},"v":"1"}]}}},{"name":"tags","type":"str","value":""}],"meta":{},"color":"#5eead4","icon":"font-awesome/fa-file-code-o","status":{"x":800,"y":120,"wires":[{"id":"c48d9f5358654b76","port":0}]}},{"id":"1d44384d38453f38","type":"tab","label":"ntfy - test","disabled":false,"info":"","env":[]},{"id":"ef85485fa68af1ae","type":"inject","z":"1d44384d38453f38","name":"","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"\"My other notification\" & $now()\t","payloadType":"jsonata","x":550,"y":80,"wires":[["95ba468b10b1f241"]]},{"id":"471ab16ca8421868","type":"debug","z":"1d44384d38453f38","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":990,"y":60,"wires":[]},{"id":"95ba468b10b1f241","type":"subflow:2fa00c98ec58c282","z":"1d44384d38453f38","name":"ntfy publish","env":[{"name":"server","value":"https://ntfy.example.com","type":"str"},{"name":"user","value":"ntfy_user","type":"str"},{"name":"password","value":"my_ntfy_password","type":"str"},{"name":"topic","value":"nodered","type":"str"},{"name":"title","value":"my_title","type":"str"},{"name":"priority","value":"5","type":"str"},{"name":"Title","value":"Test","type":"str"},{"name":"Priority","value":"5","type":"str"}],"x":790,"y":60,"wires":[["471ab16ca8421868"]]},{"id":"b884075d304ab43f","type":"websocket in","z":"1d44384d38453f38","name":"ntfy","server":"","client":"879565134ff524f5","x":550,"y":120,"wires":[["1eff0b8873cbc30c"]]},{"id":"d88dccba636bec08","type":"debug","z":"1d44384d38453f38","name":"","active":false,"tosidebar":true,"console":false,"tostatus":true,"complete":"true","targetType":"full","statusVal":"payload.message","statusType":"msg","x":990,"y":120,"wires":[]},{"id":"1eff0b8873cbc30c","type":"json","z":"1d44384d38453f38","name":"","property":"payload","action":"","pretty":false,"x":810,"y":120,"wires":[["d88dccba636bec08"]]},{"id":"2fda8ae306bcf7ad","type":"inject","z":"1d44384d38453f38","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"My notification","payloadType":"str","x":530,"y":40,"wires":[["95ba468b10b1f241"]]},{"id":"93bf5eeaec8ee2c9","type":"http request","z":"2fa00c98ec58c282","name":"","method":"POST","ret":"obj","paytoqs":"ignore","url":"","tls":"","persist":false,"proxy":"","insecureHTTPParser":false,"authType":"","senderr":false,"headers":[],"x":450,"y":80,"wires":[["c48d9f5358654b76"]]},{"id":"f5615ba774f12910","type":"function","z":"2fa00c98ec58c282","name":"headers + url","func":"let server = msg.server || env.get(\"server\");\nlet topic = msg.topic || env.get(\"topic\");\nlet title = msg.title || env.get(\"title\");\nlet priority = msg.priority || env.get(\"priority\") || 3\nlet tags = msg.tags || env.get(\"tags\") || ''\nlet user = env.get(\"user\");\nlet password = env.get(\"password\");\nlet Authorization = \"\";\n\nif (user != \"\" && password != \"\") {\n Authorization = 'Basic ' + new Buffer(user + ':' + password).toString('base64'); \n}\n\nlet headers = {\n 'Title': title,\n 'Priority': priority,\n 'Tags': tags,\n 'Authorization': Authorization\n// 'Authorization': 'Basic Z2VyaGFyZDpudGZ5'\n}\n\nmsg.headers = headers\n\nmsg.url = server + \"/\" + topic\n\nreturn msg;\n","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":250,"y":80,"wires":[["93bf5eeaec8ee2c9"]]},{"id":"c48d9f5358654b76","type":"change","z":"2fa00c98ec58c282","name":"statusCode","rules":[{"t":"set","p":"payload","pt":"msg","to":"statusCode","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":650,"y":120,"wires":[[]]},{"id":"879565134ff524f5","type":"websocket-client","path":"wws://ntfy.chomse.de/","tls":"","wholemsg":"false","hb":"0","subprotocol":"","headers":[]}]
Just a hint to users with iphones:
A lot of users claim that they cannot get the notification within their App without refreshing the screen and they do not get a 'ping' if a notification comes in.
The developer tells in his documentation (Configuration - ntfy):
You have to add
upstream-base-url: "https://ntfy.sh"
in your 'server.yml' of the ntfy-Server.
And now you are really done.