API Call Service returns states changed

This commit is contained in:
Paulus Schoutsen 2014-12-14 00:35:16 -08:00
parent b091e9c31c
commit 5e8673fc4a
7 changed files with 72 additions and 43 deletions

View file

@ -370,13 +370,29 @@ optional body: JSON encoded object that represents event_data
```
**/api/services/&lt;domain>/&lt;service>** - POST<br>
Calls a service within a specific domain.<br>
Calls a service within a specific domain. Will return when the service has been executed or 10 seconds has past, whichever comes first.<br>
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<br>

View file

@ -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)

View file

@ -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):

View file

@ -1,2 +1,2 @@
""" DO NOT MODIFY. Auto-generated by build_frontend script """
VERSION = "5c3b2dd8a63197e380e798da8b057b0a"
VERSION = "dc16db6d5f4ba9f6dbf9d88f65592184"

File diff suppressed because one or more lines are too long

View file

@ -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) {

View file

@ -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)
});
}
},