The WiConnect JavaScript API provides a framework for controlling a WiConnect device using the HTTP RESTful API. JavaScript using the WiConnect JavaScript API can run on a page served by the device HTTP Server, or, with the appropriate CORS configuration, on a page served by a remote server.
Using the WiConnect JavaScript API you can run any command on the device, and process the command response as desired.
The WiConnect Web App provides an example of a full-featured JavaScript application using the WiConnect JavaScript API.
For details of WiConnect commands, see WiConnect Documentation.
To use the WiConnect JavaScript API, you create a WiConnectDevice object, then run WiConnect command methods on the object, with callbacks to handle the command responses.
WiconnectJS can be installed with either NPM or Bower
npm install wiconnectjs
bower install wiconnectjs
//join network
nup -s
//set wlan autoconnect
set wl o e 1
//enable http server
set ht s e 1
//set http server CORS origin to wildcard to allow remote requests
set ht s c *
//save config & reboot
save
reboot
A WiConnectDevice object has a function corresponding to each of the WiConnect commands, as well as the properties:
host
string - hostname or IP address of the WiConnect Device to communicate with - default""
(localhost)timeout
integer - maximum amount of time to wait for response from the device - default120000
(milliseconds)retries
integer - number of attempts to issue command when a command request fails - default1
auth
object{user: "username", pass: "password"}
- HTTP basic auth credentials - defaultnull
To create a WiConnectDevice object, the syntax is:
var device = new WiConnectDevice({host: 'http://[deviceIP]' [, auth: {user: 'username', pass: 'password'}]|[, timeout: 20000]|[, retries: 5]});
example:
var device = new WiConnectDevice({host: 'http://12.34.56.78'});
To call a WiConnect command, run device.cmd()
, where cmd
is the name of the WiConnect command.
device.cmd([{args: 'command_arguments' [, flags: 0]}]);
The first argument of the device.cmd()
method is an optional arguments object, with the following structure:
args
string - string of command arguments - default""
flags
integer - WiConnect HTTP flag - default0
timeout
integer - maximum amount of time to wait for response from the device - default120000
(milliseconds)retries
integer - number of attempts to issue this command when a command request fails - default1
acceptCommandFailed
boolean - optional flag to specify if an error should be returned when WiConnect response withCommand Failed\r\n
- defaulttrue
example:
//issue a 'ver' command
device.ver();
//issue a 'ls' command
device.ls();
//issue 'ls -v' command
device.ls({args: '-v'});
A WiConnect command request object will be returned each time a command is issued to a device, and can be stored for later use, with the following methods:
done()
- set promise function to be executed when a successful response is received (see below)fail()
- set promise function to be executed when a request fails (see below)always()
- set promise function to be exectuted on completion of a command request (see below)abort()
- abort the command request immediately
example:
var versionRequest = device.ver();
To process the WiConnect command response, you need to either set a callback function, or set promise functions for parsing the response from the command request.
The callback function can be provided as the second argument (or first if a command arguments object is not being supplied) to the device commmand method call, using the following syntax:
device.[command]([{args: 'command_arguments' [, flags: 0]} [, callback(error, response){}]|[callback(error, response){}]]);
example:
device.ver(function(err, res){ /* process response here */ });
device.ls(function(err, res){ console.log(res); });
device.ls({args: '-v'}, function(err, res){
if(err){
/* process error here */
return;
}
/*process successful response here */
});
device.reboot();
device.[command]([{args: 'command_arguments' [, flags: 0]}])[.done(function(response){})][.fail( function(response){})][.always( function(response){})];
.done(function(response){})
optional function to run when command returns with a successful response. Note that the done
function has no err
argument.
.fail(function(error, response){})
optional function to run when command returns with a failure response.
.always(function(error, response){})
optional function to run when command response completes no matter whether success or failure.
example:
var versionRequest = device.ver();
//setup function to always log to console no matter whether failure or success
versionRequest.always(function(res) {
console.log('request complete.');
});
//setup success function for when response received
versionRequest.done(function(err, res) {
console.log('success!');
console.log('response: ', res);
console.log('WiConnect Version:', res.response);
});
//setup failure function for when HTTP error received
versionRequest.fail(function(err, res) {
console.log('fail!');
console.log('error:', err);
});
done
fail
and always
promise functions can also optionally be defined in the command arguments object.
example:
//predefine promise functions
var myDoneFunction = function(res) {
console.log("Done! here's the response:", res);
};
var myFailFunction = function(err, res){
console.log("Command failed :(", err);
};
var myAlwaysFunction = function(err, res){
console.log("Command request complete.");
};
//issue commands to device with promise functions in command arguments object
device.ls({
done: myDoneFunction,
fail: myFailFunction,
always: myAlwaysFunction
});
device.scan({
args: '-v',
retries: 3,
done: myDoneFunction,
fail: myFailFunction,
always: myAlwaysFunction
});
A timeout argument can be specified for commands to invoke a timeout error on the request after the specified number of milliseconds.
example:
//set an extremely small timeout period of 5milliseconds
//to ensure timeout error occurs
device.ver({timeout: 5}).fail(function(){
console.log('no response after 5 milliseconds');
});
//set retries for individual command to allow up to 5 attempts before failure
device.scan({retries: 5}, function(err, res) {
if(err){
//failed after 5 retries
return console.log('Device failed to return scan results after 5 attempts');
}
//command success
console.log(res);
})
.abort()
immediately abort request
example:
var versionRequest = device.ver();
//lets not wait for the response and abort the request immediately
versionRequest.abort();
The file_create
command accepts two additional arguments filename
and data
for writing a file to the WiConnect device. The data
argument is expected to be of type ArrayBuffer.
example:
// http://updates.html5rocks.com/2012/06/How-to-convert-ArrayBuffer-to-and-from-String
var stringToArrayBuffer = function(str){
var buf = new ArrayBuffer(str.length*2); // 2 bytes for each char
var bufView = new Uint16Array(buf);
for (var i=0, strLen=str.length; i < strLen; i++) {
bufView[i] = str.charCodeAt(i);
}
return buf;
};
var fileData = stringToArrayBuffer("Hello World!");
// create file on WiConnect device
device.file_create({filename: 'testFile.txt', data: fileData}, function(err, res){
if(err) {
// error creating file
console.log('Error writing testFile.txt');
return;
}
// file created successfully
console.log('testFile.txt created successfully on WiConnect device');
});
The WiConnectJS API is able to manage files of any size.
The WiConnect HTTP server has a maximum request size limit of 4KB per request. WiConnectJS handles this limit for you by calculating the file CRC, creating a new file and requesting an open stream handle, then writing file chunks to the open file stream. If you are inspecting network requests while using file_create
you will see multiple requests being sent to the WiConnect Device.
The stream_write
command accepts the additional argument data
for writing a data to an open stream on the WiConnect device. The data
argument is expected to be of type ArrayBuffer.
example:
// ID of open stream on WiConnect device
var stream_id = 0;
// data to write to stream
// stringToArrayBuffer function from previous example
var streamData = stringToArrayBuffer("hello");
// write 0 5
device.stream_write({
args: stream_id + " " + streamData.byteLength,
data: streamData
},
function(err, res){
if(err) {
// error writing to stream
console.log('Error writing to stream ' + stream_id);
return;
}
// data written successfully
console.log(streamData.byteLength + ' bytes of data written to stream ' + stream_id);
});
The WiConnectJS API is able to writing data of any size to open streams.
The WiConnect HTTP server has a maximum request size limit of 4KB per request. WiConnectJS handles this limit by writing data chunks sequentially to the open file stream. If you are inspecting network requests while using stream_write
you will see multiple requests being sent to the WiConnect Device.
example:
var streamID;
device.file_open({args: 'testFile.txt'},
function(err, res){
if(err){
console.log('file could not be opened');
return;
}
// the open stream ID will be returned in response property of res
// remove new line characters from response
streamID = res.response.replace('\r\n', '');
// now we have the open stream id, read 5 bytes of data from it
var bytesToRead = 5;
device.read({args: streamID + ' ' + bytesToRead}, // read 0 5
function(err, res){
if(err){
console.log('Reading stream ' + streamID + ' failed');
return;
}
var bytesFromStream = res.response;
// output the bytes read
console.log(bytesToRead + ' bytes read: ' + bytesFromStream);
});
});
var ws = new WebSocket('ws://[deviceIP]/stream');
example:
var ws = new WebSocket('ws://12.34.56.78/stream');
.onopen
handle for WebSocket open event
.onmessage
handler for WebSocket message received event
.onclose
handler for WebSocket close event
.send([message_data])
Send a WebSocket message to the device
.close()
Initiate WebSocket close handshake
example:
var ws = new WebSocket('ws://12.34.56.78/stream');
// function to execute once the websocket has been closed
ws.onclose = function() {
// log a message to the console when the websocket is closed
console.log('WebSocket has been closed!');
};
// function to execute each time a message is received via the websocket
ws.onmessage = function(event) {
var reader;
// log the message binary blob data to the console when we receive a websocket message
if(event.data instanceof Blob) {
reader = new FileReader();
reader.onload = function() {
return console.log(reader.result);
};
return reader.readAsText(event.data);
}
}
// function to execute when the socket has been opened successfully
ws.onopen = function() {
// log a message once websocket connection handshake is complete
console.log('WebSocket open to WiConnect device!');
// use 'list' command using a serial terminal, or using WiConnectJS
// open streams on the device will be displayed including a 'WEBS' stream
// indicating the open websocket
// e.g. using serial terminal
// > list
// ! # Type Info
// # 0 WEBS 12.34.56.78:80 12.34.56.78:54460
// now that the websocket is connected, send a message to the WiConnect device
ws.send('I am a teapot.');
// using a serial terminal, or using WiConnectJS read the stream
// e.g. using serial terminal
// > read 0 14
// I am a teapot.
// close the websocket
ws.close();
// note: the websocket will not be immediately closed
// WiConnect will keep the websocket open until all stream data has been read
// e.g.
// > read 0 1
// > [2015-03-23 | 03:21:37: Closed: 0]
};
WiConnect Web App, WiConnect JS API Library & WiConnect JS Build System
Copyright (C) 2015, Sensors.com, Inc. All Rights Reserved.
The WiConnect Web App, WiConnect JavaScript API and WiConnect JS build system are provided free of charge by Sensors.com. The combined source code, and all derivatives, are licensed by Sensors.com SOLELY for use with devices manufactured by ACKme Networks, or devices approved by Sensors.com.
Use of this software on any other devices or hardware platforms is strictly prohibited.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR AS IS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.