1 // svghmi.js |
1 // svghmi.js |
2 |
2 |
3 function dispatch_value(index, value) { |
3 function dispatch_value(index, value) { |
4 console.log("dispatch_value("+index+value+")"); |
4 console.log("dispatch_value("+index+", "+value+")"); |
5 }; |
5 }; |
6 |
6 |
7 // Open WebSocket to relative "/ws" address |
7 // Open WebSocket to relative "/ws" address |
8 var ws = new WebSocket(window.location.href.replace(/^http(s?:\/\/[^\/]*)\/.*$/, 'ws$1/ws')); |
8 var ws = new WebSocket(window.location.href.replace(/^http(s?:\/\/[^\/]*)\/.*$/, 'ws$1/ws')); |
9 ws.binaryType = 'arraybuffer'; |
9 ws.binaryType = 'arraybuffer'; |
18 ws.onmessage = function (evt) { |
18 ws.onmessage = function (evt) { |
19 |
19 |
20 let data = evt.data; |
20 let data = evt.data; |
21 let dv = new DataView(data); |
21 let dv = new DataView(data); |
22 let i = 0; |
22 let i = 0; |
23 for(let hash_int of hmi_hash) { |
23 try { |
24 if(hash_int != dv.getUint8(i)){ |
24 for(let hash_int of hmi_hash) { |
25 console.log("Recv non maching hash. Reload."); |
25 if(hash_int != dv.getUint8(i)){ |
|
26 throw new Error("Hash doesn't match") |
|
27 }; |
|
28 i++; |
|
29 }; |
26 |
30 |
27 // 1003 is for "Unsupported Data" |
31 while(i < data.byteLength){ |
28 ws.close(1003,"Hash doesn't match"); |
32 let index = dv.getUint32(i, true); |
|
33 console.log("Recv something index is "+index); |
|
34 i += 4; |
|
35 let iectype = hmitree_types[index]; |
|
36 if(iectype != undefined){ |
|
37 let [dvgetter, bytesize] = dvgetters[iectype]; |
|
38 let value = dvgetter.call(dv,i,true); |
|
39 dispatch_value(index, value); |
|
40 i += bytesize; |
|
41 } else { |
|
42 throw new Error("Unknown index "+index) |
|
43 } |
|
44 }; |
|
45 } catch(err) { |
|
46 // 1003 is for "Unsupported Data" |
|
47 // ws.close(1003, err.message); |
29 |
48 |
30 // TODO : remove debug alert ? |
49 // TODO : remove debug alert ? |
31 alert("HMI will be reloaded."); |
50 alert("Error : "+err.message+"\\\\nHMI will be reloaded."); |
32 |
51 |
33 // force reload ignoring cache |
52 // force reload ignoring cache |
34 location.reload(true); |
53 location.reload(true); |
35 }; |
54 } |
36 i++; |
|
37 }; |
|
38 |
|
39 while(i < data.length){ |
|
40 let index = dv.getUint32(i); |
|
41 i += 4; |
|
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 }; |
55 }; |
49 |
56 |
50 |
57 |
51 function send_blob(data) { |
58 function send_blob(data) { |
52 if(data.length > 0) { |
59 if(data.length > 0) { |
53 ws.send(new Blob([ |
60 ws.send(new Blob([new Uint8Array(hmi_hash)].concat(data))); |
54 new Uint8Array(hmi_hash), |
|
55 data])); |
|
56 }; |
61 }; |
57 }; |
62 }; |
58 |
63 |
59 const typedarray_types = { |
64 const typedarray_types = { |
60 INT: Int16Array, |
65 INT: Int16Array, |
80 let widgets = subscribers[index]; |
85 let widgets = subscribers[index]; |
81 |
86 |
82 // periods are in ms |
87 // periods are in ms |
83 let previous_period = subscriptions[index]; |
88 let previous_period = subscriptions[index]; |
84 |
89 |
85 let new_period; |
90 let new_period = 0; |
86 if(widgets.size > 0) { |
91 if(widgets.size > 0) { |
87 let maxfreq = 0; |
92 let maxfreq = 0; |
88 for(let widget of widgets) |
93 for(let widget of widgets) |
89 if(maxfreq < widgets.frequency) |
94 if(maxfreq < widget.frequency) |
90 maxfreq = widgets.frequency; |
95 maxfreq = widget.frequency; |
91 |
96 |
92 new_period = 1000/maxfreq; |
97 if(maxfreq != 0) |
93 } else { |
98 new_period = 1000/maxfreq; |
94 new_period = 0; |
|
95 } |
99 } |
96 |
100 |
97 if(previous_period != new_period) { |
101 if(previous_period != new_period) { |
98 subscriptions[index] = new_period; |
102 subscriptions[index] = new_period; |
99 delta.push([ |
103 delta.push(new Blob([ |
100 new Uint8Array([2]), /* subscribe = 2 */ |
104 new Uint8Array([2]), /* subscribe = 2 */ |
101 new Uint32Array([index]), |
105 new Uint32Array([index]), |
102 new Uint16Array([new_period])]); |
106 new Uint16Array([new_period])])); |
103 } |
107 } |
104 |
108 |
105 } |
109 } |
106 send_blob(delta); |
110 send_blob(delta); |
107 }; |
111 }; |
146 // Once connection established |
150 // Once connection established |
147 ws.onopen = function (evt) { |
151 ws.onopen = function (evt) { |
148 send_reset(); |
152 send_reset(); |
149 // show main page |
153 // show main page |
150 switch_page(default_page); |
154 switch_page(default_page); |
|
155 }; |
|
156 |
|
157 ws.onclose = function (evt) { |
|
158 // TODO : add visible notification while waiting for reload |
|
159 console.log("Connection closed. code:"+evt.code+" reason:"+evt.reason+" wasClean:"+evt.wasClean+" Reload in 10s."); |
|
160 // TODO : re-enable auto reload when not in debug |
|
161 //window.setTimeout(() => location.reload(true), 10000); |
|
162 alert("Connection closed. code:"+evt.code+" reason:"+evt.reason+" wasClean:"+evt.wasClean+"."); |
151 |
163 |
152 }; |
164 }; |
153 |
|