File transfer via serial port - python-3.x

I am trying to send a file via serial port. I tried sending picocom commands in a bash script. However the device writes out a menu of options. When it gets to the file transfer step - it writes out 'C' until a file is sent, after which it does the handshake and proceeds with the transfer. With the script I am not able to send the keystrokes 'C-a' and 'C-s' to get the '*** file:' prompt of picocom. I can do it manually. I even tried a combination of bash and python and pyautogui for the keystrokes, bash echo command to send the hex version of the keystrokes. I even tried sending 'sz' commands through the script and stty. All of these attempts were unsuccessful.
So I switched to python, and tried the xmodem library in python. I am supposed to use ymodem. I thought the 'YMODEM batch transmission session' in the library would do the job. The modem.send command always errors out with the file not being sent.
Read Byte: b'C'
Put Byte: 133
Read Byte: b'C'
send error: expected ACK; got b'C' for block 1
Put Byte: 133
Read Byte: b'C'
send error: expected ACK; got b'C' for block 1
How can i get around this?

Finally ended up using a combination of python and bash - python for serial communication and for parsing the file names of the binaries, and, bash stty and sb commands for transferring the binaries.

Related

Why is printing iwgetid giving me 0?

I'm reading the Wi-Fi connection of my Raspberry Pi, using the iwgetid command.
The output is:
wlan0 ESSID:"iPhone"
I wrote the following lines in a Python script:
import os
print(os.system("iwgetid"))
print(type(os.system("iwgetid")))
The output I got was:
0
<type 'int'>
Why is print(os.system("iwgetid") giving me 0 when it's a string?
As quoted from here:
os.system() just runs the process, it doesn't capture the output:
If command generates any output, it will be sent to the interpreter
standard output stream. The return value is the exit code of the
process:
On Unix, the return value is the exit status of the process encoded in
the format specified for wait().
To get the output from the Terminal command, use the subprocess module and the command subprocess.check_output instead of os.system.

Run AT commands from adb shell on Redmi 7

I tried this:
echo -e "ATD123456789;\r" > /dev/smd0
and then when I ran:
cat /dev/smd0
I got this output:
ATD123456789;
Is that what I'm supposed to see? The phone didn't respond to the command.
Update: The phone made a call when I used smd7 or smd11. The problem is I'm trying to send SMS messages using AT+CMGS and it's not working.
Update2: I run this command:cat /dev/smd7 & echo -e "AT+CMGS=24;\r" > /dev/smd7.
Then I enter the PDU message and I get this: /system/bin/sh: 079...771B: not found
As you probably know, the command
ATD<number>;\r
performs a voice call to the destination number <number> (without the semicolon ; the call type would depend o the current settings of AT+FCLASS command).
By default the OK result code would be received as soon as it starts remotely ringing, so after some seconds. But it would take even more if there are network problems or the remote number is unavailable/doesn't exist.
The default timeout of ATD command during a voice call is 30s, and can be changed by issuing ATS7 command. For example, to set a 1 minute timeout:
ATS7=60
The answer you get is the command echo: in fact the modem, by default, echoes every character sent to its AT port (the echo can be desabled through ATE0 command and aenabled again with ATE1). Receiving it **is the proof that the modem is correctly powered on and that it communicates correctly.
So, even though I'm aware that's not the only thing you expect to seee (you would like to see an answer!) you are actually supposed to see it.
Some pieces of advice in order to receive your answer:
Start providing simplier commands with shorter timeouts. For example the very basic AT.
Make sure to wait at least the maximum command timeout
Set the cat command in background and before starting providing commands:
cat /dev/smd0 &
echo -e "AT\r" > /dev/smd0
OK
Note: I'm not aware of any timeout in cat command.
To have an interactive session you can use:
strace 2>/dev/null -e inject=ioctl:retval=0 microcom /dev/smdXX
Without the strace command, microcom returns an ioctl error.
Strace makes microcom think the ioctl succeeded and so it allows it to continue and run.

Why is my stdin redirection ('<') not working with subprocess.Popen()?

I'm building a script in python, and one part of it needs to send an email with a file as the message body. Instead of sending the contents of the file, the script sends me the next character entered into the terminal e.g. if I enter c as a part of "cat", it doesn't put c into the terminal, but instead sends me an email with "c" as the body.
This is on CentOS 7.6.1810, with Python 3.5.6.
#!/usr/src/Python-3.5.6/python
import subprocess
import sys
import os
subprocess.Popen(["mail", "-s", "Test Subject", "myemail#myemail.com", "<", "/path/to/file.txt"], stdout=open('stdout', 'w'), stderr=open('errout', 'w'))
The contents of file.txt should be send as the body, but I just get the first letter of whatever the next thing I type is. "stdout" reads "EOT" after this, and nothing is printed to "errout". To be clear, I'm trying to invoke the command
mail -s "Test Subject" myemail#myemail.com < /path/to/file.txt
from inside of the script. This command works as expected outside of the Python script, but inside of it I run into the problem.
subprocess.Popen() executes your new process directly by default. So your code passes some additional arguments < and /path/to/file.txt to the mail executable, which will not yield the expected result.
Redirections like < on unix systems are handled by the shell, not by each individual executable. That's why you want subprocess.Popen() to run your mail command with all the arguments mail as well as the redirection < /path/to/file.txt in a shell instead.
You can do this with the shell=True parameter:
subprocess.Popen(["mail", "-s", "Test Subject", "myemail#myemail.com", "<", "/path/to/file.txt"], stdout=open('stdout', 'w'), stderr=open('errout', 'w'), shell=True)
Note that the shell is probably not necessary – you could have Popen open the file and connect mail's stdin to that descriptor, see anishsane's comment below.
Using a shell should be avoided especially if user data is being passed to the child process, as it would need to be sanitized properly to prevent command injection attacks.
See the Python 3 docs on subprocess.Popen.

Shebang causes script to fail

I'm quite bad at bash, and I try to make a script to connect to all my switches with openSSH in order to make some configuration.
I created an array containing all my 25 switches, and then I used a loop to open SSH connection with each of them.
As I'm on Windows and using bash, I've just installed Cygwin.
However, I had to use expect and writing my password in plain text as the switches are quite poor and that is the best way for me (I won't manually put my RSA key on every single switch as it would take me as much time as writing manually the configuration on every switch).
I use the shebang #!/usr/bin/expect -f to make bash recognize expect. When I do this, the expect syntax (spawn, expect, interact) works perfectly, but my array doesn't work.
I get the following error message:
extra characters after close-quote
while executing "arrayname=("172.21.21.20" "172.20.55.55" ... "
When I change the shebang, and use #!/bin/bash, expect is not found anymore :
./stationsnmp.sh: line 20: spawn : command not found couldn't read
./stationsnmp.sh: line 24: send : command not found couldn't read
file "assword": no such file or directory ./stationsnmp.sh: line 27:
send : command not found ./stationsnmp.sh: line 28: interact :
command not found
I'm really not a pro in bash, which explains I can't get this little problem... Some help would be welcome.
EDIT : Below is a part of my code
#!/bin/bash
switch=("172.20.0.229" "172.20.0.232" "172.20.0.233" "172.21.0.15" "172.21.0.16" "172.21.2.1" "172.20.2.250" "172.21.3.1" "172.20.3.250" "172.21.4.1" "172.20.4.250" "172.21.6.1" "172.20.6.250" "172.21.7.1" "172.20.7.250" "172.21.8.1" "172.20.8.250" "172.20.9.250" "172.21.9.1" "172.21.10.1" "172.20.10.250" "172.21.11.1" "172.20.11.250" "172.21.12.1" "172.21.12.250")
nmb=`echo ${#switch[#]}`
set timeout 3
for ((ii=0; ii<=$nmb; ii++))
#for ii in {0..${#switch[#]}}
do
if [ ${switch[$ii]:5:1} -eq 1 ]
then
ipdc=`echo ${switch[ii]} | grep -o -E '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.'`"10"
spawn ssh admin#switch[$ii]
expect "*assword*"
send "PASS\r"
interact
exit
fi
done
You are mixing bash and expect, those are two entirely different languages. You probably want to have a bash wrapper script with proper option handling (see getopts) which takes a list of IP addresses and execute your expect script for each IP address passed to your bash-wrapper. If your expect script is small you might want to embed it into your shell script as opposed to having it in a separate file.
EDIT:
#!/bin/bash
switches=("172.20.0.229" "172.20.0.232")
for ip in "${switches[#]}"; do
expect "${ip}" <<-'EOT'
set host [lindex $argv 0]
set timeout 3
spawn ssh -l admin $host
expect "*assword*"
send "PASS\r"
interact
exit
EOT
done

How can I perform some commands on Intersystem cache from shellscript?

I want to perform some commands on Intersystem cache from shell script. One solution which I know is through making a config file but the problem is I dont know how to use config file through shell script. Is there any other solution for this...
for example what I have to run on cache is
csession instancename
zn "area"
area>D ^%RI
Device:some/device/path
Next: It should take enter
This can be accomplished from a Linux shell, simply keep a log of the commands you need to perform and then put them into a script. Here's an example of logging into Cache and writing "Hello world" -- note that this also assumes you need to authenticate.
echo -e "username\npassword\nW \"Hello world\"\nH\n" | csession instance
Note that every command you would have run manually is in there and separated by "\n", this is the character that represents the "Enter" key.
It is possible (for some operating systems) to run the Cache terminal in batch mode. For example:
echo: off
wait for:Username
send: SYS<CR>
wait for:Password
send: XXX<CR>
echo: on
logfile: Somepath\myFile.log
send: ZN "AREA"
wait for:AREA>
send: D ^%RI
wait for:Device:
send: some/device/path
wait for:Next:
send: <CR>
This is documented in the Intersystems cache terminal documentation, especially the using terminal in batch mode section and the terminal scripts section.
This is a very old question .. as I came across the same thing and so with a little R&D I found a work around to this problem. Which is very cool and simple.
Let's say I have this file (can be with any extension with each command in separate line)
myScript.scr
zn "%SYS"
for e="a","b","c" { w e,! }
So passing it to cache terminal in case of UNIX is using csession with linux PIPE (|) operator
cat myScript.scr | csession {instance_name}
Eg.
cat myScript.scr | csession CACHE
output
a
b
c
Note:
• Don't separate a command in multiple lines else `csession` will through <SYNTAX> error. (See how I wrote the *for* loop)
• Extra knowledge - Intersystem Ensemble supports *Cache Terminal Batch Mode* in Windows case... While in linux there is no cterm to take the scripts..
• But linux gives you a work around to do this ;).
Hope this helps you guys!! cheers :D

Resources