Is there a way to get the device name connected to the serial port?
This code gives me just the name of the serial port. But I need the device name connected to it i.e. Nokia Phone
import serial
import time
ser = serial.Serial('/dev/ttyACM0',
460800,
timeout=5,
xonxoff = False,
rtscts = False,
bytesize = serial.EIGHTBITS,
parity = serial.PARITY_NONE,
stopbits = serial.STOPBITS_ONE)
sere = ser.name
print (ser, sere)
I've been checking other possibilities like gammu-detect but I would like to have a self standing python script that does this operation. Is there a way to get it done with pyserial?
Yes, of course.
But this is not strictly linked to serial port itself. It depends on the protocol the device is using.
In essential, you send some preset initial data to the device and it responds with manufacturer, name, model and version or some combination of these.
I am not sure whether this is standardized or not, you will have to search for it.
If it is standardized, it is most probably something like:
1. Open the port with 9600 baud rate
2. Send the request for info
3. Use info to reset the port etc.
I know that some programs do this. You can even hear old 56K modems reacting to the query when detection algorithm asks them who they are.
Now, you have to search whether this is a standard procedure or each device has its own.
If you are searching for phones, then very probably there is one for phone versions, perhaps each per OS like iOS, Symbian, Android, Windows *, ...
If you cannot find the protocol on the internet, then install virtual card for serial ports, perform man in the middle on looped ports to see what data is sent at initial communication with the phone application.
Note: Don't watch for data when connecting to the internet i.e. using the phone as a modem. You will see only AT&T protocol, which wouldn't help you much.
If you want to see how it works universally, use same technique with virtual serial card but when new device wizard detects for new hardware.
P.S. I found something!
Try sending:
"\x02S\x00\x00\x00\x00\x03"
You should get back some data containing numeric identifier of a device. Like serial number.
Now things work well! I had to type the .read command. Here the solution:
import serial
import time
ser = serial.Serial('/dev/ttyACM0',
460800,
timeout=5,
xonxoff = False,
rtscts = False,
bytesize = serial.EIGHTBITS,
parity = serial.PARITY_NONE,
stopbits = serial.STOPBITS_ONE)
#s = input('Enter AT command --> ')
#print ('AT command = ' + s)
ser.write(bytes('AT+CGMI' + '\r\n'))
ser.timeout = 1
response = ser.read(999)
print(response)
ser.close()
Related
I am doing an instrument integration where the instrument name is Horiba ES60. I am using an RS232 port for communicating for PC and instrument.
I have tested the PC and instrument connection through the Advance Serial Port logger and am getting the monitor result.
I have confirmed that the instrument setting and my script setting are the same.
I have written a simple script in python to read the port data. below is the script.
import time
import serial
sSerialPort = serial.Serial(port = "COM1", baudrate=9600,
bytesize=8, timeout=1, stopbits=serial.STOPBITS_ONE)
sSerialString = "" # Used to hold data coming over UART
print("Connected to : ",sSerialPort.name)
while(True):
# Wait until there is data waiting in the serial buffer
if(sSerialPort.in_waiting > 0):
# Read data out of the buffer until a carraige return / new line is found
sSerialString = sSerialPort.readline()
# Print the contents of the serial data
print(sSerialString)
Output:
b'\x05'
b'\x04'
The expected output is different and I am getting the above one.
Can someone please help to understand what's going wrong?
how to deal with port data in python.
Trying to communicate with a McPherson 747 Device Controller for the Filter Wheel on a lab instrument. It is connected to the lab computer through RS232 to usb. I've connected and communicated with other devices through serial before.
It seems that for a read request, I need to send an enquiry and header and then the Device will acknowledge and send data.
The manual for the Device says that all data is exchanged in ASCII format. Though there are also a few tables in the manual that has inputs in Hex ASCII code. The manual says that a three-byte enquiry is Hex 4E2105 or text N!< ENQ >. Acknowledge is Hex 4E2106 or text N!< ACK > . The header is a mix of several Hex ASCII inputs for reading and writing based on what information the user wants.
The issue I am having is when I code the serial information and send the enquire input, it always sends an error due to communication with the device. I am unfamiliar with Hex. Do I need to be sending the entire enquire, headeras one input, or can I send them separately? I can also try to set up communication with PyVisa but I've gotten similar errors.
Through serial:
import codecs
import serial
try:
ser = serial.Serial(port='COM1',
baudrate = 9600,
timeout = None,
xonxoff = False,
parity = serial.PARITY_NONE,
stopbits = serial.STOPBITS_ONE,
bytesize = serial.EIGHTBITS,
)
ser.close()
string = '4E2105'
enquire = codecs.decode(string,'hex')
ser.open()
ser.write(enquire); #ascii intput for pressing enter on keyboard
ser.read_until(size=None) #reads out feedback until no data is left
ser.close()
msg = f"Program communication initialized"
print(msg)
except Exception as ex:
msg = f"Error: {ex}"
print(msg)
Error: could not open port 'COM1': FileNotFoundError(2, 'The system cannot find the file specified.', None, 2)
Through Pyvisa:
import pyvisa
import serial
import codecs
string = '4E2105'
enquire = codecs.decode(string,'hex')
rm = pyvisa.ResourceManager()
rm.list_resources()
# ('ASRL1::INSTR', 'ASRL2::INSTR', 'GPIB0::12::INSTR')
inst = rm.open_resource('asrl1::instr')
inst.write_termination='\r'
inst.read_termination='\r'
inst.baud_rate = 9600
inst.data_bits = 8
inst.parity = visa.constants.Parity.none
inst.flow_control = visa.constants.VI_ASRL_FLOW_NONE
inst.write(enquire)
print(inst.query("N!<ENQ>"))
rm.close()
VisaIOError: VI_ERROR_RSRC_NFOUND (-1073807343): Insufficient location information or the requested device or resource is not present in the system.
I'm new with the python language
I have a uart bluetooth dongle, I wrote this code below and the write method works fine because I can see the response using the gtkterm software
Code:
import serial
ser = serial.Serial()
ser.baudrate = 115200
ser.port = '/dev/ttyUSB0'
ser.open()
print(ser.is_open)
ser.write(b'info\r\n') # get info command
ser.write(b'scan=00\r\n') # start scan command
The response displayed in gtkterm software:
Device information
firmware: nrf_dongle
firmware_version: 0.2.5-ba519b3
firmware_build: 20180413-104249
device_name: amine
serial_number: a58f2080352ac55bd1850576df54
mac_address: d1850576df54
device_state: 1
adv_state: 0
scan_state: 0
END
#scan:d1850576df54,20fabb03c064,-71,2,30,0201041aff4c00021570996ffaa2c34f00b776a3852c4bbd790cb90006c2
#scan:d1850576df54,20fabb044b2c,-62,2,30,0201041aff4c000215023f3d601143013582ba2e1e1603bcb9ffff02e5c5
#scan:d1850576df54,20fabb044b51,-54,3,30,0201041aff4c000215023f3d601143013582ba2e1e1603bcb9ffff02c8c5
#scan:d1850576df54,20fabb044b2c,-62,2,30,0201041aff4c000215023f3d601143013582ba2e1e1603bcb9ffff02e5c5
.
.
.
So my question is how can I read this data using the pyserial module or any other approach ?
There are many approaches to this problem. First of all the question is - do you want to implement every detail yourself as an exercise? If so then you can implement a function that will read from the serial port one byte at the time, like so:
def readline(port):
message = ""
byte = ""
while True:
byte = port.read()
if byte == "\n":
break
message += byte
return message
It will stop reading from the port when the newline character is encountered and return the message so far. But be aware that there are some problems here (is the end-of-line character always "\n"? What if there is a timeout on the read function?)
Here is the link to the documentation about how the read function behaves. Note, that if the Serial object has not been set with a timeout the function will block, which means that it will wait for the incoming data from the serial port.
The PySerial documentation is a great source of information on the topic - they also provide an example for using the readline function that takes into account problems connected to the newline differences (end-of-line characters). Here is the example from the docs rewritten for your example:
import serial
import io
ser = serial.Serial()
ser.baudrate = 115200
ser.port = '/dev/ttyUSB0'
ser.open()
print(ser.is_open)
sio = io.TextIOWrapper(io.BufferedRWPair(ser, ser))
sio.write(b'info\r\n')
sio.flush() # it is buffering. required to get the data out *now*
response = sio.readline()
print(response)
I strongly suggest to look at the miniterm.py module that is supplied with the PySerial module. Although it might be quite hard at first it is in my opinion a good source of learning material to get accustomed with this library.
I have a USB device with the following specification. Page 22 describes the GNET protocol that should be used to interact with the device.
The connection is fine but the device just doesn't give me any response, so I think I am not sending the correct data to it, maybe missing the handshake?
From Specification
Support TTY (TELE TYPE) OPERATION - Use TTY to send commands and messages
Use ASCII value for each field and use Separator "," between two
Fields.
connect_and_send.py
import serial
port = "COM3"
baud = 9600
ser = serial.Serial(port, baud, timeout=1)
if ser.isOpen():
print(ser.name + ' is open...')
# STX, N, CR
to_send = b'\x02\x4e\x0d'
print "Sending {}".format(to_send)
ser.write(to_send)
out = ser.read()
print('Receiving...'+out)
COM3 is the correct port:
Any help and guidance would be greatly appreciated.
You havenever​ to use \x4e, this is the Negative Acknowledge from the device.
Try
to_send = b'\x02F\x0d'
to get Firmware Version
I contacted the supplier in the end and the issue was setting to wrong baud rate. Changing from 9600 to 19200 resolved the problem.
I have a PC Software (OS: Win 64bit) that communicates with a machine via physical serial port RS232 and I want to make a sniffer for that port using a python. Please note that I am beginner to serial ports.
I've read multiple documents and questions posted online but most of them asks to just use 3rd-party software, but I cannot do this way because raw bytes have to be decoded into string message (I have my way own of decode/encode method).
Currently I have setup like this:
/////////////////// Physical COM1 /////////////
// (PC) Software // <------------------------> // Machine //
/////////////////// /////////////
And I want a python to output any bytes that went through COM1.
Desired Behavior diagram (Virtual serial port has a question mark because I'm not sure if that is the right approach):
/////////////////// Physical COM1 /////////////
// (PC) Software // <------------------------> // Machine //
/////////////////// | Virtual /////////////
| serial port?
v
//////////////////
// (PC) Sniffer // (Python)
//////////////////
|
v
(output bytes)
Those of who knows Advanced Serial Port Monitor, its "spymode" functionality is exactly what I am trying to achieve using python.
I've tried to use com0com and PortMon but I can't find a way to configure com0com to sniff physical port (as far as my observation goes, com0com only makes virtual ports) and PortMon does not support Windows 64-bit.
I've been stuck at this for days... any comments/links/answers are appreciated.
Thank you,
You should go through pySerial
Only one function can acquire the serial port at a time.
For one-way communication(from machine to PC software), the only way I can think of to sniff from a serial port is to read from a port1 and write to port2, where your machine is writing to port1 and PC software has been modified to read from port2.
import serial
baud_rate = 4800 #whatever baudrate you are listening to
com_port1 = '/dev/tty1' #replace with your first com port path
com_port2 = '/dev/tty2' #replace with your second com port path
listener = serial.Serial(com_port1, baudrate)
forwarder = serial.Serial(com_port2, baudrate)
while 1:
serial_out = listener.read(size=1)
print serial_out #or write it to a file
forwarder.write(serial_out)
To achieve full duplex(asynchronous two way communication), you need to have a two processes, one for each direction. You will need to synchronize these process in some way. One way to do it could be, while one process reads from port1, the other writes to port2, and vice-versa.
Read this question
Why not echo something like:
PC S/W <--> COMn(COM0COM)COMm <--> python monitor & forward <--> COM1 <--> Machine
Software wise you need 2 serial tasks one opens COMm and one opens COM1 and a central logger and anything that comes in on COMm gets logged then forwarded to COM1 and vice verca.
We can use the code above without the need to go through threading to achieve a half duplex communication.
we are going to use an infinite loop, and a variable which gonna specify in which port we are reading.
import serial
import time
baud_rate = 9600 # whatever baudrate you are listening to
com_port1 = '/dev/ttyUSB0' # replace with your first com port path
com_port2 = '/dev/ttyUSB1' # replace with your second com port path
ComRead_timeout = 0.1 # Read timeout to avoid waiting while there is no data on the buffer
ComWr_timeout = 0.1 # Write timeout to avoid waiting in case of write error on the serial port
log = open('log.txt', 'a+') # Open our log file, to put read data
From_PC_To_Device = True # this variable is used to specify which port we're gonna read from
listener = serial.Serial(port=com_port1, baudrate=baud_rate, timeout=ComRead_timeout,
write_timeout=ComWr_timeout)
forwarder = serial.Serial(port=com_port2, baudrate=baud_rate, timeout=ComRead_timeout,
write_timeout=ComWr_timeout)
while 1:
while (listener.inWaiting()) and From_PC_To_Device:
serial_out = listener.readline()
localtime = time.asctime(time.localtime(time.time()))
Msg = "PC " + localtime + " " + serial_out
Msg += "\n"
log.write(Msg)
print(serial_out) # or write it to a file
forwarder.write(serial_out)
else:
From_PC_To_Device = False
while (forwarder.inWaiting()) and not From_PC_To_Device:
serial_out = forwarder.readline()
localtime = time.asctime(time.localtime(time.time()))
Msg = "DEVICE " + localtime + " " + serial_out + "\n"
log.write(Msg)
print(serial_out) # or write it to a file
listener.write(serial_out)
else:
From_PC_To_Device = True