mqtt_client.on_connect = on_connect mqtt_client.on_message = on_message mqtt_client.on_publish = on_publish mqtt_client.on_subscribe = on_subscribe # Set a Will to be sent by the broker in case the client disconnects unexpectedly. # QOS 2: The broker will deliver the message exactly once by using a four step handshake. mqtt_client.will_set('/will/oops', payload='{} has vanished!'.format( settings.MQTT_CLIENT_ID), qos=2) connack_code = mqtt_client.connect(settings.MQTT_SERVER, settings.MQTT_PORT) cp.log('MQTT connect reply to {}, {}: {}'.format( settings.MQTT_SERVER, settings.MQTT_PORT, mqtt.connack_string(connack_code))) # Blocking call that processes network traffic, dispatches callbacks and # handles reconnecting. mqtt_client.loop_forever() except Exception as ex: cp.log('Exception in start_mqtt()! exception: {}'.format(ex)) raise cp.log('Starting...') mqtt_thread = Thread(target=start_mqtt, args=()) mqtt_thread.start() publish_thread()
if result and result.get('status') in ["error", "done"]: break time.sleep(2) try_count += 1 if try_count == 15: pingstats['error'] = "No Results - Execution Timed Out" else: # Parse results text parsedresults = result.get('result').split('\n') i = 0 index = 1 for item in parsedresults: if item[0:3] == "---": index = i + 1 i += 1 pingstats['tx'] = int(parsedresults[index].split(' ')[0]) pingstats['rx'] = int(parsedresults[index].split(' ')[3]) pingstats['loss'] = float( parsedresults[index].split(' ')[6].split('%')[0]) pingstats['min'] = float(parsedresults[index + 1].split(' ')[5].split('/')[0]) pingstats['avg'] = float(parsedresults[index + 1].split(' ')[5].split('/')[1]) pingstats['max'] = float(parsedresults[index + 1].split(' ')[5].split('/')[2]) return pingstats cp = EventingCSClient('ping_sample') cp.log('Starting...') cp.log('Output:\n' + json.dumps(ping('8.8.8.8')))
# Log the Get request cp.log(f'Received Get request: {self.path}') # Send response status code self.send_response(200) # Send headers self.send_header('Content-type', 'text/html') self.end_headers() # Send message back to client # Write content as utf-8 data self.wfile.write(bytes(WEB_MESSAGE, "utf8")) return cp = EventingCSClient('simple_web_server') WEB_MESSAGE = "Hello World from Cradlepoint router!" server_address = ('localhost', 9001) cp.log("Starting Server: {}".format(server_address)) cp.log("Web Message is: {}".format(WEB_MESSAGE)) httpd = HTTPServer(server_address, WebServerRequestHandler) try: httpd.serve_forever() except KeyboardInterrupt: cp.log("Stopping Server, Key Board interrupt")
class SIMSpeedTest(object): MIN_DOWNLOAD_SPD = 0.0 # Mbps MIN_UPLOAD_SPD = 0.0 # Mbps SCHEDULE = 0 # Run Boot2 every {SCHEDULE} minutes. 0 = Only run on boot. NUM_ACTIVE_SIMS = 0 # Number of fastest (download) SIMs to keep active. 0 = all; do not disable SIMs ONLY_RUN_ONCE = False # True means do not run if Boot2 has been run on this device before. STATUS_DEVS_PATH = '/status/wan/devices' CFG_RULES2_PATH = '/config/wan/rules2' CTRL_WAN_DEVS_PATH = '/control/wan/devices' API_URL = 'https://www.cradlepointecm.com/api/v2' CONNECTION_STATE_TIMEOUT = 7 * 60 # 7 Min NETPERF_TIMEOUT = 5 * 60 # 5 Min sims = {} def __init__(self): self.client = EventingCSClient('Boot2') def check_if_run_before(self): if self.ONLY_RUN_ONCE: if self.client.get('/config/wan/rules2/0/_id_' ) == '00000000-1234-1234-1234-1234567890ab': self.client.log( 'ERROR - Boot2 has been run before! /config/wan/rules2/0/_id = 00000000-1234-1234-1234-1234567890ab' ) raise RunBefore( 'ERROR - Boot2 has been run before! /config/wan/rules2/0/_id = 00000000-1234-1234-1234-1234567890ab' ) return False def wait_for_ncm_sync(self): # WAN connection_state if self.client.get('status/wan/connection_state') != 'connected': self.client.log('Waiting until WAN is connected...') timeout_count = 500 while self.client.get('/status/wan/connection_state') != 'connected': timeout_count -= 1 if not timeout_count: raise Timeout('WAN not connecting') time.sleep(2) # ECM State if self.client.get('status/ecm/state') != 'connected': self.client.log('Waiting until NCM is connected...') self.client.put('/control/ecm', {'start': True}) timeout_count = 500 while self.client.get('/status/ecm/state') != 'connected': timeout_count -= 1 if not timeout_count: raise Timeout('NCM not connecting') time.sleep(2) # ECM Sync if self.client.get('status/ecm/sync') != 'ready': self.client.log('Waiting until NCM is synced...') self.client.put('/control/ecm', {'start': True}) timeout_count = 500 while self.client.get('/status/ecm/sync') != 'ready': self.client.put('/control/ecm', {'start': True}) timeout_count -= 1 if not timeout_count: raise Timeout('NCM not connecting') time.sleep(2) return def NCM_suspend(self): self.client.log('Stopping NCM') timeout_count = 500 while not 'ready' == self.client.get('/status/ecm/sync'): timeout_count -= 1 if not timeout_count: raise Timeout('NCM sync not ready') time.sleep(2) self.client.put('/control/ecm', {'stop': True}) timeout_count = 500 while not 'stopped' == self.client.get('/status/ecm/state'): timeout_count -= 1 if not timeout_count: raise Timeout('NCM not stopping') time.sleep(2) def find_sims(self): while True: sims = {} wan_devs = self.client.get(self.STATUS_DEVS_PATH) or {} for uid, status in wan_devs.items(): if uid.startswith('mdm-'): error_text = status.get('status', {}).get('error_text', '') if error_text: if 'NOSIM' in error_text: continue sims[uid] = status num_sims = len(sims) if not num_sims: self.client.log('No SIMs found at all yet') time.sleep(10) continue if num_sims < 2: self.client.log('Only 1 SIM found!') raise OneModem('Only 1 SIM found!') else: break self.client.log(f'Found SIMs: {sims.keys()}') self.sims = sims return True def modem_state(self, sim, state): # Blocking call that will wait until a given state is shown as the modem's status timeout_counter = 0 sleep_seconds = 0 conn_path = '%s/%s/status/connection_state' % (self.STATUS_DEVS_PATH, sim) self.client.log(f'Connecting {self.port_sim(sim)}') while True: sleep_seconds += 5 conn_state = self.client.get(conn_path) self.client.log( f'Waiting for {self.port_sim(sim)} to connect. Current State={conn_state}' ) if conn_state == state: break if timeout_counter > self.CONNECTION_STATE_TIMEOUT: self.client.log(f'Timeout waiting on {self.port_sim(sim)}') raise Timeout(conn_path) time.sleep(min(sleep_seconds, 45)) timeout_counter += sleep_seconds self.client.log(f'{self.port_sim(sim)} connected.') return True def iface(self, sim): iface = self.client.get('%s/%s/info/iface' % (self.STATUS_DEVS_PATH, sim)) return iface def port_sim(self, sim): return f'{self.sims[sim]["info"]["port"]} {self.sims[sim]["info"]["sim"]}' def run_speedtest(self, speedtest): self.client.put('/state/system/netperf', {"run_count": 0}) res = self.client.put("/control/netperf", speedtest) self.client.log(f'Starting Speedtest... {res}') timeout_counter = 0 # wait for results delay = speedtest['input']['options']['limit']['time'] + 8 status_path = "/control/netperf/output/status" while True: time.sleep(delay) status = self.client.get(status_path) if status == 'complete': break if timeout_counter > self.NETPERF_TIMEOUT: self.client.log( f"Timeout waiting on speedtest for {speedtest['input']['options']['ifc_wan']}" ) raise Timeout(status_path) timeout_counter += delay if status != 'complete': self.client.log(f"ERROR: status=%s expected 'complete' {status}") return None # now get the result results_path = self.client.get("/control/netperf/output/results_path") results = None while not results: results = self.client.get(results_path) time.sleep(2) self.client.log('Speedtest Complete.') return results def do_speedtest(self, sim): default_speedtest['input']['options']['ifc_wan'] = self.iface(sim) default_speedtest['input']['options']['send'] = False default_speedtest['input']['options']['recv'] = True tcp_down = self.run_speedtest(default_speedtest).get('tcp_down') default_speedtest['input']['options']['send'] = True default_speedtest['input']['options']['recv'] = False tcp_up = self.run_speedtest(default_speedtest).get('tcp_up') if not tcp_up: self.client.log('do_speedtest tcp_up results missing!') default_speedtest['input']['options']['send'] = True default_speedtest['input']['options']['recv'] = False results = self.run_speedtest(default_speedtest) tcp_up = results.get('tcp_up') or None if not tcp_down: self.client.log('do_speedtest tcp_down results missing!') default_speedtest['input']['options']['send'] = False default_speedtest['input']['options']['recv'] = True results = self.run_speedtest(default_speedtest) tcp_down = results.get('tcp_down') or None down = float(tcp_down.get('THROUGHPUT', 0.0)) if tcp_down else 0.0 up = float(tcp_up.get('THROUGHPUT', 0.0)) if tcp_up else 0.0 return down, up def test_sim(self, device): try: if self.modem_state(device, 'connected'): # Get diagnostics and log it diagnostics = self.client.get( f'{self.STATUS_DEVS_PATH}/{device}/diagnostics') self.sims[device]['diagnostics'] = diagnostics self.client.log( f'Modem Diagnostics: {self.port_sim(device)} RSRP:{diagnostics.get("RSRP")}' ) # Do speedtest and log results self.sims[device]['download'], self.sims[device][ 'upload'] = self.do_speedtest(self.sims[device]) self.client.log( f'Speedtest Results: {self.port_sim(device)} TCP Download: ' f'{self.sims[device]["download"]}Mbps TCP Upload: {self.sims[device]["upload"]}Mbps' ) # Verify minimum speeds if self.sims[device].get( 'download', 0.0) > self.MIN_DOWNLOAD_SPD and self.sims[device].get( 'upload', 0.0) > self.MIN_UPLOAD_SPD: return True else: # Did not meet minimums self.client.log( f'{self.port_sim(device)} Failed to meet minimums! MIN_DOWNLOAD_SPD: {self.MIN_DOWNLOAD_SPD} MIN_UPLOAD_SPD: {self.MIN_UPLOAD_SPD}' ) return False except Timeout: message = f'Timed out running speedtest on {self.port_sim(device)}' self.client.log(message) self.client.alert(message) self.sims[device]['download'] = self.sims[device]['upload'] = 0.0 return False def create_message(self, uid, *args): message = '' for arg in args: if arg == 'download': message = "DL:{:.2f}Mbps".format( self.sims[uid]['download']) if not message else ' '.join([ message, "DL:{:.2f}Mbps".format( self.sims[uid]['download']) ]) elif arg == 'upload': message = "UL:{:.2f}Mbps".format( self.sims[uid]['upload']) if not message else ' '.join([ message, "UL:{:.2f}Mbps".format( self.sims[uid]['upload']) ]) elif arg in ['PRD', 'HOMECARRID', 'RFBAND']: # Do not include labels for these fields message = "{}".format( self.sims[uid]['diagnostics'][arg] ) if not message else ' '.join( [message, "{}".format(self.sims[uid]['diagnostics'][arg])]) else: # Include field labels (e.g. "RSRP:-82") message = "{}:{}".format( arg, self.sims[uid]['diagnostics'] [arg]) if not message else ' '.join([ message, "{}:{}".format( arg, self.sims[uid]['diagnostics'][arg]) ]) return message def lock_sim(self, sim): rules = [{ "_id_": "00000000-1234-1234-1234-123456789000", "priority": 0, "trigger_name": f"{self.sims[sim]['info']['port']} {self.sims[sim]['info']['sim']}", "trigger_string": f"type|is|mdm%sim|is|{self.sims[sim]['info']['sim']}%port|is|{self.sims[sim]['info']['port']}" }] for i, uid in enumerate(self.sims): if uid != sim: rule = { "_id_": f"0000000{i+1}-1234-1234-1234-123456789000", "priority": -9 + i, "trigger_name": f"{self.sims[sim]['info']['port']} {self.sims[sim]['info']['sim']}", "trigger_string": f"type|is|mdm%sim|is|{self.sims[sim]['info']['sim']}%port|is|{self.sims[sim]['info']['port']}", "disabled": True } rules.append(rule) self.client.put('config/wan/rules2', rules) time.sleep(2) def create_rules(self, sim_list): wan_rules = [{ "_id_": "00000000-1234-1234-1234-1234567890ab", "priority": -10, "trigger_name": "Ethernet", "trigger_string": "type|is|ethernet" }] for i in range(0, len(sim_list)): rule = { "_id_": f"0000000{i+1}-1234-1234-1234-123456789000", "priority": -9 + i, "trigger_name": f"{self.sims[sim_list[i]]['info']['port']} {self.sims[sim_list[i]]['info']['sim']}", "trigger_string": f"type|is|mdm%sim|is|{self.sims[sim_list[i]]['info']['sim']}%port|is|{self.sims[sim_list[i]]['info']['port']}" } if self.NUM_ACTIVE_SIMS and i >= self.NUM_ACTIVE_SIMS: rule['disabled'] = True wan_rules.append(rule) req = self.client.put('config/wan/rules2/', wan_rules) time.sleep(2) if self.client.get('config/wan/rules2/0/_id_' ) == '00000000-1234-1234-1234-1234567890ab': self.client.log(f'Updated WAN rules') else: self.client.log(f'WAN Rules not updated! : {req}') return def run(self): # *** Main Application Starts Here *** self.client.log( f'Boot2 Starting... MIN_DOWNLOAD_SPD:{self.MIN_DOWNLOAD_SPD} MIN_UPLOAD_SPD:{self.MIN_UPLOAD_SPD} ' f'SCHEDULE:{self.SCHEDULE} NUM_ACTIVE_SIMS:{self.NUM_ACTIVE_SIMS} ONLY_RUN_ONCE:{self.ONLY_RUN_ONCE}' ) self.check_if_run_before() self.wait_for_ncm_sync() # Get info from router product_name = self.client.get("/status/product_info/product_name") system_id = self.client.get("/config/system/system_id") router_id = self.client.get('status/ecm/client_id') self.find_sims() # Find active SIM slots # Send startup alert message = f'Boot2 Starting! {system_id} - {product_name} - Router ID: {router_id}' self.client.log(f'Sending alert to NCM: {message}') self.client.alert(message) # Pause for 3 seconds to allow NCM Alert to be sent before suspending NCM time.sleep(3) self.NCM_suspend() success = False # Boot2 Success Status - Becomes True when a SIM meets minimum speeds # Test the connected SIM first primary_device = self.client.get('status/wan/primary_device') if 'mdm-' in primary_device: # make sure its a modem if self.test_sim(primary_device): success = True # test remaining SIMs for sim in self.sims: if not self.sims[sim].get('download'): self.lock_sim(sim) if self.test_sim(sim): success = True # Prioritizes SIMs based on download speed sorted_results = sorted(self.sims, key=lambda x: self.sims[x]['download'], reverse=True) # Create WAN rules self.create_rules(sorted_results) time.sleep(3) # Build text for custom1 field results_text = datetime.datetime.now().strftime( '%m/%d/%y %H:%M:%S') # Start with a timestamp if not success: results_text += f' FAILED TO MEET MINIMUMS! MIN_DOWNLOAD_SPD:{self.MIN_DOWNLOAD_SPD} MIN_UPLOAD_SPD:{self.MIN_UPLOAD_SPD}' for uid in sorted_results: # Add the results of each SIM with the fields specified: results_text = ' | '.join([ results_text, self.create_message(uid, 'PRD', 'HOMECARRID', 'RFBAND', 'RSRP', 'download', 'upload') ]) # put messages to NCM custom fields self.wait_for_ncm_sync() if apikeys.get('X-ECM-API-ID') != 'YOUR': self.client.log( f'X-ECM-API-ID: {apikeys["X-ECM-API-ID"]} X-CP-API-ID: {apikeys["X-CP-API-ID"]}' ) req = requests.put(f'{self.API_URL}/routers/{router_id}/', headers=apikeys, json={'custom1': results_text[:255]}) self.client.log(f'NCM PUT Custom1 Result: {req.status_code}') else: self.client.log( 'No NCM API Keys configured, skipping PUT to custom1') # Complete! Send results. message = f"Boot2 Complete! {system_id} Results: {results_text}" self.client.log(message) self.client.alert(message)
""" Probe the GPS hardware and log the results. """ from csclient import EventingCSClient cp = EventingCSClient('gps_probe') gps_enabled = cp.get('/config/system/gps/enabled') if not gps_enabled: cp.log('GPS Function is NOT Enabled') else: cp.log('GPS Function is Enabled') gps_data = cp.get('/status/gps') cp.log(gps_data)
cp = EventingCSClient('cpu_usage') def get_usage(): while True: memory = cp.get('/status/system/memory') load_avg = cp.get('/status/system/load_avg') cpu = cp.get('/status/system/cpu') log_data = ( 'CPU Usage: ' + str( round( float(cpu['nice']) + float(cpu['system']) + float(cpu['user']) * float(100))) + '%, ' + ' Mem Available: ' + str( ('{:,.0f}'.format(memory['memavailable'] / float(1 << 20)) + " MB,")) + ' Mem Total: ' + str( ('{:,.0f}'.format(memory['memtotal'] / float(1 << 20)) + " MB" + "\n"))) cp.log(log_data) time.sleep(15) if __name__ == '__main__': cp.log('Started App') get_usage() cp.log('Exited App')
# hello_world - log "Hello World!" from csclient import EventingCSClient cp = EventingCSClient('hello_world') cp.log('Hello World!')
if loader not in loaders: loaders[loader] = [] # Add a name and a location about an imported module in the dict. # Don't include files that were created for this app or any # shared libraries. if this_module_name not in module_info.origin and '.so' not in module_info.origin: loaders[loader].append((module_info.name, module_info.origin)) line = '-' * 10 # Log the python version running in the device cp.log('{0} Python Version: {1} {0}'.format(line, platform.python_version())) # Log the python module that were found in the device for loader, modules in loaders.items(): if len(modules) != 0: cp.log('{0} Module Count={1}: {2} {0}'.format( line, len(modules), loader)) count = 0 for mod in modules: count += 1 cp.log('|{0:>3}| {1:20}| {2}'.format(count, mod[0], mod[1])) if __name__ == "__main__": try: log_module_list() except Exception as e: cp.log('Exception occurred! exception: {}'.format(e))
ip_data = get_ip_config_info(form) ip_config(ip_data) value = '{} - {}'.format(value, ip_data) if value == 'router_data': self.send_response(HTTPStatus.OK) self.send_header('Content-type', 'application/json') self.end_headers() self.wfile.write( bytes(json.dumps(get_router_data()), 'utf-8')) return # This is here just to echo back to the client what is receive. self.send_response(HTTPStatus.OK) self.send_header('Content-type', 'text/html') self.end_headers() self.wfile.write( bytes( '<html><body><h1>Server Received: {}</h1></body></html>'. format(value), 'utf-8')) cp = EventingCSClient('simple_custom_dashboard') server_address = ('', 9001) cp.log('Starting Server: {}'.format(server_address)) httpd = HTTPServer(server_address, WebServerRequestHandler) try: httpd.serve_forever() except KeyboardInterrupt: cp.log('Stopping Server, Key Board interrupt')
cp = EventingCSClient('multicast_to_unicast') ''' MODIFY THESE VARIABLES TO MATCH YOUR ENVIRONMENT ''' MCAST_GRP = '224.1.1.1' # Multicast group to listen on MCAST_PORT = 5001 # Multicast port to listen on MCAST_LISTEN_IP = '192.168.0.1' # Cradlepoint interface IP address to listen on UCAST_DST_IP = '192.168.0.125' #Unicast destination to UCAST_DST_PORT = 5002 ''' DO NOT CHANGE ANYTHING BELOW ''' cp.log("APP STARTED") s = socket.socket(type=socket.SOCK_DGRAM) s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) try: s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEPORT, 1) except AttributeError: pass s.setsockopt(socket.SOL_IP, socket.IP_MULTICAST_TTL, 20) s.setsockopt(socket.SOL_IP, socket.IP_MULTICAST_LOOP, 1) s.bind(('', MCAST_PORT)) intf = MCAST_LISTEN_IP s.setsockopt(socket.SOL_IP, socket.IP_MULTICAST_IF, socket.inet_aton(intf)) s.setsockopt(socket.SOL_IP, socket.IP_ADD_MEMBERSHIP,
# anonymous user authorizer.add_user('survey', 'survey', FTP_DIR, perm='elradfmwM') authorizer.add_anonymous(FTP_DIR) # Instantiate FTP handler class handler = FTPHandler handler.authorizer = authorizer # Define a customized banner (string returned when client connects) handler.banner = "pyftpdlib based ftpd ready." # Instantiate FTP server class and listen on 0.0.0.0:2121. # Application can only use ports higher that 1024 and the port # will need to be allowed in the router firewall address = ('', 2121) server = FTPServer(address, handler) # set a limit for connections server.max_cons = 256 server.max_cons_per_ip = 5 # start ftp server cp.log('Starting FTP server...') server.serve_forever() # This will run the server in another thread # t = Thread(target=server.serve_forever()) # t.start() except Exception as e: cp.log('Exception occurred! exception: {}'.format(e))
A reference application to access GNSS on the IBR1700. See the readme.txt for more details. """ import time import socket from inetline import ReadLine from csclient import EventingCSClient cp = EventingCSClient('ibr1700_gnss') gnssd_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) try: cp.log('Starting...') gnss_addr = ("127.0.0.1", 17488) cp.log("Attempting sock.connect({})".format(gnss_addr)) gnssd_sock.connect(gnss_addr) # Turns on ALL messages. Only way to turn off is to close the socket. cp.log("Attempting sock.send(b'ALL\\r\\n')") gnssd_sock.sendall(b'ALL\r\n') # Enable IMU messages cp.log("Attempting sock.send(b'IMU yes\\r\\n')") gnssd_sock.sendall(b'IMU yes\n\r') receive_line = ReadLine()
class DataUsageCheck(object): """ Establish global variables. Set rate shaping values (in Kbps) """ # Modem Defaults (as of 7.0.40) - Not used when QoS is Disabled maxbwup = 25000 maxbwdown = 25000 minbwup = 512 minbwdown = 512 capreached = 0 STATUS_DEVS_PATH = '/status/wan/devices' STATUS_DATACAP_PATH = '/status/wan/datacap' CFG_RULES2_PATH = '/config/wan/rules2' def __init__(self): self.cp = EventingCSClient(app_name) def find_modems(self): while True: devs = self.cp.get(self.STATUS_DEVS_PATH) modems_list = [x for x in devs if x.startswith('mdm-')] self.cp.log(f'modems_list: {modems_list}') num_modems = len(modems_list) if not num_modems: self.cp.log('No Modems found at all yet') time.sleep(10) continue else: return modems_list def find_modem_profiles(self): wan_ifcs = self.cp.get(self.CFG_RULES2_PATH) modem_profiles_list = [ x['_id_'] for x in wan_ifcs if x['trigger_string'].startswith('type|is|mdm') ] self.cp.log(f'modem_profiles_list: {modem_profiles_list}') return modem_profiles_list def reset_throttle(self, modem_profiles_list, monthlyreset): for mdm in modem_profiles_list: if monthlyreset: self.cp.delete(self.CFG_RULES2_PATH + '/' + mdm + '/bandwidth_egress') self.cp.delete(self.CFG_RULES2_PATH + '/' + mdm + '/bandwidth_ingress') else: if 'bandwidth_egress' in self.cp.get(self.CFG_RULES2_PATH + '/' + mdm): self.cp.delete(self.CFG_RULES2_PATH + '/' + mdm + '/bandwidth_egress') if 'bandwidth_ingress' in self.cp.get(self.CFG_RULES2_PATH + '/' + mdm): self.cp.delete(self.CFG_RULES2_PATH + '/' + mdm + '/bandwidth_ingress') self.cp.put('config/qos/enabled', False) if monthlyreset: self.cp.log( 'Monthly data usage reset - disabling reduced LTE data rate') message = ( f'Monthly data usage reset - disabling reduced LTE data rate ' f'for {self.system_id} - {self.product_name} - Router ID: ' f'{self.router_id}') self.cp.alert(message) self.capreached = 0 def set_throttle(self, modem_profiles_list): for mdm in modem_profiles_list: self.cp.put(self.CFG_RULES2_PATH + '/' + mdm + '/bandwidth_egress', self.minbwup) self.cp.put( self.CFG_RULES2_PATH + '/' + mdm + '/bandwidth_ingress', self.minbwdown) self.cp.put('config/qos/enabled', True) self.cp.log( 'Exceeded monthly data usage threshold - reducing LTE data rate') message = ( f'Exceeded monthly data usage threshold - reducing LTE data rate ' f'for {self.system_id} - {self.product_name} - Router ID: ' f'{self.router_id}') self.cp.alert(message) self.capreached = 1 def run(self): # Get info from router to populate description field in NCM # alert message self.product_name = self.cp.get('/status/product_info/product_name') self.system_id = self.cp.get('/config/system/system_id') self.router_id = self.cp.get('status/ecm/client_id') # Retrieve list of modems and their profiles modems_list = [str(x.split('-')[1]) for x in self.find_modems()] modem_profiles_list = self.find_modem_profiles() # Reset any throttling to account for router reboots. If a # data cap alert is still active during the monthly cycle, the # appropriate rate shaping will be re-applied monthlyreset = False self.reset_throttle(modem_profiles_list, monthlyreset) time.sleep(5) while True: if self.cp.get(self.STATUS_DATACAP_PATH + '/completed_alerts/'): alerts = self.cp.get(self.STATUS_DATACAP_PATH + '/completed_alerts/') limitreached = 0 for modem in modems_list: if [ x['rule_id'] for x in alerts if x['rule_id'] == modem + '-monthly' if 'email_alert' in x['alerts'] ]: limitreached += 1 if limitreached > 0 and self.capreached == 0: self.set_throttle(modem_profiles_list) elif limitreached == 0 and self.capreached == 1: monthlyreset = True self.reset_throttle(modem_profiles_list, monthlyreset) elif self.capreached == 1: monthlyreset = True self.reset_throttle(modem_profiles_list, monthlyreset) time.sleep(10)
system_id = cp.get('/config/system/system_id') mqtt_client = mqtt.Client(client_id=system_id) mqtt_client.disable_logger() # Assign callback functions mqtt_client.on_connect = on_connect mqtt_client.on_subscribe = on_subscribe mqtt_client.on_message = on_message # Connect to the MQTT broker using the server and port in the settings file. connack_code = mqtt_client.connect(settings.MQTT_SERVER, settings.MQTT_PORT) cp.log('MQTT connect reply to {}, {}: {}'.format( settings.MQTT_SERVER, settings.MQTT_PORT, mqtt.connack_string(connack_code))) # Blocking call that processes network traffic, dispatches callbacks and # handles reconnecting. mqtt_client.loop_forever() except Exception as ex: cp.log('Exception in start_mqtt()! exception: {}'.format(ex)) raise if __name__ == "__main__": try: start_mqtt() except Exception as ex: cp.log('Exception occurred!: {}'.format(ex))
class DataUsageCheck(object): """ Establish global variables. Set rate shaping values (in Kbps) for 70, 80, 90 & 100% rate tiers. e.g. minbwup_70 & minbwdown_70 refers to upload & download at 70% Each of the rate tiers have a default throttling limit set below: 70% - 6000Kbps Tx/Rx 80% - 3000Kbps Tx/Rx 90% - 1500Kbps Tx/Rx 100% - 600Kbps Tx/Rx """ minbwup_70 = 6000 minbwdown_70 = 6000 minbwup_80 = 3000 minbwdown_80 = 3000 minbwup_90 = 1500 minbwdown_90 = 1500 minbwup_100 = 600 minbwdown_100 = 600 STATUS_DEVS_PATH = '/status/wan/devices' STATUS_DATACAP_PATH = '/status/wan/datacap' CFG_RULES2_PATH = '/config/wan/rules2' def __init__(self): self.cp = EventingCSClient(app_name) def find_modems(self): while True: devs = self.cp.get(self.STATUS_DEVS_PATH) modems_list = [x for x in devs if x.startswith('mdm-')] self.cp.log(f'modems_list: {modems_list}') num_modems = len(modems_list) if not num_modems: self.cp.log('No Modems found at all yet') time.sleep(10) continue else: return modems_list def find_modem_profiles(self): wan_ifcs = self.cp.get(self.CFG_RULES2_PATH) modem_profiles_list = [ x['_id_'] for x in wan_ifcs if x['trigger_string'].startswith('type|is|mdm') ] self.cp.log(f'modem_profiles_list: {modem_profiles_list}') return modem_profiles_list def reset_throttle(self, modem_profiles_list, monthlyreset): for mdm in modem_profiles_list: if monthlyreset: self.cp.delete(self.CFG_RULES2_PATH + '/' + mdm + '/bandwidth_egress') self.cp.delete(self.CFG_RULES2_PATH + '/' + mdm + '/bandwidth_ingress') else: if 'bandwidth_egress' in self.cp.get(self.CFG_RULES2_PATH + '/' + mdm): self.cp.delete(self.CFG_RULES2_PATH + '/' + mdm + '/bandwidth_egress') if 'bandwidth_ingress' in self.cp.get(self.CFG_RULES2_PATH + '/' + mdm): self.cp.delete(self.CFG_RULES2_PATH + '/' + mdm + '/bandwidth_ingress') self.cp.put('config/qos/enabled', False) if monthlyreset: self.cp.log( 'Monthly data usage reset - disabling reduced LTE data rate') message = ( f'Monthly data usage reset - disabling reduced LTE data rate ' f'for {self.system_id} - {self.product_name} - Router ID: ' f'{self.router_id}') self.cp.alert(message) def set_throttle(self, modem_profiles_list, minbwup, minbwdown, tierset): for mdm in modem_profiles_list: self.cp.put(self.CFG_RULES2_PATH + '/' + mdm + '/bandwidth_egress', minbwup) self.cp.put( self.CFG_RULES2_PATH + '/' + mdm + '/bandwidth_ingress', minbwdown) self.cp.put('config/qos/enabled', True) self.cp.log('Exceeded monthly data usage threshold - ' + str(tierset) + '% tier - reducing LTE data rate') message = ( f'Exceeded monthly data usage threshold - reducing LTE data rate ' f'for {self.system_id} - {self.product_name} - Router ID: ' f'{self.router_id}') self.cp.alert(message) def run(self): # Get info from router to populate description field in NCM # alert message self.product_name = self.cp.get('/status/product_info/product_name') self.system_id = self.cp.get('/config/system/system_id') self.router_id = self.cp.get('status/ecm/client_id') # Retrieve list of modems and their profiles modems_list = [str(x.split('-')[1]) for x in self.find_modems()] modem_profiles_list = self.find_modem_profiles() # Reset any throttling to account for router reboots. If a # data cap alert is still active during the monthly cycle, the # appropriate rate shaping will be re-applied monthlyreset = False self.reset_throttle(modem_profiles_list, monthlyreset) time.sleep(5) currtierset = 0 while True: if self.cp.get(self.STATUS_DATACAP_PATH + '/completed_alerts/'): alerts = self.cp.get(self.STATUS_DATACAP_PATH + '/completed_alerts/') limitreached = 0 tierset = 0 for indalert in alerts: for modem in modems_list: if (indalert['alerts'] and indalert['rule_id'] == modem + '-monthly'): if 'email_alert' in indalert['alerts']: limitreached += 1 tierset = 100 minbwup = self.minbwup_100 minbwdown = self.minbwdown_100 continue elif 'early_email-90.0' in indalert['alerts']: limitreached += 1 tierset = 90 minbwup = self.minbwup_90 minbwdown = self.minbwdown_90 continue elif 'early_email-80.0' in indalert['alerts']: limitreached += 1 tierset = 80 minbwup = self.minbwup_80 minbwdown = self.minbwdown_80 continue elif 'early_email-70.0' in indalert['alerts']: limitreached += 1 tierset = 70 minbwup = self.minbwup_70 minbwdown = self.minbwdown_70 continue if limitreached > 0 and currtierset != tierset: currtierset = tierset self.set_throttle(modem_profiles_list, minbwup, minbwdown, currtierset) elif limitreached == 0 and currtierset > 0: currtierset = 0 monthlyreset = True self.reset_throttle(modem_profiles_list, monthlyreset) elif currtierset > 0: currtierset = 0 monthlyreset = True self.reset_throttle(modem_profiles_list, monthlyreset) time.sleep(10)
if line: output += line + '<br>' return output class ShellHandler(tornado.web.RequestHandler): """handle requests for the /shell endpoint.""" def get(self): """return command response.""" response = '' try: cmd = self.get_argument('cmd') response = shell(cmd) or 'No Response' except Exception as e: cp.log(e) self.write(response) if __name__ == "__main__": cp = EventingCSClient('cp_shell') cp.log(f'Starting webserver on port {server_port}...') application = tornado.web.Application([ (r"/shell", ShellHandler), (r"/(.*)", tornado.web.StaticFileHandler, { "path": static_path, "default_filename": "index.html" }), ]) application.listen(server_port) tornado.ioloop.IOLoop.current().start()
password=sas_token) mqtt_client.tls_set(ca_certs=path_to_root_cert, certfile=None, keyfile=None, cert_reqs=ssl.CERT_REQUIRED, tls_version=ssl.PROTOCOL_TLSv1, ciphers=None) mqtt_client.tls_insecure_set(False) mqtt_client.connect(iot_hub_name + '.azure-devices.net', port=8883) # Get some router data and publish to the IoT Hub device_data = dict() cp.log('device_data = {}'.format(device_data)) device_data['router_id'] = cp.get('/config/system/system_id') device_data['product_name'] = cp.get('/status/product_info/product_name') # Not all CP devices have a modem_temperature if device_data['product_name'].startswith('ibr200') is False: device_data['router_temperature'] = cp.get( '/status/system/modem_temperature') mqtt_client.publish('devices/' + device_id + '/messages/events/', urllib.parse.urlencode(device_data), qos=1) mqtt_client.loop_forever() except Exception as e:
import time from csclient import EventingCSClient cp = EventingCSClient('ports-status') APP_NAME = 'PORTS_STATUS' DEBUG = False MODELS_WITHOUT_WAN = ['CBA', 'W18', 'W200', 'W400', 'L950', 'IBR200', '4250'] if DEBUG: cp.log("DEBUG ENABLED") if DEBUG: cp.log("Getting Model") """Get model number, since some models don't have ethernet WAN""" model = '' model = cp.get('/status/product_info/product_name') if DEBUG: cp.log(model) while True: try: ports_status = "" is_available_modem = 0 is_available_wan = 0 is_available_wwan = 0 is_configured_wwan = 0 wans = cp.get('/status/wan/devices') mdm_present = False for wan in wans: if 'mdm' in wan:
""" This app will create a file and then upload it to an FTP server. The file will be deleted when the app is stopped. """ from csclient import EventingCSClient from ftplib import FTP cp = EventingCSClient('ftp_client') TEMP_FILE = 'my_file.txt' cp.log('ftp_client send_ftp_file()...') # Create a temporary file to upload to an FTP server try: f = open(TEMP_FILE, 'w') f.write('This is a test!!') f.write('This is another test!!') f.close() except OSError as msg: cp.log('Failed to open file: {}. error: {}'.format(TEMP_FILE, msg)) try: # Connect to an FTP test server ftp = FTP('speedtest.tele2.net') # Login to the server reply = ftp.login('anonymous', 'anonymous') cp.log('FTP login reply: {}'.format(reply)) # Change to the proper directory for upload ftp.cwd('/upload/')
# shell_sample - execute linux shell_sample command and return output from csclient import EventingCSClient def shell(cmd): """ executes a linux shell command and returns the output :param cmd: string command to be executed. e.g. "ls -al" :return: string output of shell command """ from subprocess import Popen, PIPE output = '' cmd = cmd.split(' ') tail = Popen(cmd, stdout=PIPE, stderr=PIPE, universal_newlines=True) for line in iter(tail.stdout.readline, ''): if tail.returncode: break if line: output += line return output cp = EventingCSClient('shell_sample') cp.log('Starting...') cp.log('Output:\n' + shell('ls -al'))