Serverless Computing is often useful in event-driven Internet of Things (IoT) scenarios. For example when IoT sensors exceed a certain temperature actions are invoked to fix the issue.
OpenWhisk is IBM’s serverless computing offering in Bluemix. In order to implement a use case like above with the experimental OpenWhisk service, at this point you need to deploy a non-serverless application which receives MQTT events from IoT devices and invokes the appropriate OpenWhisk actions. While such a model seems to defeat the purpose of a serverless architecture, it allows developers to add their own filtering logic. For example rather than invoking hundreds of actions for hundreds of device events, you can invoke the potentially processing-intensive actions only for certain events, for example when the temperature is too hot.
Below is a simple sample how you could do this. Here is a sample action.
1
2
3
4
function main(params) {
params = JSON.stringify(params);
return { "message": "you sent me " + params };
}
For testing purposes you can invoke events via MQTT tools.
The following code shows a Node.js application that can be deployed via Cloud Foundry or Docker on Bluemix.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
var cfenv = require("cfenv");
var appEnv = cfenv.getAppEnv();
var express = require('express');
var app = express();
app.get('/', function (req, res) {
res.send('up');
});
app.listen(appEnv.port, appEnv.bind, function() {
console.log('listening on port ' + appEnv.port);
});
var openwhisk = require('openwhisk');
var ow = openwhisk({ api: 'https://openwhisk.ng.bluemix.net/api/v1/',
api_key: 'xxx:xxx',
namespace: 'niklas_heidloff@de.ibm.com_dev' });
var Client = require("ibmiotf");
var appClientConfig = {
"org" : "1o56n8",
"id" : 'myapp',
"auth-key" : "a-1o56n8-xxx",
"auth-token" : "xxx"
}
var appClient = new Client.IotfApplication(appClientConfig);
appClient.connect();
appClient.on("connect", function () {
// change this for the device events you're interested in
appClient.subscribeToDeviceEvents("TestDeviceType","+","+","json");
});
appClient.on("deviceEvent", function (deviceType, deviceId, eventType, format, payload) {
// add your own filter logic here
payload = JSON.parse(payload);
ow.actions.invoke({ actionName: "openwhisk",
params: payload }).then(result => {
console.log('success', result);
})
});
The Node application uses iot-nodejs for the MQTT part and openwhisk as a convenience library to invoke actions.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
{
"name": "mqtt-to-openwhisk",
"version": "1.0.0",
"description": "",
"main": "app.js",
"dependencies": {
"ibmiotf": "^0.2.12",
"openwhisk": "2.0.0",
"express": "4.13.4",
"cfenv": "1.0.3"
},
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"start": "node app.js"
},
"author": "",
"license": ""
}
Invoked actions show up in the OpenWhisk dashboard.
As alternative to deploying a Node application you could also use Node-RED, the incoming IoT node and the openwhisk node.