Example #1
0
    class SchedulerExample(Agent):
        '''This agent can be used to demonstrate scheduling and 
        acutation of devices. It reserves a non-existant device, then
        acts when its time comes up. Since there is no device, this 
        will cause an error.
        '''
    
    
        def __init__(self, **kwargs):
            super(SchedulerExample, self).__init__(**kwargs)
    
        @Core.receiver('onsetup')
        def setup(self, sender, **kwargs):
            self._agent_id = config['agentid']

        @Core.receiver('onstart')            
        def startup(self, sender, **kwargs):
#             self.publish_schedule()
            self.use_rpc()
    
    
    
        @PubSub.subscribe('pubsub', topics.ACTUATOR_SCHEDULE_ANNOUNCE(campus='campus',
                                             building='building',unit='unit'))
        def actuate(self, peer, sender, bus,  topic, headers, message):
            print ("response:",topic,headers,message)
            if headers[headers_mod.REQUESTER_ID] != agent_id:
                return
            '''Match the announce for our fake device with our ID
            Then take an action. Note, this command will fail since there is no 
            actual device'''
            headers = {
                        'requesterID': agent_id,
                       }
            self.vip.pubsub.publish(
            'pubsub', topics.ACTUATOR_SET(campus='campus',
                                             building='building',unit='unit',
                                             point='point'),
                                     headers, str(0.0))
    
        
        def publish_schedule(self):
            '''Periodically publish a schedule request'''
            headers = {
                        'AgentID': agent_id,
                        'type': 'NEW_SCHEDULE',
                        'requesterID': agent_id, #The name of the requesting agent.
                        'taskID': agent_id + "-ExampleTask", #The desired task ID for this task. It must be unique among all other scheduled tasks.
                        'priority': 'LOW', #The desired task priority, must be 'HIGH', 'LOW', or 'LOW_PREEMPT'
                    } 
            
            start = str(datetime.datetime.now())
            end = str(datetime.datetime.now() + datetime.timedelta(minutes=1))
    
    
            msg = [
                   ['campus/building/unit',start,end]
                   #Could add more devices
    #                 ["campus/building/device1", #First time slot.
    #                  "2014-1-31 12:27:00",     #Start of time slot.
    #                  "2016-1-31 12:29:00"],     #End of time slot.
    #                 ["campus/building/device2", #Second time slot.
    #                  "2014-1-31 12:26:00",     #Start of time slot.
    #                  "2016-1-31 12:30:00"],     #End of time slot.
    #                 ["campus/building/device3", #Third time slot.
    #                  "2014-1-31 12:30:00",     #Start of time slot.
    #                  "2016-1-31 12:32:00"],     #End of time slot.
                    #etc...
                ]
            self.vip.pubsub.publish(
            'pubsub', topics.ACTUATOR_SCHEDULE_REQUEST, headers, msg)
            
            
        def use_rpc(self):
            try: 
                start = str(datetime.datetime.now())
                end = str(datetime.datetime.now() + datetime.timedelta(minutes=1))
    
                msg = [
                   ['campus/building/unit3',start,end]
                   ]
                result = self.vip.rpc.call(
                                           'platform.actuator', 
                                           'request_new_schedule',
                                           agent_id, 
                                           "some task",
                                           'LOW',
                                           msg).get(timeout=10)
                print("schedule result", result)
            except Exception as e:
                print ("Could not contact actuator. Is it running?")
                print(e)
                return
            
            try:
                if result['result'] == 'SUCCESS':
                    result = self.vip.rpc.call(
                                           'platform.actuator', 
                                           'set_point',
                                           agent_id, 
                                           'campus/building/unit3/some_point',
                                           '0.0').get(timeout=10)
                    print("Set result", result)
            except Exception as e:
                print ("Expected to fail since there is no real device to set")
                print(e)    
    class Agent(PublishMixin, BaseAgent):
        def __init__(self, **kwargs):
            super(Agent, self).__init__(**kwargs)
            self.lock_timer = None
            self.lock_acquired = False
            self.tasklet = None
            self.data_queue = green.WaitQueue(self.timer)
            self.value_queue = green.WaitQueue(self.timer)
            self.weather_data_queue = green.WaitQueue(self.timer)

            self.last_run_time = None
            self.is_running = False
            self.remaining_time = None
            self.task_id = agent_id
            self.retry_schedule = None
            self.start = None
            self.end = None

        def setup(self):
            super(Agent, self).setup()
            self.scheduled_task()

        def startrun(self, algo=None):
            _log.debug('start diagnostic')
            if algo is None:
                algo = afdd.AFDD(self, config_path).run_all
            self.tasklet = greenlet.greenlet(algo)
            self.is_running = True
            self.last_run_time = datetime.datetime.now()
            self.tasklet.switch()

        def scheduled_task(self):
            '''
            Schedule re-occuring diagnostics
            '''
            _log.debug('Schedule Dx')
            headers = {
                'type': 'NEW_SCHEDULE',
                'requesterID': agent_id,
                'taskID': agent_id,
                'priority': 'LOW_PREEMPT'
            }

            min_run_hour = math.floor(min_run_window / 3600)
            min_run_minute = int((min_run_window / 3600 - min_run_hour) * 60)

            self.start = datetime.datetime.now().replace(hour=start_hour,
                                                         minute=start_minute)
            self.end = self.start + datetime.timedelta(hours=2, minutes=30)
            run_start = self.end - datetime.datetime.now()
            required_diagnostic_time = datetime.timedelta(
                hours=min_run_hour, minutes=min_run_minute)

            if run_start < required_diagnostic_time:
                self.start = self.start + datetime.timedelta(days=1)
                self.end = self.start + datetime.timedelta(hours=2, minutes=30)
                sched_time = datetime.datetime.now() + datetime.timedelta(
                    days=day_run_interval + 1)
                sched_time = sched_time.replace(hour=0, minute=1)
            else:
                sched_time = datetime.datetime.now() + datetime.timedelta(
                    days=day_run_interval)

            self.start = str(self.start)
            self.end = str(self.end)
            self.task_timer = self.periodic_timer(
                60, self.publish_json, topics.ACTUATOR_SCHEDULE_REQUEST(),
                headers, [[
                    "{campus}/{building}/{unit}".format(**rtu_path),
                    self.start, self.end
                ]])
            event = sched.Event(self.scheduled_task)
            self.next = self.schedule(sched_time, event)

        @matching.match_headers({
            headers_mod.REQUESTER_ID: agent_id,
            'type': 'CANCEL_SCHEDULE'
        })
        @matching.match_exact(topics.ACTUATOR_SCHEDULE_RESULT())
        def preempt(self):
            if self.is_running:
                self.cancel_greenlet()

        @matching.match_headers({headers_mod.REQUESTER_ID: agent_id})
        @matching.match_exact(topics.ACTUATOR_SCHEDULE_ANNOUNCE(**rtu_path))
        def on_schedule(self, topic, headers, message, match):
            msg = jsonapi.loads(message[0])
            now = datetime.datetime.now()
            self.remaining_time = headers.get('window', 0)
            if self.task_id == headers.get('taskID', ''):
                if self.remaining_time < termination_window:
                    if self.is_running:
                        self.cancel_greenlet()
                elif (self.remaining_time > min_run_window and
                      (self.last_run_time is None or (now - self.last_run_time)
                       > datetime.timedelta(hours=23, minutes=50))):
                    self.startrun()

        @matching.match_headers({headers_mod.REQUESTER_ID: agent_id})
        @matching.match_exact(topics.ACTUATOR_SCHEDULE_RESULT())
        def schedule_result(self, topic, headers, message, match):
            msg = jsonapi.loads(message[0])
            _log.debug('Actuator response received')
            self.task_timer.cancel()

        @matching.match_exact(topics.DEVICES_VALUE(point='all', **rtu_path))
        def on_new_data(self, topic, headers, message, match):
            data = jsonapi.loads(message[0])
            #Check override status
            if int(data["VoltronPBStatus"]) == 1:
                if self.is_running:
                    _log.debug("User override is initiated...")
                    headers = {
                        'Content-Type': 'text/plain',
                        'requesterID': agent_id,
                    }
                    self.publish(
                        topics.ACTUATOR_SET(point="VoltronFlag", **rtu_path),
                        headers, str(0.0))
                    self.cancel_greenlet()
            else:
                self.data_queue.notify_all(data)

        @matching.match_headers({headers_mod.REQUESTER_ID: agent_id})
        @matching.match_glob(topics.ACTUATOR_VALUE(point='*', **rtu_path))
        def on_set_result(self, topic, headers, message, match):
            self.value_queue.notify_all((match.group(1), True))

        @matching.match_headers({headers_mod.REQUESTER_ID: agent_id})
        @matching.match_glob(topics.ACTUATOR_ERROR(point='*', **rtu_path))
        def on_set_error(self, topic, headers, message, match):
            self.value_queue.notify_all((match.group(1), False))

        def cancel_greenlet(self):
            #kill all tasks currently in the queue
            self.data_queue.kill_all()
            self.value_queue.kill_all()
            #kill current tasklet
            self.tasklet.throw()
            self.is_running = False

        def sleep(self, timeout):
            _log.debug('wait for steady state({})'.format(timeout))
            green.sleep(timeout, self.timer)

        def get_new_data(self, timeout=None):
            _log.debug('get_new_data({})'.format(timeout))
            return self.data_queue.wait(timeout)

        def command_equip(self, point_name, value, timeout=None):
            _log.debug('set_point({}, {}, {})'.format(point_name, value,
                                                      timeout))
            headers = {
                'Content-Type': 'text/plain',
                'requesterID': agent_id,
            }
            self.publish(topics.ACTUATOR_SET(point=point_name, **rtu_path),
                         headers, str(value))
            try:
                return self.value_queue.wait(timeout)
            except green.Timeout:
                return True

        def weather_request(self, timeout=None):
            _log.debug('weather request for {}'.format(zip_code))
            headers = {'Content-Type': 'text/plain', 'requesterID': agent_id}
            msg = {'zipcode': str(zip_code)}
            self.publish_json('weather/request', headers, msg)
            try:
                return self.weather_data_queue.wait(timeout)
            except green.Timeout:
                return 'INCONCLUSIVE'

        matching.match_headers({headers_mod.REQUESTER_ID: agent_id})

        @matching.match_exact('weather/response/temperature/temp_f')
        def weather_response(self, topic, headers, message, match):
            data = float(jsonapi.loads(message[0]))
            print data
            self.weather_data_queue.notify_all(data)
Example #3
0
    class Agent(PublishMixin, BaseAgent):
        '''This agent can be used to demonstrate scheduling and 
        acutation of devices. It reserves a non-existant device, then
        acts when its time comes up. Since there is no device, this 
        will cause an error.
        '''
        def __init__(self, **kwargs):
            super(Agent, self).__init__(**kwargs)

        def setup(self):
            # Demonstrate accessing a value from the config file
            _log.info(config['message'])

            # Always call the base class setup()
            super(Agent, self).setup()

            self.publish_schedule()

        @matching.match_exact(
            topics.ACTUATOR_SCHEDULE_ANNOUNCE(campus='campus',
                                              building='building',
                                              unit='unit'))
        @matching.match_headers({headers_mod.REQUESTER_ID: agent_id})
        def actuate(self, topic, headers, message, match):
            '''Match the announce for our fake device with our ID
            Then take an action. Note, this command will fail since there is no 
            actual device'''
            headers = {
                'requesterID': agent_id,
            }
            self.publish_json(
                topics.ACTUATOR_SET(campus='campus',
                                    building='building',
                                    unit='unit',
                                    point='point'), headers, str(0.0))

        @periodic(settings.SCHEDULE_PERIOD)
        def publish_schedule(self):
            '''Periodically publish a schedule request'''
            headers = {
                'AgentID': agent_id,
                'type': 'NEW_SCHEDULE',
                'requesterID': agent_id,  #The name of the requesting agent.
                'taskID': agent_id +
                "-ExampleTask",  #The desired task ID for this task. It must be unique among all other scheduled tasks.
                'priority':
                'LOW',  #The desired task priority, must be 'HIGH', 'LOW', or 'LOW_PREEMPT'
            }

            start = str(datetime.datetime.now())
            end = str(datetime.datetime.now() + datetime.timedelta(minutes=1))

            msg = [
                ['campus/building/unit', start, end]
                #Could add more devices
                #                 ["campus/building/device1", #First time slot.
                #                  "2014-1-31 12:27:00",     #Start of time slot.
                #                  "2016-1-31 12:29:00"],     #End of time slot.
                #                 ["campus/building/device2", #Second time slot.
                #                  "2014-1-31 12:26:00",     #Start of time slot.
                #                  "2016-1-31 12:30:00"],     #End of time slot.
                #                 ["campus/building/device3", #Third time slot.
                #                  "2014-1-31 12:30:00",     #Start of time slot.
                #                  "2016-1-31 12:32:00"],     #End of time slot.
                #etc...
            ]
            self.publish_json(topics.ACTUATOR_SCHEDULE_REQUEST, headers, msg)