Node-RED farmOS library

Ah good stuff.

Glad you got going. Authentication is the the trickiest part.

Post up any issues you have with filtering, it likely won’t be Node-Red specific issues you run into and anyone who works with the farmOS API can help just the same. You are not limited to using the pre built nodes either now, if you know JS at all you can write your own functions in a function node and grab to token from the Global Variable.

Either way let us know how you get on and feel free to offer suggestions.

1 Like

I did have a lot of trouble getting the Oauth2 going and the farmos GET block. Started to mess around with it, got in too deep and now it’s working again with a minor facelift.

[{"id":"658a10db51914bd5","type":"subflow","name":"farmOS GET","info":"","category":"farmOS","in":[{"x":60,"y":160,"wires":[{"id":"095b676e3b19157d"},{"id":"b8fafcb461dfe2bd"}]}],"out":[{"x":1600,"y":180,"wires":[{"id":"cc97b07158070174","port":0}]}],"env":[{"name":"Source","type":"str","value":"path","ui":{"label":{"en-US":"API Source"},"type":"select","opts":{"opts":[{"l":{"en-US":"Load from Global Variable"},"v":"global"},{"l":{"en-US":"Load from Flow Variable"},"v":"flow"},{"l":{"en-US":"Enter below"},"v":"path"},{"l":{"en-US":"msg.payload"},"v":"msgpay"}]}}},{"name":"API","type":"str","value":"","ui":{"type":"input","opts":{"types":["str"]}}},{"name":"filter_source","type":"str","value":"none","ui":{"label":{"en-US":"Filter Source"},"type":"select","opts":{"opts":[{"l":{"en-US":"Load from Global Variable"},"v":"global"},{"l":{"en-US":"Load from Flow Variable"},"v":"flow"},{"l":{"en-US":"Enter below"},"v":"enter"},{"l":{"en-US":"N/A"},"v":"none"}]}}},{"name":"Filter","type":"str","value":"","ui":{"type":"input","opts":{"types":["str"]}}}],"meta":{},"color":"#C7E9C0","icon":"font-awesome/fa-leaf"},{"id":"90e52141bcc6f160","type":"http request","z":"658a10db51914bd5","name":"","method":"GET","ret":"obj","paytoqs":"ignore","url":"","tls":"","persist":false,"proxy":"","authType":"","senderr":false,"x":1250,"y":180,"wires":[["cc97b07158070174"]]},{"id":"cc97b07158070174","type":"function","z":"658a10db51914bd5","name":"Check for next","func":"var token = global.get('token');\nmsg.headers = {\n Authorization: \"Bearer \"+token\n}\n\n\nif (msg.payload.links != null && msg.payload.links.hasOwnProperty(\"next\")){\n msg.url = msg.payload.links.next.href;\n\n}else{\n msg.url = null;\n msg.complete = \"complete\";\n}\n\nif (msg.payload.links != null){\nconst endpoints = msg.payload.links;\nconst keys = Object.keys(endpoints);\nmsg.options = keys;\n}\n\nif (msg.statusCode == \"404\"){\n msg.payload = \"Not Found, Check url / enpoints are valid\"\n}\n\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":1440,"y":180,"wires":[["8a1fbce15d8543e7"]]},{"id":"8a1fbce15d8543e7","type":"switch","z":"658a10db51914bd5","name":"","property":"url","propertyType":"msg","rules":[{"t":"nnull"}],"checkall":"true","repair":false,"outputs":1,"x":1330,"y":120,"wires":[["90e52141bcc6f160"]]},{"id":"c4f8e1dacfa44eb0","type":"switch","z":"658a10db51914bd5","name":"Select endpoint","property":"Source","propertyType":"env","rules":[{"t":"eq","v":"path","vt":"str"},{"t":"eq","v":"global","vt":"str"},{"t":"eq","v":"flow","vt":"str"},{"t":"eq","v":"msgpay","vt":"str"}],"checkall":"true","repair":false,"outputs":4,"x":600,"y":180,"wires":[["3784fd0ee5ddbc24"],["2ea054243a98ec4f"],["1142bd88fac5c153"],["9f4232786fb1c85c"]]},{"id":"095b676e3b19157d","type":"switch","z":"658a10db51914bd5","name":"select filter","property":"filter_source","propertyType":"env","rules":[{"t":"eq","v":"enter","vt":"str"},{"t":"eq","v":"global","vt":"str"},{"t":"eq","v":"flow","vt":"str"},{"t":"eq","v":"none","vt":"str"}],"checkall":"true","repair":false,"outputs":4,"x":170,"y":160,"wires":[["5fdf316119c6ece8"],["071b140a3423b066"],["32c4c6f5cec139e3"],["7cc90e01acefd815"]]},{"id":"5fdf316119c6ece8","type":"change","z":"658a10db51914bd5","name":"From Entered value","rules":[{"t":"set","p":"filter","pt":"msg","to":"Filter","tot":"env"}],"action":"","property":"","from":"","to":"","reg":false,"x":370,"y":80,"wires":[["c4f8e1dacfa44eb0"]]},{"id":"071b140a3423b066","type":"change","z":"658a10db51914bd5","name":"From Global","rules":[{"t":"set","p":"filter","pt":"msg","to":"Filter","tot":"global"}],"action":"","property":"","from":"","to":"","reg":false,"x":350,"y":120,"wires":[["c4f8e1dacfa44eb0"]]},{"id":"32c4c6f5cec139e3","type":"change","z":"658a10db51914bd5","name":"From Flow","rules":[{"t":"set","p":"filter","pt":"msg","to":"Filter","tot":"flow"}],"action":"","property":"","from":"","to":"","reg":false,"x":350,"y":160,"wires":[["c4f8e1dacfa44eb0"]]},{"id":"7cc90e01acefd815","type":"change","z":"658a10db51914bd5","name":"From N/A","rules":[{"t":"set","p":"filter","pt":"msg","to":"","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":340,"y":200,"wires":[["c4f8e1dacfa44eb0"]]},{"id":"9f4232786fb1c85c","type":"change","z":"658a10db51914bd5","name":"From Entered value","rules":[{"t":"set","p":"api","pt":"msg","to":"payload","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":830,"y":240,"wires":[["3ec36b205817bf30"]]},{"id":"1142bd88fac5c153","type":"change","z":"658a10db51914bd5","name":"From Flow","rules":[{"t":"set","p":"api","pt":"msg","to":"api","tot":"flow"}],"action":"","property":"","from":"","to":"","reg":false,"x":810,"y":200,"wires":[["3ec36b205817bf30"]]},{"id":"2ea054243a98ec4f","type":"change","z":"658a10db51914bd5","name":"From Global","rules":[{"t":"set","p":"api","pt":"msg","to":"API_selection","tot":"global"}],"action":"","property":"","from":"","to":"","reg":false,"x":810,"y":160,"wires":[["3ec36b205817bf30"]]},{"id":"3784fd0ee5ddbc24","type":"change","z":"658a10db51914bd5","name":"From Entered value","rules":[{"t":"set","p":"api","pt":"msg","to":"API","tot":"env"}],"action":"","property":"","from":"","to":"","reg":false,"x":830,"y":120,"wires":[["3ec36b205817bf30"]]},{"id":"3ec36b205817bf30","type":"function","z":"658a10db51914bd5","name":"path","func":"var token = global.get('token');\nvar api = msg.api;\nconst filter = msg.filter;\n\n// Authorization \nmsg.headers = {};\nmsg.headers['Authorization'] = \"Bearer \"+token;\nmsg.headers['Accept'] = \"application/vnd.api+json\";\nmsg.headers['content-type'] = 'application/vnd.api+json';\n\n// convert '--' to '/'\napi=api.replace(\"--\",\"/\")\n\n// Add filters\nif (filter != null && filter.includes(\"Filter\")) {\nmsg.url = global.get('farmOSurl').concat('/api/' + api + '?' + filter);\n}\nelse {\nmsg.url = global.get('farmOSurl').concat('/api/' + api); \n}\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":1050,"y":180,"wires":[["90e52141bcc6f160","fb59630f4bbfdc63"]]},{"id":"fb59630f4bbfdc63","type":"debug","z":"658a10db51914bd5","name":"Http request","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":1270,"y":240,"wires":[]},{"id":"076ecfe27b86f69f","type":"debug","z":"658a10db51914bd5","name":"GET input","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":360,"y":260,"wires":[]},{"id":"b8fafcb461dfe2bd","type":"change","z":"658a10db51914bd5","name":"From block","rules":[{"t":"set","p":"filter","pt":"msg","to":"Filter","tot":"env"},{"t":"set","p":"source","pt":"msg","to":"Source","tot":"env"},{"t":"set","p":"api","pt":"msg","to":"API","tot":"env"},{"t":"set","p":"filter_source","pt":"msg","to":"filter_source","tot":"env"}],"action":"","property":"","from":"","to":"","reg":false,"x":210,"y":260,"wires":[["076ecfe27b86f69f"]]}]

Thanks, right now I’m just trying to get the filter to do anything…

Like a request doesn’t seem to work.
http://farmos.bwf/api/asset/compost?Filter[status]=archived
I need to get better acquainted with the whole thing…

2 Likes

Does that filter work for you just using the browser? (Logged in to your instance of course)

You can also filter using the API node just use asset/compost?Filter[status]=archived
And “get” as method

I take it you see a token saved in global variables and if you are modifying the flows this token is included in the header of any requests?

1 Like

Hey,

I figured it out, it is case sensitive filter…

Yes, I do have to bearer token in the global variables and it is included in the header of the requests.

3 Likes

Ah great you’ll be flying so. Probably should have spotted that, but it’s been a good while since I’ve looked at it.

There is another option to polling farmOS for changes that you may be interested in if you fancy getting your hands dirty with some code.

I started a discussion here: External notifications, webhooks, MQTT etc - #16 by Farmer-Ed and have some working code. Which again I haven’t looked at in a good while and probably needs some tidying still or redesign to fit in with Core farm_notification module

1 Like

I tried to install the module but got some error saying the module is not compatible with Drupal version from FarmOS 3.2.1.

I’m getting a little acquainted with the FarmOS API. Currently, slowly inching my way towards trying to submit to MQTT messages to comply to a unified namespace structure based on new log events in FarmOS.

I’m using United Manufacturing Hub as my Unified Namespace for my sensors and would like at least some Operational information logged through it for my dashboard in grafana.

I’m very new to Drupal and php so the learning curve right now is hitting me hard but I’d love to try and contribute to the notification module if possible. Just need some time to get up to speed on a lot of things.

2 Likes

I haven’t updated anything I’ve been working on for farmOS 3.x / Drupal 10. At the very minimum they may just need to be marked for Drupal 10 in the .info.yml file

Something like this:

name: Farm Notifications
description: Notifies events to external server by HTTP POST.
type: module
package: farmOS Contrib
core_version_requirement: ^9 || ^10
dependencies:

There may be other new issues and probably needs plenty of work anyway so use with caution, but it may give you a starting point.

Any contribution will be welcome, but it may be a complete redesign by the time I get back to it.

1 Like