More improvements to State

This commit is contained in:
Paulus Schoutsen 2014-01-22 19:40:19 -08:00
parent 7c15e24d09
commit 659f185252
4 changed files with 34 additions and 31 deletions

View File

@ -62,7 +62,7 @@ def start_home_assistant(bus):
def _process_match_param(parameter): def _process_match_param(parameter):
""" Wraps parameter in a list if it is not one and returns it. """ """ Wraps parameter in a list if it is not one and returns it. """
if parameter is None: if not parameter:
return MATCH_ALL return MATCH_ALL
elif isinstance(parameter, list): elif isinstance(parameter, list):
return parameter return parameter
@ -290,14 +290,18 @@ class Bus(object):
class State(object): class State(object):
""" Object to represent a state within the state machine. """ """ Object to represent a state within the state machine. """
def __init__(self, state, attributes=None, last_changed=None): __slots__ = ['entity_id','state','attributes','last_changed']
def __init__(self, entity_id, state, attributes=None, last_changed=None):
self.entity_id = entity_id
self.state = state self.state = state
self.attributes = attributes or {} self.attributes = attributes or {}
last_changed = last_changed or dt.datetime.now() last_changed = last_changed or dt.datetime.now()
# Strip microsecond from last_changed else we cannot guarantee # Strip microsecond from last_changed else we cannot guarantee
# state == State.from_json_dict(state.to_json_dict()) # state == State.from_dict(state.as_dict())
# This behavior occurs because to_json_dict strips microseconds # This behavior occurs because to_dict uses datetime_to_str
# which strips microseconds
if last_changed.microsecond: if last_changed.microsecond:
self.last_changed = last_changed - dt.timedelta( self.last_changed = last_changed - dt.timedelta(
microseconds=last_changed.microsecond) microseconds=last_changed.microsecond)
@ -306,23 +310,20 @@ class State(object):
def copy(self): def copy(self):
""" Creates a copy of itself. """ """ Creates a copy of itself. """
return State(self.state, dict(self.attributes), self.last_changed) return State(self.entity_id, self.state,
dict(self.attributes), self.last_changed)
def to_json_dict(self, entity_id=None): def as_dict(self):
""" Converts State to a dict to be used within JSON. """ Converts State to a dict to be used within JSON.
Ensures: state == State.from_json_dict(state.to_json_dict()) """ Ensures: state == State.from_dict(state.as_dict()) """
json_dict = {'state': self.state, return {'entity_id': self.entity_id,
'attributes': self.attributes, 'state': self.state,
'last_changed': util.datetime_to_str(self.last_changed)} 'attributes': self.attributes,
'last_changed': util.datetime_to_str(self.last_changed)}
if entity_id:
json_dict['entity_id'] = entity_id
return json_dict
@staticmethod @staticmethod
def from_json_dict(json_dict): def from_dict(json_dict):
""" Static method to create a state from a dict. """ Static method to create a state from a dict.
Ensures: state == State.from_json_dict(state.to_json_dict()) """ Ensures: state == State.from_json_dict(state.to_json_dict()) """
@ -332,14 +333,15 @@ class State(object):
if last_changed: if last_changed:
last_changed = util.str_to_datetime(last_changed) last_changed = util.str_to_datetime(last_changed)
return State(json_dict['state'], return State(json_dict['entity_id'],
json_dict['state'],
json_dict.get('attributes'), json_dict.get('attributes'),
last_changed) last_changed)
except KeyError: # if key 'state' did not exist except KeyError: # if key 'state' did not exist
return None return None
def __repr__(self): def __repr__(self):
return "{}({}, {})".format( return "<state {}:{}, {}>".format(
self.state, self.attributes, self.state, self.attributes,
util.datetime_to_str(self.last_changed)) util.datetime_to_str(self.last_changed))
@ -386,22 +388,23 @@ class StateMachine(object):
except KeyError: except KeyError:
# If state did not exist yet # If state did not exist yet
self.states[entity_id] = State(new_state, attributes) self.states[entity_id] = State(entity_id, new_state,
attributes)
else: else:
if old_state.state != new_state or \ if old_state.state != new_state or \
old_state.attributes != attributes: old_state.attributes != attributes:
state = self.states[entity_id] = \
State(entity_id, new_state, attributes)
self.bus.fire_event(EVENT_STATE_CHANGED, self.bus.fire_event(EVENT_STATE_CHANGED,
{'entity_id': entity_id, {'entity_id': entity_id,
'old_state': old_state, 'old_state': old_state,
'new_state': state}) 'new_state': state})
self.states[entity_id] = State(new_state, attributes)
def get_state(self, entity_id): def get_state(self, entity_id):
""" Returns a dict (state, last_changed, attributes) describing """ Returns the state of the specified entity. """
the state of the specified entity. """
with self.lock: with self.lock:
try: try:
# Make a copy so people won't mutate the state # Make a copy so people won't mutate the state

View File

@ -514,7 +514,7 @@ class RequestHandler(BaseHTTPRequestHandler):
if self.use_json: if self.use_json:
state = self.server.statemachine.get_state(entity_id) state = self.server.statemachine.get_state(entity_id)
self._write_json(state.to_json_dict(entity_id), self._write_json(state.as_dict(),
status_code=HTTP_CREATED, status_code=HTTP_CREATED,
location= location=
URL_API_STATES_ENTITY.format(entity_id)) URL_API_STATES_ENTITY.format(entity_id))
@ -613,10 +613,10 @@ class RequestHandler(BaseHTTPRequestHandler):
state = self.server.statemachine.get_state(entity_id) state = self.server.statemachine.get_state(entity_id)
if state: try:
self._write_json(state.to_json_dict(entity_id)) self._write_json(state.as_dict())
else: except AttributeError:
# If entity_id does not exist # If state for entity_id does not exist
self._message("State does not exist.", HTTP_UNPROCESSABLE_ENTITY) self._message("State does not exist.", HTTP_UNPROCESSABLE_ENTITY)
def _handle_get_api_events(self, path_match, data): def _handle_get_api_events(self, path_match, data):

View File

@ -56,7 +56,7 @@ class JSONEncoder(json.JSONEncoder):
""" Checks if Home Assistat object and encodes if possible. """ Checks if Home Assistat object and encodes if possible.
Else hand it off to original method. """ Else hand it off to original method. """
if isinstance(obj, ha.State): if isinstance(obj, ha.State):
return obj.to_json_dict() return obj.as_dict()
return json.JSONEncoder.default(self, obj) return json.JSONEncoder.default(self, obj)
@ -270,7 +270,7 @@ class StateMachine(ha.StateMachine):
if req.status_code == 200: if req.status_code == 200:
data = req.json() data = req.json()
return ha.State.from_json_dict(data) return ha.State.from_dict(data)
elif req.status_code == 422: elif req.status_code == 422:
# Entity does not exist # Entity does not exist

View File

@ -138,7 +138,7 @@ class TestHTTPInterface(unittest.TestCase):
_url(hah.URL_API_STATES_ENTITY.format("test")), _url(hah.URL_API_STATES_ENTITY.format("test")),
data={"api_password": API_PASSWORD}) data={"api_password": API_PASSWORD})
data = ha.State.from_json_dict(req.json()) data = ha.State.from_dict(req.json())
state = self.statemachine.get_state("test") state = self.statemachine.get_state("test")