Your browser doesn't support the features required by impress.js, so you are presented with a simplified version of this presentation.
For the best experience please use the latest Chrome, Safari or Firefox browser.
Building Applications with AGL Framework
José Bollo
AGL Member Meeting Fall
September 7 - 8, 2016
Munich, Germany
Aren’t you just hungry to bring your application inside AGL ?
Get the right tools !
an UI ? a service ? a client of other services ?
on car ? on a device ? on cloud ?
The connection between the frontend and backend is either:
The connection between the backend and services or between services are either:
How to connect?
HTTP? HTTPS? DBUS?
WS? WSS? UDS? Denso's Service Bus? ...
Who knows?
The framework knows!
It knows:
The AGL framework (AF) is made of 2 parts:
Agl Framework - MAIN
af-main
Agl Framework - BINDER
af-binder
af-main: the main environment and utilities
af-binder: the backend binder
illustration
The demo TXC is a player of openXC traces:
static const struct afb_verb_desc_v1 verbs[]= {
{"start", AFB_SESSION_CHECK, start , "start to play a trace"},
{"stop", AFB_SESSION_CHECK, stop , "stop to play a trace"},
{"subscribe", AFB_SESSION_CHECK, subscribe , "subscribes to the event of 'name'"},
{"unsubscribe",AFB_SESSION_CHECK, unsubscribe , "unsubscribes to the event of 'name'"},
{NULL}
};
static const struct afb_binding plugin_desc = {
.type = AFB_BINDING_VERSION_1,
.v1 = {
.info = "trace openXC service",
.prefix = "txc",
.verbs = verbs
}
};
const struct afb_binding *afbBindingV1Register (const struct afb_binding_interface *itf) {
afbitf = itf;
return &plugin_desc;
}
static void subscribe_unsubscribe(struct afb_req request, int subscribe) {
int ok, i, n; struct json_object *args, *a, *x;
/* makes the subscription/unsubscription */
args = afb_req_json(request);
if (args == NULL || !json_object_object_get_ex(args, "event", &a)) {
ok = subscribe_unsubscribe_all(request, subscribe);
} else if (json_object_get_type(a) != json_type_array) {
ok = subscribe_unsubscribe_name(request, subscribe, json_object_get_string(a));
} else {
ok = subscribe_unsubscribe_array(request, subscribe, a);
}
/* send the report */
if (ok)
afb_req_success(request, NULL, NULL);
else
afb_req_fail(request, "error", NULL);
}
static void subscribe(struct afb_req request) {
subscribe_unsubscribe(request, 1);
}
static void unsubscribe(struct afb_req request) {
subscribe_unsubscribe(request, 0);
}
struct signal {
const char *name;
struct afb_event event;
};
static int subscribe_unsubscribe_sig(struct afb_req request, int subscribe, struct signal *sig) {
if (!afb_event_is_valid(sig->event)) {
if (!subscribe)
return 1;
sig->event = afb_daemon_make_event(afbitf->daemon, sig->name);
if (!afb_event_is_valid(sig->event)) {
return 0;
}
}
if (subscribe)
return afb_req_subscribe(request, sig->event) >= 0;
else
return afb_req_unsubscribe(request, sig->event) >= 0;
}
static void send_trace(const char *name, struct json_object *object) {
struct signal *sig = getsig(name);
if (sig && afb_event_is_valid(sig->event))
afb_event_push(sig->event, json_object_get(object));
}
function onOpen() {
ws.call("txc/subscribe", {event:[
"engine_speed",
"fuel_level",
"fuel_consumed_since_restart",
"longitude",
"latitude",
"odometer",
"vehicle_speed",
"START",
"STOP"]}, onSubscribed, onAbort);
ws.call("stat/subscribe", true);
ws.onevent("stat/stat", gotStat);
}
function doConnect() {
document.body.className = "connecting";
setMapsLockState(false);
ws = new afb.ws(onOpen, onAbort);
}
function onSubscribed() {
document.body.className = "connected";
setMapsLockState(false);
ws.onevent("txc/engine_speed", gotEngineSpeed);
ws.onevent("txc/fuel_level", gotFuelLevel);
ws.onevent("txc/fuel_consumed_since_restart", gotFuelSince);
ws.onevent("txc/longitude", gotLongitude);
ws.onevent("txc/latitude", gotLatitude);
ws.onevent("txc/odometer", gotOdometer);
ws.onevent("txc/vehicle_speed", gotVehicleSpeed);
ws.onevent("txc/START", gotStart);
ws.onevent("txc/STOP", gotStop);
ws.onevent("txc", gotAny);
}
function gotVehicleSpeed(obj) {
vspeed = Math.round(obj.data.value);
wdgVsp.innerHTML = String(vspeed);
gauges.speed.setValue(vspeed);
}
<?xml version="1.0" encoding="UTF-8"?>
<widget xmlns="http://www.w3.org/ns/widgets" id="txc-demo" version="0.1">
<name>OpenXC Trace Player</name>
<icon src="icon.png"/>
<content src="index.html" type="application/vnd.agl.html.hybrid"/>
<description>This is a demo using OpenXC trace</description>
<author>Jose Bollo <jobol@iot.bzh> / Stephane Desneux <sdx@iot.bzh></author>
<license>APL 2.0</license>
<feature name="urn:AGL:provides-binding">
<param name="name" value="txc"/>
<param name="src" value="lib/txc-binding.so"/>
<param name="type" value="application/vnd.agl.binding.v1"/>
<param name="scope" value="private"/>
</feature>
<feature name="urn:AGL:provides-binding">
<param name="name" value="stat"/>
<param name="src" value="lib/stat-binding.so"/>
<param name="type" value="application/vnd.agl.binding.v1"/>
<param name="scope" value="private"/>
</feature>
</widget>
mkdir -p package/lib
gulp widget-config-prod
cp -a dist.prod package/htdocs
cp icon_hybrid_html5_128.png package/icon.png
mv package/htdocs/config.xml package/
cp -a data package/
cp *.so package/lib
wgtpkg-pack -f -o txc-demo.wgt package
afm-util install txc-demo.wgt
afm-util start txc-demo@0.1
1) The file nyc-downtown-crosstown.json has an average of 424 events per second
2) A 500kbps one CAN bus can send up to an average of 9000 messages (events) per second
3) txc-demo can play traces accelerated
then) playing the file at speed x21 (near 9000 divided by 424) represent a CAN bus at full speed
listener | maximum speed | event per sec |
---|---|---|
no listener | x79 | ~ 33500 |
1 listener in same process | ~ x60 | ~ 25400 |
1 listener WS | ~ x35 | ~ 14800 |
1 listener DBUS | ~ x15 | ~ 6300 |
3 listeners WS | ~ x12 | ~ 5100 |
3 listeners DBUS | ~ x6 | ~ 2500 |
The framework is integrated in AGL 2.0.
Take it, use it, try to break it
Give feedback and send request for improvements
Use a spacebar or arrow keys to navigate