Esempio n. 1
0
        class Agent(PublishMixin, BaseAgent):
            def setup(self):
                super(Agent, self).setup()
                self.damper = 0

            @matching.match_regex(topics.ACTUATOR_LOCK_ACQUIRE() + '(/.*)')
            def on_lock_result(self, topic, headers, message, match):
                _log.debug(
                    "Topic: {topic}, {headers}, Message: {message}".format(
                        topic=topic, headers=headers, message=message))
                self.publish(topics.ACTUATOR_LOCK_RESULT() + match.group(0),
                             headers, jsonapi.dumps('SUCCESS'))

            @matching.match_regex(topics.ACTUATOR_SET() + '(/.*/([^/]+))')
            def on_new_data(self, topic, headers, message, match):
                _log.debug(
                    "Topic: {topic}, {headers}, Message: {message}".format(
                        topic=topic, headers=headers, message=message))
                if match.group(2) == 'Damper':
                    self.damper = int(message[0])
                self.publish(topics.ACTUATOR_VALUE() + match.group(0), headers,
                             message[0])

            @periodic(5)
            def send_data(self):
                data = {
                    'ReturnAirTemperature': 55,
                    'OutsideAirTemperature': 50,
                    'MixedAirTemperature': 45,
                    'Damper': self.damper
                }
                self.publish_ex(topics.DEVICES_VALUE(point='all', **rtu_path),
                                {}, ('application/json', jsonapi.dumps(data)))
Esempio n. 2
0
 def pre_cool_get_lock(self, e_start,e_end):
     
     now = datetime.datetime.now()
     day=now.weekday()
   
     if not Schedule[day]:
         print"Unoccupied today"
         return
         
     self.state = 'PRECOOL'
     
     #e_end = e_start.replace(hour=cpp_end_hour, minute =0, second = 0)
     #e_end = e_start + datetime.timedelta(minutes=2)
     e_start_unix = time.mktime(e_start.timetuple())
     e_end_unix = time.mktime(e_end.timetuple())
    
     def run_schedule_builder():
         #current_time = time.mktime(current_time.timetuple())
         self.schedule_builder(e_start_unix, e_end_unix,
                               current_spacetemp=77.0,
                               pre_csp=csp_pre,
                               building_thermal_constant=building_thermal_constant,
                               normal_coolingstpt=76.0,
                               timestep_length=timestep_length,
                               dr_csp=csp_cpp)
         self.lock_handler=None
     
     self.lock_handler = run_schedule_builder
     
     headers = {
         headers_mod.CONTENT_TYPE: headers_mod.CONTENT_TYPE.JSON,
         'requesterID': agent_id}
     self.publish(topics.ACTUATOR_LOCK_ACQUIRE(**rtu_path), headers)
Esempio n. 3
0
 def setup(self):
     super(Agent, self).setup()
     headers = {
         'Content-Type': 'text/plain',
         'requesterID': agent_id,
     }
     self.publish(topics.ACTUATOR_LOCK_ACQUIRE(**rtu_path), headers)
Esempio n. 4
0
 def setup(self):
     """acquire lock fom actuator agent"""
     super(Agent, self).setup()
     headers = {
         'Content-Type': 'text/plain',
         'requesterID': agent_id,
     }
     self.lock_timer = self.periodic_timer(
         1, self.publish, topics.ACTUATOR_LOCK_ACQUIRE(**rtu_path),
         headers)
Esempio n. 5
0
 def update_schedule_state(self, unix_time):
     headers = {
         'Content-Type': 'text/plain',
         'requesterID': agent_id,
     }
     now = datetime.datetime.fromtimestamp(unix_time)
     day = now.weekday()
     if Schedule[day]:
         self.schedule_state = True
         #TODO: set this up to handle platform not running.
         #This will hang after a while otherwise.
         self.lock_timer = super(Agent, self).periodic_timer(
             1, self.publish, topics.ACTUATOR_LOCK_ACQUIRE(**rtu_path),
             headers)
     else:
         self.schedule_state = False
         self.publish(topics.ACTUATOR_LOCK_RELEASE(**rtu_path), headers)
Esempio n. 6
0
    class Agent(PublishMixin, BaseAgent):
        """Class agent"""
        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)

        def setup(self):
            """acquire lock fom actuator agent"""
            super(Agent, self).setup()
            headers = {
                'Content-Type': 'text/plain',
                'requesterID': agent_id,
            }
            self.lock_timer = self.periodic_timer(
                1, self.publish, topics.ACTUATOR_LOCK_ACQUIRE(**rtu_path),
                headers)

        @matching.match_exact(topics.ACTUATOR_LOCK_ACQUIRE(**rtu_path))
        def __on_lock_sent(self, topic, headers, message, match):
            """lock recieved"""
            self.lock_timer.cancel()

        @matching.match_exact(topics.ACTUATOR_LOCK_RESULT(**rtu_path))
        def __on_lock_result(self, topic, headers, message, match):
            """lock result"""
            msg = jsonapi.loads(message[0])
            holding_lock = self.lock_acquired
            if headers['requesterID'] == agent_id:
                self.lock_acquired = msg == 'SUCCESS'
            elif msg == 'SUCCESS':
                self.lock_acquired = False
            if self.lock_acquired and not holding_lock:
                self.start()

        @matching.match_exact(topics.DEVICES_VALUE(point='all', **rtu_path))
        def __on_new_data(self, topic, headers, message, match):
            """watching for new data"""
            data = jsonapi.loads(message[0])
            self.data_queue.notify_all(data)

        @matching.match_glob(topics.ACTUATOR_VALUE(point='*', **rtu_path))
        def __on_set_result(self, topic, headers, message, match):
            """set value in conroller"""
            self.value_queue.notify_all((match.group(1), True))

        @matching.match_glob(topics.ACTUATOR_ERROR(point='*', **rtu_path))
        def __on_set_error(self, topic, headers, message, match):
            """watch for actuator error"""
            self.value_queue.notify_all((match.group(1), False))

        def __sleep(self, timeout=None):
            """built in sleep in green"""
            #_log.debug('sleep({})'.format(timeout))
            green.sleep(timeout, self.timer)

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

        def __command_equip(self, point_name, value, timeout=None):
            """set value in controller"""
            _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 None

        def __time_out(self):
            """if timeout occurs"""
            global fan1_norm
            global fan2_norm
            global csp_norm
            global min_damper
            if fan1_norm == 0:
                self.__sleep(
                    600)  #If controller loses volttron heartbeat will reset
                self.start()  #wait at least this long
            else:
                try:
                    self.__command_equip('CoolSupplyFanSpeed1', fan1_norm)
                except green.Timeout:
                    self.__sleep(600)
                    self.start()
                try:
                    self.__command_equip('CoolSupplyFanSpeed2', fan2_norm)
                except green.Timeout:
                    self.__sleep(600)
                    self.start()
                try:
                    self.__command_equip('ESMDamperMinPosition', min_damper)
                except green.Timeout:
                    self.__sleep(600)
                    self.start()
                try:
                    self.__command_equip('ReturnAirCO2Stpt', csp_norm)
                except green.Timeout:
                    self.__sleep(600)
                    self.start()

        @matching.match_exact(
            topics.DEVICES_VALUE(point='Occupied', **rtu_path))
        def __overide(self, topic, headers, message, match):
            """watch for override from controller"""
            data = jsonapi.loads(message[0])
            if not bool(data):
                self.tasklet = greenlet.greenlet(self.__on_override)
                self.tasklet.switch()

        def __on_override(self):
            global fan1_norm
            global fan2_norm
            global csp_norm
            global min_damper
            global override_flag

            if fan1_norm != 0 and not override_flag:
                override_flag = True
                _log.debug('Override initiated')
                try:
                    self.__command_equip('CoolSupplyFanSpeed1', fan1_norm)
                except green.Timeout:
                    self.__sleep(
                        43200)  #if override wait for 12 hours then resume
                    self.start(
                    )  #catalyst will default to original operations with no volttron heatbeat
                try:
                    self.__command_equip('CoolSupplyFanSpeed2', fan2_norm)
                except green.Timeout:
                    self.__sleep(43200)
                    self.start()
                try:
                    self.__command_equip('ESMDamperMinPosition', min_damper)
                except green.Timeout:
                    self.__sleep(43200)
                    self.start()
                try:
                    self.__command_equip('ReturnAirCO2Stpt', csp_norm)
                except green.Timeout:
                    self.__sleep(43200)
                    self.start()
            elif fan1_norm == 0 and not override_flag:
                override_flag = True
                self.__sleep(43200)
                self.start()

        def start(self):
            """Starting point for DR application"""
            global override
            override_flag = False
            self.tasklet = greenlet.greenlet(self.__go)
            self.tasklet.switch()

        def __go(self):
            """start main DR procedure"""
            #self.__command_equip('CoolSupplyFanSpeed1', 75)
            #self.__command_equip('CoolSupplyFanSpeed2', 90)
            #self.__command_equip('ESMDamperMinPosition', 5)
            global fan1_norm
            global fan2_norm
            global csp_norm
            global min_damper
            try:
                self.__command_equip('ReturnAirCO2Stpt', 74)
            except green.Timeout:
                self.__time_out()
            try:
                voltron_data = self.__get_new_data()
            except green.Timeout:
                self.__time_out()
                # Gracefully handle exception
            min_damper = float(voltron_data["ESMDamperMinPosition"])
            fan1_norm = float(voltron_data["CoolSupplyFanSpeed1"])
            fan2_norm = float(voltron_data["CoolSupplyFanSpeed2"])
            csp_norm = float(voltron_data["ReturnAirCO2Stpt"])
            _log.debug("Zone normal cooling temperature setpoint:  " +
                       repr(csp_norm))
            _log.debug("Supply fan cooling speed 1:  " + repr(fan1_norm))
            _log.debug("Supply fan cooling speed 2:  " + repr(fan2_norm))
            _log.debug("Normal minimum damper position:  " + repr(min_damper))
            self.tasklet = greenlet.greenlet(self.get_signal)
            self.tasklet.switch()

        def __pre_cpp_timer(self):
            """Schedule to run in get_signal"""
            _log.debug("Pre-cooling for CPP Event"
                       )  #pre-cool change cooling set point
            self.tasklet = greenlet.greenlet(self.__pre_csp)
            self.tasklet.switch()
            self.pre_timer = self.periodic_timer(settings.pre_cooling_time,
                                                 self.__pre_cpp_cooling)

        def __pre_cpp_cooling(self):
            """start pre cooling procedure"""
            self.tasklet = greenlet.greenlet(self.__pre_csp)
            self.tasklet.switch()

        def __pre_csp(self):
            """set cooling temp. set point"""
            self.__sleep(1)
            try:
                voltron_data = self.__get_new_data()
            except green.Timeout:
                self.__time_out()
            csp_now = float(voltron_data["ReturnAirCO2Stpt"])
            if csp_now > settings.csp_pre:
                try:
                    csp = csp_now - cooling_slope
                    self.__command_equip("ReturnAirCO2Stpt", csp)
                except green.Timeout:
                    self.__time_out()
            elif csp_now <= settings.csp_pre:
                try:
                    self.__command_equip("ReturnAirCO2Stpt", settings.csp_pre)
                except green.Timeout:
                    self.__time_out()
                self.pre_timer.cancel()

        def __accelerated_pre_cpp_timer(self):
            """if DR signal is received after normal pre"""
            _log.debug("Pre-cooling for CPP Event"
                       )  #pre-cool change cooling set point
            self.tasklet = greenlet.greenlet(self.__accelerated_pre_csp)
            self.tasklet.switch()
            self.pre_timer = self.periodic_timer(
                settings.pre_time, self.__accelerated_cpp_cooling)

        def __accelerated_cpp_cooling(self):
            """start accelerated pre-cooling"""
            self.tasklet = greenlet.greenlet(self.__accelerated_pre_csp)
            self.tasklet.switch()

        def __accelerated_pre_csp(self):
            """set cooling temp set point"""
            _log.debug("Accelerated pre-cooling for CPP Event")
            global accel_slope
            self.__sleep(2)
            try:
                voltron_data = self.__get_new_data()
            except green.Timeout:
                self.__time_out()
            csp_now = float(voltron_data["ReturnAirCO2Stpt"])
            csp = csp_now - accel_slope
            if csp_now > settings.csp_pre:
                try:
                    self.__command_equip("ReturnAirCO2Stpt", csp)
                except green.Timeout:
                    self.__time_out()
            elif csp_now <= settings.csp_pre:
                try:
                    self.__command_equip("ReturnAirCO2Stpt", settings.csp_pre)
                except green.Timeout:
                    self.__time_out()
                self.pre_timer.cancel()

        def __during_cpp_timer(self):
            """during CPP scheduled in get_signal"""
            self.tasklet = greenlet.greenlet(self.__during_cpp)
            self.tasklet.switch()

        def __during_cpp(self):
            """start CPP procedure"""
            _log.debug("During CPP Event")  # remove when done testing
            self.__sleep(2)
            global fan1_norm
            global fan2_norm
            cpp_damper = settings.cpp_damper
            fan_reduction = settings.fan_reduction
            cpp_csp = settings.cpp_csp
            cpp_fan1 = fan1_norm - fan1_norm * fan_reduction
            cpp_fan2 = fan2_norm - fan2_norm * fan_reduction
            self.__sleep(1)
            try:
                self.__command_equip("CoolSupplyFanSpeed1", cpp_fan1)
            except green.Timeout:
                self.__time_out()
            try:
                self.__command_equip("CoolSupplyFanSpeed2", cpp_fan2)
            except green.Timeout:
                self.__time_out()
            try:
                self.__command_equip("ReturnAirCO2Stpt", cpp_csp)
            except green.Timeout:
                self.__time_out()
            try:
                self.__command_equip('ESMDamperMinPosition', cpp_damper)
            except green.Timeout:
                self.__time_out()

        def __after_cpp_timer(self):
            """after CPP scheduled in get_signal"""
            self.tasklet = greenlet.greenlet(self.__restore_fan_damper)
            self.tasklet.switch()
            _log.debug("After CPP Event, returning to normal operations")
            self.tasklet = greenlet.greenlet(self.__restore_cooling_setpoint)
            self.tasklet.switch()
            timer = settings.after_time
            self.after_timer = self.periodic_timer(timer,
                                                   self.__after_cpp_cooling)

        def __after_cpp_cooling(self):
            """Start after CPP procedure"""
            _log.debug("After_CPP_COOLING")
            self.tasklet = greenlet.greenlet(self.__restore_cooling_setpoint)
            self.tasklet.switch()

        def __restore_fan_damper(self):
            """restore original fan speeds"""
            global fan1_norm
            global fan2_norm
            global min_damper
            self.__sleep(
                2
            )  # so screen _log.debugs in correct order remove after testing.
            try:
                self.__command_equip("ESMDamperMinPosition", min_damper)
            except green.Timeout:
                self.__time_out()
            try:
                self.__command_equip("CoolSupplyFanSpeed1", fan1_norm)
            except green.Timeout:
                self.__time_out()
            try:
                self.__command_equip("CoolSupplyFanSpeed2", fan2_norm)
            except green.Timeout:
                self.__time_out()

        def __restore_cooling_setpoint(self):
            """restore normal cooling temp setpoint"""
            global csp_norm
            self.__sleep(2)  #remove after testing
            try:
                voltron_data = self.__get_new_data()
            except green.Timeout:
                self.__time_out()
            csp_now = float(voltron_data["ReturnAirCO2Stpt"])
            if csp_now > csp_norm:
                csp = csp_now - cooling_slope
                try:
                    self.__command_equip("ReturnAirCO2Stpt", csp)
                except green.Timeout:
                    self.__time_out()
            elif csp_now <= csp_norm:
                self.after_timer.cancel()
                try:
                    self.__command_equip("ReturnAirCO2Stpt", csp_norm)
                except green.Timeout:
                    self.__time_out()

        def get_signal(self):
            """get and format DR signal and schedule DR proc."""
            #Pull signal from source
            self.__sleep(2)  #remove after testing
            global csp_norm
            global cooling_slope
            global accel_slope
            time_now = time.mktime(datetime.datetime.now().timetuple())
            time_pre = time.mktime(
                datetime.datetime.now().replace(hour=settings.pre_cpp_hour,
                                                minute=23,
                                                second=0,
                                                microsecond=0).timetuple())
            time_event = time.mktime(datetime.datetime.now().replace(
                hour=settings.during_cpp_hour,
                minute=25,
                second=0,
                microsecond=0).timetuple())
            time_after = time.mktime(datetime.datetime.now().replace(
                hour=settings.after_cpp_hour,
                minute=27,
                second=0,
                microsecond=0).timetuple())
            if (settings.signal and time_now < time_pre):
                _log.debug("Scheduling1")
                time_step = settings.pre_cooling_time / 3600
                #cooling_slope = (csp_norm-settings.csp_pre)/((((time_event-time_pre)/3600)-0.5)*time_step)
                cooling_slope = 1  # for testing use a constant
                temp = ((time_event - time_pre) / 3600)
                _log.debug("cooling slope: " + repr(cooling_slope))
                pre_cpp_time = datetime.datetime.now().replace(
                    hour=settings.pre_cpp_hour,
                    minute=23,
                    second=0,
                    microsecond=0)
                self.schedule(pre_cpp_time, sched.Event(self.__pre_cpp_timer))
                during_cpp_time = datetime.datetime.now().replace(
                    hour=settings.during_cpp_hour,
                    minute=25,
                    second=0,
                    microsecond=0)
                self.schedule(during_cpp_time,
                              sched.Event(self.__during_cpp_timer))
                after_cpp_time = datetime.datetime.now().replace(
                    hour=settings.after_cpp_hour,
                    minute=27,
                    second=0,
                    microsecond=0)
                self.schedule(after_cpp_time,
                              sched.Event(self.__after_cpp_timer))
                #self.start_timer.cancel()
            elif (settings.signal and time_now > time_pre
                  and time_now < time_event):
                _log.debug("Scheduling2")
                #self.start_timer.cancel()
                #accel_slope = (csp_norm-settings.csp_pre)/((time_event-time_now)/(3600))
                accel_slope = 2  #for testing use a constant
                during_cpp_time = datetime.datetime.now().replace(
                    hour=settings.during_cpp_hour,
                    minute=36,
                    second=20,
                    microsecond=0)
                self.schedule(during_cpp_time,
                              sched.Event(self.__during_cpp_timer))
                after_cpp_time = datetime.datetime.now().replace(
                    hour=settings.after_cpp_hour,
                    minute=39,
                    second=10,
                    microsecond=0)
                self.schedule(after_cpp_time,
                              sched.Event(self.__after_cpp_timer))
                self.__accelerated_pre_cpp_timer()
            elif (settings.signal and time_now > time_event
                  and time_now < time_after):
                _log.debug("Too late to pre-cool!")
                #self.start_timer.cancel()
                after_cpp_time = datetime.datetime.now().replace(
                    hour=settings.after_cpp_hour,
                    minute=17,
                    second=0,
                    microsecond=0)
                self.schedule(after_cpp_time,
                              sched.Event(self.__after_cpp_timer))
                self.tasklet = greenlet.greenlet(self.__during_cpp)
                self.tasklet.switch()
            else:
                _log.debug("CPP Event Is Over")
                #self.start_timer.cancel()
                self.__sleep(60)
                self.get_signal()
Esempio n. 7
0
    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)

        def setup(self):
            super(Agent, self).setup()
            headers = {
                'Content-Type': 'text/plain',
                'requesterID': agent_id,
            }
            self.lock_timer = self.periodic_timer(
                1, self.publish, topics.ACTUATOR_LOCK_ACQUIRE(**rtu_path),
                headers)

        def start(self, algo=None):
            if algo is None:
                algo = afdd
            self.tasklet = greenlet.greenlet(algo)
            self.tasklet.switch(self)

        @matching.match_exact(topics.ACTUATOR_LOCK_ACQUIRE(**rtu_path))
        def on_lock_sent(self, topic, headers, message, match):
            self.lock_timer.cancel()

        @matching.match_exact(topics.ACTUATOR_LOCK_RESULT(**rtu_path))
        def on_lock_result(self, topic, headers, message, match):
            msg = jsonapi.loads(message[0])
            holding_lock = self.lock_acquired
            if headers['requesterID'] == agent_id:
                self.lock_acquired = msg == 'SUCCESS'
            elif msg == 'SUCCESS':
                self.lock_acquired = False
            if self.lock_acquired and not holding_lock:
                self.start()

        @matching.match_exact(topics.DEVICES_VALUE(point='all', **rtu_path))
        def on_new_data(self, topic, headers, message, match):
            data = jsonapi.loads(message[0])
            self.data_queue.notify_all(data)

        @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_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 sleep(self, timeout):
            _log.debug('sleep({})'.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 set_point(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 None
Esempio n. 8
0
    class Agent(PublishMixin, BaseAgent):
        """Class agent"""
        def __init__(self, **kwargs):
            super(Agent, self).__init__(**kwargs)
            self.schedule_state = False
            self.fan1_norm = 0
            self.fan2_norm = 0
            self.csp_norm = 0
            self.accel_slope = 0
            self.cooling_slope = 0
            self.min_damper = 0
            self.override_flag = False
            self.lock_timer = None
            self.lock_acquired = False
            self.timers = []
            self.tasks = []
            self.tasklet = None
            self.data_queue = green.WaitQueue(self.timer)
            self.value_queue = green.WaitQueue(self.timer)
            self.running = False

        def setup(self):
            """acquire lock fom actuator agent"""
            super(Agent, self).setup()

        @matching.match_exact(
            topics.DEVICES_VALUE(point='CoolCall1', **rtu_path))
        def dr_signal(self, topic, headers, message, match):
            data = jsonapi.loads(message[0])
            if not self.running and bool(data):
                print("start")
                self.running = True
                time_now = time.mktime(datetime.datetime.now().timetuple())
                self.update_schedule_state(time_now)
                #self.schedule(next_time, self.update_schedule_state)
                if (self.schedule_state):
                    self.start()
                else:
                    _log.debug(
                        "DR signal is False or day is not an occupied day")

        def update_schedule_state(self, unix_time):
            headers = {
                'Content-Type': 'text/plain',
                'requesterID': agent_id,
            }
            now = datetime.datetime.fromtimestamp(unix_time)
            day = now.weekday()
            if Schedule[day]:
                self.schedule_state = True
                #TODO: set this up to handle platform not running.
                #This will hang after a while otherwise.
                self.lock_timer = super(Agent, self).periodic_timer(
                    1, self.publish, topics.ACTUATOR_LOCK_ACQUIRE(**rtu_path),
                    headers)
            else:
                self.schedule_state = False
                self.publish(topics.ACTUATOR_LOCK_RELEASE(**rtu_path), headers)

        @matching.match_exact(topics.ACTUATOR_LOCK_ACQUIRE(**rtu_path))
        def _on_lock_sent(self, topic, headers, message, match):
            """lock request received"""
            self.lock_timer.cancel()

        @matching.match_exact(topics.ACTUATOR_LOCK_RESULT(**rtu_path))
        def _on_lock_result(self, topic, headers, message, match):
            """lock result"""
            msg = jsonapi.loads(message[0])
            holding_lock = self.lock_acquired
            if headers['requesterID'] == agent_id:
                self.lock_acquired = msg == 'SUCCESS'
            elif msg == 'SUCCESS':
                self.lock_acquired = False
            if self.lock_acquired and not holding_lock:
                self.start()

        @matching.match_exact(topics.DEVICES_VALUE(point='all', **rtu_path))
        def _on_new_data(self, topic, headers, message, match):
            """watching for new data"""
            data = jsonapi.loads(message[0])
            self.data_queue.notify_all(data)

        @matching.match_glob(topics.ACTUATOR_VALUE(point='*', **rtu_path))
        def _on_set_result(self, topic, headers, message, match):
            """set value in conroller"""
            self.value_queue.notify_all((match.group(1), True))

        @matching.match_glob(topics.ACTUATOR_ERROR(point='*', **rtu_path))
        def _on_set_error(self, topic, headers, message, match):
            """watch for actuator error"""
            self.value_queue.notify_all((match.group(1), False))

        def _sleep(self, timeout=None):
            """built in sleep in green"""
            _log.debug('sleep({})'.format(timeout))
            green.sleep(timeout, self.timer)

        def _get_new_data(self, timeout=data_timeout):  #timeout=data_timeout
            """wait for new data"""
            _log.debug('get_new_data({})'.format(timeout))
            return self.data_queue.wait(timeout)

        def _command_equip(self, point_name, value, timeout):
            """set value in controller"""
            _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))
            while True:
                point, success = self.value_queue.wait(timeout)
                if point == point_name:
                    if success:
                        return
                    raise CommandSetError()

        def _time_out(self):
            """if timeout occurs"""
            if (self.fan1_norm and self.fan2_norm and self.min_damper
                    and self.csp_norm):
                try:
                    self._command_equip('CoolSupplyFanSpeed1', self.fan1_norm)
                    self._command_equip('CoolSupplyFanSpeed2', self.fan2_norm)
                    self._command_equip('ESMDamperMinPosition',
                                        self.min_damper)
                    self._command_equip('StandardDamperMinPosition',
                                        self.csp_norm)
                except green.Timeout:
                    pass
            for timer in self.timers:
                timer.cancel()
            del self.timers[:]
            current = greenlet.getcurrent()
            for task in self.tasks:
                if task is not current:
                    task.parent = current
                    task.throw()
            print 'adding current task to task list'
            self.tasks[:] = [current]
            self._sleep(
                600)  #If controller loses volttron heartbeat will reset
            self.running = False

        @matching.match_exact(
            topics.DEVICES_VALUE(point='Occupied', **rtu_path)
        )  # for now look for Occuppied, DR Override will be added
        def _override(self, topic, headers, message, match):
            """watch for override from controller"""
            data = jsonapi.loads(message[0])
            if not bool(data):
                self.greenlet(self._on_override)

        def _on_override(self):
            if not self.override_flag:
                self.override_flag = True
                _log.debug("Override initiated")
                for timer in self.timers:
                    timer.cancel()
                del self.timers[:]
                current = greenlet.getcurrent()
                for task in self.tasks:
                    if task is not current:
                        task.parent = current
                        task.throw()
            if self.fan1_norm:
                try:
                    self._command_equip('CoolSupplyFanSpeed1', self.fan1_norm)
                    self._command_equip('CoolSupplyFanSpeed2', self.fan2_norm)
                    self._command_equip('ESMDamperMinPosition',
                                        self.min_damper)
                    self._command_equip('ReturnAirCO2Stpt', self.csp_norm)
                except green.Timeout:
                    self._sleep(
                        43200)  #if override wait for 12 hours then resume
                    self._go(
                    )  #catalyst will default to original operations with no volttron heatbeat
                self._sleep(43200)
                self.override_flag = False
                self.running = False
            elif not self.fan1_norm and not self.override_flag:
                self.override_flag = True
                self._sleep(43200)
                self.override_flag = False
                self.running = False

        def start(self):
            """Starting point for DR application"""
            self.override_flag = False
            self.greenlet(self._go)

        def _go(self):
            """start main DR procedure"""
            self._command_equip('StandardDamperChangeOverSetPoint', 75, 20)
            self._command_equip('CoolSupplyFanSpeed2', 90, 20)
            self._command_equip('CoolSupplyFanSpeed1', 75, 20)
            self._command_equip('StandardDamperMinPosition', 65, 20)
            try:
                self._command_equip('ESMDamperMinPosition', 5, 20)

                voltron_data = self._get_new_data()
            except CommandSetError:
                self._time_out()
            except green.Timeout:
                self._time_out()
            self.min_damper = float(voltron_data["ESMDamperMinPosition"])
            self.fan1_norm = float(voltron_data["CoolSupplyFanSpeed1"])
            self.fan2_norm = float(voltron_data["CoolSupplyFanSpeed2"])
            self.csp_norm = float(voltron_data["ReturnAirCO2Stpt"])
            _log.debug("Zone normal cooling temperature setpoint:  " +
                       repr(self.csp_norm))
            _log.debug("Supply fan cooling speed 1:  " + repr(self.fan1_norm))
            _log.debug("Supply fan cooling speed 2:  " + repr(self.fan2_norm))
            _log.debug("Normal minimum damper position:  " +
                       repr(self.min_damper))
            self.get_signal()

        def _pre_cpp_timer(self):
            """Schedule to run in get_signal"""
            _log.debug("Pre-cooling for CPP Event"
                       )  #pre-cool change cooling set point
            self._pre_csp()
            self.pre_timer = self.periodic_timer(settings.pre_time,
                                                 self._pre_cpp_cooling)

        def _pre_cpp_cooling(self):
            """start pre cooling procedure"""
            self.greenlet(self._pre_csp)

        def _pre_csp(self):
            """set cooling temp set point"""
            try:
                voltron_data = self._get_new_data()
            except green.Timeout:
                self._time_out()
            csp_now = float(voltron_data["ReturnAirCO2Stpt"])
            if csp_now > csp_pre and not csp < csp_pre:
                try:
                    csp = csp_now - self.cooling_slope
                    self._command_equip("ReturnAirCO2Stpt", csp)
                except green.Timeout:
                    self._time_out()
            elif csp_now <= csp_pre and not csp < csp_pre:
                try:
                    self._command_equip("ReturnAirCO2Stpt", settings.csp_pre)
                except green.Timeout:
                    self._time_out()
                self.pre_timer.cancel()

        def _accelerated_pre_cpp_timer(self):
            """if DR signal is received after normal pre"""
            _log.debug("Pre-cooling for CPP Event"
                       )  #pre-cool change cooling set point
            self._accelerated_pre_csp()
            self.pre_timer = self.periodic_timer(settings.pre_time,
                                                 self._accelerated_cpp_cooling)

        def _accelerated_cpp_cooling(self):
            """start accelerated pre-cooling"""
            self.greenlet(self._accelerated_pre_csp)

        def _accelerated_pre_csp(self):
            """set cooling temp set point"""
            _log.debug("Accelerated pre-cooling for CPP Event")
            try:
                voltron_data = self._get_new_data()
            except green.Timeout:
                self._time_out()
            csp_now = float(voltron_data["ReturnAirCO2Stpt"])
            csp = csp_now - self.accel_slope
            if csp_now > csp_pre and not csp < csp_pre:
                try:
                    self._command_equip("ReturnAirCO2Stpt", csp)
                except green.Timeout:
                    self._time_out()
            elif csp_now <= csp_pre or csp < csp_pre:
                try:
                    self._command_equip("ReturnAirCO2Stpt", settings.csp_pre)
                except green.Timeout:
                    self._time_out()
                self.pre_timer.cancel()

        def _during_cpp_timer(self):
            """during CPP scheduled in get_signal"""
            self.greenlet(self._during_cpp)

        def _during_cpp(self):
            """start CPP procedure"""
            # remove when done testing
            _log.debug("During CPP Event")
            damper_cpp = settings.damper_cpp
            fan_reduction = settings.fan_reduction
            csp_cpp = settings.csp_cpp
            cpp_fan1 = self.fan1_norm - self.fan1_norm * fan_reduction
            cpp_fan2 = self.fan2_norm - self.fan2_norm * fan_reduction
            try:
                self._command_equip("CoolSupplyFanSpeed1", cpp_fan1)
                self._command_equip("CoolSupplyFanSpeed2", cpp_fan2)
                self._command_equip("ReturnAirCO2Stpt", csp_cpp)
                self._command_equip('ESMDamperMinPosition', damper_cpp)
            except green.Timeout:
                self._time_out()

        def _after_cpp_timer(self):
            """after CPP scheduled in get_signal"""
            self.greenlet(self._restore_fan_damper)
            _log.debug("After CPP Event, returning to normal operations")
            self.greenlet(self._restore_cooling_setpoint)
            timer = settings.after_time
            self.after_timer = self.periodic_timer(timer,
                                                   self._after_cpp_cooling)

        def _after_cpp_cooling(self):
            """Start after CPP procedure"""
            _log.debug("After_CPP_COOLING")
            self.greenlet(self._restore_cooling_setpoint)

        def _restore_fan_damper(self):
            """restore original fan speeds"""
            try:
                self._command_equip("ESMDamperMinPosition", self.min_damper)
                self._command_equip("CoolSupplyFanSpeed1", self.fan1_norm)
                self._command_equip("CoolSupplyFanSpeed2", self.fan2_norm)
            except green.Timeout:
                self._time_out()

        def _restore_cooling_setpoint(self):
            """restore normal cooling temp setpoint"""
            try:
                voltron_data = self._get_new_data()
            except green.Timeout:
                self._time_out()
            csp_now = float(voltron_data["ReturnAirCO2Stpt"])
            if csp_now > self.csp_norm:
                csp = csp_now - self.cooling_slope
                try:
                    self._command_equip("ReturnAirCO2Stpt", csp)
                except green.Timeout:
                    self._time_out()
            elif csp_now <= self.csp_norm:
                self.after_timer.cancel()
                try:
                    self._command_equip("ReturnAirCO2Stpt", self.csp_norm)
                    self._sleep(60)
                    self.running = False
                except green.Timeout:
                    self._time_out()

        def periodic_timer(self, *args, **kwargs):
            timer = super(Agent, self).periodic_timer(*args, **kwargs)
            self.timers.append(timer)
            return timer

        def schedule(self, time, event):
            super(Agent, self).schedule(time, event)
            self.timers.append(event)

        def greenlet(self, *args, **kwargs):
            task = greenlet.greenlet(*args, **kwargs)
            self.tasks.append(task)
            current = greenlet.getcurrent()
            if current.parent is not None:
                task.parent = current.parent
            task.switch()

        def get_signal(self):
            """get and format DR signal and schedule DR proc."""
            time_now = time.mktime(datetime.datetime.now().timetuple())
            time_pre = time.mktime(
                datetime.datetime.now().replace(hour=settings.pre_cpp_hour,
                                                minute=0,
                                                second=0,
                                                microsecond=0).timetuple())
            time_event = time.mktime(datetime.datetime.now().replace(
                hour=settings.during_cpp_hour,
                minute=12,
                second=0,
                microsecond=0).timetuple())
            time_after = time.mktime(datetime.datetime.now().replace(
                hour=settings.after_cpp_hour,
                minute=14,
                second=0,
                microsecond=0).timetuple())

            if (settings.signal and time_now < time_pre):
                _log.debug("Scheduling1")
                time_step = settings.pre_time / 3600
                #self.cooling_slope = (self.csp_norm - settings.csp_pre) / ((((time_event - time_pre) / 3600) - 0.5) * time_step)
                self.cooling_slope = 1  # for testing use a constant
                temp = ((time_event - time_pre) / 3600)
                _log.debug("cooling slope: " + repr(self.cooling_slope))
                self.schedule(time_pre, sched.Event(self._pre_cpp_timer))
                self.schedule(time_event, sched.Event(self._during_cpp_timer))
                after_cpp_time = datetime.datetime.now().replace(
                    hour=settings.after_cpp_hour,
                    minute=59,
                    second=0,
                    microsecond=0)
                self.schedule(time_after, sched.Event(self._after_cpp_timer))
                #self.start_timer.cancel()
            elif (settings.signal and time_now > time_pre
                  and time_now < time_event):
                _log.debug("Scheduling2")
                #self.start_timer.cancel()
                #self.accel_slope = (self.csp_norm - settings.csp_pre) / ((time_event - time_now) / (3600))
                self.accel_slope = 2  #for testing use a constant
                #self.cooling_slope = (self.csp_norm - settings.csp_pre) / ((((time_event - time_pre) / 3600) - 0.5) * time_step)
                self.cooling_slope = 1  # for testing use a constant
                self.schedule(time_event, sched.Event(self._during_cpp_timer))
                self.schedule(time_after, sched.Event(self._after_cpp_timer))
                self._accelerated_pre_cpp_timer()
            elif (settings.signal and time_now > time_event
                  and time_now < time_after):
                _log.debug("Too late to pre-cool!")
                #self.start_timer.cancel()
                self.schedule(time_after, sched.Event(self._after_cpp_timer))
                self._during_cpp()
            else:
                _log.debug("CPP Event Is Over")
                #self.start_timer.cancel()
                self._sleep(60)
                self.get_signal()