Skip to content
Snippets Groups Projects
Commit 568e7758 authored by clohr's avatar clohr
Browse files

Préparation de la v0.5r2

git-svn-id: https://redmine.imt-atlantique.fr/svn/xaal/code/C/trunk@1594 b32b6428-25c9-4566-ad07-03861ab6144f
parent b2e23fd3
No related branches found
No related tags found
No related merge requests found
......@@ -3,6 +3,7 @@ xaaws.o: xaaws.c xaal.h xaaws.h db.h options.h proto-http.h proto-xaal.h \
options.o: options.c options.h xaal.h
proto-http.o: proto-http.c proto-http.h xaaws.h xaal.h db.h xaagent.h \
options.h
proto-xaal.o: proto-xaal.c proto-xaal.h db.h xaal.h xaaws.h
proto-xaal.o: proto-xaal.c proto-xaal.h db.h xaal.h xaaws.h xaagent.h \
options.h
xaagent.o: xaagent.c xaal.h xaagent.h options.h db.h
db.o: db.c db.h xaal.h
......@@ -99,7 +99,7 @@ are answers in the form of json data provided REST and WebSockets API.
An Event Stream API to get informed of attributes change
- The WebSockets API:
. The "xaal" WebSockets protocol:
. The "xaal-ctl" WebSockets protocol:
Sends: pass requests to the xAAL bus like the POST API
Receive: get attributesChange from the xAAL bus
. The "xaal-dump" WebSockets protocol:
......
......@@ -29,12 +29,81 @@
#include "proto-xaal.h"
#include "db.h"
#include "xaaws.h"
#include "xaagent.h"
int callback_xaal_proto(struct lws *wsi, enum lws_callback_reasons reason,
void *user, void *in, size_t len) {
int callback_xaal_ctl(struct lws *wsi, enum lws_callback_reasons reason, void *user, void *in, size_t len) {
struct per_session_data__xaal_ctl *pss = (struct per_session_data__xaal_ctl *)user;
switch (reason) {
case LWS_CALLBACK_ESTABLISHED: {
req_t *req = (req_t *) malloc( sizeof(req_t) );
req->wsi = wsi;
TAILQ_INSERT_TAIL(&(db.attrreqs), req, entries);
pss->janswer = NULL;
pss->tok = json_tokener_new();
lws_callback_on_writable(wsi);
break; }
case LWS_CALLBACK_SERVER_WRITEABLE:
if (pss->janswer) {
if ( serve_ws_stream(wsi, pss->janswer) ) {
json_object_put(pss->janswer);
pss->janswer = NULL;
break;
} else {
lwsl_err("Can't feed WebSocket 'xaal-ctl'\n");
return -1;
}
}
break;
case LWS_CALLBACK_RECEIVE: {
struct json_object *jinput;
enum json_tokener_error jerr;
jinput = json_tokener_parse_ex(pss->tok, in, len);
jerr = json_tokener_get_error(pss->tok);
switch (jerr) {
case json_tokener_success:
if (jinput) {
if ( !ws_xAALrequest(&bus, &me, jinput) )
lwsl_err("Can't forward xAAL request from 'xaal-ctl'\n");
json_object_put(jinput);
}
json_tokener_free(pss->tok);
pss->tok = json_tokener_new();
break;
case json_tokener_continue:
break;
default:
lwsl_err("Can't read WebSocket 'xaal-ctl'. JSON error: %s\n", json_tokener_error_desc(jerr));
json_object_put(jinput);
json_tokener_free(pss->tok);
pss->tok = json_tokener_new();
}
break; }
case LWS_CALLBACK_CLOSED:
json_tokener_free(pss->tok);
break;
default:
break;
}
return 0;
}
......
......@@ -28,7 +28,13 @@ struct per_session_data__xaal_dump {
};
int callback_xaal_proto(struct lws *wsi, enum lws_callback_reasons reason, void *user, void *in, size_t len);
struct per_session_data__xaal_ctl {
struct json_object *janswer;
struct json_tokener *tok;
};
int callback_xaal_ctl(struct lws *wsi, enum lws_callback_reasons reason, void *user, void *in, size_t len);
int callback_xaal_dump(struct lws *wsi, enum lws_callback_reasons reason, void *user, void *in, size_t len);
......
var socket;
var dev_addr;
var methods;
......@@ -106,19 +107,27 @@ function send(name) {
msg.body[parameter] = methods[name].parameters[parameter].editor.getValue();
}
$.ajax({
url: "/json/send",
type: "POST",
data: JSON.stringify(msg),
contentType: "application/json",
success: reply
});
socket.send(JSON.stringify(msg));
}
$(document).ready(function() {
dev_addr = $.url().param('device');
$('#title1').append(' <em>'+dev_addr+'</em>');
socket = new WebSocket( "ws://" + document.domain + ':' + location.port, "xaal-ctl" );
socket.onmessage = function(event) {
var newAttr = JSON.parse(event.data);
if (newAttr.device == dev_addr) {
$.each(newAttr.attributes, function(i, attribute) {
document.getElementById(attribute.name+'_value').innerHTML = JSON.stringify(attribute.value, null, 2);
document.getElementById(attribute.name+'_date').innerHTML = attribute.date;
});
}
};
$.ajax({
url: '/json/description?device='+dev_addr,
dataType: 'json',
......@@ -140,18 +149,4 @@ $(document).ready(function() {
success: populate_methods_table
});
if (!!window.EventSource) {
var source = new EventSource('/json/attributesChange');
source.onmessage = function(event) {
var newAttr = JSON.parse(event.data);
if (newAttr.device == dev_addr) {
$.each(newAttr.attributes, function(i, attribute) {
document.getElementById(attribute.name+'_value').innerHTML = JSON.stringify(attribute.value, null, 2);
document.getElementById(attribute.name+'_date').innerHTML = attribute.date;
});
}
};
}
});
var dev_addr;
var methods;
function populate_device_table(device) {
if ('address' in device)
$('#address').html(device.address);
if ('devType' in device)
$('#devType').html('<a href="/schema.html?devType='+device.devType+'">'+device.devType+'</a>');
if ('vendorId' in device)
$('#vendorId').html(device.vendorId);
if ('productId' in device)
$('#productId').html(device.productId);
if ('hwId' in device)
$('#hwId').append($('<pre/>').html(JSON.stringify(device.hwId)));
if ('version' in device)
$('#version').html(device.version);
if ('groupId' in device)
$('#groupId').html('<a href="/device.html?groupId='+device.groupId+'">'+device.groupId+'</a>');
if ('url' in device)
$('#url').html('<a href="'+device.url+'">'+device.url+'</a>');
if ('info' in device)
$('#info').html(device.info);
if ('timeout' in device)
$('#timeout').html(device.timeout);
if ('unsupportedAttributes' in device)
$('#unsupportedAttributes').append($('<pre/>').html(JSON.stringify(device.unsupportedAttributes)));
if ('unsupportedMethods' in device)
$('#unsupportedMethods').append($('<pre/>').html(JSON.stringify(device.unsupportedMethods)));
if ('unsupportedNotifications' in device)
$('#unsupportedNotifications').append($('<pre/>').html(JSON.stringify(device.unsupportedNotifications)));
$.ajax({
url: '/json/map?device='+device.address,
dataType: 'json',
data: null,
success: function(map){
$.each(map, function(key, value) {
if (key)
$('#map').append(' ');
$('#map').append('<a href="/index.html?map='+key+'">'+key+'</a>'+':"'+value+'"');
});
}
});
};
function populate_attributes_table(attributes){
$.each(attributes, function(i, attribute) {
$('#attributes').append($('<tr/>')
.append($('<td/>').html(attribute.name))
.append($('<td/>').append($('<pre/>').html(JSON.stringify(attribute.type, null, 2))))
.append($('<td/>').append($('<pre/>').html(JSON.stringify(attribute.value, null, 2)).attr('id', attribute.name+'_value')))
.append($('<td/>').html(attribute.unit))
.append($('<td/>').html(attribute.description))
.append($('<td/>').html(attribute.date).attr('id', attribute.name+'_date'))
);
});
};
function populate_methods_table(data) {
methods = data;
$.each(methods, function(name, method) {
var parameters_layout = $('<p/>');
for (parameter in method.parameters)
if (method.parameters[parameter].direction != 'out')
parameters_layout.append($('<div id="'+name+'_'+parameter+'"/>'));
$('#methods').append($('<tr/>')
.append($('<td/>').html('<button id="'+name+'" onClick="send(this.id)">'+name+'</button>'))
.append($('<td/>').html(method.description))
.append($('<td/>').html(parameters_layout))
);
for (parameter in method.parameters)
if (method.parameters[parameter].direction != 'out') {
method.parameters[parameter].type.title = parameter;
method.parameters[parameter].editor =
new JSONEditor(document.getElementById(name+'_'+parameter),
{schema: method.parameters[parameter].type,
disable_collapse: true,
theme: 'bootstrap2'});
}
});
};
function reply(data) {
//alert(JSON.stringify(data));
}
function send(name) {
var msg = { header: { targets:[dev_addr], action:name } };
if ('parameters' in methods[name])
for (parameter in methods[name].parameters)
if ('editor' in methods[name].parameters[parameter]) {
if (!('body' in msg)) msg.body = {};
msg.body[parameter] = methods[name].parameters[parameter].editor.getValue();
}
$.ajax({
url: "/json/send",
type: "POST",
data: JSON.stringify(msg),
contentType: "application/json",
success: reply
});
}
$(document).ready(function() {
dev_addr = $.url().param('device');
$('#title1').append(' <em>'+dev_addr+'</em>');
$.ajax({
url: '/json/description?device='+dev_addr,
dataType: 'json',
data: null,
success: populate_device_table
});
$.ajax({
url: '/json/attributes?device='+dev_addr,
dataType: 'json',
data: null,
success: populate_attributes_table
});
$.ajax({
url: '/json/methods?device='+dev_addr,
dataType: 'json',
data: null,
success: populate_methods_table
});
if (!!window.EventSource) {
var source = new EventSource('/json/attributesChange');
source.onmessage = function(event) {
var newAttr = JSON.parse(event.data);
if (newAttr.device == dev_addr) {
$.each(newAttr.attributes, function(i, attribute) {
document.getElementById(attribute.name+'_value').innerHTML = JSON.stringify(attribute.value, null, 2);
document.getElementById(attribute.name+'_date').innerHTML = attribute.date;
});
}
};
}
});
......@@ -731,6 +731,42 @@ struct json_object *post_xAALrequest(const xAAL_businfo_t *bus, const xAAL_devin
}
/* Send an xAAL request given by the WebSocket API */
bool ws_xAALrequest(const xAAL_businfo_t *bus, const xAAL_devinfo_t *me, json_object *jinput) {
struct json_object *jheader, *jtargets, *jtarget, *jaction, *jbody, *janswer;
const char *action;
int sz, i;
if ( !json_object_object_get_ex(jinput, "header", &jheader)
|| !json_object_is_type(jheader, json_type_object)
|| !json_object_object_get_ex(jheader, "action", &jaction)
|| !json_object_is_type(jaction, json_type_string)
|| !json_object_object_get_ex(jheader, "targets", &jtargets)
|| !json_object_is_type(jtargets, json_type_array) ) {
json_object_put(jinput);
return false;
}
action = json_object_get_string(jaction);
if (!validate_method(action)) {
json_object_put(jinput);
return false;
}
sz = json_object_array_length(jtargets);
for (i = 0; i < sz; i++) {
jtarget = json_object_array_get_idx(jtargets, i);
if ( !json_object_is_type(jtarget, json_type_string)
|| !validate_addr(json_object_get_string(jtarget)) ) {
json_object_put(jinput);
return false;
}
}
json_object_object_get_ex(jinput, "body", &jbody);
return xAAL_write_bus(bus, me, "request", action, jbody, jtargets);
}
......
......@@ -41,6 +41,9 @@ void callback_checking(const xAAL_businfo_t *bus, const xAAL_devinfo_t *me, db_t
/* Send an xAAL request given by the web API */
struct json_object *post_xAALrequest(const xAAL_businfo_t *bus, const xAAL_devinfo_t *me, char *msg, size_t len);
/* Send an xAAL request given by the WebSocket API */
bool ws_xAALrequest(const xAAL_businfo_t *bus, const xAAL_devinfo_t *me, json_object *jinput);
/* Feed http stream and web sockets with interesting data from xAAL */
void streams_feed(reqs_t *reqs, json_object *jobj);
......
......@@ -62,6 +62,7 @@ xAAL_devinfo_t me;
/* list of supported protocols and callbacks */
static struct lws_protocols protocols[] = {
{ "http-only", callback_http, sizeof(struct per_session_data__http), 0 },
{ "xaal-ctl", callback_xaal_ctl, sizeof(struct per_session_data__xaal_ctl), 0 },
{ "xaal-dump", callback_xaal_dump, sizeof(struct per_session_data__xaal_dump), 0 },
{ NULL, NULL, 0, 0 }
};
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment