AGL Member Meeting Fall september 2016 München
José Bollo from

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 !

Then you should first ask

What is my application ?

an UI ? a service ? a client of other services ?

and ...

Where runs my application ?

on car ? on a device ? on cloud ?

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

The demo TXC is a player of openXC traces:

Writing an application for the framework :
Write the backend binding
Write the frontend application
Write the configuration and package the application
binding: Initialisation
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;
}
binding: Handling requests
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);
}
binding: Subscribing to event
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;
}
binding: Sending events
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));
}
client: Connecting
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);
} 
client: Handler
function gotVehicleSpeed(obj) {
    vspeed = Math.round(obj.data.value);
    wdgVsp.innerHTML = String(vspeed);
    gauges.speed.setValue(vspeed);
}
Packaging: config.xml
<?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 &lt;jobol@iot.bzh&gt; / Stephane Desneux &lt;sdx@iot.bzh&gt;</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>
Known application types Any of this types will use public bindings it declares to need
Packaging: building the 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
Installing and running
afm-util install txc-demo.wgt
afm-util start txc-demo@0.1
Bench using TXC-demo on board Porter

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

Bench result on board Porter
listenermaximum speedevent per sec
no listenerx79~ 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
Advantages of using framework
Conclusion

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