'''
Gets the '/status' from the router config store and send it
to a test server.
'''

import datetime
import urllib.request
import urllib.parse
from csclient import EventingCSClient

cp = EventingCSClient('send_to_server')


def post_to_server():
    try:
        # The tree item to get from the router config store
        tree_item = '/status/system/sdk'
        start_time = datetime.datetime.now()

        # Get the item from the router config store
        tree_data = cp.get(tree_item)
        cp.log("{}: {}".format(tree_item, tree_data))

        time_to_get = datetime.datetime.now() - start_time
        encode_start_time = datetime.datetime.now()

        # URL encode the tree_data
        params = urllib.parse.urlencode(tree_data)

        # UTF-8 encode the URL encoded data
        params = params.encode('utf-8')
"""
This application will communicate with MS Azure IoT Hub using MQTT. It was developed
based on the sample from here:
    https://github.com/MicrosoftDocs/azure-docs/blob/master/articles/iot-hub/iot-hub-mqtt-support.md

Refer to section 'Using the MQTT protocol directly'.
"""

import os
import ssl
import urllib.parse

from csclient import EventingCSClient
from paho.mqtt import client as mqtt

cp = EventingCSClient('mqtt_azure_tls')

# Path to the TLS certificates file. The certificates were copied from the certs.c file
# located here: https://github.com/Azure/azure-iot-sdk-c/blob/master/certs/certs.c
path_to_root_cert = os.path.join(os.getcwd(), 'certs.cer')

# MS Azure IoT Hub name
iot_hub_name = ''

# Device name in MS Azure IoT Hub
device_id = ''

# SAS token for the device id. This can be generated using the Device Explorer Tool.
# The format of the token should be similar to:
# 'SharedAccessSignature sr={your hub name}.azure-devices.net%2Fdevices%2FMyDevice01%2Fapi-version%3D2016-11-14&sig=vSgHBMUG.....Ntg%3d&se=1456481802'
sas_token = ''
Beispiel #3
0
from csclient import EventingCSClient
import time
import os

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__':
Beispiel #4
0
- Connects to MQTT test server ‘test.mosquitto.org’
- Subscribes to topics as defined in settings.py.
- Runs a background thread which publishes data to the topics defined in settings.py every 10 secs.
- Generates a log when the MQTT server sends the published information for topics subscribed.
"""
import os
import json
import time
import settings
import paho.mqtt.client as mqtt
import paho.mqtt.publish as publish

from threading import Thread
from csclient import EventingCSClient

cp = EventingCSClient('mqtt_app')
mqtt_client = None


# Called when the broker responds to our connection request.
def on_connect(client, userdata, flags, rc):
    cp.log('MQTT Client connection results: {}'.format(
        mqtt.connack_string(rc)))

    # Subscribing in on_connect() means that if we lose the connection and
    # reconnect then subscriptions will be renewed.
    # QOS 0: The broker will deliver the message once, with no confirmation.
    # QOS 1: The broker will deliver the message at least once, with confirmation required.
    # QOS 2: The broker will deliver the message exactly once by using a four step handshake.
    #
    # A list of tuples (i.e. topic, qos). Both topic and qos must be present in the tuple.
Beispiel #5
0
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)
                           'Authorization': f'Bearer {dispatcher.config["server_token"]}'}
            else:
                headers = {'Content-Type': 'application/json'}
            debug_log(f'HTTP POST - URL: {url}')
            debug_log(f'HTTP POST - Headers: {headers}')
            debug_log(f'HTTP POST - Payload: {payload}')
            req = requests.post(url, headers=headers, json=payload)
            cp.log(f'HTTP POST Result: {req.status_code} {req.text}')
        except Exception as e:
            logstamp = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
            logs.append(f'{logstamp} Exception in Send to Server: {e}')
            cp.log(f'Exception in Send to Server: {e}')


if __name__ == "__main__":
    cp = EventingCSClient('Mobile Site Survey')
    cp.log('Starting...')
    
    # Wait for WAN connection
    while not cp.get('status/ecm/state') == 'connected':
        time.sleep(1)
    time.sleep(3)
        
    dispatcher = Dispatcher()
    Thread(target=dispatcher.loop, daemon=True).start()
    application = tornado.web.Application([
        (r"/config", ConfigHandler),
        (r"/submit", SubmitHandler),
        (r"/test", TestHandler),
        (r"/(.*)", tornado.web.StaticFileHandler,
         {"path": os.path.dirname(__file__), "default_filename": "index.html"}),
Beispiel #7
0
        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')))
Beispiel #8
0
"""
This app will start an FTP server. This is done by using
pyftplib and also asynchat.py and asyncore.py. For detail
information about pyftplib, see https://pythonhosted.org/pyftpdlib/.
"""

import os
import sys
from csclient import EventingCSClient

from pyftpdlib.authorizers import DummyAuthorizer
from pyftpdlib.handlers import FTPHandler
from pyftpdlib.servers import FTPServer

cp = EventingCSClient('ftp_server')

# This requires a USB compatible storage device plugged into
# the router. It will mount to /var/media.
if sys.platform == 'linux2':
    FTP_DIR = 'FTP'
else:
    FTP_DIR = os.getcwd()

try:
    authorizer = DummyAuthorizer()
    # Define a new user having full r/w permissions and a read-only
    # anonymous user
    authorizer.add_user('survey', 'survey', FTP_DIR, perm='elradfmwM')
    authorizer.add_anonymous(FTP_DIR)

    # Instantiate FTP handler class
PIP example:
pip(3) install --ignore-install --target=<app directory path> <python module>
* note: use pip on Windows and pip3 on Linux or OS X
"""

import os
import sys
import pkgutil
import platform
import collections

from importlib import util
from csclient import EventingCSClient

cp = EventingCSClient('python_module_list')


def log_module_list():
    # name this file (module)
    this_module_name = os.path.basename(__file__).rsplit('.')[0]

    # dict for loaders with their modules
    loaders = collections.OrderedDict()

    # names of build-in modules
    for module_name in sys.builtin_module_names:

        # find an information about a module by name
        module_info = util.find_spec(module_name)
Beispiel #10
0
"""
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()
Beispiel #11
0
from csclient import EventingCSClient
import socket
import struct

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))
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)
Beispiel #13
0
"""
Use MQTT and subscribe to the IBR1700 OBD-II PIDs
Reference: https://www.eclipse.org/paho/clients/python/docs/

This app does the following:
- Connects to the internal MQTT Broker
- Subscribes to all OBD-II PIDs.
- Outputs logs when the PID publish messages are received.

"""
import settings
from csclient import EventingCSClient
import paho.mqtt.client as mqtt

cp = EventingCSClient('ibr1700_obdii')

mqtt_client = None

# Topics for all OBD-II PIDs with QOS
topics = [(settings.VEHICLE_SPEED, 0), (settings.ENGINE_SPEED, 0),
          (settings.THROTTLE_POSITION, 0), (settings.ODOMETER, 0),
          (settings.FUEL_LEVEL, 0), (settings.ENGINE_COOLANT_TEMPERATURE, 0),
          (settings.IGNITION_STATUS, 0), (settings.MIL_STATUS, 0),
          (settings.FUEL_RATE, 0), (settings.PTO_STATUS, 0),
          (settings.SEATBELT_FASTENED, 0), (settings.MISFIRE_MONITOR, 0),
          (settings.FUEL_SYSTEM_MONITOR, 0),
          (settings.COMPREHENSIVE_COMPONENT_MONITOR, 0),
          (settings.CATALYST_MONITOR, 0),
          (settings.HEATED_CATALYST_MONITOR, 0),
          (settings.EVAPORATIVE_SYSTEM_MONITOR, 0),
          (settings.SECONDARY_AIR_SYSTEM_MONITOR, 0),
Beispiel #14
0
# hello_world - log "Hello World!"
from csclient import EventingCSClient
cp = EventingCSClient('hello_world')
cp.log('Hello World!')
Beispiel #15
0
"""
Copyright (c) 2016 CradlePoint, Inc. <www.cradlepoint.com>.  All rights
reserved.

This file contains confidential information of CradlePoint, Inc. and your use
of this file is subject to the CradlePoint Software License Agreement
distributed with this file. Unauthorized reproduction or distribution of this
file is subject to civil and criminal penalties.
"""
import os
import sys
from csclient import EventingCSClient


def mkroutes(route, directory):
    location = "%s/%s" % (os.getcwd(), directory)
    route_map.append((route, location))


cp = EventingCSClient('hspt')

# Build route maps for / and /resources
route_map = []
sys.path.append('.')
mkroutes('/(.*)', '')
mkroutes('/resources/(.*)', 'resources/')

value = {'action': 'start', 'routes': route_map, 'server': 'hotspotServer'}
cp.put('/control/system/httpserver', value)
                    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')
Beispiel #17
0
from csclient import EventingCSClient
cp = EventingCSClient('mqtt_app')

MQTT_CLIENT_ID = cp.get('config/system/system_id')

# MQTT Server settings
MQTT_SERVER = 'test.mosquitto.org'
MQTT_PORT = 1883
MQTT_USER_NAME = 'anonymous'
MQTT_PASSWORD = '******'

# MQTT Topics
# Topics are named the same as the path to get the data from the
# NCOS device. This was done for simplicity.
GPS_TOPIC = '/status/gps/lastpos'
MODEM_TEMP_TOPIC = '/status/system/modem_temperature'
WAN_CONNECTION_STATE_TOPIC = '/status/wan/connection_state'
Beispiel #18
0
        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()
Beispiel #19
0
# tornado_sample - simple web server using tornado

from csclient import EventingCSClient
import tornado.web


class MainHandler(tornado.web.RequestHandler):
    def get(self):
        self.write("Hello Cradlepoint!")


if __name__ == "__main__":
    cp = EventingCSClient('tornado_sample')
    cp.log('Starting...')
    application = tornado.web.Application([
        (r"/", MainHandler),
    ])
    application.listen(9001)
    tornado.ioloop.IOLoop.current().start()
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:
        # 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")
Beispiel #22
0
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)
Beispiel #23
0
- Enable Global Data Usage in Connection manager
- Establish data cap alert thresholds on the appropriate cellular
  interface profile(s)
"""

app_name = 'throttle_cellular_datacap_rate_tiered'

try:
    from csclient import EventingCSClient
    import sys
    import time
    import json
    import traceback
    import logging.handlers
except Exception as ex:
    EventingCSClient().log(f'Import failure: {ex}')
    EventingCSClient().log(f'Traceback: {traceback.format_exc()}')
    sys.exit(-1)


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
Beispiel #24
0
 def __init__(self):
     self.client = EventingCSClient('Boot2')
Beispiel #25
0
 def __init__(self):
     self.cp = EventingCSClient(app_name)
# app_template_csclient - app framework using csclient.py
from csclient import EventingCSClient
cp = EventingCSClient('app_template_csclient')
cp.log('Starting...')
Beispiel #27
0
#
# Changes and improvements suggested by Steve Majewski.
# Modified by Jack to work on the mac.
# Modified by Siebren to support docstrings and PASV.
# Modified by Phil Schwartz to add storbinary and storlines callbacks.
# Modified by Giampaolo Rodola' to add TLS support.
#

from csclient import EventingCSClient
import os
import sys
import socket
import warnings
from socket import _GLOBAL_DEFAULT_TIMEOUT

cp = EventingCSClient('ftp_client')

__all__ = ["FTP"]

# Magic number from <socket.h>
MSG_OOB = 0x1                           # Process data out of band


# The standard FTP server control port
FTP_PORT = 21
# The sizehint parameter passed to readline() calls
MAXLINE = 8192


# Exception raised when an error or invalid response is received
class Error(Exception): pass
Beispiel #28
0
"""
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)
Beispiel #29
0
"""
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/')
Beispiel #30
0
# 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'))