diff --git a/README.md b/README.md index 77e29f4..91adee3 100644 --- a/README.md +++ b/README.md @@ -1,62 +1,182 @@ -# Example code for mist-api on node.js +# Trying out Mist and Wish on Node.js ## Prerequisites -If you are running on Linux x64 or OSX x64 everything should work out of the box according to the instructions below. Windows is not supported yet. +When running Linux x64 or macOS x64 everything should work swimmingly if you follow the instructions below. Windows isn't supported (yet). -Download and install node.js v6.x: https://nodejs.org/dist/latest-v6.x/. You may use Node Version Manager `nvm` (https://github.com/creationix/nvm). +Install: -You will need to have an appropriate wish-core (the peer-to-peer identity based communication layer mist is based on). The source is available at: https://github.com/ControlThings/wish-c99. +1. [Node.js v6](https://nodejs.org/dist/latest-v6.x/). Note that v6.x is _required_. You can use [nvm](https://github.com/creationix/nvm) to run multiple Node versions on the same computer. -Install command line tools for Mist and Wish: +2. *Wish*, the p2p communication layer Mist is using. Download the [Wish binaries](https://www.controlthings.fi/dev/) for Linux/macOS, or build it from [the Wish source code](https://github.com/ControlThings/wish-c99). Copy the `wish-core` binary into the examples root folder. + +3. Install Mist and Wish command line tools for further testing and tweaking (optional): + +```sh +$ npm install -g mist-cli@latest wish-cli@latest +``` + +## Me and Marielle +In this example we'll create two entities (or _things_) and do our best to make them communicate with each other. + +1. **Marielle** (```marielle/```) is a person looking for friends and reacting whenever someone is smiling or frowning at her. +2. **Me** (```me/```) is _just me_, a simple app for my own interactions with Marielle. + +So here we go! + +To lessen the confusion, it might be smart to use two seperate terminal windows (one for each entity), and to further create two tabs within each terminal (one for the Wish server, one for running the Node.js app). + +But, first, in the examples root folder, run: ```sh -npm install -g mist-cli@latest wish-cli@latest +$ npm install ``` -Create an identity. +### Marielle Terminal - Wish Tab + +Assuming you have the Wish binary installed in the root folder and named ```wish-core```: ```sh -wish-cli -identity.create('Demo Identity') +$ chmod a+x wish-core +$ cd marielle +$ cp ../wish-core . +$ ./wish-core -a 9095 -p 37300 ``` -In the examples root directory run: +**NOTE**: The cores create their own working files/databases, so we're copying each `wish-core` into its entity's folder to prevent them from overwriting each other's files. + +- *-a* specifies which port Wish will use to listen for app communication. Marielle will talk to Wish over this port. + +- *-p* is the port used for global communication with other Wish cores. + +### Marielle Terminal - Application Tab ```sh -npm install +$ cd marielle +$ node marielle.js +``` + +Marielle ensures she has an identity (private and public key) and boots up. If everything is ok, she says: + +``` +Hello, world. I am Marielle. ``` -## Running examples +### Me Terminal - Wish Tab -### Switch +```sh +$ cd me +$ cp ../wish-core . +$ ./wish-core -a 9094 -p 37200 +``` +_Note_ that the ports are different. When we are running two cores on the same computer, they have to run on different ports. -A simplistic switch implementation. +### Me Terminal - Application Tab ```sh -node switch/run.js +$ cd me +$ node me.js +``` + +Running _me_ without arguments will show the usage instructions: + +``` +usage: node me.js [who | hello | smile | frown] + +who List who is present +hello Become friends with everyone +smile Smile broadly! +frown Frown angrily ``` -### Parking +- *who* lists all the entities that are present on the local broadcast network. If both entities are running, you should se yourself and Marielle. + +- *hello* sends friend requests to all other entities on the local network. Marielle is listening for these and will automatically become friends with anyone interested (check for this happening in the Marielle application tab). + +- *smile* sends a smile to all your friends. Remember to say *hello* first, otherwise you won't have any friends. + +- *frown* sends an angry smile to all our friends. + +### Example Output -A parking service. +Show a list of anyone present. ```sh -node parking/run.js +$ node me.js who +I'm here! +Marielle is here. ``` -## Accessing the examples from CLI +Say hello (make a friend request). ```sh -# run the command line tool -mist-cli -# shows help -help() -# shows list of peers available -list() -# show model -mist.control.model(peers[x]) -# write to relay endpoint of switch -mist.control.write(peers[x], 'relay', true) +$ node me.js hello +Saying hello to Marielle + +On Marielle's terminal (with Marielle running): +I got a cool friend! +``` + +Try who again. + +``` +$ node me.js who +I'm here! +Your friend Marielle is here. +``` + +Smile to Marielle. + +```sh +$ node me.js smile +:) + +On Marielle's terminal: +Oh! That makes me happy! +``` + +(The smiley above in the _me_ terminal is Marielle's return value.) + +## Long Distance Relationship + +Once the friend connection has been made using the local broadcast network, you can freely move yourself or Marielle elsewhere. + +As long as both entities have working internet connections, they will be able to communicate with each other securely using built-in relay connectivity. + +## Further Reading + +Check out the READMEs in the subfolders for more information about the actual code. + +## The CLIs + +If you installed the optional command line tools, you can interact with the Wish and Mist APIs without using Node.js. *Note* that you have to set the core port number using an environment variable. + +Show the internal help and list all known identities: + +```sh +$ export CORE=9094 +$ wish-cli +wish> help() +... +wish> identity.list() +... +``` + +Show the internal help, list all peers (friends) and smile to Marielle, who happens to be peers[0]: + +```sh +$ export CORE=9094 +$ mist-cli +mist> help() +... +mist> list() +Known peers: + peers[0]: Marielle (Marielle) +mist> mist.control.invoke(peers[0], "smile") +reqId: 7 +mist> +':)' +mist> + ``` diff --git a/chat/beacon.js b/chat/beacon.js deleted file mode 100644 index f81752a..0000000 --- a/chat/beacon.js +++ /dev/null @@ -1,138 +0,0 @@ -var MistNode = require('mist-api').MistNode; - -var cls = 'fi.controlthings.chat'; - -function Beacon() { - var self = this; - this.node = new MistNode('RandomBeacon'); - this.peers = {}; - this.beaconEnabled = true; - this.peerCount = 0; - this.messageCountOld = 0; - this.messageCount = 0; - this.messageCountPerSecond = 0; - - self.node.addEndpoint('mist.name', { type: 'string', read: (args, peer, cb) => { cb(null, 'RandomBeacon'); } }); - self.node.addEndpoint('mist.class', { type: 'string', read: (args, peer, cb) => { cb(null, cls); } }); - - self.node.addEndpoint('message', { - invoke: (args, peer, cb) => { - console.log('Received message:', args); - self.node.wish.request('identity.get', [peer.ruid], (err, data) => { - cb(null, 'You are known to me as '+data.alias); - }); - } - }); - - self.node.addEndpoint('beaconEnabled', { - type: 'bool', - read: (args, peer, cb) => { cb(null, self.beaconEnabled); }, - write: (value, peer, cb) => { - self.beaconEnabled = value; - cb(); - self.node.changed('beaconEnabled'); - - // if set to true, start sending beacons to online peers - if(value) { - for(var i in self.peers) { - self.startBeacon(self.peers[i].peer); - } - } - } - }); - - self.node.addEndpoint('peerCount', { - type: 'int', - read: (args, peer, cb) => { cb(null, self.peerCount); } - }); - - self.node.addEndpoint('messageCount', { type: 'int', read: (args, peer, cb) => { cb(null, self.messageCount); } }); - self.node.addEndpoint('messageCountPerSecond', { type: 'int', read: (args, peer, cb) => { cb(null, self.messageCountPerSecond); } }); - - self.node.on('online', (peer) => { - self.node.request(peer, 'control.read', ['mist.class'], (err, type) => { - if (type === cls) { - self.node.wish.request('identity.get', [peer.luid], (err, data1) => { - self.node.wish.request('identity.get', [peer.ruid], (err, data2) => { - //console.log('peer:alias', data1.alias, data2.alias); - self.node.request(peer, 'control.read', ['mist.name'], (err, name) => { - //console.log('peer:alias', data1.alias, data2.alias, data); - console.log('peer:alias', data1.alias, data2.alias, name, type); - - // start "spamming" - self.startBeacon(peer); - }); - }); - }); - } - }); - }); - - self.node.on('offline', (peer) => { - // stop "spamming" - self.stopBeacon(peer); - }); - - setInterval(() => { - if (self.messageCount !== self.messageCountOld) { - self.messageCountPerSecond = self.messageCount - self.messageCountOld; - self.messageCountOld = self.messageCount; - self.node.changed('messageCount'); - self.node.changed('messageCountPerSecond'); - } - }, 1000); -} - -function toUrl(peer) { - return peer.protocol +':'+ peer.luid.toString('base64')+peer.ruid.toString('base64')+peer.rhid.toString('base64')+peer.rsid.toString('base64'); -} - -function bacon(self, peer, url) { - return function() { - if (!self.peers[url]) { return console.log('bail!', self.peers, url); }; - if(!self.beaconEnabled) { return; } - - self.node.request(peer, 'control.invoke', ['message', 'beacon! ('+( ++self.peers[url].cnt )+')'], (err, data) => { - if (err) { return console.log('send message error:', data); } - - // message delivered - console.log('sent message successfully, they said:', data); - self.messageCount++; - setTimeout(bacon(self, peer, url)); - }); - }; -} - -Beacon.prototype.startBeacon = function(peer) { - var url = toUrl(peer); - - console.log('beacon ', typeof bacon); - - this.peers[url] = { - interval: setTimeout(bacon(this, peer, url), 30), - peer: peer, - cnt: this.peers[url] ? this.peers[url].cnt : 0 - }; - - this.updatePeerCount(); -}; - -Beacon.prototype.stopBeacon = function(peer) { - var url = toUrl(peer); - if (!this.peers[url]) { return; }; - clearInterval(this.peers[url].interval); - delete this.peers[url]; - this.updatePeerCount(); -}; - -Beacon.prototype.updatePeerCount = function() { - var count = 0; - for(var i in this.peers) { count++; } - - console.log('peerCount:', count); - - this.peerCount = count; - this.node.changed('peerCount'); -}; - -var beacon = new Beacon(); \ No newline at end of file diff --git a/chat/chat.js b/chat/chat.js deleted file mode 100644 index 54672df..0000000 --- a/chat/chat.js +++ /dev/null @@ -1,48 +0,0 @@ -var MistNode = require('mist-api').MistNode; - -var cls = 'fi.controlthings.chat'; - -function Chat() { - var self = this; - this.node = new MistNode(process.env.NAME || 'Chat'); - - self.node.addEndpoint('mist.name', { type: 'string', read: (args, peer, cb) => { cb(null, 'Chat'); } }); - self.node.addEndpoint('mist.class', { type: 'string', read: (args, peer, cb) => { cb(null, cls); } }); - - self.node.addEndpoint('message', { - invoke: (args, peer, cb) => { - console.log('Received message:', args); - self.node.wish.request('identity.get', [peer.ruid], (err, data) => { - cb(null, 'You are known to me as '+data.alias); - }); - } - }); - - self.node.on('online', (peer) => { - self.node.request(peer, 'control.read', ['mist.class'], (err, type) => { - if (type === cls) { - self.node.wish.request('identity.get', [peer.luid], (err, data1) => { - self.node.wish.request('identity.get', [peer.ruid], (err, data2) => { - self.node.request(peer, 'control.read', ['mist.name'], (err, name) => { - console.log('peer:alias', data1.alias, data2.alias, name, type); - - self.node.request(peer, 'control.invoke', ['message', 'I see U!'], (err, data) => { - if (err) { return console.log('send message error:', data); } - - // message delivered - console.log('sent message successfully, they said:', data); - }); - }); - }); - }); - } - }); - - }); - - self.node.on('offline', (peer) => { - //console.log('chat:offline', peer); - }); -} - -var chat = new Chat(); \ No newline at end of file diff --git a/marielle/marielle.js b/marielle/marielle.js new file mode 100644 index 0000000..f6cff7f --- /dev/null +++ b/marielle/marielle.js @@ -0,0 +1,93 @@ +var Api = require("../mist/api"); + +var name = "Marielle"; +var coreIp = "127.0.0.1"; +var corePort = 9095; + +function friendRequestListener(api) { + api.onFriendRequest(() => { + api + .listFriendRequests() + .then(data => { + // Accept all requests without thinking. + for (var x = 0; x < data.length; x++) { + api + .acceptFriend(data[x].luid, data[x].ruid) + .then(() => { + console.log("I got a cool friend!"); + }) + .catch(err => { + console.log("Getting friends ain't easy :/", err); + }); + } + }) + .catch(err => { + console.log("Couldn't get list of friend requests.", err); + }); + }); +} + +function Marielle() { + var api = new Api(name, coreIp, corePort); + + api.onReady().then(() => { + api.ensureIdentity(name).then(() => { + + console.log("Hello, world! I am Marielle."); + + /* + * Start listener for automatically accepting friend requests. + */ + friendRequestListener(api); + + /* + * Set up an endpoint so that I can say my name. + */ + + var node = api.node(); + + node.addEndpoint("mist", { type: "string" }); + node.addEndpoint("mist.name", { + type: "string", + read: function(args, peer, cb) { + cb(null, name); + } + }); + + /* + * Set up an endpoint so that I can tell whether I'm happy or not. + * Also add reactions if someone is smiling or frowning to me. + */ + + var happy = true; + + node.addEndpoint("happy", { + type: "bool", + read: function(args, peer, cb) { + cb(null, happy); + } + }); + + node.addEndpoint("smile", { + invoke: function(args, peer, cb) { + console.log("Oh! That makes me happy!"); + happy = true; + node.changed("happy"); + cb(null, ":)"); + } + }); + + node.addEndpoint("frown", { + invoke: function(args, peer, cb) { + console.log("Oh, REALLY?!"); + happy = false; + node.changed("happy"); + cb(null, ":("); + } + }); + }); + }); +} + +// Start me up +var myMyselfAndI = new Marielle(); diff --git a/me/me.js b/me/me.js new file mode 100644 index 0000000..d1bc2a3 --- /dev/null +++ b/me/me.js @@ -0,0 +1,131 @@ +var Api = require("../mist/api"); + +var name = "Me"; +var coreIp = "127.0.0.1"; +var corePort = 9094; + +function usage() { + console.log(""); + console.log("usage: node me.js [who | hello | smile | frown]"); + console.log(""); + console.log("who\tList who is present"); + console.log("hello\tBecome friends with everyone"); + console.log("smile\tSmile broadly!"); + console.log("frown\tFrown angrily"); +} + +function Me() { + var api = new Api(name, coreIp, corePort); + + api.onReady().then(() => { + api + .ensureIdentity(name) + .then(() => { + if (process.argv.length <= 2) { + usage(); + process.exit(0); + } else { + var cmd = process.argv[2]; + + if (cmd == "who") { + api + .listEveryone() + .then(everyone => { + api + .listFriends() + .then(friends => { + for (var x = 0; x < everyone.length; x++) { + if (everyone[x].alias == name) { + console.log("I'm here!"); + } else { + var isFriend = false; + + for (var k in friends) { + if ( + Buffer.compare(everyone[x].ruid, friends[k].ruid) == + 0 + ) { + isFriend = true; + } + } + console.log( + (isFriend ? "Your friend " : "") + + everyone[x].alias + + " is here." + ); + } + } + process.exit(0); + }) + .catch(err => { + console.log("Failed to get list", err); + process.exit(1); + }); + }) + .catch(err => { + console.log("Failed to get list", err); + process.exit(1); + }); + } else if (cmd == "hello") { + api + .listEveryone() + .then(everyone => { + // Get my id + var luid; + for (var x = 0; x < everyone.length; x++) { + if (everyone[x].alias == name) { + luid = everyone[x].ruid; + } + } + + // Put out friendRequests to anyone else present. + for (var x = 0; x < everyone.length; x++) { + if (Buffer.compare(everyone[x].ruid, luid) != 0) { + console.log("Saying hello to " + everyone[x].alias); + api + .friendRequest(luid, everyone[x].ruid, everyone[x].rhid) + .catch(err => { + console.log("Failed.", err); + }); + } + } + + // Give friend requests 5 seconds to complete. + setTimeout(() => { + process.exit(0); + }, 5000); + }) + .catch(err => { + process.exit(1); + }); + } else if (cmd == "smile" || cmd == "frown") { + api + .listFriends() + .then(friends => { + for (var k in friends) { + api + .invoke(friends[k], cmd) + .then(data => { + console.log(data); + process.exit(0); + }) + .catch(err => { + console.log("Failed to smile.", err); + process.exit(0); + }); + } + }) + .catch(err => { + console.log("Failed to smile.", err); + process.exit(0); + }); + } + } + }) + .catch(err => { + console.log("Failed to create identity", err); + }); + }); +} + +var me = new Me(); diff --git a/mist/api.js b/mist/api.js new file mode 100644 index 0000000..e0a00af --- /dev/null +++ b/mist/api.js @@ -0,0 +1,97 @@ +var Mist = require("mist-api").Mist; + +module.exports = class Api { + constructor(name, coreIp, corePort) { + this.api = new Mist({ name: name, coreIp: coreIp, corePort: corePort }); + } + + node() { + return this.api.node; + } + + onReady() { + return new Promise( + function(resolve, reject) { + this.api.on("ready", () => { + resolve(); + }); + }.bind(this) + ); + } + + /* + * Make requests to the Wish API. + */ + + wishRequest(cmd, args) { + return new Promise((resolve, reject) => { + this.api.wish.request(cmd, args, (err, data) => { + if (err) { + // If we are failing in identiy creation because we already have + // an identity, all is well. + if (cmd == "identity.create" && data.code == 304) { + resolve(data); + } else { + reject(data); + } + } else { + resolve(data); + } + }); + }); + } + + ensureIdentity(name) { + return this.wishRequest("identity.create", [name]); + } + + listEveryone() { + return this.wishRequest("wld.list", []); + } + + friendRequest(luid, ruid, rhid) { + return this.wishRequest("wld.friendRequest", [luid, ruid, rhid]); + } + + listFriendRequests() { + return this.wishRequest("identity.friendRequestList", []); + } + + acceptFriend(luid, ruid) { + return this.wishRequest("identity.friendRequestAccept", [luid, ruid]); + } + + /* + * Make requests to the Mist API + */ + + mistRequest(cmd, args) { + return new Promise((resolve, reject) => { + this.api.request(cmd, args, (err, data) => { + if (err) { + reject(data); + } else { + resolve(data); + } + }); + }); + } + + listFriends() { + return this.mistRequest("listPeers", []); + } + + invoke(friend, action) { + return this.mistRequest("mist.control.invoke", [friend, action]); + } + + onFriendRequest(cb) { + this.api.request("signals", [], (err, data) => { + if (!err) { + if (data == "friendRequest") { + cb(); + } + } + }); + } +} diff --git a/package.json b/package.json index 26b8858..589a0bf 100644 --- a/package.json +++ b/package.json @@ -9,6 +9,6 @@ }, "repository": { "type": "git", - "url": "https://github.com/akaustel/mist-examples-nodejs.git" + "url": "https://github.com/mglonnro/mist-examples-nodejs.git" } } diff --git a/parking/run.js b/parking/run.js deleted file mode 100644 index aed5cf2..0000000 --- a/parking/run.js +++ /dev/null @@ -1,4 +0,0 @@ -var Parking = require('./src/parking.js').Parking; - -var parking = new Parking(); - diff --git a/parking/src/model.json b/parking/src/model.json deleted file mode 100644 index 4dce0fb..0000000 --- a/parking/src/model.json +++ /dev/null @@ -1,92 +0,0 @@ -{ - "mist": { - "type": "string", - "#": { - "name": { - "label": "Name", - "type": "string", - "read": true - }, - "ui": { - "type": "string", - "#": { - "url": { - "label": "Url", - "type": "string", - "read": true - } - } - }, - "product": { - "type": "string", - "#": { - "description": { - "type": "string", - "read": true - }, - "imageUrl": { - "type": "string", - "read": true - } - } - } - } - }, - "directory": { - "type": "invoke", - "invoke": true - }, - "version": { - "type": "meta", - "tag": "version", - "value": "0.0.1" - }, - "owner": { - "label": "Owner", - "type": "string", - "read": true - }, - "geo": { - "label": "Location", - "type": "invoke", - "invoke": true - }, - "vehicle": { - "label": "Supported vehicles", - "type": "invoke", - "invoke": true - }, - "chargeEnabled": { - "label": "Enable charging", - "type": "bool", - "read": true, - "write": true - }, - "chargeTime": { - "label": "Charging time remaining", - "type": "int", - "read": true - }, - "spotCount": { - "label": "Amount of parking spots", - "type": "int", - "read": true, - "write": true - }, - "spotFree": { - "label": "Amount of free parking spots", - "type": "int", - "read": true - }, - "getParkingSpot": { - "label": "Find free parking spot", - "type": "invoke", - "invoke": true - }, - "cancelParkingSpot": { - "label": "Cancel parking spot", - "type": "invoke", - "invoke": true - } -} - diff --git a/parking/src/parking.js b/parking/src/parking.js deleted file mode 100644 index 5617f9e..0000000 --- a/parking/src/parking.js +++ /dev/null @@ -1,159 +0,0 @@ -var EventEmitter = require('events').EventEmitter; -var MistNode = require('mist-api').MistNode; -var model = require('./model.json'); -var util = require("util"); - -var name = process.env.NAME || 'Parking'; -var lon = parseFloat(process.env.LON) || 25.6809455; -var lat = parseFloat(process.env.LAT) || 60.404048; - -if (!process.env.NAME) { - console.log('Use: NAME="MY Parking Ltd. 2" to run several instances.'); -} - -var parkingSpots = []; -var parkingCount = 10; -var parkingId = 1; -var owner = "ControlThings"; -var vehicle = ["Car"]; -var coordinates = {lon: lon, lat: lat}; - -var imageUrl = 'https://mist.controlthings.fi/parking.bmp'; -var description = ""; - -function Parking(id) { - var url = 'http://mist.cto.fi/mist-parking-ui-0.0.2.tgz' - - var self = this; - var node = new MistNode({ name: name }); // , coreIp: '127.0.0.1', corePort: 9094 - - this.chargeEnabled = false; - this.chargeTime = 10; - - setInterval(function() { - if (self.chargeTime <= 0 || !self.chargeEnabled) { return; } - - self.chargeTime--; - node.changed('chargeTime'); - - if(self.chargeTime === 0) { - self.chargeEnabled = false; - node.changed('chargeEnabled'); - } - }, 1000); - - node.create(model); - - node.read('chargeEnabled', function(args, peer, cb) { cb(null, self.chargeEnabled); }); - node.read('chargeTime', function(args, peer, cb) { cb(null, self.chargeTime); }); - - node.read('mist.name', function(args, peer, cb) { cb(null, name); }); - node.read('mist.ui.url', function(args, peer, cb) { cb(null, url); }); - node.read('owner', function(args, peer, cb) { cb(null, owner); }); - - node.read('spotCount', function(args, peer, cb) { cb(null, parkingCount); }); - node.read('spotFree', function(args, peer, cb) { cb(null, parkingCount - parkingSpots.length); }); - - node.read('mist.product.imageUrl', function(args, peer, cb) { cb(null, imageUrl); }); - node.read('mist.product.description', function(args, peer, cb) { cb(null, description); }); - - node.invoke('vehicle', function (args, peer, cb) { - cb(null, vehicle); - }); - - node.invoke('geo', function (args, peer, cb) { - cb(null, coordinates); - }); - - node.invoke("directory", function (args, peer, cb) { - - var schema = { - "@context": "http://schema.mobivoc.org/", - "@type": "ParkingFacility", - "@id": 84, - totalCapacity: { - "@type": "totalCapacity", - value: parkingCount - }, - supportVehicleType: { - "@type": "vehicleType", - value: vehicle - }, - placeName: { - "@type": "placeName", - value: name - }, - isOwnedBy: { - "@type": "isOwnedBy", - value: owner - }, - isLocated: { - "@type": "ParkingFacilityLocation", - "@context": "http://schema.org", - //"@type": "Place", - geo: { - "@type": "GeoCoordinates", - latitude: coordinates.lat, - longitude: coordinates.lon - } - } - }; - - cb(null, schema); - }); - - node.invoke('geo', function (args, peer, cb) { - cb(null, {lon: coordinates.lon, lat: coordinates.lat}); - }); - - node.invoke('getParkingSpot', function (args, peer, cb) { - - if (parkingCount <= parkingSpots.length) { - // parking is full - return cb({err: "We're full", code: 1}); - } - - var reservation = {id: 'p-' + (parkingId++)}; - parkingSpots.push(reservation); - node.changed('spotFree'); - cb(null, reservation); - }); - - node.invoke('cancelParkingSpot', function (args, peer, cb) { - var reservationId = args[0]; - for (var i in parkingSpots) { - if (parkingSpots[i].id === reservationId) { - parkingSpots.splice(i, 1); - node.changed('spotFree'); - return cb(null, true); - } - } - cb(null, {err: 'Parking not found', code: 2}); - }); - - node.write('spotCount', function (value, peer, cb) { - parkingCount = value; - node.changed('spotCount'); - node.changed('spotFree'); - cb(); - }); - - node.write('chargeEnabled', function (value, peer, cb) { - self.chargeEnabled = !!value; - - node.changed('chargeEnabled'); - - if (!!value) { - self.chargeTime = 10; - node.changed('chargeTime'); - } - cb(); - }); -} - - -util.inherits(Parking, EventEmitter); - -module.exports = { - Parking: Parking -}; diff --git a/switch/run.js b/switch/run.js deleted file mode 100644 index c6ab993..0000000 --- a/switch/run.js +++ /dev/null @@ -1,4 +0,0 @@ -var Switch = require('./src/switch.js').Switch; - -var mistIoSwitch = new Switch(); - diff --git a/switch/src/switch.js b/switch/src/switch.js deleted file mode 100644 index 470acee..0000000 --- a/switch/src/switch.js +++ /dev/null @@ -1,38 +0,0 @@ -var MistNode = require('mist-api').MistNode; - -var name = process.env.NAME || 'Switch'; - -if (!process.env.NAME) { console.log('Use: NAME="Switch Label" to run several instances.'); } - -function Switch() { - var relay = false; - - var node = new MistNode({ name: name }); // , coreIp: '127.0.0.1', corePort: 9094 - - // add `mist` endpoint - node.addEndpoint('mist', { type: 'string' }); - // add `mist.name` as subendpoint to mist - node.addEndpoint('mist.name', { type: 'string', read: function(args, peer, cb) { cb(null, name); } }); - - // add readable and writable `number` endpoint - node.addEndpoint('relay', { - type: 'bool', - read: function(args, peer, cb) { - cb(null, relay); - }, - write: function(value, peer, cb) { - // write the internal state variable for `number` endpoint - relay = !!value; - // signal successful write - cb(); - // signal `number` value changed - node.changed('relay'); - - console.log('relay set to:', relay); - } - }); -} - -module.exports = { - Switch: Switch -};