Cellular signal level indicator

Is there an OpenWRT integrated way to read the received signal level of an LTE modem, and display it via an LED (perhaps as PWM code)?

1 Like

None that I am aware of.

Solved that problem by writing a script. In a once-a-second loop, it reads the signal measurements using the uqmi command, and configures the dual-colour LED to flicker (according to data traffic) red for bad signal, yellow for fair, green for good signal. Fairly straight-forward. It is inspired by, but quite different from, the scripts in the documentation page https://openwrt.org/docs/guide-user/hardware/led/wifi.meter

If anybody is interested, I am happy to share it. Does it make sense to include it on that page?

2 Likes

I'd be interested in doing a LuCI addon so seeing the script and maybe some uqmi example outputs would be useful since I don't have hardware access myself.

Do you want me to post them here in this thread?

Yes, please :slight_smile:

So here we go.

uqmi output when connected to LTE:

root@Lemon:~# uqmi -d /dev/cdc-wdm0 --get-signal-info
{
        "type": "lte",
        "rssi": -89,
        "rsrq": -11,
        "rsrp": -115,
        "snr": 18
}

uqmi output when connected to GSM:

root@Lemon:~# uqmi -d /dev/cdc-wdm0 --get-signal-info
{
        "type": "gsm",
        "signal": -102,
}

I have not been able yet to book into a UMTS (3G) network, as my cell provider got rid of most of their 3G coverage.

In case you wonder why the device's name is Lemon, check a picture of the HW-C108. :grinning:

1 Like

Here is the script. It could be trimmed a bit, as right now it does a bit more than necessary:

#!/bin/sh
#
#   Script running in the background to switch LED colour according
#     to Received Signal Strength
#
#    2020 by Peter Rottengatter - Code under GPLv2
#

device=wwan0


LED_traffic()
{
   dir=${leds_dir}/c108:${1}:modem
   echo netdev > ${dir}/trigger

   echo 1 > ${dir}/link
   echo 1 > ${dir}/rx
   echo 1 > ${dir}/tx
   cat ${dir}/max_brightness > ${dir}/brightness
   echo "${device}" > ${dir}/device_name
 }

LED_off()
{
   dir=${leds_dir}/c108:${1}:modem
   echo none > ${dir}/trigger
 }


NL="$(echo -e ',\n:')"
NL=${NL:1:1}

leds_dir=/sys/class/leds
previous_rssi=1

while true;
  do
     sleep 1
     info=$(uqmi -d /dev/cdc-wdm0 --get-signal-info)

     old_IFS=${IFS}
     IFS=",${NL}"

     for line in ${info}
       do
          label=${line#*\"};   label=${label%\": *}
          value=${line#*: }
          value=${value#\"};   value=${value%\"*}

          case ${label}
            in
             type)                  # Type of connection
               type=${value} ;;
             rssi)                  # Received signal strength indicator
               rssi=${value} ;;
             rsrq)                  # Reference signal received quality
               rsrq=${value} ;;
             rsrp)                  # Reference signal received power
               rsrp=${value} ;;
             snr)                   # Signal to noise ratio
               snr=${value}  ;;
             signal)                # Signal strength for GSM
               rssi=${value} ;;
            esac
       done

     IFS=${old_IFS}

     if [ ${rssi} -eq ${previous_rssi} ]; then
          continue;
       fi
     previous_rssi=${rssi}

     if [ ${rssi} -le -90 ]; then
          LED_traffic red           # Bad signal: LED colour set to red
          LED_off green
          continue;
       fi
     if [ ${rssi} -le -75 ]; then
          LED_traffic red           # Fair signal: LED colour set to yellow
          LED_traffic green
          continue;
       fi
     if [ ${rssi} -le -1 ]; then
          LED_off red               # Good signal: LED colour set to green
          LED_traffic green
          continue;
       fi
     LED_traffic red                # What does RSSI=0 mean? Take it as bad signal
     LED_off green
  done

exit 0

If you do such a LuCI app, I think it would make sense to include some other information provided by uqmi. Immediately to my mind come IMEI and IMSI:

root@Lemon:~# uqmi -d /dev/cdc-wdm0 --get-imei
"8667580xxxxx486"
root@Lemon:~# uqmi -d /dev/cdc-wdm0 --get-imsi
"Not supported"

I used five 'x' to replace five decimal digits for privacy.
I do not know why the IMSI is not reported. AFAIK this should be standard functionality.

I'll check if I find other information from uqmi that would make sense to be displayed. I actually planned to do such an app myself, which would be a fairly simple matter of adding an entry in the Status menu, a status page showing cell network type, signal strength(s), IMEI/IMSI and others. But I'm new to Lua, and you may already have LuCI background so you could probably do that more effectively and faster.

Is there any uqmi command to list the available devices? I cannot really hardcode /dev/cdc-wdm0

I'll check it out, but you can also install it and check, or check the manpage on the internet.

But even if there is no option to list devices, you can still have the user enter it in some configuration field.

I have a status page in LuCI working. I want to populate it a bit more, and may send a screenshot tomorrow. I also have to work around a bug in uqmi: It does not lock the device it is working with. If the signal strength script and the LuCI status page code call it at the same time it locks up. I'm thinking of a wrapper script that puts a semaphore in place.

I have implemented that wrapper script, and - lo and behold! - it also fixes another annoying problem that I had with LTE access: Sometimes, after switching the device on, the WWAN interface would refuse to connect. I didn't care today, I was working on the wrapper, i.e. locally, anyway. Working on uqmi, I noticed for the first time the reason: There were two uqmi processes in deadlock, a new pair appearing as soon as I kill them. So I finished the wrapper, copied it into place, killed the deadlocked processes, and suddenly the WWAN interface connects.

So I think this bug needs to be fixed. Where can I report it? Does the uqmi sub-project have a bugtracker?

You don't need uqmi for that. You can simply list all the qmi_wwan devices. E.g

root@wrt1900ac-1:~# echo /sys/bus/usb/drivers/qmi_wwan/*/usbmisc/*
/sys/bus/usb/drivers/qmi_wwan/3-2:1.8/usbmisc/cdc-wdm0

Excellent, thanks. I was also looking into this. I guess if there is more than one listed it would make sense to check which one is used in an entry in /etc/config/network? Or is there any more sensible approach?

I implemented your hint in my signal indicator script that I had posted above. It works nicely. I also managed to find a way to detect the interface name (wwan0 in my case) automatically. The way to detect two modem LEDs without hardcoding the router model name is a bit crude, but it works. So no loose ends left here. The improved script is here.

#!/bin/sh
#
#   Script running in the background to switch LED colour according
#     to Received Signal Strength
#
#    (c) 2020 by Peter Rottengatter - Code under GPLv2
#


qmi_path='/sys/bus/usb/drivers/qmi_wwan/*/usbmisc/*'
qmi_name=$(basename $(echo ${qmi_path}))

for path in $(echo /sys/class/net/*/device/usbmisc/*)
  do
     if [ "$(basename ${path})" = "${qmi_name}" ]; then
          qmi_iface=${path%%/device/usbmisc/*}
          qmi_iface=${qmi_iface#/sys/class/net/}
       fi
  done

if [ -z "${qmi_iface}" ]; then
     exit 255
  fi
qmi_device=/dev/${qmi_name}

for path in $(echo /sys/class/leds/*modem)
  do
     try=${path%:red:modem}
     if [ "${try}" != "${path}" ]; then
          red_path=${try}
       fi
     try=${path%:green:modem}
     if [ "${try}" != "${path}" ]; then
          green_path=${try}
       fi
  done
if [ "${red_path}" != "${green_path}" ]; then
     exit 255
  fi
leds_prefix=${red_path}


LED_traffic()
{
   dir=${leds_prefix}:${1}:modem
   echo netdev > ${dir}/trigger

   echo 1 > ${dir}/link
   echo 1 > ${dir}/rx
   echo 1 > ${dir}/tx
   cat ${dir}/max_brightness > ${dir}/brightness
   echo "${qmi_iface}" > ${dir}/device_name
 }

LED_off()
{
   dir=${leds_prefix}:${1}:modem
   echo none > ${dir}/trigger
 }


NL="$(echo -e ',\n:')"
NL=${NL:1:1}

previous_rssi=1

while true;
  do
     sleep 1
     info=$(uqmi -d ${qmi_device} --get-signal-info)

     old_IFS=${IFS}
     IFS=",${NL}"

     for line in ${info}
       do
          label=${line#*\"};   label=${label%\": *}
          value=${line#*: }
          value=${value#\"};   value=${value%\"*}

          case ${label}
            in
             type)                  # Type of connection
               type=${value} ;;
             rssi)                  # Received signal strength indicator
               rssi=${value} ;;
             rsrq)                  # Reference signal received quality
               rsrq=${value} ;;
             rsrp)                  # Reference signal received power
               rsrp=${value} ;;
             snr)                   # Signal to noise ratio
               snr=${value}  ;;
             signal)                # Signal strength for GSM
               rssi=${value} ;;
            esac
       done

     IFS=${old_IFS}

     if [ ${rssi} -eq ${previous_rssi} ]; then
          continue;
       fi
     previous_rssi=${rssi}

     if [ ${rssi} -le -90 ]; then
          LED_traffic red           # Bad signal: LED colour set to red
          LED_off green
          continue;
       fi
     if [ ${rssi} -le -75 ]; then
          LED_traffic red           # Fair signal: LED colour set to yellow
          LED_traffic green
          continue;
       fi
     if [ ${rssi} -le -1 ]; then
          LED_off red               # Good signal: LED colour set to green
          LED_traffic green
          continue;
       fi
     LED_traffic red                # What does RSSI=0 mean? Take it as bad signal
     LED_off green
  done

exit 0

So here is the screen shot. The luci app is fairly complete for the moment. Later I want to include a few very useful pieces of information, however, just a with IMSI and ICCID, uqmi does not support providing them yet. Very useful would be listing supported frequency bands to see if the modem is compatible with the cell network operator, or showing the frequency in use.

Any comments or suggestions?

BTW.: The theme is "Material" with personalised colours.

1 Like

Here is a version that includes almost all what I want. The displayed information where uqmi does not provide it is dummy.

Whoever reads this is more likely to be familiar with the Bootstrap theme, so here we go:

2 Likes

I removed the hardcoded device definition and replaced it by auto detection. In this form it should be usable and informative for anybody with a device featuring a qmi capable modem running unter OpenWRT.

Since there are no comments or suggestions forthcoming I'd like to make it available to everybody for testing. In order to get acquainted with the package format I unpacked some existing ones, nosed around a bit, and packaged my code manually. I now have a file luci-app-qmi-cellstatus_1.0.0_all.ipk, that opkg installs just fine.

Pretty sure that is not the official way to bring in a new package to make it available for testing. The docs seem to describe only the creation of a package from external sources that needs configuration and compilation, etc. This here is a trivialily in comparison, two files that cater for all architectures, no compilation or any processing needed.

Any suggestions on how to proceed?

1 Like

I have previously suggested to email me for the package, but now I made it available for download through
http://www.rottengatter.de/download/luci-app-qmi-cellstatus_1.0.0_all.ipk
So if you have an LTE or UMTS modem that runs via the QMI driver feel free to install and test it. Just download it to your OpenWRT system, and from the directory with the file run

opkg install ./luci-app-qmi-cellstatus_1.0.0_all.ipk

That's it. You may need to log out of LuCI and re-login in order to see the new entry in the Status menu.

After you've done that and checked it out I'd appreciate if you could drop me one or two lines here with your experience and suggestions.

18 Likes

This topic was automatically closed 10 days after the last reply. New replies are no longer allowed.