<< Click to Display Table of Contents >> Navigation: JavaScript > Custom JavaScript functions for device specific functionality |
Various custom functions exist that help JavaScript interact with project variables and objects. By pressing CTRL+SPACE in the JavaScript editor content area (1), a list with auto complete suggestions will appear. On the top of the list are functions from the category Custom Functions (2). A Tooltip (3) for the selected function shows a short description and gives informations about the parameter(s) / return types.
The print function allows to print debug messages to the serial console. This can be very helpful in debugging JavaScripts during development. Note that when a lot of debug messages are used the system performance can be slightly decreased. When releasing a project the print statements should be commented. Prototype: print (string stringToPrint); Examples: var result = 21 * 2;
// output: String to print print("String to print");
// output: Result was 42 print("Result was " + result);
// output: Strings and numbers can be concatenated! print("Strings " + "and " + "numbers " + "can " + "be " + "concatenated!");
Please note that the print function also works with the PClient simulation on the PC. The output will be written in the file %USER%\AppData\Roaming\%program version%\extracted_components\pclient\simulation\console_output.txt |
In a project a lot of variables are used to store runtime data and you can configure your own variables in a project. To retrieve the value of such a variable the getVariableValue function can be used. Prototype: var result = getVariableValue(string nameOfVariable); The returned value of that function contains the value of the variable. This can be either a string or a number depending on the variable type. Examples: var backlightValue = getVariableValue("@DisplayBacklightIntensity"); // result is a number representing the backlight intensity print("Value of backlight is: " + backlightValue);
var terminalName = getVariableValue("@Terminal"); // result is a string representing the name of the device this is executed print("I am running on a " + terminalName); |
To set a value to a pre-defined or self-created variable you can use the setVariableValue function. The return value of the function will be true (setting value worked) or false (setting value failed). Prototype: var result = setVariableValue(string nameOfVariable, number newValueForVariable); //or var result = setVariableValue(string nameOfVariable, string newValueForVariable); Example: var worked = setVariableValue("@DisplayBacklightIntensity", 50); if (worked === true) { print("Setting display backlight to 50% worked!"); } else { print("Failed to set the display backlight intensity to 50% :("); } |
With this function you can check if a variable has a valid value. Returns true if the variable has a valid value. Returns false if the variable doesn't have a defined value. Returns "undefined" if the variable doesn't exist or if the function was not called with one parameter only. Prototype: var result = getVariableValid(string nameOfVariable); The returned value of that function contains the information about the variable. Examples: var result = getVariableValid("Speed"); if (result === true) print("The variable has a valid value."); else if (result === false) print("The variable does NOT have a valid value."); else print("The variable does not exist or the function was called inappropriately."); |
All graphical objects (DDO => Display Data Object) in a project have a lot of properties. In some cases these properties can be of interest during runtime in a JavaScript. To retrieve the value of such a property the function getProperty can be used. Prototype: var value = getProperty(number DDO-ID, string propertyName); The return value of the getProperty function will be either the value of the property or undefined if something did not work. Since the properties of a DDO consist of various data types, the returned property value can also be a different data type depending on the property. Here is a list of all the properties that can be read and/or changed through JavaScript.
Examples for getProperty: var DDOID = 42; var myID = getProperty(DDOID, "ID"); print("ID of DDO no. " + DDOID + ": " + myID);
var myColor = new Array(4); myColor = getProperty(DDOID, "Background Color"); // Now the array contains the Red, Green, Blue and Alpha components print("The background color is: R: " + myColor[0] + " G: " my Color[1] + " B: " + myColor[2] + " A: " + myColor[3]);
var imagePath = getProperty(DDOID, "Background Image"); print("The image path is: " imagePath); |
Setting properties is as easy as getting them. The setProperty function can be used for that. Prototypes: var result = setProperty(number DDO-ID, string propertyName, integer value); var result = setProperty(number DDO-ID, string propertyName, double value); var result = setProperty(number DDO-ID, string propertyName, bool value); var result = setProperty(number DDO-ID, string propertyName, string value); var result = setProperty(number DDO-ID, string propertyName, Array array); Examples: var DDOID = 42; var myColor = new Array(4); // Define a full red color myColor[0] = 255; myColor[1] = 0; myColor[2] = 0; myColor[3] = 255; //Alpha channel: completely opaque
// Setting a new name to a DDO: var worked = setProperty(DDOID, "Name", "MyNewName"); if (worked === true) { print("Setting new name worked!"); } else { print("Setting name failed!"); }
// Set the background color: worked = setProperty(DDOID, "Background Color", myColor); // Set a new background image worked = setProperty(DDOID, "Background Image", "/opt/images/bg.png"); |
The contents of a file on the file system or external media can be read and stored in a vector containing strings. Each vector entry represents one line of a file. If the reading was not successful, the result is undefined. Important note: The current maximum line length that is read is 1024 characters. If the file contains a line that is longer, it is possible that the file can not be read correctly Important note 2: The maximum number of bytes is currently restricted to 2MB. If the file is larger than 2MB, only the first 2MB of the file are read, the rest is discarded. Prototype: var result = readFile(string filePath); Example: //read the contents of the file /proc/cpuinfo var myData = readFile("/proc/cpuinfo");
//check if successful: if (undefined == myData) { //reading failed! print("Error reading file /proc/cpuinfo"); } else { //reading successful, myData is now an array //print contents to console: for (var i = 0; i < myData.length; i++) { print("Line " + (i + 1) + ": " + myData[i]); } }
To display the contents of the retreived vector the Table Object can be used: setProperty(TableID, "Table Data", myData); For details see the manual chapter for the table object. |
With the writeToFile function it is possible to write strings to a file. For security reasons the file can only be located on a connected USB stick or on a dedicated folder of the device. If the filePath provided is not on the connected USB stick, the file is automatically created in the device's dedicated directory (on the device this is usually in "/opt/user_files/", on the windows simulation this directory is in the designer's install path (pclient/user_files/). Note that a file is automatically created if it does not exist yet (this will fail if the path contains directories that do not exist). If the file is located on a USB stick, the size of the file is not restricted (write will fail if there is no space left on the device). If the file is located on the file system of the device, the memory that is available in the /opt/user_files directory is limited to 100 MB (you can create many smaller files but not more than 100 MB in the directory). Writing will fail if this limit is reached. From this version onwards, files can also be saved in the directory /opt/data. This folder will be backed up during an OS / application update, which is advantageous to keep data intact. The stringToWrite parameter may contain any string. No line breaks are added at the end of each write, these need to be added to the stringToWrite if desired (add "\n" for a line break). If the string only consists of one line, a line break has to be added at the end. The option parameter can either be "append" or "replace". If the string is appended, the string will just be added at the end of the file. If the string is replaced, the whole content of the file is discarded before writing the new string to the file. If any other string is provided as option parameter the writeToFile function will fail. The optional sync parameter can be set to true if the file shall be directly written to disk (reduce the risk of corrupt files at total power loss). The sync to disk will be done after the content was written to the file. If the sync parameter is set to true the writeToFile function will not return until synchronization is finished! If the sync parameter is omitted or set to false, the synchronization will be done by the operating system after some time or when the device is shut down. The return value of the writeToFile function is either true if writing to the file (and optional sanchronization) was successful or false if writing or synchronizing to disk failed. Prototype: var result = writeToFile(string filePath, string stringToWrite, string option, bool sync); Example: var usbMountPath = getVariableValue("@USBMountPath"); var filePath = usbMountPath + "/myFile.txt"; var myTextWithLineBreak = "Hello, this is line 1.\nAndThis is line 2.\n"; var doSync = false; var result = writeToFile(filePath, myTextWithLineBreak, "append", doSync); if (result == true) { print("Writing into file was successful!"); } else { print("Writing into file FAILED!"); } |
The ring buffer alarm log data can be similarly retrieved as the contents of a file. There will also be a vector returned which contains each alarm log entry. Additionally a format string and a delimiter character can be provided to get a formatted result. The format string can contain several keywords delimited by the delimiter character. The keywords that can be used are: •timestamp: The date and time when the alarm was logged in seconds since 1970-01-01 00:00 •timestring: The date and time when the alarm was logged as a formatted text. The format is "DayOfWeek Month DayOfMonth Hour:Minute:Second Year", e.g. "Mon Sep 3 13:42:00 2012" •alarmtext: The text that was configured for the logged alarm in the property "Alarm Log Text" of the alarm object. •alarmevent: The event that caused the alarm log entry (either "Enqueued", "Shown", "Confirmed" or "Removed") •alarmvariables: The values of the variables @AlarmShow, @AlarmCurrent and @AlarmCurrentPriority at the time of the logging entry. Each value in hex delimited by the delimiter character. Example format string: "timestring;alarmtext;alarmevent" Delimiter character: ";" This would cause one entry of the returned vector to look like this: "Mon Sep 3 13:42:00 2012;Engine Oil Pressure too high;Shown" Prototype: var result = getAlarmLogRingBufferContent(string formatString, string delimiterCharacter); Example: //create a new array and retrieve the ring buffer content var myLog = new Array(); myLog = getAlarmLogRingBufferContent ("timestring;alarmtext", ";");
//check if successful: if (myLog.length == 0) { //reading failed! No entries in the buffer? print("Error reading Alarm Log Ring Buffer content"); } else { //reading successful, myLog is now an array //print contents to console: print("Alarm log:"); for (var i = 0; i < myLog.length; i++) { print(myLog[i]); } } Note: The returned array can be easily passed to a table object so it can be shown on screen ( setProperty(IDofTableObject, "Table Data", arrayWithLogContent); ) Note 2: If the formatting of the date and time is not what is desired, the timestring can be used to create a JavaScript Date object which provides easy access to each part of the date and time: //assume that we already have an array filled with log data and that the timestamp is the first part of each entry var i = 0; //extract the timestamp from the log entry var timestampAsString = myLog[i].substr(0, myLog[i].indexOf(";")); Var timestamp = parseInt(timestampAsString); var myDate = new Date(timestamp * 1000); //now each part of the date/time can be accessed separately: //e.g. myDate.getDate() <-- day of month //or myDate.getSeconds() <-- seconds and so on... |
Simply use the following function to delete the complete alarm log ring buffer: deleteAlarmLogRingBufferContent(); |
The moveDDO function can be used to move an object to a new position. Please use this function with care, this can lead to a very high system load if this function is abused to e.g. create complex animations. Prototype: var result = moveDDO(number ParentObjectID, number ObjectIDtoBeMoved, number newX, number newY); The first parameter is the object ID of the parent of the object that shall be moved (check project tree to find the parent). The second parameter is the ID of the object that shall be moved. The third and fourth parameters are the new coordinates inside the parent. Example: //Move the picture graphic DDO 42. The parent of this ddo is frame 21 var pictureDDO = 42; var frameDDO = 21;
//now move to position 84/36: var movingWorked = moveDDO(frameDDO, pictureDDO, 84, 36); if (movingWorked) { print("Moving picture was successful!"); } else { print("Moving picture failed! :( "); }
Example project: Download this project to see how the MoveDDO function can be used. |
If the fadeout time for softkey frames was set in project properties, the softkey frames will be hidden after that time. To show them again, a physical key needs to be pressed. If the softkey frames shall be shown again by some other event, the showSoftkeyFrames function can be used. Prototype: var result = showSoftkeyFrames(); Note: The function will always return true. |
First things first: This function should only be used if there is really no other way of sending the desired message using the CAN protocol settings provided! Implementing a CAN protocol in JavaScript is not a good idea! Prototype: var result = sendCANMessage(number CAN-Port, number CAN-ID, number DLC, number Byte1, number Byte2, number Byte3, number Byte4, number Byte5, number Byte6, number Byte7, number Byte8); Description of the parameters: •CAN-Port: Number of the CAN port that shall be used for sending the message (numbering starts with 1) •CAN-ID: The CAN messages CAN ID •DLC: Data length code: how many data bytes shall be sent •Byte1...Byte8: The data bytes of the CAN message Example: //send CAN message with ID 0x601 and 8 data bytes on port 1: var result = sendCANMessage(1, 0x601, 8, 0xde, 0xad, 0xbe, 0xef, 0xb0, 0x0b, 0xaf, 0xfe); if (result) { print("CAN message sent successfully!"); } else { print("Failed to send CAN messge!"); } |
With this command it is possible to execute a JavaScript file from within another JavaScript file. Example: includeFile("example.js") The included file will be executed as if the source code was written in the source file (except when it's a function). This is useful if you have a part of code that you need to execute in many different places. |
It is possible to use functions in JavaScript. To create a function, use the following syntax: Example: function function_name (input variables) { <code> return return_value; } The input variables as well as the return value are optional. The input variables will be forwardef from the calling JavaScript. Executing the function looks like this: Example: var result = function (input variables); You can combine this with the includeFile function to create a set of multi purpose JavaScript functions that you can use in different places in your project (Note that you need to declare the functions globally for them to stay alive). Please note that for a function to be declared once and stay "alive, it needs to be declared like this:
function_name = function function_name (input variables) { <code> return return_value; } |
It is possible to call functions in JavaScript that simulate encoder actions: Example: generateAction("Navigate Up");//simulates a counterclockwise encoder movement generateAction("Navigate Down");//simulates a clockwise encoder movement generateAction("Navigate Confirm");//simulates an encoder press |
For the purpose of prohibiting going back to pages with a password access with the escape key, it is possible to delete the browsing history with this command. To prohibit certain pages from being accessable with the escape key, set the property "Add To Page History" to false. |
The multimediaCommand function can be used to send commands to a MultimediaPlayer object. Various commands can be used to control playback or manipulate the playlist of the MultimediaPlayer object. Prototype: var result = multimediaCommand(number MultimediaPlayerObjectID, string commandString, number eoptionalValue); The first parameter is the object ID of the MultimediaPlayer object to which the command shall be sent. The second parameter is the command string (see below for a list of available commands. Note that the command string can either be in upper or lower case letters (e.g. "play" == "Play" == "PLAY")) The third parameter is an optional/mandatory value that can/needs to be provided to some of the commands. Note:The multimediaCommand function returns true (if the command was successfully sent to the MultimediaPlayer object) or false (if the command failed). The only exception is: If the command string is "get playlist", an array containing the pathes of all files that are currently in the playlist is returned. Available commands: •"play" Optional Value: None Description: Begin playback of the currently selected media file •"stop" Optional Value: None Description: Stop playback of the currently selected media file •"pause" Optional Value: None Description: Pause playback of the currently selected media file •"back" Optional Value: None Description: Jump to the previous file in the playlist •"next" Optional Value: None Description: Jump to the next file in the playlist •"mute" Optional Value: None Description: Mute the MultimediaPlayer •"unmute" Optional Value: None Description: Unmute the MultimediaPlayer (current volume set) •"set volume" Optional Value: volume offset, any integer number (volume is restricted to be between 0 and 100, so it only makes sense to set an offset between -100 and 100) Description: If no optional value is provided, the volume that is set in the volume bar graph of the MultimediaPlayer is used. If an optional volume is provided, this will be treated as an offset to the current volume. •"set position" Optional Value: integer number (positive or negative) Description: Jump to a position in the currently played back file. If no optional value is provided, the position that is set in the position bar graph of the MultimediaPlayer is used. If an optional value is provided, the value is treated as an offset to the current position (in seconds). •"shuffle" Optional Value: true or false Description: If no value is provided, the pressed state of the MultimediaPlayer's shuffle button is used. If true is provided as parameter, the playlist will be randomized. If false is provided, the playlist will return to it's original sequence. •"loop" Optional Value: integer number between 0 and 2 Description: If no value is provided, the value of the MultimediaPlayer's loop list is used. If a value is provided, the values have the following effect: 0: Don't loop, 1: loop current file, 2: loop playlist (after end of last file in playlist was reached, begin at start of playlist) •"add to playlist" Mandatory Value: string with the path to the file that shall be added to the playlist Description: Add a media file to the playlist of the multimedia player. •"remove from playlist" Mandatory Value: string with the path to the file that shall be removed from the playlist. If the file was added to the multimedia player at design time or if it was manually copied to PROJECT_PATH/terminal_files/multimedia directory, it is enough to provide the file name with suffix (e.g. "myMedia.mp3") to remove the file. If the file was added to the playlist at runtime (e.g. from an USB drive), the full path (e.g. "/disk/usbsda1/myMedia.mp3") needs to be used to remove the file from the playlist. Description: Remove a file from the playlist. •"select playlist entry" Mandatory Value: number >= 1 Description: Select a certein entry position in the playlist •"clear playlist" Optional Value: None Description: Remove all files from the playlist. After that the playlist will be empty. •"add directory to playlist" Mandatory Value: string that contains a path to a folder that contains media files that shall be added to the playlist Description: Add all files in the specified directory to the playlist. Make sure that only media files that can be played back are in the folder. •"toggle fullscreen" Optional Value: None Description: Switch between fullscreen mode and normal mode •"get playlist" Optional Value: None Description: Get an array that contains strings. The strings are the full qualified pathes to the media files that are currently in the playlist. Example: //Our MultimediaPlayer object has object ID 42: var mmpID = 42; //Start playback of the current file var result = multimediaCommand(mmpID, "play"); if (result == true) { print("Play command successfully sent"); } else { print("Error sending play command to MultimediaPlayer with ID " + mmpID); } //From here we ommit the handling of the return value (to save some space in the example code) //Pause playback of the current file multimediaCommand(mmpID, "pause"); //Jump to next file in playlist multimediaCommand(mmpID, "next"); //Jump to 1 minute and 30 seconds in the current file multimediaCommand(mmpID, "set position", 90); //Add another file to the playlist multimediaCommand(mmpID, "add to playlist", "/disk/usbsda1/mySong.mp3"); //Remove all files from playlist: multimediaCommand(mmpID, "clear playlist"); //Add the content of a directory to the playlist: multimediaCommand(mmpID, "add directory to playlist", "/disk/usbsda1/music/");
//Get the complete playlist and show all pathes in a table (with ID 55) var playlistEntries = new Array(); playlistEntries = multimediaCommand(mmpID, "get playlist"); setProperty(55, "Table Data", playlistEntries); Please note that the example above is not meant to be executed (makes no sense to execute the commands in that order in one script). |
The value history of a 2D Graph object is stored in binary ring buffers on the non-volatile memory of the device. In order to process the data on a PC (e.g. spreadsheet application), it needs to be copied to an external media (e.g. usb drive). As soon as this function is called, the copy process will start. The progress can be observed in the Copy Progress Variable of a 2D Graph. While copying is in progress all new values of the 2D Graph will be buffered and will not get lost. After the copy has finished (Copy progress variable value is 100), the external media can be removed and the data can be processed with the Graph History Tool on a PC. Prototype: var result = save2DGraphHistory(number Graph-DDO-ID, string targetPath); The result of this function is true if the copy process could be started (correct object ID and target path was provided). This does not mean that the copy process has successfully finished. Example (copy to USB drive): //Get path of mounted USB drive: var usbMountPath = getVariableValue("@USBMountPath"); //Save history to target path. The 2D Graph has object ID 42 var result = save2DGraphHistory(42, usbMountPath); if (true == result) { print("Copy 2D Graph history started"); } else { print("Starting copy 2D Graph history FAILED"); } |
Use this function to completely delete the value history of a 2D Graph object. This will instantly delete the binary ring buffer on the non-volatile memory and the currently shown value lines. Prototype: var result = delete2DGraphHistory(number Graph-DDO-ID); The result of this function is true if a correct graph object ID was provided. |
requestVariableValueFromOwner - Initiate a read request to the owner of a variable (CANopen SDO Upload Request) |
This function can be used as a trigger to send out a read request to the owner of a variable. Currently this function can only be used to send out a CANopen SDO Upload Request. See SDO Upload Request Support This function can be called multiple times in one script for different variables. All requests will be buffered and send out one after another after the equivalent SDO Upload Responses was received (or after timeout). Prototype: var result = requestVariableValueFromOwner(string NameOfCANopenVariable); The result of this function is true if the variable is a CANopen variable and the Upload Request was accepted by CANopen. It returns false if either the settings of the variable were not correct (e.g. if it was no CANopen variable) or if the CANopen stack was not correctly configured (e.g. no appropriate SDO Client Channel settings were made for the CANopen ECU). |
Use this function to start the calibration process of a resistive touchscreen. Capacitive touchscreens do not need calibration. When this function is called, the calibration process is displayed but PClient will continue to run (e.g. cyclic scripts, cyclic CAN messages) but won't accept touch events and will not paint anymore until calibration is finished. Prototype: var result = startTouchscreenCalibration(); The result of this function is true if the touch calibration process was started successfully and false if it is either not supported on the current device or an error occurred. Important Notes: •On devices with capacitive touch the calibration process might start but will have no effect. Capacitive touchscreens do not need calibration. •On devices with I.MX35 CPU, the new calibration values are directly used after the calibration has finished. On devices with I.MX6 CPU, the new calibration values will only have an effect after a cold boot (write 0xb007 to variable @PWR_CurrentPowerMode). |
The writeEEPROM function allows writing values to EEPROM. The values in EEPROM are very save and will survive a complete a software update as well as unexpected power losses (except during the writing process).
Note: The number of EEPROM write cycles is limited (device dependent). Do not write to EEPROM too often (e.g. not in a cyclic script or CAN message)!
The maximum usabe EEPROM size for all devices is 28672 bytes.
Prototype: var result = writeEEPROM (number EEPROM_ADDRESS, number LENGTH, number/bool/string VALUE);
Parameters: •EEPROM_ADDRESS: The start address in the EEPROM to write the data to •LENGTH: The data length. The following rules apply: ◦If writing a bool, the length needs to be set to 1 ◦If writing a number, the length needs to be 1, 2, 3 or 4 ◦If writing a string, the area starting at the address will be reset to 0 in EEPROM and after that the string will be written (if a string is shorter than the provided length, still the whole length is reset to 0 before the shorter string is written). If a string is longer than length, only the given number of bytes will be written to EEPROM. ◦EEPROM_ADDRESS + LENGTH may not be greater than the maximum EEPROM size (28672) •VALUE: Currently the following JavaScript data types are supported: number, string and bool. If e.g. an array object is provided as value parameter, the writeEEPROM function will fail. •Return value (result): If the provided value was written successfully, the number of bytes that were written are returned. If writing the value to EEPROM failed, undefined will be returned (observe console error messages when testing the project).
Note: The EEPROM functions will only work on the device, not in the PClient simulation.
Examples:
var ret = writeEEPROM(0, 4, 0xdeadbeaf);//write the number 0xDEADBEAF into 4 bytes starting at position 0 print("Write 0xdeadbeef: " + ret); //console output: Write 0xdeadbeef: 4
var ret = writeEEPROM(4, 2, 32767); //write the number 32767 into 2 bytes starting at position 4 print("Write 32767: " + ret); //console output: Write 32767: 2
var ret = writeEEPROM(6, 20, "Hallo Test!"); //write the string "Hallo Test!" into 20 bytes starting at position 4 print("Write str: " + ret); //console output: Write str: 11
ret = writeEEPROM(26, 1, true); //write a bool into 1 byte at position 26 print("Write b: " + ret); //console output: Write b: 1
ret = writeEEPROM(27, 1, -1); //write the number -1 (minus 1) into 1 byte at position 27 print("Write minus1: " + ret); //Write minus1: 1
ret = writeEEPROM(28, 2, 0x55); //write the number 0x55 into 2 bytes starting at position 28 print("Write 16bit 0x55: " + ret); //console output: Write 16bit 0x55: 2 |
The writeEEPROM function allows reading values from EEPROM. The maximum usable EEPROM size is 28672 bytes.
Prototype: var value = readEEPROM(number EEPROM_ADDRESS, number LENGTH, string OPTIONAL_DATATYPE);
Parameters: •EEPROM_ADDRESS: The start address in the EEPROM to read the data from •LENGTH: The data length. The following rules apply: ◦If reading a bool, the length will be ignored and 1 is always used ◦If reading a number, the length needs to be 1, 2, 3 or 4 ◦EEPROM_ADDRESS + length may not be greater than max EEPROM size (28672) •OPTIONAL_DATATYPE: This is a hint about the type of data that shall be read. The readEEPROM function will try to use the correct data type as its return value. If this parameter is ommited or a non supported value is used, a byte array will be used as return type (see Return value below) ◦Possible values: ▪“bool” ▪“number” ▪“string” •Return value (value): In case reading failed, undefined will be returned (observe console error messages when testing the project). If reading worked, the value that was read from EEPROM will be returned. The data type of the returned value depends on OPTIONAL_DATATYPE parameter. If this parameter was omitted, a byte array object is returned that contains the single data bytes of the EEPROM (as numbers).
Note: The written and returned numbers are treated as signed 32Bit integers regardless of the actual data length! If e.g. -1 is written with a length of 1 and then read again, 255 will be returned (see example below)! The handling of such data is up to the script programmer!
Examples (see writeEEPROM for the according write functions):
var x = readEEPROM(0, 4, "number"); //read 4 bytes from postion 0, interpret the data as a number print("Read 0xdeadbeef: " + x); //console output: Read 0xdeadbeef: -559038801
Why -559038801? 0xdeadbeef in binary is 1101 1110 1010 1101 1011 1110 1010 1111 (32 bits). According to the note above, the 1 in the highest bit is interpreted as the sign. 1101 1110 1010 1101 1011 1110 1010 1111 as a 32 bit signed number is -559038801
var n = readEEPROM(4, 2, "number"); //read 2 bytes from postion 4, interpret the data as a number print("Read 32767: " + n); //console output: Read 32767: 32767
var str = readEEPROM(6, 20, "string"); //read 20 bytes from postion 6, interpret the data as a string print("Read str: " + str); //console output: Read str: Hallo Test!
Why "Hallo Test!", even though 20 bytes are read? As seen below, the positions 6 to 16 (11 bytes -> 11 characters in "Hallo Test!") are filled with the letters. The rest was set to 0. 0 is interpreted as the stop sign (i.e. the end of a string).
var b = readEEPROM(26, 1, "bool"); print("Read b: " + b); //console output: Read b: true
var minus1 = readEEPROM(27, 1, "number"); print("Read minus1: " + minus1); //console output: Read minus1: 255
Why 255? -1 in binary is, in 32 bit, 1111 1111 1111 1111 1111 1111 1111 1111). But only 1 byte is stored. 1111 1111 equals 255.
var b16 = readEEPROM(28, 2, "number"); print("Read 16bit 0x55: " + b16); //console output: Read 16bit 0x55: 85
var arr = readEEPROM(0, 29); for (var i = 0; i < arr.length; ++i) { print("arr[" + i + "]: " + arr[i]); } //console output: // arr[0]: 175 -> 0xAF // arr[1]: 190 -> 0xBE // arr[2]: 173 -> 0xAD // arr[3]: 222 -> 0xDE -> makes 0xDEADBEAF // arr[4]: 255 -> 0xFF // arr[5]: 127 -> 0x7F -> makes 32767 // arr[6]: 72 -> 0x48 -> ASCII H // arr[7]: 97 -> 0x61 -> ASCII a // arr[8]: 108 -> 0x6C -> ASCII l // arr[9]: 108 -> 0x6C -> ASCII l // arr[10]: 111 -> 0x6F -> ASCII o // arr[11]: 32 -> 0x20 -> ASCII <blank space> // arr[12]: 84 -> 0x54 -> ASCII T // arr[13]: 101 -> 0x65 -> ASCII e // arr[14]: 115 -> 0x73 -> ASCII s // arr[15]: 116 -> 0x74 -> ASCII t // arr[16]: 33 -> 0x21 -> ASCII ! // arr[17]: 0 -> String stop sign // arr[18]: 0 -> String stop sign // arr[19]: 0 -> String stop sign // arr[20]: 0 -> String stop sign // arr[21]: 0 -> String stop sign // arr[22]: 0 -> String stop sign // arr[23]: 0 -> String stop sign // arr[24]: 0 -> String stop sign // arr[25]: 0 -> String stop sign // arr[26]: 1 -> bool true // arr[27]: 255 -> 0xFF // arr[28]: 85 -> 0x55
Why was this long array returned? No data type was given in the read command, so the bytes are returned as a JavaScript array.
Please note: Numbers are stored LSB first, Strings are stored linearly from beginning to end. |
With this function the ID of the object (graphical object or CAN mapping) or the name of the variable that triggered the execution of the current script.
Prototype: var result = getCallerID();
result will contain the ID of the object if the script was triggered by a graphical object or a CAN mapping, or the name of the variable if the script was triggered by a variable. If neither is the case (only theoretical, should never happen), the result will be undefined. |
createUSBDirectory - Create a directory on the USB stick or in user_files |
This function can be used to create a directory on a USB stick or in the /opt/user_files directory on the device itself. provide a directory name or hierarchy as a parameter. If the path starts with /opt/user_files, the directory hierarchy is created inside the user_files directory. If the path is not below /opt/user_files, the current USB mount path is automatically prepended to the path and the directory is created on the USB stick. The path may not contain a ".." or "*".
Prototype:
var result = createUSBDirectory(string directoryPath);
The result of the function will be true if creating the directory was successful (or the directory already exists) or false if -the path contains a ".." or "*" -the path is not inside of /opt/user_files and no USB stick is inserted -creating the directory failed for unknown reasons |
getDirectoryContent - Get the contents of a directory |
With this function the contents of a directory can be read. The first parameter is the path to the directory that shall be read. The second parameter is optional and can be used to filter the result to contain only files or only directories. Use "DIRECTORIES_ONLY" or "FILES_ONLY" as filter options. If the second parameter is omitted or has an other value than the two filter options, files and directories will be returned.
Prototype:
var result = getDirectoryContent(string directoryPath, string optionalFilter);
The function will return undefined if the contents of the provided directory could not be read. If the contents were read successfully, an array of strings will be returned that contains all file and/or directory names inside of the provided directory path. |
deleteFileOrDirectory- Delete a file or directory on a USB stick or in user_files |
With this function a file or directory can be deleted. A file or directory can only be deleted if it is either on a USB stick or in the user_files directory (/opt/user_files). The function's only parameter is the path to the file or directory that shall be deleted. To erase the contents of a folder an asterisk may be provided at the the end of the path (e.g. "/opt/user_files/*"). A ".." may not be contained in the provided path.
Prototype:
var result = deleteFileOrDirectory(string directoryOrFilePath);
The function returns true if the directory or file(s) were deleted successfully. It returns false if the file(s) or directory could not be deleted. |
This function copies a file or directory or files or directories within the file system (including USB stick). The two (obligatory) parameters are the source and destination file path.
Return value is 'true' if the copy process was successful. Return value is false if the copy process was not successful or if the parameters were invalid or missing. To be able to copy files into the user_files directory, it can be created using the createUSBDirectory function.
Prototype:
var success = copyFileOrDirectory(String sourcePath, String destinationPath);
Examples:
//copy the file test.txt from /opt to /opt/test copyFileOrDirectory("/opt/test.txt","/opt/test/");
//copy the file test.txt from /opt to /opt/test and rename it test2.txt copyFileOrDirectory("/opt/test.txt","/opt/test/test2.txt");
//copy all files from /opt/test_dir1 to /opt/test_dir2 copyFileOrDirectory("/opt/test_dir1/*","/opt/test_dir2/");
//copy the directory /opt/test_dir inluding all its content to /opt/parent_dir (resulting in /opt/parent_dir/test_dir copyFileOrDirectory("/opt/test_dir/","/opt/parent_dir/");
Please note: This function blocks the execution until it is finished. Blocks means: The thread that caused the execution of the script will block. Usually this is the PClient main thread including any painting operation. The programmer is advised to show a warning to the device user when a blocking function is called. If the script was triggered e.g. by a CAN stack (e.g. timeout or received event), it will also block that thread and will e.g. not send cyclic messages during the block! The time it takes to finish this function depends on the size of the copied data. |
This function moves a file or directory or files or directories within the file system (including USB stick). A file or directory can only be moved if it is either on a USB stick or in the user_files directory (/opt/user_files). The two (obligatory) parameters are the source and destination file path.
Return value is 'true' if the move process was successful. Return value is false if the move process was not successful or if the parameters were invalid or missing.
Prototype:
var success = moveFileOrDirectory(String sourcePath, String destinationPath);
Examples:
//move the file test.txt from /opt/user_files to /opt/test moveFileOrDirectory("/opt/user_files/test.txt","/opt/test/");
//move the file test.txt from /opt/user_files to /opt/test and rename it test2.txt moveFileOrDirectory("/opt/user_files/test.txt","/opt/test/test2.txt");
//move all files from /opt/user_files/test_dir1 to /opt/test_dir2 moveFileOrDirectory("/opt/user_files/test_dir1/*","/opt/test_dir2/");
//move the directory /opt/user_files/test_dir inluding all its content to /opt/parent_dir (resulting in /opt/parent_dir/test_dir copyFileOrDirectory("/opt/user_files/test_dir/","/opt/parent_dir/");
Please note: This function blocks the execution until it is finished. Blocks means: The thread that caused the execution of the script will block. Usually this is the PClient main thread including any painting operation. The programmer is advised to show a warning to the device user when a blocking function is called. If the script was triggered e.g. by a CAN stack (e.g. timeout or received event), it will also block that thread and will e.g. not send cyclic messages during the block! The time it takes to finish this function depends on the size of the moved data. |
This function performs a "sync" command. This is relevant if the device is shut down after a copy / move process. The OS finishes these operations quite slowly in the background.
Prototype:
syncFilesystem();
Please note: This function blocks the execution until it is finished. Blocks means: The thread that caused the execution of the script will block. Usually this is the PClient main thread including any painting operation. The programmer is advised to show a warning to the device user when a blocking function is called. If the script was triggered e.g. by a CAN stack (e.g. timeout or received event), it will also block that thread and will e.g. not send cyclic messages during the block! The time it takes to finish this function depends on the size of the copied/moved data. |
This function opens the PDF reader, optionally with a PDF file and / or a "Open File" button.
Prototype:
bool openPDFReader(optional:String pathToPDFtoOpen, optional:bool showOpenButton);
Parameters:
•pathToPDFtoOpen: String with full path to the PDF file to open. No restrictions. Can be anywhere on the file system or e.g. USB stick. •showOpenButton: Flag to indicate if the open button shall be shown or not. Note that if no path was provided, the open button is shown automatically.
Return value:
•true if starting the PDF reader was successful (this is no indication if the provided PDF could be loaded) •false if starting the PDF reader failed
Note that the PDF reader cannot be opened in the PClient simulation, only on the device. |
With great power comes great responsibility!
This function executes any command on the Linux system console. We cannot stress enough that it is very easy to slow down or even completely stop the PClient misusing this command, it is even possible to destroy almost all data on the device. But we also know that it can be very useful in certain situations, e.g. to be able to change the boot logo on a device at runtime.
Prototype:
var ret = runSystemCommand(string command, bool waitForFinished, bool returnCommandOutput);
Parameters:
•command: A string with the command to execute •waitForFinished: Optional bool flag. If set to true (which is also default if the parameter is not set), PClient main loop waits until the command has finished. If set to false, the function will return immediately but the caller will not know the final result of the command •returnCommandOutput: If this flag is set to true, this function will return the complete console output of the executed command instead of the return value. This parameter is also optional, if not set, the default value is false. Note: If set to true, waitForFinished also needs to be true.
Return values:
•true if the command executed successfully while returnCommandOutput was set to false or not set •A string containing the complete output of the executed command if returnCommandOutput was set to true •If anything fails, an exception is thrown and the execution of the whole script file is interrupted at the line of the system call. Surround with try/catch block for error handling.
Good example:
var ret = runSystemCommand("top -n 1", true, true);
Bad example:
var ret = runSystemCommand("top", true, true);
Why is it bad? The example will never return because top will keep running, thus the JavaScript file will never finish.
Good example:
var ret = runSystemCommand("rm -rf /opt/data/own_data", true, false);
Bad example:
var ret = runSystemCommand("rm -rf /opt/*", true, false);
Why is it bad? The example will delete ALL files and folders in /opt, killing the project, PClient, updater and all user data.
Once again: Please use this function with care. There are no limitations in this function, whatever is the content of <command> will be forwarded to the system. There are plenty of commands that take a long time to process.
Always test the commands that should be used thoroughly before implementing them for field use! |
This function returns the trigger that executed the currently running JavaScript file. The return is a string identical to the event names as they are used in the program.
Prototype:
var eventName = getTriggerEvent();
Return value:
The event that triggered the JavaScript. Possible values are: Jump To Page Set Value Scale Value Next Softkey Level Previous Softkey Level Start Application Send Event To Plugin Open For Input Navigate Up Navigate Down Navigate Confirm Open PDF Reader Set Media Player Command
OnProjektInit OnProjektExit OnPageInit OnPageExit OnProjektRepeat OnPageRepeat
OnEncoderMove OnPress OnRelease OnLongPress OnLongRelease OnDblClick OnIntValueChange OnStringValueChange OnEnterValue OnEnterNewValue OnEscape OnOpenForInput OnEnabledWithFocus OnEnabledWithoutFocus
OnValueChangeByOwner OnValueChangeRequest
OnPowerOn OnLowPower OnSleep
OnReceiveTimeoutAction OnReceiveTimeoutResolvedAction OnMappingReceived
OnHeartbeatTimeout OnHeartbeatTimeoutResolved
OnEncoderPress OnEncoderRelease OnEncoderLongPress OnEncoderLongRelease OnEncoderDoublePress |