« Close

Datasheets and User Guides

App Notes

Software & Driver

 

Kipling Hacks and Hidden Features

Kipling is an open source application. Its source code is published to Github in a project called ljswitchboard-project_manager. The application is written in Node.js and currently uses the GUI front end tool NW.js (previously known as node-webkit). Sometimes the README.md files descriptions lag behind how the application works and what versions of packages it uses. It has a lot of moving parts but one really cool feature about NW.js applications (in newer versions look at the SDK builds) is the "developer tools" interface. NW.js, as well as Github's Electron, are both based off Google's Chromium open source application and run JavaScript/HTML/CSS files as a desktop application. These applications integrate features of Node.js into them which allow applications to perform native system calls such as file I/O, networking, and most importantly, communicate with .dll/.so/.dylib files. This lets the application use our LJM driver to communicate with and control devices. Both of these tools are really nice for developing responsive, cross platform applications. For a quick getting started tutorial with LJM and Node.js, look at our Node.js Examples page.

Given that Kipling is an open source project and it provides access to the back-end for development purposes, we have had a few customer questions that have been solved or assisted by informing them on how to open the developer tools and run a few commands. These commands may or may not change in the future so don't be surprised if they don't work in the future. Feel free to email us if you really need to dig into Kipling's back-end to accomplish something or have questions. Also feel free to post on Github – we will receive your questions and do our best to address them. If you want to contribute to the application, please let us know.

Opening the Developer Tools

Press the "ctrl+shift+alt+c" keys to open a second window. If this window isn't familiar to you, Google search "google chrome developer tools" to learn more. The key tab that this webpage addresses and utilizes is the console which lets us type and execute JavaScript code.

Kipling Hacking - Open a Device by IP

Opening a device by IP address

In Kipling 3.1.4 you can navigate to the device selector tab and type:

1
2
3
4
5
6
7
activeModule.viewGen.onConnect({'connectionType':{'dt': [device type number T7: 7],'ct':[connection type number usb:1, eth:3, wifi: 4], 'ipAddress':'[device ip address ex: 192.168.1.2]'},device:{'isMockDevice':false,'serialNumber':[device serial number ex: 470010111]}}).then(pr,pe)

// Example T7, Ethernet, IP:192.168.1.2, SN: 470010111:
activeModule.viewGen.onConnect({'connectionType':{'dt':7, 'ct':3, 'ipAddress':'192.168.1.2'}, device:{'isMockDevice':false,'serialNumber':470010111}}).then(pr,pe)

// Many of the function calls return promises as implemented by the npm library "q". There are two
// globally defined functions "pr" and "pe" that print the result, and print the error.

Kipling Hacking - Look up Error Codes

Looking up Error Codes

You can run a line of code to look up an LJM error code to get its definition. This is particularly useful when developing Lua Scripts because errors are reported as numbers. These numbers can be deciphered and help determine the issue at hand.

1
2
3
modbus_map.getErrorInfo(1236)
// or
modbus_map.getErrorInfo("LJME_CANNOT_OPEN_DEVICE")

Kipling Hacking - Look up Register Information

Looking up Register Information

You can run a line of code to look up an LJM error code to get what its meaning is, for example:

1
2
3
modbus_map.getAddressInfo(0)
// or
modbus_map.getAddressInfo("AIN0")

Kipling Hacking - Device Control

Device Control

Not all modules (tabs, ex: Device Selector, Device Info, etc.) support this but several do. You can run various commands that communicate directly with the device. One module that does is the Device Info module. For more details look at the ljswitchboard-ljm_device_curator Github repository.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
// Read one register 
sdModule.activeDevice.iRead('AIN0').then(pr,pe) 

// Read many addresses in one modbus transaction 
sdModule.activeDevice.iReadMany(['AIN0','AIN1']).then(pr,pe)

// Perform multiple single read calls aka multiple modbus reads
sdModule.activeDevice.iReadMultiple(['AIN0','AIN1']).then(pr,pe)

// Write to one register.
sdModule.activeDevice.iWrite('DAC0',0).then(pr,pe)

Kipling Hacking - set RTC time

Configure the RTC Timestamp

While you are on a tab that lets you communicate with the device (for example the "Lua Script Debugger" tab, you can configure the T7s RTC with your computer's current time with the following script. More information about the T7s RTC can be found in section 19.0 RTC (T7-Pro Only)

sdModule.activeDevice.write('RTC_SET_TIME_S',(new Date()).getTime()/1000).then(pr,pe)

To verify that this worked properly, run the "Read RTC" script. The returned timestamp should reflect the current UTC time.

Kipling Hacking - Download Digit Data

Download Data from a Digit

Most likely requires Kipling 3.1.5 and higher. Possibly requires Kipling 3.1.6 and higher. While you are on a tab that lets you communicate with the device (for example the "Device Info" tab), you can download the data that a Digit has logged. More information about the Digit's logging abilities can be found in the Digit Datasheet.

sdModule.activeDevice.callFunc('readDigitLoggedData',[]).then(function(data){
    console.log('Downloaded data from Digit, creating file.');
    // var dataRaw = JSON.stringify(data, null, 4);
    var txtData = '';
    try {
    var basicDataToSave = {};
    Object.keys(data).forEach(function(key) {
        if(key !== 'data') {
            basicDataToSave[key] = data[key];
        }
    });
    txtData += 'Items Logged: ';
    if(data.logParams.itemsLogged.temperature) {
        txtData += 'Temperature';
    }
    if(data.logParams.itemsLogged.temperature) {
        txtData += 'Humidity';
    }
    if(data.logParams.itemsLogged.temperature) {
        txtData += 'Light';
    }
    txtData += '\nNum Saved Readings, ' + data.logParams.storedBytes.numReadings;
    txtData += '\nLog Interval: ' + data.logParams.logInterval.time;
    txtData += '\nStart Time: ' + data.logParams.startTime.time;
    txtData += '\nStart Time value: ' + data.logParams.startTime.value;
    txtData += '\nHeaders:\nTime, Temperature (C), Temperature (' + data.temperatureUnits+ '), Humidity (%RH), Light (lux), warning, pwrFail, reset, usbActive\n';
 
    data.data.forEach(function(dataPoint) {
        txtData += dataPoint.time.toString() + ', ';
        txtData += dataPoint.temperatureC.toString() + ', ';
        txtData += dataPoint.temperature.toString() + ', ';
        txtData += dataPoint.humidity.toString() + ', ';
        txtData += dataPoint.light.toString() + ', ';
        txtData += dataPoint.sysFlags.warning.toString() + ', ';
        txtData += dataPoint.sysFlags.pwrFail.toString() + ', ';
        txtData += dataPoint.sysFlags.reset.toString() + ', ';
        txtData += dataPoint.sysFlags.usbActive.toString() + '\n';
    });
    } catch(err) {
        console.log('Error making data...', err);
    }
    var fp = path.join('C:','Users','chris','DGT_' + sdModule.activeDevice.savedAttributes.serialNumber.toString() + '_data.txt');
    // var fpRaw = path.join('C:','Users','chris','DGT_' + sdModule.activeDevice.savedAttributes.serialNumber.toString() + '_raw_data.txt');
 
    try {
        fs.writeFileSync(fp, txtData, {'flag': 'w'});
        // fs.writeFileSync(fpRaw, dataRaw, {'flag': 'w'});
    } catch(err) {
        console.log('Error creating file', err);
    }
    console.log('Finished making file');
},pe);

A message should print out saying "Finished Making File" when finished. You can configure where the data is saved by changing the line of code that defines "var fp".