Skip to content
This repository was archived by the owner on Jul 25, 2024. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
0a65109
Fix simulator code + add definition of creating shadow to be used by …
Aug 29, 2017
0a0f33b
Add frequency of polling as a configurable option in device.json
Aug 29, 2017
f95349b
Only increment flow count when a zero to one transition occurs
Aug 29, 2017
6074374
Add color attributes on register + rename from deviceId to thingName
Aug 29, 2017
2ea1114
use default read interval - used across all sensors
Aug 30, 2017
f970c65
1st cut of Ultrasonic code including defining a read function
Aug 30, 2017
3228731
Implement Beer display messages including implementation of self-auto…
Sep 3, 2017
a571606
Move Flow.on callback method into initReaders
Sep 3, 2017
eb294ec
Fix borked device shadow registration and register device config and …
Sep 3, 2017
a4f80a9
Implement shadow updating of beer data and config data (both can be p…
Sep 3, 2017
161680b
Add missing packages for new beer LCD messaging. Move message code co…
Sep 3, 2017
44f2f33
Initial implementation of broken ultrasonic ranger. Currently sensor …
Sep 3, 2017
d88e9ad
Update Johnny-5 to latest tagged release 0.11.6
Sep 3, 2017
10187ee
Modify start sequence so that device shadow updates (which can includ…
Sep 5, 2017
3aebfd6
Improve auto-scroll to actually scroll character by character + defin…
Sep 7, 2017
c6943ce
Updated FlowSensor code including both analog and digital sensor opti…
Sep 28, 2017
05b84d3
Fix beer percentage calculation!
Sep 29, 2017
8569999
Add IOT error callback handling to avoid node exiting.
Oct 2, 2017
d675d38
Merge pull request #12 from andyfase/feature/device
jerwallace Nov 6, 2017
6a1fbe0
Remove interfaces as a published item
jerwallace Nov 18, 2017
0711654
Enable publish of sensor data to shadow + disable shadow versioning
Nov 22, 2017
942d4a1
Update default strings with precision floats
Nov 23, 2017
309a3f1
Merge pull request #14 from andyfase/feature/device
jerwallace Nov 27, 2017
393a3fa
updated grove-lcd.js to display readable kegdata
veloduff Oct 1, 2018
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 44 additions & 0 deletions device/components/grove-flow-sensor-analog.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
var GroveSensor = require("./grove-sensor.js");

// NOTE: We set this as an ANALOG signal not DIGITAL!!!
AnalogFlowSensor = function(pin, freq, multiplier) {
GroveSensor.call(this, { pin : pin, freq: freq });
this.flowMultiplier = multiplier;
this.flowCount = 0;
this.isLow = false;

this.within([0,100], this.lowTrigger);
this.within([900,1023], this.highTrigger);
};


AnalogFlowSensor.prototype = Object.create(GroveSensor.prototype, {
isFlowing: {
value: function() {
if (this.flowCount>0) return true;
else return false;
}
},
read: {
value: function() {
var _fc = this.flowCount;
this.flowCount = 0;
return _fc * this.flowMultiplier;
}
},
lowTrigger: {
value: function() {
this.isLow = true;
}
},
highTrigger: {
value: function() {
if (this.isLow) {
this.flowCount++;
}
this.isLow = false;
}
}
});

exports = module.exports = AnalogFlowSensor;
47 changes: 31 additions & 16 deletions device/components/grove-flow-sensor.js
Original file line number Diff line number Diff line change
@@ -1,22 +1,37 @@
var GroveSensor = require("./grove-sensor.js");

FlowSensor = function(pin) {
GroveSensor.call(this, { pin : pin, type: "digital" });
};
FlowSensor = function(pin, freq, multiplier) {
GroveSensor.call(this, { pin : pin, type: "digital", freq: freq });
this.flowMultiplier = multiplier;
this.flowCount = 0;
this.last = 0;

FlowSensor.prototype = Object.create(GroveSensor.prototype);
FlowSensor.prototype.flowCount = 0;
FlowSensor.prototype.isFlowing = function () {
if (this.flowCount>0) return true;
else return false;
}
FlowSensor.prototype.incrementFlowCount = function () {
this.flowCount++;
this.on("change", this.processChange);
};
FlowSensor.prototype.read = function () {
var _fc = this.flowCount;
this.flowCount = 0;
return _fc;
}


FlowSensor.prototype = Object.create(GroveSensor.prototype, {
isFlowing: {
value: function() {
if (this.flowCount>0) return true;
else return false;
}
},
read: {
value: function() {
var _fc = this.flowCount;
this.flowCount = 0;
return _fc * this.flowMultiplier;
}
},
processChange: {
value: function() {
if (this.last === 0 && this.value === 1) {
this.flowCount++;
}
this.last = this.value;
}
}
});

exports = module.exports = FlowSensor;
117 changes: 103 additions & 14 deletions device/components/grove-lcd.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,25 @@
var five = require("johnny-five");
var vsprintf = require('sprintf-js').vsprintf;
var pad = require('pad');

GroveLCD = function(messages) {
GroveLCD = function(config) {
five.LCD.call(this, {
controller: "JHD1313M1"
});
this.messages = messages;
this.messages = null;
this.autoscroll.lines = [];
this.autoscroll.linepos = [];
this.autoscroll.wait = [];
this.interval = {
autoscroll: null,
messages: null
};
this.timer = {};
this.autoscroll.position = 0;
this.currentMessage = 0;
this.kegdata = {};

this.updateConfig(config, false);
};

GroveLCD.prototype = Object.create(five.LCD.prototype, {
Expand All @@ -28,20 +43,94 @@ GroveLCD.prototype = Object.create(five.LCD.prototype, {
).cursor(0, 0).print(line1).cursor(1,0).print(line2);
}
},
displayRandomMessage: {
value: function () {
try {
var randColor = [
Math.floor(Math.random() * 255),
Math.floor(Math.random() * 255),
Math.floor(Math.random() * 255),
]
var randMessage = Math.floor(Math.random() * this.messages.length);
this.printRGB(randColor,this.messages[randMessage].line1,this.messages[randMessage].line2);
} catch (e) {
console.log("Error printing...");
startAutoScroll: {
value: function() {
this.timer.scroll = setInterval(this.printContinousScrolling, this.interval.autoscroll, this);
this.timer.message = setInterval(this.displayBeerMessage, this.interval.messages, this);
this.displayBeerMessage(this);
}
},
printContinousScrolling: {
value: function (lcd) {
if (lcd.autoscroll.lines.length < 1) {
return;
}
for (var i=0; i < lcd.autoscroll.lines.length; i++) {
if (lcd.autoscroll.lines[i].length > 16) { // scroll if length of overall line greater than 16 characters

if (lcd.autoscroll.linepos[i] == null) {
lcd.autoscroll.linepos[i] = 0;
}

if (lcd.autoscroll.linepos[i] == 0 || lcd.autoscroll.linepos[i] + 16 >= lcd.autoscroll.lines[i].length) {
lcd.autoscroll.wait[i] = (lcd.autoscroll.wait[i] == null) ? 1 : lcd.autoscroll.wait[i] + 1;
if (lcd.autoscroll.wait[i] >= 4) {
lcd.autoscroll.linepos[i] = (lcd.autoscroll.linepos[i] > 0) ? 0 : 1;
lcd.autoscroll.wait[i] = null;
}
} else {
lcd.autoscroll.linepos[i]++;
}

lcd.cursor(i,0).print(lcd.autoscroll.lines[i].substring(lcd.autoscroll.linepos[i], lcd.autoscroll.linepos[i] + 16));
}
else {
lcd.cursor(i,0).print(pad(lcd.autoscroll.lines[i],16));
}
}
}
},
updateConfig: {
value: function(config, reset) {
this.messages = config.messages;
this.interval.autoscroll = config.intervals.autoScroll;
this.interval.messages = config.intervals.rotateMessages;

if (reset) {
// reset auto-scroll
clearTimeout(this.timer.scroll);
clearTimeout(this.timer.message);
this.autoscroll.position = 0;
this.startAutoScroll();
}
}
},
updateKegData: {
value: function(data) {
this.kegdata = data;
}
},
displayBeerMessage: {
value: function (lcd) {
// only display messages if we have beer info to display
if (! ('usage' in lcd.kegdata)) {
return
}

// calculate beer usage data to display
lcd.kegdata.used = Math.round(((lcd.kegdata.size - lcd.kegdata.usage) / lcd.kegdata.size) * 100);
lcd.kegdata.left = Math.round((lcd.kegdata.size - lcd.kegdata.usage) * 100) / 100;

//substitute in needed variables
var line1vars = [];
var line2vars = [];
for (var i=0; i < lcd.messages[lcd.currentMessage].line1vars.length; i++) {
line1vars[i] = lcd.kegdata[lcd.messages[lcd.currentMessage].line1vars[i]];
}

for (var i=0; i < lcd.messages[lcd.currentMessage].line2vars.length; i++) {
line2vars[i] = lcd.kegdata[lcd.messages[lcd.currentMessage].line2vars[i]];
}

lcd.autoscroll.lines[0] = vsprintf(lcd.messages[lcd.currentMessage].line1, line1vars);
lcd.autoscroll.lines[1] = vsprintf(lcd.messages[lcd.currentMessage].line2, line2vars);
lcd.autoscroll.linepos = [];
lcd.autoscroll.wait = [];
lcd.bgColor(lcd.messages[lcd.currentMessage].color);

// increment next line to display
lcd.currentMessage = (lcd.currentMessage + 1 >= lcd.messages.length) ? 0 : ++lcd.currentMessage;
}
}
});

Expand Down
7 changes: 4 additions & 3 deletions device/components/grove-sound-sensor.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
var GroveSensor = require("./grove-sensor.js");
var DEFAULT_READ_INTERVAL = 1000;

SoundSensor = function(pin) {
GroveSensor.call(this, { pin: pin });
SoundSensor = function(pin, freq) {
GroveSensor.call(this, { pin : pin, freq: freq });
};

SoundSensor.prototype = Object.create(GroveSensor.prototype, {
Expand All @@ -12,7 +13,7 @@ SoundSensor.prototype = Object.create(GroveSensor.prototype, {
value: false
},
readInterval: {
value: 500
value: DEFAULT_READ_INTERVAL
},
read: {
value: function() {
Expand Down
4 changes: 2 additions & 2 deletions device/components/grove-temp-sensor.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
var GroveSensor = require("./grove-sensor.js");

TempSensor = function(pin) {
GroveSensor.call(this, { pin : pin });
TempSensor = function(pin, freq) {
GroveSensor.call(this, { pin : pin, freq: freq });
};

TempSensor.prototype = Object.create(GroveSensor.prototype, {
Expand Down
25 changes: 21 additions & 4 deletions device/components/grove-ultrasonic-ranger.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,26 @@
var GroveSensor = require("./grove-sensor.js");
var five = require("johnny-five");
var DEFAULT_READ_INTERVAL = 1000;

UltrasonicRanger = function(pin) {
GroveSensor.call(this, { pin : pin, type: "digital" });

UltrasonicRanger = function(pin, freq) {
five.Proximity.call(this, {
controller: "HCSR04",
pin: pin,
freq: freq
});
};

UltrasonicRanger.prototype = Object.create(GroveSensor.prototype, {});
UltrasonicRanger.prototype = Object.create(five.Proximity.prototype, {
readInterval: {
value: DEFAULT_READ_INTERVAL
},
read: {
value: function() {
return this.lastProximity;
}
}
});

UltrasonicRanger.prototype.lastProximity = 0;

exports = module.exports = UltrasonicRanger;
96 changes: 57 additions & 39 deletions device/device.json
Original file line number Diff line number Diff line change
@@ -1,40 +1,58 @@
{
"deviceId": "SBS003",
"location": "San Francisco",
"short": "SFO",
"region": "us-east-1",
"intervals": {
"rotateMessages": 10000,
"publish": 1020
},
"topic": "sbs",
"logTopic": "logs",
"certs": {
"privateKey": "/opt/sbs/cert/private.pem.key",
"certificate": "/opt/sbs/cert/certificate.pem.crt",
"caCert": "/opt/sbs/cert/root.pem.crt"
},
"components": {
"leds": {
"blue": 2,
"green": 5,
"red": 6
},
"sensors": {
"Sound": "A0",
"Temperature": "A1",
"Flow": 3,
"Proximity": 4
}
},
"api": {
"endpoint": "<YOUR_API_ENDPOINT>",
"apiKey": "<YOUR_API_KEY>"
},
"messages": [
{"line1":"I :heart: beer!","line2":"How about you?"},
{"line1":"Step right up...","line2":"and grab a beer!"},
{"line1":"What a beautiful","line2":"day for a beer!"},
{"line1":"HEY! YOU!","line2":"Want a beer?"}
]
}
"thingName": "sbs",
"location": "Vancouver",
"short": "YVR",
"region": "us-east-1",
"intervals": {
"rotateMessages": 30000,
"autoScroll": 400,
"topic": 1020,
"shadow": 300000
},
"topicName": "simpleBeerEdisonTopic",
"logTopic": "simpleBeerEdisonTopicLogs",
"certs": {
"privateKey": "/opt/sbs/cert/private.pem.key",
"certificate": "/opt/sbs/cert/certificate.pem.crt",
"caCert": "/opt/sbs/cert/root.pem.crt"
},
"components": {
"leds": {
"blue": 2,
"green": 5,
"red": 6
},
"sensors": {
"Sound": {
"pin": "A0"
},
"Temperature": {
"pin": "A1"
},
"Flow": {
"pin": "A2",
"freq": 1,
"multiplier": 3.2715
},
"Proximity": {
"pin": 4
}
}
},
"messages": [
{
"line1": "Beer: %s, from %s brewery",
"line1vars": ["name", "brewery"],
"line2": "Description: %s",
"line2vars": ["desc"],
"color": "#f442ce"
},
{
"line1": "Beer is at %2.0f%% used.",
"line1vars": ["used"],
"line2": "Only %.2f liters left!",
"line2vars": ["left"],
"color": "#f2a7e2"
}
]
}
Loading