Example #1
0
 def try_connect(username: Optional[str],
                 password: Optional[str]) -> Connection:
     """Try connecting with given credentials."""
     if username or password:
         conn = AuthorizedConnection(
             user_input[CONF_URL],
             username=username,
             password=password,
             timeout=CONNECTION_TIMEOUT,
         )
     else:
         try:
             conn = AuthorizedConnection(
                 user_input[CONF_URL],
                 username="",
                 password="",
                 timeout=CONNECTION_TIMEOUT,
             )
             user_input[CONF_USERNAME] = ""
             user_input[CONF_PASSWORD] = ""
         except ResponseErrorException:
             _LOGGER.debug(
                 "Could not login with empty credentials, proceeding unauthenticated",
                 exc_info=True,
             )
             conn = Connection(user_input[CONF_URL],
                               timeout=CONNECTION_TIMEOUT)
             del user_input[CONF_USERNAME]
             del user_input[CONF_PASSWORD]
     return conn
Example #2
0
def main():
    connection = AuthorizedConnection(f'http://{ip}/', login, password)
    with output(output_type='dict') as output_lines:
        while True:
            try:
                client = Client(connection)
                print_signal(client, output_lines)
                print_traffic(client, output_lines)
                time.sleep(1)
            except ResponseErrorLoginCsfrException:
                connection = AuthorizedConnection(f'http://{ip}/', login, password)
    client.user.logout()
Example #3
0
 def init(self):
     if self.wait_modem_ready() is False:
         return
     if self._password is None:
         self._base_url = "http://{}/".format(self._ip)
         self._connection = AuthorizedConnection(self._base_url,
                                                 login_on_demand=True)
     else:
         self._base_url = "http://{}:{}@{}/".format(self._user,
                                                    self._password,
                                                    self._ip)
         self._connection = AuthorizedConnection(self._base_url)
     self._client = Client(self._connection)
     self._infos = self._client.device.information()
     self._present = True
Example #4
0
def _setup_lte(hass, lte_config) -> None:
    """Set up Huawei LTE router."""
    url = lte_config[CONF_URL]
    username = lte_config[CONF_USERNAME]
    password = lte_config[CONF_PASSWORD]

    # Get MAC address for use in unique ids. Being able to use something
    # from the API would be nice, but all of that seems to be available only
    # through authenticated calls (e.g. device_information.SerialNumber), and
    # we want this available and the same when unauthenticated too.
    host = urlparse(url).hostname
    try:
        if ipaddress.ip_address(host).version == 6:
            mode = "ip6"
        else:
            mode = "ip"
    except ValueError:
        mode = "hostname"
    mac = get_mac_address(**{mode: host})

    connection = AuthorizedConnection(url, username=username, password=password)
    client = Client(connection)

    data = RouterData(client, mac)
    hass.data[DATA_KEY].data[url] = data

    def cleanup(event):
        """Clean up resources."""
        client.user.logout()

    hass.bus.listen_once(EVENT_HOMEASSISTANT_STOP, cleanup)
def login():
    global ip
    global user
    global password
    global connection
    global login_time
    global logged_in

    try:
        print("logging in")
        connection = AuthorizedConnection(f'http://{ip}/', user, password)
        print("setting client")
        huawei_lte_rest_api.globals.client = Client(connection)
        login_time = datetime.datetime.utcnow()
        logged_in = True

        print("logging in - success")
        print(login_time)
        return json.dumps({"status": "logged in"})

    except Exception as error:
        errorMsg = error.args
        if errorMsg[0] == "108003: Already login":
            print("already logged in")
            login_time = datetime.datetime.utcnow()
            logged_in = True
            return json.dumps({"status": "logged in"})
        else:
            print("logging in - error")
            print(errorMsg[0])
            logged_in = False
            return json.dumps({"status": errorMsg[0]})
Example #6
0
def _setup_lte(hass, lte_config) -> None:
    """Set up Huawei LTE router."""
    from huawei_lte_api.AuthorizedConnection import AuthorizedConnection
    from huawei_lte_api.Client import Client

    url = lte_config[CONF_URL]
    username = lte_config[CONF_USERNAME]
    password = lte_config[CONF_PASSWORD]

    connection = AuthorizedConnection(
        url,
        username=username,
        password=password,
    )
    client = Client(connection)

    data = RouterData(client)
    data.update()
    hass.data[DATA_KEY].data[url] = data

    def cleanup(event):
        """Clean up resources."""
        client.user.logout()

    hass.bus.listen_once(EVENT_HOMEASSISTANT_STOP, cleanup)
def update_gsm():
	global _gsm_band
	global _gsm_mode
	global _gsm_rssi
	global _gsm_rsrq
	global _gsm_rsrp
	global _gsm_signal
	global client
	global connection
	global _gsm_reading_status

	try:
		signal = client.device.signal()
		info = client.device.information()
		status = client.monitoring.status()
		_gsm_mode = info['workmode']
		_gsm_band = int(signal['band'])
		_gsm_rssi = int(signal['rssi'].split('dBm')[0])
		_gsm_rsrq = int(signal['rsrq'].split('dB')[0])
		_gsm_rsrp = int(signal['rsrp'].split('dBm')[0])
		_gsm_signal = int(status['SignalIcon'])
		_gsm_reading_status = 'OK'
	except:
		print(traceback.format_exc())
		_gsm_reading_status = 'KO'
		connection = AuthorizedConnection(router_url)
		client = Client(connection)
Example #8
0
    def make_client(self):
        MODEM_CREDS_USERNAME = "******"
        MODEM_LOCAL_IP = "192.168.8.2"

        # establish a connection
        connection = AuthorizedConnection('http://{}:{}@{}/'.format(
            MODEM_CREDS_USERNAME, self._password, MODEM_LOCAL_IP))
        # init the client
        return Client(connection)
Example #9
0
    def get(self, request, *args, **kwargs):

        # Connection
        connection = AuthorizedConnection(settings.HUAWEI_LTE_API_URL)

        sms_provider = Sms(connection)

        data, status_code = get_sms_list(sms_provider, box_type="DRAFTBOX")

        return Response(data, status=status_code)
Example #10
0
def main():
    banner()
    currentDT = datetime.datetime.now()
    number_logins = int(input("Number of login attempts: "))
    for x in range(0, number_logins):
        connection = AuthorizedConnection(
            'http://*****:*****@192.168.8.1/')
        client = Client(connection)
        print("Login number " + str(x + 1) + " at: " +
              currentDT.strftime("%I:%M:%S %p"))
Example #11
0
 def try_connect(user_input: dict[str, Any]) -> AuthorizedConnection:
     """Try connecting with given credentials."""
     username = user_input.get(CONF_USERNAME) or ""
     password = user_input.get(CONF_PASSWORD) or ""
     conn = AuthorizedConnection(
         user_input[CONF_URL],
         username=username,
         password=password,
         timeout=CONNECTION_TIMEOUT,
     )
     return conn
Example #12
0
def listen():
    jeedom_socket.open()
    logging.debug("Start listening...")

    try:
        while 1:
            time.sleep(_cycle)

            try:
                connection = AuthorizedConnection(_device_url)
                client = Client(connection)
            except Exception as e:
                logging.error('Fail to connect on the device : ' + str(e))
                continue

            try:
                signal = client.monitoring.status()
                jeedom_com.send_change_immediate({
                    'cmd':
                    'signal',
                    'message':
                    signal['SignalIcon']
                })
            except Exception as e:
                logging.error('Fail to check signal : ' + str(e))

            try:
                data = client.net.current_plmn()
                jeedom_com.send_change_immediate({
                    'cmd': 'operatorName',
                    'message': data['FullName']
                })
            except Exception as e:
                logging.error('Fail to check current plmn : ' + str(e))

            try:
                read_socket(client)
            except Exception as e:
                logging.error('Exception on socket : ' + str(e))

            try:
                checkUnreadMessages(client)
            except Exception as e:
                logging.error('Fail to check unread sms : ' + str(e))

            try:
                client.user.logout()
            except ResponseErrorNotSupportedException as e:
                pass
            except Exception as e:
                logging.error('Fail to logout : ' + str(e))
    except KeyboardInterrupt:
        shutdown()
Example #13
0
 def get_connection() -> Connection:
     """Set up a connection."""
     if entry.options.get(CONF_UNAUTHENTICATED_MODE):
         _LOGGER.debug("Connecting in unauthenticated mode, reduced feature set")
         connection = Connection(url, timeout=CONNECTION_TIMEOUT)
     else:
         _LOGGER.debug("Connecting in authenticated mode, full feature set")
         username = entry.data.get(CONF_USERNAME) or ""
         password = entry.data.get(CONF_PASSWORD) or ""
         connection = AuthorizedConnection(
             url, username=username, password=password, timeout=CONNECTION_TIMEOUT
         )
     return connection
Example #14
0
    def __init__(self, stick_addi):
        self.run_trigger = False
        self.client = None
        self.rsrq = -999
        self.sinr = -999
        self.rsrp = -999
        try:
            self.client = Client(AuthorizedConnection(stick_addi))
            self.run_trigger = True
        except Exception as e:
            print("Connection2Modem Error ...")
            raise e

        self.net_mode = self.get_net_mode()
Example #15
0
    def get_connection() -> Connection:
        """
        Set up a connection.

        Authorized one if username/pass specified (even if empty), unauthorized one otherwise.
        """
        username = config_entry.data.get(CONF_USERNAME)
        password = config_entry.data.get(CONF_PASSWORD)
        if username or password:
            connection: Connection = AuthorizedConnection(
                url, username=username, password=password, timeout=CONNECTION_TIMEOUT
            )
        else:
            connection = Connection(url, timeout=CONNECTION_TIMEOUT)
        return connection
Example #16
0
def main():
    banner()
    ### Command line -helper for args
    import argparse
    parser = argparse.ArgumentParser(description="Huawei B315s-22 4G router information gathering tool")
    parser.add_argument("-i", "--ip", type=str, help="IP address of the router", metavar=("IP Router"))
    parser.add_argument("-n", "--nologin", action='store_true', help="Use this if you don't have any credentials")
    parser.add_argument("-u", "--username", type=str, default="admin", help="Username used to login to the router, default=admin")
    parser.add_argument("-p", "--password", type=str, default="admin", help="Password used to login to the router, default=admin")
    parser.add_argument("-w", "--write", type=str, help="Filename", metavar=("FILENAME"))
    args = parser.parse_args()

    #Check if atleast the ip address is given
    if args.ip == None:
        parser.print_usage()
    elif valid_ip(args.ip) == False:
        sys.exit("Enter a valid IP address")

    if args.nologin == True:
        try:
            connection = Connection('http://192.168.8.1/')
            client = Client(connection)
            data = getAllInfoWithoutLogin(client)
            if args.write:
                print("Data has been written into : " + args.write + "\n")
                writeToFile(args.write, data)
            else:
                print(data)
        except Exception as e:
            print(e)
    
    if args.username == True and args.password == True:
        try:
            connection = AuthorizedConnection('http://'+args.username+':'+args.password+'@'+args.ip+'/')
            client = Client(connection)
            data = getAllInfoLogin(client)
            if args.write:
                print("Data has been written into : " + args.write + "\n")
                writeToFile(args.write, data)
            else:
                print(data)
        except Exception as e:
            print(e)
Example #17
0
    def post(self, request, *args, **kwargs):

        ser_data = request.data

        serializer = SMSSerializer(data=ser_data)

        if serializer.is_valid(raise_exception=True):

            # Connection
            connection = AuthorizedConnection(settings.HUAWEI_LTE_API_URL)

            # sms api
            sms_provider = Sms(connection)

            data = serializer.data

            # get data
            phone_number_list = [
                "+" + str(data["phone"]),
            ]

            sms_content = data["content"]

            # Send sms
            Status = sms_provider.send_sms(phone_number_list, sms_content)

            # create response
            # TODO: check delevry rapport or check draft if not sent
            DRAFTBOX_data, status_code = get_sms_list(sms_provider,
                                                      box_type="DRAFTBOX")

            data = {'results': True, 'Status': Status}
            status_code = HTTP_200_OK

        else:
            data = {'results': False}
            status_code = HTTP_400_BAD_REQUEST

        return Response(data, status=status_code)
Example #18
0
 def testAPI(self):
     connection = AuthorizedConnection('http://*****:*****@' + G_ROUTER_IP + '/')
     client = Client(connection)
     print(client.device.information())
# load environment variable from .env file
HUAWEI_ROUTER_IP_ADDRESS = os.getenv("HUAWEI_ROUTER_IP_ADDRESS")
HUAWEI_ROUTER_ACCOUNT = os.getenv("HUAWEI_ROUTER_ACCOUNT")
HUAWEI_ROUTER_PASSWORD = os.getenv("HUAWEI_ROUTER_PASSWORD")
GMAIL_ACCOUNT = os.getenv("GMAIL_ACCOUNT")
GMAIL_PASSWORD = os.getenv("GMAIL_PASSWORD")
MAIL_RECIPIENT = os.getenv("MAIL_RECIPIENT").split(",")
DELAY_SECOND = int(os.getenv("DELAY_SECOND"))

# Use infinite loop to check SMS
while True:
    try:
        # Establish a connection with authorized
        connection = AuthorizedConnection('http://{}:{}@{}/'.format(
            HUAWEI_ROUTER_ACCOUNT, HUAWEI_ROUTER_PASSWORD,
            HUAWEI_ROUTER_IP_ADDRESS))
        client = Client(connection)
        # Set account phone number to pass on to the sms email
        ACCOUNT_PHONE_NUMBER = client.device.information()['Msisdn']
        # print(ACCOUNT_PHONE_NUMBER)
        # get first SMS(unread priority)
        sms = client.sms.get_sms_list(1, BoxTypeEnum.LOCAL_INBOX, 1, 0, 0, 1)
        # Skip this loop if the SMS was read
        if int(sms['Messages']['Message']['Smstat']) == 1:
            # Logout
            client.user.logout()
            # Inspection interval(second)
            time.sleep(DELAY_SECOND)
            continue
Example #20
0
# Huawei LTE modem api
#
# export ADMIN_PASSWORD=""
#

import os

from huawei_lte_api.Client import Client
from huawei_lte_api.AuthorizedConnection import AuthorizedConnection
from huawei_lte_api.Connection import Connection
from huawei_lte_api.Connection import GetResponseType, SetResponseType

ADMIN_PASSWORD = os.environ.get("ADMIN_PASSWORD")

connection = AuthorizedConnection('http://*****:*****@192.168.8.1/',
                                  username='******',
                                  password=ADMIN_PASSWORD)

client = Client(
    connection
)  # This just simplifies access to separate API groups, you can use device = Device(connection) if you want

# print(client.device.signal())  # Can be accessed without authorization
# print(client.device.information())  # Needs valid authorization, will throw exception if invalid credentials are passed in URL


def switchOnLTE():
    # dataswitch: 0 to disable LTE modem, 1 to enable LTE modem
    dataswitch = 1
    client.dial_up.set_mobile_dataswitch(dataswitch)
Example #21
0
 def __enter__(self):
     connection = AuthorizedConnection('http://{}:{}@{}/'.format(
         self.username, self.password, self.ip))
     self.client = Client(connection)
     return self.client
Example #22
0
    def theLoop(self):
        # Setup logging if not done already
        if not self.LoggingSetupDone:
            if not self.setup_logging():
                print("Unable to setup logging")
            # Set logger verbosity level
            if verboseLevel >= 3:
                log_level = logging.DEBUG
                setDebugging(True)
            elif verboseLevel == 2:
                log_level = logging.INFO
            elif verboseLevel == 1:
                log_level = logging.WARN
            else:
                log_level = logging.ERROR
            app.logger.setLevel(log_level)
            self.LoggingSetupDone = True

        # Stop loop if we got the signal to quit
        if self.stop:
            reactor.stop()
            return False

        self.logger.info("")
        self.logger.info("#####################################################")
        self.logger.info("")


        ########################################################################################################################################################################

        # Create an Graphite Event and exit
        if (app.locationTag):
            self.stop = True
            try:
                if self.create_graphite_event("Location changed", [ self.config['eventTag_LocationChanged'] ], 'Location: {}'.format(self.locationTag)):
                    self.logger.info("Successfully created the event.")
                else:
                    self.logger.error("Failed to create the event.")
                    return False
            except Exception as e:
                self.logger.error("Failed to create the event. Exception: {}".format(str(e)))
                return False
            return True

        ########################################################################################################################################################################

        # Reboot the Huawei LTE/5G modem and exit
        if (app.reboot):
            self.stop = True
            try:
                self.logger.info("# Connecting...")
                self.connection = AuthorizedConnection('http://{}:{}@{}/'.format(self.config['router_username'], self.config['router_password'], self.config['router_hostname'])) # Login required even for signal data
                client = Client(self.connection)
                self.logger.info("Done.")

                self.logger.warning("# Rebooting...")
                self.logger.info(client.device.reboot())
                self.logger.warning("# Done.")
            except Exception as e:
                self.logger.error("Unable to reboot the device. Exception: {}".format(str(e)))
                return False
            return True

        ########################################################################################################################################################################
        # Initialize Graphyte (for sending data)

        # Get current time
        ts = time.time()

        if (self.sendData2Graphite):
            try:
                # Init #       hostname,   port,    prefix, timeout, interval
                graphyte.init(self.config['graphite_hostname'], self.config['graphite_port']) # Skip prefix, timeout and interval (no data?)
            except Exception as e:
                self.logger.error("Unable to initialize Graphyte (for sending metrics to Graphite). Exception: {}".format(str(e)))

        ########################################################################################################################################################################
        # Create & send test data to Graphite and exit
        if self.sendTestData:
            for signalDataKey in self.config['signalDataKeys']:
                try:
                    if (self.testData[signalDataKey + '_value'] < self.testData[signalDataKey + '_max']):
                        self.testData[signalDataKey + '_value'] += 1
                    else:
                        self.testData[signalDataKey + '_value'] = self.testData[signalDataKey + '_min']
                except Exception as e:
                    self.logger.error("Exception: {}".format(str(e)))

            for metric, value in sorted(self.testData.items()):
                
                # Replace dots with underscores
                safe_metric = metric.replace('.', '_')
            
                # Build the metric path from general prefix, 'test' and key name (metric)
                metric_path = self.config['graphite_prefix'] + ".test." + safe_metric

                # Only act on _values, skip originals
                if bool(re.match('.*_value$', metric)):
                        if bool(re.match('.*lfreq.*', metric)):
                            value = value * 1000

                        if (self.sendData2Graphite):
                            sendDataText = "Sending *test* data"
                        else:
                            sendDataText = "Simulating (not sending) *test* data"

                        self.logger.info("%s for '%s'. ts=%d => %s" % (sendDataText, metric_path, ts, datetime.datetime.fromtimestamp(ts).strftime('%Y-%m-%d %H:%M:%S')))
                        self.logger.debug("Value: '{}'".format(value))

                        if (self.sendData2Graphite):
                            try:
                                # send data - metric_path,    value, [timestamp, tags (dict)]
                                graphyte.send(metric_path, value, ts)
                            except Exception as e:
                                self.logger.error("Unable to send the test data to Graphite. Exception: {}".format(str(e)))
                                return False
                else:
                    # Skipping original values, as these can't be saved as strings.
                    pass
            self.logger.warning("Success. Loop done. Waiting max. {} seconds for the next run.".format(self.config['loopInterval']))
            return True

        ################################################################################
        # Get real data and send it to Graphite

        # Check if logged in or login timed out...
        try:
            if self.connection.logged_in == False or self.connection._is_login_timeout() == True:
                self.logger.info("Not already logged in OR login has timed out. We need to (re)connect.")
                raise Exception('not_logged_in')

            self.logger.debug("#self.connection.logged_in: {}".format(self.connection.logged_in))
            self.logger.debug("#self.connection._is_login_timeout(): {}".format(self.connection._is_login_timeout()))
        # ... if not, (re)connect
        except:
            try:
                self.logger.info("# Connecting...")
                self.connection = AuthorizedConnection('http://{}:{}@{}/'.format(self.config['router_username'], self.config['router_password'], self.config['router_hostname'])) # Login required even for signal data
                self.logger.info("# Done.")
            except Exception as e:
                self.logger.warning("Failed on 1st try to connect OR we got the already logged in exception.")
                self.logger.warning("Exception: {}".format(str(e)))
        # Try to get data from the API...
        try:
            client = Client(self.connection)
            APIsignalData = client.device.signal()
        except Exception as e1:
            # ... If that failed,reconnecting first and then try again.
            try:
                self.logger.info("# Connecting...")
                self.connection = AuthorizedConnection('http://{}:{}@{}/'.format(self.config['router_username'], self.config['router_password'], self.config['router_hostname'])) # Login required even for signal data
                self.logger.info("# Done.")

                client = Client(self.connection)
                APIsignalData = client.device.signal()
            except Exception as e2:
                self.logger.warning("Failed on 2nd try to connect OR we got the already logged in exception.")
                self.logger.warning("Exception (e1): {}".format(str(e1)))
                self.logger.warning("Exception (e2): {}".format(str(e2)))
                return False

        # Get values for the signalDataKeys (variables) from the returned API data, convert the string values to floats (returns None aka. null if it fails), ...
        # ... strip specific extra characters (check self.signalData_strip_regexp) and save the original value as well.
        signalData2Graphite = dict()
        for signalDataKey in self.config['signalDataKeys']:
            try:
                signalData2Graphite[signalDataKey + '_original'] = APIsignalData[signalDataKey]
                signalData2Graphite[signalDataKey + '_value'] = floatOrNull(re.sub(r"{}".format(self.signalData_strip_regexp), "", APIsignalData[signalDataKey]))
            except:
                pass

        # Get current time
        ts = time.time()

        # Check if Cell ID changed
        cell_id_changed = False
        try:
            if (self.saveData['latest_cell_id']):
                pass
            else:
                cell_id_changed = True
        except:
            self.saveData['latest_cell_id'] = ''
            cell_id_changed = True
        try:
            if (APIsignalData['cell_id'] != self.saveData['latest_cell_id']):
                self.logger.info("*** CELL ID changed.")
                cell_id_changed = True
        except:
            pass

        # Create Cell ID changed Graphite Event
        failed_to_send_cell_id_changed = False
        if (cell_id_changed):
            if (self.sendData2Graphite):
                sendDataText = "Creating an Event"
            else:
                sendDataText = "Simulating an Event creation"

            self.logger.info("%s ('%s'). ts=%d => %s" % (sendDataText, self.config['eventTag_CellIDchanged'], ts, datetime.datetime.fromtimestamp(ts).strftime('%Y-%m-%d %H:%M:%S')))
            self.logger.debug("Cell ID: {}/{} (Old/New)".format(self.saveData['latest_cell_id'], APIsignalData['cell_id']))

            if (self.sendData2Graphite):
                try:
                    if self.create_graphite_event("Cell ID changed", [self.config['eventTag_CellIDchanged'], "cell_id_{}".format(APIsignalData['cell_id'])], 'Cell ID: {}/{} (Old/New)'.format(self.saveData['latest_cell_id'], APIsignalData['cell_id'])):
                        self.logger.warning("Successfully created the event.")

                        # Save the Cell ID change to a variable and the JSON file
                        self.saveData['latest_cell_id'] = APIsignalData['cell_id']
                        self.saveJSONfile(self.saveDataFilePath, self.saveData)
                    else:
                        self.logger.error("Failed to create the event in Graphite. Unknown error.")
                        failed_to_send_cell_id_changed = True
                except Exception as e:
                    self.logger.error("Failed to create the event in Graphite. Exception: {}".format(str(e)))
                    failed_to_send_cell_id_changed = True

        # Go through all the values and send them to Graphite
        for extra_prefix in {"all", 'by_cell_id.' + APIsignalData['cell_id']}: # Send the data with the extra prefixes 'all' and by the Cell ID (double data stored, but you can later on filter the data per Cell ID as well)
            for metric, value in sorted(signalData2Graphite.items()):
                
                # Replace dots with underscores
                safe_metric = metric.replace('.', '_')
            
                # Build the metric path from general prefix, extra prefix and key name (metric)
                metric_path = self.config['graphite_prefix'] + "." + extra_prefix + "." + safe_metric

                # Only act on _values, skip originals
                if bool(re.match('.*_value$', metric)):
                        haveOriginalValue = True
                        try:
                            # Get original value
                            original_value_key = re.sub(r"_value", "_original", metric)
                            original_value = signalData2Graphite[original_value_key]
                        except Exception as e:
                            haveOriginalValue = False
                            self.logger.warning("Unable to get the original value. Exception: {}".format(str(e)))


                        if self.sendData2Graphite:
                            sendDataText = "Sending data"
                        else:
                            sendDataText = "Simulating (not sending) data"

                        self.logger.info("%s for '%s'. ts=%d => %s" % (sendDataText, metric_path, ts, datetime.datetime.fromtimestamp(ts).strftime('%Y-%m-%d %H:%M:%S')))

                        if haveOriginalValue:
                            self.logger.debug("Value: '{}' (Original_value: '{}')".format(value, original_value))
                        else:
                            self.logger.debug("Value: '{}'".format(value))

                        if self.sendData2Graphite:
                            try:
                                # send data - metric_path,    value, [timestamp, tags (dict)]
                                graphyte.send(metric_path, value, ts)
                            except Exception as e:
                                self.logger.error("Unable to send the data to Graphite. Exception: {}".format(str(e)))
                                return False
                else:
                    # Skipping original values, as these can't be saved as strings.
                    pass
        


        # Save latest cell ID only if we successfully sent the data to Graphite
        if (self.sendData2Graphite and not failed_to_send_cell_id_changed):
            self.saveData['latest_cell_id'] = APIsignalData['cell_id']
            self.saveJSONfile(self.saveDataFilePath, self.saveData)
        self.logger.warning("Success. Loop done. Waiting max. {} seconds for the next run.".format(self.config['loopInterval']))
        return True
Example #23
0
class App:

    def __init__(self):
        self.daemonize = False
        self.reboot = False
        self.locationTag = False
        self.stop = False
        self.sendData2Graphite = False
        self.level = logging.INFO
        self.LoggingSetupDone = False
        self.enableLoop = False
        self.sendTestData = False

        self.connection = False

        self.testData = dict()
        self.testData['nrrsrp_value'] = -100
        self.testData['nrrsrp_min'] = -100
        self.testData['nrrsrp_max'] = -76
        
        self.testData['nrrsrq_value'] = -30
        self.testData['nrrsrq_min'] = -30
        self.testData['nrrsrq_max'] = -0
        
        self.testData['nrsinr_value'] = -5
        self.testData['nrsinr_min'] = -5
        self.testData['nrsinr_max'] = 35
        
        self.testData['rsrp_value'] = -100
        self.testData['rsrp_min'] = -100
        self.testData['rsrp_max'] = -76
        
        self.testData['rsrq_value'] = -30
        self.testData['rsrq_min'] = -30
        self.testData['rsrq_max'] = -0
        
        self.testData['sinr_value'] = -5
        self.testData['sinr_min'] = -5
        self.testData['sinr_max'] = 35
        
        self.testData['rssi_value'] = -94
        self.testData['rssi_min'] = -94
        self.testData['rssi_max'] = -65
        
        self.testData['ltedlfreq_value'] = 1500 # Multiplied by 1000
        self.testData['ltedlfreq_min'] = 1500 # Multiplied by 1000
        self.testData['ltedlfreq_max'] = 2000 # Multiplied by 1000
        
        self.testData['lteulfreq_value'] = 1500 # Multiplied by 1000
        self.testData['lteulfreq_min'] = 1500 # Multiplied by 1000
        self.testData['lteulfreq_max'] = 2000 # Multiplied by 1000
        
        self.testData['dlfrequency_value'] = 10 # Multiplied by 1000
        self.testData['dlfrequency_min'] = 10 # Multiplied by 1000
        self.testData['dlfrequency_max'] = 60 # Multiplied by 1000
        
        self.testData['ulfrequency_value'] = 10 # Multiplied by 1000
        self.testData['ulfrequency_min'] = 10 # Multiplied by 1000
        self.testData['ulfrequency_max'] = 60 # Multiplied by 1000
        
        # Explains below regexp ###               =|<|>| dB(m)  | (k)Hz  
        self.signalData_strip_regexp = "(=|<|>|(dB(m)?)|((k)?Hz))" # These characters and unit of measurements will be stripped from the signal data values

        self.config = dict()
        
        # Default values for the default config file that will be written if it doesn't exist already.
        self.default_config = {
            "router_hostname": "192.168.8.1",
            "router_username": "******",
            "router_password": "******",
            "graphite_hostname": "localhost",
            "graphite_port": 2003,
            "graphite_prefix": "huawei2graphite",
            "graphite_protocol": "http",
            "graphite_http_port": 8080,
            "graphite_url_hostname": "localhost",
            "logfile": "/tmp/huawei2graphite.log",
            "loopInterval": 30.0,
            "eventTag_LocationChanged": "huawei2graphite_location_changed",
            "eventTag_CellIDchanged": "huawei2graphite_cell_id_changed",
            # These data keys will be collected from the Huawei LTE/5G modem, converted to float and their values sent to Graphite
            # 5G (non-standalone aka. with 4G as a anchor): ["rsrp", "rsrq", "rssi", "sinr", "lteulfreq", "ltedlfreq", "ulfrequency", "dlfrequency", "nrrsrp", "nrrsrq", "nrsinr"]
            "signalDataKeys": ["rsrp", "rsrq", "rssi", "sinr", "lteulfreq", "ltedlfreq", "ulfrequency", "dlfrequency", "nrrsrp", "nrrsrq", "nrsinr"],

        }

        # Set config and cache locations
        self.homeFolder = str(Path.home())
        self.dataFolder = self.homeFolder + '/.config/huawei2graphite/'
        self.configFileName = "config.json"
        self.configFilePath = self.dataFolder + self.configFileName
        self.cacheFolder = self.homeFolder + '/.cache/huawei2graphite/'
        self.saveDataFileName = "data.json"
        self.saveDataFilePath = self.cacheFolder + self.saveDataFileName

    # Create folder if it doesn't exist
    def createFolder(self, folder):
        if not os.path.exists(folder):
            try:
                os.makedirs(folder)
                return True
            except Exception as e:
                print("ERROR: Unable to create the '{}' directory. Exception: {}".format(folder, str(e)))
                sys.exit(15)
        return True

    # Save dict as JSON file
    def saveJSONfile(self, filename, data):
        try:
            with open(filename, 'w',) as saveFile:
                json.dump(data, saveFile, sort_keys = True, indent = 4, ensure_ascii = False)
                saveFile.close()
            return True
        except Exception as e:
            print("WARNING: Unable to write the '{}' JSON file. Exception: {}".format(filename, str(e)))
        return False

    # Load JSON data from file and return it, on failure return empty dict()
    def loadJSONfile(self, filename):
        try:
            if os.path.exists(filename):
                with open(filename, 'r',) as loadFile:
                    return json.load(loadFile)
        except Exception as e:
            print("WARNING: Unable to read the '{}' JSON file. Exception: {}".format(filename, str(e)))
        return dict()

    # Setup logger (and log to file)
    def setup_logging(self):
        os.umask(0o22)
        self.logger = logging.getLogger()

        self.logger.setLevel(self.level)
        formatter = logging.Formatter('%(asctime)s [%(process)d] %(levelname)s: %(message)s','%Y-%m-%d %H:%M:%S')
        try:
            loghandler = logging.handlers.WatchedFileHandler(self.config['logfile'])
        except IOError:
            print("Could not open logfile ({0})".format(self.config['logfile']))
            return False

        loghandler.setFormatter(formatter)
        self.logger.addHandler(loghandler)

        if self.daemonize:
           # Redirect stdout and stderr to logger, using StreamToLogger object that handles writes
            sys.stdout = StreamToLogger(self.logger, logging.INFO)
            sys.stderr = StreamToLogger(self.logger, logging.ERROR)

        else:
            # Set up a second loghandler, that writes to stderr
            loghandler2 = logging.StreamHandler(sys.stderr)
            loghandler2.setFormatter(formatter)
            self.logger.addHandler(loghandler2)

        return True

    def usage(self):
        print("Usage: {} [-h] [-l|-r|-d|-t|-o] [] [-i secs] [-v[v]...]".format(os.path.realpath(__file__)))
        print("-h = help/usage")
        print("-l = enable loop")
        print("-r = reboot device")
        print("-d = daemonize")
        print("-t = Generate test data instead with a 'test' path. Increment values on every loop run, but keep them between min/max values.")
        print('-o "Location Text" = add an Event with the text value to Graphite.')
        print("-s = enable sending data to Graphite (by default this program just prints the value).")
        print("-i X = set the loop interval to X seconds (default is 30.0). keep in mind that it will be ran every X seconds always, regardless of the last running time.")
        print("-v = more verbose (add to get more verbose)")
        sys.exit(2)

    def main(self):

        # Create data/cache folders if they don't exist
        self.createFolder(self.dataFolder)
        self.createFolder(self.cacheFolder)

        # Load config and earlier saved data
        self.config = self.loadJSONfile(self.configFilePath)
        self.saveData = self.loadJSONfile(self.saveDataFilePath)
        

        # Check that config data exists
        try:
            if not (self.config):
                if os.path.exists(self.configFilePath):
                    print("ERROR: the '{}' config file exists, but it is empty or corrupt. Exiting.".format(self.configFilePath))
                    sys.exit(14)
                else:
                    print("ERROR: the '{}' config file does not exist, creating new config file with default values. You need to modify at least the router password.".format(self.configFilePath))
                    self.saveJSONfile(self.configFilePath, self.default_config)
                    sys.exit(13)
        except Exception as e:
                print("ERROR: Failed to check the presence of the 'self.config' dict(). Exception: {}".format(str(e)))
                sys.exit(14)

        # Check that the default password has been changed
        try:
            if (self.config['router_password'] == self.default_config['router_password']):
                print("ERROR: the '{}' config file still has the default router password. Please change it first.".format(self.configFilePath))
                sys.exit(15)
        except Exception as e:
            print("ERROR: Failed to check if the default password has been changed. 'self.config[router_password]' & 'self.default_config[router_password]' dict(). Exception: {}".format(str(e)))
            sys.exit(16)

        # Generate the Graphite URL
        try:
            self.graphite_url = self.config['graphite_protocol'] + '://' + self.config['graphite_url_hostname'] + ':' + str(self.config['graphite_http_port'])
        except Exception as e:
            print("ERROR: Failed to combine the config variables 'graphite_protocol', 'graphite_url_hostname' & 'graphite_http_port' to 'self.graphite_url'. Exception: {}".format(str(e)))
            sys.exit(17)

        # Start loop (or run loop only once).
        if app.daemonize or app.enableLoop:
            theLoopTask = task.LoopingCall(self.theLoop)
            theLoopTask.start(self.config['loopInterval'])
            reactor.run()
        else:
            self.theLoop()

    # Create events at Graphite to mark changes in the timeline
    def create_graphite_event(self, event_description, tags, event_data):
        tags_string = " ".join(str(x) for x in tags)  # Converting dictionary to comma-separated string, as we have an array but Graphite expects multiple tags comma-separated like "a,b,c" or "a b c" (space-separated)
        event = {"what": event_description, "tags": tags_string, "data": event_data}
        try:
            requests.post(self.graphite_url +"/events/", data=json.dumps(event), timeout=1)
        except Exception as e:
            self.logger.error('Error while creating an Graphite Event. Exception: {}'.format(str(e)))
            return False
        return True

    # The main loop
    def theLoop(self):
        # Setup logging if not done already
        if not self.LoggingSetupDone:
            if not self.setup_logging():
                print("Unable to setup logging")
            # Set logger verbosity level
            if verboseLevel >= 3:
                log_level = logging.DEBUG
                setDebugging(True)
            elif verboseLevel == 2:
                log_level = logging.INFO
            elif verboseLevel == 1:
                log_level = logging.WARN
            else:
                log_level = logging.ERROR
            app.logger.setLevel(log_level)
            self.LoggingSetupDone = True

        # Stop loop if we got the signal to quit
        if self.stop:
            reactor.stop()
            return False

        self.logger.info("")
        self.logger.info("#####################################################")
        self.logger.info("")


        ########################################################################################################################################################################

        # Create an Graphite Event and exit
        if (app.locationTag):
            self.stop = True
            try:
                if self.create_graphite_event("Location changed", [ self.config['eventTag_LocationChanged'] ], 'Location: {}'.format(self.locationTag)):
                    self.logger.info("Successfully created the event.")
                else:
                    self.logger.error("Failed to create the event.")
                    return False
            except Exception as e:
                self.logger.error("Failed to create the event. Exception: {}".format(str(e)))
                return False
            return True

        ########################################################################################################################################################################

        # Reboot the Huawei LTE/5G modem and exit
        if (app.reboot):
            self.stop = True
            try:
                self.logger.info("# Connecting...")
                self.connection = AuthorizedConnection('http://{}:{}@{}/'.format(self.config['router_username'], self.config['router_password'], self.config['router_hostname'])) # Login required even for signal data
                client = Client(self.connection)
                self.logger.info("Done.")

                self.logger.warning("# Rebooting...")
                self.logger.info(client.device.reboot())
                self.logger.warning("# Done.")
            except Exception as e:
                self.logger.error("Unable to reboot the device. Exception: {}".format(str(e)))
                return False
            return True

        ########################################################################################################################################################################
        # Initialize Graphyte (for sending data)

        # Get current time
        ts = time.time()

        if (self.sendData2Graphite):
            try:
                # Init #       hostname,   port,    prefix, timeout, interval
                graphyte.init(self.config['graphite_hostname'], self.config['graphite_port']) # Skip prefix, timeout and interval (no data?)
            except Exception as e:
                self.logger.error("Unable to initialize Graphyte (for sending metrics to Graphite). Exception: {}".format(str(e)))

        ########################################################################################################################################################################
        # Create & send test data to Graphite and exit
        if self.sendTestData:
            for signalDataKey in self.config['signalDataKeys']:
                try:
                    if (self.testData[signalDataKey + '_value'] < self.testData[signalDataKey + '_max']):
                        self.testData[signalDataKey + '_value'] += 1
                    else:
                        self.testData[signalDataKey + '_value'] = self.testData[signalDataKey + '_min']
                except Exception as e:
                    self.logger.error("Exception: {}".format(str(e)))

            for metric, value in sorted(self.testData.items()):
                
                # Replace dots with underscores
                safe_metric = metric.replace('.', '_')
            
                # Build the metric path from general prefix, 'test' and key name (metric)
                metric_path = self.config['graphite_prefix'] + ".test." + safe_metric

                # Only act on _values, skip originals
                if bool(re.match('.*_value$', metric)):
                        if bool(re.match('.*lfreq.*', metric)):
                            value = value * 1000

                        if (self.sendData2Graphite):
                            sendDataText = "Sending *test* data"
                        else:
                            sendDataText = "Simulating (not sending) *test* data"

                        self.logger.info("%s for '%s'. ts=%d => %s" % (sendDataText, metric_path, ts, datetime.datetime.fromtimestamp(ts).strftime('%Y-%m-%d %H:%M:%S')))
                        self.logger.debug("Value: '{}'".format(value))

                        if (self.sendData2Graphite):
                            try:
                                # send data - metric_path,    value, [timestamp, tags (dict)]
                                graphyte.send(metric_path, value, ts)
                            except Exception as e:
                                self.logger.error("Unable to send the test data to Graphite. Exception: {}".format(str(e)))
                                return False
                else:
                    # Skipping original values, as these can't be saved as strings.
                    pass
            self.logger.warning("Success. Loop done. Waiting max. {} seconds for the next run.".format(self.config['loopInterval']))
            return True

        ################################################################################
        # Get real data and send it to Graphite

        # Check if logged in or login timed out...
        try:
            if self.connection.logged_in == False or self.connection._is_login_timeout() == True:
                self.logger.info("Not already logged in OR login has timed out. We need to (re)connect.")
                raise Exception('not_logged_in')

            self.logger.debug("#self.connection.logged_in: {}".format(self.connection.logged_in))
            self.logger.debug("#self.connection._is_login_timeout(): {}".format(self.connection._is_login_timeout()))
        # ... if not, (re)connect
        except:
            try:
                self.logger.info("# Connecting...")
                self.connection = AuthorizedConnection('http://{}:{}@{}/'.format(self.config['router_username'], self.config['router_password'], self.config['router_hostname'])) # Login required even for signal data
                self.logger.info("# Done.")
            except Exception as e:
                self.logger.warning("Failed on 1st try to connect OR we got the already logged in exception.")
                self.logger.warning("Exception: {}".format(str(e)))
        # Try to get data from the API...
        try:
            client = Client(self.connection)
            APIsignalData = client.device.signal()
        except Exception as e1:
            # ... If that failed,reconnecting first and then try again.
            try:
                self.logger.info("# Connecting...")
                self.connection = AuthorizedConnection('http://{}:{}@{}/'.format(self.config['router_username'], self.config['router_password'], self.config['router_hostname'])) # Login required even for signal data
                self.logger.info("# Done.")

                client = Client(self.connection)
                APIsignalData = client.device.signal()
            except Exception as e2:
                self.logger.warning("Failed on 2nd try to connect OR we got the already logged in exception.")
                self.logger.warning("Exception (e1): {}".format(str(e1)))
                self.logger.warning("Exception (e2): {}".format(str(e2)))
                return False

        # Get values for the signalDataKeys (variables) from the returned API data, convert the string values to floats (returns None aka. null if it fails), ...
        # ... strip specific extra characters (check self.signalData_strip_regexp) and save the original value as well.
        signalData2Graphite = dict()
        for signalDataKey in self.config['signalDataKeys']:
            try:
                signalData2Graphite[signalDataKey + '_original'] = APIsignalData[signalDataKey]
                signalData2Graphite[signalDataKey + '_value'] = floatOrNull(re.sub(r"{}".format(self.signalData_strip_regexp), "", APIsignalData[signalDataKey]))
            except:
                pass

        # Get current time
        ts = time.time()

        # Check if Cell ID changed
        cell_id_changed = False
        try:
            if (self.saveData['latest_cell_id']):
                pass
            else:
                cell_id_changed = True
        except:
            self.saveData['latest_cell_id'] = ''
            cell_id_changed = True
        try:
            if (APIsignalData['cell_id'] != self.saveData['latest_cell_id']):
                self.logger.info("*** CELL ID changed.")
                cell_id_changed = True
        except:
            pass

        # Create Cell ID changed Graphite Event
        failed_to_send_cell_id_changed = False
        if (cell_id_changed):
            if (self.sendData2Graphite):
                sendDataText = "Creating an Event"
            else:
                sendDataText = "Simulating an Event creation"

            self.logger.info("%s ('%s'). ts=%d => %s" % (sendDataText, self.config['eventTag_CellIDchanged'], ts, datetime.datetime.fromtimestamp(ts).strftime('%Y-%m-%d %H:%M:%S')))
            self.logger.debug("Cell ID: {}/{} (Old/New)".format(self.saveData['latest_cell_id'], APIsignalData['cell_id']))

            if (self.sendData2Graphite):
                try:
                    if self.create_graphite_event("Cell ID changed", [self.config['eventTag_CellIDchanged'], "cell_id_{}".format(APIsignalData['cell_id'])], 'Cell ID: {}/{} (Old/New)'.format(self.saveData['latest_cell_id'], APIsignalData['cell_id'])):
                        self.logger.warning("Successfully created the event.")

                        # Save the Cell ID change to a variable and the JSON file
                        self.saveData['latest_cell_id'] = APIsignalData['cell_id']
                        self.saveJSONfile(self.saveDataFilePath, self.saveData)
                    else:
                        self.logger.error("Failed to create the event in Graphite. Unknown error.")
                        failed_to_send_cell_id_changed = True
                except Exception as e:
                    self.logger.error("Failed to create the event in Graphite. Exception: {}".format(str(e)))
                    failed_to_send_cell_id_changed = True

        # Go through all the values and send them to Graphite
        for extra_prefix in {"all", 'by_cell_id.' + APIsignalData['cell_id']}: # Send the data with the extra prefixes 'all' and by the Cell ID (double data stored, but you can later on filter the data per Cell ID as well)
            for metric, value in sorted(signalData2Graphite.items()):
                
                # Replace dots with underscores
                safe_metric = metric.replace('.', '_')
            
                # Build the metric path from general prefix, extra prefix and key name (metric)
                metric_path = self.config['graphite_prefix'] + "." + extra_prefix + "." + safe_metric

                # Only act on _values, skip originals
                if bool(re.match('.*_value$', metric)):
                        haveOriginalValue = True
                        try:
                            # Get original value
                            original_value_key = re.sub(r"_value", "_original", metric)
                            original_value = signalData2Graphite[original_value_key]
                        except Exception as e:
                            haveOriginalValue = False
                            self.logger.warning("Unable to get the original value. Exception: {}".format(str(e)))


                        if self.sendData2Graphite:
                            sendDataText = "Sending data"
                        else:
                            sendDataText = "Simulating (not sending) data"

                        self.logger.info("%s for '%s'. ts=%d => %s" % (sendDataText, metric_path, ts, datetime.datetime.fromtimestamp(ts).strftime('%Y-%m-%d %H:%M:%S')))

                        if haveOriginalValue:
                            self.logger.debug("Value: '{}' (Original_value: '{}')".format(value, original_value))
                        else:
                            self.logger.debug("Value: '{}'".format(value))

                        if self.sendData2Graphite:
                            try:
                                # send data - metric_path,    value, [timestamp, tags (dict)]
                                graphyte.send(metric_path, value, ts)
                            except Exception as e:
                                self.logger.error("Unable to send the data to Graphite. Exception: {}".format(str(e)))
                                return False
                else:
                    # Skipping original values, as these can't be saved as strings.
                    pass
        


        # Save latest cell ID only if we successfully sent the data to Graphite
        if (self.sendData2Graphite and not failed_to_send_cell_id_changed):
            self.saveData['latest_cell_id'] = APIsignalData['cell_id']
            self.saveJSONfile(self.saveDataFilePath, self.saveData)
        self.logger.warning("Success. Loop done. Waiting max. {} seconds for the next run.".format(self.config['loopInterval']))
        return True
Example #24
0
            closg = wrongJSON.find(r'"', unesc + 2)
            wrongJSON = s[:closg] + r'\"' + s[closg + 1:]
    return wrongJSON
    #return wrongJSON.replace('\"','')


if len(sys.argv) == 4:
    ip = sys.argv[1]
    login = sys.argv[2]
    pwd = sys.argv[3]
    list = []

    list.append('{"huawei_lte_api": "' + huawei_lte_api.__version__ + '"}')

    try:
        connection = AuthorizedConnection('http://' + login + ':' + pwd + '@' +
                                          ip)
        client = Client(connection)

        try:
            list.append(json.dumps(client.user.state_login()))
        except:
            list.append('{"state_login()": "Not supported"}')

        try:
            list.append(json.dumps(client.sms.sms_count()))
        except:
            list.append('{"sms_count()": "Not supported"}')

        try:
            list.append(Clean_JSON(json.dumps(client.sms.get_sms_list())))
        except:
Example #25
0
from huawei_lte_api.AuthorizedConnection import AuthorizedConnection
from huawei_lte_api.Client import Client
from huawei_lte_api.Connection import Connection

parser = ArgumentParser()
parser.add_argument('url', type=str)
parser.add_argument('--username', type=str)
parser.add_argument('--password', type=str)
args = parser.parse_args()

if args.username is None:
    connection = Connection(args.url)
else:
    connection = AuthorizedConnection(args.url,
                                      username=args.username,
                                      password=args.password)

client = Client(connection)


def dump(method: Callable[[], Any]) -> None:
    print("==== %s" % method)
    try:
        pprint.pprint(method())
    except Exception as e:
        print(str(e))
    print("")


dump(client.device.information)
Example #26
0
        elif bandt == "2100":
            exp = int(bandsList[0][0].replace('b', ''))
        elif bandt == "2600":
            exp = int(bandsList[6][0].replace('b', ''))
        else:
            rep = "KO"
            print("Unknown frequency")
            print("Usage : " + basename(sys.argv[0]) + " " + usage)
            exit()
        band = band + 2**(exp - 1)
    lteband = str(hex(band)).replace("0x", "")

# Set band
try:
    url = "http://*****:*****@" + ip
    connection = AuthorizedConnection(url)
    client = Client(connection)
    networkband = "3FFFFFFF"
    networkmode = "03"
    if band != -1:
        client.net.set_net_mode(lteband, networkband, networkmode)
except Exception as e:
    print("Connexion error - " + str(e))
    exit()

# Statistics loop
keyboardThread = Keyboard()  # Threads init
if (len(sys.argv) == 5):
    pingThread = Ping()
statThread = Stat()
keyboardThread.start()  # Threads start
Example #27
0
 def init_connection(self):
     connection = AuthorizedConnection(self.url, self.login, self.password)
     self.client = Client(connection)
Example #28
0
from huawei_lte_api.Client import Client
from huawei_lte_api.AuthorizedConnection import AuthorizedConnection
from huawei_lte_api.Connection import Connection
from huawei_lte_api.enums.sms import BoxTypeEnum
from huawei_lte_api.enums.sms import TextModeEnum

connection = AuthorizedConnection('http://*****:*****@192.168.8.1/')
client = Client(connection)

#Read SMS
sms = client.sms.get_sms_list(1, BoxTypeEnum.LOCAL_INBOX, 1, 0, 0, 1)
print(sms)

#Send SMS
#print(client.sms.config())
#print(client.sms.send_sms([1144], "SALDO"))
Example #29
0
# Rain uses 1800MHz and 2600MHz but DOES NOT do Carrier aggregation.
# B525 router will auto connect to 1800MHz only - even though the router does support 2600MHZ. You will need a script to force it to 2600MHZ on the rain network.
# 1800MHz is generally slower on the download, but faster on the upload and has better ping/latency.
#  2600MHz is generally faster on the download, but slower on the upload and has more sporadic ping/latency.

#With Rain you can select Band 3 (1800MHz) and Depending on your router model Band 38 (2600MHz) TDD OR Band 40 (2500-2600MHz) TDD. Check your router specs and select the band accordingly. Band 38 = 2600MHz and Band 41 = 2500MHz they are exactly the same band but some routers handle is differently.

from huawei_lte_api.Client import Client
from huawei_lte_api.AuthorizedConnection import AuthorizedConnection
from huawei_lte_api.Connection import Connection

# connection = Connection('http://192.168.8.1/') For limited access, I have valid credentials no need for limited access
# connection = AuthorizedConnection('http://*****:*****@192.168.8.1/', login_on_demand=True) # If you wish to login on demand (when call requires authorization), pass login_on_demand=True

# 192.168.1.1
connection = AuthorizedConnection('http://*****:*****@192.168.8.1/')

client = Client(
    connection
)  # This just simplifies access to separate API groups, you can use device = Device(connection) if you want
print(client.device.signal())  # Can be accessed without authorization
print(
    client.device.information()
)  # Needs valid authorization, will throw exception if invalid credentials are passed in URL

#<response>
#<NetworkMode>00</NetworkMode>
#<NetworkBand>3FFFFFFF</NetworkBand>
#<LTEBand>7FFFFFFFFFFFFFFF</LTEBand>
#</response>
Example #30
0
    def performRecovery(self):
        print("routermonitor.py: In performRecovery, rebooting modem")
        connection = AuthorizedConnection('http://*****:*****@' + G_ROUTER_IP + '/')

        client = Client(connection)
        client.device.reboot()