def onReadRequest(self, offset, callback):
     if not offset:
         Logger.info(LOCATION,
                     'Device Info being read by connected device.')
         total_memory = virtual_memory()
         endian = sys.byteorder
         sysData = {
             'platform': platform.system(),
             'release': platform.release(),
             'type': platform.uname().system,
             'arch': platform.uname().machine,
             'cpus': json.dumps(os.cpu_count()),
             'hostname': socket.gethostname(),
             'totalMemory': total_memory.total
         }
         # Mapping endian value to match with node sdk
         if endian == 'little':
             sysData['endianness'] = 'LE'
         else:
             sysData['endianness'] = 'BE'
         self.deviceInfoData.extend(map(ord, json.dumps(sysData)))
     #Return the necessary data through the call back
     callback(Characteristic.RESULT_SUCCESS, self.deviceInfoData[offset:])
 def onReadRequest(self, offset, callback):
     if not offset:
         Logger.info(LOCATION,
                     'Device Network info being read by connected device.')
         interfaces = netifaces.interfaces()
         address = ''
         interface_name = ''
         for iface in interfaces:
             addrs = netifaces.ifaddresses(iface)
             # Skip local address
             if not iface.startswith('lo'):
                 try:
                     # Filter only ipv4 address
                     ipv4_address_list = addrs[netifaces.AF_INET]
                     for ipv4 in ipv4_address_list:
                         address = ipv4['addr']
                         interface_name = iface
                 except Exception as exception:
                     # Filter only ipv4 address
                     pass
         data = {'network': address, 'ip': interface_name}
         self.networkData.extend(map(ord, json.dumps(data)))
     #Return the necessary network related data through the callback
     callback(Characteristic.RESULT_SUCCESS, self.networkData[offset:])
Exemple #3
0
 def get_actions(self):
     Logger.info(LOCATION, 'Retrieving actions...')
     try:
         actions = self.bot_service.get(ACTIONS_ENDPOINT)
         Logger.success(
             LOCATION, 'Successfully retrieved ' + str(len(actions)) +
             ' action(s) from server')
         Store.set_actions(actions)
         return actions
     except falcon.HTTPServiceUnavailable:
         Logger.warning(
             LOCATION,
             'Unable to retrieve actions from server. Loading locally stored action(s)...'
         )
         actions = self.store.get_actions()
         Logger.success(
             LOCATION, 'Successfully loaded ' + str(len(actions)) +
             ' cached action(s)')
         return actions
 def generate_qr_code(self):
     try:
         Logger.info(LOCATION,
                     'Generating QR Code for alternative pairing...')
         device_information = self.configuration.get_device_information()
         image = qrcode.make(json.dumps(device_information),
                             image_factory=PymagingImage)
         Store.save_qrcode(image)
         Logger.success(LOCATION, 'QR Code successfully generated')
     except Exception as exception:
         Logger.error(LOCATION, 'QR Code not generated')
         raise exception
 def pair(self):
     try:
         response = self.bot_service.get(RESOURCE)
     except:
         Logger.error(LOCATION, 'Failed pairing attempt.')
         return False
     if response['status'] is True:
         Logger.success(LOCATION, 'Device successfully paired.')
         return True
     else:
         Logger.error(LOCATION, 'Failed pairing attempt.')
         return False
Exemple #6
0
 def remove_configuration():
     try:
         if Store.has_configuration():
             os.remove(_configuration_file_path)
             os.remove(_qr_image_path)
             Logger.success(LOCATION,
                            'Successfully removed configuration file')
         else:
             Logger.warning(LOCATION,
                            'Could not reset, no configuration available')
     except IOError as io_error:
         Logger.error(LOCATION, io_error.message)
         raise io_error
 def run(self):
     if not self.can_pair:
         return
     if self.device_status == DeviceStatus.MULTIPAIR:
         Logger.info(LOCATION,
                     'Multipair mode, no need to poll or delete keys...')
         return
     Logger.info(LOCATION, 'Starting to pair device...')
     for tries in range(1, MAXIMUM_TRIES + 1):
         Logger.info(LOCATION, 'Pairing device, attempt: ' + str(tries))
         if self.pair():
             return True
         time.sleep(POLLING_INTERVAL_IN_SECONDS)
     return False
    def onWriteRequest(self, data, offset, withoutResponse, callback):
        if offset:
            callback(Characteristic.RESULT_ATTR_NOT_LONG)
        else:
            callback(Characteristic.RESULT_SUCCESS)

        if offset > len(data):
            callback(bleno.Characteristic.RESULT_INVALID_OFFSET)
            Logger.error(LOCATION, 'Error in Characteristic')
        else:
            callback(Characteristic.RESULT_SUCCESS, data[offset:])
            details = json.loads(data)

            if details['Skip'] == True:
                Logger.info(
                    LOCATION, 'Connected device skipped Wifi setup. ' +
                    'Initializing pairing process...')
                PairingService().run()
            else:
                wifiDetails = ''

                if details['SSID'] != '':
                    wifiDetails = 'ctrl_interface=DIR=/var/run/wpa_supplicant' + \
                                  ' GROUP=netdev\r\n update_config=1\r\n country=GB \r\n'+ \
                                  'network={ \r\n        ssid="' + details['SSID'] + \
                                  '" \r\n' + \
                                  '        psk="' + details['PWD'] + \
                                  '" \r\n        ' + \
                                  'key_mgmt=WPA-PSK \r\n}'

                Logger.info(
                    LOCATION,
                    'Wifi setup complete. Initializing pairing process...')
                PairingService().run()
                time.sleep(3)
                subprocess.run([
                    'sudo echo \'' + wifiDetails + '\' > ./wpa_supplicant.conf'
                ],
                               shell=True)
                subprocess.run([
                    "sudo", "cp", "./wpa_supplicant.conf",
                    "/etc/wpa_supplicant/"
                ])
                subprocess.run(["sudo", "rm", "./wpa_supplicant.conf"])
                subprocess.run(["sudo", "sleep", "1", "&&", "reboot"])
Exemple #9
0
 def remove_configuration():
     try:
         if Store.has_configuration():
             os.remove(_configuration_file_path)
             if os.path.isfile(_qr_image_path):
                 os.remove(_qr_image_path)
             if os.path.isfile(_saved_actions_path):
                 os.remove(_saved_actions_path)
             if os.path.isfile(_last_triggered_path):
                 os.remove(_last_triggered_path)
             Logger.success(LOCATION,
                            'Successfully reset device configuration')
         else:
             Logger.warning(LOCATION,
                            'Could not reset, no configuration available')
     except IOError as io_error:
         Logger.error(LOCATION, io_error.message)
         raise io_error
Exemple #10
0
 def _handle_ssl_exception():
     error = 'SSL Fingerprint verification failed. Could not verify server.'
     Logger.error(LOCATION, error)
     raise falcon.HTTPServiceUnavailable(description=error)
Exemple #11
0
 def on_setServiceError(error):
     if error:
         Logger.error(LOCATION, 'setServices: ', error)
     else:
         Logger.info(LOCATION, 'Successfully set services.')
Exemple #12
0
# Function to validate the given IP Address
def is_valid(ip):
    regex = '''^(25[0-5]|2[0-4][0-9]|[0-1]?[0-9][0-9]?)\.(
                25[0-5]|2[0-4][0-9]|[0-1]?[0-9][0-9]?)\.(
                25[0-5]|2[0-4][0-9]|[0-1]?[0-9][0-9]?)\.(
                25[0-5]|2[0-4][0-9]|[0-1]?[0-9][0-9]?)'''

    return re.search(regex, ip)


if not store.has_configuration():
    if len(sys.argv) <= 1:
        exit('Please add your makerID to configure the SDK: "make server makerID=YOUR_MAKER_ID"')
    maker_id = sys.argv[1]  # 1 -> First argument after server.py
    configuration_service.initialize_configuration(maker_id)

# If OS is windows based, it doesn't support gunicorn so we run waitress
if os.name == 'nt':
    subprocess.run(['waitress-serve', '--port=3001', 'bot_python_sdk.api:api'])
else:
    cmd = subprocess.Popen(['hostname', '-I'], stdout=subprocess.PIPE)
    ip = cmd.communicate()[0].decode('ascii').split(' ')[0]
    if is_valid(ip):
        Logger.info(LOCATION, "Detected IP Address :" + ip)
    else:
        Logger.info(LOCATION, "Failed in detecting valid IP Address, using loop back address: 127.0.0.1")
        ip = '127.0.0.1'
    Logger.info(LOCATION, "Starting Webserver at URL: http://" + ip + ':3001/')
    subprocess.run(['gunicorn', '-b', ip + ':3001', 'bot_python_sdk.api:api'])
Exemple #13
0
 def on_get(self, request, response):
     Logger.info(LOCATION,
                 INCOMING_REQUEST + METHOD_GET + ' ' + ACTIONS_ENDPOINT)
     response.media = self.action_service.get_actions()
Exemple #14
0
 def _handle_unsupported_frequency(frequency):
     error = 'Frequency not supported: ' + frequency
     Logger.error(LOCATION, error)
     raise falcon.HTTPBadRequest(description=error)
Exemple #15
0
 def on_get(self, request, response):
     Logger.info(LOCATION, "Serving QRCode Request...")
     stream = open(QRCODE_IMG_PATH, 'rb')
     content_length = os.path.getsize(QRCODE_IMG_PATH)
     response.content_type = "image/png"
     response.stream, response.content_length = stream, content_length
Exemple #16
0
 def _handle_maximum_frequency(frequency):
     error = 'Maximum ' + frequency + ' triggers reached'
     Logger.error(LOCATION, error)
     raise falcon.HTTPBadRequest(description=error)
Exemple #17
0
def check_and_resume_configuration():
    configuration = ConfigurationStore().get()
    device_status = configuration.get_device_status()
    system_platform = platform.system()
    Logger.info(LOCATION, "Detected Platform System: " + system_platform)
    if device_status is DeviceStatus.ACTIVE:
        Logger.info(LOCATION,
                    "Device is already active, no need to further configure")
        Logger.info(LOCATION, "Server is waiting for requests to serve...")
        Logger.info(
            LOCATION,
            "Supported Endpoints: /qrcode    /actions    /pairing    /activate"
        )
    elif device_status is DeviceStatus.PAIRED:
        Logger.info(LOCATION,
                    "Device state is PAIRED, resuming the configuration")
        ConfigurationService().resume_configuration()
    elif device_status is DeviceStatus.MULTIPAIR and PairingService().pair():
        Logger.info(
            LOCATION,
            "Device is paired as MULTIPAIR, Server is waiting for requests to serve..."
        )
    else:
        Logger.info(
            LOCATION,
            "Pair the device either using QRCode or Bluetooth Service through FINN Mobile App"
        )
        if system_platform != 'Darwin' and configuration.is_bluetooth_enabled(
        ):
            from bot_python_sdk.bluetooth_service import BluetoothService
            # Handle BLE specific events and callbacks
            BluetoothService().initialize()
            ConfigurationService().resume_configuration()
 def generate_key(self):
     Logger.info('Key Generator', 'Generating KeyPair...')
     key = PKey()
     key.generate_key(TYPE_RSA, 1024)
     key = key.to_cryptography_key()
     return self._public_key(key), self._private_key(key)
Exemple #19
0
 def on_get(self, request, response):
     Logger.info(LOCATION, "Serving base endpoint request...")
     response.body = '{"message": "BoT-Python-SDK Webserver", "endpoints" : "/qrcode    /actions    /pairing    /activate" }'
     response.status = falcon.HTTP_200