Today, we're excited to announce our newest addition to the PubNub BLOCKS Catalog – the Falkonry AI block for time series AI. The Falkonry AI block allows you to analyze your massive real-time streams of data, and lets you build models or predict future action based on those data streams.
In this article, we dive into a simple example of how to send real-time events from an IoT device (simulated by a real-time AngularJS web application) into a Falkonry IoT AI pipeline with a modest 27-line PubNub JavaScript BLOCK and 77 lines of HTML and JavaScript.
In the past few years, there have been tremendous advances in machine learning, feature detection, pattern recognition and response. With Falkonry, we show how to give these Time Series AI capabilities to your real-time application.
What is Falkonry?
So, what exactly are these “Time Series AI” services we speak of? Falkonry is an artificial intelligence platform that provides sophisticated analytics to time series applications on demand. It uses machine learning to analyze data set features and provide condition analysis on your custom data set. With Falkonry, you can automate large-scale condition detection that previously required huge human effort and cost to implement (Industrial and Transportation operations and maintenance, IT system anomaly detection, and more).
As we prepare to explore our sample AngularJS web application with Time Series AI features, let's check out the underlying Falkonry API.
Falkonry API
General-purpose machine learning is a notoriously difficult area, and typically requires substantial effort and engineering resources to maintain high quality results across the wide range of data sets in real-world applications (especially in the context of mission-critical industrial, commercial and medical use cases). Falkonry provides a solution to these issues with a friendly UI and straightforward API. Through the
Falkonry provides a solution to these issues with a friendly UI and straightforward API. Through the API and user interface, it is possible to answer real-world queries and provide structured information in response to user messages in real time.
Getting Started with Falkonry API
The next thing you'll need to get started with natural language understanding services is a Falkonry account to take advantage of the Falkonry APIs.
- Step 1: go to the Falkonry signup form to create an account.
- Step 2: go to the Account Settings/Integration section and create a new API token (make note of it for the future).
- Step 3: create an Event Buffer, configure ‘id' as the entity attribute, and click the new Event Buffer's link in the left-hand panel to display its details (make note of its upload webhook URL for the future).
- Step 4: when you like, put together pipelines to analyze your data using the pipelines feature.
All in all, not too shabby!
Setting up the BLOCK
With PubNub BLOCKS, it's easy to create code to run in the network. Here's how to make it happen:
- Step 1: go to the application instance on the PubNub Admin Portal.
- Step 2: create a new block.
- Step 3: paste in the block code from the next section and update the credentials with the API token and webhook URL from the previous steps above.
- Step 4: Start the block, and test it using the “publish message” button and payload on the left-hand side of the screen.
That's all it takes to create your serverless code running in the cloud!
Diving into the Code – the BLOCK
You'll want to grab the 27 lines of BLOCK JavaScript and save them to a file, say, pubnub_falkonry_block.js
. It's available as a Gist on GitHub for your convenience.
First up, we declare our dependency on xhr (for HTTP requests) and create a function to handle incoming messages.
function process(request) { const xhr = require('xhr');
Next, we set up variables for accessing the service (the API token and webhook upload URL from previous steps).
const token = 'YOUR_FALKONRY_API_TOKEN'; const webhookUrl = 'https://sandbox.falkonry.ai/webhook/YOUR_FALKONRY_WEBHOOK';
Next, we set up the HTTP options for the upload API request. We use a POST request to upload the data. We use a form body for the message, and use the API token for the Authorization header. The upload API uses the time in milliseconds.
try { request.message.time = new Date().getTime(); var params = { method: 'POST', headers: { Authorization: 'Token ' + token, Accept: 'application/json', 'Content-Type': 'application/json' }, body: request.message };
Finally, we call the upload endpoint with the given data, log the upload result to console (remove this after debugging), and catch any errors and log to the BLOCKS console. Pretty easy!
return xhr.fetch(webhookUrl, params).then(function (r) { console.log(r); return request.ok(); }); } catch (e) { console.error('Uncaught exception:', e); return request.ok(); } }
All in all, it doesn't take a lot of code to add time series data collection functionality to your application. We like that!
OK, let's move on to the UI!
Diving into the Code – the User Interface
You'll want to grab these 77 lines of HTML & JavaScript and save them to a file, say, pubnub_falkonry_ui.html
.
The first thing you should do after saving the code is to replace two values in the JavaScript:
- YOUR_PUB_KEY: with the PubNub publish key mentioned above.
- YOUR_SUB_KEY: with the PubNub subscribe key mentioned above.
If you don't, the UI will not be able to communicate with anything and probably clutter your console log with entirely too many errors.
For your convenience, this code is also available as a Gist on GitHub, and a Codepen as well. Enjoy!
Dependencies
First up, we have the JavaScript code & CSS dependencies of our application.
<!doctype html> <html> <head> <script src="https://code.jquery.com/jquery-1.10.1.min.js"></script> <script src="https://cdn.pubnub.com/pubnub-3.15.1.min.js"></script> <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.6/angular.min.js"></script> <script src="https://cdn.pubnub.com/sdk/pubnub-angular/pubnub-angular-3.2.1.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js"></script> <link rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.0.2/css/bootstrap.min.css" /> <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.6.3/css/font-awesome.min.css" /> </head> <body>
For folks who have done front-end implementation with AngularJS before, these should be the usual suspects:
- JQuery : gives us the ability to use easy JQuery selectors.
- PubNub JavaScript client: to connect to our data stream integration channel.
- AngularJS: were you expecting a niftier front-end framework? Impossible!
- PubNub Angular JavaScript client: provides PubNub services in AngularJS quite nicely indeed.
- Underscore.js: we could avoid using Underscore.JS, but then our code would be less awesome.
In addition, we bring in 2 CSS features:
- Bootstrap: in this app, we use it just for vanilla UI presentation.
- Font-Awesome: we love Font Awesome because it lets us use truetype font characters instead of image-based icons. Pretty sweet!
Overall, we were pretty pleased that we could build a nifty UI with so few dependencies. And with that… on to the UI!
The User Interface
Here's what we intend the UI to look like:
The UI is pretty straightforward – everything is inside a div
tag that is managed by a single controller that we'll set up in the AngularJS code.
<div class="container" ng-app="PubNubAngularApp" ng-controller="MyAICtrl"> <pre> NOTE: make sure to update the PubNub keys below with your keys, and ensure that the AI BLOCK is configured properly! </pre> <h3>MyApp IoT Data Feed</h3>
We provide simple text inputs for the simulated IoT data to send to the PubNub channel as well as a button to perform the publish()
action.
<p>Device ID: <input ng-model="deviceid" /></p> <p>Device Temp: <input ng-model="devicetemp" /></p> <p>Device Speed: <input ng-model="devicespeed" /></p> <p><input type="button" ng-click="publish()" value="Send!" /></p>
Our UI consists of a simple list of data messages. We iterate over the messages in the controller scope using a trusty ng-repeat
. Each message includes the uploaded data attributes. All of these attributes are accessible for the condition detection and machine learning.
<ul> <li ng-repeat="message in messages track by $index"> Device: {{message.id}} <br /> Temp: {{message.temp}} <br /> Speed: {{message.speed}} <br /> </li> </ul>
And that's it – a functioning real-time UI in just a handful of code (thanks, AngularJS)!
The AngularJS Code
Right on! Now we're ready to dive into the AngularJS code. It's not a ton of JavaScript, so this should hopefully be pretty straightforward.
The first lines we encounter set up our application (with a necessary dependency on the PubNub AngularJS service) and a single controller (which we dub MyAICtrl
). Both of these values correspond to the ng-app
and ng-controller
attributes from the preceding UI code.
<script> angular.module('PubNubAngularApp', ["pubnub.angular.service"]) .controller('MyAICtrl', function($rootScope, $scope, Pubnub) {
Next up, we initialize a bunch of values. First is a random device id for uniqueness (your devices will likely know their own IDs). Next is a set of data values corresponding to the device (in our case, temperature and speed). Next is an array of message objects which starts out empty. After that, we set up the channel as the channel name where we will send and receive real-time structured data messages. NOTE: make sure this matches the channel specified by your BLOCK configuration!
$scope.deviceid = parseInt(Math.random() * 10000); $scope.devicetemp = 20; $scope.devicespeed = 100; $scope.messages = []; $scope.channel = 'falkonry-input';
We initialize the Pubnub
object with our PubNub publish and subscribe keys mentioned above, and set a scope variable to make sure the initialization only occurs once. NOTE: this uses the v3 API syntax.
if (!$rootScope.initialized) { Pubnub.init({ publish_key: 'YOUR_PUB_KEY', subscribe_key: 'YOUR_SUB_KEY', ssl:true }); $rootScope.initialized = true; }
The next thing we'll need is a real-time message callback called msgCallback
; it takes care of all the real-time messages we need to handle from PubNub. In our case, we have only one scenario – an incoming message containing the time series data values. We unshift the message object onto the scope array; that unshift()
operation should be in a $scope.$apply()
call so that AngularJS gets the idea that a change came in asynchronously.
var msgCallback = function(payload) { $scope.$apply(function() { $scope.messages.unshift(payload); }); };
The publish()
function takes the contents of the text inputs and publishes them as a structured data object to the PubNub channel.
$scope.publish = function() { Pubnub.publish({ channel: $scope.channel, message: {id:$scope.deviceid, temp:$scope.devicetemp, speed:$scope.devicespeed} }); };
In the main body of the controller, we subscribe()
to the message channel (using the JavaScript v3 API syntax) and bind the events to the callback function we just created.
Pubnub.subscribe({ channel: [$scope.channel], message: msgCallback });
We mustn't forget close out the HTML tags accordingly.
}); </script> </body> </html>
Now, we have a direct ingestion channel from our web UI into our Falkonry Event Buffer. If you're using an embedded platform, you would follow exactly the same PubNub message pattern, with the benefit that no data in the BLOCK would need to change!
Not too shabby for a little less than eighty lines of HTML & JavaScript!
Conclusion
Thank you so much for joining us in the Falkonry Time Series AI article of our web service integration series! Hopefully it's been a useful experience learning about machine-learning-enabled technologies. In future articles, we'll dive deeper into additional web service APIs and use cases for other real-time web applications.
Stay tuned, and please reach out anytime if you feel especially inspired or need any help!