Esempio n. 1
0
def system_worker_task(chronos):

    # Call App's worker
    if env.app_workerTask:
        worker_msg = None
        try:
            logger.debug('Mem free:', pal.get_mem_free())
            worker_msg = env.app_workerTask.call()
            if worker_msg:
                run_controlled(2,
                               apost,
                               api='/apps/worker/',
                               data={'msg': worker_msg})
            report('worker', 'OK')
        except Exception as e:
            logger.error(
                'Error in executing app\'s worker taks or sending its data: {} {}'
                .format(e.__class__.__name__, e))
            logger.debug(pal.get_traceback(e))
            run_controlled(2,
                           report,
                           what='worker',
                           status='KO',
                           message='{} {} ({})'.format(e.__class__.__name__, e,
                                                       pal.get_traceback(e)))
Esempio n. 2
0
def preregister():
    from crypto_rsa import Srsa
    pubkey = 28413003199647341169755148817272580434684756919496624803561225904937920874272008267922241718272669080997784342773848675977238304083346116914731539644572572184061626687258523348629880944116435872100013777281682624539900472318355160325153486782544158202452609602511838141993451856549399731403548343252478723563
    logger.info('Pre-registering myself with aes128ecb key="{}"'.format(env.payload_encrypter.key))
    response = run_controlled(None,
                              apost,
                              api='/things/preregister/',
                              data={'key': Srsa(pubkey).encrypt_text(str(env.payload_encrypter.key)),
                                    'kty': 'aes128ecb',
                                    'ken': 'srsa1'})        
    if not response:
        raise Exception('Empty Response from preregister')
    
    return response['content']['token']
Esempio n. 3
0
def register():
    logger.info('Registering myself with tid={} and aid={}'.format(
        env.tid, env.aid))
    response = run_controlled(None,
                              apost,
                              api='/things/register/',
                              data={
                                  'tid': env.tid,
                                  'aid': env.aid,
                                  'app_version': env.app_version,
                                  'pythings_version': env.pythings_version,
                                  'pool': env.pool,
                                  'frozen': env.frozen,
                                  'platform': platform
                              })
    if not response:
        raise Exception('Empty Response from register')

    return (response['content']['token'], response['content']['epoch'])
Esempio n. 4
0
def system_management_task(chronos):
    
    updates=False
    
    # Call management API
    response = run_controlled(2,apost,api='/apps/management/')
    if response and 'content' in response: 
        content = response['content']
    else:
        logger.error('Error in receiving/parsing settings, skipping the rest of the management task!')
        return
    del response
    gc.collect()

    # Update settings, Pythings and App.
    try:
        if 'settings' in content and content['settings'] != env.settings:
            updates='Settings'
            from updates_settings import update_settings
            update_settings(content)

        elif not env.frozen and env.settings['pythings_version'].upper() != 'FACTORY' and env.settings['pythings_version'] != env.pythings_version:
            updates='Pythings' 
            logger.debug('Downloading new Pythings (running version = "{}"; required version = "{}")'.format(env.pythings_version, env.settings['pythings_version']))
            from updates_pythings import update_pythings
            update_pythings(env.settings['pythings_version'])

        else:
            if env.settings['app_version'] != env.app_version:
                updates='App' 
                logger.debug('Downloading new App (running version = "{}"; required version = "{}")'.format(env.app_version, env.settings['app_version']))
                from updates_app import update_app
                update_app(env.settings['app_version'])

    except Exception as e:
        logger.error('Error in management task while updating {} ({}: {}), skipping the rest...'.format(updates, e.__class__.__name__, e))
        logger.debug(pal.get_traceback(e))
        run_controlled(2,report,what='management', status='KO', message='{} {} ({})'.format(e.__class__.__name__, e, pal.get_traceback(e)))
        return False

    gc.collect()

    # If updates, reboot.
    if updates:
        logger.info('Rebooting due to update')
        run_controlled(2,report,what='pythings', status='OK', message='Resetting due to {} update'.format(updates))
        hal.reboot()

    # Management Command (cmd), Command ID (cid) and Management Reply
    msg = content['msg'] if 'msg' in content else None
    mid = content['mid'] if 'mid' in content else None
    mty = content['type'] if 'type' in content else 'APP'
    rep = None

    # Execute system management message if we have one
    if mid and mty == 'CMD':
        cmd = msg
        try:
            logger.debug('Executing "{}"'.format(cmd))
            try:
                rep = pal.execute(cmd)
            except AttributeError:
                rep = 'Remote commands are not supported on this platform.'

        except Exception as e:
            logger.error('Error in executing app\'s management task: {} {}'.format(e.__class__.__name__, e))
            logger.debug(pal.get_traceback(e))
            run_controlled(2,report,what='management', status='KO', message='{} {} ({})'.format(e.__class__.__name__, e, pal.get_traceback(e)))

    # Call App's management
    if env.app_managementTask:
        try:
            logger.debug('Mem free:', pal.get_mem_free())
            if mid and mty == 'APP':
                rep=env.app_managementTask.call(msg)
            else:
                env.app_managementTask.call(None)
                
        except Exception as e:
            logger.error('Error in executing app\'s management task: {} {}'.format(e.__class__.__name__, e))
            logger.debug(pal.get_traceback(e))
            run_controlled(2,report,what='management', status='KO', message='{} {} ({})'.format(e.__class__.__name__, e, pal.get_traceback(e)))

    # Report if everything OK..
    if mid:
        run_controlled(2,report,what='management', status='OK', message={'mid':mid,'rep':rep})
    else:
        run_controlled(2,report,what='management', status='OK')
Esempio n. 5
0
def start():

    # Get Pythings version
    env.pythings_version = common.get_pythings_version()

    print('\n|--------------------------|')
    print('|  Starting PythingsOS :)  |')
    print('|--------------------------|')
    print(' Version: {}'.format(env.pythings_version))
    print(' Platform: {}'.format(platform))
    try: print(' Thing ID: {}\n'.format(hal.get_tid()))
    except: pass

    # Init hardware and platform
    hal.init()
    pal.init()
    
    # Start setup  mode if required
    if hal.HW_SUPPORTS_RESETCAUSE and hal.HW_SUPPORTS_WLAN and hal.get_reset_cause() in hal.WEBSETUP_RESETCAUSES:
        setup_timeout = int(load_param('setup_timeout', 60))
        if setup_timeout:
            if hal.HW_SUPPORTS_LED: hal.LED.on()
            from websetup import websetup
            gc.collect()
            websetup(timeout_s=setup_timeout)
            if hal.HW_SUPPORTS_LED: hal.LED.off()
            logger.info('Resetting...')
            hal.reboot()

    # Disable AP mode, Enable and configure STA mode 
    if hal.HW_SUPPORTS_WLAN:
        hal.WLAN.ap_active(False)
        hal.WLAN.sta_active(True)

    # Start loading settings and parameters
    from utils import load_settings
    env.settings = load_settings()
    env.payload_encrypter = None # Initalization

    # Load backend: the local param wins 
    env.backend = load_param('backend', None)

    if not env.backend:
        backend_overrided = False
        if 'backend' in env.settings and env.settings['backend']:
            env.backend = env.settings['backend']
        else:
            env.backend = 'backend.pythings.io'
    else:
        backend_overrided = True

    # Load aid and tid: only local param or default
    env.aid = load_param('aid', None)
    if env.aid is None:
        logger.critical('AID not provided, stopping here. Please set it up!')
        import time
        while True:
            time.sleep(1)
    env.tid = load_param('tid', None)
    if env.tid is None: env.tid = hal.get_tid()

    # Load pool: the local param wins 
    env.pool = load_param('pool', None)
    if not env.pool:
        if 'pool' in env.settings and env.settings['pool']:
            env.pool = env.settings['pool']
      
    env.frozen = hal.is_frozen()

    # Tasks placeholders
    env.app_workerTask = None
    env.app_managementTask = None
      
    # Report
    logger.info('Running with backend="{}" and aid="{}"'.format(env.backend, env.aid))

    # Get app version:
    env.app_version = common.get_app_version()

    # Register and perform the first management task call on "safe" backend, if not overrided
    if not backend_overrided:
        backend_set = env.backend
        env.backend ='backend.pythings.io'
    
    # Pre-register if payload encryption activated
    use_payload_encryption = env.settings['payload_encryption'] if 'payload_encryption' in env.settings else hal.USE_ENCRYPTION_DEFAULT
    if use_payload_encryption and hal.HW_SUPPORTS_ENCRYPTION and pal.get_payload_encrypter():
        logger.info('Enabling Payload Encryption and preregistering')
        env.payload_encrypter = pal.get_payload_encrypter()(comp_mode=True)
        from preregister import preregister
        token = preregister()
        env.token = token
        logger.info('Got token: {}'.format(env.token))
        del preregister
        gc.collect()
        
    # Register yourself, and start a new session
    from register import register
    token, epoch = register()
    if not env.payload_encrypter:
        env.token = token
        logger.info('Got token: {}'.format(env.token))
    del register
    gc.collect()
    
    # Sync time and add to env
    chronos = hal.Chronos(epoch)
    env.chronos = chronos

    # Call system management (will update App/Pythings versions  and settings if required)
    logger.info('Calling system management (preloop)')
    from management import system_management_task
    system_management_task(chronos)
    del system_management_task
    gc.collect()
    
    # Set back host to the proper one
    if not backend_overrided:
        env.backend=backend_set
        del backend_set
    gc.collect()

    # Init app
    try:
        from worker_task import WorkerTask
        env.app_workerTask = WorkerTask()
    except Exception as e:
        logger.error('Error in importing/loading app\'s worker tasks: {} {}'.format(e.__class__.__name__, e))
        logger.debug(pal.get_traceback(e))
        from api import report
        common.run_controlled(2,report,what='worker', status='KO', message='{} {} ({})'.format(e.__class__.__name__, e, pal.get_traceback(e)))

    try:
        from management_task import ManagementTask
        env.app_managementTask = ManagementTask()
    except Exception as e:
        logger.error('Error in importing/loading  app\'s management tasks: {} {}'.format(e.__class__.__name__, e))
        logger.debug(pal.get_traceback(e))
        from api import report
        common.run_controlled(2,report,what='management', status='KO', message='{} {} ({})'.format(e.__class__.__name__, e, pal.get_traceback(e)))

    # Setup intervals
    worker_interval = int(env.settings['worker_interval']) if 'worker_interval' in env.settings else 300
    management_interval = int(env.settings['management_interval']) if 'management_interval' in env.settings else 60

    # Start main loop
    loop_count = 0
    while True:
        
        if loop_count % management_interval == 0:
            logger.info('Calling management (loop={})'.format(loop_count))
            if hal.HW_SUPPORTS_LED:
                hal.LED.on(); sleep(0.05); hal.LED.off()
            from management import system_management_task
            system_management_task(chronos)
            del system_management_task
            gc.collect()
            logger.info('Done management')

        if loop_count % worker_interval == 0:
            logger.info('Calling worker (loop={})'.format(loop_count))
            from worker import system_worker_task
            system_worker_task(chronos)
            del system_worker_task
            gc.collect()
            logger.info('Done worker')
            
        loop_count+=1
        sleep(1)