1/********************************************************************\
4 Created by: Stefan Ritt
5 Created by: Konstantin Olchanski
7 Contents: JavaScript midas library for building custom pages
9\********************************************************************/
11// MIDAS type definitions from midas.h
74const TID_FLOAT64 = 10;
75const TID_BITFIELD = 11;
88const AT_EVALUATED = 3;
91const MT_ERROR = (1<<0);
92const MT_INFO = (1<<1);
93const MT_DEBUG = (1<<2);
94const MT_USER = (1<<3);
96const MT_TALK = (1<<5);
97const MT_CALL = (1<<6);
99const STATE_STOPPED = 1; /**< MIDAS run stopped */
100const STATE_PAUSED = 2; /**< MIDAS run paused */
101const STATE_RUNNING = 3; /**< MIDAS run running */
103const TR_START = 1; /**< Start transition */
104const TR_STOP = 2; /**< Stop transition */
105const TR_PAUSE = 4; /**< Pause transition */
106const TR_RESUME = 8; /**< Resume transition */
107const TR_STARTABORT = 16; /**< Start aborted transition */
108const TR_DEFERRED = 4096;
110const MODE_READ = (1<<0);
111const MODE_WRITE = (1<<1);
112const MODE_DELETE = (1<<2);
113const MODE_EXCLUSIVE = (1<<3);
114const MODE_ALLOC = (1<<6);
115const MODE_WATCH = (1<<7);
117/// \defgroup mjsonrpc_js JSON-RPC Javascript library (mjsonrpc_xxx)
119var mjsonrpc_default_url_web = "";
120var mjsonrpc_default_url_file = "https://localhost:8443/";
125if (window.location.protocol == 'file:') {
126 mjsonrpc_url = mjsonrpc_default_url_file;
128 mjsonrpc_url = mjsonrpc_default_url_web;
132function mjsonrpc_set_url(url)
134 /// \ingroup mjsonrpc_js
135 /// Change the URL of JSON-RPC server
136 /// @param[in] url the new URL, i.e. "https://daqserver.example.com:8443" (string)
141function loadScript(src) {
142 return new Promise((resolve, reject) => {
143 let script = document.createElement('script');
146 script.onload = () => resolve(script);
147 script.onerror = () => reject(new Error(`Script load error for ${src}`));
149 document.head.appendChild(script);
153async function mjsonrpc_send_request(req)
156 /// \ingroup mjsonrpc_js
157 /// Send JSON-RPC request(s) via HTTP POST. RPC response and error handling is done using the Javascript Promise mechanism:
160 /// var req = mjsonrpc_make_request(method, params, id);
161 /// mjsonrpc_send_request(req).then(function(rpc) {
162 /// var req = rpc.request; // reference to the rpc request
163 /// var id = rpc.id; // rpc response id (should be same as req.id)
164 /// var result = rpc.result; // rpc response result
166 /// }).catch(function(error) {
167 /// mjsonrpc_error_alert(error);
171 /// @param[in] req request object or an array of request objects (object or array of objects)
172 /// @returns new Promise
174 //console.log("mjsonrpc_send_request!");
176 return new Promise(function(resolve, reject) {
177 var xhr = new XMLHttpRequest();
178 //xhr.responseType = 'json'; // this does not work: behaviour is not defined if RPC returns unparsable JSON
179 if (req.id == "arraybuffer") {
180 xhr.responseType = 'arraybuffer';
182 xhr.responseType = 'text';
184 xhr.withCredentials = true;
186 xhr.onreadystatechange = function()
188 //alert("XHR: ready state " + xhr.readyState + " status " + xhr.status);
189 if (xhr.readyState == 4) {
191 if (xhr.status != 200) {
192 var error = new Object;
199 var contentType = xhr.getResponseHeader("Content-Type");
200 //console.log("XHR ContentType: " + contentType);
201 //console.log("XHR response type: " + typeof(xhr.response));
203 if (contentType == "application/octet-stream") {
204 var response = xhr.response;
205 //console.log("XHR response type: " + typeof(response));
206 //console.log("XHR response: " + response);
209 } else if (contentType == "application/json") {
210 var rpc_response = null;
211 var xhr_response = xhr.response;
213 // if xhr.responseType is "arraybuffer", we need to convert it back to text
214 // before we can parse it as json. K.O.
215 if (xhr.responseType == "arraybuffer") {
216 xhr_response = new TextDecoder("utf-8").decode(xhr.response);
220 rpc_response = JSON.parse(xhr_response);
222 throw "JSON parser returned null";
225 //alert("exception " + exc);
226 var error = new Object;
229 error.exception = exc;
234 if (Array.isArray(rpc_response)) {
235 var batch = new Array;
236 for (var i=0; i<rpc_response.length; i++) {
237 var rpc = new Object;
238 rpc.request = req[i];
239 rpc.id = rpc_response[i].id;
240 if (rpc_response[i].hasOwnProperty("error")) {
241 rpc.error = rpc_response[i].error;
243 rpc.result = rpc_response[i].result;
251 if (rpc_response.error) {
252 var error = new Object;
255 error.error = rpc_response.error;
260 var rpc = new Object;
262 rpc.id = rpc_response.id;
263 rpc.result = rpc_response.result;
267 var error = new Object;
270 error.error = "Unexpected Content-Type: " + contentType;
277 xhr.open('POST', mjsonrpc_url + "?mjsonrpc");
278 xhr.setRequestHeader('Content-Type', 'application/json');
279 xhr.setRequestHeader('Accept', 'application/json');
280 if (req == "send invalid json")
281 xhr.send("invalid json");
283 // special serialization for BigInt numbers
284 let j = JSON.stringify(req, (key, value) =>
285 typeof value === 'bigint' ? value.toString() : value
293function mjsonrpc_debug_alert(rpc) {
294 /// \ingroup mjsonrpc_js
295 /// Debug method to show RPC response
296 /// @param[in] rpc object (object), see mjsonrpc_send_request()
299 if (Array.isArray(rpc)) {
300 //console.log("here!");
302 rpc.forEach(function(r) {
305 a += "method: \"" + r.request.method + "\", params: " + r.request.params + ", id: " + JSON.stringify(r.id) + ", error: " + JSON.stringify(r.error);
307 a += "method: \"" + r.request.method + "\", params: " + r.request.params + ", id: " + JSON.stringify(r.id) + ", response: " + JSON.stringify(r.result);
311 alert("mjsonrpc_debug_alert: array:\n" + a);
313 alert("mjsonrpc_debug_alert: method: \"" + rpc.request.method + "\", params: " + rpc.request.params + ", id: " + JSON.stringify(rpc.id) + ", response: " + JSON.stringify(rpc.result));
317function mjsonrpc_decode_error(error) {
318 /// \ingroup mjsonrpc_js
319 /// Convert RPC error status to human-readable string
320 /// @param[in] error rejected promise error object (object)
321 /// @returns decoded error report (string)
323 //console.log("mjsonrpc_decode_error: " + JSON.stringify(error));
324 //console.log("mjsonrpc_decode_error xhr: " + JSON.stringify(error.xhr));
325 //for (var x in error.xhr) {
326 // if (x == "responseText") continue;
327 // if (x == "responseXML") continue;
328 // console.log("xhr[" + x + "] = [" + error.xhr[x] + "]");
331 function is_network_error(xhr) {
332 return xhr.readyState==4 && xhr.status==0;
334 function is_http_error(xhr) {
335 return xhr.readyState==4 && xhr.status!=200;
337 function print_xhr(xhr) {
338 return "readyState: " + xhr.readyState + ", HTTP status: " + xhr.status + " (" + xhr.statusText + ")";
340 function print_request(request) {
341 //console.log("print_request: " + request + ", JSON: " + JSON.stringify(request));
342 if (Array.isArray(request)) {
343 var s = "batch request: ";
344 request.forEach(function(item, index) {
345 s += print_request(item);
350 return "method: \"" + request.method + "\", params: " + request.params + ", id: " + request.id;
353 if (error.xhr && is_network_error(error.xhr)) {
354 return "network error: see javascript console, " + print_request(error.request);
355 } else if (error.xhr && is_http_error(error.xhr)) {
356 return "http error: " + print_xhr(error.xhr) + ", " + print_request(error.request);
357 } else if (error.exception) {
358 return "json parser exception: " + error.exception + ", " + print_request(error.request);
359 } else if (error.error) {
360 return "json-rpc error: " + JSON.stringify(error.error) + ", " + print_request(error.request) + ", " +
361 "<br>" + error.xhr.response;
362 } else if (error.request && error.xhr) {
363 return "unknown error, request: " + print_request(error.request) + ", xhr: " + print_xhr(error.xhr);
365 return "javascript exception: " + error;
369function mjsonrpc_error_alert(error, callback, param) {
370 /// \ingroup mjsonrpc_js
371 /// Handle all errors
372 /// @param[in] error rejected promise error object (object)
375 var s = mjsonrpc_decode_error(error);
376 dlgMessage("RPC Error", s, true, true, callback, param);
378 dlgMessage("Javascript exception or error", error, true, true, callback, param);
383function mjsonrpc_make_request(method, params, id)
385 /// \ingroup mjsonrpc_js
386 /// Creates a new JSON-RPC request object
387 /// @param[in] method name of the RPC method (string)
388 /// @param[in] params parameters of the RPC method (object)
389 /// @param[in] id optional request id (see JSON-RPC specs) (object)
390 /// @returns the request object (object)
395 var req = new Object();
396 req.jsonrpc = "2.0"; // version
398 if (typeof params == 'string') {
399 req.params = JSON.parse(params);
404 req.params = null; // make sure we have "params", even if set to null or undefined
410function mjsonrpc_call(method, params, id)
412 /// \ingroup mjsonrpc_js
413 /// Creates a JSON-RPC request and sends it to mhttpd via HTTP POST.
414 /// RPC response and error handling is done using the Javascript Promise mechanism:
417 /// mjsonrpc_call(method, params, id).then(function(rpc) {
418 /// var req = rpc.request; // reference to the rpc request
419 /// var id = rpc.id; // rpc response id (should be same as req.id)
420 /// var result = rpc.result; // rpc response result
422 /// }).catch(function(error) {
423 /// mjsonrpc_error_alert(error);
426 /// @param[in] method name of the RPC method (string)
427 /// @param[in] params parameters of the RPC method (object)
428 /// @param[in] id optional request id (see JSON-RPC specs) (object)
429 /// @returns new Promise
431 var req = mjsonrpc_make_request(method, params, id);
432 return mjsonrpc_send_request(req);
435function mjsonrpc_start_program(name, id) {
436 /// \ingroup mjsonrpc_js
437 /// Start a MIDAS program
439 /// RPC method: "start_program"
442 /// mjsonrpc_start_program("logger").then(function(rpc) {
443 /// var req = rpc.request; // reference to the rpc request
444 /// var id = rpc.id; // rpc response id (should be same as req.id)
445 /// var result = rpc.result; // rpc response result
446 /// var status = rpc.result.status; // return status of ss_system(), see MIDAS JSON-RPC docs
448 /// }).catch(function(error) {
449 /// mjsonrpc_error_alert(error);
452 /// @param[in] name Name of program to start, should be same as the ODB entry "/Programs/name" (string)
453 /// @param[in] id optional request id (see JSON-RPC specs) (object)
454 /// @returns new Promise
456 var req = new Object();
458 return mjsonrpc_call("start_program", req, id);
461function mjsonrpc_stop_program(name, unique, id) {
462 /// \ingroup mjsonrpc_js
463 /// Stop a MIDAS program via cm_shutdown()
465 /// RPC method: "cm_shutdown"
468 /// mjsonrpc_stop_program("logger").then(function(rpc) {
469 /// var req = rpc.request; // reference to the rpc request
470 /// var id = rpc.id; // rpc response id (should be same as req.id)
471 /// var result = rpc.result; // rpc response result
472 /// var status = rpc.result.status; // return status of cm_shutdown(), see MIDAS JSON-RPC docs and cm_shutdown() docs
474 /// }).catch(function(error) {
475 /// mjsonrpc_error_alert(error);
478 /// @param[in] name Name of program to stop (string)
479 /// @param[in] unique bUnique argument to cm_shutdown() (bool)
480 /// @param[in] id optional request id (see JSON-RPC specs) (object)
481 /// @returns new Promise
483 var req = new Object();
486 return mjsonrpc_call("cm_shutdown", req, id);
489function mjsonrpc_cm_exist(name, unique, id) {
490 /// \ingroup mjsonrpc_js
491 /// Stop a MIDAS program via cm_exist()
493 /// RPC method: "cm_exist"
495 /// @param[in] name Name of program to stop (string)
496 /// @param[in] unique bUnique argument to cm_shutdown() (bool)
497 /// @param[in] id optional request id (see JSON-RPC specs) (object)
498 var req = new Object();
501 return mjsonrpc_call("cm_exist", req, id);
504function mjsonrpc_al_reset_alarm(alarms, id) {
505 /// \ingroup mjsonrpc_js
508 /// RPC method: "al_reset_alarm"
511 /// mjsonrpc_al_reset_alarm(["alarm1", "alarm2"]).then(function(rpc) {
512 /// var req = rpc.request; // reference to the rpc request
513 /// var id = rpc.id; // rpc response id (should be same as req.id)
514 /// var result = rpc.result; // rpc response result
515 /// ... result.status[0]; // status of al_reset_alarm() for 1st alarm
516 /// ... result.status[1]; // status of al_reset_alarm() for 2nd alarm
517 /// }).catch(function(error) {
518 /// mjsonrpc_error_alert(error);
521 /// @param[in] alarms Array of alarm names (array of strings)
522 /// @param[in] id optional request id (see JSON-RPC specs) (object)
523 /// @returns new Promise
525 var req = new Object();
527 return mjsonrpc_call("al_reset_alarm", req, id);
530function mjsonrpc_al_trigger_alarm(name, message, xclass, condition, type, id) {
531 /// \ingroup mjsonrpc_js
534 /// RPC method: "al_reset_alarm"
537 /// mjsonrpc_al_reset_alarm(["alarm1", "alarm2"]).then(function(rpc) {
538 /// var req = rpc.request; // reference to the rpc request
539 /// var id = rpc.id; // rpc response id (should be same as req.id)
540 /// var result = rpc.result; // rpc response result
541 /// ... result.status[0]; // status of al_reset_alarm() for 1st alarm
542 /// ... result.status[1]; // status of al_reset_alarm() for 2nd alarm
543 /// }).catch(function(error) {
544 /// mjsonrpc_error_alert(error);
547 /// @param[in] alarms Array of alarm names (array of strings)
548 /// @param[in] id optional request id (see JSON-RPC specs) (object)
549 /// @returns new Promise
551 var req = new Object();
553 req.message = message;
555 req.condition = condition;
557 return mjsonrpc_call("al_trigger_alarm", req, id);
560function mjsonrpc_db_copy(paths, id) {
561 /// \ingroup mjsonrpc_js
562 /// Get a copy of ODB. Symlinks are not resolved, ODB path names are not converted to lower-case.
564 /// Instead of this function, please use db_get_values() as a simple way to get easy to use ODB values.
566 /// RPC method: "db_copy"
569 /// mjsonrpc_db_copy(["/runinfo", "/equipment/foo"]).then(function(rpc) {
570 /// var req = rpc.request; // reference to the rpc request
571 /// var id = rpc.id; // rpc response id (should be same as req.id)
572 /// var result = rpc.result; // rpc response result
573 /// ... result.status[0]; // status of db_get_value() for /runinfo
574 /// ... result.status[1]; // status of db_get_value() for /equipment
575 /// var runinfo = result.data[0]; // javascript object representing the ODB runinfo structure
576 /// var equipment = result.data[1]; // javascript object representing /equipment/foo
577 /// }).catch(function(error) {
578 /// mjsonrpc_error_alert(error);
581 /// @param[in] paths Array of ODB paths (array of strings)
582 /// @param[in] id optional request id (see JSON-RPC specs) (object)
583 /// @returns new Promise
585 var req = new Object();
587 return mjsonrpc_call("db_copy", req, id);
590function mjsonrpc_db_get_values(paths, id) {
591 /// \ingroup mjsonrpc_js
592 /// Get values of ODB variables
594 /// RPC method: "db_get_values"
597 /// mjsonrpc_db_get_values(["/runinfo", "/equipment"]).then(function(rpc) {
598 /// var req = rpc.request; // reference to the rpc request
599 /// var id = rpc.id; // rpc response id (should be same as req.id)
600 /// var result = rpc.result; // rpc response result
601 /// ... result.status[0]; // status of db_get_value() for /runinfo
602 /// ... result.status[1]; // status of db_get_value() for /equipment
603 /// ... result.last_written[0]; // "last written" timestamp for /runinfo
604 /// ... result.last_written[1]; // "last written" timestamp for /equipment
605 /// var runinfo = result.data[0]; // javascript object representing the ODB runinfo structure
606 /// ... runinfo["run number"]; // access the run number, note: all ODB names should be in lower-case.
607 /// ... runinfo["run number/last_written"]; // "last_written" timestamp for the run number
608 /// ... result.data[1].foo.variables.bar; // access /equipment/foo/variables/bar
609 /// }).catch(function(error) {
610 /// mjsonrpc_error_alert(error);
613 /// @param[in] paths Array of ODB paths (array of strings)
614 /// @param[in] id optional request id (see JSON-RPC specs) (object)
615 /// @returns new Promise
617 var req = new Object();
619 return mjsonrpc_call("db_get_values", req, id);
622function mjsonrpc_db_get_value(paths, id) {
623 /// \ingroup mjsonrpc_js
624 /// Get values of ODB variables
626 /// RPC method: "db_get_value"
629 /// mjsonrpc_db_get_value("/runinfo").then(function(rpc) {
630 /// var req = rpc.request; // reference to the rpc request
631 /// var id = rpc.id; // rpc response id (should be same as req.id)
632 /// var result = rpc.result; // rpc response result
633 /// ... result.status[0]; // status of db_get_value() for /runinfo
634 /// ... result.status[1]; // status of db_get_value() for /equipment
635 /// ... result.last_written[0]; // "last written" timestamp for /runinfo
636 /// ... result.last_written[1]; // "last written" timestamp for /equipment
637 /// var runinfo = result.data[0]; // javascript object representing the ODB runinfo structure
638 /// ... runinfo["run number"]; // access the run number, note: all ODB names should be in lower-case.
639 /// ... runinfo["run number/last_written"]; // "last_written" timestamp for the run number
640 /// ... result.data[1].foo.variables.bar; // access /equipment/foo/variables/bar
641 /// }).catch(function(error) {
642 /// mjsonrpc_error_alert(error);
645 /// @param[in] paths Array of ODB paths (array of strings)
646 /// @param[in] id optional request id (see JSON-RPC specs) (object)
647 /// @returns new Promise
649 let req = new Object();
651 return mjsonrpc_call("db_get_values", req, id);
654function db_get_value(path, callback) {
655 if (!Array.isArray(path))
658 let req = new Object();
660 req.omit_names = true;
661 req.omit_last_written = true;
662 mjsonrpc_call("db_get_values", req).then(rpc => callback(rpc))
663 .catch(error => mjsonrpc_error_alert(error));
666function mjsonrpc_db_ls(paths, id) {
667 /// \ingroup mjsonrpc_js
668 /// Get list of contents of an ODB subdirectory, similar to odbedit command "ls -l". To get values of ODB variables, use db_get_values().
670 /// RPC method: "db_ls"
673 /// mjsonrpc_db_ls(["/alarms/alarms", "/equipment"]).then(function(rpc) {
674 /// var req = rpc.request; // reference to the rpc request
675 /// var id = rpc.id; // rpc response id (should be same as req.id)
676 /// var result = rpc.result; // rpc response result
677 /// ... result.status[0]; // status of db_copy_json_ls() for /alarms/alarms
678 /// ... result.status[1]; // status of db_copy_json_ls() for /equipment
679 /// var alarms = result.data[0]; // javascript object representing the contents of ODB /alarms/alarms
680 /// var equipment = result.data[1]; // javascript object representing the contents of ODB /equipment
681 /// }).catch(function(error) {
682 /// mjsonrpc_error_alert(error);
685 /// @param[in] paths Array of ODB paths (array of strings)
686 /// @param[in] id optional request id (see JSON-RPC specs) (object)
687 /// @returns new Promise
689 var req = new Object();
691 return mjsonrpc_call("db_ls", req, id);
694function mjsonrpc_db_resize(paths, new_lengths, id) {
695 /// \ingroup mjsonrpc_js
696 /// Change size of ODB arrays
698 /// RPC method: "db_resize"
701 /// mjsonrpc_db_resize(["/test/intarray1", "/test/dblarray2"], [10, 20]).then(function(rpc) {
702 /// var req = rpc.request; // reference to the rpc request
703 /// var id = rpc.id; // rpc response id (should be same as req.id)
704 /// var result = rpc.result; // rpc response result
705 /// ... result.status[0]; // status of db_set_num_values() for 1st path
706 /// ... result.status[1]; // status of db_set_num_values() for 2nd path
707 /// }).catch(function(error) {
708 /// mjsonrpc_error_alert(error);
711 /// @param[in] paths Array of ODB paths (array of strings)
712 /// @param[in] new_sizes Array of new sizes for each path (array of ints)
713 /// @param[in] id optional request id (see JSON-RPC specs) (object)
714 /// @returns new Promise
716 var req = new Object();
718 req.new_lengths = new_lengths;
719 return mjsonrpc_call("db_resize", req, id);
722function mjsonrpc_db_key(paths, id) {
723 /// \ingroup mjsonrpc_js
726 /// RPC method: "db_key"
729 /// mjsonrpc_db_key(["/test/intarray1", "/test/dblarray2"]).then(function(rpc) {
730 /// var req = rpc.request; // reference to the rpc request
731 /// var id = rpc.id; // rpc response id (should be same as req.id)
732 /// var result = rpc.result; // rpc response result
733 /// ... result.status[0]; // status of db_get_key() for 1st path
734 /// ... result.status[1]; // status of db_get_key() for 2nd path
735 /// }).catch(function(error) {
736 /// mjsonrpc_error_alert(error);
739 /// @param[in] paths Array of ODB paths (array of strings)
740 /// @param[in] id optional request id (see JSON-RPC specs) (object)
741 /// @returns new Promise
743 var req = new Object();
745 return mjsonrpc_call("db_key", req, id);
748function mjsonrpc_db_delete(paths, id) {
749 /// \ingroup mjsonrpc_js
750 /// Delete ODB entries
752 /// RPC method: "db_delete"
755 /// mjsonrpc_db_delete(["/test/test1", "/test/test2"]).then(function(rpc) {
756 /// var req = rpc.request; // reference to the rpc request
757 /// var id = rpc.id; // rpc response id (should be same as req.id)
758 /// var result = rpc.result; // rpc response result
759 /// ... result.status[0]; // status of db_delete() for 1st path
760 /// ... result.status[1]; // status of db_delete() for 2nd path
761 /// }).catch(function(error) {
762 /// mjsonrpc_error_alert(error);
765 /// @param[in] paths Array of ODB paths (array of strings)
766 /// @param[in] id optional request id (see JSON-RPC specs) (object)
767 /// @returns new Promise
769 var req = new Object();
771 return mjsonrpc_call("db_delete", req, id);
774function mjsonrpc_db_paste(paths, values, id) {
775 /// \ingroup mjsonrpc_js
776 /// Write values info ODB.
778 /// RPC method: "db_paste"
781 /// mjsonrpc_db_paste(["/runinfo/run number", "/equipment/foo/settings/bar"], [123,456]).then(function(rpc) {
782 /// var req = rpc.request; // reference to the rpc request
783 /// var id = rpc.id; // rpc response id (should be same as req.id)
784 /// var result = rpc.result; // rpc response result
785 /// ... result.status[0]; // status of db_set_value() for /runinfo
786 /// ... result.status[1]; // status of db_set_value() for /equipment
787 /// }).catch(function(error) {
788 /// mjsonrpc_error_alert(error);
791 /// @param[in] paths Array of ODB paths (array of strings)
792 /// @param[in] values Array of ODB values (array of anything)
793 /// @param[in] id optional request id (see JSON-RPC specs) (object)
794 /// @returns new Promise
796 var req = new Object();
799 return mjsonrpc_call("db_paste", req, id);
802function mjsonrpc_db_set_value(path, value, id) {
803 /// \ingroup mjsonrpc_js
804 /// Write value info ODB.
806 /// RPC method: "db_set_value"
809 /// mjsonrpc_set_value("runinfo/run number", 123).then(function(rpc) {
810 /// var req = rpc.request; // reference to the rpc request
811 /// var id = rpc.id; // rpc response id (should be same as req.id)
812 /// var result = rpc.result; // rpc response result
813 /// ... result.status[0]; // status of db_set_value() for /runinfo
814 /// ... result.status[1]; // status of db_set_value() for /equipment
815 /// }).catch(function(error) {
816 /// mjsonrpc_error_alert(error);
819 /// @param[in] paths Array of ODB paths (array of strings)
820 /// @param[in] values Array of ODB values (array of anything)
821 /// @param[in] id optional request id (see JSON-RPC specs) (object)
822 /// @returns new Promise
824 var req = new Object();
826 req.values = [value];
827 return mjsonrpc_call("db_paste", req, id);
830function mjsonrpc_db_create(paths, id) {
831 /// \ingroup mjsonrpc_js
832 /// Create ODB entries
834 /// RPC method: "db_create"
836 /// @param[in] paths Array of ODB entries to create (array of objects)
837 /// @param[in] paths[i].path ODB path name to create (string)
838 /// @param[in] paths[i].type TID_xxx data type (integer)
839 /// @param[in] paths[i].array_length Optional array length (default is 1) (integer)
840 /// @param[in] paths[i].string_length Optional string length (default is NAME_LENGTH) (integer)
841 /// @param[in] id optional request id (see JSON-RPC specs) (object)
842 /// @returns new Promise
844 return mjsonrpc_call("db_create", paths, id);
847function mjsonrpc_cm_msg(message, type, id) {
848 /// \ingroup mjsonrpc_js
849 /// Get values of ODB variables
851 /// RPC method: "cm_msg1"
854 /// mjsonrpc_cm_msg("this is a new message").then(function(rpc) {
855 /// var req = rpc.request; // reference to the rpc request
856 /// var id = rpc.id; // rpc response id (should be same as req.id)
857 /// var status = rpc.result.status; // return status of MIDAS cm_msg1()
859 /// }).catch(function(error) {
860 /// mjsonrpc_error_alert(error);
863 /// @param[in] message Text of midas message (string)
864 /// @param[in] type optional message type, one of MT_xxx. Default is MT_INFO (integer)
865 /// @param[in] id optional request id (see JSON-RPC specs) (object)
866 /// @returns new Promise
868 var req = new Object();
869 req.message = message;
872 return mjsonrpc_call("cm_msg1", req, id);
875function mjsonrpc_get_timezone() {
876 /// Get timezone offset of server in hours
878 /// RPC method: "get_timezone"
881 /// mjsonrpc_get_timezone().then(function(rpc) {
882 /// var req = rpc.request; // reference to the rpc request
883 /// var tz = rpc.result; // server timezone
885 /// }).catch(function(error) {
886 /// mjsonrpc_error_alert(error);
889 /// @returns new Promise
891 var req = new Object();
892 return mjsonrpc_call("get_timezone", req, 0);
895function modbset(path, value)
896 /// \ingroup mjsonrpc_js
897 /// Simplified function to initiate an ODB write RPC request. This function returns immediately, without waiting for the request to complete. There is no way to check that the write request completed without error. Multiple calls to modbset() may result in out-of-order writes to ODB (later requests may be processed before earlier requests).
900 if (Array.isArray(path)) {
901 mjsonrpc_db_paste(path,value).then(function(rpc) {}).catch(function(error) {
902 mjsonrpc_error_alert(error); });
904 mjsonrpc_db_paste([path],[value]).then(function(rpc) {}).catch(function(error) {
905 mjsonrpc_error_alert(error); });
913function bkToObj(array) {
914 /// Midas banks-to-object: Parses a raw midas even received via the new bm_receive_event
915 /// call and converts it into an JS object of with following elements and returns it:
917 /// e.event_id <-- elements of midas event header
918 /// e.trigger_mask <-/
919 /// e.serial_number <-/
921 /// e.time_stamp_date<-/
924 /// e.banks_16bit <-- true if we have 16-bit banks
925 /// e.banks_32bit <-- true if we have 32-bit banks
926 /// e.banks_32bita <-- true if we have 64-bit aligned 32-bit banks
929 /// e.bank[] <-- array of banks
930 /// .name <-- name of bank
931 /// .type <-- bank type, one of TID_xxx
932 /// .size <-- bank size in bytes
933 /// .hexdata[] <-- array of raw (byte) data
934 /// .array[] <-- array of converted data (UINT16, UINT32, UINT32, INT32, FLOAT, DOUBLE)
936 /// This function is used by the event_dump.html page and can be used in a custom
937 /// page for single event displays.
941 let data8 = new Uint8Array(array);
942 let data16 = new Uint16Array(array);
943 let data32 = new Uint32Array(array);
945 // decode event header
946 e.event_id = data16[0];
947 e.trigger_mask = data16[1];
948 e.serial_number = data32[1];
949 e.time_stamp = data32[2];
950 e.time_stamp_date = new Date(e.time_stamp*1000);
951 e.data_size = data32[3];
953 let event_header_size = 16; // bytes
955 // decode banks size and type
956 e.bank_total_size = data32[4];
957 e.bank_flags = data32[5];
958 e.banks_16bit = (e.bank_flags === 0x01);
959 e.banks_32bit = (e.bank_flags === 0x11);
960 e.banks_32bita = (e.bank_flags === 0x31);
961 let bank_header_size = 8;
963 let i8 = event_header_size + bank_header_size;
965 //console.log("AAA bank type: " + e.banks_16bit + e.banks_32bit + e.banks_32bita);
967 // iterate over banks
968 while(i8 < e.data_size + event_header_size) {
970 b.name = String.fromCharCode(data8[i8], data8[i8 + 1], data8[i8 + 2], data8[i8 + 3]);
972 b.type = data16[i8/2 + 2];
973 b.size = data16[i8/2 + 3];
975 } else if (e.banks_32bit) {
976 b.type = data32[i8/4 + 1];
977 b.size = data32[i8/4 + 2];
979 } else if (e.banks_32bita) {
980 b.type = data32[i8/4 + 1];
981 b.size = data32[i8/4 + 2];
984 if (b.type >= tid_name.length)
989 if (b.type === TID_INT8) {
990 } else if (b.type === TID_UINT8) {
991 } else if (b.type === TID_INT16) {
993 } else if (b.type === TID_UINT16) {
995 } else if (b.type === TID_INT32) {
997 } else if (b.type === TID_UINT32) {
999 } else if (b.type === TID_INT64) {
1001 } else if (b.type === TID_UINT64) {
1003 } else if (b.type === TID_FLOAT) {
1005 } else if (b.type === TID_DOUBLE) {
1010 let aligned_size = align8(b.size);
1012 if (b.size % size_align != 0) {
1013 //console.log("b.size: " + b.size + " misalign: " + b.size % size_align);
1014 b.size -= (b.size % size_align);
1017 b.data = array.slice(i8, i8+b.size);
1020 //if (e.banks_32bit) {
1021 // let pad = align8(b.size) - b.size;
1026 b.hexdata = new Uint8Array(b.data);
1028 if (b.type === TID_INT8)
1029 b.array = new Int8Array(b.data);
1030 else if (b.type === TID_UINT8)
1031 b.array = new Uint8Array(b.data);
1032 else if (b.type === TID_INT16)
1033 b.array = new Int16Array(b.data);
1034 else if (b.type === TID_UINT16)
1035 b.array = new Uint16Array(b.data);
1036 else if (b.type === TID_INT32)
1037 b.array = new Int32Array(b.data);
1038 else if (b.type === TID_UINT32)
1039 b.array = new Uint32Array(b.data);
1040 else if (b.type === TID_INT64)
1041 b.array = new BigInt64Array(b.data);
1042 else if (b.type === TID_UINT64)
1043 b.array = new BigUint64Array(b.data);
1044 else if (b.type === TID_FLOAT)
1045 b.array = new Float32Array(b.data);
1046 else if (b.type === TID_DOUBLE)
1047 b.array = new Float64Array(b.data);
1049 b.array = "Unknown data type " + b.type;
1061 * js-indent-level: 3
1062 * indent-tabs-mode: nil