kermit doesn't wait long enough - serial-port

I'm writing a kermit script to start an elf on an IMX board running a custom kernel and I'm trying to capture a string written by the elf, with the following script:
set input echo on
lineout tests_domains/usb/hid/build/test # send elf name to the board's shell
minput 40 "<--- PNC TEST STATUS: PASS" "<--- PNC TEST STATUS: INCONCLUSIVE" "<--- PNC TEST STATUS: FAIL" "<--- PNC TEST STATUS: NOTRUN" "<--- PNC TEST STATUS: TIMEOUT"
switch \v(minput) {
:1, echo "TEST PASS", exit 0
:2, echo "TEST INCONCLUSIVE", exit 1
:3, echo "TEST FAIL", exit 2
:4, echo "TEST NOTRUN", exit 3
:5, echo "TEST TIMEOUT", exit 4
:default, echo "entering default case", echo \v(minput), exit 255
}
However minput returns before having received one of the <--- PNC TESTS STATUS string and before 40 seconds. It returns circa 5~6 seconds after having launched the elf.
The full output of the board on its uart is as follows: https://pastebin.com/vsps5ZQ1 It ends up correctly with <--- PNC TEST STATUS: PASS
Whereas when capturing the output with the script above, it terminates as follows: https://pastebin.com/wFSDdn5s Output shows that the default case of the switch is executed, after having captured the string "0". It always return after a string of the form [ 6.099262][usbd:imx ] prime_endpoint: IN endpoint 1 (3) (last line written by the board in the second paste). I don't understand why the latter happens.
If there are alternatives to kermit to perform what I'm doing, please propose them to me. Online documentation for kermit is sparse.
Final note: ny kermit startup script (~/.kermrc) is as follows:
set line /dev/ttyUSB0
set speed 115200
set carrier-watch off
set handshake none
set flow-control none
robust
set file type bin
set file name lit
set rec pack 1000
set send pack 1000
set window 5

\v(minput) expands to the index of the received string, and indexing is zero-based.
This means that you should have written
minput 40 "<--- PNC TEST STATUS: PASS" "<--- PNC TEST STATUS: INCONCLUSIVE" "<--- PNC TEST STATUS: FAIL" "<--- PNC TEST STATUS: NOTRUN" "<--- PNC TEST STATUS: TIMEOUT"
switch \v(minput) {
:0, echo "TEST PASS", exit 0
:1, echo "TEST INCONCLUSIVE", exit 1
:2, echo "TEST FAIL", exit 2
:3, echo "TEST NOTRUN", exit 3
:4, echo "TEST TIMEOUT", exit 4
:default, echo "entering default case", echo \v(minput), exit 255
}
What happens with your code is that, upon receiving <--- PNC TEST STATUS: PASS, minput exits with \v(minput) set to 0 and the switch only matches the default. The 0 in your output is not the string being received, it is its index as given to minput.

Related

Opening a serialport, transmitting on txd, dtr and rts

Morning all,
I have developed an app with C# and Windows Forms that opens a serialport and transmits on txd, dtr and rts.
I want to be able to do this with tcl/tk but finding serialport tutorials on tcl/tk is proving quite difficult. I did find something on Stackoverflow Here. But when running it:
It says "couldn't open serial "COM7": permission denied"
Does anyone know why permission is denied and how to grant permission? Also does this code even work.
Does anyone have any sample code I can try or can point me to a good understandable source please?
You could have a look at this example that uses a Tcl/tk to read data from a serial port:
############################################
# A first quick test if you have a modem
# open com2: for reading and writing
# For UNIX'es use the appropriate devices /dev/xxx
set serial [open com2: r+]
# setup the baud rate, check it for your configuration
fconfigure $serial -mode "9600,n,8,1"
# don't block on read, don't buffer output
fconfigure $serial -blocking 0 -buffering none
# Send some AT-command to your modem
puts -nonewline $serial "AT\r"
# Give your modem some time, then read the answer
after 100
puts "Modem echo: [read $serial]"
############################################
# Example (1): Poll the comport periodically
set serial [open com2: r+]
fconfigure $serial -mode "9600,n,8,1"
fconfigure $serial -blocking 0 -buffering none
while {1} {
set data [read $serial] ;# read ALL incoming bytes
set size [string length $data] ;# number of received byte, may be 0
if { $size } {
puts "received $size bytes: $data"
} else {
puts "<no data>"
update ;# Display output, allow to close wish-window
}
############################################
# Example (2): Fileevents
set serial [open com2: r+]
fconfigure $serial -mode "9600,n,8,1" -blocking 0 -buffering none -translation binary
fileevent $serial readable [list serial_receiver $serial]
proc serial_receiver { chan } {
if { [eof $chan] } {
puts stderr "Closing $chan"
catch {close $chan}
return
}
set data [read $chan]
set size [string length $data]
puts "received $size bytes: $data"
}
(disclaimer: this is taken verbatim from here)
EDIT: I am sorry but I do not have enough reputation to comment, but it is probably a good idea to specify the platform to narrow down what the permission issues might be related to.

Reading serial port in Rebol3

I am using Rebol3 v3.0.99.4.20 that has both the /View and serial functionality.
I am opening a port with:
ser: open serial://ttyUSB0/9600
Then, I set up my asynchronous handler:
ser/awake: func [event /local p][
p: event/port
switch event/type [
lookup [open p]
connect [write p to-binary request]
read [
result: to-string p/data
close p
return true
]
wrote [read event/port]
]
false
]
The problem I have now is that I cannot figure out how to read data from the serial port. I always only get back the last command I wrote to the serial port in ser/data.
For example:
>> ser: open serial://ttyUSB0/9600
>> write ser "debug on^/"
>> read ser
== "debug on^/"
That looks OK so far, but this is how the serial device operates using the Linux command, 'screen':
My input:
debug on
The serial device response:
Debug messages enabled.
>
However, I never can read the "Debug messages enabled." text.
>> read ser
== "debug on^/"
>> wait ser
== none
>> read ser
== "debug on^/"
>> copy ser/data
== "debug on^/"
Not sure what I'm missing.
In Rebol2, it is much more straightforward, but not asynchronous:
>> system/ports/serial
== [com1 com2 com4]
>> ser: open/no-wait serial://port3/9600/8/none/1
>> insert ser "debug on^/"
>> copy ser
== "debug on^/Debug messages enabled.^/>"
>> copy ser
== ""
A 2nd copy doesn't return anything because the first copy cleared the serial buffer. If data was streaming to the serial port, additional 'copy commands would return additional data from the serial buffer. But it doesn't work this way in Rebol3.
Found this info in the archives of a chat group:
ser: open serial://ttyUSB0/9600
written: false
ser/awake: func [evt][
switch evt/type [
read [
attempt [print to-string evt/port/data]
read evt/port
return true
]
wrote [
written: true
return true
]
]
false
]
write ser "debug on^/"
while [not written][
wait [ser 1]
]
read ser
wait [ser 1]
The event loop you provided in your question actually should read the data for you. If you want to keep reading data, you should not exit the loop with return true but do another read in the read event. You should process the data inside the event loop.

Error Handling while running sqlplus from shell scripts

I need to validate whether DB connection is success/failure.
This is my code
report=`sqlplus -S /nolog << EOF
WHENEVER OSERROR EXIT 9;
WHENEVER SQLERROR EXIT SQL.SQLCODE;
connect <<username>>/<<Password>>#hostname:port
set linesize 1500
set trimspool on
set verify off
set termout off
set echo off
set feedback off
set heading on
set pagesize 0
spool extract.csv
<<My SQL Query>>
spool off;
exit;
EOF`
I have tried the below option based on the thread Managing error handling while running sqlplus from shell scripts but its picking the first cell value rather than the connection status.
if [ $report != 0 ]
then
echo "Connection Issue"
echo "Error code $sql_return_code"
exit 0;`enter code here`
fi
Please advise.
I needed something similar but executed it a bit differently.
First, I have list.txt which contains the databases that I would like to test. I am using wallet connections but this could be edited to hold username/password.
list.txt:
DB01 INSTANCE1.SCHEMA1
DB02 INSTANCE2.SCHEMA2
DB03 INSTANCE3.SCHEMA3
DB04 INSTANCE4.SCHEMA4
I have OK.sql which contains the query that I want to run on each database.
OK.sql:
select 'OK' from dual;
exit
Last, I user test.sh to read list.txt, attempt to connect and run OK.sql on each line, and record the result in (drumroll) result.txt.
test.sh:
. /etc/profile
rm result.txt
while read -r name wallet; do
echo "BEGIN-"$name
if (sqlplus -S /#$wallet #OK.sql < /dev/null | grep -e 'OK'); then
echo $name "GOOD" >> result.txt
else
echo $name "BAD" >> result.txt
fi
echo "END-"$name
done < list.txt
After the run check your result.txt.
result.txt:
DB01 BAD
DB02 GOOD
DB03 GOOD
DB04 GOOD
I hope this helps.

How can I access the last message which is sent to a processor in MPI?

I am using a master-worker structure using Message Passing Interface (MPI) but whenever I call Receive function, instead of receiving the messages in the order of sending sequence, I need to receive the last message sent from the master to the each processor and ignore the previous ones!
My question is that if there is any way that we can access each processor's buffer and pick the last message in the queue?
No, you can't just peer into the queue; but you can test to see if more messages are present with MPI_Probe or MPI_Iprobe, and while there are more messages present, keep receiving and discarding the old data:
#!/usr/bin/env python
from mpi4py import MPI
import time
def waiter(comm, sendTask):
# wait for messages to be present
while not comm.Iprobe(source=sendTask, tag=1):
time.sleep(1)
# read all messages while more are available, discarding old
while comm.Iprobe(source=sendTask, tag=1):
lastMsg = comm.recv(source=sendTask, tag=1)
if lastMsg is None:
print "No messages pending"
else:
print "Last message was ", lastMsg
comm.Barrier()
def sender(comm, waitTask):
for msgno in range(5):
print "sending: ", msgno
comm.send(msgno, dest=waitTask, tag=1)
print "sending: ", -1
comm.send(-1, dest=waitTask, tag=1)
comm.Barrier()
if __name__== "__main__":
comm = MPI.COMM_WORLD
sendTask = 1
waitTask = 0
if comm.rank == waitTask:
waiter(comm, sendTask)
elif comm.rank == sendTask:
sender(comm, waitTask)
else:
comm.Barrier()
Running gives
$ mpirun -np 2 ./readall.py
sending: 0
sending: 1
sending: 2
sending: 3
sending: 4
sending: -1
Last message was -1

batch file load balacing code query

I am trying to run a bat file code from the following reference:
Detecting batch IP conflict
however, i am getting an error:
TRUE - invalid alias verb
-1 was unexpected at this time.
Could someone kindly explain this to me please. thanks. sample code attached below
#echo off
setlocal
:: Host to ping
set primary=x.x.x.1
:: Ping with options (1 ping sent per loop, wait 500 ms for timeout)
set ping_options=-n 1 -w 500
:: Fail over after x ping failed responses
set fail_limit=5
:loop
:: Ping x.x.x.1. Test for "reply from". If success, set failures=0; otherwise, increment failures
( ping %ping_options% %primary% 2>&1 | find /i "reply from" >NUL && set failures=0 ) || set /a "failures+=1"
:: If failures >= limit, switch IP
if failures GEQ %fail_limit% call :switch
:: Pause for a second and begin again.
ping -n 2 0.0.0.0 >NUL
goto loop
:: Switch subroutine
:switch
:: Get current IPv4 address
for /f "tokens=2 delims={}," %%I in ('wmic nicconfig where ipenabled="TRUE" get ipaddress /format:list') do set IP=%%~I
:: If the last character if the current IP is 1, switch to 2 (or vice versa)
if %IP:~-1%==1 ( set other=%IP:0,-1%2 ) else set other=%IP:0,-1%1
:: Perform the switch
netsh int ipv4 set address name="Local Area Connection" source=static address=%other% mask=255.255.255.0 gateway=none
All you need to do is escape the equal sign in the wmic command.
for /f "tokens=2 delims={}," %%I in (
'wmic nicconfig where ipenabled^="TRUE" get ipaddress /format:list'
) do set IP=%%~I

Resources