Created
May 14, 2018 18:51
-
-
Save kimthostrup/5545569a6a054782fa357a4018e97e8f to your computer and use it in GitHub Desktop.
Quick, dirty and crappy script to pull DOCSIS connection info from a UPC Connect Box (Compal CH7465LG) and push it to influxdb. Should run as a systemd service. Requires this: https://github.com/ties/compal_CH7465LG_py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python3 | |
import argparse | |
import pprint | |
import os | |
import sys | |
import datetime | |
import signal | |
from time import sleep | |
from lxml import etree | |
from io import StringIO, BytesIO | |
from influxdb import InfluxDBClient | |
# Push the parent directory onto PYTHONPATH before compal module is imported | |
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '..'))) | |
from compal import Compal # noqa | |
CB_HOST = '192.168.100.1' | |
CB_PASSWD = '' | |
ID_HOST = 'localhost' | |
ID_PORT = 8086 | |
ID_DB = 'upc' | |
M_HOSTNAME = '' | |
METRICS_SECONDS = 5 | |
run = True | |
def handler_stop_signals(signum, frame): | |
global run | |
run = False | |
signal.signal(signal.SIGINT, handler_stop_signals) | |
signal.signal(signal.SIGTERM, handler_stop_signals) | |
if __name__ == '__main__': | |
while run: | |
try: | |
# InfluxDB init | |
influx = InfluxDBClient(ID_HOST, ID_PORT, '', '', ID_DB) | |
influx.create_database(ID_DB) | |
retention_policy = 'modem_policy' | |
influx.create_retention_policy(retention_policy, '180d', 1, default=True) | |
except Exception as e: | |
print('ERROR: Error while setting up InfluxDB. Will retry.') | |
print(e) | |
sleep(0.5) | |
continue | |
break | |
while run: | |
try: | |
# modem init and login | |
modem = Compal(CB_HOST, CB_PASSWD) | |
modem.login() | |
except Exception as e: | |
print('ERROR: Failed to log into the modem.') | |
print(e) | |
sleep(0.5) | |
continue | |
break | |
while run: | |
try: | |
# get data | |
mtime = datetime.datetime.utcnow() | |
us_resp = modem.xml_getter(11,{}) | |
ds_resp = modem.xml_getter(10,{}) | |
# process response xmls | |
usp = {} | |
dsp = {} | |
dsn = {} | |
# upstream | |
root = etree.XML(bytes(bytearray(us_resp.text, encoding='utf-8'))) | |
for upstream in root: | |
if upstream.tag == 'upstream': | |
cid = upstream.find('usid').text | |
cpow = upstream.find('power').text | |
usp['value' + str(cid).zfill(2)] = int(cpow) | |
# downstream | |
root = etree.XML(bytes(bytearray(ds_resp.text, encoding='utf-8'))) | |
for downstream in root: | |
if downstream.tag == 'downstream': | |
cid = downstream.find('chid').text | |
cpow = downstream.find('pow').text | |
csnr = downstream.find('snr').text | |
dsp['value' + str(cid).zfill(2)] = int(cpow) | |
dsn['value' + str(cid).zfill(2)] = int(csnr) | |
# write data | |
json_body = [ | |
{ | |
"measurement": "modem.upstream_power", | |
"time": mtime.strftime("%Y-%m-%d %H:%M:%S"), | |
"fields": usp | |
}, | |
{ | |
"measurement": "modem.downstream_power", | |
"time": mtime.strftime("%Y-%m-%d %H:%M:%S"), | |
"fields": dsp | |
}, | |
{ | |
"measurement": "modem.downstream_snr", | |
"time": mtime.strftime("%Y-%m-%d %H:%M:%S"), | |
"fields": dsn | |
} | |
] | |
influx.write_points(json_body, retention_policy=retention_policy) | |
done_time = datetime.datetime.utcnow() | |
time_diff = done_time - mtime | |
if time_diff.seconds >= 5: | |
print('WARN: Couldn\'t complete metrics reporting in {} seconds.'.format(METRICS_SECONDS)) | |
sleep_time = 0 | |
else: | |
sleep_time = METRICS_SECONDS - (time_diff.seconds + (time_diff.microseconds / 1000000)) | |
sleep(sleep_time) | |
except Exception as e: | |
# This probably won't end well. I know this is ugly. | |
print('ERROR: Error while processing modem data.') | |
print(e) | |
print('ERROR: something happened, attempting to log into the modem again...') | |
sleep(0.5) | |
# try logging in again | |
try: | |
modem.login() | |
except Exception as e: | |
print('ERROR: Failed to log into the modem.') | |
print(e) | |
print('Received SIGTERM, logging out...') | |
modem.logout() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment