NodeJS Raspberry Pi & rpio Watch button not working - node.js

I've installed the rpio node module, the first time I ran it, I changed the pin to 33. It worked, and outputted some info and changed upon changing the state of the button. However, after stopping the script, then running it again it doesn't seem to work. I've tried a reboot and thats still given me no luck.
Here is my code:
var rpio = require('rpio');
var pin = 33;
console.log('test');
rpio.open(pin, rpio.INPUT, rpio.PULL_DOWN);
function pollcb(cbpin)
{
var state = rpio.read(cbpin) ? 'pressed' : 'released';
console.log('Button event on P%d (button currently %s)', cbpin, state);
}
rpio.poll(pin, pollcb);

Related

Using node.js, I cannot get the stdout from a macos app until the process finishes

I've created a helper app with Xcode. It's a command line app that keeps running using RunLoop (because it will do Bluetooth things in the background).
I want to spawn this app using node.js and read its output. I've sucessufully done this with other applications using the spawn method. However, with this MacOS app nothing is visible until the app finishes.
My node.js code:
const { spawn } = require('node:child_process')
const child = spawn(PROCESS)
child.stdout.on('data', data => {
console.log(data.toString());
})
My Swift code (helper app):
import Foundation
var shouldKeepRunning = true
print("app started")
let controller = Controller()
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + .seconds(10)) {
shouldKeepRunning = false
}
while shouldKeepRunning == true && RunLoop.current.run(mode: RunLoop.Mode.default, before: Date.distantFuture) {
}
In node.js app started is only printed after 10 seconds, when the app finishes. When running the app using Terminal, I see app started immediately.
Does anyone know why this happens and how it can be solved?
Thanks!
This question is actually the same: swift "print" doesn't appear in STDOut but 3rd party c library logs do when running in docker on ECS but instead of node.js Docker is not logging the output.
I fixed it by adding the following to the top of my code:
setbuf(stdout, nil)
This will make print() write to stdout directly without waiting for some buffer to be full first.

Why do I get this error in Node.js for my online game?

I have made an online multiplayer game where the backend is nodejs, and sometimes when people test it, they spam bullets or use a script to create lots of players, I get an error. I have limits for this, so there can only be 500 bullets and 20 players in the game, and they all disappear eventually, but even when it doesn't let people create too many bullets/players, when they try to, I get this error:
zlib.js:499
var newReq = self._handle.write(flushFlag,
^
TypeError: Cannot read property 'write' of null
at Zlib.callback (zlib.js:499:33)
I am using socket.io with express. There is nothing to do with zlib in my code, and those are the only npm dependencies I am using.
A very slimmed down version of the code I'm using (which should ideally not have been shared in any form):
//Dependencies
var express = require("express");
var app = express();
var server = require('http').Server(app);
var io = require('socket.io')(server);
var fs = require('fs');
/* a bunch of vars + config */
//Express
server.listen(7654);
//Some functions
//Socket.io Listeners
io.on('connection', function(socket) {
//Declare Player
socket.on("declare player", function (data) {
if (Object.keys(players).length > maxPlayers) return; //Make sure no more than 20 players
//If statements to check valid data was sent
var playerdata = {
//Player Data
};
//Referral code stuff
//Secret Names
switch (playerdata.name) {
//Secret player codes for powerups
}
playerSecrets[data.id] = data.secret;
players[data.id] = playerdata;
});
//Player Action
socket.on("player action", function (data) {
/* Player controls input, mostly redacted */
switch (data.action.command) {
case "shoot": //Shoot Bullet
players[data.id].score--;
if (bullets.length > maxBullets) return; //Maximum Bullets in Arena (500)
bullets.push({/*bullet data*/});
break;
}
});
});
//Kill Player
function kill(playerid) {
delete players[playerid];
delete playerSecrets[playerid];
}
//Generate stars
//Game loop
setInterval(function () {
//Emit gamedata to clients
io.emit("gamedata", {
players: players,
stars: stars,
bullets: bullets,
referrals: referralData
});
//For each player
for (var i = 0; i < Object.keys(players).length; i++) {
//Redacted
}
//For each bullet
for (var i = 0; i < bullets.length; i++) {
//Redacted
}
}, 1000 / tickSpeed);
I wonder if it's related to things being added to JSON/Arrays, because that is what happens when a player is created/a bullet is shot, and spamming those causes this to happen. See socket.on("player action" and socket.on("declare player".
We have had the same issue within same time frame. We did a full look through our dependencies for all uses of the core node library zlib... and found that the only one that changed in our dep list since seeing issue was the "ws" node module. This a dependency of engine.io, which in turn is a dependency of socket.io. https://github.com/socketio/engine.io/pull/564/commits/6a47059eb8164cdf4c6537a7fef6829c90a398f7
^ boom, engine.io bumped ws up 3 major versions and only released a minor version. So you picked this up if you bumped from socket.io 2.1.1 -> 2.2.0. That is because in between those versions they bumped their engine.io dep to point to the latest minor version:
https://github.com/socketio/socket.io/commit/190d22b46e3c2ed18413458a2106322f8bac99f5
I was experiencing the same troubles on Ubuntu. But when running the code on my Mac there was no error/bug.
It turned out I had forgotten to confirm the version of Node running on Ubuntu. Turned out to be V8.x is the latest version of NodeJS on Ubuntu's repos. Once I installed LTS with NVM, the bug/error immediately disappeared on Ubuntu as well.
For anyone who may have made this same mistake, check your version of Node first.

GPIO over Raspberry Pi 3 model B using Node.js

I am trying to blink the led using raspberry pi 3 model B,
I have all the required modules installed on my machine i.e. npm , nodejs , pi-gpio (fixed the minor changes to detect the gpio )
Code is :
var gpio = require("pi-gpio");
gpio.open(16, "output", function(err) {
gpio.write(16, 1, function() {
gpio.close(16);
});
});
//reading the data on the pin i.e pin : 16
gpio.open(16, "output", function (err) {
gpio.read(16, function (err, value) {
console.log("Data is "+ value);
gpio.close(16);
});
});
But above code throws error while running it,
node app.js
error :
Error when trying to open pin 16
gpio-admin : could not flush data to /sys/class/gpio/export : Device or resource busy
Thanks in advance
Any links where I can see the circuit diagram and code.
Concern : I dont want to change the platform i.e. node.js
pi-gpio which i am using is : https://github.com/rakeshpai/pi-gpio
pi-gpio is just writing to the GPIO device in the background so you can skip node.js and pi-gpio and do the same manually for testing purposes.
Example:
gpio.open(16, ...
# is the same as writing in terminal:
echo 16 > /sys/class/gpio/export
and
... "output" ...
# is the same as writing in terminal:
echo "out" > /sys/class/gpio/gpio16/direction
etc.
First of all, try rebooting the Pi and see if that takes care of the issue.
If that didn't help, try manually closing/unexporting the pin as root and then re-run the script.
# unexport the pin as root in case something's holding on to it
sudo echo 16 > /sys/class/gpio/unexport
The commands below basically constitute the pi-gpio API. These lines are what you would put in a shell script to control your GPIOs. Test them without sudo first in the order I've written them and if they don't work, try with sudo. If they still don't work, I think you have a wiring/hardware problem or need to change some system settings elsewhere.
# unexport the pin
sudo echo 16 > /sys/class/gpio/unexport
# export it again
sudo echo 16 > /sys/class/gpio/export
# make it an output
sudo echo "out" > /sys/class/gpio/gpio16/direction
# write a HIGH - is the LED on now?
sudo echo 1 > /sys/class/gpio/gpio16/value
# read the value of the pin - is it 1 after writing a 1 to the pin?
cat /sys/class/gpio/gpio16/value
# write a LOW - did it turn off?
sudo echo 0 > /sys/class/gpio/gpio16/value
Let's use 'rpio' module instead of 'pi-gpio'.
https://github.com/jperkin/node-rpio
It works fine on Pi3, zero etc.
As pi-gpio has already fixed the old and new sysPath (issue# https://github.com/rakeshpai/pi-gpio )
But it is dependent on quick2wire-gpio-admin lib.
So small fix required in quick2wire-gpio-admin
git clone https://github.com/quick2wire/quick2wire-gpio-admin.git
cd quick2wire-gpio-admin
The src/gpio-admin.c has
int size = snprintf(path, PATH_MAX, "/sys/devices/virtual/gpio/gpio%u/%s", pin, filename);
replace with :
int size = snprintf(path, PATH_MAX, GPIO_CLASS_PATH "gpio%u/%s", pin, filename);
Then go to cd quick2wire-gpio-admin directory
Then sudo make uninstall and
sudo make install
Then it is running fine.
The Code for is as follows : (filename : blinking12.js)
var gpio = require("pi-gpio");
var intervalId;
var durationId;
var gpioPin = 12;
gpio.open(gpioPin, "output", function (err) {
var on =1 ;
console.log("GPIO pin "+gpioPin+" is open toggling LED every 100mS for 10s");
intervalId = setInterval( function () {
gpio.write(gpioPin, on, function () {
on = (on + 1)% 2;
});
}, 100);
});
durationId = setTimeout (function () {
clearInterval(intervalId);
clearTimeout(durationId);
console.log('10 seconds blinking completed');
gpio.write(gpioPin, 0, function () {
gpio.close(gpioPin);
//process.exit(0);
});
}, 10000);
To run the code :
node blinking12.js
Output on my machine :
GPIO pin 12 is open toggling LED every 100mS for 10s
10 seconds blinking completed

Raspi-io: Error: Unknown pin "null"

I'm using the johnn-five and raspi-io packages for node and I'm trying to read the events created on a PIR motion sensor, but everytime I run the application, an error is thrown.
console
pi#raspberrypi ~/poc $ sudo node app.js
1439476578608 Device(s) RaspberryPi-IO
1439476578749 Connected RaspberryPi-IO
1439476578825 Repl Initialized
>> /home/pi/poc/node_modules/raspi-io/lib/index.js:316
throw new Error("Unknown pin \"" + pin + "\"");
^
Error: Unknown pin "null"
at Raspi._defineProperty.value (/home/pi/poc/node_modules/raspi-io/lib/index.js:316:17)
at Raspi.pinMode (/home/pi/poc/node_modules/raspi-io/lib/index.js:327:47)
at Motion.Controllers.PIR.initialize.value (/home/pi/poc/node_modules/johnny-five/lib/motion.js:27:17)
at new Motion (/home/pi/poc/node_modules/johnny-five/lib/motion.js:180:10)
at Board.<anonymous> (/home/pi/poc/app.js:9:16)
at Board.emit (events.js:104:17)
at process._tickDomainCallback (node.js:381:11)
package.js
{
"name": "poc",
"version": "0.0.1",
"main": "app.js",
"private": true,
"dependencies": {
"johnny-five": "0.8.86",
"raspi-io": "3.3.4"
}
}
app.js
var raspi = require('raspi-io');
var five = require('johnny-five');
var board = new five.Board({
io: new raspi()
});
board.on('ready', function() {
var motion = new five.Motion({pin: 'PI-17'});
motion.on('calibrated', function() {
console.log('calibrated');
});
motion.on('motionstart', function() {
console.log('motionstart');
});
motion.on('motionend', function() {
console.log('motionend');
});
});
However, the following code DOES seem to work:
snipped from another poc
var raspi = require('raspi');
var gpio = require('raspi-gpio');
raspi.init(function() {
var input = new gpio.DigitalInput({
pin: 'P1-17'
});
var logInput = function() {
console.log('Input 17: ' + input.read());
setTimeout(logInput, 1000);
};
logInput();
});
The Raspberry is a Rev. 2 model B.
The Motion detector I'm using is this one.
The cables are connected as follows (physical pin, taken from this schema)
Motion Sensor -> Pi
1 GND -> 6 GND
2 VDD -> 1 +3/V3 OUT
3 OUT -> 11 GPIO17
Any help would be greatly appreciated.
After more searching I came across this image.
It provided me with more insight on the WiringPi Pin numbers, BCM GPIO naming and P1 naming.
The pin GPIO0 on Pin 0 (BCM 17) seems to be throwing the error.
I switched to using pin GPIO4 on Pin 4 (BCM 23).
It doesn't really make sense why the 0 doesn't work, but for now, the poc I'm working on can progress again.
Your issue wasn't with any of your code, or a naming issue. You unfortunately chose poorly for which pin to use. P1-17 isn't able to accept an input, as it is dedicated 3.3v out. Choose another pin, and you should be fine.
Any pin reserved for I2C or Serial can't be used for regular GPIO function within Johnny Five, along with the dedicated power and ground pins which can't be used for IO, ever. As long as you avoid these ports, you'll be fine. A good resource on Raspberry Pi pinouts is here.

firmatajs, multiple Arduinos give timeout (johnny-five, cylonjs)

I have two Arduino unos flashed with the standard StandardFirmata and i'm trying the multi board demo with a simple node project (johnny-five npm package). Both arduinos work when I try them separately. with the following code:
var five = require("johnny-five");
var boardOne = new five.Board({ id: "A", port: "/dev/cu.usbmodem1d1141" });
boardOne.on("ready", function(){
var led = new five.Led({
pin: 13,
board: this
});
led.on();
});
node index.js
1418288836782 Connected /dev/cu.usbmodem1d1141
1418288836784 Repl Initialized
>>
When trying the multi board example I get:
Device or Firmware Error A timeout occurred while connecting to the Board.
Please check that you've properly flashed the board with the correct firmware.
var five = require("johnny-five");
var ports = [
{ id: "A", port: "/dev/cu.usbmodem1d1141" },
{ id: "B", port: "/dev/cu.usbmodem1d1131" }
];
new five.Boards(ports).on("ready", function(){
var led = new five.Led({
pin: 13,
board: this[0]
});
led.on();
});
Update #1:
Out of curiosity I tried to switch around the usb cables and got some different results:
1) Only one arduino seems to connect:
1418318698635 Device(s) /dev/cu.usbmodem1a1231,/dev/cu.usbmodem1a1241
1418318698642 Device(s) /dev/cu.usbmodem1a1241
1418318701849 Connected /dev/cu.usbmodem1a1231
1418318701850 Board ID: A
or 2) I get an error:
.../johnny-five-master/node_modules/firmata/lib/firmata.js:246
board.pins[pin].analogChannel = currentValue;
^
TypeError: Cannot set property 'analogChannel' of undefined
at Object.SYSEX_RESPONSE.(anonymous function) [as 106]
(.../johnny-five-master/node_modules/firmata/lib/firmata.js:246:35)
Update #2:
I did the above test with cylon.js and got the same results. Still no clue how to fix this :(
One arduino works fine, multiple do nothing. (Maybe an osx related problem?)
Update #3:
I added some logs in the johnny-five code and it's definitely a connection problem(I think!?). The second Arduino never responds. I switched the order of the arduinos and get the same result (first one connects, the other fails to respond). The connection is asynchronous, so maybe it gets blocked somewhere. The lights on both arduinos definitely show some action is going on.
node index.js
err: undefined --- type: connect --- io: /dev/tty.usbmodem1d1111
err: undefined --- type: connect --- io: /dev/tty.usbmodem1d1121
err: undefined --- type: ready --- io: /dev/tty.usbmodem1d1111
1418467187527 Connected /dev/tty.usbmodem1d1111
1418467187527 Board ID: A
1418467284327 Device or Firmware Error A timeout occurred while connecting to the Board.
Please check that you've properly flashed the board with the correct firmware.
Thanks to #izar for posting this and then bringing the question to us in the Johnny-Five gitter channel. From there, Divan Visagie (from Johnny-Five core team) worked to triage the bug and was able to confirm via reproduction. This revealed a bug in Firmata.js, where the options passed to Serialport were being extended by that class. Since the defaults object was reused and Object.assign is not a "deep" operation, the changes were being made to a reference, not a copy. The result was that the second initialization was getting a set of "defaults" that were loaded up with the first instance's own data. The issue was fixed by changing Firmata to use fresh defaults for every instance. Here's the patch

Resources