1 // svghmi.js |
1 // svghmi.js |
2 |
2 |
3 (function(){ |
3 function dispatch_value(index, value) { |
4 // Open WebSocket to relative "/ws" address |
4 console.log("dispatch_value("+index+value+")"); |
5 var ws = new WebSocket(window.location.href.replace(/^http(s?:\/\/[^\/]*)\/.*$/, 'ws$1/ws')); |
5 }; |
6 |
6 |
7 // Register message reception handler |
7 // Open WebSocket to relative "/ws" address |
8 ws.onmessage = function (evt) { |
8 var ws = new WebSocket(window.location.href.replace(/^http(s?:\/\/[^\/]*)\/.*$/, 'ws$1/ws')); |
9 // TODO : dispatch and cache hmi tree updates |
9 ws.binaryType = 'arraybuffer'; |
10 |
10 |
11 var received_msg = evt.data; |
11 const dvgetters = { |
12 // TODO : check for hmitree hash header |
12 INT: [DataView.prototype.getInt16, 2], |
13 // if not matching, reload page |
13 BOOL: [DataView.prototype.getInt8, 1] |
14 alert("Message is received..."+received_msg); |
14 /* TODO */ |
|
15 }; |
|
16 |
|
17 // Register message reception handler |
|
18 ws.onmessage = function (evt) { |
|
19 |
|
20 let data = evt.data; |
|
21 let dv = new DataView(data); |
|
22 let i = 0; |
|
23 for(let hash_int of hmi_hash) { |
|
24 if(hash_int != dv.getUint8(i)){ |
|
25 console.log("Recv non maching hash. Reload."); |
|
26 |
|
27 // 1003 is for "Unsupported Data" |
|
28 ws.close(1003,"Hash doesn't match"); |
|
29 |
|
30 // TODO : remove debug alert ? |
|
31 alert("HMI will be reloaded."); |
|
32 |
|
33 // force reload ignoring cache |
|
34 location.reload(true); |
|
35 }; |
|
36 i++; |
15 }; |
37 }; |
16 |
38 |
17 // Once connection established |
39 while(i < data.length){ |
18 ws.onopen = function (evt) { |
40 let index = dv.getUint32(i); |
19 // TODO : enable the HMI (was previously offline, or just starts) |
41 i += 4; |
20 // show main page |
42 let iectype = hmitree_types[index]; |
|
43 let [dvgetter, bytesize] = dvgetters[iectypes]; |
|
44 value = dvgetter.call(dv,i); |
|
45 dispatch_value(index, value); |
|
46 i += bytesize; |
|
47 }; |
|
48 }; |
21 |
49 |
22 |
50 |
23 // TODO : prefix with hmitree hash header |
51 function send_blob(data) { |
24 ws.send("test"); |
52 if(data.length > 0) { |
|
53 ws.send(new Blob([ |
|
54 new Uint8Array(hmi_hash), |
|
55 data])); |
25 }; |
56 }; |
26 })(); |
57 }; |
|
58 |
|
59 const typedarray_types = { |
|
60 INT: Int16Array, |
|
61 BOOL: Uint8Array |
|
62 /* TODO */ |
|
63 }; |
|
64 |
|
65 function send_reset() { |
|
66 send_blob(new Uint8Array([1])); /* reset = 1 */ |
|
67 }; |
|
68 |
|
69 // subscription state, as it should be in hmi server |
|
70 // hmitree indexed array of integers |
|
71 var subscriptions = hmitree_types.map(_ignored => 0); |
|
72 |
|
73 // subscription state as needed by widget now |
|
74 // hmitree indexed array of Sets of widgets objects |
|
75 var subscribers = hmitree_types.map(_ignored => new Set()); |
|
76 |
|
77 function update_subscriptions() { |
|
78 let delta = []; |
|
79 for(let index = 0; index < subscribers.length; index++){ |
|
80 let widgets = subscribers[index]; |
|
81 |
|
82 // periods are in ms |
|
83 let previous_period = subscriptions[index]; |
|
84 |
|
85 let new_period; |
|
86 if(widgets.size > 0) { |
|
87 let maxfreq = 0; |
|
88 for(let widget of widgets) |
|
89 if(maxfreq < widgets.frequency) |
|
90 maxfreq = widgets.frequency; |
|
91 |
|
92 new_period = 1000/maxfreq; |
|
93 } else { |
|
94 new_period = 0; |
|
95 } |
|
96 |
|
97 if(previous_period != new_period) { |
|
98 subscriptions[index] = new_period; |
|
99 delta.push([ |
|
100 new Uint8Array([2]), /* subscribe = 2 */ |
|
101 new Uint32Array([index]), |
|
102 new Uint16Array([new_period])]); |
|
103 } |
|
104 |
|
105 } |
|
106 send_blob(delta); |
|
107 }; |
|
108 |
|
109 function update_value(index, value) { |
|
110 iectype = hmitree_types[index]; |
|
111 jstype = typedarray_types[iectypes]; |
|
112 send_blob([ |
|
113 new Uint8Array([0]), /* setval = 0 */ |
|
114 new jstype([value]) |
|
115 ]); |
|
116 |
|
117 }; |
|
118 |
|
119 var current_page; |
|
120 |
|
121 function switch_page(page_name) { |
|
122 let old_desc = page_desc[current_page]; |
|
123 let new_desc = page_desc[page_name]; |
|
124 /* TODO hide / show widgets */ |
|
125 /* TODO move viewport */ |
|
126 |
|
127 /* remove subsribers of previous page if any */ |
|
128 if(old_desc) for(let widget of old_desc.widgets){ |
|
129 for(let index of widget.indexes){ |
|
130 subscribers[index].delete(widget); |
|
131 } |
|
132 } |
|
133 /* add new subsribers if any */ |
|
134 if(new_desc) for(let widget of new_desc.widgets){ |
|
135 for(let index of widget.indexes){ |
|
136 subscribers[index].add(widget); |
|
137 } |
|
138 } |
|
139 |
|
140 current_page = page_name; |
|
141 |
|
142 update_subscriptions(); |
|
143 }; |
|
144 |
|
145 |
|
146 // Once connection established |
|
147 ws.onopen = function (evt) { |
|
148 send_reset(); |
|
149 // show main page |
|
150 switch_page(default_page); |
|
151 |
|
152 }; |
|
153 |