From e08b370aca63e5ecfa0f5f7e6d41918c9013ab71 Mon Sep 17 00:00:00 2001
From: Jake Hartnell
Date: Sat, 22 Oct 2016 15:00:10 -0700
Subject: [PATCH 1/7] Different approach.
---
examples/light.js | 79 +++++++++++
lib/Thing.js | 201 +++++++++++++--------------
test/test-thing2.js | 107 +++++++++++++++
test/thing-test.js | 324 ++++++++++++++++++++++----------------------
4 files changed, 442 insertions(+), 269 deletions(-)
create mode 100644 examples/light.js
create mode 100644 test/test-thing2.js
diff --git a/examples/light.js b/examples/light.js
new file mode 100644
index 0000000..0304771
--- /dev/null
+++ b/examples/light.js
@@ -0,0 +1,79 @@
+// Import the latest build of the Grow.js library
+var Thing = require('../.././dist/Thing.umd.js');
+
+// Declare need variable for example
+var currentLightValue;
+var currentTempValue;
+
+// Create a new light instance. Connects by default to localhost:3000
+var light = new Thing({
+ uuid: '5b7ba90f-ce42-44e4-9ecb-fcb256b89352',
+ token: 'mGQknLsQM4fyeJWYNCPebEqQH3SCxgcP',
+ name: 'Light', // The display name for the thing.
+ desription: 'An LED light with a basic on/off api.',
+
+ // Properties can be updated by the API
+ properties: {
+ state: {
+ type: String,
+ value: 'off'
+ },
+ lightConditions: String
+ },
+
+ // Actions are the API of the thing.
+ actions: {
+ turn_light_on: {
+ name: 'On', // Display name for the action
+ description: 'Turns the light on.', // Optional description
+ schedule: 'at 9:00am', // Optional scheduling using later.js
+ // Is this rule pattern useful?
+ function: function () {
+ // Emit a 'light off' event, set state to on.
+ light.emitEvent('Light on').set('state', 'on');
+ console.log('Light on');
+ }
+ },
+ turn_light_off: {
+ name: 'off',
+ schedule: 'at 8:30pm', // Run this function at 8:30pm
+ function: function () {
+ // Emit a 'light off' event, set the state property to 'off'
+ light.emitEvent('Light off').set('state', 'off');
+ console.log('Light off');
+ }
+ }
+ },
+ events: {
+ temp_data: {
+ name: 'Log temperature data',
+ type: 'temperature',
+ template: 'sensor',
+ schedule: 'every 1 second',
+ function: function () {
+ currentTempValue = Math.random();
+
+ // // Send data to the Grow-IoT app.
+ light.log({
+ type: 'temperature',
+ value: currentTempValue
+ });
+ }
+ },
+ light_data: {
+ name: 'Log light data',
+ type: 'light',
+ template: 'sensor',
+ schedule: 'every 1 second',
+ function: function () {
+ currentLightValue = Math.random();
+
+ // Send data to the Grow-IoT app.
+ light.log({
+ type: 'light',
+ value: currentLightValue
+ });
+ }
+ }
+ }
+});
diff --git a/lib/Thing.js b/lib/Thing.js
index 58bc36c..62f73ed 100644
--- a/lib/Thing.js
+++ b/lib/Thing.js
@@ -18,36 +18,34 @@ class Thing extends EventEmitter {
_.extend(this, config);
}
- if (!_.isUndefined(this.events)) {
- _.each(this.events, (event, key, list) => {
- if (!_.isUndefined(event.on)) {
- this.on(event.on, () => {
- if (!_.isUndefined(event.rule)) {
- if (event.rule.condition() === true) {
- event.rule.consequence();
- }
- } else {
- event.function();
- }
- });
- }
- });
+ // if (!_.isUndefined(this.events)) {
+ // _.each(this.events, (event, key, list) => {
+ // if (!_.isUndefined(event.on)) {
+ // this.on(event.on, () => {
+ // event.function();
+ // });
+ // }
+ // });
+ // }
+
+ if (!_.isUndefined(this.start)) {
+ this.start();
}
- if (!_.isUndefined(this.properties)) {
- for (var property in this.properties) {
- // If the property is a function we initialize it.
- if (typeof this.properties[property] === 'function') {
- // Note this function should return property value.
- this.properties[property] = this.properties[property]()
- }
- }
- }
+
+ // if (!_.isUndefined(this.properties)) {
+ // for (var property in this.properties) {
+ // // If the property is a function we initialize it.
+ // if (typeof this.properties[property] === 'function') {
+ // this.properties[property] = this.properties[property]()
+ // }
+ // }
+ // }
// Callback is optional. May be used for a start function.
- if (!_.isUndefined(callback)) {
- callback();
- }
+ // if (!_.isUndefined(callback)) {
+ // callback();
+ // }
}
/**
@@ -55,44 +53,44 @@ class Thing extends EventEmitter {
* @param {String} ID The key of the action object you want.
* @returns {Object}
*/
- getAction (ID) {
- let action = {};
- _.each(this.actions, (value, key, list) => {
- if (key === ID) {
- return action = value;
- } else if (this.actions[key].id === ID) {
- return action = value;
- }
- });
-
- if (_.isEmpty(action)) {
- return false;
- } else {
- return action;
- }
- }
+ // getAction (ID) {
+ // let action = {};
+ // _.each(this.actions, (value, key, list) => {
+ // if (key === ID) {
+ // return action = value;
+ // } else if (this.actions[key].id === ID) {
+ // return action = value;
+ // }
+ // });
+
+ // if (_.isEmpty(action)) {
+ // return false;
+ // } else {
+ // return action;
+ // }
+ // }
/**
* Get event object by key
* @param {String} ID The key / id of the event object you want.
* @returns {Object}
*/
- getEvent (ID) {
- let event = {}
- _.each(this.events, (value, key, list) => {
- if (key === ID) {
- return event = value;
- } else if (this.events[key].id === ID) {
- return event = value;
- }
- });
-
- if (_.isEmpty(event)) {
- return false;
- } else {
- return event;
- }
- }
+ // getEvent (ID) {
+ // let event = {}
+ // _.each(this.events, (value, key, list) => {
+ // if (key === ID) {
+ // return event = value;
+ // } else if (this.events[key].id === ID) {
+ // return event = value;
+ // }
+ // });
+
+ // if (_.isEmpty(event)) {
+ // return false;
+ // } else {
+ // return event;
+ // }
+ // }
/**
* Update a property based on a component ID.
@@ -100,41 +98,30 @@ class Thing extends EventEmitter {
* @param {String} value The value to update the property to.
* @param {String} key Optional. Use to update the property of an event or action.
*/
- set (property, value, key) {
- if (_.isUndefined(key)) {
- this.properties[property] = value;
- this.emit('property-updated');
- }
- else {
- // what if they both have the same key?
- let action = this.getAction(key);
- let event = this.getEvent(key);
- if (action) {
- action[property] = value;
- } else if (event) {
- event[property] = value;
- }
- this.emit('property-updated');
- }
+ set (key, value) {
+ // if (!_.isUndefined(this.properties[key])) {
+ this.properties[key] = value;
+ this.emit('property-updated', key);
+ // }
+ // else {
+ // // what if they both have the same key?
+ // let action = this.getAction(key);
+ // let event = this.getEvent(key);
+ // if (action) {
+ // action[property] = value;
+ // } else if (event) {
+ // event[property] = value;
+ // }
+ // this.emit('property-updated');
+ // }
}
/* Get a property by key.
* @param {String} property
* @returns {String} key Optional. Use to get an event or action property.
*/
- get (property, key) {
- if (_.isUndefined(key)) {
- return this.properties[property];
- } else {
- let action = this.getAction(key);
- let event = this.getEvent(key);
- if (action) {
- return action[property];
- }
- if (event) {
- return event[property];
- }
- }
+ get (key) {
+ return this.properties[key];
}
/**
@@ -145,28 +132,28 @@ class Thing extends EventEmitter {
*/
call (key, options) {
try {
- let action = this.getAction(key);
- let event = this.getEvent(key);
-
- if (action) {
- if (!_.isUndefined(options)) {
- var output = action.function(options);
- }
- else {
- var output = action.function();
- }
- this.emit(key);
- }
+ // let action = this.getAction(key);
+ // let event = this.getEvent(key);
- else if (event) {
- if (!_.isUndefined(options)) {
- var output = event.function(options);
- }
- else {
- var output = event.function();
- }
- this.emit(key);
+ // if (action) {
+ if (!_.isUndefined(options)) {
+ var output = this[key](options);
+ }
+ else {
+ var output = this[key]();
}
+ this.emit(key);
+ // }
+
+ // else if (event) {
+ // if (!_.isUndefined(options)) {
+ // var output = event.function(options);
+ // }
+ // else {
+ // var output = event.function();
+ // }
+ // this.emit(key);
+ // }
// We return any returns of called functions for testing.
if (!_.isUndefined(output)) {
diff --git a/test/test-thing2.js b/test/test-thing2.js
new file mode 100644
index 0000000..60cb28d
--- /dev/null
+++ b/test/test-thing2.js
@@ -0,0 +1,107 @@
+const Thing = require('../dist/Thing.umd');
+const _ = require('underscore');
+
+global.expect = require('chai').expect;
+
+(function setup () {
+ beforeEach(function() {
+
+ global.thing = {
+ // Meta data
+ uuid: null,
+ token: null,
+ name: 'Dr. Dose', // The display name for the thing.
+ desription: 'Dr. Dose keeps your pH balanced.',
+
+ // Properties can be updated by the API, Metadata cannot.
+ properties: {
+ state: null,
+ duration: 2000,
+ eC_reading: null,
+ pH_reading: null
+ },
+
+ start: function () {
+ // Maybe emit an event instead?
+ return 'Dr. Dose initialized.';
+ },
+
+ acid: function (duration) {
+ return 'acid';
+ },
+
+ base: function (duration) {
+ return 'base';
+ },
+
+ nutrient: function (duration) {
+ return 'nutrient: ' + duration;
+ },
+
+ ec_data: function () {
+ return 'ec_data';
+ },
+
+ ph_data: function () {
+ return 'ph_data';
+ }
+ }
+ });
+
+ afterEach(function() {
+ delete global.thing;
+ });
+})();
+
+
+describe('Thing test', () => {
+ // Do we really need a new thing every time?
+ beforeEach(() => {
+ global.testThing = new Thing(thing);
+ });
+
+ it('should have cloned metadata', () => {
+ expect(testThing.token).to.equal(null);
+ expect(testThing.uuid).to.equal(null);
+ });
+
+ describe('PROPERTIES', () => {
+ it('should get a property', () => {
+ expect(testThing.get('duration')).to.equal(2000);
+ });
+
+ it('should set a property', () => {
+ testThing.set('duration', 3000);
+ expect(testThing.get('duration')).to.equal(3000);
+ });
+
+ it('should emit an event when a property is set', () => {
+ var event = false;
+ testThing.on('property-updated', () => {
+ return event = true;
+ });
+ testThing.set('duration', 5000);
+ expect(testThing.get('duration')).to.equal(5000);
+ expect(event).to.equal(true);
+ });
+ });
+
+ describe('Methods:', () => {
+ it('should be able to call a method.', () => {
+ expect(testThing.call('acid')).to.equal('acid');
+ });
+
+ it('should emit an event when a method is called', () => {
+ var event = false;
+ testThing.on('acid', () => {
+ return event = true;
+ });
+ testThing.call('acid');
+ expect(event).to.equal(true);
+ });
+ });
+
+ afterEach(() => {
+ delete global.testThing;
+ });
+});
diff --git a/test/thing-test.js b/test/thing-test.js
index f74fe44..629a2c1 100644
--- a/test/thing-test.js
+++ b/test/thing-test.js
@@ -1,162 +1,162 @@
-const Thing = require('../dist/Thing.umd');
-const _ = require('underscore');
-
-global.expect = require('chai').expect;
-
-(function setup () {
- beforeEach(function() {
-
- global.thing = {
- name: 'Light', // The display name for the thing.
- id: 'Light',
- username: 'YourUsernameHere', // The username of the account you want this device to be added to.
- properties: { // These can be updated by the API.
- state: 'off',
- lightconditions: function () {
- return 'unset';
- }
- },
- actions: { // a list of action objects with keys
- turn_light_on: {
- name: 'On', // Display name for the action
- description: 'Turns the light on.', // Optional description
- schedule: 'at 9:00am', // Optional scheduling using later.js
- event: 'Light turned on', // Optional event to emit when called.
- function: function () {
- // The implementation of the action.
- return 'Light on.';
- }
- },
- turn_light_off: {
- name: 'off',
- schedule: 'at 8:30pm',
- event: 'Light turned off',
- function: function () {
- return 'Light off.';
- }
- },
- light_data: {
- name: 'Log light data', // Events get a display name like actions
- type: 'light', // Currently need for visualization component... HACK.
- template: 'sensor',
- schedule: 'every 1 second', // Events should have a schedule option that determines how often to check for conditions.
- function: function () {
- return 10;
- }
- }
- },
- events: {
- dark: {
- name: 'It\'s dark.',
- on: 'light_data', // Hook into an action.
- function: function () {
- return;
- }
- },
- light: {
- name: 'It\'s light.',
- on: 'light_data',
- function: function () {
- return;
- }
- }
- }
- }
- });
-
- afterEach(function() {
- delete global.thing;
- });
-})();
-
-
-describe('Thing test', () => {
- beforeEach(() => {
- global.testThing = new Thing(thing);
- });
-
- it('should have cloned metadata', () => {
- expect(testThing.name).to.equal('Light');
- expect(testThing.id).to.equal('Light');
- expect(testThing.username).to.equal('YourUsernameHere');
- });
-
- describe('ACTIONS', () => {
- it('should register actions in the config object', () => {
- expect(_.allKeys(testThing.actions).length).to.equal(3);
- });
-
- it('should return the right action object when given an action id.', () => {
- var action = testThing.getAction('light_data')
- expect(action.name).to.equal('Log light data');
- });
-
- it('should be able to call a registered action.', () => {
- expect(testThing.call('turn_light_on')).to.equal('Light on.');
- });
-
- it('should get an action property', () => {
- expect(testThing.get('name', 'turn_light_on')).to.equal('On');
- });
-
- it('should set an action property', () => {
- testThing.set('name', 'Robert', 'turn_light_on');
- expect(testThing.get('name', 'turn_light_on')).to.equal('Robert');
- });
-
- it('should emit an event when an action is called', () => {
- var event = false;
- testThing.on('turn_light_on', () => {
- return event = true;
- });
- testThing.call('turn_light_on');
- expect(event).to.equal(true);
- });
- });
-
- describe('EVENTS', () => {
- it('should register events in the config object', () => {
- expect(_.allKeys(testThing.events).length).to.equal(2);
- });
-
- it('should get an event property', () => {
- expect(testThing.get('name', 'dark')).to.equal('It\'s dark.');
- });
-
- it('should set an event property', () => {
- testThing.set('name', 'Robert', 'dark');
- expect(testThing.get('name', 'dark')).to.equal('Robert');
- });
-
- it('should return the right event object when given an id.', () => {
- var component = testThing.getEvent('dark');
- expect(component.name).to.equal('It\'s dark.');
- });
- });
-
- describe('PROPERTIES', () => {
- it('should initialize correctly', () => {
- expect(testThing.get('lightconditions')).to.equal('unset');
- });
-
- it('should set a property', () => {
- testThing.set('lightconditions', 'dark');
- expect(testThing.get('lightconditions')).to.equal('dark');
- });
-
- it('should emit an event when a property is set', () => {
- var event = false;
- testThing.on('property-updated', () => {
- return event = true;
- });
- testThing.set('lightconditions', 'light');
- expect(testThing.get('lightconditions')).to.equal('light');
- expect(event).to.equal(true);
- });
-
- });
-
- afterEach(() => {
- delete global.testThing;
- });
-});
+// const Thing = require('../dist/Thing.umd');
+// const _ = require('underscore');
+
+// global.expect = require('chai').expect;
+
+// (function setup () {
+// beforeEach(function() {
+
+// global.thing = {
+// name: 'Light', // The display name for the thing.
+// id: 'Light',
+// username: 'YourUsernameHere', // The username of the account you want this device to be added to.
+// properties: { // These can be updated by the API.
+// state: 'off',
+// lightconditions: function () {
+// return 'unset';
+// }
+// },
+// actions: { // a list of action objects with keys
+// turn_light_on: {
+// name: 'On', // Display name for the action
+// description: 'Turns the light on.', // Optional description
+// schedule: 'at 9:00am', // Optional scheduling using later.js
+// event: 'Light turned on', // Optional event to emit when called.
+// function: function () {
+// // The implementation of the action.
+// return 'Light on.';
+// }
+// },
+// turn_light_off: {
+// name: 'off',
+// schedule: 'at 8:30pm',
+// event: 'Light turned off',
+// function: function () {
+// return 'Light off.';
+// }
+// },
+// light_data: {
+// name: 'Log light data', // Events get a display name like actions
+// type: 'light', // Currently need for visualization component... HACK.
+// template: 'sensor',
+// schedule: 'every 1 second', // Events should have a schedule option that determines how often to check for conditions.
+// function: function () {
+// return 10;
+// }
+// }
+// },
+// events: {
+// dark: {
+// name: 'It\'s dark.',
+// on: 'light_data', // Hook into an action.
+// function: function () {
+// return;
+// }
+// },
+// light: {
+// name: 'It\'s light.',
+// on: 'light_data',
+// function: function () {
+// return;
+// }
+// }
+// }
+// }
+// });
+
+// afterEach(function() {
+// delete global.thing;
+// });
+// })();
+
+
+// describe('Thing test', () => {
+// beforeEach(() => {
+// global.testThing = new Thing(thing);
+// });
+
+// it('should have cloned metadata', () => {
+// expect(testThing.name).to.equal('Light');
+// expect(testThing.id).to.equal('Light');
+// expect(testThing.username).to.equal('YourUsernameHere');
+// });
+
+// describe('ACTIONS', () => {
+// it('should register actions in the config object', () => {
+// expect(_.allKeys(testThing.actions).length).to.equal(3);
+// });
+
+// it('should return the right action object when given an action id.', () => {
+// var action = testThing.getAction('light_data')
+// expect(action.name).to.equal('Log light data');
+// });
+
+// it('should be able to call a registered action.', () => {
+// expect(testThing.call('turn_light_on')).to.equal('Light on.');
+// });
+
+// it('should get an action property', () => {
+// expect(testThing.get('name', 'turn_light_on')).to.equal('On');
+// });
+
+// it('should set an action property', () => {
+// testThing.set('name', 'Robert', 'turn_light_on');
+// expect(testThing.get('name', 'turn_light_on')).to.equal('Robert');
+// });
+
+// it('should emit an event when an action is called', () => {
+// var event = false;
+// testThing.on('turn_light_on', () => {
+// return event = true;
+// });
+// testThing.call('turn_light_on');
+// expect(event).to.equal(true);
+// });
+// });
+
+// describe('EVENTS', () => {
+// it('should register events in the config object', () => {
+// expect(_.allKeys(testThing.events).length).to.equal(2);
+// });
+
+// it('should get an event property', () => {
+// expect(testThing.get('name', 'dark')).to.equal('It\'s dark.');
+// });
+
+// it('should set an event property', () => {
+// testThing.set('name', 'Robert', 'dark');
+// expect(testThing.get('name', 'dark')).to.equal('Robert');
+// });
+
+// it('should return the right event object when given an id.', () => {
+// var component = testThing.getEvent('dark');
+// expect(component.name).to.equal('It\'s dark.');
+// });
+// });
+
+// describe('PROPERTIES', () => {
+// it('should initialize correctly', () => {
+// expect(testThing.get('lightconditions')).to.equal('unset');
+// });
+
+// it('should set a property', () => {
+// testThing.set('lightconditions', 'dark');
+// expect(testThing.get('lightconditions')).to.equal('dark');
+// });
+
+// it('should emit an event when a property is set', () => {
+// var event = false;
+// testThing.on('property-updated', () => {
+// return event = true;
+// });
+// testThing.set('lightconditions', 'light');
+// expect(testThing.get('lightconditions')).to.equal('light');
+// expect(event).to.equal(true);
+// });
+
+// });
+
+// afterEach(() => {
+// delete global.testThing;
+// });
+// });
From eacbed5708415d21422fc9ea5bcc8ee45037c971 Mon Sep 17 00:00:00 2001
From: Jake Hartnell
Date: Sat, 22 Oct 2016 15:02:27 -0700
Subject: [PATCH 2/7] Clean up.
---
lib/Thing.js | 99 +---------------------------------------------------
1 file changed, 1 insertion(+), 98 deletions(-)
diff --git a/lib/Thing.js b/lib/Thing.js
index 62f73ed..2f066fb 100644
--- a/lib/Thing.js
+++ b/lib/Thing.js
@@ -18,80 +18,11 @@ class Thing extends EventEmitter {
_.extend(this, config);
}
- // if (!_.isUndefined(this.events)) {
- // _.each(this.events, (event, key, list) => {
- // if (!_.isUndefined(event.on)) {
- // this.on(event.on, () => {
- // event.function();
- // });
- // }
- // });
- // }
-
if (!_.isUndefined(this.start)) {
this.start();
}
-
-
- // if (!_.isUndefined(this.properties)) {
- // for (var property in this.properties) {
- // // If the property is a function we initialize it.
- // if (typeof this.properties[property] === 'function') {
- // this.properties[property] = this.properties[property]()
- // }
- // }
- // }
-
- // Callback is optional. May be used for a start function.
- // if (!_.isUndefined(callback)) {
- // callback();
- // }
}
- /**
- * Get an action object by key
- * @param {String} ID The key of the action object you want.
- * @returns {Object}
- */
- // getAction (ID) {
- // let action = {};
- // _.each(this.actions, (value, key, list) => {
- // if (key === ID) {
- // return action = value;
- // } else if (this.actions[key].id === ID) {
- // return action = value;
- // }
- // });
-
- // if (_.isEmpty(action)) {
- // return false;
- // } else {
- // return action;
- // }
- // }
-
- /**
- * Get event object by key
- * @param {String} ID The key / id of the event object you want.
- * @returns {Object}
- */
- // getEvent (ID) {
- // let event = {}
- // _.each(this.events, (value, key, list) => {
- // if (key === ID) {
- // return event = value;
- // } else if (this.events[key].id === ID) {
- // return event = value;
- // }
- // });
-
- // if (_.isEmpty(event)) {
- // return false;
- // } else {
- // return event;
- // }
- // }
-
/**
* Update a property based on a component ID.
* @param {String} property The property of the component to be update.
@@ -99,21 +30,8 @@ class Thing extends EventEmitter {
* @param {String} key Optional. Use to update the property of an event or action.
*/
set (key, value) {
- // if (!_.isUndefined(this.properties[key])) {
this.properties[key] = value;
this.emit('property-updated', key);
- // }
- // else {
- // // what if they both have the same key?
- // let action = this.getAction(key);
- // let event = this.getEvent(key);
- // if (action) {
- // action[property] = value;
- // } else if (event) {
- // event[property] = value;
- // }
- // this.emit('property-updated');
- // }
}
/* Get a property by key.
@@ -132,10 +50,6 @@ class Thing extends EventEmitter {
*/
call (key, options) {
try {
- // let action = this.getAction(key);
- // let event = this.getEvent(key);
-
- // if (action) {
if (!_.isUndefined(options)) {
var output = this[key](options);
}
@@ -143,19 +57,8 @@ class Thing extends EventEmitter {
var output = this[key]();
}
this.emit(key);
- // }
-
- // else if (event) {
- // if (!_.isUndefined(options)) {
- // var output = event.function(options);
- // }
- // else {
- // var output = event.function();
- // }
- // this.emit(key);
- // }
- // We return any returns of called functions for testing.
+ // We return any returns of called functions.
if (!_.isUndefined(output)) {
return output;
}
From 48ef771274d257cabd1cea305a2685afe39e85f8 Mon Sep 17 00:00:00 2001
From: Jake Hartnell
Date: Sat, 22 Oct 2016 15:40:18 -0700
Subject: [PATCH 3/7] v0.2.8
---
package.json | 2 +-
test/{test-thing2.js => test-thing.js} | 0
test/thing-test.js | 162 -------------------------
3 files changed, 1 insertion(+), 163 deletions(-)
rename test/{test-thing2.js => test-thing.js} (100%)
delete mode 100644 test/thing-test.js
diff --git a/package.json b/package.json
index cf39f99..8a93c02 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "Thing.js",
- "version": "0.2.7",
+ "version": "0.2.8",
"description": "Create thing objects with properties, actions, and events. Use for IoT devices or even living things like plants.",
"main": "dist/Thing.umd.js",
"jsnext:main": "dist/Thing.es6.js",
diff --git a/test/test-thing2.js b/test/test-thing.js
similarity index 100%
rename from test/test-thing2.js
rename to test/test-thing.js
diff --git a/test/thing-test.js b/test/thing-test.js
deleted file mode 100644
index 629a2c1..0000000
--- a/test/thing-test.js
+++ /dev/null
@@ -1,162 +0,0 @@
-// const Thing = require('../dist/Thing.umd');
-// const _ = require('underscore');
-
-// global.expect = require('chai').expect;
-
-// (function setup () {
-// beforeEach(function() {
-
-// global.thing = {
-// name: 'Light', // The display name for the thing.
-// id: 'Light',
-// username: 'YourUsernameHere', // The username of the account you want this device to be added to.
-// properties: { // These can be updated by the API.
-// state: 'off',
-// lightconditions: function () {
-// return 'unset';
-// }
-// },
-// actions: { // a list of action objects with keys
-// turn_light_on: {
-// name: 'On', // Display name for the action
-// description: 'Turns the light on.', // Optional description
-// schedule: 'at 9:00am', // Optional scheduling using later.js
-// event: 'Light turned on', // Optional event to emit when called.
-// function: function () {
-// // The implementation of the action.
-// return 'Light on.';
-// }
-// },
-// turn_light_off: {
-// name: 'off',
-// schedule: 'at 8:30pm',
-// event: 'Light turned off',
-// function: function () {
-// return 'Light off.';
-// }
-// },
-// light_data: {
-// name: 'Log light data', // Events get a display name like actions
-// type: 'light', // Currently need for visualization component... HACK.
-// template: 'sensor',
-// schedule: 'every 1 second', // Events should have a schedule option that determines how often to check for conditions.
-// function: function () {
-// return 10;
-// }
-// }
-// },
-// events: {
-// dark: {
-// name: 'It\'s dark.',
-// on: 'light_data', // Hook into an action.
-// function: function () {
-// return;
-// }
-// },
-// light: {
-// name: 'It\'s light.',
-// on: 'light_data',
-// function: function () {
-// return;
-// }
-// }
-// }
-// }
-// });
-
-// afterEach(function() {
-// delete global.thing;
-// });
-// })();
-
-
-// describe('Thing test', () => {
-// beforeEach(() => {
-// global.testThing = new Thing(thing);
-// });
-
-// it('should have cloned metadata', () => {
-// expect(testThing.name).to.equal('Light');
-// expect(testThing.id).to.equal('Light');
-// expect(testThing.username).to.equal('YourUsernameHere');
-// });
-
-// describe('ACTIONS', () => {
-// it('should register actions in the config object', () => {
-// expect(_.allKeys(testThing.actions).length).to.equal(3);
-// });
-
-// it('should return the right action object when given an action id.', () => {
-// var action = testThing.getAction('light_data')
-// expect(action.name).to.equal('Log light data');
-// });
-
-// it('should be able to call a registered action.', () => {
-// expect(testThing.call('turn_light_on')).to.equal('Light on.');
-// });
-
-// it('should get an action property', () => {
-// expect(testThing.get('name', 'turn_light_on')).to.equal('On');
-// });
-
-// it('should set an action property', () => {
-// testThing.set('name', 'Robert', 'turn_light_on');
-// expect(testThing.get('name', 'turn_light_on')).to.equal('Robert');
-// });
-
-// it('should emit an event when an action is called', () => {
-// var event = false;
-// testThing.on('turn_light_on', () => {
-// return event = true;
-// });
-// testThing.call('turn_light_on');
-// expect(event).to.equal(true);
-// });
-// });
-
-// describe('EVENTS', () => {
-// it('should register events in the config object', () => {
-// expect(_.allKeys(testThing.events).length).to.equal(2);
-// });
-
-// it('should get an event property', () => {
-// expect(testThing.get('name', 'dark')).to.equal('It\'s dark.');
-// });
-
-// it('should set an event property', () => {
-// testThing.set('name', 'Robert', 'dark');
-// expect(testThing.get('name', 'dark')).to.equal('Robert');
-// });
-
-// it('should return the right event object when given an id.', () => {
-// var component = testThing.getEvent('dark');
-// expect(component.name).to.equal('It\'s dark.');
-// });
-// });
-
-// describe('PROPERTIES', () => {
-// it('should initialize correctly', () => {
-// expect(testThing.get('lightconditions')).to.equal('unset');
-// });
-
-// it('should set a property', () => {
-// testThing.set('lightconditions', 'dark');
-// expect(testThing.get('lightconditions')).to.equal('dark');
-// });
-
-// it('should emit an event when a property is set', () => {
-// var event = false;
-// testThing.on('property-updated', () => {
-// return event = true;
-// });
-// testThing.set('lightconditions', 'light');
-// expect(testThing.get('lightconditions')).to.equal('light');
-// expect(event).to.equal(true);
-// });
-
-// });
-
-// afterEach(() => {
-// delete global.testThing;
-// });
-// });
From 4d521f997dc37479b313a9b12715410f6e47be8d Mon Sep 17 00:00:00 2001
From: Jake Hartnell
Date: Sat, 22 Oct 2016 15:55:58 -0700
Subject: [PATCH 4/7] Update readme.
---
README.md | 90 +++++++++++++++----------------------------------------
1 file changed, 24 insertions(+), 66 deletions(-)
diff --git a/README.md b/README.md
index d921aa7..39ec547 100644
--- a/README.md
+++ b/README.md
@@ -1,101 +1,59 @@
# Thing.js
-Thing.js is meant to be an extremely light weight IoT-framework. Loosely inspired by [W3C web of things framework](https://github.com/w3c/web-of-things-framework), a thing is an object that has:
+Thing.js is meant to be an *extremely light weight* IoT-framework.
* Metadata
* Properties
-* Actions
-* Events
+* Methods
-Thing.js exports a single class 'Thing,' which is an extension of the [Node.js EventEmitter Class](https://nodejs.org/api/events.html), and basic methods for:
+Thing.js exports a single class 'Thing,' which is an extension of the [Node.js EventEmitter Class](https://nodejs.org/api/events.html) and basic methods for:
* Updating properties
-* Calling actions
-* Emiting events
-* Setting up event listeners
+* Calling methods
+* Emiting events for either of the above.
[Full documentation available here](http://commongarden.github.io/Thing.js/docs/Thing.js.html).
-For example of how this can be used in an IoT stack, checkout [Grow.js](https://github.com/CommonGarden/Grow.js) and [Grow-IoT](https://github.com/CommonGarden/Grow-IoT).
+For example of how this can be used in an IoT stack, checkout [Grow.js](https://github.com/CommonGarden/Grow.js) which is used to connect devices (or purely software things) to a [Grow-IoT](https://github.com/CommonGarden/Grow-IoT) instance.
## Install
```bash
npm install Thing.js
```
-### Example
+### Usage
```javascript
-var Thing = require('Thing.js');
+const Thing = require('Thing.js');
-var Light = new Thing({
+const Light = new Thing({
name: 'Light',
desription: 'An LED light with a basic on/off api.',
username: 'jakehart',
+ // These are setable and getable by the api.
properties: {
- state: 'off',
- lightconditions: function () {
- // Properties can be updated by the API.
- // Note: property functions should return a value.
- // When using actual hardware you might use this function to get the
- // state of a pin.
- return null;
- }
+ state: null,
},
- actions: {
- turn_light_on: {
- name: 'On', // Display name for the action
- description: 'Turns the light on.', // Optional description
- function: function () {
- // The implementation of the action.
- console.log('light on');
- Light.set('state', 'on');
- }
- },
- turn_light_off: {
- name: 'off',
- function: function () {
- console.log('light off');
- Light.set('state', 'off');
- }
- },
- light_data: {
- name: 'Log light data',
- type: 'light',
- template: 'sensor',
- function: function () {
- console.log("Log light data.")
- }
- }
+ start: function () {
+ console.log('Thing initialized, this code runs first');
},
- events: {
- check_light_data: {
- name: 'Check light data',
- on: 'turn_light_on', // Adds Listener for action event.
- function: function () {
- console.log('this event listener is called when the light is turned on.');
- }
- }
- }
-},
-function start () {
- // Optional callback function.
- return;
+ turn_light_on: function () {
+ console.log('light on');
+ Light.set('state', 'on');
+ },
+ turn_light_off: function () {
+ console.log('light off');
+ Light.set('state', 'off');
+ }
});
-console.log(Light.get(state));
-// logs 'off'
+Light.on('turn_light_on', function() {
+ console.log('Light turned on.')
+});
Light.call('turn_light_on');
-// logs 'Light on.'
-// logs 'this event listener is called when the light is turned on.'
-
-console.log(Light.get(state));
-// logs 'on'
```
-Please open issues or PRs with thoughts || suggestions || proposals.
-
# Developing
Code is written in ES6, and compiled using [rollup](https://github.com/rollup/rollup). [Full documentation is available here](http://commongarden.github.io/Thing.js/docs/Thing.js.html).
From ac53a92409680a9628f91c0f02704ecbfa0b5165 Mon Sep 17 00:00:00 2001
From: Jake Hartnell
Date: Sat, 22 Oct 2016 18:43:24 -0700
Subject: [PATCH 5/7] Update readme.
---
README.md | 6 ------
1 file changed, 6 deletions(-)
diff --git a/README.md b/README.md
index 39ec547..25e9aa8 100644
--- a/README.md
+++ b/README.md
@@ -1,11 +1,5 @@
# Thing.js
-Thing.js is meant to be an *extremely light weight* IoT-framework.
-
-* Metadata
-* Properties
-* Methods
-
Thing.js exports a single class 'Thing,' which is an extension of the [Node.js EventEmitter Class](https://nodejs.org/api/events.html) and basic methods for:
* Updating properties
From ee5be7710d3b2a1af93c00d076d5a77bc7f84f48 Mon Sep 17 00:00:00 2001
From: Jake Hartnell
Date: Sat, 22 Oct 2016 18:44:52 -0700
Subject: [PATCH 6/7] Update docs.
---
docs/Thing.js.html | 176 ++++-----------------------------------------
docs/index.html | 94 ++++++------------------
2 files changed, 35 insertions(+), 235 deletions(-)
diff --git a/docs/Thing.js.html b/docs/Thing.js.html
index cc6878e..6248c67 100644
--- a/docs/Thing.js.html
+++ b/docs/Thing.js.html
@@ -24,10 +24,6 @@ Create thing objects with properties, actions, and e
- Thing
- - getAction
-
- - getEvent
-
- set
- get
@@ -82,117 +78,10 @@
_.extend(this, config);
}
- if (!_.isUndefined(this.events)) {
- _.each(this.events, (event, key, list) => {
- if (!_.isUndefined(event.on)) {
- this.on(event.on, () => {
- if (!_.isUndefined(event.rule)) {
- if (event.rule.condition() === true) {
- event.rule.consequence();
- }
- } else {
- event.function();
- }
- });
- }
- });
- }
-
- if (!_.isUndefined(this.properties)) {
- for (var property in this.properties) {
- // If the property is a function we initialize it.
- if (typeof this.properties[property] === 'function') {
- // Note this function should return property value.
- this.properties[property] = this.properties[property]()
- }
- }
- }
-
- // Callback is optional. May be used for a start function.
- if (!_.isUndefined(callback)) {
- callback();
+ if (!_.isUndefined(this.start)) {
+ this.start();
}
}
-
-
getAction
-
-
-
method
Thing.prototype.getAction()
-
-
-
-
-
- Option name |
- Type |
- Description |
-
-
-
-
- ID |
- String |
- The key of the action object you want. |
-
-
-
- Get an action object by key
- getAction (ID) {
- let action = {};
- _.each(this.actions, (value, key, list) => {
- if (key === ID) {
- return action = value;
- } else if (this.actions[key].id === ID) {
- return action = value;
- }
- });
-
- if (_.isEmpty(action)) {
- return false;
- } else {
- return action;
- }
-}
-
- getEvent
-
-
-
method
Thing.prototype.getEvent()
-
-
-
-
-
- Option name |
- Type |
- Description |
-
-
-
-
- ID |
- String |
- The key / id of the event object you want. |
-
-
-
-
- getEvent (ID) {
- let event = {}
- _.each(this.events, (value, key, list) => {
- if (key === ID) {
- return event = value;
- } else if (this.events[key].id === ID) {
- return event = value;
- }
- });
-
- if (_.isEmpty(event)) {
- return false;
- } else {
- return event;
- }
-}
set
@@ -227,22 +116,9 @@
Update a property based on a component ID.
- set (property, value, key) {
- if (_.isUndefined(key)) {
- this.properties[property] = value;
- this.emit('property-updated');
- }
- else {
- // what if they both have the same key?
- let action = this.getAction(key);
- let event = this.getEvent(key);
- if (action) {
- action[property] = value;
- } else if (event) {
- event[property] = value;
- }
- this.emit('property-updated');
- }
+ set (key, value) {
+ this.properties[key] = value;
+ this.emit('property-updated', key);
}
get
@@ -268,19 +144,8 @@
- get (property, key) {
- if (_.isUndefined(key)) {
- return this.properties[property];
- } else {
- let action = this.getAction(key);
- let event = this.getEvent(key);
- if (action) {
- return action[property];
- }
- if (event) {
- return event[property];
- }
- }
+ get (key) {
+ return this.properties[key];
}
call
@@ -313,30 +178,15 @@
Calls a registered action or event function, emits event if the the action has an 'event'
property defined.
call (key, options) {
try {
- let action = this.getAction(key);
- let event = this.getEvent(key);
-
- if (action) {
- if (!_.isUndefined(options)) {
- var output = action.function(options);
- }
- else {
- var output = action.function();
- }
- this.emit(key);
+ if (!_.isUndefined(options)) {
+ var output = this[key](options);
}
-
- else if (event) {
- if (!_.isUndefined(options)) {
- var output = event.function(options);
- }
- else {
- var output = event.function();
- }
- this.emit(key);
+ else {
+ var output = this[key]();
}
+ this.emit(key);
- // We return any returns of called functions for testing.
+ // We return any returns of called functions.
if (!_.isUndefined(output)) {
return output;
}
diff --git a/docs/index.html b/docs/index.html
index 8662df4..7cc3105 100644
--- a/docs/index.html
+++ b/docs/index.html
@@ -27,98 +27,48 @@ Create thing objects with properties, actions, and e
Thing.js
-Thing.js is meant to be an extremely light weight IoT-framework. Loosely inspired by W3C web of things framework, a thing is an object that has:
-
-- Metadata
-- Properties
-- Actions
-- Events
-
-Thing.js exports a single class 'Thing,' which is an extension of the Node.js EventEmitter Class, and basic methods for:
+Thing.js exports a single class 'Thing,' which is an extension of the Node.js EventEmitter Class and basic methods for:
- Updating properties
-- Calling actions
-- Emiting events
-- Setting up event listeners
+- Calling methods
+- Emiting events for either of the above.
Full documentation available here.
-For example of how this can be used in an IoT stack, checkout Grow.js and Grow-IoT.
+For example of how this can be used in an IoT stack, checkout Grow.js which is used to connect devices (or purely software things) to a Grow-IoT instance.
Install
npm install Thing.js
-Example
-var Thing = require('Thing.js');
+Usage
+const Thing = require('Thing.js');
-var Light = new Thing({
+const Light = new Thing({
name: 'Light',
desription: 'An LED light with a basic on/off api.',
username: 'jakehart',
+ // These are setable and getable by the api.
properties: {
- state: 'off',
- lightconditions: function () {
- // Properties can be updated by the API.
- // Note: property functions should return a value.
- // When using actual hardware you might use this function to get the
- // state of a pin.
- return null;
- }
+ state: null,
+ },
+ start: function () {
+ console.log('Thing initialized, this code runs first');
},
- actions: {
- turn_light_on: {
- name: 'On', // Display name for the action
- description: 'Turns the light on.', // Optional description
- schedule: 'at 9:00am', // Optional scheduling using later.js
- function: function () {
- // The implementation of the action.
- console.log('light on');
- Light.set('state', 'on');
- }
- },
- turn_light_off: {
- name: 'off',
- schedule: 'at 8:30pm',
- function: function () {
- console.log('light off');
- Light.set('state', 'off');
- }
- },
- light_data: {
- name: 'Log light data',
- type: 'light',
- template: 'sensor',
- schedule: 'every 1 second',
- function: function () {
- console.log("Log light data.")
- }
- }
+ turn_light_on: function () {
+ console.log('light on');
+ Light.set('state', 'on');
},
- events: {
- check_light_data: {
- name: 'Check light data',
- on: 'turn_light_on', // Adds Listener for action event.
- function: function () {
- console.log('this event listener is called when the light is turned on.');
- }
- }
- }
-},
-function start () {
- // Optional callback function.
- return;
+ turn_light_off: function () {
+ console.log('light off');
+ Light.set('state', 'off');
+ }
});
-console.log(Light.get(state));
-// logs 'off'
+Light.on('turn_light_on', function() {
+ console.log('Light turned on.')
+});
Light.call('turn_light_on');
-// logs 'Light on.'
-// logs 'this event listener is called when the light is turned on.'
-
-console.log(Light.get(state));
-// logs 'on'
-Please open issues or PRs with thoughts || suggestions || proposals.
Developing
Code is written in ES6, and compiled using rollup. Full documentation is available here.
npm run build
builds the library.
From d5fb2734cb5871097b34556dc378439203211e89 Mon Sep 17 00:00:00 2001
From: Jake Hartnell
Date: Sat, 10 Dec 2016 13:49:22 -0800
Subject: [PATCH 7/7] v0.3
---
docs/Thing.js.html | 5 +--
examples/light.js | 79 ----------------------------------------------
lib/Thing.js | 5 +--
package.json | 2 +-
4 files changed, 7 insertions(+), 84 deletions(-)
delete mode 100644 examples/light.js
diff --git a/docs/Thing.js.html b/docs/Thing.js.html
index 6248c67..e435f25 100644
--- a/docs/Thing.js.html
+++ b/docs/Thing.js.html
@@ -78,6 +78,7 @@
_.extend(this, config);
}
+ // What would be other useful default methods?
if (!_.isUndefined(this.start)) {
this.start();
}
@@ -175,7 +176,7 @@
- Calls a registered action or event function, emits event if the the action has an 'event'
property defined.
+ Calls a method, emits event
property defined.
call (key, options) {
try {
if (!_.isUndefined(options)) {
@@ -184,7 +185,7 @@
else {
var output = this[key]();
}
- this.emit(key);
+ this.emit(key, options);
// We return any returns of called functions.
if (!_.isUndefined(output)) {
diff --git a/examples/light.js b/examples/light.js
deleted file mode 100644
index 0304771..0000000
--- a/examples/light.js
+++ /dev/null
@@ -1,79 +0,0 @@
-// Import the latest build of the Grow.js library
-var Thing = require('../.././dist/Thing.umd.js');
-
-// Declare need variable for example
-var currentLightValue;
-var currentTempValue;
-
-// Create a new light instance. Connects by default to localhost:3000
-var light = new Thing({
- uuid: '5b7ba90f-ce42-44e4-9ecb-fcb256b89352',
- token: 'mGQknLsQM4fyeJWYNCPebEqQH3SCxgcP',
- name: 'Light', // The display name for the thing.
- desription: 'An LED light with a basic on/off api.',
-
- // Properties can be updated by the API
- properties: {
- state: {
- type: String,
- value: 'off'
- },
- lightConditions: String
- },
-
- // Actions are the API of the thing.
- actions: {
- turn_light_on: {
- name: 'On', // Display name for the action
- description: 'Turns the light on.', // Optional description
- schedule: 'at 9:00am', // Optional scheduling using later.js
- // Is this rule pattern useful?
- function: function () {
- // Emit a 'light off' event, set state to on.
- light.emitEvent('Light on').set('state', 'on');
- console.log('Light on');
- }
- },
- turn_light_off: {
- name: 'off',
- schedule: 'at 8:30pm', // Run this function at 8:30pm
- function: function () {
- // Emit a 'light off' event, set the state property to 'off'
- light.emitEvent('Light off').set('state', 'off');
- console.log('Light off');
- }
- }
- },
- events: {
- temp_data: {
- name: 'Log temperature data',
- type: 'temperature',
- template: 'sensor',
- schedule: 'every 1 second',
- function: function () {
- currentTempValue = Math.random();
-
- // // Send data to the Grow-IoT app.
- light.log({
- type: 'temperature',
- value: currentTempValue
- });
- }
- },
- light_data: {
- name: 'Log light data',
- type: 'light',
- template: 'sensor',
- schedule: 'every 1 second',
- function: function () {
- currentLightValue = Math.random();
-
- // Send data to the Grow-IoT app.
- light.log({
- type: 'light',
- value: currentLightValue
- });
- }
- }
- }
-});
diff --git a/lib/Thing.js b/lib/Thing.js
index 2f066fb..00b1f7b 100644
--- a/lib/Thing.js
+++ b/lib/Thing.js
@@ -18,6 +18,7 @@ class Thing extends EventEmitter {
_.extend(this, config);
}
+ // What would be other useful default methods?
if (!_.isUndefined(this.start)) {
this.start();
}
@@ -43,7 +44,7 @@ class Thing extends EventEmitter {
}
/**
- * Calls a registered action or event function, emits event if the the action has an 'event'
+ * Calls a method, emits event
* property defined.
* @param {String} key The id of the action / event to call.
* @param {Object} options Optional, options to call with the function.
@@ -56,7 +57,7 @@ class Thing extends EventEmitter {
else {
var output = this[key]();
}
- this.emit(key);
+ this.emit(key, options);
// We return any returns of called functions.
if (!_.isUndefined(output)) {
diff --git a/package.json b/package.json
index 8a93c02..c339d3d 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "Thing.js",
- "version": "0.2.8",
+ "version": "0.3.0",
"description": "Create thing objects with properties, actions, and events. Use for IoT devices or even living things like plants.",
"main": "dist/Thing.umd.js",
"jsnext:main": "dist/Thing.es6.js",