How to write commands to a serial port using NodeJs? - python

Good day everyone,
I am having issues writing commands to a lock connected to a USB controller which is connected to the laptop port using NodeJs. I have successfully achieved this in python, but is having issues in nodejs.
The reason why I am converting to nodejs is because the entire application is written in nodejs and runs has a desktop app via electron, and opening/closing port is just a small component of it.
The python equivalent and which works fine
ser = serial.Serial()
ser.baudrate = 38400 #Suggested rate in Southco documentation, both locks and program MUST be at same rate
// COMPORT is a variable that stores an integer such as 6
ser.port = "COM{}".format(COMPORT)
ser.timeout = 10
ser.open()
command = "open1"
#call the serial_connection() function
ser.write(("%s\r\n"%command).encode('ascii')) #Southco locks receives and sends commands in ASCII
Now in NodeJs, I am using the library serialport and I am trying to achieve this via nodejs that runs under the electron app.
var SerialPort = require('serialport');
var port = new SerialPort("COM6", {
baudRate: 38400
});
port.on('open', function() {
port.write(Buffer.from('open1', 'ascii'), function(err) {
if (err)
return sendData(500, err.message);
console.log('message written');
});
});
I know nodejs is able to interact with the port because when I run serialport-list in command prompt or when i run it within the code
SerialPort.list(function (err, ports) {
ports.forEach(function(port) {
console.log(port.comName, port.pnpId, port.manufacturer); // or console.log(port)
});
});
it shows the port information. Hence, nodejs is able to read the port, and issue information about the specific port, but I cant seem to issue command succesfully to it. It seems to get execute since no error message is thrown and it does display message written in console, but the lock does not react, whereas with the python code the lock does react by opening or closing demanding on the command that is written.
Any help would be appreciated.

If you look in the SerialPort docs you'll see that the port is immediately opened when a new instance is instantiated, unless you pass the option AutoOn=false.
So, in your case, the port is already open by the time you set the listener .on('open'), so it never receives an event. Remove the listener and just call .write() immediately.

Related

Python SSH Interactive Shell call back on data receive

I'm trying to implement a interactive SSH shell using python as back-end. Basically I want to pass each character to shell along with and special character like new line, Ctrl-C. Then pass back the result. I found similar solution in node.js at Connecting to remote SSH server (via Node.js/html5 console)
I can establish a websocket from fronend/JS side and send each character on key-press. But I'm facing problem in getting shell output back. In node.js ssh2 package its looks like on receiving data it can call some function
}).on('data', function(data) {
console.log('STDOUT: ' + data);
}).stderr.on('data', function(data) {
console.log('STDERR: ' + data);
});
I checked the python's ssh2-python and Paramiko, but in both I see we have to loop continuously and check if any data is available on channel. Do we have something like callback similar to node.js ?
So that I can handle incoming stream + continuous outgoing stream( in case of command like top and ping)

How to correctly configure and close an SSH session with paramiko

I have an Onion Omega2 device acting as a linux server that has a UART stream from an Arduino chip. Through the terminal on my laptop I can connect via SSH and stream the data from the UART coming into the device. I then attempted to create an SSH shell in Python using Paramiko. Code shown below:
import paramiko
def ssh_comm(ip, usr, passwd):
client = paramiko.SSHClient();
client.set_missing_host_key_policy(paramiko.AutoAddPolicy());
client.connect(ip, username=usr, password=passwd);
channel = client.invoke_shell();
channel.send("screen /dev/ttyS1 9600 \n");
print("/n");
points = 0;
while points < 100:
if channel.recv_ready():
print(channel.recv(1024));
points = points + 1;
channel.shutdown(2);
client.close();
return;
ssh_comm("192.xxx.x.x", "root", "password");
First time around it connects well and all data is streamed back to my laptop. However when I let the shell close and then re-open it I only recieve a few packets every now and then back from the Omega2. (It still connects fine though) After connecting through python the transmission is also intermittent when forming the SSH connection on the terminal using: ssh root#192.xxx.x.x.
Restarting the Omega 2 fixes this however since I can repeatedly connect though the terminal with no issues I beleive the problem must be to do with closing the session within the python code. Or not configuring it properly. Having looked through the paramiko docs and tried my best to configure it correctly I still get the same issue. Any ideas as to what could be causing it?
I found that the error is not to do with the SSH configuration but rather not closing the screen command before closing the channel. this was done by sending CTRL-A then k then y.
channel.send("\x01");
channel.send("k");
channel.send("y");
The \x01 represents CTRL-A. Without this re-running the program causes a second screen to be created and they both fight over the UART stream. Solution was found with reference to: Python Paramiko send CTRL+C to an ssh shell And provides a second method of fixing the problem.

Upload code to ESP32/Arduino while pySerial is running

I'm working on a project that an ESP32 module needs to read some value from a sensor and send it to a python code using pySerial. My code in constantly reading from the serial, as I can send data to it at any time. The problem is that the python program cannot be stopped because it's a server, but i still want to upload code whenever I want to the ESP32 module. Also, I'm sending data via serial on the void setup() function, so I need the python code to be running when the code is uploaded to the board, that is, when the setup() function runs.
I know I can't upload my code to the board while the serial port is being used by pySerial, but is there any way around? Like closing the connection while I'm uploading the code or when there is no data to be sent?
Here is the code that I'm using:
import serial
import json
ser = serial.Serial("COM6", 115200)
while(1):
if(ser.in_waiting > 0):
leitura = ser.read_until(b'}').decode('ascii')
data = json.loads(leitura)
handleRequest(data)

Python serial write doesn't work FIRST run

I have 2 programs to test serial communication, an simple arduino program that echoes whatever is on the serial port and a python program that writes to the serial port and prints the reply.
I'm having an issue where whenever I upload the arduino program and try to run the python the first time after I uploaded, it would be stuck on print ser.readline() which I'm assuming means for some reason python is not writing to the serial port. I would have to quit the python program and run it again to get it to get a reply from arduino. The program would continue to work until I re-upload the arduino then once again python wouldn't work on first run. Also if I open and close the serial monitor before I run the python program it will work the first run. Does anyone know what is the issue? This is on Ubuntu.
arduino
String str;
void setup() {
// Turn the Serial Protocol ON
Serial.begin(115200);
}
void loop() {
if (Serial.available()) {
str = Serial.readStringUntil('\n'); // Read the serial input
Serial.println(str); // sends ascii code
}
}
Python
import serial
ser = serial.Serial('/dev/ttyACM1', 115200)
for i in range(0,4):
str = "test string\n"
ser.write(str)
print ser.readline()
The issue is likely related to many Arduinos resetting when a new serial connection is made.
The solution is to either add a delay (about 2 seconds works) to the python program between the serial connection being created and the first data being sent or modifying the hardware to prevent a reset on serial connect.
By default python Serial might be blocking by default try removing the timeout:
ser = serial.Serial('/dev/ttyACM1', 115200,timeout=0)
additionally have a peek at the serial.threaded in the docs
I added
time.sleep(1)
ser.setDTR(level=0)
time.sleep(1)
after opening the serial port and the issue was fixed.

Python sockets - auto connect client to server

I have an application where Python acts as a client talking to another shell (tcl). I would like to have Python connect automatically - I have it all working now but I have to manually do a sock.connect in python. The problem is the tcl shell is started from the Python script in an os.system call:
def start_tcl():
exit_tcl() #Close any existing connections
server.reset(2540) #Create new socket
os.system("vivado -mode tcl -source server.tcl") #Open tcl server and connect to socket
So if I put connect right after that, the server isn't actually opened yet, and I get endpoint not terminated. Is there a way to have Python wait to connect to the socket once the server is connected? I'm sure I don't fully understand sockets, am I going about this all wrong?
I ended up using a while loop in case anyone is interested:
while ( server.connect() is "None" ):
time.sleep(1)
– Kaleb Droskiewicz

Categories

Resources