From 5e8673fc4a38dafd69b9e914a5516bd20571626c Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Sun, 14 Dec 2014 00:35:16 -0800 Subject: [PATCH] API Call Service returns states changed --- README.md | 24 +++++++++-- homeassistant/components/__init__.py | 2 +- homeassistant/components/http/__init__.py | 7 +-- homeassistant/components/http/frontend.py | 2 +- .../components/http/www_static/frontend.html | 4 +- .../polymer/home-assistant-api.html | 43 +++++++++++-------- .../http/www_static/polymer/state-card.html | 33 +++++++------- 7 files changed, 72 insertions(+), 43 deletions(-) diff --git a/README.md b/README.md index 26b9460e53a..4693ec92d6d 100644 --- a/README.md +++ b/README.md @@ -370,13 +370,29 @@ optional body: JSON encoded object that represents event_data ``` **/api/services/<domain>/<service>** - POST
-Calls a service within a specific domain.
+Calls a service within a specific domain. Will return when the service has been executed or 10 seconds has past, whichever comes first.
optional body: JSON encoded object that represents service_data +Returns a list of states that have changed since the start of this service call. + ```json -{ - "message": "Service keyboard/volume_up called." -} +[ + { + "attributes": { + "next_rising": "07:04:15 29-10-2013", + "next_setting": "18:00:31 29-10-2013" + }, + "entity_id": "sun.sun", + "last_changed": "23:24:33 28-10-2013", + "state": "below_horizon" + }, + { + "attributes": {}, + "entity_id": "process.Dropbox", + "last_changed": "23:24:33 28-10-2013", + "state": "on" + } +] ``` **/api/event_forwarding** - POST
diff --git a/homeassistant/components/__init__.py b/homeassistant/components/__init__.py index 0680b5c67af..6720ae2a2d9 100644 --- a/homeassistant/components/__init__.py +++ b/homeassistant/components/__init__.py @@ -96,7 +96,7 @@ def setup(hass, config): # ent_ids is a generator, convert it to a list. data[ATTR_ENTITY_ID] = list(ent_ids) - hass.services.call(domain, service.service, data) + hass.services.call(domain, service.service, data, True) hass.services.register(ha.DOMAIN, SERVICE_TURN_OFF, handle_turn_service) hass.services.register(ha.DOMAIN, SERVICE_TURN_ON, handle_turn_service) diff --git a/homeassistant/components/http/__init__.py b/homeassistant/components/http/__init__.py index 5bb139b2123..a50ed7c9845 100644 --- a/homeassistant/components/http/__init__.py +++ b/homeassistant/components/http/__init__.py @@ -86,7 +86,7 @@ import homeassistant as ha from homeassistant.const import ( SERVER_PORT, URL_API, URL_API_STATES, URL_API_EVENTS, URL_API_SERVICES, URL_API_EVENT_FORWARD, URL_API_STATES_ENTITY, AUTH_HEADER) -from homeassistant.helpers import validate_config +from homeassistant.helpers import validate_config, TrackStates import homeassistant.remote as rem import homeassistant.util as util from . import frontend @@ -484,9 +484,10 @@ class RequestHandler(SimpleHTTPRequestHandler): domain = path_match.group('domain') service = path_match.group('service') - self.server.hass.services.call(domain, service, data, True) + with TrackStates(self.server.hass) as changed_states: + self.server.hass.services.call(domain, service, data, True) - self._json_message("Service {}/{} called.".format(domain, service)) + self._write_json(changed_states) # pylint: disable=invalid-name def _handle_post_api_event_forward(self, path_match, data): diff --git a/homeassistant/components/http/frontend.py b/homeassistant/components/http/frontend.py index 2feb9bc20fc..af8b97f120c 100644 --- a/homeassistant/components/http/frontend.py +++ b/homeassistant/components/http/frontend.py @@ -1,2 +1,2 @@ """ DO NOT MODIFY. Auto-generated by build_frontend script """ -VERSION = "5c3b2dd8a63197e380e798da8b057b0a" +VERSION = "dc16db6d5f4ba9f6dbf9d88f65592184" diff --git a/homeassistant/components/http/www_static/frontend.html b/homeassistant/components/http/www_static/frontend.html index ab03282f023..93dcefa6fb6 100644 --- a/homeassistant/components/http/www_static/frontend.html +++ b/homeassistant/components/http/www_static/frontend.html @@ -61,11 +61,11 @@ if(this.removeAttribute(a),d)return j(this,a,c);var e=c,f=m(this,a,e);return j(t {{stateObj.entityDisplay}}
{{lastChangedFromNow(stateObj.last_changed)}} -
diff --git a/homeassistant/components/http/www_static/polymer/home-assistant-api.html b/homeassistant/components/http/www_static/polymer/home-assistant-api.html index 6f10dbaa84c..3bccf223179 100644 --- a/homeassistant/components/http/www_static/polymer/home-assistant-api.html +++ b/homeassistant/components/http/www_static/polymer/home-assistant-api.html @@ -139,6 +139,12 @@ this.fire('states-updated'); }, + _pushNewStates: function(new_states) { + new_states.map(function(state) { + this._pushNewState(state); + }.bind(this)); + }, + // call api methods fetchAll: function() { this.fetchStates(); @@ -205,19 +211,14 @@ "GET", "services", null, successServicesUpdated.bind(this), onError); }, - turn_on: function(entity_id) { - // we call the turn_on method on the domain of the entity_id - // because the call to homeassistant.turn_on does not wait - // till the call is done. - var parts = entity_id.split("."); - - this.call_service(parts[0], "turn_on", {entity_id: entity_id}); + turn_on: function(entity_id, options) { + this.call_service( + "homeassistant", "turn_on", {entity_id: entity_id}, options); }, - turn_off: function(entity_id) { - var parts = entity_id.split("."); - - this.call_service(parts[0], "turn_off", {entity_id: entity_id}); + turn_off: function(entity_id, options) { + this.call_service( + "homeassistant", "turn_off", {entity_id: entity_id}, options); }, set_state: function(entity_id, state, attributes) { @@ -236,10 +237,11 @@ payload, successToast.bind(this)); }, - call_service: function(domain, service, parameters) { + call_service: function(domain, service, parameters, options) { parameters = parameters || {}; + options = options || {}; - var successToast = function() { + var successHandler = function(changed_states) { if(service == "turn_on" && parameters.entity_id) { this.showToast("Turned on " + parameters.entity_id + '.'); } else if(service == "turn_off" && parameters.entity_id) { @@ -248,14 +250,21 @@ this.showToast("Service "+domain+"/"+service+" called."); } - // if we call a service on an entity_id, update the state - if(parameters && parameters.entity_id) { - this.fetchStates(); + this._pushNewStates(changed_states); + + if(options.success) { + options.success(); + } + }; + + var errorHandler = function(error_data) { + if(options.error) { + options.error(error_data); } }; this.call_api("POST", "services/" + domain + "/" + service, - parameters, successToast.bind(this)); + parameters, successHandler.bind(this), errorHandler); }, fire_event: function(eventType, eventData) { diff --git a/homeassistant/components/http/www_static/polymer/state-card.html b/homeassistant/components/http/www_static/polymer/state-card.html index c7656e3787a..8b0be4dc076 100755 --- a/homeassistant/components/http/www_static/polymer/state-card.html +++ b/homeassistant/components/http/www_static/polymer/state-card.html @@ -139,31 +139,34 @@ }, stateChanged: function(oldVal, newVal) { - this.stateUnknown = newVal === null; this.toggleChecked = newVal === "on"; }, turn_on: function() { + // We call stateChanged after a successful call to re-sync the toggle + // with the state. It will be out of sync if our service call did not + // result in the entity to be turned on. Since the state is not changing, + // the resync is not called automatic. if(this.cb_turn_on) { - this.cb_turn_on(this.stateObj.entity_id); - - // unset state while we wait for an update - var delayUnsetSate = function() { - this.stateObj.state = null; - }; - setTimeout(delayUnsetSate.bind(this), 500); + this.cb_turn_on(this.stateObj.entity_id, { + success: function() { + this.stateChanged(this.stateObj.state, this.stateObj.state); + }.bind(this) + }); } }, turn_off: function() { + // We call stateChanged after a successful call to re-sync the toggle + // with the state. It will be out of sync if our service call did not + // result in the entity to be turned on. Since the state is not changing, + // the resync is not called automatic. if(this.cb_turn_off) { - this.cb_turn_off(this.stateObj.entity_id); - - // unset state while we wait for an update - var delayUnsetSate = function() { - this.stateObj.state = null; - }; - setTimeout(delayUnsetSate.bind(this), 500); + this.cb_turn_off(this.stateObj.entity_id, { + success: function() { + this.stateChanged(this.stateObj.state, this.stateObj.state); + }.bind(this) + }); } },