Ejemplo n.º 1
0
    def __init__(self, device_name='/dev/ttyUSB0', all_attached_device_names=[],
                 baud_rate='9600', chatscript_file=None):

        super(PPP, self).__init__(device_name=device_name, baud_rate=baud_rate,
                                  chatscript_file=chatscript_file)

        self.route = Route()
        self.all_attached_device_names = all_attached_device_names
        self._ppp = PPPConnection(self.device_name, self.baud_rate, 'noipdefault',
                                  'usepeerdns', 'persist', 'noauth',
                                  #added by Jianwei Liu
                                  'debug',
                                  connect=self.connect_script)
Ejemplo n.º 2
0
 def __init__(self, event=Event()):
     super().__init__(event=event)
     self._connection_status = CLOUD_DISCONNECTED
     self._modem = None
     self._route = Route()
     self.__receive_port = None
Ejemplo n.º 3
0
class Cellular(Network):

    _modemHandlers = {
        'e303': E303.E303,
        'ms2131': MS2131.MS2131,
        'e372': E372.E372,
        'bg96': BG96.BG96,
        'nova': Nova_U201.Nova_U201,
        'novam': NovaM.NovaM,
        '': Modem
    }

    def __init__(self, event=Event()):
        super().__init__(event=event)
        self._connection_status = CLOUD_DISCONNECTED
        self._modem = None
        self._route = Route()
        self.__receive_port = None

    def autodetect_modem(self):
        # scan for a modem and set it if found
        dev_devices = self._scan_for_modems()
        if dev_devices is None:
            raise NetworkError('Modem not detected')
        self.modem = dev_devices[0]

    def load_modem_drivers(self):
        self._load_modem_drivers()

    def getConnectionStatus(self):
        return self._connection_status

    def is_connected(self):
        return self._connection_status == CLOUD_CONNECTED or self.modem.is_connected(
        )

    def connect(self, timeout=DEFAULT_CELLULAR_TIMEOUT):
        self.logger.info(
            'Connecting to cell network with timeout of %s seconds', timeout)
        success = False
        try:
            success = self.modem.connect(timeout=timeout)
        except KeyboardInterrupt as e:
            pass

        if success:
            self.logger.info('Successfully connected to cell network')
            # Disable at sockets mode since we're already establishing PPP.
            # This call is needed in certain modems that have limited interfaces to work with.
            time.sleep(2)
            # give the device a little time to enumerate
            self.disable_at_sockets_mode()
            self.__configure_routing()
            self._connection_status = CLOUD_CONNECTED
            self.event.broadcast('cellular.connected')
            super().connect()
        else:
            self.logger.info('Failed to connect to cell network')

        return success

    def disconnect(self):
        self.logger.info('Disconnecting from cell network')
        self.__remove_routing()
        success = self.modem.disconnect()
        if success:
            self.logger.info('Successfully disconnected from cell network')
            self.enable_at_sockets_mode()
            self._connection_status = CLOUD_DISCONNECTED
            self.event.broadcast('cellular.disconnected')
            super().disconnect()
        else:
            self.logger.info('Failed to disconnect from cell network')

        return success

    def reconnect(self):
        self.logger.info('Reconnecting to cell network')
        success = self.disconnect()

        if success == False:
            self.logger.info('Failed to disconnect from cell network')
            return False

        return self.connect()

    def create_socket(self):
        self.modem.create_socket()

    def connect_socket(self, host, port):
        self.modem.connect_socket(host, port)
        # This delay is required as recommended in the uBlox spec sheet.
        time.sleep(2)

    def listen_socket(self, port):
        self.modem.listen_socket(port)

    def write_socket(self, data):
        return self.modem.write_socket(data)

    def close_socket(self):
        return self.modem.close_socket()

    def send_message(self, data):
        return self.modem.send_message(data)

    def open_receive_socket(self, receive_port):
        self.__receive_port = receive_port
        self.event.subscribe('cellular.forced_disconnect',
                             self.__reconnect_after_forced_disconnect)
        return self.modem.open_receive_socket(receive_port)

    def pop_received_message(self):
        return self.modem.pop_received_message()

    def disable_at_sockets_mode(self):
        self.modem.disable_at_sockets_mode()

    def enable_at_sockets_mode(self):
        self.modem.enable_at_sockets_mode()

    def enableSMS(self):
        return self.modem.enableSMS()

    def disableSMS(self):
        return self.modem.disableSMS()

    def popReceivedSMS(self):
        return self.modem.popReceivedSMS()

    # EFFECTS: Returns the sim otp response from the sim.
    def get_sim_otp_response(self, command):
        return self.modem.get_sim_otp_response(command)

    def __reconnect_and_receive(self):
        if not self.at_sockets_available:
            self.connect()
        self.open_receive_socket(self.__receive_port)

    def __reconnect_after_forced_disconnect(self):
        self.logger.info('Reconnecting after forced disconnect...')
        time.sleep(
            5
        )  # uBlox takes some time to update internal state after disconnect
        self.__reconnect_and_receive()
        while not self.is_connected():
            self.logger.info('Reconnect failed. Retrying in 5 seconds...')
            time.sleep(5)
            self.__reconnect_and_receive()
        self.logger.info('Ready to receive data on port %s',
                         self.__receive_port)

    def __configure_routing(self):
        # maybe we don't have to tear down the routes but we probably should
        self.logger.info('Adding routes to Hologram cloud')
        self._route.add('10.176.0.0/16', self.localIPAddress)
        self._route.add('10.254.0.0/16', self.localIPAddress)
        if self.scope == NetworkScope.SYSTEM:
            self.logger.info(
                'Adding system-wide default route to cellular interface')
            self._route.add_default(self.localIPAddress)

    def __remove_routing(self):
        self.logger.info('Removing routes to Hologram cloud')
        if self.localIPAddress:
            self._route.delete('10.176.0.0/16', self.localIPAddress)
            self._route.delete('10.254.0.0/16', self.localIPAddress)
            if self.scope == NetworkScope.SYSTEM:
                self.logger.info(
                    'Removing system-wide default route to cellular interface')
                self._route.delete_default(self.localIPAddress)

    def _load_modem_drivers(self):
        dl = DriverLoader.DriverLoader()
        for (modemName, modemHandler) in self._modemHandlers.items():
            module = modemHandler.module
            if module:
                if not dl.is_module_loaded(module):
                    self.logger.info('Loading module %s for %s', module,
                                     modemName)
                    dl.load_module(module)
                    syspath = modemHandler.syspath
                    if syspath:
                        usb_ids = modemHandler.usb_ids
                        for vid_pid in usb_ids:
                            dl.force_driver_for_device(syspath, vid_pid[0],
                                                       vid_pid[1])

    def _scan_for_modems(self):
        res = None
        for (modemName, modemHandler) in self._modemHandlers.items():
            if self._scan_for_modem(modemHandler):
                res = (modemName, modemHandler)
                break
        return res

    def _scan_for_modem(self, modemHandler):
        usb_ids = modemHandler.usb_ids
        for vid_pid in usb_ids:
            if not vid_pid:
                continue
            self.logger.debug('checking for vid_pid: %s', str(vid_pid))
            for dev in list_ports.grep("{0}:{1}".format(
                    vid_pid[0], vid_pid[1])):
                self.logger.info('Detected modem %s', modemHandler.__name__)
                return True
        return False

    @property
    def modem(self):
        return self._modem

    @modem.setter
    def modem(self, modem):
        if modem not in self._modemHandlers:
            raise NetworkError('Invalid modem type: %s' % modem)
        else:
            self._modem = self._modemHandlers[modem](event=self.event)

    @property
    def localIPAddress(self):
        return self.modem.localIPAddress

    @property
    def remoteIPAddress(self):
        return self.modem.remoteIPAddress

    @property
    def signal_strength(self):
        return self.modem.signal_strength

    @property
    def modem_id(self):
        return self.modem.modem_id

    @property
    def imsi(self):
        return self.modem.imsi

    @property
    def iccid(self):
        return self.modem.iccid

    @property
    def operator(self):
        return self.modem.operator

    # This property will be set to None if a modem is not physically attached.
    @property
    def active_modem_interface(self):
        return repr(self.modem)

    @property
    def description(self):
        return self.modem.description

    @property
    def location(self):
        return self.modem.location

    @property
    def at_sockets_available(self):
        return self.modem.at_sockets_available
Ejemplo n.º 4
0
class PPP(IPPP):

    def __init__(self, device_name='/dev/ttyUSB0', all_attached_device_names=[],
                 baud_rate='9600', chatscript_file=None):

        super(PPP, self).__init__(device_name=device_name, baud_rate=baud_rate,
                                  chatscript_file=chatscript_file)

        self.route = Route()
        self.all_attached_device_names = all_attached_device_names
        self._ppp = PPPConnection(self.device_name, self.baud_rate, 'noipdefault',
                                  'usepeerdns', 'persist', 'noauth',
                                  #added by Jianwei Liu
                                  'debug',
                                  connect=self.connect_script)

    def isConnected(self):
        return self._ppp.connected()

    # EFFECTS: Establishes a PPP connection. If this is successful, it will also
    #          reroute packets to ppp0 interface.
    def connect(self, timeout=DEFAULT_PPP_TIMEOUT):

        self.__enforce_no_existing_ppp_session()

        result = self._ppp.connect(timeout=timeout)

        if result == True:
            if not self.route.wait_for_interface(DEFAULT_PPP_INTERFACE,
                                   MAX_PPP_INTERFACE_UP_RETRIES):
                self.logger.error('Unable to find interface %s. Disconnecting',
                        DEFAULT_PPP_INTERFACE)
                self._ppp.disconnect()
                return False
            return True
        else:
            return False


    def disconnect(self):
        self._ppp.disconnect()
        self.__shut_down_existing_ppp_session()
        return True

    # EFFECTS: Makes sure that there are no existing PPP instances on the same
    #          device interface.
    def __enforce_no_existing_ppp_session(self):

        pid_list = self.__check_for_existing_ppp_sessions()

        if len(pid_list) > 0:
            raise PPPError('Existing PPP session(s) are established by pid(s) %s. Please close/kill these processes first'
                             % pid_list)

    def __shut_down_existing_ppp_session(self):
        pid_list = self.__check_for_existing_ppp_sessions()

        # Process this only if it is a valid PID integer.
        for pid in pid_list:
            self.logger.info('Killing pid %s that currently have an active PPP session',
                             pid)
            psutil.Process(pid).terminate()

    def __check_for_existing_ppp_sessions(self):

        existing_ppp_pids = []
        self.logger.info('Checking for existing PPP sessions')

        for proc in psutil.process_iter():
            try:
                pinfo = proc.as_dict(attrs=['pid', 'name'])
            except:
                raise PPPError('Failed to check for existing PPP sessions')

            if 'pppd' in pinfo['name']:
                self.logger.info('Found existing PPP session on pid: %s', pinfo['pid'])
                existing_ppp_pids.append(pinfo['pid'])

        return existing_ppp_pids

    @property
    def localIPAddress(self):
        return self._ppp.raddr

    @property
    def remoteIPAddress(self):
        return self._ppp.laddr