Skip to content

Commit d7b1623

Browse files
authored
network-openwrt-status,network-huawei-modem: add scripts
1 parent f814ef2 commit d7b1623

File tree

6 files changed

+211
-0
lines changed

6 files changed

+211
-0
lines changed
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
# Script: network-huawei-modem
2+
3+
Print stats from Huawei modem sticks. Such as signal levels, sms count and traffic bandwidth.
4+
5+
Tested with E3372h-320, but should work with others.
6+
7+
![network-huawei-modem](screenshots/1.png)
8+
9+
10+
## Dependencies
11+
12+
* [`Salamek/huawei-lte-api`](https://github.com/Salamek/huawei-lte-api)
13+
14+
15+
## Configuration
16+
17+
Just insert your modem ip and credentials into heading of script.
18+
19+
20+
## Module
21+
22+
```ini
23+
[module/network-huawei-modem]
24+
type = custom/script
25+
exec = ~/polybar-scripts/network-huawei-modem.py
26+
interval = 5
27+
```
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
#!/usr/bin/env python3
2+
# -*- coding: utf-8 -*- # PEP 263
3+
4+
from huawei_lte_api.Client import Client
5+
from huawei_lte_api.Connection import Connection
6+
7+
# Configuration
8+
host = '192.168.8.1'
9+
username = 'admin'
10+
password = ''
11+
12+
MODEM_URL = f"http://{username}:{password}@{host}/"
13+
14+
15+
def scale_units(rate):
16+
decimal_places = 2
17+
for unit in ['bps', 'Kbps', 'Mbps', 'Gbps', 'Tbps']:
18+
if rate < 1000.0:
19+
if unit == 'bps':
20+
decimal_places = 0
21+
break
22+
rate /= 1000.0
23+
return f"{rate:.{decimal_places}f}{unit}"
24+
25+
26+
if __name__ == '__main__':
27+
with Connection(MODEM_URL) as connection:
28+
# This just simplifies access to separate API groups,
29+
# you can use device = Device(connection) if you want
30+
client = Client(connection)
31+
32+
signal = client.device.signal()
33+
traffic = client.monitoring.traffic_statistics()
34+
sms = client.sms.sms_count()
35+
status = client.monitoring.status()
36+
sms_unread = int(sms['LocalUnread'])
37+
38+
power = status['SignalIcon']
39+
sinr = signal['sinr']
40+
sms_icon = '' if sms_unread else ''
41+
down = scale_units(int(traffic['CurrentDownloadRate']) * 8)
42+
up = scale_units(int(traffic['CurrentUploadRate']) * 8)
43+
result = f":{power} SINR:{sinr} {sms_icon}:{sms_unread}{down}{up}"
44+
45+
print(result)
15.5 KB
Loading
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
# Script: network-openwrt-status
2+
3+
Print stats from OpenWrt router. Such as signal levels, sms count and traffic bandwidth.
4+
5+
Written for Microdrive Tandem-4GT-OEM modem, but can be adopted to work with all OpenWrt routers.
6+
7+
![network-openwrt-status](screenshots/1.png)
8+
9+
10+
## Dependencies
11+
12+
* `python-requests`
13+
14+
15+
## Configuration
16+
17+
Just insert your router ip and credentials into heading of script.
18+
19+
20+
## Module
21+
22+
```ini
23+
[module/network-openwrt-status]
24+
type = custom/script
25+
exec = ~/polybar-scripts/network-openwrt-status.py
26+
interval = 5
27+
```
Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
#!/usr/bin/python3
2+
# -*- coding: utf-8 -*- # PEP 263
3+
4+
import requests
5+
from binascii import unhexlify
6+
7+
# Configuration
8+
host = '192.168.8.1'
9+
username = 'root'
10+
password = ''
11+
12+
LOGIN_URL = f"http://{host}/cgi-bin/luci/"
13+
MODEM_URL = f"http://{host}/cgi-bin/luci/?status=1"
14+
SMS_URL = f"http://{host}/cgi-bin/luci/admin/services/modem_read_sms/all?block=0"
15+
BW_URL = f"http://{host}/cgi-bin/luci/admin/status/realtime/bandwidth_status/wwan0"
16+
17+
18+
def scale_units(rate):
19+
# input: integer
20+
decimal_places = 2
21+
for unit in ['bps', 'Kbps', 'Mbps', 'Gbps', 'Tbps']:
22+
if rate < 1000.0:
23+
if unit == 'bps':
24+
decimal_places = 0
25+
break
26+
rate /= 1000.0
27+
return f"{rate:.{decimal_places}f}{unit}"
28+
29+
30+
def sms_concatenate(data):
31+
# input: list of dicts
32+
sms = list()
33+
concat = dict()
34+
for item in data:
35+
if not item['fail']:
36+
if 'c_ref' in item:
37+
if item['c_ref'] not in concat:
38+
concat[item['c_ref']] = list()
39+
concat[item['c_ref']].append(item)
40+
else:
41+
sms.append(item)
42+
if len(concat):
43+
for key, parts in concat.items():
44+
parts.sort(key=lambda x: x['c_cur'])
45+
for part in parts:
46+
if part['c_cur'] == 1:
47+
sms.append(part)
48+
else:
49+
sms[-1]['data'] += part['data']
50+
return sms
51+
52+
53+
def sms_decode(sms):
54+
# input: dict
55+
if sms['dcs'] == 2:
56+
sms['data'] = unhexlify(sms['data']).decode('utf-16be')
57+
return sms
58+
59+
60+
if __name__ == '__main__':
61+
# setup session and authenticate
62+
s = requests.Session()
63+
s.post(LOGIN_URL, data={'luci_username': username, 'luci_password': password})
64+
s.headers.update({'Content-Type': 'application/json'})
65+
66+
# get lte modem stats (luci-mod-microdrive)
67+
r = s.get(MODEM_URL)
68+
r = r.json()
69+
name = r['ifg']['spn']
70+
lvl = r['ifg']['rssi_lv']
71+
rssi = r['ifg']['cell_lte'][0]['rssi']
72+
rsrp = r['ifg']['cell_lte'][0]['rsrp']
73+
sinr = r['ifg']['cell_lte'][0]['sinr']
74+
result = f"{name}{lvl}% RSSI {rssi}dBm RSRP {rsrp}dBm SINR {sinr}dB"
75+
76+
# get sms count (luci-mod-microdrive)
77+
r = s.get(SMS_URL)
78+
r = r.json()
79+
mem_total = 255
80+
mem_used = 0
81+
sms_count = 0
82+
if r['code'] == 0 and 'out' in r and 'sms' in r['out']:
83+
mem_total = r['out']['mem']['total']
84+
mem_used = r['out']['mem']['used']
85+
data = r['out']['sms']
86+
if len(data):
87+
sms = sms_concatenate(data)
88+
sms_count = len(sms)
89+
icon = '' if sms_count else ''
90+
# if mem_used > mem_total * 0.90:
91+
# sms_count = 'MANY'
92+
result = result + f" {icon} {sms_count}"
93+
94+
# get traffic stats
95+
# the response is array of array [[TIME, RXB, RXP, TXB, TXP]]
96+
# we only need two last items with TIME, RXB and TXB fields
97+
r = s.get(BW_URL)
98+
r = r.json()
99+
rxb = 0
100+
txb = 0
101+
if len(r) >= 2:
102+
# get last two items
103+
a = r.pop()
104+
b = r.pop()
105+
# normalize difference against time interval
106+
# this code from luci XHR.poll function
107+
time_delta = a[0] - b[0]
108+
rxb = scale_units((a[1] - b[1]) / time_delta * 8)
109+
txb = scale_units((a[3] - b[3]) / time_delta * 8)
110+
result = result + f" {rxb}{txb}"
111+
112+
print(result)
15.3 KB
Loading

0 commit comments

Comments
 (0)