Linux shell: save input line from Serial Port each minute and send to remote server - shell

I have Arduino connected to computer over RS-232 (only TxD, RxD and GND).
Arduino only send data to computer and computer receive it. Computer do not transmit anything to Arduino.
Computer is WiFi router with OpenWrt linux with 16MB RAM and 4MB flash for system. I do not have free enough space for "good tool" like python (I have the same working program on x86 PC written in python).
Arduino send data to PC +- each 60 seconds. Data has following format:
SENSOR1;12.34;95.47
ABC245;34.5;75.1
2 sensors each have 2 values. Line is ended using <CR><LF>. I can modify this "protocol" to for example one line like (or any other):
SENSOR1;12.34;95.47|ABC245;34.5;75.1
so on wifi router I need little program which read this string every minute and save it to variable. This variable insert to curl and send to remote server. Can I send data to server without curl (with less ram/flash usage)?
I would like to use pure bysybox sh (bash is to big).
I found Bash script: save stream from Serial Port (/dev/ttyUSB0) to file until a specific input (e.g. eof) appears :
#!/bin/bash
while read line; do
if [ "$line" != "EOF" ]; then
echo "$line" >> file.txt
else
break
fi
done < /dev/ttyUSB0
awk `
/EOF/ {exit;}
{print;}` < /dev/ttyUSB0 > file.txt
is it good choice to use/modify these script? Is there any other better solution?

Why not give a try to ser2net pakage?
This will allow forward the serial port to the server.
It work ok on OpenWrt
Lua is buid in.
A script in Lua ca read also from the serial port , but you neet to set the port parameters first with stty
stty 9600 raw < /dev/ttyUSB0
lua myscript < /dev/ttyUSB0

Related

mouse movement real time transmission from raspberry pi

i'm trying to send the coordinates of mouse connected to a raspberry pi to an ESP8266 in the same network.
I just wrote this bash script
#!/bin/bash
device='/dev/input/event1'
mouseX="*(REL_X), value*"
mouseY="*(REL_Y), value*"
evtest "$device" | while read line; do
case $line in
($mouseX) X=${line##*value }
curl 'http://192.168.0.4/ricevuto?X='"$X" &
;;
($mouseY) Y=${line##*value }
curl 'http://192.168.0.4/ricevuto?Y='"$Y" &
;;
esac
done
the command "evtest" capture the mouse movements and the script extract the coordinates, curl send the data.
It works, but it's really SLOW! With the "&" at the end of the curls is faster but sometimes the coordinates are messed up...
Is there a way to establish a connection and just transmit data without make a request everytime?
Just to explain my final goal: i'm trying to use a mouse, connected to a raspberry pi, on multiple devices: in this case the receiver (esp8266) will be connected to a arduino leonardo that can recreate the mouse movement on an android TV.
Thanks for the help or any other simpler solution!
Here's a sketch of how the shell loop could be avoided:
evtest "$device" | sed -un 's/.*(REL_\([XY]\)), value /\1=/p' | …
The … can be a command like netcat or mosquitto_pub -l. The above will generate messages like X=2 or Y=1, but the message format can be changed by using some other replacement than \1=.

Binding to a random free port (as with port 0) in bash

In Bash only, how can I retrieve two open port numbers that are guaranteed to be available, as is done in other languages (Perl or Python) by binding to port 0? My operating system is Ubuntu 16.04 LTS.
I've seen perl and python examples, but nothing that works without using a separate language.
My end goal is to replace the following unreliable script, so I can assign the results to variables and use them later in my script
count=0;
for i in {11212..12655}
do
netstat -ntpl | grep [0-9]:${1:-$i} -q ;
if [ $? -eq 1 ]; then
aLen=${#PORTS[#]};
#echo $i:$?
if [ $aLen -lt 2 ]; then
PORTS[$count]=$i;
((count++));
else
break;
fi;
fi;
done
PORTs1="${PORTS[0]}";
PORTs2="${PORTS[1]}";
Ended up utilizing Python to get what I needed.
PORT1=$(python -c 'import socket; s=socket.socket(); s.bind(("", 0)); print(s.getsockname()[1]); s.close()');
PORT2=$(python -c 'import socket; s=socket.socket(); s.bind(("", 0)); print(s.getsockname()[1]); s.close()');
Inasmuch as your goal is to assign two port numbers, which are guaranteed to be free, to PORTs1 and PORTs2 variables, such that they can be bound to at a later point in time, this is inherently impossible.
The entire reason binding to port 0 works is that it lets the operating system choose a port that is immediately available at the time of the operation itself. If you choose the port number before you open it, then you've created a window in which another process can bind to the port. By contrast, if you bind to the port before you start the program that ultimately needs to own the listening socket, it's no longer free.
Passing a file descriptor pre-bound to a port -- rather than passing a port number to later bind to -- is possible (though not using shell-built-in functionality that's guaranteed to be present in bash), but it's going to require rewriting the program you're invoking; and if you're going to do that, you might as well rewrite that program to ask the OS to randomly select its port numbers and write them out in a usable format itself.

How to run the "cat" command on the background inside the script

I have a USB LTE modem connected to my Raspberry and I need to read replies sent via serial line, generated by requests sent using the "echo" command.
Example:
cat /dev/ttyUSB0 &>> /ttyUSB0_logs &
echo "AT+csq" > /dev/ttyUSB0
echo "AT+cgreg=2" > /dev/ttyUSB0
echo "AT+cgreg?" > /dev/ttyUSB0
The problem is, although the "cat" command should run on the background and all output is directed to the file, script still freezes at this point. If I use the first command outside of the script, it works as I expect - it stores all output to the file ttyUSB0_logs on the background and I can use the received data for other operations. The question is - how can I integrate the first command to the script to get it work this way? Thanks a lot.
you want:
cat /dev/ttyUSB0 >> /ttyUSB0_logs &
if that doesn't work, you should double check what is actually freezing. you can put set -x at the top of the script to get tracing output.

piping Linux cat command to web in openWRT

I want to run a shell script from openWRT. Basically its need to constantly read arduino serial port and when its reads something its need to be sent to a web based service.
Currently this is my script which only save to text file:
cat /dev/ttyACM0 >> /www/home/log.txt &
I want to avoid saving to file and send the output string right to a web based service that store the readings in mySQL DB.
All the data saving web service is all set and working something like this:
http://my-service.com/?data=what-ever-the-arduino-spits
Is there a way to do it with wget?
maybe something like this:
cat /dev/ttyACM0 | xargs -n % wget http://ivardi.info?todb=%
keep in mind that the openWRT is on a 32 RAM and 4MB flash storage so this is only possible with shell script and not Phyton/PHP.
Regards
Note that it could be dangerous in some cases to directly read the serial (/dev/ttyACM0) device and pass it direct to wget in case the read blocked for some reason (what happens if the serial port is disconnected and reconnected?)
It could be safer to route the output to a file; then in a loop read the most recent data and 'pushing' that using wget. Perhaps something like:
#!/bin/bash
while true; do
tail -1 /www/home/log/txt | wget <...options...>
sleep 60
done
In reality you would probably need to do something a little more advanced so that you don't keep sending duplicate data.
Of course, in your own situation what you proposed may be sufficient...

Bash programming, interrogating ttyUSB port

I'm new in this of bash programming in linux, basically what I want to do is to program a bash file that can open the port ttyUSB0 and then I need to interrogate it with AT commands (like "0100") and then assign the response to a variable, I've been trying this with this different ways:
1) Using cat
#!/bin/bash
PORT= \ls /dev/ttyU*
cat $PORT
????
2) Using Minicom
`#!/bin/bash
minicom
????
'
3) Using Screen
#!/bin/bash
PORT= \ls /dev/ttyU*
screen $PORT
????
How can I interrogate it before the cat, minicom and screen starts? What should I have to put in ???? of the 3 different codes?
Thank you so much!!!
Don't try writing to a tty device using bash, you'll end up chasing your own tail forever. Use minicom or C-Kermit for that.
If you want to check that the device is active before starting minicom, you can read from it with bash and there is a good explanation of how to achieve this here: Bash read from ttyUSB0 and send to URL
You should be able to use my atinout program for this. It is a command line tool to talk with a modem:
$ echo AT | atinout - /dev/ttyUSB0 -
AT
OK
$
So with a little bit of scripting you should be able to extract the response you want (remember to always check for a successful OK response).

Resources