semuconsulting/PyGPSClient

[Feature] Manual serial port field for UDP fake PTY ports

hpsaturn opened this issue · 11 comments

Overview

I have a GPS that stream data via UPD to my PC. With that I did a fake "serial" interface, like /dev/pts/14, but I can't put it in the serial port connection option because is read only and it is for ttyUSB* ports. Is possible leave this like a manual field?

Solution

Leave the serial port like a manual field (r/w field)

Additional Context

To do a fake serial console and replicate it, please follow the next commands:

Init PTYs:

socat -d -d pty,raw,echo=0 pty,raw,echo=0

Output:

2022/10/07 18:05:11 socat[952338] N PTY is /dev/pts/14
2022/10/07 18:05:11 socat[952338] N PTY is /dev/pts/16
2022/10/07 18:05:11 socat[952338] N starting data transfer loop with FDs [5,5] and [7,7]

Write to input PTY with UDP data:

netcat -u -l -p 9000 > /dev/pts/16

Test new PTY:

cat < /dev/pts/14

output:

$GPGSV,1,1,00*79
$GPGLL,,,,,,V,N*64
$GPRMC,,V,,,,,,,,,,N*53
$GPVTG,,,,,,,,,N*30
$GPGGA,,,,,,0,00,99.99,,,,,,*48
$GPGSA,A,1,,,,,,,,,,,,,99.99,99.99,99.99*30
$GPGSV,1,1,00*79
$GPGLL,,,,,,V,N*64
$GPRMC,,V,,,,,,,,,,N*53
$GPVTG,,,,,,,,,N*30
$GPGGA,,,,,,0,00,99.99,,,,,,*48
$GPGSA,A,1,,,,,,,,,,,,,99.99,99.99,99.99*,,,,0,00,99.99,,,,,,*48
$GPGSA,A,1,,,,,,,,,,,,,99.99,99.99,99.99*30

I wrote a small guide to have virtual serial ports. This guide uses your script socker server implementation and one virtual serial port. With this possible new feature, we could put direct the virtual serial port instead the socket server. It's only an idea.

Hi @hpsaturn. Thanks for this, and sorry it's taken a while to get back to you.

Given the additional information you've provided on virtual ports, I'm not entirely clear what the outstanding issue is or what additional functionality you're after.

As you've presumably seen, the serial port listbox in PyGPSClient uses the standard Python serial.tools.list_ports.comports function to list the available serial ports. This is primarily intended for physical serial connections (i.e. USB or UART), and as a standard library function I have no direct control over its functionality.

I could, as you suggest, add a manual serial port entry facility, but since the listbox works for 99% of standard use cases I'm somewhat loath to complicate the UI for what would be a niche case. I could, as an alternative, provide an optional command line facility for manual port override e.g. pygpsclient port=/dev/pts/14.

As you've seen, PyGPSClient can also read directly from a TCP or UDP socket stream - have you actually tried reading your device's UDP stream directly using this facility, rather than coverting it to a virtual serial port using socat?

If you can clarify exactly what missing functionality you're after, I'm happy to investigate further.

Hi @semuadmin

Thanks for your detailed explanation. I think that option on the command line or via an environment variable could works. Also I understand that this feature maybe nobody needs it, is a minor feature. With the command line option I wouldn't have to start the UDP server.

Regarding to try to read direct the UDP device stream, I need test again because didn't works. I tried many times on many ways. But let me test again, maybe I had some protocol mistakes..

Hi @hpsaturn Yes, suggest try the direct UDP/TCP socket and let me know how you get on. Purely out of interest, any particular reason why you favour UDP over TCP?

I take it you're working with IOT devices like the ESP32? I have in the past tested using a WROOM ESP32 with an old NEO-M6 GPS module connected via UART, transmitting a raw NMEA data stream via a TCP socket using the wifiserver.h Arduino library, and it did work fine with PyGPSClient's socket stream facility.

Yes I will try again it. Regarding TCP/UDP, don't matter. I want map the UART output via TCP/UDP for other features. For example I have a CLI, and sometimes for debugging via UDP could be more fast without no matter lost some packets.. But again, let me try again to test the direct UDP/TCP socket again, for close this issue.

Hi @hpsaturn

FYI I've added a PR containing the following enhancement:

Add provision to pass user-defined serial port designator via command line keyword argument port or environment variable PYGPSCLIENT_USERPORT.

e.g.

pygpsclient port=/dev/tty12345

or

export PYGPSCLIENT_USERPORT = "/dev/tty12345"
pygpsclient

Any user-defined port will appear in the serial port listbox as the first preselected item.

Works like a charm!

(pvenv) (add-app-entry-kwargs) avp:PyGPSClientȹ export PYGPSCLIENT_USERPORT="/dev/pts/10" 
(pvenv) (add-app-entry-kwargs) avp:PyGPSClientȹ python3 -m pygpsclient

screenshot20221104_120455

screenshot20221102_231819

I will change my guide because with this improvement I don't need starting the socket server, I don't need the last part on the guide.

Thanks!

I'm in need of this workaround due to pyserial/pyserial#489, it blocks /dev/ttyS0 on which the GPS is present.
Unfortunately, I can't seem to get the tweak to work

Hi @hpsaturn

FYI I've added a PR containing the following enhancement:

Add provision to pass user-defined serial port designator via command line keyword argument port or environment variable PYGPSCLIENT_USERPORT.

e.g.

pygpsclient port=/dev/tty12345

or

export PYGPSCLIENT_USERPORT = "/dev/tty12345"
pygpsclient

Any user-defined port will appear in the serial port listbox as the first preselected item.

pygpsclient: error: unrecognized arguments: port=/dev/ttyS0

PyGPSClient 1.4.7
Python 3.9.2
Raspberry Pi OS 64-bit "Bullseye"

Thanks for your time,
Martin

Hi @Ve2mrx

Things have moved on a bit since this change was originally made. The easiest way to do this now is via a *.json configuration file e.g. pygpsclient.json. The following configuration setting in the file will take precedence over any command line arguments:

"userport_s": "/dev/ttyS0",

To create an initial default configuration file, simply use the 'File...Save Configuration` menu option.

Unfortunately it appears I've broken the command line parsing so the alternative pygpsclient --userport /dev/ttyS0 or pygpsclient -U /dev/ttyS0 command line argument (note updated syntax) doesn't currently work - a fix will go into v1.4.8: 13ec43b.

Hope this helps

@semuadmin Thanks, this fixed my problem!

Martin