svghmi/gen_index_xhtml.xslt
branchsvghmi
changeset 2803 f48121cf31b6
parent 2802 64e6f73b9859
child 2805 e521e0d133d5
equal deleted inserted replaced
2802:64e6f73b9859 2803:f48121cf31b6
   318 </xsl:text>
   318 </xsl:text>
   319     <xsl:text>// svghmi.js
   319     <xsl:text>// svghmi.js
   320 </xsl:text>
   320 </xsl:text>
   321     <xsl:text>
   321     <xsl:text>
   322 </xsl:text>
   322 </xsl:text>
       
   323     <xsl:text>var cache = hmitree_types.map(_ignored =&gt; undefined);
       
   324 </xsl:text>
       
   325     <xsl:text>
       
   326 </xsl:text>
   323     <xsl:text>function dispatch_value(index, value) {
   327     <xsl:text>function dispatch_value(index, value) {
   324 </xsl:text>
   328 </xsl:text>
   325     <xsl:text>    let widgets = subscribers[index];
   329     <xsl:text>    let widgets = subscribers[index];
   326 </xsl:text>
   330 </xsl:text>
   327     <xsl:text>
   331     <xsl:text>
   328 </xsl:text>
   332 </xsl:text>
   329     <xsl:text>    // TODO : value cache
   333     <xsl:text>    if(widgets.size &gt; 0) {
       
   334 </xsl:text>
       
   335     <xsl:text>        for(let widget of widgets){
       
   336 </xsl:text>
       
   337     <xsl:text>            let idxidx = widget.indexes.indexOf(index);
       
   338 </xsl:text>
       
   339     <xsl:text>            if(idxidx == -1){
       
   340 </xsl:text>
       
   341     <xsl:text>                throw new Error("Dispatching to widget not interested, should not happen.");
       
   342 </xsl:text>
       
   343     <xsl:text>            }
       
   344 </xsl:text>
       
   345     <xsl:text>            let d = widget.dispatch;
       
   346 </xsl:text>
       
   347     <xsl:text>            if(typeof(d) == "function" &amp;&amp; idxidx == 0){
       
   348 </xsl:text>
       
   349     <xsl:text>                return d.call(widget,value);
       
   350 </xsl:text>
       
   351     <xsl:text>            }else if(typeof(d) == "object" &amp;&amp; d.length &gt;= idxidx){
       
   352 </xsl:text>
       
   353     <xsl:text>                d[idxidx].call(widget,value);
       
   354 </xsl:text>
       
   355     <xsl:text>            }/* else dispatch_0, ..., dispatch_n ? */
       
   356 </xsl:text>
       
   357     <xsl:text>            /*else {
       
   358 </xsl:text>
       
   359     <xsl:text>                throw new Error("Dunno how to dispatch to widget at index = " + index);
       
   360 </xsl:text>
       
   361     <xsl:text>            }*/
       
   362 </xsl:text>
       
   363     <xsl:text>        }
       
   364 </xsl:text>
       
   365     <xsl:text>    }
       
   366 </xsl:text>
       
   367     <xsl:text>
       
   368 </xsl:text>
       
   369     <xsl:text>    cache[index] = value;
   330 </xsl:text>
   370 </xsl:text>
   331     <xsl:text>    
   371     <xsl:text>    
   332 </xsl:text>
   372 </xsl:text>
   333     <xsl:text>    if(widgets.size &gt; 0) {
   373     <xsl:text>};
   334 </xsl:text>
   374 </xsl:text>
   335     <xsl:text>        for(let widget of widgets){
   375     <xsl:text>
   336 </xsl:text>
   376 </xsl:text>
   337     <xsl:text>            let idxidx = widget.indexes.indexOf(index);
   377     <xsl:text>function init_widgets() {
   338 </xsl:text>
   378 </xsl:text>
   339     <xsl:text>            if(idxidx == -1){
   379     <xsl:text>    Object.keys(hmi_widgets).forEach(function(id) {
   340 </xsl:text>
   380 </xsl:text>
   341     <xsl:text>                throw new Error("Dispatching to widget not interested, should not happen.");
   381     <xsl:text>        let widget = hmi_widgets[id];
       
   382 </xsl:text>
       
   383     <xsl:text>        let init = widget.init;
       
   384 </xsl:text>
       
   385     <xsl:text>        if(typeof(init) == "function"){
       
   386 </xsl:text>
       
   387     <xsl:text>            return init.call(widget);
       
   388 </xsl:text>
       
   389     <xsl:text>        }
       
   390 </xsl:text>
       
   391     <xsl:text>    });
       
   392 </xsl:text>
       
   393     <xsl:text>};
       
   394 </xsl:text>
       
   395     <xsl:text>
       
   396 </xsl:text>
       
   397     <xsl:text>// Open WebSocket to relative "/ws" address
       
   398 </xsl:text>
       
   399     <xsl:text>var ws = new WebSocket(window.location.href.replace(/^http(s?:\/\/[^\/]*)\/.*$/, 'ws$1/ws'));
       
   400 </xsl:text>
       
   401     <xsl:text>ws.binaryType = 'arraybuffer';
       
   402 </xsl:text>
       
   403     <xsl:text>
       
   404 </xsl:text>
       
   405     <xsl:text>const dvgetters = {
       
   406 </xsl:text>
       
   407     <xsl:text>    INT: [DataView.prototype.getInt16, 2],
       
   408 </xsl:text>
       
   409     <xsl:text>    BOOL: [DataView.prototype.getInt8, 1]
       
   410 </xsl:text>
       
   411     <xsl:text>    /* TODO */
       
   412 </xsl:text>
       
   413     <xsl:text>};
       
   414 </xsl:text>
       
   415     <xsl:text>
       
   416 </xsl:text>
       
   417     <xsl:text>// Register message reception handler 
       
   418 </xsl:text>
       
   419     <xsl:text>ws.onmessage = function (evt) {
       
   420 </xsl:text>
       
   421     <xsl:text>
       
   422 </xsl:text>
       
   423     <xsl:text>    let data = evt.data;
       
   424 </xsl:text>
       
   425     <xsl:text>    let dv = new DataView(data);
       
   426 </xsl:text>
       
   427     <xsl:text>    let i = 0;
       
   428 </xsl:text>
       
   429     <xsl:text>    //console.log("Recv something.");
       
   430 </xsl:text>
       
   431     <xsl:text>    try {
       
   432 </xsl:text>
       
   433     <xsl:text>        for(let hash_int of hmi_hash) {
       
   434 </xsl:text>
       
   435     <xsl:text>            if(hash_int != dv.getUint8(i)){
       
   436 </xsl:text>
       
   437     <xsl:text>                throw new Error("Hash doesn't match");
       
   438 </xsl:text>
       
   439     <xsl:text>            };
       
   440 </xsl:text>
       
   441     <xsl:text>            i++;
       
   442 </xsl:text>
       
   443     <xsl:text>        };
       
   444 </xsl:text>
       
   445     <xsl:text>
       
   446 </xsl:text>
       
   447     <xsl:text>        //console.log("Recv something GOOD.");
       
   448 </xsl:text>
       
   449     <xsl:text>
       
   450 </xsl:text>
       
   451     <xsl:text>        while(i &lt; data.byteLength){
       
   452 </xsl:text>
       
   453     <xsl:text>            let index = dv.getUint32(i, true);
       
   454 </xsl:text>
       
   455     <xsl:text>            //console.log("Recv something index is "+index);
       
   456 </xsl:text>
       
   457     <xsl:text>            i += 4;
       
   458 </xsl:text>
       
   459     <xsl:text>            let iectype = hmitree_types[index];
       
   460 </xsl:text>
       
   461     <xsl:text>            if(iectype != undefined){
       
   462 </xsl:text>
       
   463     <xsl:text>                let [dvgetter, bytesize] = dvgetters[iectype];
       
   464 </xsl:text>
       
   465     <xsl:text>                let value = dvgetter.call(dv,i,true);
       
   466 </xsl:text>
       
   467     <xsl:text>                dispatch_value(index, value);
       
   468 </xsl:text>
       
   469     <xsl:text>                i += bytesize;
       
   470 </xsl:text>
       
   471     <xsl:text>            } else {
       
   472 </xsl:text>
       
   473     <xsl:text>                throw new Error("Unknown index "+index)
   342 </xsl:text>
   474 </xsl:text>
   343     <xsl:text>            }
   475     <xsl:text>            }
   344 </xsl:text>
   476 </xsl:text>
   345     <xsl:text>            let d = widget.dispatch;
   477     <xsl:text>        };
   346 </xsl:text>
   478 </xsl:text>
   347     <xsl:text>            if(typeof(d) == "function" &amp;&amp; idxidx == 0){
   479     <xsl:text>    } catch(err) {
   348 </xsl:text>
   480 </xsl:text>
   349     <xsl:text>                return d.call(widget,value);
   481     <xsl:text>        // 1003 is for "Unsupported Data"
   350 </xsl:text>
   482 </xsl:text>
   351     <xsl:text>            }else if(typeof(d) == "object" &amp;&amp; d.length &gt;= idxidx){
   483     <xsl:text>        // ws.close(1003, err.message);
   352 </xsl:text>
   484 </xsl:text>
   353     <xsl:text>                d[idxidx].call(widget,value);
   485     <xsl:text>
   354 </xsl:text>
   486 </xsl:text>
   355     <xsl:text>            }/* else dispatch_0, ..., dispatch_n ? */
   487     <xsl:text>        // TODO : remove debug alert ?
   356 </xsl:text>
   488 </xsl:text>
   357     <xsl:text>            /*else {
   489     <xsl:text>        alert("Error : "+err.message+"\nHMI will be reloaded.");
   358 </xsl:text>
   490 </xsl:text>
   359     <xsl:text>                throw new Error("Dunno how to dispatch to widget at index = " + index);
   491     <xsl:text>
   360 </xsl:text>
   492 </xsl:text>
   361     <xsl:text>            }*/
   493     <xsl:text>        // force reload ignoring cache
       
   494 </xsl:text>
       
   495     <xsl:text>        location.reload(true);
       
   496 </xsl:text>
       
   497     <xsl:text>    }
       
   498 </xsl:text>
       
   499     <xsl:text>};
       
   500 </xsl:text>
       
   501     <xsl:text>
       
   502 </xsl:text>
       
   503     <xsl:text>
       
   504 </xsl:text>
       
   505     <xsl:text>function send_blob(data) {
       
   506 </xsl:text>
       
   507     <xsl:text>    if(data.length &gt; 0) {
       
   508 </xsl:text>
       
   509     <xsl:text>        ws.send(new Blob([new Uint8Array(hmi_hash)].concat(data)));
       
   510 </xsl:text>
       
   511     <xsl:text>    };
       
   512 </xsl:text>
       
   513     <xsl:text>};
       
   514 </xsl:text>
       
   515     <xsl:text>
       
   516 </xsl:text>
       
   517     <xsl:text>const typedarray_types = {
       
   518 </xsl:text>
       
   519     <xsl:text>    INT: Int16Array,
       
   520 </xsl:text>
       
   521     <xsl:text>    BOOL: Uint8Array
       
   522 </xsl:text>
       
   523     <xsl:text>    /* TODO */
       
   524 </xsl:text>
       
   525     <xsl:text>};
       
   526 </xsl:text>
       
   527     <xsl:text>
       
   528 </xsl:text>
       
   529     <xsl:text>function send_reset() {
       
   530 </xsl:text>
       
   531     <xsl:text>    send_blob(new Uint8Array([1])); /* reset = 1 */
       
   532 </xsl:text>
       
   533     <xsl:text>};
       
   534 </xsl:text>
       
   535     <xsl:text>
       
   536 </xsl:text>
       
   537     <xsl:text>// subscription state, as it should be in hmi server
       
   538 </xsl:text>
       
   539     <xsl:text>// hmitree indexed array of integers
       
   540 </xsl:text>
       
   541     <xsl:text>var subscriptions =  hmitree_types.map(_ignored =&gt; 0);
       
   542 </xsl:text>
       
   543     <xsl:text>
       
   544 </xsl:text>
       
   545     <xsl:text>// subscription state as needed by widget now
       
   546 </xsl:text>
       
   547     <xsl:text>// hmitree indexed array of Sets of widgets objects
       
   548 </xsl:text>
       
   549     <xsl:text>var subscribers = hmitree_types.map(_ignored =&gt; new Set());
       
   550 </xsl:text>
       
   551     <xsl:text>
       
   552 </xsl:text>
       
   553     <xsl:text>function update_subscriptions() {
       
   554 </xsl:text>
       
   555     <xsl:text>    let delta = [];
       
   556 </xsl:text>
       
   557     <xsl:text>    for(let index = 0; index &lt; subscribers.length; index++){
       
   558 </xsl:text>
       
   559     <xsl:text>        let widgets = subscribers[index];
       
   560 </xsl:text>
       
   561     <xsl:text>
       
   562 </xsl:text>
       
   563     <xsl:text>        // periods are in ms
       
   564 </xsl:text>
       
   565     <xsl:text>        let previous_period = subscriptions[index];
       
   566 </xsl:text>
       
   567     <xsl:text>
       
   568 </xsl:text>
       
   569     <xsl:text>        let new_period = 0;
       
   570 </xsl:text>
       
   571     <xsl:text>        if(widgets.size &gt; 0) {
       
   572 </xsl:text>
       
   573     <xsl:text>            let maxfreq = 0;
       
   574 </xsl:text>
       
   575     <xsl:text>            for(let widget of widgets)
       
   576 </xsl:text>
       
   577     <xsl:text>                if(maxfreq &lt; widget.frequency)
       
   578 </xsl:text>
       
   579     <xsl:text>                    maxfreq = widget.frequency;
       
   580 </xsl:text>
       
   581     <xsl:text>
       
   582 </xsl:text>
       
   583     <xsl:text>            if(maxfreq != 0)
       
   584 </xsl:text>
       
   585     <xsl:text>                new_period = 1000/maxfreq;
   362 </xsl:text>
   586 </xsl:text>
   363     <xsl:text>        }
   587     <xsl:text>        }
   364 </xsl:text>
   588 </xsl:text>
       
   589     <xsl:text>         
       
   590 </xsl:text>
       
   591     <xsl:text>        if(previous_period != new_period) {
       
   592 </xsl:text>
       
   593     <xsl:text>            subscriptions[index] = new_period;
       
   594 </xsl:text>
       
   595     <xsl:text>            delta.push(
       
   596 </xsl:text>
       
   597     <xsl:text>                new Uint8Array([2]), /* subscribe = 2 */
       
   598 </xsl:text>
       
   599     <xsl:text>                new Uint32Array([index]), 
       
   600 </xsl:text>
       
   601     <xsl:text>                new Uint16Array([new_period]));
       
   602 </xsl:text>
       
   603     <xsl:text>        }
       
   604 </xsl:text>
       
   605     <xsl:text>        
       
   606 </xsl:text>
   365     <xsl:text>    }
   607     <xsl:text>    }
   366 </xsl:text>
   608 </xsl:text>
   367     <xsl:text>};
   609     <xsl:text>    send_blob(delta);
   368 </xsl:text>
   610 </xsl:text>
   369     <xsl:text>
   611     <xsl:text>};
   370 </xsl:text>
   612 </xsl:text>
   371     <xsl:text>function init_widgets() {
   613     <xsl:text>
   372 </xsl:text>
   614 </xsl:text>
   373     <xsl:text>    Object.keys(hmi_widgets).forEach(function(id) {
   615     <xsl:text>function send_hmi_value(index, value) {
   374 </xsl:text>
   616 </xsl:text>
   375     <xsl:text>        let widget = hmi_widgets[id];
   617     <xsl:text>    let iectype = hmitree_types[index];
   376 </xsl:text>
   618 </xsl:text>
   377     <xsl:text>        let init = widget.init;
   619     <xsl:text>    let jstype = typedarray_types[iectype];
   378 </xsl:text>
   620 </xsl:text>
   379     <xsl:text>        if(typeof(init) == "function"){
   621     <xsl:text>    send_blob([
   380 </xsl:text>
   622 </xsl:text>
   381     <xsl:text>            return init.call(widget);
   623     <xsl:text>        new Uint8Array([0]),  /* setval = 0 */
   382 </xsl:text>
   624 </xsl:text>
   383     <xsl:text>        }
   625     <xsl:text>        new Uint32Array([index]), 
   384 </xsl:text>
   626 </xsl:text>
   385     <xsl:text>    });
   627     <xsl:text>        new jstype([value])]);
   386 </xsl:text>
   628 </xsl:text>
   387     <xsl:text>};
   629     <xsl:text>
   388 </xsl:text>
   630 </xsl:text>
   389     <xsl:text>
   631     <xsl:text>    cache[index] = value;
   390 </xsl:text>
   632 </xsl:text>
   391     <xsl:text>// Open WebSocket to relative "/ws" address
   633     <xsl:text>};
   392 </xsl:text>
   634 </xsl:text>
   393     <xsl:text>var ws = new WebSocket(window.location.href.replace(/^http(s?:\/\/[^\/]*)\/.*$/, 'ws$1/ws'));
   635     <xsl:text>
   394 </xsl:text>
   636 </xsl:text>
   395     <xsl:text>ws.binaryType = 'arraybuffer';
   637     <xsl:text>function change_hmi_value(index, opstr) {
   396 </xsl:text>
   638 </xsl:text>
   397     <xsl:text>
   639     <xsl:text>    let op = opstr[0];
   398 </xsl:text>
   640 </xsl:text>
   399     <xsl:text>const dvgetters = {
   641     <xsl:text>    let given_val = opstr.slice(1);
   400 </xsl:text>
   642 </xsl:text>
   401     <xsl:text>    INT: [DataView.prototype.getInt16, 2],
   643     <xsl:text>    let old_val = cache[index]
   402 </xsl:text>
   644 </xsl:text>
   403     <xsl:text>    BOOL: [DataView.prototype.getInt8, 1]
   645     <xsl:text>    let new_val;
   404 </xsl:text>
   646 </xsl:text>
   405     <xsl:text>    /* TODO */
   647     <xsl:text>    switch(op){
   406 </xsl:text>
   648 </xsl:text>
   407     <xsl:text>};
   649     <xsl:text>      case "=":
   408 </xsl:text>
   650 </xsl:text>
   409     <xsl:text>
   651     <xsl:text>        eval("new_val"+opstr);
   410 </xsl:text>
   652 </xsl:text>
   411     <xsl:text>// Register message reception handler 
   653     <xsl:text>        break;
   412 </xsl:text>
   654 </xsl:text>
   413     <xsl:text>ws.onmessage = function (evt) {
   655     <xsl:text>      case "+":
   414 </xsl:text>
   656 </xsl:text>
   415     <xsl:text>
   657     <xsl:text>      case "-":
   416 </xsl:text>
   658 </xsl:text>
   417     <xsl:text>    let data = evt.data;
   659     <xsl:text>      case "*":
   418 </xsl:text>
   660 </xsl:text>
   419     <xsl:text>    let dv = new DataView(data);
   661     <xsl:text>      case "/":
   420 </xsl:text>
   662 </xsl:text>
   421     <xsl:text>    let i = 0;
   663     <xsl:text>        if(old_val != undefined)
   422 </xsl:text>
   664 </xsl:text>
   423     <xsl:text>    //console.log("Recv something.");
   665     <xsl:text>            new_val = eval("old_val"+opstr);
   424 </xsl:text>
   666 </xsl:text>
   425     <xsl:text>    try {
   667     <xsl:text>        break;
   426 </xsl:text>
       
   427     <xsl:text>        for(let hash_int of hmi_hash) {
       
   428 </xsl:text>
       
   429     <xsl:text>            if(hash_int != dv.getUint8(i)){
       
   430 </xsl:text>
       
   431     <xsl:text>                throw new Error("Hash doesn't match");
       
   432 </xsl:text>
       
   433     <xsl:text>            };
       
   434 </xsl:text>
       
   435     <xsl:text>            i++;
       
   436 </xsl:text>
       
   437     <xsl:text>        };
       
   438 </xsl:text>
       
   439     <xsl:text>
       
   440 </xsl:text>
       
   441     <xsl:text>        //console.log("Recv something GOOD.");
       
   442 </xsl:text>
       
   443     <xsl:text>
       
   444 </xsl:text>
       
   445     <xsl:text>        while(i &lt; data.byteLength){
       
   446 </xsl:text>
       
   447     <xsl:text>            let index = dv.getUint32(i, true);
       
   448 </xsl:text>
       
   449     <xsl:text>            //console.log("Recv something index is "+index);
       
   450 </xsl:text>
       
   451     <xsl:text>            i += 4;
       
   452 </xsl:text>
       
   453     <xsl:text>            let iectype = hmitree_types[index];
       
   454 </xsl:text>
       
   455     <xsl:text>            if(iectype != undefined){
       
   456 </xsl:text>
       
   457     <xsl:text>                let [dvgetter, bytesize] = dvgetters[iectype];
       
   458 </xsl:text>
       
   459     <xsl:text>                let value = dvgetter.call(dv,i,true);
       
   460 </xsl:text>
       
   461     <xsl:text>                dispatch_value(index, value);
       
   462 </xsl:text>
       
   463     <xsl:text>                i += bytesize;
       
   464 </xsl:text>
       
   465     <xsl:text>            } else {
       
   466 </xsl:text>
       
   467     <xsl:text>                throw new Error("Unknown index "+index)
       
   468 </xsl:text>
       
   469     <xsl:text>            }
       
   470 </xsl:text>
       
   471     <xsl:text>        };
       
   472 </xsl:text>
       
   473     <xsl:text>    } catch(err) {
       
   474 </xsl:text>
       
   475     <xsl:text>        // 1003 is for "Unsupported Data"
       
   476 </xsl:text>
       
   477     <xsl:text>        // ws.close(1003, err.message);
       
   478 </xsl:text>
       
   479     <xsl:text>
       
   480 </xsl:text>
       
   481     <xsl:text>        // TODO : remove debug alert ?
       
   482 </xsl:text>
       
   483     <xsl:text>        alert("Error : "+err.message+"\nHMI will be reloaded.");
       
   484 </xsl:text>
       
   485     <xsl:text>
       
   486 </xsl:text>
       
   487     <xsl:text>        // force reload ignoring cache
       
   488 </xsl:text>
       
   489     <xsl:text>        location.reload(true);
       
   490 </xsl:text>
   668 </xsl:text>
   491     <xsl:text>    }
   669     <xsl:text>    }
   492 </xsl:text>
   670 </xsl:text>
   493     <xsl:text>};
   671     <xsl:text>    if(new_val != undefined &amp;&amp; old_val != new_val)
   494 </xsl:text>
   672 </xsl:text>
   495     <xsl:text>
   673     <xsl:text>        return send_hmi_value(index, new_val);
   496 </xsl:text>
       
   497     <xsl:text>
       
   498 </xsl:text>
       
   499     <xsl:text>function send_blob(data) {
       
   500 </xsl:text>
       
   501     <xsl:text>    if(data.length &gt; 0) {
       
   502 </xsl:text>
       
   503     <xsl:text>        ws.send(new Blob([new Uint8Array(hmi_hash)].concat(data)));
       
   504 </xsl:text>
       
   505     <xsl:text>    };
       
   506 </xsl:text>
       
   507     <xsl:text>};
       
   508 </xsl:text>
       
   509     <xsl:text>
       
   510 </xsl:text>
       
   511     <xsl:text>const typedarray_types = {
       
   512 </xsl:text>
       
   513     <xsl:text>    INT: Int16Array,
       
   514 </xsl:text>
       
   515     <xsl:text>    BOOL: Uint8Array
       
   516 </xsl:text>
       
   517     <xsl:text>    /* TODO */
       
   518 </xsl:text>
       
   519     <xsl:text>};
       
   520 </xsl:text>
       
   521     <xsl:text>
       
   522 </xsl:text>
       
   523     <xsl:text>function send_reset() {
       
   524 </xsl:text>
       
   525     <xsl:text>    send_blob(new Uint8Array([1])); /* reset = 1 */
       
   526 </xsl:text>
       
   527     <xsl:text>};
       
   528 </xsl:text>
       
   529     <xsl:text>
       
   530 </xsl:text>
       
   531     <xsl:text>// subscription state, as it should be in hmi server
       
   532 </xsl:text>
       
   533     <xsl:text>// hmitree indexed array of integers
       
   534 </xsl:text>
       
   535     <xsl:text>var subscriptions =  hmitree_types.map(_ignored =&gt; 0);
       
   536 </xsl:text>
       
   537     <xsl:text>
       
   538 </xsl:text>
       
   539     <xsl:text>// subscription state as needed by widget now
       
   540 </xsl:text>
       
   541     <xsl:text>// hmitree indexed array of Sets of widgets objects
       
   542 </xsl:text>
       
   543     <xsl:text>var subscribers = hmitree_types.map(_ignored =&gt; new Set());
       
   544 </xsl:text>
       
   545     <xsl:text>
       
   546 </xsl:text>
       
   547     <xsl:text>function update_subscriptions() {
       
   548 </xsl:text>
       
   549     <xsl:text>    let delta = [];
       
   550 </xsl:text>
       
   551     <xsl:text>    for(let index = 0; index &lt; subscribers.length; index++){
       
   552 </xsl:text>
       
   553     <xsl:text>        let widgets = subscribers[index];
       
   554 </xsl:text>
       
   555     <xsl:text>
       
   556 </xsl:text>
       
   557     <xsl:text>        // periods are in ms
       
   558 </xsl:text>
       
   559     <xsl:text>        let previous_period = subscriptions[index];
       
   560 </xsl:text>
       
   561     <xsl:text>
       
   562 </xsl:text>
       
   563     <xsl:text>        let new_period = 0;
       
   564 </xsl:text>
       
   565     <xsl:text>        if(widgets.size &gt; 0) {
       
   566 </xsl:text>
       
   567     <xsl:text>            let maxfreq = 0;
       
   568 </xsl:text>
       
   569     <xsl:text>            for(let widget of widgets)
       
   570 </xsl:text>
       
   571     <xsl:text>                if(maxfreq &lt; widget.frequency)
       
   572 </xsl:text>
       
   573     <xsl:text>                    maxfreq = widget.frequency;
       
   574 </xsl:text>
       
   575     <xsl:text>
       
   576 </xsl:text>
       
   577     <xsl:text>            if(maxfreq != 0)
       
   578 </xsl:text>
       
   579     <xsl:text>                new_period = 1000/maxfreq;
       
   580 </xsl:text>
       
   581     <xsl:text>        }
       
   582 </xsl:text>
       
   583     <xsl:text>         
       
   584 </xsl:text>
       
   585     <xsl:text>        if(previous_period != new_period) {
       
   586 </xsl:text>
       
   587     <xsl:text>            subscriptions[index] = new_period;
       
   588 </xsl:text>
       
   589     <xsl:text>            delta.push(
       
   590 </xsl:text>
       
   591     <xsl:text>                new Uint8Array([2]), /* subscribe = 2 */
       
   592 </xsl:text>
       
   593     <xsl:text>                new Uint32Array([index]), 
       
   594 </xsl:text>
       
   595     <xsl:text>                new Uint16Array([new_period]));
       
   596 </xsl:text>
       
   597     <xsl:text>        }
       
   598 </xsl:text>
       
   599     <xsl:text>        
       
   600 </xsl:text>
       
   601     <xsl:text>    }
       
   602 </xsl:text>
       
   603     <xsl:text>    send_blob(delta);
       
   604 </xsl:text>
       
   605     <xsl:text>};
       
   606 </xsl:text>
       
   607     <xsl:text>
       
   608 </xsl:text>
       
   609     <xsl:text>function send_hmi_value(index, value) {
       
   610 </xsl:text>
       
   611     <xsl:text>    let iectype = hmitree_types[index];
       
   612 </xsl:text>
       
   613     <xsl:text>    let jstype = typedarray_types[iectype];
       
   614 </xsl:text>
       
   615     <xsl:text>    send_blob([
       
   616 </xsl:text>
       
   617     <xsl:text>        new Uint8Array([0]),  /* setval = 0 */
       
   618 </xsl:text>
       
   619     <xsl:text>        new Uint32Array([index]), 
       
   620 </xsl:text>
       
   621     <xsl:text>        new jstype([value])]);
       
   622 </xsl:text>
       
   623     <xsl:text>
       
   624 </xsl:text>
       
   625     <xsl:text>};
       
   626 </xsl:text>
       
   627     <xsl:text>
       
   628 </xsl:text>
       
   629     <xsl:text>function change_hmi_value(index, opstr) {
       
   630 </xsl:text>
       
   631     <xsl:text>    let op = opstr[0];
       
   632 </xsl:text>
       
   633     <xsl:text>    if(op == "=")
       
   634 </xsl:text>
       
   635     <xsl:text>        return send_hmi_value(index, Number(opstr.slice(1)));
       
   636 </xsl:text>
       
   637     <xsl:text>
       
   638 </xsl:text>
       
   639     <xsl:text>    alert('Change '+opstr+" TODO !!! (index :"+index+")");
       
   640 </xsl:text>
   674 </xsl:text>
   641     <xsl:text>}
   675     <xsl:text>}
   642 </xsl:text>
   676 </xsl:text>
   643     <xsl:text>
   677     <xsl:text>
   644 </xsl:text>
   678 </xsl:text>