Javascript » History » Revision 18
Revision 17 (Torbjorn Carlqvist Admin, 09/05/2021 08:11 PM) → Revision 18/28 (Torbjorn Carlqvist Admin, 12/02/2022 02:23 PM)
h1. Javascript guide for DTXr code IDE Shows the various commands and events that can be used to build automation scripts. [[#Commands|Commands]] [[#Events|Events]] --- h2. Commands //Set this h3. *print* - Prints a message to THIS device id. //The var is used in commands below for convinience. var gThisDeviceId = 123456; /** LOG/DEBUG **/ //Prints to console footer log window as well as autmation.log //Note that automation.js is also written to by various services in DTX by //default, not only what you do with print() in your code. //Consider this as a volatile log where you debug and then clear from time to time. //10Mbyte is max then it will rollover to time-stamped zip file and automation.js is cleared. print("hello"); //Prints to automation_user.log //This statement is the only source for loggin in this file. //Consider this to be a persistant log of important process matters. //10Mbyte is max then it will rollover to time-stamped zip automation.log file anf automation-user.js is cleared. Controller.printToUserLog("hello user log"); /** BACnet related **/ //Translation helper for BACnet object ID->NAME //Many even arguments are enumerated where theese function can help print(getObjectTypeById(4)); //Binary Output print(getPropertyTypeById(85)); //presentValue <pre><code class="javascript">print("hello");</code></pre> // *** Write a value to h3. *readProperty* - Reads an object property *** Controller.writeProperty(85343,binaryOutput,0,presentValue,priority_1,active); // *** Read a value from a property. *** //Will return both primitiv and constructed (JSON) values //Primitive <pre><code class="javascript"> print(Controller.readProperty(85343/*TOCA DEV PC*/,binaryOutput,0,presentValue)); //Constructed (always JSON format from complex values) //A priorityArray property is one example of constructed result print(Controller.readProperty(85343/*TOCA DEV PC*/,binaryOutput,0,priorityArray)); // *** COV Subscribtion *** //With auto incremented process id, sensitivity (increment) of 1 (analog values) and subscription lifetime of 300s Controller.COVSubscribe(covProcIncr,85343/*TOCA DEV PC*/,analogInput,instance_0,noCovConfirmation,presentValue,1 /*sensitivity*/,300 /*lifetime (s)*/); //With fixed process /*********************************************************************************************** * @param {Number} device - The device id 123, sensitivity (increment) no sesnitivity (binary values) and subscription lifetime of 300s Controller.COVSubscribe(123,85343/*TOCA DEV PC*/,binaryInput,instance_0,noCovConfirmation,presentValue,null,300 /*lifetime (s)*/); //UN-Subscribe with specific process * @param {Number} objectType - The object type. Both id 10 Controller.COVSubscribe(123,85343,binaryInput,instance_0,null,presentValue,defaultIncrement,null); // *** Intrinsic Reporting (Alarms and Events) *** //Remote Event Subscribe Controller.eventSubscribe(someOtherDeviceId/*device id*/,instance_0/*Notification Class*/); //Enable event/alarm reporting on enumerated names can be used. * @param {Number} objectInstance - The object Controller.enableIntrinsicReporting(0/*NotificationClass*/,3/*delay*/,analogValue,instance_0,notifyTypeEvent); Controller.writeProperty(analogValue,instance_0,presentValue,priority_1,50); //TextMessage Controller.sendTextMessage(gThisDeviceId,"SOME_TYPE_OF_MSG","hello myself, what's up?"); //Acknowledge alarm and events Controller.acknowledgeAlarm(gThisDeviceId,analogInput,instance_0,processIdZero, ackNormal,1584383651150,"Toca",new Date().getTime()); //Issue an alert for instance. Must be a specific object via an Alert Enrollment Object //The recipients in the notification class connected to the shosen alert enrollment object will receive the alert alertEnrollmentObjectInstance = 0; propretaryEventType = 666; Controller.issueAlert(alertEnrollmentObjectInstance,analogInput,0,"To high!",propretaryEventType); Controller.getEnrollmentSummary(gThisDeviceId); //Send event notif local or remote nodes //DeviceId,NotificationClass,AckRequired,Message Controller.sendNotification(gThisDeviceId,0,1,"Coffe anyone?"); //Get all alarms for a specific device. Return JSON resp = print(Controller.getAlarmSummary(gThisDeviceId)); //Get all events for a specific device. Return JSON resp = print(Controller.getEventSummary(gThisDeviceId)); // *** Special Object Types *** // //Read a range of datapoints from a TrendLog object //The response is JSON with an array of value/timestamp Controller.readRange(gThisDeviceId,trendLogMultiple,0); // *** HTTP REST positive number. * @param {Number} propertyId - The property id. Both id and Web Socket *** //HTTP GET Request. Returns respons as string resp = Controller.HTTP_GET('https://httpbin.org','get','Accept:application/json|Content-Type:application/json','myparam=hello'); //HTTP POST(also PUT and PATCH) Request. Return response as string resp = Controller.HTTP_POST('https://httpbin.org/post' ,'Accept:application/json|Content-Type:application/json' ,'myparam=hello' ,'any payload string data'); //Web socket call to any webpage in the project file //This require that the page has loaded the Ws.js import. //Se HTTP Websocket template from the project tree sub menu Controller.sendToWS("mypage","Hello My Page this is a payload"); //Connect to a Web Socket //DTX has a built in single web socket client. //Connect Controller.connectWebSocket("wss://any.websocket.host"); //Send a message once connection is established Controller.sendWebSocketText("Hello"); // *** SQL relational database access *** //Note, SQL db is not embedded so JDBC config is made in settings in advance. //Only PostgresSQL is supported for the moment! //Simple query. Result (if any) will always enumerated names can be JSON! print(Controller.sqlExecuteQuery("select used. * from anytable")); //Inserts and updates are preferably solved with functions or procedures on //the databas side. @return {*} The CALL statement result can then be utilized: Controller.sqlExecuteQuery("CALL upsert_anytable("+name+",'"+age+"')"); //But of course a simple insert can also be sent... print(Controller.sqlExecuteQuery("insert into anytable values('kalle','13')")); // *** Timers and Schedulers *** //Show all current jobs (including system jobs) Controller.schedulerSummary(); //Pause all jobs Controller.pauseAllJobs(); //Pause a specific job Controller.pauseJob("JobA"); //Resume all jobs Controller.resumeAllJobs(); //Resume a specific job Controller.resumeJob("JobA"); //Start job //Eg. executes function myCallbackFunction() with argument "df" after 10 seconds Controller.startJob('Job1',10,'myCallbackFunction("df")'); //Eg. executes function myCallbackFunction() repeatedly every minute //with a start delay any type. It is dependent of 5 seconds Controller.startJob('Job2',5,60,'myCallbackFunction'); //Eg. start a CRON job that executes myCallbackFunction //at 00:10 AM (10 minute past midnight) every day Controller.startCronJob("Job3",'0 10 0 ? * * *','myCallbackFunction'); //Note: CRON can be difficult to construct. //Use the below link to both crete object type and property. Primitive values such as numbers and string but also verify your CRON strings. //https://www.freeformatter.com/cron-expression-generator-quartz.html JSON formatted text. ***********************************************************************************************/ //Cancel //Reads a job by using the name provided above present value from analog input object 0. Controller.cancelJob("Job3"); Controller.readProperty(85343,analogInput,0,presentValue); //Cancel all jobs Controller.cancelAllJobs(); //Cancel a specific jobs Controller.cancelJob("JobG"); //This is a special function where you can schedule //Use the execution of //a code snippet. //Arg1: job identifier - To paus/cancel the job. //Arg2: start delay (s) - Time until first exec //Arg3: period(s) - Time between exec, set result to 0 if no repetition is required. //Arg4: repeates - Number of repeates, null if infinit, 0 if no repeat //Arg5: code - Any Javascript Controller.scheduleExecution(5,0,0,"print('print once in 5 sec');"); // *** MISC *** //Send an email. Note, needs smtp-server config first Controller.SendEmail("torbjorn.carlqvist@davitor.com","anysubject","some body"); // *** Embedded JSON storage *** //Perfect to use when automation settings, states, structures etc must be persisted print and //the use of an external SQL database is unnecessary //Push a string to spcified queue (queue will be created if not exist) //This queue is persistant during reboot of the evice //All queues and records are stored in the collection "jsonstore.json" which can be found in project folder logic Controller.JSONPush("toca","msg5"); res = Controller.readProperty(85343,analogInput,0,presentValue); //Pop a string from the specified queue. FIFO! print(res); //Returns null if no strings found ( res > 0 ){ print("value larger than 0!"); print(Controller.JSONPop("toca")); print(Controller.JSONPersist("nisse")); } print(Controller.JSONPersist("1588058754445","palle")); </code></pre> print(Controller.JSONRestore("1588058754445")); print(Controller.JSONBrowse("toca")); //Change name on multiple local objects //This can be used when a group of objects need h3. *eventSubscribe* - Send request for intrinsic reporting notification to have save name prefix. //eg. when a sensor has multiple object and you want them to share same sensor name. Controller.updateLocalObjectNames("TestBI","newname"); remote node. //This method should be used when javascript forms a link between <pre><code class="javascript"> //an external interaface and the object stack. //Typically when a button on a HMI should update an binaryInput or //a reception of a BLE Beacon should update an analogInput. //This method will create an object if no object exists with same profilName property Controller.createOrUpdateLocalObject(analogInput,null,"MyObjectName",123); // *** File access ***/ //Basic file R/W/List for files in project folder (and sub folders) Controller.writeFile("file_rw_test.txt","Hello file handling!"); print(Controller.readFile("file_rw_test.txt")); print(Controller.listFiles(".txt",null)); print(Controller.listFiles(".json","mysubfolder")); print(Controller.removeFiles(".txt",null)); // *** OS operations ***/ //Run commands on host operatice system //Result is JSON string //The exit_code tells if successful or not. //There is a built in timeout if you accedently start a job that does not //stop of it's own. Like doing unlimited ping on Linux //No, there is no way to stop a command with Ctrl-C from JS. //Note, the process is running in foreground so if DTX dies the process dies too. print(Controller.execCommand("ping -n 3 google.com")); // *** Serial Ports ***/ //List all connected serial ports. /*********************************************************************************************** * @param {Number} device - The response device id * @param {Number} notificationClass - This is JSON and can tell a lot //about the serial port. For example in which USB socket it is connected. print(Controller.listSerialPorts()); //Connect to a serial port (multiple connection is allowed) //Use instance of the serial port name from remote notification class where the response from listSerialPorts() above. //As argument form a JSON according to specification. //Example of setting up a serial connection to ttyACM0 that handles //delimited responses with a "Return(0d)" at the END with a speed of 115200baud //Note that if a connection already occurs in this name it request will be closed automatically Controller.setupSerialPort("ttyACM0",'{"msgDelim":true,"baudrate":115200,"delimPattern":"0d","delimPosition":"end"}'); handled. * @return N/A ***********************************************************************************************/ //Send ASCII data to the connected port Controller.writeSerialAscii("ttyACM0","hello"); //Send HEX data to the serial port Controller.writeSerialHex("ttyACM0","03"); //Eg. Ctrl-C in HEX //Close serial port Controller.closeSerialPort("ttyACM0"); //NOTE: all received serial data enters the event callback "onSerialReceive" /*** MODBUS ***/ /* Modbus TCP */ //If needed, use this to simulate a slave on THIS device //Request for test purpose. //Will setup a demo image of regs and coils Controller.modbusTCPCreateSlave(); //Read coils (true/false) //Args: Slave IP, Slave Port, Start Addr, Count //Return: JSON Array with result print(Controller.modbusTCPReadCoils("localhost",502,1,1)); //Reading input discretes (true/false) //Args: Slave IP, Slave Port, Start Addr, Count //Return: JSON Array with result print(Controller.modbusTCPReadInputDiscretes("localhost",502,1,5)); //Reading input registers (Analog Inputs) //Can be either signed or unsigned 16-bit values. //Args: Slave IP, Slave Port, Start Addr, Count //Return: JSON Array with result print(Controller.modbusTCPReadInputRegisters("localhost",502,1,5)); //Reading holding registers (Analog Outputs) //Can be either signed or unsigned 16-bit values. //Args: Slave IP, Slave Port, Start Addr, Count //Return: JSON Array with result print(Controller.modbusTCPReadHoldingRegisters("localhost",502,1,5)); //Write to coil (!CAUTION!) //Note, always returns null //Args: Slave IP, Slave Port, Addr, Status (true=On/1, false=Off/0) Controller.modbusTCPWriteCoil("localhost",502,1,false); /* Modbus Serial */ //Note, setting null as port settings defaults to 9600/8N1 //A mock-up test slave for serial modbus //Args: Port, Port Settings, RTU Controller.modbusSerialCreateSlave("COM1",null,false); //Writing to a MODBUS slave coil via Serial RTU //Args: Port, Port Settings,RTU,reg address, value/state Controller.modbusSerialWriteCoil("COM2",null,false,2,true); //Reading notification from a MODBUS slave coil via Serial RTU //Args: Port, Port Settings,RTU,reg address Controller.modbusSerialReadCoils("COM2",null,false,1,2); /*** Controller management ***/ //Running reInit() will completly clear the JS-engine, stop all jobs device 84757 and notification class 0 //re-actiavate the code and finally call the init() method. Controller.reInit(); Controller.eventSubscribe(84757,0); </code></pre> h2. Events h3. *eventNotificationReceived* - Called when an intrinsic report notification is received. <pre><code class="javascript"> /*********************************************************************************************** * @param {Number} processIdentifier - Event process on the caller side * @param {Number} initiatingDevice - The device that send the event * @param {Number} object - The source object in readable format * @param {Number} objectType - The source object of the event * @param {Number} objectInstance - The instance of source object * @param {String} timeStampUTC - Event timestamp in UTC format * @param {Number} notificationClass - The NC handling this event on remote node * @param {Number} priority - Event priority * @param {Number} eventType - The type of event received * @param {String} messageText - Readable notification message * @param {Number} notifyType - Type of notification [0:Event,1:Alamr,2:AckNotif] * @param {Boolean} ackRequired - true if ack is required to clear this event on the remote node * @param {String} fromState - The previous state * @param {String} toState - The current state after the change * @param {Object} eventValues - A map of specific map of values for the particular eventType ***********************************************************************************************/ function eventNotificationReceived(processIdentifier,initiatingDevice,object,objectType,objectInstance,timeStampUTC,notificationClass,priority,eventType,messageText,notifyType,ackRequired,fromState,toState,eventValues){ //Use this event to act on notifications that is set to be subscribed by this device. } </code></pre>