Last active
October 9, 2017 16:20
-
-
Save plopp/85b3cceabd35dbe2554a65c6b1a9f4e0 to your computer and use it in GitHub Desktop.
Example client for the Yanzi Cirrus API
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const WebSocket = require('ws'); | |
const http = require('http'); | |
function assertDefinedEnv(varname) { | |
if (!(varname in process.env)) | |
throw "Error: Missing required env var " + varname; | |
} | |
assertDefinedEnv("SHREK_URL"); | |
assertDefinedEnv("PLUG_ENERGY_DID"); | |
assertDefinedEnv("PLUG_GPIO_DID"); | |
assertDefinedEnv("SENSOR_LID"); | |
assertDefinedEnv("YANZI_USER"); | |
assertDefinedEnv("YANZI_PASS"); | |
process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0'; | |
const PORT = process.env.PORT || 5000; | |
let cirrus_ws = new WebSocket(process.env.SHREK_URL, { | |
origin: 'https://devshrek.yanzi.se' | |
}); | |
//For this simple example, lets just store the last value in a global var. | |
var global_last_known_usage = -1; | |
/** | |
* Send an object over the cirrus connection. This will fail if the websocket | |
* is not open. | |
*/ | |
function sendMessage(message) { | |
if (cirrus_ws.readyState != WebSocket.OPEN) { | |
console.error("Couldn't send cirrus message: Socket not open"); | |
return; | |
} | |
try { | |
cirrus_ws.send(JSON.stringify(message, null, 1)); | |
} catch (e) { | |
console.error("Couldn't send cirrus message. " + e); | |
} | |
} | |
function sendLoginRequest(username, password) { | |
var request = { | |
"messageType": "LoginRequest", | |
"username": username, | |
"password": password, | |
"timeSent": new Date().getTime() | |
} | |
sendMessage(request); | |
} | |
function subscribeToDataFromLocation(locationId) { | |
var request = { | |
"messageType": "SubscribeRequest", | |
"timeSent": new Date().getTime(), | |
"unitAddress": { | |
"resourceType": "UnitAddress", | |
"locationId": locationId | |
}, | |
"subscriptionType": { | |
"resourceType": "SubscriptionType", | |
"name": "data" | |
} | |
} | |
sendMessage(request); | |
} | |
/** | |
* Really simple method to extract a single instantPower from a SubscribeData | |
* response for the specified lid/did. Will return undefined if not found. | |
* */ | |
function extractPlugUsageFromSubscribeData(json, lid, did) { | |
for (var i in json.list) { | |
var sample_list = json.list[i]; | |
//Is this our sensor? | |
if (sample_list.dataSourceAddress.did == did) { | |
console.log("Got update from plug") | |
console.log(JSON.stringify(sample_list.list[0])) | |
if (sample_list.list.length == 0) | |
throw "Error: empty sample list"; | |
return sample_list.list[0].instantPower; | |
} | |
} | |
return undefined; | |
} | |
function processResponse(json) { | |
if (json.messageType == "LoginResponse") { | |
console.log("Got login status: " + json.responseCode.name); | |
// lets assume we were logged in | |
subscribeToDataFromLocation(process.env.SENSOR_LID); | |
} else if (json.messageType == "SubscribeData") { | |
var res = extractPlugUsageFromSubscribeData(json, process.env.SENSOR_LID, process.env.PLUG_ENERGY_DID); | |
if (res !== undefined) { | |
global_last_known_usage = res; | |
} | |
} | |
} | |
/** | |
* Send a message to do a binary turn-off of the specified unit. | |
*/ | |
function sendTurnOff(lid, did) { | |
var request = { | |
"messageType": "ControlRequest", | |
"timeSent": new Date().getTime(), | |
"unitAddress": { | |
"resourceType": "UnitAddress", | |
"did": did, | |
"locationId": lid | |
}, | |
"did": did, | |
"controlValue": { | |
"resourceType": "ControlValueBinary", | |
"value": false | |
} | |
}; | |
sendMessage(request); | |
} | |
function sendTurnOn(lid, did) { | |
var request = { | |
"messageType": "ControlRequest", | |
"timeSent": new Date().getTime(), | |
"unitAddress": { | |
"resourceType": "UnitAddress", | |
"did": did, | |
"locationId": lid | |
}, | |
"did": did, | |
"controlValue": { | |
"resourceType": "ControlValueBinary", | |
"value": true | |
} | |
}; | |
sendMessage(request); | |
} | |
/** | |
* Event handlers for websocket: | |
*/ | |
cirrus_ws.on('connection', function connection(ws, req) { | |
console.log(JSON.stringify(req)); | |
const ip = req.connection.remoteAddress; | |
}); | |
cirrus_ws.on('open', function open() { | |
console.log("Connection opened"); | |
// Lets log in immidiately | |
sendLoginRequest(process.env.YANZI_USER, process.env.YANZI_PASS); | |
}); | |
cirrus_ws.on('message', function (data, flags) { | |
processResponse(JSON.parse(data)); | |
}); | |
function handleRequest(request, response) { | |
response.write("<html>"); | |
if (request.url == "/off") { | |
sendTurnOff(process.env.SENSOR_LID, process.env.PLUG_GPIO_DID); | |
response.write("Sent turn-off command"); | |
} | |
if (request.url == "/on") { | |
sendTurnOn(process.env.SENSOR_LID, process.env.PLUG_GPIO_DID); | |
response.write("Sent turn-on command"); | |
} | |
if (global_last_known_usage == -1) { | |
response.write("Waiting for information about the plug"); | |
} else { | |
response.write('The plug is using ' | |
+ (global_last_known_usage > 2 ? global_last_known_usage + " W" : "0 W")); | |
} | |
response.write("<br><a href=/on>Send turn-on command</a>") | |
response.end("<br><a href=/off>Send turn-off command</a></html>"); | |
} | |
var server = http.createServer(handleRequest); | |
//Lets start our server | |
server.listen(PORT, function () { | |
console.log("Server listening on: http://localhost:%s", PORT); | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment