Meshtastic-python feature in Android app

Hi,
I was thinking about new feature for Android app. I realy like meshtastic-python CLI but I am missing this in a field when troubleshooting node. So my idea is to implement this feature in mobile app. Maybe would be cool to implement it into chat window.

/meshtastic -h

and response could be same as in console.
It could help troubleshoot or manage nodes remotely (over BT) without need of cable and computer.
What do you think?

3 Likes

Have you considered using Termux for this? You’d need to install python and the meshtastic-python client inside Termux, and access the device through Wi-Fi and TCP/IP (for now, I think; USB or BLE will be a bit challenging due to limitations on Android). I think I saw someone trying to get USB through Termux working (aha, I did indeed see someone trying that!), but that’s probably going to be a long shot.

I did indeed manage to get the CLI installed on termux, but sadly can’t get the termux-usb side of things working…

So the furthest I’ve got so far with termux is by doing the following:

  • Install Termux from fdroid (doesn’t work when installed from Google play)
  • Install Termux-api from fdroid
  • pkg update
  • pkg upgrade
  • pkg install termux-api libusb clang python
  • pip install --upgrade pip
  • pip install --upgrade pytap2
  • pip install --upgrade wheel
  • pip install --upgrade meshtastic
  • termux-usb -l
  [
     "/dev/bus/usb/001/002"
  ]
  • termux-usb -r /dev/bus/usb/001/002
    Then click accept
  • meshtastic --port /Dev/bus/usb/001/002 --info

Unfortunately meshtastic then throws the following error:

Traceback (most recent call last):
  File "/data/data/com.termux/files/usr/lib/python3.9/site-packages/serial/serialposix.py", line 322, in open
    self.fd = os.open(self.portstr, os.O_RDWR | os.O_NOCTTY | os.O_NONBLOCK)
PermissionError: [Errno 13] Permission denied: '/dev/bus/usb/001/002'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/data/data/com.termux/files/usr/bin/meshtastic", line 8, in <module>
    sys.exit(main())
  File "/data/data/com.termux/files/usr/lib/python3.9/site-packages/meshtastic/__main__.py", line 663, in main
    common()
  File "/data/data/com.termux/files/usr/lib/python3.9/site-packages/meshtastic/__main__.py", line 508, in common
    client = SerialInterface(
  File "/data/data/com.termux/files/usr/lib/python3.9/site-packages/meshtastic/__init__.py", line 933, in __init__
    self.stream.open()
  File "/data/data/com.termux/files/usr/lib/python3.9/site-packages/serial/serialposix.py", line 325, in open
    raise SerialException(msg.errno, "could not open port {}: {}".format(self._port, msg))
serial.serialutil.SerialException: [Errno 13] could not open port /dev/bus/usb/001/002: [Errno 13] Permission denied: '/dev/bus/usb/001/002'

I’m not sure if it might need to use the termux libusb library to connect with rather than what it uses currently, or if there’s something else I’m missing. I’ll keep trying to poke at it, but if anyone else has any ideas…

Does it work with TCP/IP? meshtastic --host $node_address while connected to the SoftAP on the ESP32 or while connected to the same Wi-Fi AP? I’m guessing it should, since that’s just networking stuff, and that works with pkg.

I don’t think that’s supposed to work on Termux, based on the docs. The example code does this:

assert((argc > 1) && (sscanf(argv[1], "%d", &fd) == 1));
assert(!libusb_init(&context));
assert(!libusb_wrap_sys_device(context, (intptr_t) fd, &handle));

and launches the user application with this:

termux-usb -e ./usbtest /dev/bus/usb/001/002

So you’ll need some wrapper to read the single argument passed from termux-usb, which will be a number (a file descriptor) which can then be used in libusb as an already-open file descriptor from within meshtastic. The normal flow probably won’t work; if you really want to try it anyway, try making a wrapper launch script to do something like:

#!sh
exec meshtastic --info --port /proc/self/fd/${1}

but I don’t think that’ll work. You’d then call it with:

termux-usb -e ./meshtastic.wrapper /dev/bus/usb/001/002
1 Like

So trying meshtastic --host 192.168.42.1 --info seems to just reset the device wifi, changing the SSID & password to blank, the CLI then times out. Though this also happens when trying it from my PC. @geeksville is this a new bug?

Using the wrapper technique I think works a bit better, though it doesn’t like having the #!sh line in there despite sh otherwise running quite nicely on termux, seems to work without it though. It doesn’t seem to like the port that it sends to meshtastic though. I’ve tried stripping out the /proc/self/fd/ but that obviously doesn’t work either. I’m currently reading through the various github pages on it, but not getting anywhere yet.

~ $ termux-usb -e ./mesh.sh /dev/bus/usb/001/002  Traceback (most recent call last):
  File "/data/data/com.termux/files/usr/lib/python3.9/site-packages/serial/serialposix.py", line 322, in open
self.fd = os.open(self.portstr, os.O_RDWR | os.O_NOCTTY | os.O_NONBLOCK)
  PermissionError: [Errno 13] Permission denied: '/proc/self/fd/7'                                    
  During handling of the above exception, another exception occurred:
Traceback (most recent call last):
    File "/data/data/com.termux/files/usr/bin/meshtastic", line 8, in <module>
        sys.exit(main())
    File "/data/data/com.termux/files/usr/lib/python3.9/site-packages/meshtastic/__main__.py", line 663, in main
        common()
    File "/data/data/com.termux/files/usr/lib/python3.9/site-packages/meshtastic/__main__.py", line 508, in common
        client = SerialInterface(
    File "/data/data/com.termux/files/usr/lib/python3.9/site-packages/meshtastic/__init__.py", line 933, in __init__
        self.stream.open()
    File "/data/data/com.termux/files/usr/lib/python3.9/site-packages/serial/serialposix.py", line 325, in open
        raise SerialException(msg.errno, "could not open port {}: {}".format(self._port, msg))
        serial.serialutil.SerialException: [Errno 13] could not open port /proc/self/fd/7: [Errno 13] Permission denied: '/proc/self/fd/7'

But then I can’t seem to even get the example usbtest code to work after being compile, that just gives me this error:

~ $ termux-usb -e ./usbtest /dev/bus/usb/001/002
usbtest.c:13: int main(int, char **): assertion "!libusb_init(&context)" failed
/data/data/com.termux/files/usr/libexec/termux-callback: line 3: 13676 Aborted
$TERMUX_CALLBACK "$@"

Admittedly my knowledge of C is almost zero, but I’m kinda coming to the conclusion that usb on termux isn’t happening…

That sounds like this. What device firmware version are you using?

It sounds like the Android API for doing this requires an already-open file descriptor. Also, you probably can’t access the UART that way directly; something (libusb?) needs to know how to use the opened fd and translate it into a serial byte stream on one side, but the other side would need to use the opened fd to interact with the USB UART bridge.

libusb_init() failed. You’ll have to dig into why – but this seems like a likely explanation.

2 Likes

Yup, that bugfix has got meshtastic working over wifi nicely, I need to pay more attention to the bugs…

I managed to get the test code working with the solution provided in that issue, though when closing the usb it still throws an issue. I’m gonna try to compile meshtastic on termux and see if that lets usb work, just thinking the version on pip might be using a standard usb library rather than calling the termux one.

AFAICT, Meshtastic does not use libusb at all. --port specifies a character/unbuffered stream device, such as a serial port. The Linux driver for the CP21xx family should take care of all the USB specific stuff. Meshtastic’s SerialInterface counts on something that behaves “like a serial port” (or other unbuffered character device/stream, maybe?), and has no USB awareness at all. You could, for instance, hook up an old PC from 2004 with its RS232 port to a RS232 to 3V3 UART bridge to an ESP32 + GPS + LoRA radio, and use meshtastic --port /dev/ttyS1 --info and it should (mostly) work, minus the high baud rate.

I am not sure what /dev/bus/usb/001/002 is as my own Android device doesn’t have such a thing – or, more likely, my Termux-usb isn’t configured correctly. But I suspect it’s a unique special purpose “file” for Android’s USB stack to interact with libusb, which would mean that trying to use it directly in meshtastic won’t work (with --port). You’d need to add code in meshtastic to use libusb with termux-usb/Android.

I think you’re right, I still haven’t been able to get it to work and suspect I probably won’t be able to. At least we know that it does work over wi-fi though, I’ll add that to the docs. Thanks for your help with this!

1 Like

Glad to help.

That hints to me that perhaps a feature/enhancement on the app for the future should be to allow configuration of ESP32 boards for Wi-Fi; otherwise, serial access from a PC is required for using the python API (can’t bootstrap wifi over wifi).