Beispiel #1
0
def sendTOTP(args, data, is_sms=False):

    if not args['iccid'] and ('device_id' in data):
        args['iccid'] = data['device_id']

    if not args['imsi'] and ('private_key' in data):
        args['imsi'] = data['private_key']

    credentials = {'device_id': args['iccid'], 'private_key': args['imsi']}
    hologram = HologramCloud(credentials, enable_inbound=False,
                             authentication_type='totp',
                             network='cellular')

    modem = ''
    # Load the ICCID and IMSI values if modem is physically attached to machine
    if hologram.network.isModemAttached():
        modem = hologram.network.active_modem_interface
        hologram.credentials = {'device_id': hologram.network.iccid,
                                'private_key': hologram.network.imsi}
        hologram.initializeNetwork('cellular-' + str(modem).lower())

    if (hologram.credentials['device_id'] is None) or (hologram.credentials['private_key'] is None):
        raise HologramError('Device id or private key not specified or cannot be pulled from modem. Please specify them or rerun the program with a provided device key')

    result = hologram.network.connect()
    if result == False:
        raise HologramError('Failed to connect to cell network')

    send_message_helper(hologram, args, is_sms=is_sms)
    hologram.network.disconnect()
Beispiel #2
0
def run_hologram_send(args):

    if args['message'] is None:
        raise HologramError('Message body cannot be empty')
    elif args['cloud'] and args['sms']:
        raise HologramError('must pick either one of cloud or sms')
    elif args['sms']:
        run_hologram_send_sms(args)
    else:
        run_hologram_send_cloud(args)
def run_hologram_send_sms(args):

    if args['devicekey'] is None:
        raise HologramError('--devicekey is required')
    elif args['destination'] is None:
        raise HologramError(
            '--destination missing. A destination number must be provided in order to send SMS to it'
        )

    data = dict()
    # SMS can only be sent with CSRPSK auth.
    sendPSK(args, data, is_sms=True)
Beispiel #4
0
def run_hologram_send_sms(args):

    if args['devicekey'] is None:
        raise HologramError('--devicekey is required')
    elif args['destination'] is None:
        raise HologramError('--destination missing. A destination number must be provided in order to send SMS to it')

    data = dict()
    if args['authtype'] == 'totp' and not args['devicekey']:
        sendTOTP(args, data, is_sms=True)
    else:
        sendPSK(args, data, is_sms=True)
Beispiel #5
0
    def _flush_used_response_from_serial_port_buffer(self, expected_response):

        self._serial_port_lock.writer_acquire()

        # LEFT SUBSTRING
        index = self._serial_port_buffer.find(expected_response)
        if index == -1:
            self._serial_port_lock.writer_release()
            raise HologramError(
                'Internal SDK error: expected AT response not found')

        # This stores what came before it
        str_left = self._serial_port_buffer[:index]
        #print 'str_left: ' + str_left.encode('string_escape')

        # RIGHT SUBSTRING
        # Cut the substring off from the buffer by finding the 'right' position.
        # Find the first occurrence of AT+ since index.
        right = self._serial_port_buffer.find('AT', index)
        str_right = self._serial_port_buffer[right:]
        #print 'str_right: ' + str_right.encode('string_escape')

        self._serial_port_buffer = str_left + str_right

        self._serial_port_lock.writer_release()
Beispiel #6
0
    def __init__(self, credentials, send_host='', send_port=0,
                 receive_host='', receive_port=0, enable_inbound=False,
                 network=''):

        super(CustomCloud, self).__init__(credentials,
                                          send_host=send_host,
                                          send_port=send_port,
                                          receive_host=receive_host,
                                          receive_port=receive_port,
                                          network=network)

        # Enforce that the send and receive configs are set before using the class.
        if enable_inbound and (receive_host == '' or receive_port == 0):
            raise HologramError('Must set receive host and port for inbound connection')

        self._periodic_msg_lock = threading.Lock()
        self._periodic_msg = None
        self._periodic_msg_enabled = False

        self._receive_buffer_lock = threading.Lock()
        self._receive_cv = threading.Lock()
        self._receive_buffer = deque()
        self._receive_socket = None

        self._accept_thread = None
        self.socketClose = True
        self._is_send_socket_open = False

        if enable_inbound == True:
            self.initializeReceiveSocket()
def sendPSK(args, data, is_sms=False):

    if not (args['devicekey']) and ('devicekey' in data):
        args['devicekey'] = data['devicekey']

    if not args['devicekey']:
        raise HologramError('Device key not specified')

    credentials = {'devicekey': args['devicekey']}

    recv = ''
    if not is_sms and (args['host'] is not None or args['port'] is not None):
        # we're using some custom cloud
        customCloud = CustomCloud(None,
                                  send_host=args['host'],
                                  send_port=args['port'])
        recv = customCloud.sendMessage(args['message'],
                                       timeout=args['timeout'])
        print(f'RESPONSE FROM CLOUD: {recv}')
    else:
        # host and port are default so use Hologram
        hologram = HologramCloud(credentials,
                                 authentication_type='csrpsk',
                                 network='cellular')
        send_message_helper(hologram, args, is_sms=is_sms)
    def setAuthenticationType(self, credentials, authentication_type='csrpsk'):

        if authentication_type not in HologramCloud._authentication_handlers:
            raise HologramError('Invalid authentication type: %s' % authentication_type)

        self.authenticationType = authentication_type

        self.authentication = HologramCloud._authentication_handlers[self.authenticationType](credentials)
Beispiel #9
0
def run_network_disconnect(args):
    print 'Checking for existing PPP sessions'
    for proc in psutil.process_iter():

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

        if 'pppd' in pinfo['name']:
            print 'Found existing PPP session on pid: %s' % pinfo['pid']
            print 'Killing pid %s now' % pinfo['pid']
            psutil.Process(pinfo['pid']).terminate()
Beispiel #10
0
    def setAuthenticationType(self, credentials, authentication_type='csrpsk'):

        try:
            if authentication_type not in HologramCloud._authentication_handlers:
                raise HologramError('Invalid authentication type: %s' %
                                    authentication_type)

            self.authenticationType = authentication_type

            self.authentication = HologramCloud._authentication_handlers[
                self.authenticationType](credentials)
        except HologramError as e:
            self.logger.error(repr(e))
            sys.exit(1)
def run_modem_disconnect(args):
    print('Note: "hologram modem disconnect" is deprecated '\
            'in favor of "hologram network disconnect"')
    print('Checking for existing PPP sessions')
    for proc in psutil.process_iter():

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

        if 'pppd' in pinfo['name']:
            print('Found existing PPP session on pid: %s' % pinfo['pid'])
            print('Killing pid %s now' % pinfo['pid'])
            psutil.Process(pinfo['pid']).terminate()
Beispiel #12
0
def modem_connection_status():
    #print('Checking for existing PPP sessions')
    for proc in psutil.process_iter():
        try:
            pinfo = proc.as_dict(attrs=['pid', 'name'])
        except:
            raise HologramError('Failed to check for existing PPP sessions')
            return False

        if 'pppd' in pinfo['name']:
            #print('Found existing PPP session on pid: {}'.format(pinfo['pid']))
            return pinfo['pid']
            # print 'Killing pid %s now' % pinfo['pid']
            # psutil.Process(pinfo['pid']).terminate()
    #print('No PPP session running. Not Connected')
    return False
Beispiel #13
0
    def sendPeriodicMessage(self, interval, message, topics=None, timeout=5):

        try:
            self._enforce_minimum_periodic_interval(interval)

            if not self._periodic_msg_disabled.is_set():
                raise HologramError(
                    'Cannot have more than 1 periodic message job at once')
            self._periodic_msg_disabled.clear()

        except Exception as e:
            self.__enforce_network_disconnected()
            raise

        self._periodic_msg = threading.Thread(
            target=self._periodic_job_thread,
            args=[interval, self.sendMessage, message, topics, timeout])
        self._periodic_msg.start()
    def request_hex_nonce(self):

        self.open_send_socket()

        # build nonce request payload string
        nonce_request = self.authentication.buildNonceRequestPayloadString()

        self.logger.debug("Sending nonce request with body of length %d", len(nonce_request))
        self.logger.debug('Send: %s', nonce_request)

        nonce = super().sendMessage(message=nonce_request, timeout=10, close_socket=False)
        self.logger.debug('Nonce request sent.')

        resultbuf_hex = binascii.b2a_hex(nonce)

        if resultbuf_hex is None:
            raise HologramError('Internal nonce error')

        return resultbuf_hex
Beispiel #15
0
    def request_nonce(self):

        self.open_send_socket()

        # build nonce request payload string
        request = self.authentication.buildNonceRequestPayloadString()

        self.logger.debug("Sending nonce request with body of length %d",
                          len(request))
        self.logger.debug('Send: %s', request)

        self.sock.send(request)
        self.logger.debug('Nonce request sent.')

        resultbuf = binascii.b2a_hex(
            self.receive_send_socket(max_receive_bytes=32))

        if resultbuf is None:
            raise HologramError('Internal nonce error')

        return resultbuf
Beispiel #16
0
    def __init__(self,
                 credentials,
                 send_host='',
                 send_port=0,
                 receive_host='',
                 receive_port=0,
                 enable_inbound=False,
                 network=''):

        super(CustomCloud, self).__init__(credentials,
                                          send_host=send_host,
                                          send_port=send_port,
                                          receive_host=receive_host,
                                          receive_port=receive_port,
                                          network=network)

        # Enforce that the send and receive configs are set before using the class.
        if enable_inbound and (receive_host == '' or receive_port == 0):
            raise HologramError(
                'Must set receive host and port for inbound connection')

        self._periodic_msg = None
        # We start with the event set, clear it when running and then set when
        # shutting down. This way, the thread can wait on it and stop immediately
        # when the script is exiting
        self._periodic_msg_disabled = threading.Event()
        self._periodic_msg_disabled.set()

        self._receive_buffer_lock = threading.Lock()
        self._receive_cv = threading.Lock()
        self._receive_buffer = deque()
        self._receive_socket = None

        self._accept_thread = None
        self.socketClose = True
        self._is_send_socket_open = False

        if enable_inbound == True:
            self.initializeReceiveSocket()
Beispiel #17
0
    def sendPeriodicMessage(self, interval, message, topics=None, timeout=5):

        try:
            self._enforce_minimum_periodic_interval(interval)

            self._periodic_msg_lock.acquire()

            if self._periodic_msg_enabled == True:
                raise HologramError('Cannot have more than 1 periodic message job at once')

            self._periodic_msg_enabled = True

            self._periodic_msg_lock.release()

        except Exception as e:
            self.__enforce_network_disconnected()
            raise

        self._periodic_msg = threading.Thread(target=self._periodic_job_thread,
                                              args=[interval, self.sendMessage,
                                                    message, topics, timeout])
        self._periodic_msg.daemon = True
        self._periodic_msg.start()
Beispiel #18
0
 def _enforce_minimum_periodic_interval(self, interval):
     if interval < MIN_PERIODIC_INTERVAL:
         raise HologramError('Interval cannot be less than %d seconds.' %
                             MIN_PERIODIC_INTERVAL)
Beispiel #19
0
 def __enforce_receive_host_and_port(self):
     if self.receive_host == '' or self.receive_port == 0:
         raise HologramError(
             'Receive host and port must be set before making this operation'
         )
Beispiel #20
0
 def __enforce_send_host_and_port(self):
     if self.send_host == '' or self.send_port == 0:
         raise HologramError(
             'Send host and port must be set before making this operation')
Beispiel #21
0
 def disable_at_sockets_mode(self):
     raise HologramError(
         'Cannot disable AT command sockets on this Modem type')
Beispiel #22
0
 def __enforce_authentication_type_supported(self):
     if self.authenticationType is not 'csrpsk':
         raise HologramError('%s does not support SDK SMS features' %
                             self.authenticationType)
Beispiel #23
0
 def __enforce_valid_destination_number(self, destination_number):
     if not destination_number.startswith('+'):
         raise HologramError(
             'SMS destination number must start with a \'+\' sign')
Beispiel #24
0
 def __enforce_max_sms_length(self, message):
     if len(message) > MAX_SMS_LENGTH:
         raise HologramError('SMS cannot be more than %d characters long' %
                             MAX_SMS_LENGTH)
def run_hologram_activate(args):

    hologram = HologramCloud(dict(), network='cellular')
    sim = hologram.network.iccid

    if sim is None:
        raise HologramError('Failed to fetch SIM number from the modem')

    func_args = dict()

    if args['apikey'] is None:
        (username, password) = prompt_for_username_and_password()
        func_args['username'] = username
        func_args['password'] = password
    else:
        func_args['apikey'] = args['apikey']

    api = Api(**func_args)

    success, plans = api.getPlans()

    if success == False:
        raise HologramError('Failed to fetch plans')

    planIdToZonesDict = populate_valid_plans(plans)

    selected_plan, plan_name = prompt_for_plan(plans, planIdToZonesDict)
    selected_zone = prompt_for_zone(planIdToZonesDict[selected_plan])

    # preview
    success, response = api.activateSIM(sim=sim,
                                        plan=selected_plan,
                                        zone=selected_zone,
                                        preview=True)

    if success == False:
        print('Activation verification failed: %s' % response)
        return
    elif not confirm_activation(sim, plan_name, selected_plan, selected_zone,
                                response['total_cost']):
        return

    success, response = api.activateSIM(sim=sim,
                                        plan=selected_plan,
                                        zone=selected_zone)

    if success == True:
        print('Activating SIM... (this may take up to a few minutes)')
    else:
        print('Activation failed')
        return

    start_time = time.time()
    while time.time() < start_time + CHECK_LIVE_SIM_STATE_MAX_TIMEOUT:
        success, sim_state = api.getSIMState(sim)

        if sim_state == 'LIVE':
            break

        time.sleep(CHECK_LIVE_SIM_STATE_INTERVAL)

    if sim_state == 'LIVE':
        print('Activation successful!')
    else:
        print(
            'SIM is still not activated. Check status in a few minutes on Hologram Dashboard (https://dashboard.hologram.io/) or contact [email protected] with any further delays'
        )