Skip to content

Commit e147bbe

Browse files
committed
initial commit
1 parent 1957890 commit e147bbe

File tree

8 files changed

+253
-2
lines changed

8 files changed

+253
-2
lines changed

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
node_modules
2+
.DS_Store
3+
.idea

README.md

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,31 @@
1-
# cayennejs
2-
Cayenne IoT Node.JS library
1+
# Cayenne IoT Node.JS API
2+
3+
```
4+
npm install cayennejs
5+
```
6+
7+
```
8+
var Cayenne = require('cayennejs');
9+
10+
// Initiate MQTT API
11+
const cayenneClient = new Cayenne.MQTT({
12+
username: "foobar",
13+
password: "secret",
14+
clientId: "thing-id"
15+
});
16+
17+
cayenneClient.connect((err, mqttClient) => {
18+
// dashboard widget automatically detects datatype & unit
19+
cayenneClient.kelvinWrite(3, 65);
20+
21+
// sending raw values without datatypes
22+
cayenneClient.rawWrite(4, 123);
23+
24+
// subscribe to data channel for actions (actuators)
25+
cayenneClient.on("cmd9", function(data) {
26+
console.log(data);
27+
});
28+
29+
});
30+
31+
```

index.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
module.exports = require('./lib/cayenne');

lib/cayenne.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
// export the class
2+
module.exports = {
3+
MQTT: require('./mqtt')
4+
};

lib/datatypes.js

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
var TYPE = {};
2+
3+
TYPE.ANALOG = "analog"
4+
TYPE.DIGITAL = "digital"
5+
TYPE.BAROMETRIC_PRESSURE = "bp" // Barometric pressure
6+
TYPE.BATTERY = "batt" // Battery
7+
TYPE.LUMINOSITY = "lum" // Luminosity
8+
TYPE.PROXIMITY = "prox" // Proximity
9+
TYPE.RELATIVE_HUMIDITY = "rel_hum" // Relative Humidity
10+
TYPE.TEMPERATURE = "temp" // Temperature
11+
TYPE.VOLTAGE = "voltage" // Voltage
12+
13+
var UNIT = {};
14+
UNIT.UNDEFINED = "null"
15+
UNIT.PASCAL = "pa" // Pascal
16+
UNIT.HECTOPASCAL = "hpa" // Hectopascal
17+
UNIT.PERCENT = "p" // % (0 to 100)
18+
UNIT.RATIO = "r" // Ratio
19+
UNIT.VOLTS = "v" // Volts
20+
UNIT.LUX = "lux" // Lux
21+
UNIT.CENTIMETER = "cm" // Centimeter
22+
UNIT.METER = "m" // Meter
23+
UNIT.DIGITAL = "d" // Digital (0/1)
24+
UNIT.FAHRENHEIT = "f" // Fahrenheit
25+
UNIT.CELSIUS = "c" // Celsius
26+
UNIT.KELVIN = "k" // Kelvin
27+
UNIT.MILLIVOLTS = "mv" // Millivolts
28+
29+
module.exports = {
30+
TYPE:TYPE,
31+
UNIT:UNIT
32+
}

lib/mqtt.js

Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
const routes = require('routes');
2+
const mqtt = require('mqtt');
3+
const DataTypes = require('./datatypes.js');
4+
const TYPE = DataTypes.TYPE;
5+
const UNIT = DataTypes.UNIT;
6+
const events = require('events');
7+
const Router = routes();
8+
const THINGS = 'things';
9+
10+
11+
var Cayenne = function(options) {
12+
apiVersion = "v1";
13+
this.options = options;
14+
15+
this.debug = this.options.debug || false;
16+
this.ssl = this.options.ssl || false;
17+
18+
this.broker = this.options.broker || "mqtt.mydevices.com";
19+
20+
this.client = null;
21+
this.connected = false;
22+
23+
this.rootTopic = [
24+
apiVersion,
25+
this.options.username,
26+
THINGS,
27+
this.options.clientId
28+
].join('/');
29+
30+
};
31+
32+
Cayenne.prototype.__proto__ = events.EventEmitter.prototype;
33+
34+
Cayenne.prototype.connect = function(callback) {
35+
const self = this;
36+
thingTopic = this.rootTopic;
37+
38+
this.client = mqtt.connect("mqtt://" + broker, {
39+
username: this.options.username,
40+
password: this.options.password,
41+
clientId: this.options.clientId,
42+
});
43+
44+
this.client.on('connect', function () {
45+
self.connected = true;
46+
self.client.subscribe(self.rootTopic + '/cmd/+');
47+
48+
return callback(null, self.client);
49+
});
50+
51+
this.client.on('message', self.onMessage.bind(self));
52+
53+
const cmdTopic = apiVersion + '/:username/'+THINGS+'/:thingId/cmd/:channel';
54+
Router.addRoute(cmdTopic, this.handleCommand.bind(this));
55+
56+
}
57+
58+
Cayenne.prototype.rawWrite = function(channel, value, type, unit) {
59+
var topic = this.getDataTopic(channel);
60+
var payload;
61+
62+
if (unit === undefined) {
63+
unit = "null";
64+
}
65+
66+
if (type === undefined) {
67+
payload = value;
68+
} else {
69+
payload = type + "," + unit + "=" + value;
70+
}
71+
72+
this.client.publish(topic, payload);
73+
};
74+
75+
76+
Cayenne.prototype.getDataTopic = function (channel) {
77+
return this.rootTopic + '/data/' + channel;
78+
};
79+
80+
Cayenne.prototype.handleCommand = function (req) {
81+
const payload = req.payload.split(',');
82+
const seq = payload[0];
83+
const cmd = payload[1];
84+
85+
this.client.publish(this.rootTopic + '/response', 'ok,'+seq);
86+
this.client.publish(this.rootTopic + '/data/' + req.meta.channel, cmd);
87+
88+
this.emit("cmd" + req.meta.channel, req);
89+
}
90+
91+
Cayenne.prototype.onMessage = function(topic, payload) {
92+
var route = Router.match(topic);
93+
94+
if (!route) {
95+
return;
96+
}
97+
98+
var req = {
99+
path: topic,
100+
payload: payload.toString(),
101+
meta: route ? route.params: null,
102+
splats: route ? route.splats : null
103+
};
104+
105+
return route.fn(req);
106+
}
107+
108+
Cayenne.prototype.celsiusWrite = function (channel, value) {
109+
this.rawWrite(channel, value, TYPE.TEMPERATURE, UNIT.CELSIUS);
110+
}
111+
112+
Cayenne.prototype.fahrenheitWrite = function (channel, value) {
113+
this.rawWrite(channel, value, TYPE.TEMPERATURE, UNIT.FAHRENHEIT)
114+
}
115+
116+
Cayenne.prototype.kelvinWrite = function (channel, value) {
117+
this.rawWrite(channel, value, TYPE.TEMPERATURE, UNIT.KELVIN)
118+
}
119+
120+
Cayenne.prototype.luxWrite = function (channel, value) {
121+
this.rawWrite(channel, value, TYPE.LUMINOSITY, UNIT.LUX)
122+
}
123+
124+
Cayenne.prototype.pascalWrite = function (channel, value) {
125+
this.rawWrite(channel, value, TYPE.BAROMETRIC_PRESSURE, UNIT.PASCAL)
126+
}
127+
128+
Cayenne.prototype.hectoPascalWrite = function (channel, value) {
129+
this.rawWrite(channel, value, TYPE.BAROMETRIC_PRESSURE, UNIT.HECTOPASCAL)
130+
}
131+
132+
module.exports = Cayenne;

package.json

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
{
2+
"name": "cayennejs",
3+
"description": "Cayenne API Node.JS Library",
4+
"version": "0.0.1",
5+
"homepage": "mydevices.com/cayenne",
6+
"repository": "https://github.com/myDevicesIoT/cayennejs",
7+
"main": "",
8+
"keywords": ["cayenne", "mqtt", "iot", "api", "mydevices"],
9+
"engines": {
10+
"node": ">=4.0.0"
11+
},
12+
"dependencies": {
13+
"mqtt": "2.x.x",
14+
"routes": "^2.1.0"
15+
},
16+
"devDependencies": {
17+
"assert": "^1.4.1",
18+
"mocha": "^3.1.2"
19+
},
20+
"scripts": {
21+
"test": "mocha --timeout 2000"
22+
},
23+
"license": "MIT"
24+
}

test/mqtt.js

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
const Cayenne = require('../');
2+
3+
const cayenneClient = new Cayenne.MQTT({
4+
username: "",
5+
password: "",
6+
clientId: ""
7+
});
8+
9+
describe('MQTT connection', function() {
10+
11+
it('should connect with valid credentials', function(done) {
12+
cayenneClient.connect(done);
13+
});
14+
15+
it('should send sensor data', function(done) {
16+
cayenneClient.kelvinWrite(3, 65);
17+
18+
done();
19+
});
20+
21+
it('should subscribe to channel and receive data', function (done) {
22+
cayenneClient.on("cmd9", function(){
23+
setTimeout(done, 1000);
24+
});
25+
});
26+
});

0 commit comments

Comments
 (0)