Project

General

Profile

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>