last modification: 2025/04/30
InDriver Documentation
Getting started - download, installation, requirements 7
Install the Additional API(s) 18
● Null InDriver.debug( String debugMsg, String msgType = ‘debug’, Boolean cut=true ); 27
● String InDriver.debugVariables( ); 27
● String InDriver.driverName( ); 27
● String InDriver.configuration( String Array path ); 28
● String InDriver.currentPath( ); 29
● String InDriver.hookTs( Number hook ); 29
● String InDriver.hookTs( ); 29
● Boolean InDriver.import( String api ); 29
● Null InDriver.installExtensions( String extension); 30
● Null InDriver.installHook( Number hook ); 30
● Boolean InDriver.isHook( Number hook ); 31
● Boolean InDriver.isPrivateMessage(); 31
● Boolean InDriver.loadScript( Number scriptPath); 31
● String InDriver.messageData( ); 31
● String InDriver.messageSender( ); 32
● String InDriver.messageTs( ); 32
● String InDriver.messageTags( ); 32
● String InDriver.onHook( ms ); 33
● String InDriver.onHook( [ms1,ms2] ); 33
● Null InDriver.restartTask(String taskName) 33
● Null InDriver.sendMessage( String dt, String tags, String data ); 33
● Null InDriver.setFlag( String flag, String info ); 34
● Null InDriver.shutdown(); 35
● String InDriver.sqlExecute( String server, String query ); 35
● Boolean InDriver.sqlExecuteAll( String query ); 36
● Boolean InDriver.sqlIsSucceeded( ); 36
● String InDriver.sqlLastError( ); 36
● String InDriver.taskName( ); 37
● Null InHttpServerApi.debugMode( Boolean enabled ); 38
● Boolean InHttpServerApi.route( String path, String method ); 38
● Number InHttpServerApi.listen( String configString ); 38
● Number InHttpServerApi.listen( Object configJson ); 38
● Boolean OPCUAClientApi.connect( String &clientName, String &cfg = "" ) 40
● Boolean OPCUAClientApi.disconnect( String &clientName ) 40
● String OPCUAClientApi.readMultipleNodes( String &clientName, const String &nodeCfg ) 41
● Boolean OPCUAClientApi.writeMultipleNodes( String &clientName, String &nodeCfg ) 42
● Boolean OPCUAClientApi.isConnected( String &clientName ) 42
● String OPCUAClientApi.lastError() 43
● void JSOPCUAServerApi.start( const QString &cfg = "" ) 44
● void JSOPCUAServerApi.stop() 44
● Boolean JSOPCUAServerApi.addNodes( String &nodeCfg, String &folder = "" ) 44
● Boolean JSOPCUAServerApi.writeMultipleNodes( String &nodeCfg ) 45
● String JSOPCUAServerApi.readMultipleNodes( String &nodeCfg) 46
● String OPCUAServerApi.lastError() 46
● Null RestApi.commitWait( ); 50
● Null RestApi.defineRequest( String request, String def ); 50
Headers object can contain standard headers or any custom (raw) headers. 51
● Boolean RestApi.getData( String request ); 51
● String RestApi.getRawHeader( String request, String headerName); 51
● String RestApi.getRawHeaderPairs( String request ); 51
● String RestApi.isSucceeded(); 51
● Boolean RestApi.sendRequest( String request ); 52
● Boolean RestApi.sendRequest( String request, String def); 52
● Boolean RestApi.wait( Number timeout ); 52
● Null ModbusApiestApi.commit( ); 54
● Null ModbusApi.commitWait( ); 54
● Null ModbusApi.connectDevice( String device, String def ); 54
● Null ModbusApi.getAllData( ); 56
● Null ModbusApi.getDeviceData( String device ); 57
● Null ModbusApi.getDeviceRequestData( String device, String reg ); 57
● Null ModbusApi.getDeviceRequestValue( String device, String reg, Number Array addresses ); 58
● Boolean ModbusApi.isLastTransactionCompleted( String device ); 58
● Boolean ModbusApi.isLastTransactionCompleted(); 59
● Boolean ModbusApi.isSucceeded( ); 59
● Null ModbusApi.readDevice( String device, String def ); 59
● Null ModbusApi.wait( Number timeout ); 60
● Null ModbusApi.writeDevice( String device, String def ); 60
● bool SMTPApi.configure( String JsonSMTPCfg ); 63
● String SMTPApi.lastError( ); 63
● bool SMTPApi.send( String JsonEmailCfg ); 63
● Null TsApi.aggregate( String aggregator ); 67
● Boolean ProcessApi.close( String name ); 69
● Boolean ProcessApi.closeAll( ); 69
● Boolean ProcessApi.kill( String name ); 70
● Boolean ProcessApi.killAll( ); 70
● Number ProcessApi.pid( String name ); 70
● String ProcessApi.program( String name ); 70
● Boolean ProcessApi.setWorkingDirectory( String name, String directory); 70
● Boolean ProcessApi.start( String name, String program, String Array args ); 70
● String ProcessApi.state( String name ); 70
● Boolean ProcessApi.waitAllForFinished( Number msecs = 30000); 70
● Boolean ProcessApi.waitAllForStarted( Number msecs = 30000); 70
● Boolean ProcessApi.waitForFinished( String name, Number msecs ); 71
● Boolean ProcessApi.waitForStarted( String name, Number msecs ); 71
● String ProcessApi.workingDirectory( String name ); 71
● StringList PdfApi.allPageLabels() 72
● String PdfApi.asImageBase64( Number page, String format = "PNG" ) 72
● String PdfApi.load( String &file ) 73
● String PdfApi.pageText( Number page ) 73
● String PdfApi.pageLabel( Number page ) 74
● String PdfApi.readText( Number from = 0, Number count = -1 ) 74
● String PdfApi.savePageAsImage( Number page, String path ) 75
● String PdfApi.setCodec( String &codec ) 76
● Number PdfApi.pageCount() 76
● void PdfApi.setPassword( String &password ) 76
● String PdfApi.password() const 77
● String PdfApi.status() const 77
● String PdfApi.metadata() const 77
● Null FileApi.addFileSystemWatcherPath( String path ); 80
Boolean FileApi.appendLine( String name, String line ) 81
● Null FileApi.close( String name ); 81
● Null FileApi.closeAll( ); 81
● Boolean FileApi.copy( String from, String to ) 81
● Boolean FileApi.fileExists( String path ) 82
● Number FileApi.fileSize( String name ) 82
● bool FileApi.isOpen( String name ) 82
● Null FileApi.open( String name ,String file, String Array modes ); 82
● Null FileApi.readAll( String name ); 83
StringList FileApi.readLines( String name ) 83
● Boolean FileApi.removeFile( String path ) 83
● Null FileApi.removeFileSystemWatcherPath( String file ); 83
● Null FileApi.write( String name, String data); 84
● Null SerialPortApi.acceptRead( String name ); 85
● Null SerialPortApi.availablePorts( ); 85
● Null SerialPortApi.close( String name ); 85
● Null SerialPortApi.closeAll( ); 86
● Null SerialPortApi.error( String name ); 86
● Null SerialPortApi.open( String name, String portSettings ); 86
● Number SerialPortApi.write( String name, Number Array data); 87
● Null TcpSocketApi.acceptRead( String name ); 89
● Null TcpSocketApi.connect( String name, String socketSettings ); 89
● Null TcpSocketApi.disconnect( String name ); 90
● Null TcpSocketApi.disconnectAll( ); 90
● Boolean TcpSocketApi.write( String name, Number Array data); 90
● Null TcpServerApi.listen( String tcpServerCfg); 93
● Boolean TcpServerApi.write( String name, Number Array data, Number timeout); 93
Detailed description: (comming soon) 95
● Null UdpSocketApi.acceptRead( String name ); 95
● Null UdpSocketApi.bind( String name, String udpCfg ); 95
● Null UdpSocketApi.isBusy( String name); 95
Innovative Data Analytics is a recently established IT company located in Kraków, Poland, founded by programmer and automation engineer Andrzej Jarosz.
Leveraging his experience from his previous project, ANT Solutions, established in 2006, and maintaining a leading position in MES (Manufacturing Execution Systems), Andrzej has embarked on a new challenge with analytics.io.
The core idea driving Andrzej is to provide a smart data automation engine for engineers, developers, data analysts, and more, to build powerful systems using just a few lines of simple code.
The project is dedicated to both non-commercial users, who can use the software completely free, and commercial projects.
www.linkedin.com/in/andrzej-jarosz-6b6ba96
InDriver is a versatile automation engine that executes multiple JavaScript tasks simultaneously, facilitating easy solution creation within minutes, even without programming experience.
Utilize the specialized API to support technologies such as REST API, SQL, Modbus, TCP Server, Socket, Serial Port, Files, JSON, and more, to create seamless custom data integration in just a few lines of code.
Distinguished from typical SaaS, InDriver is an application for straightforward installation on local machines or in the cloud, providing unlimited data processing capabilities without cost constraints.
InStudio allows remote configuration of InDrivers across multiple computers, enabling distributed solutions, with numerous copy-paste examples for quick integration.
InDriver can be freely downloaded from https://www.inanalytics.io/downloads.
InDriver is absolutely free for non-commercial use.
For commercial use, users are obligated to purchase an annual plan.
InDriver is provided as a zip archive containing the InSetup.exe installer, which installs both InDriver and InStudio.
Currently, there is an available version for Windows operating systems, such as:
Windows 10 and Windows Server 2016 and later.
Unpack InSetup.zip and run InSetup.exe
|
Launch InStudio and InDriver. |
After the installation is completed, and both InDriver and InStudio are launched, InDriver starts as a console application, while InStudio starts as a window application, as shown in the screenshot below:
To start InDriver, run either indriver.exe or the recommended indriver.bat script.
The indriver.bat script includes a loop that automatically restarts indriver.exe if it crashes unexpectedly, improving stability during execution.
InDriver also accepts several command-line arguments:
The system requires a license, even for non-commercial use, when a free license is provided. To set up the license, please follow these steps:
To expedite the license request, please provide us with your organization's data and describe your project. If you are requesting a free license, please explain why your project is non-commercial.
We prioritize all license requests with maximum urgency and commit to responding within 24 hours.
Remark:
InStudio Setup allows you to configure SQL Servers, and user data, install InServer, and manage other APIs included in the InDriver package, as well as manage licenses.
InStudio communicates with InDriver, enabling their configuration, management, and programming of tasks using either a local machine connection or a database connection.
A local machine connection provides direct access to InDriver installed on the same machine. On the other hand, a database connection not only facilitates communication on the local machine but also enables the construction of a distributed system. In a distributed system, one or more InDrivers may run on various machines and be managed from a single InStudio.
Database communication becomes particularly valuable for system redundancy when configuring more than one database server. The schema below illustrates the database connection between InDrivers and InStudio.
One or more SQL Servers can serve as gateways by installing InServerAPI on them, a process easily facilitated through InStudio.
To configure SQL servers, open the 'Setup' menu and navigate to the 'InStudio' tab. By default, two servers are provided. Fill in the correct details:
Enter the 'Name' for the configured server in InStudio, remember to set 'Active' to true, and press the 'Save' button.
If valid data is provided, after a few seconds, the connection table on the left should display configured servers in the horizontal header, indicated in green for successful connections or red if the database connection failed.
The screenshot below illustrates a situation where the LocalPGSQL connection has failed, as indicated by the red status in the Connections table on the left.
To debug the reason for any error, click on the server name, which opens a server window with a table of errors. Click 'Refresh,' and the last 100 errors will be updated.
When SQL Server(s) are configured correctly, the next step is to install InServerAPI. InServerAPI is a set of SQL functions and tables used by InDrivers and InStudio to communicate with each other, and store logs, configurations, messages, etc.
To install InServerAPI, open the 'InServer' tab, select the previously configured SQL server from the combo box, and press 'Install.'
If the installation is successful, the installed SQL tables should be listed in the table, and the status should be indicated in green.
This step is not obligatory. The additional API may provide a set of SQL functions and tables to support the programming of various solutions.
Currently, TsApi (tsapi.sql) is available, which includes functions dedicated to JSON Time Series Processing. To install an additional API on the previously selected server, select the API by checking it and pressing the 'Install' button. If the installation is successful, the 'Installed API' table should display the installed API.
To begin configuring InDriver, click on the selected row in the column corresponding to the server or local connector.
If you prefer to use a database connection between InDriver and InStudio (with InServerAPI previously installed), simply press 'Import servers from InStudio.' All previously configured servers will be copied to InDriver's configuration. After this, press the 'Send+Restart' button. InDriver will restart and should be connected to the servers.
It is possible to add more SQL server connections for InDriver, not only the servers that play the role of InServers. InDriver tasks can easily interact with databases. Once the database source is configured, the InDriver.sqlExecute() function may be used by providing the configured server name.
To add a new task, click 'Insert' in the 'Tasks' context menu.
Open the task, select the 'Editor' tab, and write InDriver.debug('Hello world'); in the 'onStartup' script. Then, press the 'Save And Reload' button. Done! Your first JS task is being reloaded, and in a few seconds, you will see the debug log 'Hello world!' Great job!
To be done soon :)
InDriver can simultaneously execute multiple tasks. To insert a new task, click 'Insert' on the tasks content menu and select either 'New task' or 'Load task from file.' The second option enables loading saved task configurations, including example tasks with names starting from '@...' provided with InDriver in the default folder 'SavedTasks'. InDriver configuration is stored as a JSON object in the 'driver.cfg' file.
Inserting a new task:
Task configuration:
"Default Task configuration items are displayed with bold font and consist of:
Additionally, the user can add other JSON Objects, Variables, or Arrays that will store user data. In this example ‘userData’ object is added with Number and String values.
Each InDriver Task functions as a distinct JavaScript Engine, executing four ‘pre-defined functions:
onStartup() and onShutdown() are called once when the Task starts and stops, respectively.
The onHook() function is continuously called at intervals defined in the Task configuration, or it can be declared using InDriver.installHook(hook) and removed using InDriver.uninstallHook(hook).
The above image shows the Task default configuration set.
Hooks are intervals defined in milliseconds (ms); for example, a hook of 10000 (equals 10s), executing every 10s synchronized with the computer clock where InDriver is running.
InDriver's JavaScript tasks enhance programming efficiency through additional API Objects. The default InDriver object is equipped with an API specifically designed to interact with other tasks, access configuration, control hooks, and messages, execute SQL functions on configured servers, and create additional API Objects.
Outputs a debug message to the Debug console. The msgType parameter can take on values such as 'debug' (default), 'critical', 'fatal', 'info', or 'warning'. Then cut = false entire debugMsg will be logged else the message will be limited to 2000 characters.
Example:
⇒ onHook
InDriver.debug(‘This is my debug line’); InDriver.debug(‘This is my critical debug line’,’critical’); |
Returns entire list of variables used in global scope of JS code. The list is alse printed in debug console.
Example:
⇒ onHook
var i=10; var j = “variable”; var array = [1,2,3,j]; InDriver.debugVariables(); |
Returns the name of the InDriver.
Example:
⇒ onHook
const taskName = InDriver.driverName(); |
Returns a JSON string that includes the task's configuration located at the specified path.
Example:
⇒ onStartup
InDriver.configuration([]); // RETURNS: { "UserData": { "Number": 123, "String": "Abc" }, "active": true, "enableonHook": true, "enableonMessage": true, "hooks": [ 10000 ], "listening": [ "*" ], "name": "task", "onHookScript": "let ts= InDriver.hookTs();\nInDriver.debug('hooks => ' +InDriver.hooks()+' => ISO '+ ts.toISOString());", "onMessageScript": "", "onShutdownScript": "", "onStartupScript": "\nInDriver.setFlag('busy','calculations in progress');\nInDriver.debug(InDriver.configuration([]));\nInDriver.debug(InDriver.configuration([\"UserData\"]));", "tags": [ "*" ], "type": "JS" } InDriver.debug(InDriver.configuration(["UserData"])); //RETURNS { "Number": 123, "String": "Abc" } |
Returns the directory that contains the InDriver.exe.
⇒ onStartup
InDriver.debug(InDriver.currentPath()); |
Returns DateTime of currently executed hook
Read more about Hooks in the ‘onHook’ function description.
Example:
⇒ onHook
const ts= InDriver.hookTs(10000); // or if (InDriver.isHook(10000)) { const ts= InDriver.hookTs(); } |
.
Creates a JavaScript object with InDriver API.
List of available InDriver APIs:
The function returns true when the API object is successfully created; otherwise, it returns false when the apiName is incorrect.
Example:
⇒ onStartup
InDriver.import('Modbus'); Modbus.connectDevice('IOLogic','{"mode": "TCP", "networkAddress": "192.168.0.22"}'); |
When InDriver.import('Modbus'); is called, the 'Modbus' object is created, offering a set of additional functions.
Installs JavaScript extensions to add functionality that is not available in a standard ECMAScript implementation.
Available Extensions:
Example:
⇒ onStartup
InDriver.installExtensions(“ConsoleExtension”); |
Initiates the execution of the onHookScript for each hook defined in milliseconds. Typically called in the 'onStartupScript,' but can be used anywhere. Each JS task can install multiple hooks that will be simultaneously executed, for example, every 10s, 60s, and 3600s. Hooks are synchronized with the system clock.
Read more about Hooks in the ‘onHook’ function description.
Example:
⇒ onStartup
InDriver.installHook(10000); // 10 seconds InDriver.installHook(60000); //1-minute InDriver.installHook(3600000); //1-hour |
.
Returns true if the current execution of the onHook function is due to the hook interval; otherwise, returns false.
Read more about Hooks in the ‘onHook’ function description.
Example:
⇒ onHook
if (InDriver.isHook(10000)) { let ts= InDriver.hookTs(10000); } |
Returns true if the current message comes from this task otherwise, returns false.
It is equivalent to if (InDriver.taskName() === InDriver.messageSender()) {}
Example:
⇒ onMessage
if (InDriver.isPrivateMessage()) { // this is private message } |
Loads JS script from file path scriptPath. ScriptPath can point to script file in current InDriver working directory or to any other location
Example:
⇒ onStartup
InDriver.loadScript(“scriptslibrary/script.js” ); //or InDriver.loadScript(“c:/program files/InDriver/scriptslibrary/script.js” ); |
Returns the data attached by another task when invoking InDriver.sendMessage with tags listened to by this task.
Example:
⇒ onMessage
const msgData = InDriver.messageData( ); |
Returns the name of another task that invoked InDriver.sendMessage with tags listened to by this task.
Example:
⇒ onMessage
const msgSender = InDriver.messageSender( ); |
Returns the timestamp (DateTime) on which another task invoked InDriver.sendMessage with tags listened to by this task
Example:
⇒ onMessage
const msgTs = InDriver.messageTs( ); |
Returns the tags attached by another task when invoking InDriver.sendMessage with tags listened to by this task.
Tags are used to identify different messages; for example, all messages with data that needs to be logged in the database can be marked with the 'archive' tag.
Example:
⇒ onMessage
const msgTags = InDriver.messageTags( ); |
Evaluates onHook script immediately, simulating real hook event. Function useful during debugging, called in onStartup saves time of waiting for hook event.
Example:
⇒ onStartup
InDriver.onHook(10000); // calls immediately 10000ms onHook script. InDriver.onHook(1000, 10000); // calls immediately onHook script simulating 1000 and 10000ms hooks. |
The InDriver.restartTask(taskName); function stops and restarts a running task within the InDriver application.
This function is useful for implementing retry logic, reacting to transient errors, or refreshing task execution without restarting the entire application.
Sends a message to all listening tasks. Each task can listen to all other tasks ('*'), specified tasks, or specified tags.
Arguments: dt for timestamp, tags as an array describing the message, and data as a string containing data sent with the message.
Example:
⇒ onHook
var cd= new Date(); var data = InDriver.sqlExecute(‘LocalDatabase’, ‘select * from public.table;’); InDriver.sendMessage(cd.getDate(), {‘archive’}, data); |
Sets a flag with associated flag information (info). Flags play a role as additional information is displayed in the 'Status' tab.
Example:
⇒ onHook
InDriver.setFlag('busy','calculations in progress'); |
Function immediately stops all currently running tasks and gracefully exits the InDriver application. This function is available only when InDriver is started in batch mode (using the -mode batch argument). It is designed for scenarios where InDriver should run a set of automated tasks or scripts and terminate upon receiving a shutdown request — for example, from within a script or triggered by external logic.
Note: Calling this function in modes other than batch has no effect.
⇒ onHook
InDriver.shutdown(); |
Executes an SQL query on the database related to the specified server. Returns a JSON array with the retrieved rows. Each row is represented as a JSON object with variable keys corresponding to columns and values corresponding to their values. Servers are defined in the InDriver configuration item server.
Example:
⇒ onHook
var data = InDriver.sqlExecute(‘localserver’, ‘select * from public.table’); |
Executes an SQL query on all database servers defined in InDriver. Returns true when the execution succeeds on all servers or false if even one execution fails.Remark: If false is returned, some queries may have been executed successfully.
Example:
⇒ onHook
var b = InDriver.sqlExecuteAll( ‘insert into public.table ( ts timestamp with time zone, task text ) values (now(), ‘’‘+InDriver.taskName()+’’’);’); |
Returns true if last sqlExecute or sqlExecuteAll have been executed successfully otherwise, it returns false.
Example:
⇒ onHook
var data = InDriver.sqlExecute(‘localserver’, ‘select * from public.table’); if (!InDriver.sqlIsSucceeded()) { InDriver.debug(InDriver.sqlLastError()); } |
Returns an error string if the last sqlExecute or sqlExecuteAll was not executed successfully, otherwise, it returns an empty string.
Example:
⇒ onHook
var data = InDriver.sqlExecute(‘localserver’, ‘select * from public.table’); if (!InDriver.sqlIsSucceeded()) { InDriver.debug(InDriver.sqlLastError()); } |
Returns the name of the task.
Example:
⇒ onHook
const taskName = InDriver.taskName(); |
The InHttpServerApi allows you to launch an HTTP server inside an InDriver task. It enables defining custom API endpoints (routes) that call JavaScript functions and return dynamic responses. This API is ideal for integrating InDriver with external systems, mobile apps, operator terminals, or exposing task data and controls over REST.
Enables or disables debug mode. When enabled, incoming HTTP requests and route handling details are printed to the console for debugging purposes.
Tries to bind a HttpServer to address and port. Returns the server port upon success, 0 otherwise.
Available configuration keys:
Example:
InDriver.import('HttpServerApi'); function getStatus(request) { InDriver.debug("getStatus request: " + JSON.stringify(request)); return { message: "System OK, user=" + request.body.name }; } function getData(request) { InDriver.debug ("getData request: " + JSON.stringify(request)); let ts = new Date(); // można użyć jako timestamp do logów let result = InDriver.sqlExecute("azureserver", "select * from public.shelly order by ts desc limit 1;"); InDriver.debug("SQL result: " + result); return JSON.parse(result); } HttpServerApi.debugMode(true); HttpServerApi.route("/api/<arg>", "post"); let port = HttpServerApi.listen({ "address":"any", "port": 8080 }); InDriver.debug("HTTP server started on port: " + port); |
Registers a new HTTP route. The request to this route will call corresponding to pattern JS and method functions.
Clears previously set headers and set new defined in JSON format
Example:
InDriver.import('HttpServerApi'); function Control(request) { InDriver.debug("getStatus request: " + JSON.stringify(request)); HttpServerApi.setCorsHeaders( {"Access-Control-Allow-Origin" : "*", "Access-Control-Allow-Methods" :"GET, POST, PUT, DELETE, OPTIONS ", "Access-Control-Allow-Headers" :"Content-Type"} return “”; } HttpServerApi.route("/api/<arg>", "Control"); |
The JSOPCUAClientApi provides an interface for interacting with OPC UA servers as a client. It allows connecting to servers, browsing nodes, reading and writing node values, and managing multiple OPC UA client connections.
Establishes a connection to an OPC UA server.
Example:
⇒ onStartup
InDriver.import("OPCUAClientApi"); OPCUAClientApi.connect("Client1", '{"EndpointUrl":"opc.tcp://localhost:4840", "Timeout":5000}'); |
Disconnects a specified client from the server.
Example:
⇒ onStartup
InDriver.import("OPCUAClientApi"); OPCUAClientApi.connect("Client1", '{"EndpointUrl":"opc.tcp://localhost:4840", "Timeout":5000}'); OPCUAClientApi.disconnect("Client1"); |
Browses the OPC UA server's nodes starting from a specified node.
Example:
⇒ onStartup
InDriver.import("OPCUAClientApi"); OPCUAClientApi.connect("Client1", '{"EndpointUrl":"opc.tcp://localhost:4840", "Timeout":5000}'); let nodes = OPCUAClientApi.browse("Client1", "ns=2;i=100", "", 10); InDriver.debug(nodes); OPCUAClientApi.disconnect("Client1"); |
Reads multiple nodes' values from the server.
Example:
⇒ onStartup
InDriver.import("OPCUAClientApi"); OPCUAClientApi.connect("Client1", '{"EndpointUrl":"opc.tcp://localhost:4840", "Timeout":5000}'); |
⇒ onHook
let data = OPCUAClientApi.readMultipleNodes("Client1", '[{"nodeId":"ns=2;s=Temperature"}]'); InDriver.debug(data); |
Writes values to multiple nodes on the server.
Example:
⇒ onStartup
InDriver.import("OPCUAClientApi"); OPCUAClientApi.connect("Client1", '{"EndpointUrl":"opc.tcp://localhost:4840", "Timeout":5000}'); |
⇒ onHook
OPCUAClientApi.writeMultipleNodes("Client1", '[{"nodeId":"ns=2;s=Temperature","value":25}]'); |
Checks if a client is connected to the server.
Example:
⇒ onStartup
InDriver.import("OPCUAClientApi"); OPCUAClientApi.connect("Client1", '{"EndpointUrl":"opc.tcp://localhost:4840", "Timeout":5000}'); let status = OPCUAClientApi.isConnected("Client1"); InDriver.debug("Connected: " + status); |
Retrieves the last error message.
Returns: The last error message as a string.
Example:
⇒ onStartup
InDriver.import("OPCUAClientApi"); OPCUAClientApi.connect("Client1", '{"EndpointUrl":"opc.tcp://localhost:4840", "Timeout":5000}'); let error = OPCUAClientApi.lastError(); InDriver.debug("Last Error: " + error); |
The JSOPCUAServerApi provides an interface for setting up and managing an OPC UA server. It supports starting and stopping the server, adding nodes, and reading/writing node values.
Starts the OPC UA server with a specified configuration.
Example:
⇒ onStartup
InDriver.import("OPCUAServerApi"); OPCUAServerApi.start('{"EndpointUrl":"opc.tcp://localhost:4840"}'); |
Stops the OPC UA server.
Example:
⇒ onStartup
InDriver.import("OPCUAServerApi"); OPCUAServerApi.start('{"EndpointUrl":"opc.tcp://localhost:4840"}'); |
⇒ onShutdown
OPCUAServerApi.stop(); |
Adds nodes to the OPC UA server.
Example:
⇒ onStartup
InDriver.import("OPCUAServerApi"); OPCUAServerApi.start('{"EndpointUrl":"opc.tcp://localhost:4840"}') OPCUAServerApi.addNodes('[{"nodeId":"ns=2;s=TemperatureSensor","name":"Sensor"}]', "Objects"); |
Writes values to multiple nodes on the server.
Example:
⇒ onStartup
InDriver.import("OPCUAServerApi"); OPCUAServerApi.start('{"EndpointUrl":"opc.tcp://localhost:4840"}') OPCUAServerApi.addNodes('[{"nodeId":"ns=2;s=TemperatureSensor","name":"Sensor"}]', "Objects"); |
⇒ onHook
OPCUAServerApi.writeMultipleNodes('[{"nodeId":"ns=2;s=Temperature","value":22.5}]'); |
Reads values from multiple nodes on the server.
Example:
Example:
⇒ onStartup
InDriver.import("OPCUAServerApi"); OPCUAServerApi.start('{"EndpointUrl":"opc.tcp://localhost:4840"}') OPCUAServerApi.addNodes('[{"nodeId":"ns=2;s=TemperatureSensor","name":"Sensor"}]', "Objects"); |
⇒ onHook
let data = OPCUAServerApi.readMultipleNodes('[{"nodeId":"ns=2;s=Temperature"}]'); InDriver.debug(data); |
Retrieves the last error message.
Returns: The last error message as a string.
Example:
⇒ onStartup
InDriver.import("OPCUAClientApi"); OPCUAServerApi.connect("Client1", '{"EndpointUrl":"opc.tcp://localhost:4840", "Timeout":5000}'); let error = OPCUAServerApi.lastError(); InDriver.debug("Last Error: " + error); |
The RestApi object provides functions that simplify the programming of RESTful API calls. The following illustrative examples showcase three solutions enabled by the JS API provided with InDriver: simple single request calling, simultaneous calling of multiple requests, and collecting data from RestAPI and mixed APIs, such as ModbusApi and RestApi.
Example 1: Calling a single request and waiting for a response or timeout.
Retrieve the weather forecast for Kraków, Poland, and log the data into the Azure SQL Database Server every 1 minute. Replace 'your_app_id' with your OpenWeatherMap.org application ID.
⇒ onStartup
InDriver.import("RestApi"); RestApi.defineRequest('Krakow','{"url":"https://api.openweathermap.org/data/2.5/weather?appid=your_app_id&q=krakow","timeout":5000, "type":"get","headers":{"ContentTypeHeader":"application/json"}}'); InDriver.installHook(60000); |
⇒ onHook
RestApi.sendRequest('Krakow); if (RestApi.isSucceeded()) { let ts= InDriver.hookTs(); const data = RestApi.getData('Krakow'); InDriver.debug(data); InDriver.sqlExecute("azureserver", "insert into public.weather (source, ts, data ) values ( 'Krakow','"+ts.toISOString()+"',$$"+data+"$$);"); } |
Example 2: Simultaneously calling multiple requests and waiting for responses or timeouts.
Retrieve the weather forecast for Kraków, Poland, and Chicago, USA, and log the data into the Azure SQL Database Server every 1 minute. This method ensures that both requests are executed simultaneously.
⇒ onStartup
InDriver.import("RestApi"); RestApi.defineRequest('Krakow','{"url":"https://api.openweathermap.org/data/2.5/weather?appid=your_app_id&q=krakow","timeout":5000, "type":"get","headers":{"ContentTypeHeader":"application/json"}}'); RestApi.defineRequest(‘Chicago','{"url":"https://api.openweathermap.org/data/2.5/weather?appid=your_app_id&q=chicago","timeout":5000, "type":"get","headers":{"ContentTypeHeader":"application/json"}}'); InDriver.installHook(60000); |
⇒ onHook
RestApi.begin(); RestApi.sendRequest('Krakow'); RestApi.sendRequest('Chicago'); RestApi.commitWait(); if (RestApi.isSucceeded()) { let ts= InDriver.hookTs(); const dataFromKrakow = RestApi.getData('Krakow'); const dataFromChicago = RestApi.getData('Chicago'); InDriver.debug(‘Krakow: ’ + dataFromKrakow + ‘\nChicago: ‘ + dataFromChicago); InDriver.sqlExecute("azureserver", "insert into public.weather (source, ts, data ) values ( 'Krakow','"+ts.toISOString()+"',$$"+dataFromKrakow+"$$);"), } |
Example 3: Simultaneously calling multiple mixed API requests and waiting for responses or timeouts.
Retrieve the weather forecast for Kraków, Poland, and IO states from a Modbus device (Moxa IOLogic) simultaneously. This method ensures that both requests are executed simultaneously.
⇒ onStartup
InDriver.import("RestApi"); InDriver.import("ModbusApi"); RestApi.defineRequest('Krakow','{"url":"https://api.openweathermap.org/data/2.5/weather?appid=your_app_id&q=krakow","timeout":5000, "type":"get","headers":{"ContentTypeHeader":"application/json"}}'); Modbus.connectDevice('IOLogic','{"mode" : "TCP", "networkAddress" : "192.168.0.22"}'); InDriver.installHook(60000); |
⇒ onHook
Modbus.begin(); RestApi.begin(); RestApi.sendRequest('Krakow'); Modbus.readDevice('IOLogic','{"name": "coils1", "type": "COILS", "address":1, "size":8}'); Modbus.commit(); RestApi.commit(); Modbus.wait(); RestApi.wait(); const weatherData = RestApi.getData('Krakow'); const modbusData = Modbus.getAllData(); let ts = InDriver.hookTimestamp(); InDriver.sqlExecute("azureserver", "insert into public.weather (source, timestamp, data ) values ( 'Krakow','"+ts.toISOString()+"',$$"+weatherData +"$$);"); InDriver.sqlExecute("azureserver", "insert into public.iologic (source, timestamp, data ) values ( 'IoLogic','"+ts.toISOString()+"',$$"+modbusData+"$$);"); |
Similar to SQL, this function initiates a block of code where multiple RestApi.sendRequest calls can be called. Following RestApi.begin(), all RestApi.sendRequest() calls are not executed immediately but will be processed after the execution of the RestApi.commit() or RestApi.commitWait() commands. Learn more about making simultaneous calls to multiple REST API requests or even mixed API requests (e.g., RestApi and ModbusApi)
This function concludes the block of code initiated by RestApi.begin() and executes all RestApi.sendRequest functions called within the block. The function does not wait for responses or timeouts. For a version that does wait until all answers are completed or timed out, refer to RestApi.commitWait().
This function concludes the block of code initiated by RestApi.begin(), executes all RestApi.sendRequest calls, and waits for responses or timeouts. For a version that does not wait until all answers are completed or timed out, refer to RestApi.commit().
Defines a RESTful API data request with the name 'request', which can be invoked using the sendRequest function. Multiple requests can be defined, and they can be easily called by providing only their names.
The request parameters are stored in 'def' as JSON and consist of the following keys: 'url', 'timeout', 'type', 'headers', and “rawData”. Below is an example of a REST API definition:
{ "url": "https://api.openweathermap.org/data/2.5/weather?appid=your_app_id&q=krakow", "timeout": 5000, "type": "get", "headers": { "ContentTypeHeader": "application/json" }, “rawData”:”” } |
The function returns the data obtained from the previous call to RestApi.sendRequest() for the specified request name request, as defined in RestApi.defineRequest().
The function returns the value of specified headerName from the previous call to RestApi.sendRequest() for the specified request name request, as defined in RestApi.defineRequest().
The function returns returned headers with corresponding values from the previous call to RestApi.sendRequest() for the specified request name request, as defined in RestApi.defineRequest().
Returns true if the preceding call to RestApi.sendRequest() or block’s functions: RestApi.commit() or RestApi.commitWait() was successful, indicating that a valid response was received before the specified timeout.
Sends a RESTful API request with the name request, as defined using the RestApi.defineRequest function. The function waits until the response is received or until the specified timeout is reached if not called in a block starting from RestApi.begin(). When RestApi.defineRequest is called within the block starting from RestApi.begin(), the request is postponed until RestApi.commit() or RestApi.commitWait() is called. Learn more about making simultaneous calls to multiple REST API requests or even mixed API requests (e.g., RestApi and ModbusApi).
RestApi.sendRequest(String request, String def) replaces the request definition key’s values, provided in the previous RestApi.defineRequest call. When the request was not previously defined, the new request is created with the name request and parameters def but is not added to the defined request.
The function returns false if the request name provided in the name argument has not been defined previously; otherwise, it returns true.
The function waits for the completion of the previously called RestApi.commit(). It continues to wait until the response is received or until the specified timeouts, as defined in the request, are reached.
The function waits for the completion of the previously called RestApi.commit(). It continues to wait until the response is received or until the specified timeout is reached.
The ModbusApi object offers functions that streamline the programming of Modbus device read and write operations. ModbusApi supports both instant calls to the device and grouping calls using SQL-like begin() and commit() or commitWait() blocks. Please refer to the RestApi description for detailed information on instant and grouping calls.
⇒ onStartup
InDriver.import("RestApi"); InDriver.import("ModbusApi"); RestApi.defineRequest('Krakow','{"url":"https://api.openweathermap.org/data/2.5/weather?appid=your_app_id&q=krakow","timeout":5000, "type":"get","headers":{"ContentTypeHeader":"application/json"}}'); Modbus.connectDevice('IOLogic','{"mode" : "TCP", "networkAddress" : "192.168.0.22"}'); InDriver.installHook(60000); |
⇒ onHook
Modbus.begin(); RestApi.begin(); RestApi.sendRequest('Krakow'); Modbus.readDevice('IOLogic','{"name": "coils1", "type": "COILS", "address":1, "size":8}'); Modbus.commit(); RestApi.commit(); Modbus.wait(); RestApi.wait(); const weatherData = RestApi.getData('Krakow'); const modbusData = Modbus.getAllData(); let ts = InDriver.hookTimestamp(); InDriver.sqlExecute("azureserver", "insert into public.weather (source, ts, data ) values ( 'Krakow','"+ts.toISOString()+"',$$"+weatherData +"$$);"); InDriver.sqlExecute("azureserver", "insert into public.iologic (source, ts, data ) values ( 'IoLogic','"+ts.toISOString()+"',$$"+modbusData+"$$);"); |
Similar to SQL, this function initiates a block of code where multiple ModbusApi.readDevice() or ModbusApi.writeDevice() calls can be called. Following ModbusApi.begin(), ModbusApi.readDevice(), and ModbusApi.writeDevice() calls are not executed immediately but will be processed after the execution of the ModbusApi.commit() or ModbusApi.commitWait() commands. Learn more about making simultaneous reads or writes to multiple Modbus devices or even mixed API requests (e.g., RestApi and ModbusApi).
This function concludes the block of code initiated by ModbusApi.begin() and executes all ModbusApi.readDevice() or ModbusApi.writeDevice() functions called within the block. The function does not wait for responses or timeouts. For a version that does wait until all answers are completed or timed out, refer to ModbusApi.commitWait().
This function concludes the block of code initiated by ModbusApi.begin(), executes all ModbusApi.readDevice() or ModbusApi.writeDevice() functions, and waits for responses or timeouts. For a version that does not wait until all answers are completed or timed out, refer to ModbusApi.commit().
Creates a Modbus device connection named device with connection parameters included in def. Once the connection is created, ModbusApi.readDevice() or ModbusApi.writeDevice() functions can be invoked with the connected device's name. Multiple connections can be defined. Users do not have to keep checking if the connection is still alive because InDriver performs non-stop checks, and when a disconnection occurs, it is automatically reconnected. The connection parameters are stored in def' as JSON and consist of the following keys:
Default parameters are not obligatory.
Below are examples of connection definitions (def):
{ "mode": "TCP", "networkAddress": "192.168.0.22" } |
{ "mode": "TCP", "networkAddress": "192.168.0.22", "networkPort": 502, "timeoutMs": 3000, "numberOfRetries": 3 } |
{ "mode": "RTU", "serialPortName": "COM1" } |
{ "mode": "RTU", "serialPortName": "COM1" "baudRate": 9600, "parity": 2, "dataBits": 8, "stopBits": 1, "timeoutMs": 3000, "numberOfRetries": 3 } |
Below are examples of the use of ModbusApi.connecDevice()
ModbusApi.connecDevice( ‘MoxaIOLogicTCP’,’{ "mode": "TCP", "networkAddress": "192.168.0.22"}’); ModbusApi.connecDevice( ‘MoxaIOLogicRTU’,’{ "mode": "RTU", "serialPortName": "COM1"}’); |
Returns data collected for all defined devices in the previous ModbusApi.readDevice() or multiple ModbusApi.readDevice() function calls when invoked within a block between ModbusApi.begin() and ModbusApi.commit() or ModbusApi.commitWait().
For example, from a block with two ModbusApi.readDevice() functions that read devices Moxa1 and Moxa2, as shown below:
ModbusApi.begin(); ModbusApi.readDevice('Moxa1','{"name": "coilsA", "type": "COILS", "address":1, "size":4}'); ModbusApi.readDevice('Moxa1','{"name": "coilsB", "type": "COILS", "address":5, "size":4}'); ModbusApi.readDevice('Moxa2','{"name": "coils", "type": "COILS", "address":1, "size":8}'); ModbusApi.commitWait(); |
ModbusApi.getAllData() returns the collected data when the readout is successful:
{ "Moxa1": { "Read": { "coilsA": { "1": true, "2": false, "3": true, "4": false }, "coilsB": { "5": true, "6": false, "7": true, "8": false } } }, "Moxa2": { "Read": { "coils": { "1": true, "2": false, "3": true, "4": false, "5": true, "6": false, "7": true, "8": false } } } } |
Similar to the ModbusApi.getAllData() function, this function returns a portion of the collected data related to the specified device named device as defined in the ModbusApi.readDevice() function. In the above example presented for the ModbusApi.getAllData() function, ModbusApi.getDeviceData("Moxa1") returns:
{ "Moxa1": { "Read": { "coilsA": { "1": true, "2": false, "3": true, "4": false }, "coilsB": { "5": true, "6": false, "7": true, "8": false } } } } |
Similar to the ModbusApi.getDeviceData() function, this function returns a portion of the collected data related to the specified device named device and the register named reg as defined in the ModbusApi.readDevice() function. In the above example presented for the ModbusApi.getDeviceAllData() function, ModbusApi.getDeviceRequestData("Moxa1", "coilsA") returns:
{ "Moxa1": { "Read": { "coilsA": { "1": true, "2": false, "3": true, "4": false } } } } |
Similar to the ModbusApi.getDeviceRequestData() function, this function returns the selected values whose addresses are listed in an array named addresses, related to the specified device named device, and the register named reg as defined in the ModbusApi.readDevice() function. In the above example presented for the ModbusApi.getDeviceAllData() function, ModbusApi.getDeviceRequestValue("Moxa1", "coilsA", [1, 2, 3]) returns
5 |
Binary 101
Returns true if the most recent transaction involving the specified device was completed successfully without any errors or timeouts. If the specified device was not involved in the last transaction, or if the transaction encountered an error or timeout, the function returns false.
Returns true if in the most recent transaction encountered an error or timeout. otherwise returns false.
Returns true if the preceding call to RestApi.readDevice() or RestApi.writeDevice() or block’s functions: RestApi.commit() or RestApi.commitWait() was successful, indicating that a valid response was received before the specified timeout.
Sends a Modbus read device request to the device with the name device as defined using the ModbusApi.connectDevice() function. The function waits until the response is received or until the specified timeout is reached if not called in a block starting from ModbusApi.begin().
When ModbusApi.readDevice is called within the block starting from ModbusApi.begin(), the request is postponed until ModbusApi.commit() or ModbusApi.commitWait() is called.
Learn more about making simultaneous calls to multiple REST API requests or even mixed API requests (e.g., RestApi and ModbusApi).
The argument def is passed as JSON and includes the definition of the Modbus read request. It consists of the following key-value pairs:
{ "name": "coils1", “deviceAddress”:1, "type": "COILS", "address": 1, "size": 8 } |
Below is an example of Modbus Read Device Request:
ModbusApi.readDevice(‘Moxa’, ‘{ "name": "coils1", "type": "COILS", "address": 1, "size": 8 }’); |
Before using the ModbusApi.readDevice function, the device must be connected using the ModbusApi.connectDevice function.
The function returns false if the device name provided in the name argument has not been defined previously; otherwise, it returns true.
The function waits for the completion of the previously called ModbusApi.commit(). It continues to wait until the response is received or until all specified request timeouts, as defined in the request, are reached.
The function waits for the completion of the previously called ModbusApi.commit(). It continues to wait until the response is received or until the specified timeout is reached.
Similar to the ModbusApi.readDevice() function, the ModbusApi.writeDevice() function executes a Modbus device write request.
The argument def is passed as JSON and includes the definition of the Modbus write request. It consists of the following key-value pairs:
Refer to the device’s Modbus Register Map, Modbus protocol, and the connected device’s limitations.
{ "name": "coils1", “deviceAddress”:1, "type": "COILS", "address": 1, "data": [1,1,1] } |
Below is an example of Modbus Write Device Request:
ModbusApi.writeDevice(‘Moxa’, ‘{ "name": "coils1", "type": "COILS", "address": 1, "data": [1,1,1] }’); |
Before using the ModbusApi.writeDevice function, the device must be connected using the ModbusApi.connectDevice function.
The function returns false if the device name provided in the name argument has not been defined previously; otherwise, it returns true.
The SMTPApi object offers functions that streamline the email sending, supporting both instant send commands calls and grouping calls using SQL-like begin() and commit() blocks.
E-mails sending Example Code Block
InDriver.import('SMTPApi'); SMTPApi.configure('{"email":"sender@gmail.com","name":"Sender Name","server":"smtp.gmail.com","password":"password "}'); SMTPApi.begin(); SMTPApi.send('{"email":"contact@inanalytics.io","name":"Contact","subject":"First email from InDriver","text":"InDriver can send e-mails :)"}'); SMTPApi.send('{"email":"contact@inanalytics.io","name":"Contact","subject":"Second email from InDriver","text":"InDriver can send e-mails :)"}'); SMTPApi.commit(); |
or direct send one e-email, without begin()...commit() block;
InDriver.import('SMTPApi'); SMTPApi.configure('{"email":"sender@gmail.com","name":"Sender Name","server":"smtp.gmail.com","password":"password "}'); SMTPApi.send('{"email":"contact@inanalytics.io","name":"Contact","subject":"First email from InDriver","text":"InDriver can send e-mails :)"}'); |
Function initiates a block of code where multiple SMTPApi.send function will be collected before SMTPApi.commit will send them one-by-one in one efficient loop.
This function sould be called first to configure SMTP Server and Sender as string with JSON Object containing following values:
Complete JsonCfg Object should contain following key-values
{
"email":"example@gmail.com",
"name":"Sender Name",
"server":"smpt server address",
"password":"password"
}
Function return true valid SMTP configuration is provided or false when an error occurred.
Function sends all mails collected within SMTPApi.begin() and SMTPApi.commit() code block in one efficient loop, returning true when all emails are sent or false when an error occurred.
Function return last error string
Function sends immediately email or collect them when called within SMTPApi.begin() and SMTPApi.commit() code block.
Valid email JSON Object defined by JsonEmailCfg string contains following key-values:
{
"email":"recipient@gmail.com",
"name":"Recipient Name",
"subject":"subject",
"text":"text"
}
Function return true when e-mail is sent or false when an error occurred.
The TsApi provides functions that enhance the programming of Time Series Data. A time series is a sequence of data points indexed in chronological order, typically taken at equally spaced intervals. InDriver primarily utilizes JSON objects for data and configuration. The Time Series JSON data provided by InDriver's API offers an efficient and universal approach to data collection. This enables the processing and logging of data from various sources into database tables in a consistent manner.
TsApi includes functions for data processing, such as aggregation or forecasting, and encapsulates database vendor-dependent SQL queries for time series data processing. This design allows dashboards to be independent of the underlying database vendor, utilizing TsApi functions instead of regular SQL queries. TsApi versions dedicated to different databases are installed with InDriver, providing the same functionality while accommodating differences to remain compatible with the specific database in use.
Example of JSON Time Series Table.
Example of JSON Time Series Aggregation Table.
Aggregation Table column extras [JSON] | Aggregation Table column data [JSON] |
This function triggers the Aggregation Engine to perform the next part of calculations and should be implemented in the onHook function.
Example:
⇒ onHook
TsApi.aggregate(“a”); |
The function establishes an Aggregation Engine with the name aggregator to perform aggregation from the source table named table on the server named server. The aggregator creates aggregation tables for each specified aggregation interval.
The default intervals are set to 1 minute, 15 minutes, 1 hour, and 1 day, with the default time zone (timeZone)set to 'UTC.' The time zone is relevant for 1-day aggregations to determine the UTC time when the day starts in the specified time zone. The default sources are an empty array (sources: []), indicating that data from all sources will be aggregated. If the source array includes declared sources, the aggregation is performed only on these specified sources.
The default step size is set to 10,000, meaning that every aggregation cycle processes 10,000 rows of the source table. An aggregation cycle is triggered by the TsApi.aggregate() function.
The names of the aggregation tables for these intervals are composed of the source table name plus the interval name, for example, 'table_1minute,' 'table_15minutes,' 'table_1hour,' and 'table_1day.' The aggregation tables have the same columns as the source table, plus one additional column named 'extras,' which is used to store aggregation statistic data.
Example:
⇒ onStartup
InDriver.import(‘TsApi’); TsApi.defineAggregator(“a”, “azureserver”, “public.weather”); |
The ProcessApi provides functions used to start and close external programs.
General Example:
Example:
⇒ onStartup
InDriver.import("ProcessApi"); |
⇒ onHook
InDriver.debug(“go = ”+ProcessApi.start("backup",'"C:\\backup.bat”',"")); ProcessApi.waitForStarted("backup"); InDriver.debug("pid = "+ProcessApi.pid("backup\n dir = "+ProcessApi.workingDirectory("backup\n prg = "+ProcessApi.program("backup")+”\n stat = "+ProcessApi.state("backup")); ProcessApi.waitForFinished("backup"); |
⇒ onShutdown
ProcessApi.killAll() |
Closes all communication with the process associated with the name and kills it.
Closes all communication with all processes started with ProcessApi.start function.
Kills the process associated with the name, causing it to exit immediately.
Kills all processes started with ProcessApi.start function.
Returns the native process identifier for the process associated with the name, if available. If no process is currently running, 0 is returned.
Returns the program of the process associated with the name.
Sets the working directory of the process associated with the name.
Starts the given program in a new process, passing the command line arguments in args. Associate the process handle with the name.
Returns the current state of the process associated with the name.
Blocks until all of the processes have finished or until msecs milliseconds have passed.
Returns true if the processes finished; otherwise returns false (if the operation timed out or if an error occurred).
Blocks until all of the processes have started or until msecs milliseconds have passed.
Returns true if the processes finished; otherwise returns false (if the operation timed out or if an error occurred).
Blocks until the process associated with the name has finished or until msecs milliseconds have passed.
Returns true if the process is finished; otherwise returns false (if the operation timed out or if an error occurred).
Blocks until the process associated with the name has started or until msecs milliseconds have passed.
Returns true if the process is started; otherwise returns false (if the operation timed out or if an error occurred).
If the process associated with the name has been assigned a working directory, this function returns the working directory that the process will enter before the program has started.
The PdfApi provides an interface for interacting with PDF documents, allowing you to load files, extract text, retrieve metadata, handle security settings, and manage PDF file operations.
Returns a list of labels for all pages in the currently loaded PDF document.
Returns: A StringList (array of strings), where each item corresponds to the label of a page in the PDF. Page labels may differ from their numeric index, especially in professionally prepared documents.
Example:
⇒ onStartup
InDriver.import("PdfApi"); PdfApi.load(InDriver.currentPath() + "/report.pdf"); let labels = PdfApi.allPageLabels(); InDriver.debug("Page labels: " + labels.join(", ")); |
Returns a base64-encoded image of the specified PDF page, ready to embed in HTML or a UI.
Parameters:
Returns: A String containing the image in data:image/...;base64,... format. Can be used in <img> tags, web previews, or image containers.
Example:
⇒ onStartup
InDriver.import("PdfApi"); PdfApi.load(InDriver.currentPath() + "/manual.pdf"); let img = PdfApi.asImageBase64(0); // Render first page InDriver.debug("<img src='" + img + "'>"); // Show as HTML |
Loads a PDF document specified by the file path.
Return Values:
Example:
⇒ onStartup
InDriver.import("PdfApi"); let status = PdfApi.load(InDriver.currentPath() + "/document.pdf"); InDriver.debug("Load status: " + status); |
Retrieves the text content of the specified page in the loaded PDF.
Parameters:
Example:
⇒ onStartup
InDriver.import("PdfApi"); let status = PdfApi.load(InDriver.currentPath() + "/document.pdf"); let text = PdfApi.pageText(0); // Get text from the first page InDriver.debug(text); |
Returns the label of the specified page, which may differ from its numerical index.
Parameters:
Example:
⇒ onStartup
InDriver.import("PdfApi"); let status = PdfApi.load(InDriver.currentPath() + "/document.pdf"); let label = PdfApi.pageLabel(0); // Get the label of the first page InDriver.debug("Page Label: " + label); |
Returns the concatenated text from one or more pages of the currently loaded PDF document.
Parameters:
Returns: A String containing all text from the specified page range. Text from different pages is separated by newline characters.
Function use examples:
Example:
InDriver.import("PdfApi"); let status = PdfApi.load(InDriver.currentPath() + "/manual.pdf"); let intro = PdfApi.readText(0, 2); // Get text from first two pages InDriver.debug("Intro text:\n" + intro); |
Renders the specified PDF page and saves it as an image file.
Parameters:
Returns: A String with the saved file path if successful, or an empty string "" on error.
Example:
⇒ onStartup
InDriver.import("PdfApi"); PdfApi.load(InDriver.currentPath() + "/report.pdf"); let out = PdfApi.savePageAsImage(0, InDriver.currentPath() + "/page0.png"); InDriver.debug("Saved image: " + out); |
Sets the codec used for decoding the text in the PDF. For example, "Utf8" for UTF-8 encoding.
Parameters:
⇒ onStartup
InDriver.import("PdfApi"); PdfApi.setCodec("Utf8"); InDriver.debug("Codec set to Utf8"); |
Returns the total number of pages in the loaded PDF.
Example:
⇒ onStartup
InDriver.import("PdfApi"); let status = PdfApi.load(InDriver.currentPath() + "/document.pdf"); let count = PdfApi.pageCount(); InDriver.debug("Total Pages: " + count); |
Sets the password for accessing a password-protected PDF.
Parameters:
Example:
⇒ onStartup
InDriver.import("PdfApi"); PdfApi.setPassword("securePassword123"); let status = PdfApi.load(InDriver.currentPath() + "/protected.pdf"); InDriver.debug("Load status: " + status); |
Retrieves the password currently set for the PDF.
Example:
⇒ onStartup
InDriver.import("PdfApi"); let password = PdfApi.password(); InDriver.debug("Current Password: " + password); |
Returns the current status of the loaded document.
Possible Values:
Example:
⇒ onStartup
InDriver.import("PdfApi"); let status = PdfApi.status(); InDriver.debug("PDF Status: " + status); |
Retrieves the metadata of the loaded PDF as a JSON string. Metadata fields include:
Example:
⇒ onStartup
InDriver.import("PdfApi"); let status = PdfApi.load(InDriver.currentPath() + "/document.pdf"); let metadata = PdfApi.metadata(); InDriver.debug("PDF Metadata: " + metadata); |
Closes the currently loaded PDF document and releases resources.
Example:
⇒ onStartup
InDriver.import("PdfApi"); let status = PdfApi.load(InDriver.currentPath() + "/document.pdf"); PdfApi.close(); InDriver.debug("PDF closed."); |
The FileApi provides an interface for reading from and writing to files and an interface for monitoring files and directories for modifications.
Adds a file or directory path to the file system watcher.
When the system detects any change in the specified path, the onMessage function is invoked with a relevant tag: "FileChanged" for file changes and "DirectoryChanged" for directory changes and message data as a JSON object with a key "path" and the value of the path where the change is detected.
Example:
⇒ onStartup
InDriver.import("FileApi"); FileApi.addFileSystemWatcherPath(InDriver.currentPath()+"/driver.cfg"); |
⇒ onMessage
if (InDriver.messageSender() === InDriver.taskName()) { InDriver.debug(InDriver.messageTags()+":"+InDriver.messageData()); } /* When driver.cfg is changed onMessage is called onMessage: [FileChanged]: { "message": { "path": "C:/MyDevelopment/debug/driver.cfg", "type": "JSscript" } } */ |
Appends a single line to the file. Adds a newline character automatically.
Parameters:
Returns: true on success, false otherwise.
Example:
FileApi.appendLine("log", "New entry at " + InDriver.currentTimestamp()); |
Closes file related to name opened with FileApi.open function.
Closes all files opened with FileApi.open function.
Copies a file from one path to another.
Parameters:
Returns: true if copied successfully; otherwise false.
Example:
FileApi.copy("config.json", "backup/config_backup.json"); |
Checks whether a file exists at the given path.
Returns: true if the file exists; otherwise false.
Returns the size (in bytes) of an opened file.
Parameters:
Returns: The size of the file in bytes, or -1 if the file is not open or not found.
Checks if a file with the given symbolic name is currently open.
Parameters:
Returns: true if the file is open; otherwise false.
Opens the file pointed to by the 'file' parameter and assigns a handle with the specified 'name'. If the file is already open, the function returns 'AlreadyOpen'. The 'modes' parameter is an array of strings, including one or more of the following flags: ReadOnly, WriteOnly, ReadWrite, Append, Truncate, Text, Unbuffered, NewOnly, ExistingOnly.If the mode is ReadOnly or ReadWrite and the file does not exist, the function returns 'NotOpened'; otherwise, it returns 'Opened'.
Example:
⇒ onHook
InDriver.import(‘FileApi’); FileApi.open(“cfgFile”, InDriver.currentPath()+"/driver.cfg", “ReadOnly”); let data = FileApi.readAll("cfgFile"); InDriver.debug(data); FileApi.close(“cfgFile”); |
Reads all remaining data from the file associated with handle name;
Reads all lines from an opened file and returns them as a list.
Parameters:
Returns: A StringList where each item represents one line from the file.
Example:
FileApi.open("notes", "notes.txt", ["ReadOnly", "Text"]); let lines = FileApi.readLines("notes"); InDriver.debug("Line 1: " + lines[0]); |
Deletes a file from disk.
Parameters:
Returns: true if the file was successfully removed; otherwise false.
Removes the specified path from the file system watcher.
Example:
⇒ onShutdown
FileApi.removeFileSystemWatcherPath( InDriver.currentPath()+"/driver.cfg"); |
Writes data from a zero-terminated string of 8-bit characters to the file. Returns the number of written bytes, or -1 if an error occurred.
Example: copy ‘driver.cfg’ to ‘driver.cfg_copy’
⇒ onHook
InDriver.debug(FileApi.open("cfg",InDriver.currentPath()+"/driver.cfg",["ReadOnly"])); InDriver.debug(FileApi.open("cfg_copy",InDriver.currentPath()+"/driver.cfg_copy",["WriteOnly"])); let data = FileApi.readAll("cfg"); InDriver.debug(data); FileApi.write("cfg_copy",data); FileApi.closeAll(); |
The SerialPortApi provides functions for accessing serial ports, writing data, handling write requests with a specified waiting timeout, and reading data asynchronously.
Accepts data coming to the serial port associated with the specified name, and it stops waiting for data initiated by the SerialPortApi.writeAndWait function.
Generates a JSON array containing information about the available serial ports on the system.
An example of port info for a system with two COM ports.
[ { "description": "Communication Port", "location": "\\\\.\\COM1", "manufacturer": "(Standard Port Types)", "name": "COM1", "serialNumber": "", "vendorIdentifier": "" }, { "description": "Communication Port", "location": "\\\\.\\COM2", "manufacturer": "(Standard Port Types)", "name": "COM2", "serialNumber": "", "vendorIdentifier": "" } |
Closes serial port related to name opened with SerialPortApi.open function.
Closes all ports opened with SerialPortApi.open function.
Returns the last error associated with the serial port operation identified by the specified name.
Opens the serial port, assigns a handle with the specified 'name,' and configures the serial port settings based on the provided portSettings JSON object. If the JSON object is empty or if some parameters are missing, default values will be assigned. The JSON object should contain the following key-value pairs:
Example JSON Object with Default Serial Port Settings:
{ "mode": "Flow", "timeout": 3000, "bufferSize": 256, "baudRate": 9600, "parity": "NoParity", "stopBits": "OneStop", "dataBits": 8 } |
Example:
⇒ onStartup
InDriver.import(‘SerialPortApi’); SerialPortApi.open(“COM1”, ‘{ "mode": "Flow", "timeout": 3000, "bufferSize": 256, "baudRate": 9600, "parity": "NoParity", "stopBits": "OneStop", "dataBits": 8}’); |
Writes data to the device. Returns the number of bytes that were written, or -1 if an error occurred.
Example:
⇒ onHook
InDriver.import(‘SerialPortApi’); SerialPortApi.open(“COM1”, ‘{ "mode": "Flow", "timeout": 3000, "bufferSize": 256, "baudRate": 9600, "parity": "NoParity", "stopBits": "OneStop", "dataBits": 8}’); |
⇒ onHook
SerialPortApi.write(“COM1”,[0x1, 0x2, 0x3]); |
Writes data to the device and waits for an answer until the timeout or accepted data arrives at the serial port. This is a blocking function. The behavior depends on the specified mode:
To consider the data as a valid answer, the SerialPortApi.acceptRead() function should be called, indicating that the waiting for data can be stopped.
Example:
⇒ onHook
InDriver.import(‘SerialPortApi’); |
⇒ onHook
SerialPortApi.writeAndWait(“COM1”,”GetDataRequest”,[0x1, 0x2, 0x3],3000); |
⇒ onMessage
SerialPortApi.acceptRead(“COM1”); |
The SocketApi provides functions for accessing sockets, writing data, handling write requests with a specified waiting timeout, and reading data asynchronously.
Accepts data coming to the socket associated with the specified name, and it stops waiting for data initiated by the TcpSocket.writeAndWait function.
Attempts to make a connection to the address on the given port from the provided socketSettings JSON object, and assigns a handle with the specified 'name’.
If the JSON object is empty or if some parameters are missing, default values will be assigned. The JSON object should contain the following key-value pairs:
Example JSON Object with Default Socket Settings:
{ "address":”127.0.0.1”, "port": 50000, "mode": "Flow", "timeout": 3000, "bufferSize": 256 } |
Example:
⇒ onStartup
InDriver.import('TcpSocketApi'); TcpSocketApi.connect("socket",'{"address":"127.0.0.1","port":50000}'); |
Disconnect socket related to name opened with TcpSocket.connect function.
Closes all ports opened with TcpSocket.open function.
Writes data to the socket associated with handle 'name'. Returns true when all bytes are written, or false if the timeout is reached.
Example:
⇒ onHook
InDriver.import('TcpSocketApi'); TcpSocketApi.connect("socket",'{"address":"127.0.0.1","port":50000}'); |
⇒ onHook
TcpSocketApi.write(“socket”,[0x1, 0x2, 0x3]); |
Writes data to the socket associated with handle 'name' and waits for an answer until the timeout or accepted data arrives at the socket. This is a blocking function. The behavior depends on the specified mode:
To consider the data as a valid answer, the TcpSocket.acceptRead() function should be called, indicating that the waiting for data can be stopped.
Example:
⇒ onHook
InDriver.import('TcpSocketApi'); TcpSocketApi.connect("socket",'{"address":"127.0.0.1","port":50000}'); |
⇒ onHook
TcpSocketApi.writeAndWait("socket",[0x1,0x2,0x3],"req1"); |
⇒ onMessage
if (InDriver.taskName() === InDriver.messageSender()) { let data = JSON.parse(InDriver.messageData()); if (JSON.stringify(data.bytes)==="[1,2,3]")) { // loop back TcpSocketApi.acceptRead(data.socketName); } } |
When the socket receives data due to the TcpSocketApi.connect() parameters, the onMessage code block is triggered. In this case, messageSender is set to taskName, and messageData contains JSON-formatted data as illustrated in the example below:
let d = JSON.parse(InDriver.messageData()); /* d = { "bytes": "[79,75]", "data": "OK", "request": "request name", "socketName": "name of socket" } */ |
The SocketAPI offers a TCP-based server, enabling the acceptance of incoming TCP connections and facilitating the reading and writing of data to them.
Tells the server to listen for incoming connections on address and port from tcpServerCfg JSON Object.
If the JSON object is empty or if some parameters are missing, default values will be assigned. The JSON object should contain the following key-value pairs:
Example
InDriver.import('TcpServerApi'); TcpServerApi.listen('{"port":50000,"address":"Any","readMode":"Buffer","bufferSize":256}'); |
Writes data to the socket associated with handle 'name' and waits for an answer until the timeout or accepted data arrives at the socket. The behavior depends on the specified mode:
Example:
⇒ onHook
InDriver.import('TcpServerApi'); TcpServerApi.listen('{"port":50000,"address":"Any","readMode":"Buffer","bufferSize":256}'); |
⇒ onHook
⇒ onMessage
if (InDriver.taskName() === InDriver.messageSender()) { let data = JSON.parse(InDriver.messageData()); if (JSON.stringify(data.bytes)==="[1,2,3]")) { TcpServerApi.write(data.socketName, "bytes accepted"); } if (data.data==="text data"){ TcpServerApi.write(data.socketName, "text data accepted"); } } |
The UdpSocketApi provides functions for accessing UDP sockets, writing data, handling write requests with a specified waiting timeout, and reading data asynchronously.
ff
ff
ff
ff
Null UdpSocketApi.writeAndWait( String name, String address, Number port, String data, String requestName, Number timeout );
ff