class Schedule(CompositeNode,EventProducerMixin): def __init__(self): CompositeNode.__init__(self) EventProducerMixin.__init__(self) self._schedule_lock = Lock() self._schedule_condition = Condition() self._value_lock = Lock() self._value_condition = Condition() self.__schedule = None self.__value = None def configure(self,config): CompositeNode.configure(self,config) def configuration(self): config = CompositeNode.configuration(self) return config def start(self): CompositeNode.start(self) def stop(self): CompositeNode.stop(self) def set_schedule(self,client,schedule): self._schedule_lock.acquire() self._schedule_condition.acquire() try: self.__schedule = schedule self._schedule_condition.notifyAll() finally: self._schedule_lock.release() self._schedule_condition.release() self.event_generate(ScheduleChangedEvent(client,schedule)) def get_schedule(self): self._schedule_lock.acquire() try: schedule = self.__schedule finally: self._schedule_lock.release() if isinstance(schedule,Exception): raise schedule return schedule ## # @param schedule Schedule client believes to be current. def get_next_schedule(self,schedule,timeout=None): self._schedule_lock.acquire() try: if schedule is not self.__schedule: return self.__schedule self._schedule_condition.acquire() finally: self._schedule_lock.release() try: self._schedule_condition.wait(timeout) schedule = self.__schedule finally: self._schedule_condition.release() if isinstance(schedule,Exception): raise schedule return schedule def is_schedule_current(self,schedule): self._schedule_lock.acquire() try: changed = not schedule is self.__schedule finally: self._schedule_lock.release() return changed def _set(self,value): self._value_lock.acquire() self._value_condition.acquire() try: old = self.__value self.__value = value self._value_condition.notifyAll() finally: self._value_lock.release() self._value_condition.release() if old != value: self.event_generate(ChangeOfValueEvent(self,old,value)) def get(self, skipCache=0): self._value_lock.acquire() try: value = self.__value finally: self._value_lock.release() return value def get_next_value(self,value,timeout=None): self._value_lock.acquire() try: if value != self.__value: return self.__value self._value_condition.acquire() finally: self._value_lock.release() try: self._value_condition.wait(timeout) value = self.__value finally: self._value_condition.release() return value def is_value_current(self,value): self._value_lock.acquire() try: changed = not value == self.__value finally: self._value_lock.release() return changed
class Schedule(CompositeNode, EventProducerMixin): def __init__(self): CompositeNode.__init__(self) EventProducerMixin.__init__(self) self._schedule_lock = Lock() self._schedule_condition = Condition() self._value_lock = Lock() self._value_condition = Condition() self.__schedule = None self.__value = None def configure(self, config): CompositeNode.configure(self, config) def configuration(self): config = CompositeNode.configuration(self) return config def start(self): CompositeNode.start(self) def stop(self): CompositeNode.stop(self) def set_schedule(self, client, schedule): self._schedule_lock.acquire() self._schedule_condition.acquire() try: self.__schedule = schedule self._schedule_condition.notifyAll() finally: self._schedule_lock.release() self._schedule_condition.release() self.event_generate(ScheduleChangedEvent(client, schedule)) def get_schedule(self): self._schedule_lock.acquire() try: schedule = self.__schedule finally: self._schedule_lock.release() if isinstance(schedule, Exception): raise schedule return schedule ## # @param schedule Schedule client believes to be current. def get_next_schedule(self, schedule, timeout=None): self._schedule_lock.acquire() try: if schedule is not self.__schedule: return self.__schedule self._schedule_condition.acquire() finally: self._schedule_lock.release() try: self._schedule_condition.wait(timeout) schedule = self.__schedule finally: self._schedule_condition.release() if isinstance(schedule, Exception): raise schedule return schedule def is_schedule_current(self, schedule): self._schedule_lock.acquire() try: changed = not schedule is self.__schedule finally: self._schedule_lock.release() return changed def _set(self, value): self._value_lock.acquire() self._value_condition.acquire() try: old = self.__value self.__value = value self._value_condition.notifyAll() finally: self._value_lock.release() self._value_condition.release() if old != value: self.event_generate(ChangeOfValueEvent(self, old, value)) def get(self, skipCache=0): self._value_lock.acquire() try: value = self.__value finally: self._value_lock.release() return value def get_next_value(self, value, timeout=None): self._value_lock.acquire() try: if value != self.__value: return self.__value self._value_condition.acquire() finally: self._value_lock.release() try: self._value_condition.wait(timeout) value = self.__value finally: self._value_condition.release() return value def is_value_current(self, value): self._value_lock.acquire() try: changed = not value == self.__value finally: self._value_lock.release() return changed
class LightPoint(CompositeNode, EventProducerMixin): def __init__(self): self.__group = None self._value = None self._old_value = None self._last_update = 0 self.__cv = Condition() super(LightPoint, self).__init__() EventProducerMixin.__init__(self) def configure(self, cd): super(LightPoint, self).configure(cd) set_attribute(self, 'lightpoint_id', REQUIRED, cd, int) set_attribute(self, 'timeout', 2, cd, int) #relay number 5 actuates lights set_attribute(self, 'relay_num', 5, cd, int) def configuration(self): cd = super(LightPoint, self).configuration() get_attribute(self, 'lightpoint_id', cd) get_attribute(self, 'timeout', cd) get_attribute(self, 'relay_num', cd) return cd def start(self): self.parent.parent.register(self) super(LightPoint, self).start() def get(self, skipCache=0): rslt = self._value # cache miss if (uptime.secs() - self._last_update) > self.group.ttl: # motes periodically push updates - if it's been silent for # too long force an update. @fixme: the first read will still # return stale data - add blocking call and ETimeout logic last = self._last_update self.__cv.acquire() try: try: self._force_update() except: # an error using the XCommand interface occured # raise an exception but do not cache the ETimeout msglog.exception() raise ETimeout() self.__cv.wait(self.timeout) if last != self._last_update: # an update has occurred rslt = self._value else: self._last_update = uptime.secs() # let ETimeouts affect our value caching as well, # if a better update comes from the mesh, great. rslt = self._value = ETimeout() finally: self.__cv.release() if isinstance(rslt, ETimeout): raise rslt return rslt def set(self, value): value = int(value) if value < 0 or value > 1: raise EInvalidValue() self.group.server.actuate(self.lightpoint_id, self.relay_num, value) def has_cov(self): return 1 def event_subscribe(self, *args): super(LightPoint, self).event_subscribe(self, *args) self._old_value = self.get() # generate initial event self.event_generate(ChangeOfValueEvent(self, self._old_value, self._old_value, time.time())) def _force_update(self): ACTION_NONE = 2 self.group.server.actuate(self.lightpoint_id, self.relay_num, ACTION_NONE) def update(self, data): self.__cv.acquire() try: self._old_value = self._value self._value = data.get('relayState1') self._last_update = uptime.secs() self.__cv.notifyAll() self.event_generate(ChangeOfValueEvent(self, self._old_value, self._value, time.time())) finally: self.__cv.release() def __get_group(self): if self.__group is None: self.__group = self.parent return self.__group group = property(__get_group)