Skip to content

Commit

Permalink
feat: add JSDoc inline documentation and gh-page publishing
Browse files Browse the repository at this point in the history
  • Loading branch information
fh1ch committed May 27, 2017
1 parent e58b591 commit 44f88be
Show file tree
Hide file tree
Showing 6 changed files with 156 additions and 85 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
node_modules/
npm-debug.log
reports/
docs/
3 changes: 2 additions & 1 deletion .jscsrc
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,6 @@
"maximumLineLength": 320,
"requireSemicolons": true,
"requireCamelCaseOrUpperCaseIdentifiers": false,
"requireCurlyBraces": false
"requireCurlyBraces": false,
"jsDoc": false
}
9 changes: 9 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,14 @@ script:
- "npm run test"
- "cat ./reports/coverage/lcov.info | ./node_modules/.bin/coveralls"
- "npm run integration"
- "npm run docs"

deploy:
provider: pages
local_dir: ./docs
skip_cleanup: true
github_token: $GITHUB_API_KEY
on:
branch: master

sudo: false
131 changes: 49 additions & 82 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ interact with building automation devices defined by ASHRAE.
[![](https://codeclimate.com/github/fh1ch/node-bacstack/badges/gpa.svg)](https://codeclimate.com/github/fh1ch/node-bacstack)
[![](https://david-dm.org/fh1ch/node-bacstack/status.svg)](https://david-dm.org/fh1ch/node-bacstack)

> **Note:** This is an early prototype and shall not be considerate as stable.
> **Note:** This is an early prototype and shall not be considered as stable.
> Use it with caution and at your own risk!
## Usage
Expand All @@ -20,115 +20,82 @@ Add Node BACstack to your project by using:
$ npm install --save bacstack
```

#### Client
The API documentation is available under **[fh1ch.github.io/node-bacstack](https://fh1ch.github.io/node-bacstack)**.

To be able to communicate to BACNET devices, you have to initialize a new
bacstack instance. Hereby, following options are avilable:

- `option` *[object]* - The options object used for parameterising the bacstack.
- `port` *[number]* - BACNET communication port for listening and sending. Default is `47808`. *Optional*.
- `interface` *[string]* - Specific BACNET communication interface if different from primary one. *Optional*.
- `broadcastAddress` *[string]* - The address used for broadcast messages. Default is `255.255.255.255`. *Optional*.
- `adpuTimeout` *[number]* - The timeout in milliseconds until a transaction should be interpreted as error. Default is `3000`. *Optional*.
### Example

``` js
var bacnet = require('bacstack');
var client = bacnet({
port: 47809, // Use BAC1 as communication port
interface: '192.168.251.10', // Listen on a specific interface
broadcastAddress: '192.168.251.255', // Use the subnet broadcast address
adpuTimeout: 6000 // Wait twice as long for response
});
```

#### Who Is

The `whoIs` command discovers all BACNET devices in the network.

- `lowLimit` *[number]* - Minimal device instance number to search for. *Optional*.
- `highLimit` *[number]* - Maximal device instance number to search for. *Optional*.
- `address` *[string]* - Unicast address if command should device directly. *Optional*.

``` js
var bacnet = require('bacstack');
var client = bacnet();
// Initialize BACStack
var client = bacnet({adpuTimeout: 6000});

// Discover Devices
client.on('iAm', function(address, deviceId, maxAdpu, segmentation, vendorId) {
console.log('address: ', address, ' - deviceId: ', deviceId, ' - maxAdpu: ', maxAdpu, ' - segmentation: ', segmentation, ' - vendorId: ', vendorId);
});

client.whoIs();
```

#### Read Property

The `readProperty` command reads a single property of an object from a device.

- `address` *[string]* - IP address of the target device.
- `objectType` *[number]* - The BACNET object type to read.
- `objectInstance` *[number]* - The BACNET object instance to read.
- `propertyId` *[number]* - The BACNET property id in the specified object to read.
- `arrayIndex` *[number]* - The array index of the property to be read.
- `next` *[function]* - The callback containing an error, in case of a failure and value object in case of success.

``` js
var bacnet = require('bacstack');
var client = bacnet();

client.readProperty('192.168.1.43', 8, 44301, 28, null, function(err, value) {
// Read Device Object
var requestArray = [
{objectIdentifier: {type: 8, instance: 4194303}, propertyReferences: [{propertyIdentifier: 8}]}
];
client.readPropertyMultiple('192.168.1.43', requestArray, function(err, value) {
console.log('value: ', value);
});
```

#### Write Property
## Contributing

The `writeProperty` command writes a single property of an object to a device.
Implementing and maintaining a protocol stack is a lot of work, therefore any
help is appreciated, from creating issues, to contributing documentation, fixing
issues and adding new features.

- `address` *[string]* - IP address of the target device.
- `objectType` *[number]* - The BACNET object type to write.
- `objectInstance` *[number]* - IP address of the target device.
- `propertyId` *[number]* - The BACNET property id in the specified object to write.
- `priority` *[number]* - The priority to be used for writing to the property.
- `valueList` *[array]* - A list of values to be written to the speicifed property. The `Tag` value has to be a `BacnetApplicationTags` declaration as specified in `lib/bacnet-enum.js`.
- `next` *[function]* - The callback containing an error, in case of a failure and value object in case of success.
Please follow the best-practice contribution guidelines as mentioned below when
submitting any changes.

propertyId, ,
### Code Style

``` js
var bacnet = require('bacstack');
var client = bacnet();
This module uses the [Google JavaScript Code-Style](https://google.github.io/styleguide/javascriptguide.xml)
and enforces it using [JSCS](http://jscs.info/) as additional linter beneath
[JSHint](http://jshint.com/). You can test if your changes comply with the code
style by executing:

client.writeProperty('192.168.1.43', 8, 44301, 28, 12, [{Tag: 4, Value: 100}], function(err, value) {
console.log('value: ', value);
});
``` sh
$ npm run lint
```

#### Read Property Multiple
### Testing and Coverage

The `readPropertyMultiple` command reads multiple properties in multiple objects
from a device.
Testing is done using [Mocha](https://mochajs.org/) and is separated into two
sets, `unit` and `integration`. While unit tries to test on function level,
including synthetic decoding and encoding, the integration tests are using real
recorded data and are only mocking the transport layer.

- `address` *[string]* - IP address of the target device.
- `propertyIdAndArrayIndex` *[array]* - List of object and property specifications to be read.
- `objectIdentifier` *[object]* - Specifies which object to read.
- `type` *[number]* - The BACNET object type to read.
- `instance` *[number]* - The BACNET object instance to read.
- `propertyReferences` *[array]* - List of properties to be read.
- `propertyIdentifier` *[number]* - The BACNET property id in the specified object to read. Also supports `8` for *all* properties.
- `next` *[function]* - The callback containing an error, in case of a failure and value object in case of success.
For both sets, the test-coverage is calculated using [Istanbul](https://istanbul.js.org/).
Running the tests and calculating the coverage can be done locally by executing:

``` js
var bacnet = require('bacstack');
var client = bacnet();
``` sh
$ npm run test
$ npm run integration
```

var requestArray = [
{objectIdentifier: {type: 8, instance: 4194303}, propertyReferences: [{propertyIdentifier: 8}]}
];
client.readPropertyMultiple('192.168.1.43', requestArray, function(err, value) {
console.log('value: ', value);
});
It is expected that new features or fixes do not negatively impact the test
results or the coverage.

### Documentation

The API documentation is generated using [JSDoc](http://usejsdoc.org/) and
relies on in-line JSDoc3 syntax. The documentation can also be built locally by
executing:

``` sh
$ npm run docs
```

It is expected that new features or changes are reflected in the documentation
as well.

## License

[The MIT License](http://opensource.org/licenses/MIT)
Expand Down
92 changes: 91 additions & 1 deletion index.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,24 @@ var events = require('events');
var baClient = require('./lib/bacnet-client');
var baEnum = require('./lib/bacnet-enum');

/**
* To be able to communicate to BACNET devices, you have to initialize a new bacstack instance.
* @class bacstack
* @param {object=} settings - The options object used for parameterising the bacstack.
* @param {number=} [settings.port=47808] - BACNET communication port for listening and sending.
* @param {string=} settings.interface - Specific BACNET communication interface if different from primary one.
* @param {string=} [settings.broadcastAddress=255.255.255.255] - The address used for broadcast messages.
* @param {number=} [settings.adpuTimeout=3000] - The timeout in milliseconds until a transaction should be interpreted as error.
* @example
* var bacnet = require('bacstack');
*
* var client = bacnet({
* port: 47809, // Use BAC1 as communication port
* interface: '192.168.251.10', // Listen on a specific interface
* broadcastAddress: '192.168.251.255', // Use the subnet broadcast address
* adpuTimeout: 6000 // Wait twice as long for response
* });
*/
module.exports = function(settings) {
var self = new events.EventEmitter();

Expand All @@ -22,21 +40,93 @@ module.exports = function(settings) {
// Public enums
self.enum = baEnum;

// Public functions
/**
* The whoIs command discovers all BACNET devices in a network.
* @function bacstack.whoIs
* @param {number=} lowLimit - Minimal device instance number to search for.
* @param {number=} highLimit - Maximal device instance number to search for.
* @param {string=} address - Unicast address if command should device directly.
* @fires bacstack.iAm
* @example
* client.whoIs();
*/
self.whoIs = function(lowLimit, highLimit, address) {
client.whoIs(lowLimit, highLimit, address, function(address, deviceId, maxAdpu, segmentation, vendorId) {

/**
* @event bacstack.iAm
* @param {string} address - The IP address of the detected device.
* @param {number} deviceId - The BACNET device-id of the detected device.
* @param {number} maxAdpu - The max ADPU size the detected device is supporting.
* @param {number} segmentation - The type of segmentation the detected device is supporting.
* @param {number} vendorId - The BACNET vendor-id of the detected device.
* @example
* client.on('iAm', function(address, deviceId, maxAdpu, segmentation, vendorId) {
* console.log('address: ', address, ' - deviceId: ', deviceId, ' - maxAdpu: ', maxAdpu, ' - segmentation: ', segmentation, ' - vendorId: ', vendorId);
* });
*/
self.emit('iAm', address, deviceId, maxAdpu, segmentation, vendorId);
});
};

/**
* The readProperty command reads a single property of an object from a device.
* @function bacstack.readProperty
* @param {string} address - IP address of the target device.
* @param {number} objectType - The BACNET object type to read.
* @param {number} objectInstance - The BACNET object instance to read.
* @param {number} propertyId - The BACNET property id in the specified object to read.
* @param {number=} arrayIndex - The array index of the property to be read.
* @param {function} next - The callback containing an error, in case of a failure and value object in case of success.
* @example
* client.readProperty('192.168.1.43', 8, 44301, 28, null, function(err, value) {
* console.log('value: ', value);
* });
*/
self.readProperty = function(address, objectType, objectInstance, propertyId, arrayIndex, next) {
client.readProperty(address, objectType, objectInstance, propertyId, arrayIndex, next);
};

/**
* The writeProperty command writes a single property of an object to a device.
* @function bacstack.writeProperty
* @param {string} address - IP address of the target device.
* @param {number} objectType - The BACNET object type to write.
* @param {number} objectInstance - The BACNET object instance to write.
* @param {number} propertyId - The BACNET property id in the specified object to write.
* @param {number} priority - The priority to be used for writing to the property.
* @param {object[]} valueList - A list of values to be written to the speicifed property.
* @param {number} valueList.Tag - The data-type of the value to be written. Has to be a BacnetApplicationTags declaration as specified in lib/bacnet-enum.js.
* @param {number} valueList.Value - The actual value to be written.
* @param {function} next - The callback containing an error, in case of a failure and value object in case of success.
* @example
* client.writeProperty('192.168.1.43', 8, 44301, 28, 12, [{Tag: 4, Value: 100}], function(err, value) {
* console.log('value: ', value);
* });
*/
self.writeProperty = function(address, objectType, objectInstance, propertyId, priority, valueList, next) {
client.writeProperty(address, objectType, objectInstance, propertyId, priority, valueList, next);
};

/**
* The readPropertyMultiple command reads multiple properties in multiple objects from a device.
* @function bacstack.readPropertyMultiple
* @param {string} address - IP address of the target device.
* @param {object[]} propertyIdAndArrayIndex - List of object and property specifications to be read.
* @param {object} propertyIdAndArrayIndex.objectIdentifier - Specifies which object to read.
* @param {number} propertyIdAndArrayIndex.objectIdentifier.type - The BACNET object type to read.
* @param {number} propertyIdAndArrayIndex.objectIdentifier.instance - The BACNET object instance to read.
* @param {object[]} propertyIdAndArrayIndex.propertyReferences - List of properties to be read.
* @param {number} propertyIdAndArrayIndex.propertyReferences.propertyIdentifier - The BACNET property id in the specified object to read. Also supports 8 for all properties.
* @param {function} next - The callback containing an error, in case of a failure and value object in case of success.
* @example
* var requestArray = [
* {objectIdentifier: {type: 8, instance: 4194303}, propertyReferences: [{propertyIdentifier: 8}]}
* ];
* client.readPropertyMultiple('192.168.1.43', requestArray, function(err, value) {
* console.log('value: ', value);
* });
*/
self.readPropertyMultiple = function(address, propertyIdAndArrayIndex, next) {
client.readPropertyMultiple(address, propertyIdAndArrayIndex, next);
};
Expand Down
5 changes: 4 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@
"scripts": {
"lint": "jshint lib/ index.js && jscs lib/ index.js",
"test": "istanbul cover --dir reports/coverage node_modules/mocha/bin/_mocha -- test/unit/*.spec.js",
"integration": "istanbul cover --dir reports/coverage node_modules/mocha/bin/_mocha -- test/integration/*.spec.js"
"integration": "istanbul cover --dir reports/coverage node_modules/mocha/bin/_mocha -- test/integration/*.spec.js",
"docs": "jsdoc -d ./docs -t node_modules/docdash ./lib ./index.js ./README.md"
},
"repository": {
"type": "git",
Expand Down Expand Up @@ -35,8 +36,10 @@
},
"devDependencies": {
"chai": "^3.5.0",
"docdash": "^0.4.0",
"istanbul": "^0.4.5",
"jscs": "^3.0.7",
"jsdoc": "^3.4.3",
"jshint": "^2.9.4",
"mocha": "^3.2.0"
}
Expand Down

0 comments on commit 44f88be

Please sign in to comment.