Python Shell with setTimeout - javascript

I run a test.js with:
var power_meter = require('./power-meter');
var pm = new power_meter.PowerMeter();
function a() {
var power_instant = 123;
pm.broadcast(power_instant);
setTimeout(a, 249);
}
a();
The Output is
123
123
...
Now i want to import a value from a python script with python-shell with:
var PythonShell = require('python-shell');
var pyshell = new PythonShell('7powerx.py');
var power_meter = require('./power-meter');
var pm = new power_meter.PowerMeter();
pyshell.on('message', function (message) {
console.log(message);
var power_instant = message;
pm.broadcast (power_instant);
});
// end the input stream and allow the process to exit
// end the input stream and allow the process to exit
pyshell.end(function (err) {
if (err) throw err;
console.log('finished');
});
I have tried to set the "setTimeout(a, 249);"
a();
in any place but without any success.
The script started and do an output after circa 5 minutes, but then stops again and after a time it works again for a moment.
I need to place the "setTimeout" but no idea where.
Any idea?
Update.
I have in my pythonScript a time function, when i set this to 0.0 it works, but my Raspberry PI collapse. So is there a snych/timing problem.

The problem is solved:
For a looping process i need to start with:
var pyshell = new PythonShell('test.py',{scriptPath:"./", pythonOptions: ['-u']});
I hope this helps other, too!

Related

Configuring mock-cli

I'm trying to use mock-cli to stub process.arv in mocha tests for a cli app. I want to test that a message is console.logged when an incorrect argument ("imit") is passed to process.argv (as defined by commands).
I'm trying to adapt the example from the documentation but i don't think i have set everything up correctly.
it passes when i comment out "stdin: require('../mocks/fakeInputStream'), // Hook up a fake input stream" though i know it's not working correctly
it fails with TypeError: sourceStream.on is not a function when run as described below
Can someone see what I'm missing?
/index.js
var commands = ['init'];
function getGitHeadArgs() {
return process.argv.slice(2, process.argv.length);
}
if (getGitHeadArgs().length) {
if (!commands.includes(getGitHeadArgs()[0])) {
console.log("Silly Githead! That's not a githead command");
}
eval(getGitHeadArgs()[0])();
} else {
console.log("You didn't tell githead to do anything!");
}
/testIndex.js
var assert = require('assert');
var index = require('../index.js');
var mockCli = require("mock-cli");
describe("incorrect argument", function() {
it("imit throws an error if an invalid command is raised", function() {
var argv = ['node', '../index.js', 'imit']; // Fake argv
var stdio = {
stdin: require('../mocks/fakeInputStream'), // Hook up a fake input stream
stdout: process.stdout, // Display the captured output in the main console
stderr: process.stderr // Display the captured error output in the main console
};
var kill = mockCli(argv, stdio, function onProcessComplete(error, result) {
var exitCode = result.code; // Process exit code
var stdout = result.stdout; // UTF-8 string contents of process.stdout
var stderr = result.stderr; // UTF-8 string contents of process.stderr
assert.equal(exitCode, 0);
assert.equal(stdout, "Silly Githead! That's not a githead command\n");
assert.equal(stderr, '');
});
// Execute the CLI task
require('../index.js');
// Kill the task if still running after one second
setTimeout(kill, 1000);
});
Is ../mocks/fakeInputStream a valid path?
Is the object at ../mocks/fakeInputStream a valid instance of ReadableStream?
The source code is avalible at GitHub.
Make sure you meet the requirements for the captureStdin(sourceStream, callback) function.
The module uses that function to capture your fakeInputStream and pipe it into a captureStream.

Get line of error of a Nodejs eval

I'm wondering how I'd come about getting line error in eval.
eg.,
try {
eval("var hello = 5; hello hello");
} catch(err) {
console.log(err.line) // should print 2
}
Any help would be appreciated, thanks.
If you are in Node, i'd rather use the vm package as it is safer.
Here is a working solution
const vm = require('vm');
// this is the sandbox, it gives the scrip only access to these vars, which
makes it safer than a pure eval;
const sandbox = {
count: 2
};
try {
// create script to be ran
// I use backtick for new lines
const script = new vm.Script(
`count += 1;
throw new Error('test');`
);
// create the context from the sandbox
const context = new vm.createContext(sandbox);
// run the script
script.runInContext(context, {
lineOffset: 0,
displayErrors: true,
});
} catch(e) {
console.log('Line of error :', e.stack.split('evalmachine.<anonymous>:')[1].substring(0, 1))
}
Running this code will log Line of error: 3.
Here is the doc for the vm package: https://nodejs.org/api/vm.html

Get output on shell execute in js with ActiveXObject

i tried to get exe file callback result when i doing shell execute like this:
var oShell = new ActiveXObject("WScript.Shell");
var args = folderName + "\\dir\\scan.exe scan " + params.join(" ");
var ret = oShell.Run(args ,0 ,true);
but ret gaves me 0 for fail and 1 for success.
when i run the file in the cmd like this:
scan.exe arg1 arg2 arg3
this is return the correct result that i wanted : "test/test" and not 1...
what can i do?
tnx a lot
I know I might be a bit late to answer this question but I hope it can still help someone.
The way I achieved it was with the oShell.Exec() function and not with the oShell.Run().
oShell.Exec() returns an object with a property called StdOut which acts like a text file, so you can perform ReadLine(), ReadAll(), etc.
The problem is that it does not wait for the command to end, so when you run your code, it is very likely that your StdOut object will be undefined. You have to add that waiting option on the command itself.
var wshShell = new ActiveXObject("WScript.Shell");
try {
// Excecute the 'cd' command.
wshShell.CurrentDirectory = "C:\\Users";
var execOut = wshShell.Exec('cmd /C start /wait /b cd');
}
catch (e) {
console.log(e);
}
// Get command execution output.
var cmdStdOut = execOut.StdOut;
var line = cmdStdOut.ReadLine();
console.log(line);
The code above will execute a cd command on the directory C:\Users and store the output on the line variable.
I hope this answers the question.
Using a shell to receive output from BATCH file:
script.js
var pathToFile = "your_path_here"
var shell= new ActiveXObject("WScript.shell");
var output = shell.Exec(pathToFile + 'example.bat');
var response = output.StdOut.ReadLine();
console.log(response)
example.bat
#ECHO OFF
echo Hello From Batch World
exit 0

How do I call a Python function from Node.js?

I'm working on making a Homebridge plugin for a project. Homebridge is a Node.js server which I have running on a Raspberry Pi which emulates an Apple HomeKit Bridge.
Using this link, I was able to execute Python code from the following Node.js code:
var Service, Characteristic;
var spawn = require('child_process').spawn;
var py = spawn('python', ['/home/pi/Desktop/RFbulb/nRF24L01PLUS.py']);
var data = [10,10,10];
var dataString = '';
var RFstatus = true;
module.exports = function(homebridge) {
Service = homebridge.hap.Service;
Characteristic = homebridge.hap.Characteristic;
homebridge.registerAccessory("homebridge-RFbulb", "RFbulb", RFbulbAccessory);
}
function RFbulbAccessory(log, config) {
this.log = log;
this.config = config;
this.name = config["name"];
this.address = config["address"];
this.service = new Service.Lightbulb(this.name);
this.service
.getCharacteristic(Characteristic.On)
.on('get', this.getOn.bind(this))
.on('set', this.setOn.bind(this));
}
RFbulbAccessory.prototype.setOn = function(on, callback) { // This is the function throwing the error
var state = on ? "on": "off";
if (state == "on") {
data = [1,parseInt(this.address, 10),100];
dataString = '';
py.stdout.on('data', function(data) {
dataString += data.toString();
});
py.stdout.on('end', function() {
console.log(dataString);
});
py.stdin.write(JSON.stringify(data));
py.stdin.end();
RFstatus = true;
}
callback(null);
}
RFbulbAccessory.prototype.getServices = function() {
return [this.service];
}
Interestingly enough, when I activate the setOn function the first time (for example, to turn the device on) it works fine, but when I activate the setOn function a second time (to turn the device off) I get the following errors and the server exits:
events.js:141
throw er; // Unhandled 'error' event
^
Error: write after end
at writeAfterEnd (_stream_writable.js:166:12)
at Socket.Writable.write (_stream_writable.js:211:5)
at Socket.write (net.js:642:40)
at RFbulbAccessory.setOn (/usr/lib/node_modules/homebridge-RFbulb/index.js:47:12)
at emitThree (events.js:97:13)
at emit (events.js:175:7)
at Characteristic.setValue (/usr/lib/node_modules/homebridge/node_modules/hap-nodejs/lib/Characteristic.js:155:10)
at Bridge.<anonymous> (/usr/lib/node_modules/homebridge/node_modules/hap-nodejs/lib/Accessory.js:710:22)
at Array.forEach (native)
at Bridge.Accessory._handleSetCharacteristics (/usr/lib/node_modules/homebridge/node_modules/hap-nodejs/lib/Accessory.js:655:8)
What could be causing this error? Especially since the function appears to work fine for a single use.
You're getting that error because you're closing the input stream:
py.stdin.end();
After a stream has been closed, you can no longer write to it like you are here:
py.stdin.write(JSON.stringify(data));
If the Python program you're running accepts multiple commands over STDIN then simply remove the py.stdin.end() line.
However, it's likely that your Python program runs once then completes. If that's the case, you will need to respawn the process every time you want the program to run.
if (state === "on") {
py = spawn('python', ['/home/pi/Desktop/RFbulb/nRF24L01PLUS.py']);
...
}

Node.js filesystem save file error 56 EROFS while saving every 2 seconds

I am running node.js on raspbian and trying to save/update a file every 2/3 seconds using the following code:
var saveFileSaving = false;
function loop() {
mainLoop = setTimeout(function() {
// update data
saveSaveFile(data, function() {
//console.log("Saved data to file");
loop();
});
}, 1500);
}
function saveSaveFile(data, callback) {
if(!saveFileSaving) {
saveFileSaving = true;
var wstream = fs.createWriteStream(path.join(__dirname, 'save.json'));
wstream.on('finish', function () {
saveFileSaving = false;
callback(data);
});
wstream.on('error', function (error) {
console.log(error);
saveFileSaving = false;
wstream.end();
callback(null);
});
wstream.write(JSON.stringify(data));
wstream.end();
} else {
callback(null);
}
}
When I run this it works fine for an hour then starts spitting out:
[25/May/2016 11:3:4 am] { [Error: EROFS, open '<path to file>']
errno: 56,
code: 'EROFS',
path: '<path to file>' }
I have tried jsonfile plugin which also sends out a similiar write error after an hour.
I have tried both fileSystem.writeFile and fileSystem.writeFileSync both give the same error after an hour.
I was thinking it had to do with the handler not being let go before a new save occurs which is why I started using the saveFileSaving flag.
Resetting the system via hard reset fixes the issue (soft reset does not work as the system seems to be locked up).
Any suggestions guys? I have searched the web and so only found one other question slightly similar from 4 years ago which was left in limbo.
Note: I am using the callback function from the code to continue with the main loop.
I was able to get this working by unlinking the file and saving the file every time I save while it is not pretty it works and shouldn't cause too much overhead.
I also added a backup solution which saves a backup every 5 minutes in case the save file has issues.
Thank you for everyone's help.
Here is my ideas:
1) Check free space when this problem happens by typing in terminal:
df -h
2) Also check if file is editable when problem occurs. with nano or vim and etc.
3) Your code too complicated for simply scheduling data manipulation and writing it to file. Because of even Your file will be busy (saveFileSaving) You will lose data until next iteration, try to use that code:
var
async = require('async'),
fs = require('fs'),
path = require('path');
async.forever(function(next) {
// some data manipulation
try {
fs.writeFileSync(path.join(__dirname, 'save.json'), JSON.stringify(data));
}
catch(ex) {
console.error('Error writing data to file:', ex);
}
setTimeout(next, 2000);
});
4) How about keeping file descriptor open?
var
async = require('async'),
fs = require('fs'),
path = require('path');
var file = fs.createWriteStream(path.join(__dirname, 'save.json'));
async.forever(function(next) {
// some data manipulation
file.write(JSON.stringify(data));
setTimeout(next, 2000);
});
var handleSignal = function (exc) {
// close file
file.end();
if(exc) {
console.log('STOPPING PROCESS BECAUSE OF:', exc);
}
process.exit(-1);
}
process.on('uncaughtException', handleSignal);
process.on('SIGHUP', handleSignal);
5) hardware or software problems (maybe because of OS drivers) with raspberry's storage controller.

Categories