diff --git a/node-red/arm/data/flows.json b/node-red/arm/data/flows.json new file mode 100644 index 0000000..04d9971 --- /dev/null +++ b/node-red/arm/data/flows.json @@ -0,0 +1,33 @@ +[ + { + "id": "1f5f39f1.ca2cfe", + "type": "debug", + "z": "9c71f306.c8b968", + "name": "", + "active": true, + "console": "false", + "complete": "false", + "x": 481.5, + "y": 208, + "wires": [] + }, + { + "id": "5a211.3114d5efc", + "type": "inject", + "z": "9c71f306.c8b968", + "name": "", + "topic": "", + "payload": "", + "payloadType": "date", + "repeat": "", + "crontab": "", + "once": false, + "x": 265.5, + "y": 208, + "wires": [ + [ + "1f5f39f1.ca2cfe" + ] + ] + } +] diff --git a/node-red/arm/data/settings.js b/node-red/arm/data/settings.js new file mode 100644 index 0000000..b00c3ef --- /dev/null +++ b/node-red/arm/data/settings.js @@ -0,0 +1,184 @@ +/** + * Copyright 2013, 2016 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ + +// The `https` setting requires the `fs` module. Uncomment the following +// to make it available: +//var fs = require("fs"); + +module.exports = { + // the tcp port that the Node-RED web server is listening on + uiPort: process.env.PORT || 1880, + + // By default, the Node-RED UI accepts connections on all IPv4 interfaces. + // The following property can be used to listen on a specific interface. For + // example, the following would only allow connections from the local machine. + //uiHost: "127.0.0.1", + + // Retry time in milliseconds for MQTT connections + mqttReconnectTime: 15000, + + // Retry time in milliseconds for Serial port connections + serialReconnectTime: 15000, + + // Retry time in milliseconds for TCP socket connections + //socketReconnectTime: 10000, + + // Timeout in milliseconds for TCP server socket connections + // defaults to no timeout + //socketTimeout: 120000, + + // Timeout in milliseconds for HTTP request connections + // defaults to 120 seconds + //httpRequestTimeout: 120000, + + // The maximum length, in characters, of any message sent to the debug sidebar tab + debugMaxLength: 1000, + + // The file containing the flows. If not set, it defaults to flows_.json + flowFile: 'flows.json', + + // To enabled pretty-printing of the flow within the flow file, set the following + // property to true: + //flowFilePretty: true, + + // By default, all user data is stored in the Node-RED install directory. To + // use a different location, the following property can be used + //userDir: '/home/nol/.node-red/', + + // Node-RED scans the `nodes` directory in the install directory to find nodes. + // The following property can be used to specify an additional directory to scan. + //nodesDir: '/home/nol/.node-red/nodes', + + // By default, the Node-RED UI is available at http://localhost:1880/ + // The following property can be used to specifiy a different root path. + // If set to false, this is disabled. + //httpAdminRoot: '/admin', + + // Some nodes, such as HTTP In, can be used to listen for incoming http requests. + // By default, these are served relative to '/'. The following property + // can be used to specifiy a different root path. If set to false, this is + // disabled. + //httpNodeRoot: '/red-nodes', + + // The following property can be used in place of 'httpAdminRoot' and 'httpNodeRoot', + // to apply the same root to both parts. + //httpRoot: '/red', + + // When httpAdminRoot is used to move the UI to a different root path, the + // following property can be used to identify a directory of static content + // that should be served at http://localhost:1880/. + //httpStatic: '/home/nol/node-red-static/', + + // Securing Node-RED + // ----------------- + // To password protect the Node-RED editor and admin API, the following + // property can be used. See http://nodered.org/docs/security.html for details. + //adminAuth: { + // type: "credentials", + // users: [{ + // username: "admin", + // password: "$2a$08$zZWtXTja0fB1pzD4sHCMyOCMYz2Z6dNbM6tl8sJogENOMcxWV9DN.", + // permissions: "*" + // }] + //}, + + // To password protect the node-defined HTTP endpoints (httpNodeRoot), or + // the static content (httpStatic), the following properties can be used. + // The pass field is a bcrypt hash of the password. + // See http://nodered.org/docs/security.html#generating-the-password-hash + //httpNodeAuth: {user:"user",pass:"$2a$08$zZWtXTja0fB1pzD4sHCMyOCMYz2Z6dNbM6tl8sJogENOMcxWV9DN."}, + //httpStaticAuth: {user:"user",pass:"$2a$08$zZWtXTja0fB1pzD4sHCMyOCMYz2Z6dNbM6tl8sJogENOMcxWV9DN."}, + + // The following property can be used to enable HTTPS + // See http://nodejs.org/api/https.html#https_https_createserver_options_requestlistener + // for details on its contents. + // See the comment at the top of this file on how to load the `fs` module used by + // this setting. + // + //https: { + // key: fs.readFileSync('privatekey.pem'), + // cert: fs.readFileSync('certificate.pem') + //}, + + // The following property can be used to disable the editor. The admin API + // is not affected by this option. To disable both the editor and the admin + // API, use either the httpRoot or httpAdminRoot properties + //disableEditor: false, + + // The following property can be used to configure cross-origin resource sharing + // in the HTTP nodes. + // See https://github.com/troygoode/node-cors#configuration-options for + // details on its contents. The following is a basic permissive set of options: + //httpNodeCors: { + // origin: "*", + // methods: "GET,PUT,POST,DELETE" + //}, + + // If you need to set an http proxy please set an environment variable + // called http_proxy (or HTTP_PROXY) outside of Node-RED in the operating system. + // For example - http_proxy=http://myproxy.com:8080 + // (Setting it here will have no effect) + // You may also specify no_proxy (or NO_PROXY) to supply a comma separated + // list of domains to not proxy, eg - no_proxy=.acme.co,.acme.co.uk + + // The following property can be used to add a custom middleware function + // in front of all http in nodes. This allows custom authentication to be + // applied to all http in nodes, or any other sort of common request processing. + //httpNodeMiddleware: function(req,res,next) { + // // Handle/reject the request, or pass it on to the http in node + // // by calling next(); + // next(); + //}, + + // Anything in this hash is globally available to all functions. + // It is accessed as context.global. + // eg: + // functionGlobalContext: { os:require('os') } + // can be accessed in a function block as: + // context.global.os + + functionGlobalContext: { + // os:require('os'), + // octalbonescript:require('octalbonescript'), + // jfive:require("johnny-five"), + // j5board:require("johnny-five").Board({repl:false}) + }, + + // The following property can be used to order the categories in the editor + // palette. If a node's category is not in the list, the category will get + // added to the end of the palette. + // If not set, the following default order is used: + //paletteCategories: ['subflows', 'input', 'output', 'function', 'social', 'mobile', 'storage', 'analysis', 'advanced'], + + // Configure the logging output + logging: { + // Only console logging is currently supported + console: { + // Level of logging to be recorded. Options are: + // fatal - only those errors which make the application unusable should be recorded + // error - record errors which are deemed fatal for a particular request + fatal errors + // warn - record problems which are non fatal + errors + fatal errors + // info - record information about the general running of the application + warn + error + fatal errors + // debug - record information which is more verbose than info + info + warn + error + fatal errors + // trace - record very detailed logging + debug + info + warn + error + fatal errors + level: "info", + // Whether or not to include metric events in the log output + metrics: false, + // Whether or not to include audit events in the log output + audit: false + } + } +} diff --git a/node-red/arm/docker-compose.yml b/node-red/arm/docker-compose.yml index 7bb5eee..e787c1d 100644 --- a/node-red/arm/docker-compose.yml +++ b/node-red/arm/docker-compose.yml @@ -4,5 +4,6 @@ node-red: - "1880:1880" volumes: - ./data:/root/.node-red + - /dev/input:/dev/input privileged: yes restart: always diff --git a/node-red/arm/patch/36-rpi-gpio.js.patch b/node-red/arm/patch/36-rpi-gpio.js.patch new file mode 100644 index 0000000..5a6518c --- /dev/null +++ b/node-red/arm/patch/36-rpi-gpio.js.patch @@ -0,0 +1,20 @@ +--- a/36-rpi-gpio.js ++++ b/36-rpi-gpio.js +@@ -224,7 +224,7 @@ + this.butt = n.butt || 7; + var node = this; + +- node.child = spawn(gpioCommand+".py", ["mouse,node.butt]); ++ node.child = spawn(gpioCommand, ["mouse",node.butt]); + node.status({fill:"green",shape:"dot",text:"common.status.ok"}); + + node.child.stdout.on('data', function (data) { +@@ -270,7 +270,7 @@ + RED.nodes.createNode(this,n); + var node = this; + +- node.child = spawn(gpioCommand+".py", ["kbd","0"]); ++ node.child = spawn(gpioCommand, ["kbd","0"]); + node.status({fill:"green",shape:"dot",text:"common.status.ok"}); + + node.child.stdout.on('data', function (data) { diff --git a/node-red/arm/patch/README.md b/node-red/arm/patch/README.md new file mode 100644 index 0000000..410c657 --- /dev/null +++ b/node-red/arm/patch/README.md @@ -0,0 +1,4 @@ +Node-RED PATCH +============== + +python2 cannot read usb keyboard input device diff --git a/node-red/arm/patch/nrgpio b/node-red/arm/patch/nrgpio new file mode 100755 index 0000000..94c9671 --- /dev/null +++ b/node-red/arm/patch/nrgpio @@ -0,0 +1,9 @@ +#!/bin/bash + +BASEDIR=$(dirname $0) +if [[ $1 == mouse || $1 == kbd ]] +then + exec python3 -u $BASEDIR/nrinput.py $@ +else + sudo python -u $BASEDIR/nrgpio.py $@ +fi diff --git a/node-red/arm/patch/nrinput.py b/node-red/arm/patch/nrinput.py new file mode 100755 index 0000000..1e4c3bb --- /dev/null +++ b/node-red/arm/patch/nrinput.py @@ -0,0 +1,62 @@ +#!/usr/bin/env python3 + +import os +import struct +import subprocess +import sys +import time + +if sys.version_info < (3,0): + print("Sorry - currently only configured to work with python 3.x") + sys.exit(1) + +if len(sys.argv) > 2: + cmd = sys.argv[1].lower() + pin = int(sys.argv[2]) + + if cmd == "mouse": # catch mice button events + file = open( "/dev/input/mice", "rb" ) + oldbutt = 0 + + def getMouseEvent(): + global oldbutt + global pin + buf = file.read(3) + pin = pin & 0x07 + button = ord( chr(buf[0]) ) & pin # mask out just the required button(s) + if button != oldbutt: # only send if changed + oldbutt = button + print(button) + + while True: + try: + getMouseEvent() + except: + file.close() + sys.exit(0) + + elif cmd == "kbd": # catch keyboard button events + try: + while not os.path.isdir("/dev/input/by-path"): + time.sleep(10) + infile = subprocess.check_output("ls /dev/input/by-path/ | grep -m 1 'kbd'", shell=True).strip() + infile_path = "/dev/input/by-path/" + infile.decode() + EVENT_SIZE = struct.calcsize('llHHI') + file = open(infile_path, "rb") + event = file.read(EVENT_SIZE) + + while event: + (tv_sec, tv_usec, type, code, value) = struct.unpack('llHHI', event) + #if type != 0 or code != 0 or value != 0: + if type == 1: + # type,code,value + print("%u,%u" % (code, value)) + event = file.read(EVENT_SIZE) + print("0,0") + file.close() + sys.exit(0) + except: + file.close() + sys.exit(0) +else: + print("Bad parameters - mouse|kbd {pin}")