Exemplo 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)))
Exemplo n.º 2
0
def handle(e):
    # Do not move the following import on top or code will fail (why?!)
    import pal
    logger.error(
        'Error in executing Pythings OS: "{}". Will report and rebot.'.format(
            e))
    logger.debug(pal.get_traceback(e))
    try:
        from api import report
        report(what='pythings',
               status='KO',
               message='{} {} ({})'.format(e.__class__.__name__, e,
                                           pal.get_traceback(e)))
    except Exception as e2:
        logger.error(
            'Could not report error to Pythings Cloud: "{}"'.format(e2))
        logger.debug(pal.get_traceback(e2))
    import time
    time.sleep(1)
    logger.info('I will reboot in 5 seconds. CTRL-C now to stop the reboot.')
    time.sleep(5)
    import hal
    hal.reboot()
Exemplo n.º 3
0
def run_controlled(retr, function, **kwargs):
    count=0
    while True:
        try:
            return function(**kwargs)   
        except Exception as e:
            logger.error('Error in executing controlled step ({}): {} {}'.format(function,e.__class__.__name__,e))
            logger.debug(pal.get_traceback(e))
            if retr == None or count < retr:
                count += 1
                logger.info('Retrying (#{}) in 3 seconds...'.format(count))
                time.sleep(3)
            else:
                logger.info('Exiting due to maximum retries reached')
                return
        finally:
            import gc
            gc.collect()
Exemplo 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')
Exemplo 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)