gps module stops outputting information - node.js

To be as concise as possible, I am connecting to a telit ME910c1-nv socket modem made by multitech. It's not really relevant but I know someone will think this issue is hardware related when it's not.
The device has both a 4g cat m-1 modem and a gps module built in. I connect to these over UART to a raspberry pi.
The issue is that when I send AT commands to get the GPS location, eventually the module will stop sending and/or my code can no longer read from the serial port.
I am using node js to communicate with the module but I have also had the same issue with python. I have no issues in C though, which makes me think it is a higher level programming issue and timing issue.
An basic example is:
getGpsData=(modem, callback)=>{
modem.write("AT$GPSACP\r");
const timer = setTimeout( ()=>{
callback(null);
}, 5000); //wait 5 sec before returning null
modem.on('readable', readRaw=()=>{
let data = modem.read();
let output = "";
if(data){
data = data.toString();
output += data;
if(data.includes(escape_character)){ //escape character is "OK" or "ERROR"
clearTimeout(timer);
callback(output);
}
}
});
}
//connect to serial port
modem = new serialport("/dev/serial0");
on.('connect', ()=>{
//on connect read gps data at constant interval
setInterval(()=>{
getGpsData(modem, (data)=>{
modem.removeListener('readable', rawRead);
console.log(data);
}
}, 10000); //loop every 10 sec
});
When I run this, I will get about 10 - 20 gps readings and then all nulls. When I stop my code and start it again, it works fine. Sometimes it runs for an hour or more without any issues and then starts producing nulls and never recovers. If I connect directly to the modem and send it AT commands, I don't get this issue at all. It's as if my reads are out of sync with what the module it writing to the serial port.
The output from the module comes as:
$gpsacp: "gpsdata..........."
OK
I get null data reads because it times out and my escape character is never read. Sometimes I'll get the "OK" escape character and null data also.
I've rewritten my command and read function multiple times but always suffer the same issue. Anyone have any idea why this is happening or had similar experience?

Related

Johnny-Five, I2C, Controlling multiple temperature sensors using ESP8266

I'm trying figure out how to control multiple temperature sensors.
THE SETUP:
2 ESP8266 Micro Controllers
2 MCP9808 Temperature Sensors
1 Machine controlling both ESPs using Johnny-Five.
NOTE: Each ESP8266 micro controller handles one MCP9808 Temperature Sensor.
THE GOAL:
The central machine (MacOS running Johnny-Five) handles both microcontrollers under one Node JS script.
THE PROBLEM:
I can control one Micro Controller / Temperature pairing, but not both under the same script.
Apparently the key to handling both at once lies in knowing how to handle the IC2 addressing.
So far I haven't been able to find any pages, forums, instructions or combinations thereof that clearly explain the logic in terms that I can understand.
THE QUESTION:
How to handle I2C using Johnny-Five to control multiple devices
THE CODE:
It only works when handling one Sensor, not both
In other words with the 4th line commented out it works. Uncommented, it doesn't.
var five = require("johnny-five");
var {EtherPortClient}=require("etherport-client");
var Thermometers=[
//{Name:"Thermometer1", Ip:"192.168.1.101"}, //Uncommenting causes fail.
{Name:"Thermometer2", Ip:"192.168.1.102"}
];
TrackThermometers();
function TrackThermometers(){
Thermometers.forEach(function(ThisThermometer, ThermometerCount){
ThisThermometer.Board=new five.Board({
port: new EtherPortClient({
host: ThisThermometer.Ip,
port: 3030
}),
repl: false
});
ThisThermometer.Board.on("ready", function(){
ThisThermometer.Controller=new five.Thermometer({ //This cmd triggers the error
controller:"MCP9808"
});
ThisThermometer.Controller.on("change", function(){
console.log(this.id, this.fahrenheit);
});
})
});
}
SOLUTION
There is a board property (undocumented as of this post) under the J5's Thermometer API. Assigning the Board instance in question to that property associates the Thermometer instance with that board.
By way of example the above code would be edited as follows...
ThisThermometer.Controller=new five.Thermometer({
board: ThisThermometer.Board, //<-- the missing magic
controller:"MCP9808"
});
Thanks to Donovan Buck for figuring this out. May be documented soon.

Error [ERR_STREAM_DESTROYED]: Cannot call write after a stream was destroyed

Context:
I've created what I called a softmodem-poetry machine, using two softmodems transmitters to transmit synchronously two different twitter streams at the same baud rate, creating an entanglement of quasi-gibberish/quasi-legible signals coming both from softmodem 1 and softmodem 2. These programs were running three months ago.
Problem:
When I try running these programs now, I have this Error [ERR_STREAM_DESTROYED]: Cannot call write after a stream was destroyed as soon as I connect to my socket.
Here's the relevant code I think:
twit.stream("statuses/filter", { track: randomTitle}, function(stream) {
stream.on("data", function(data) {
socket.emit("tweet", data.text);
child.stdin.write(data.text);
});
});`
Here's the entire code: https://github.com/cyruslk/twitter_minimodem/blob/master/app.js
grant wrx access to log files, like chmod 777.

Firebase onDisconnect() firing multiple times

Building an app with presence following the firebase docs, is there a scenario where the on-disconnect fires when the app is still connected? We see instances where the presence node shows the app as going offline and then back online within a few seconds when we aren't losing a network connection.
We are seeing on multiple embedded devices installed in the field where presence is set to false and then almost immediately right back to true and it's occurring on all the devices within a few seconds of each other. From the testing we have done and the docs online we know that if we lose internet connection on the device it takes roughly 60 seconds before the timeout on the server fires the onDisconnect() method.
We have since added code in the presence method that allows the device if it sees the presence node be set to false while the app is actually running it will reset the presence back to true. At times when this happens we get a single write back to true and that is the end of it, other times it is like the server and client are fighting each other and the node is reset to true numerous times over the course of 50-200 milliseconds. We monitor this by pushing to another node within the device GUID each time we are forcing presence back to true. This only occurs while the module is running and after it initially establishes presence.
Here is the method that we call from our various modules that are running on the device so that we can monitor the status of each of the modules at any given time.
exports.online = function (program, currentProgram) {
var programPath = process.env.FIREBASE_DEVICES + process.env.GUID + '/status/' + program
var onlinePath = process.env.FIREBASE_DEVICES + process.env.GUID + '/statusOnlineTimes/' + program
var programRef = new firebase(programPath);
var statusRef = new firebase(process.env.FIREBASE_DEVICES + process.env.GUID + '/status/bootup');
var onlineRef = new firebase(onlinePath)
amOnline.on('value', function(snapshot) {
if (snapshot.val()) {
programRef.onDisconnect().set(false);
programRef.set(true);
programRef.on('value', function(snapshot){
if (snapshot.val() == false){
programRef.set(true);
console.log('[NOTICE] Resetting', program, 'module status back to True after Fireabase set to False')
var objectToPush = {
program: program,
time: new Date().toJSON()
}
onlineRef.push(objectToPush)
}
})
if (currentProgram != undefined) {
statusRef.onDisconnect().set('Offline')
statusRef.set(currentProgram)
}
}
});
The question we have is there ever an instance where Firebase is calling the onDisconnect() method even though it really isn't losing its status? We had instances where we would see the device go offline and then back online within 60 seconds before we added the reset code. The reset code was to combat another issue we had in the field where if the power were interrupted to the device and it did not make a clean exit, the device could reboot and and reset the presence with a new UID before the timeout for the prior instance had fired. Then once the timeout fired the device would show as offline even though it was actually online.
So we were able to stop the multiple pushes that were happening when the device reconnected by adding a programRef.off() call directly before the programRef.on(...) call. What we determined to be happening is that anytime the device went online from an offline state and the amOnline.on(...) callback fired it created a new listener.
Now we are able to handle the case where a onDisconnect() fires from a earlier program PID and overwrites the currently active program with a status of offline. This seems to solve the issue we are having with the race condition of the devices in the field able to reboot and regain connection prior to the onDisconnect() firing for the instance that was not cleanly exited.
We are still having an issue where all of the devices are going off and then back online at approximately the same time (within 1-3 seconds of each other). Are there any times where Firebase resets the ./info/connected node? Because we are monitoring presence and actually logging on and off events maybe we are just catching an event that most people don't see? Or is there something that we are doing wrong?

Handling chunked responses from process.stdout 'data' event

I have some code which I can't seem to fix. It looks as follows:
var childProcess = require('child_process');
var spawn = childProcess.spawn;
child = spawn('./simulator',[]);
child.stdout.on('data',
function(data){
console.log(data);
}
);
This is all at the backend of my web application which is running a specific type of simulation. The simulator executable is a c program which runs a loop waiting to be passed data (via its standard input) When the inputs come in for the simulation (ie from the client), I parse the input, and then write data to the child process stdin as follows:
child.stdin.write(INPUTS);
Now the data coming back is 40,000 bytes give or take. But the data seems to be getting broken into chunks of 8192 bytes. I've tried fixing the standard output buffer of the c program but it doesnt fix it. I'm wondering if there is a limit to the size of the 'data' event that is imposed by node.js? I need it to come back as one chunk.
The buffer chunk sizes are applied in node. Nothing you do outside of node will solve the problem. There is no way to get what you want from node without a little extra work in your messaging protocol. Any message larger than the chunk size will be chunked. There are two ways you can handle this issue.
If you know the total output size before you start to stream out of C, prepend the message length to the data so the node process knows how many chunks to pull before terminating the entire message.
Determine a special character you can append to the message you are sending from the C program. When node sees that character, you end the input from that message.
If you are dealing with IO in a web application you really want to stick with the async methods. You need something like the following (untested). There is a good sample of how to consume the Stream API in the docs
var data = '';
child.stdout.on('data',
function(chunk){
data += chunk;
}
);
child.stdout.on('end',
function(){
// do something with var data
}
);
I ran into the same problem. I tried many different things and was starting to get annoyed. I tried prepending and appending with special characters. Maybe I was stupid but I just couldn't get it right.
I ran into a module called linerstream which basically parses every chunk until it sees an EOF. You can use it like this:
process.stdout.pipe(new Linerstream()).on('data', (data) => {
// data here is complete and not chunked
});
The important part is that you do have to write data to stdout with a line that ends with EOF. Otherwise it doesn't know it is the end.
I can say this worked me. Hopefully it helps other people.
ppejovic's solution works, but I prefer concat-stream.
var concat = require('concat-stream');
child.stdout.pipe(concat(function(data) {
// all your data ready to be used.
});
There are a number of good stream helpers worth looking into based on your problem area. Take a look at substack's stream-handbook.

nodejs - reading from the serial port

I've been looking around for an answer on this...
Basically, I want to read data from the serial port (in this case, over USB). I've looked into the node-serialport module but it keeps stalling after the first result form the serial port. I expected it to just spit out the data when it received it. It's as if a buffer is filling up and needs to be flushed somehow?
I've slightly modified the code from the demos I found here - https://github.com/voodootikigod/node-serialport/tree/master/tests
Here's my code:
var sys = require("sys"),
repl = require("repl"),
serialPort = require("serialport").SerialPort;
// Create new serialport pointer
var serial = new serialPort("/dev/tty.usbmodem1d11" , { baudrate : 9600 });
// Add data read event listener
serial.on( "data", function( chunk ) {
sys.puts(chunk);
});
serial.on( "error", function( msg ) {
sys.puts("error: " + msg );
});
repl.start( "=>" );
I'm using an Arduino hence the 9600 baudrate.
Any help would be awesome, cheers,
James
Author of node-serialport. I have tracked down the issue and it is due to a compilation issue with IOWatcher in node.js. I have revised the strategy for reading from the serial port and it now should function as designed in all cases. Please ensure you are using node-serialport 0.2.6 and greater.
Now go out and build JS controlled robots!!!
I also experienced problems with the serial port read.
This is due to a bug in node.js v4.7 (see this issue)
However it worked after switching to an older version of Node.js (v4.0).
It might work with versions up to v4.6 also, but I haven't verified that yet.

Resources