Integrating KNX with Helium Atom ecosystem
IntroductionI've been working with smart home systems for 6 years and I can say that there is lack of cloud solutions. May be it's because clouds are too difficult for integrators to learn and work with?
Helium - compeletely high level solution for cloud integration. In analogy with programming languages - from low level(byte code, assembler) to the high-level(C, C++, Java, C#, Go, etc). So, everything changes over time and clouds are no exceptions. So, Helium Atom is a small, simple but efficient solution for connecting embedded systems to different kind of clouds.
Project overviewIn this project I show how to connect sensors(in my case it's KNX) to Google Cloud and use it's features like Cloud Functions to send push notifications by Firebase Cloud Messaging. I will use NanoPi as a sinle-board computer, Weinzierl KNX BAOS module as gateway to KNX bus and Helium Atom as a gateway to Google Cloud.
I use KNX bus (one of world standards in automation) to control lights, fan and it has temperature sensor to monitor current conditions in my house. Temperature, humidity monitoring may be helpful in addition to automatic lightning and fan control. So, let's implement it.
As a controller I use NanoPi NEO Plus2 with mounted Atom prototype module and Weinzierl KNX BAOS.
I chose NanoPi because it has two UART ports. I use UART1 for Atom Prototype board, UART2 for Weinzierl KNX BAOS module.
Getting startedConnecting hardwareI connected Weinzierl KNX BAOS 838 to UART2 at first, then I put Wireless Shield with Atom on top of it. NanoPi pins are compatible with Raspberry so there was no any problems.
NanoPi pinout:
After connecting and powering on I enabled serialports with npi-config. Now uart interfaces are available as /dev/ttyS1 and /dev/ttyS2.
Set up environmentFirst of all, add all Elements and Atoms to dashboard. Add config options to atom. Here is my config:
To work with Helium Atom prototype I will use python client library that can be found at python client library. Following instructions from Helium Dev webpage I installed helium_client pip package.
To work with KNX I will use bobaos project. I use bdsd.sock (instructions can be found here) and bdsd-cli to work with KNX datapoints. Also, for python script I wrote client library: bdsd.python.
I just cloned bdsd.python repo and inside it created script index.py.
Now, in the end, my python script looks like:
import os
import json
from bdsd_async import BDSDClient
from helium_client import Helium
helium = Helium("/dev/ttyS1")
helium.connect()
# init channel
channel = helium.create_channel('iot0x03')
config = channel.config()
# here is two values from atom config.
# I will use it in cloud functions to compare with actual temp.
low = config.get('config.low_temp')
high = config.get('config.high_temp')
atom_id = config.get('config.atom_id')
# init bobaos client
SOCKFILE = os.environ.copy()['XDG_RUNTIME_DIR'] + '/bdsd.sock'
myClient = BDSDClient(SOCKFILE)
@myClient.on('connected')
def handle_connected():
print('myClient is connected, great then')
# register listener for datapoint number 1.
# it's current temperature in the installation
@myClient.on('value')
def handle_broadcasted_value(data):
datapoint = data['id']
if datapoint == 1:
current = data['value']
# get critical temp from config
publishedData = {'current': current, 'low': low, 'high': high, 'datapoint': datapoint, atom_id: atom_id}
# publish data to IoT Cloud. { current: 24.7, high: 30, low: 15, datapoint: 1, atom_id: 'atomid'}
channel.send(json.dumps(publishedData))
myClient.loop();
Now I'm gonna tell how I connected Helium to Google Cloud.
Connecting to cloudAs as first step, create project in Google Cloud Console.
Then follow official documentation on setting up Helium with Google Cloud IoT Core.The name of channel I created is "iot0x03".
Handling with cloud functionsNow, my task is to process data from helium atom to this channel. For this case I will use Cloud Functions.
First of all, go to Firebase console. Add new project and in the project name select field choose project created in google cloud console.
Firebase will serve for Cloud Functions and Cloud Messaging for push notifications.
Install firebase command line interface.
sudo npm install -g firebase-tools
Login with firebase:
firebase login
If success then init functions project:
firebase init functions
During executing enter project to add functions, other questions. After completed this command will create 'functions' directory and 'firebase.json' file.
Following command serves to deploy function:
firebase deploy --only functions
Now, it's time to write Google IoT Core channel handler. For handling Google Cloud Pub/Sub events I will use 'functions.pubsub', following documentation.
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp();
// Create and Deploy Your First Cloud Functions
// https://firebase.google.com/docs/functions/write-firebase-functions
const MY_DEV_TOKEN = 'HERE I WILL PASTE MY PHONE TOKEN TO SEND NOTIFICATIONS';
exports.handleCriticalTemp = functions.pubsub
.topic('critical-temp-topic')
.onPublish(message => {
const messageBody = message.data ? Buffer.from(message.data, 'base64').toString() : null;
const data = JSON.parse(messageBody);
console.log(JSON.stringify(data));
const current = data.current;
const low = data.low;
const high = data.high;
const atom_id = data.atom_id;
if (current > high) {
console.log('current > critical. sending notification');
const payload = {
notification: {
title: `Temp alarm`,
body: `Temp > critical. Current ${current}, critical: ${high}. Atom: ${atom_id}.`
}
};
// Send notifications to device token.
return admin.messaging().sendToDevice(MY_DEV_TOKEN, payload);
}
if (current < low) {
console.log('current < critical. sending notification');
const payload = {
notification: {
title: `Temp alarm`,
body: `Temp < critical. Current ${current}, critical: ${low}. Atom: ${atom_id}.`
}
};
// Send notifications to device token.
return admin.messaging().sendToDevice(MY_DEV_TOKEN, payload);
}
return Promise.resolve();
});
Deploy it:
firebase deploy --only functions
Now, to check if functions was deployed, go to https://console.firebase.google.com/, open project and select 'Functions' in the side menu 'Develop'.
I will return to this functions after I init flutter application and get device token for notifications.
Creating simple flutter appI will use Android SDK and flutter to be able to create simple mobile application.
First of all, install Android Studio and Android SDK.
Then, install flutter: Get started.
After installing, run flutter doctor:
> flutter doctor
Doctor summary (to see all details, run flutter doctor -v):
[β] Flutter (Channel beta, v0.5.1, on Linux, locale en_US.UTF-8)
[β] Android toolchain - develop for Android devices (Android SDK 27.0.2)
[β] Android Studio (not installed)
[β] IntelliJ IDEA Community Edition (version 2018.1)
[β] IntelliJ IDEA Ultimate Edition (version 2018.1)
[β] Connected devices (1 available)
! Doctor found issues in 1 category.
I do not have android studio installed, instead, I have Intellij IDEA. So, I can proceed.
> flutter create iot0x03flutter
Creating project iot0x03flutter...
iot0x03flutter/iot0x03flutter_android.iml (created)
iot0x03flutter/.idea/libraries/Flutter_for_Android.xml (created)
.......
.......
All done! In order to run your application, type:
$ cd iot0x03flutter
$ flutter run
Your main program file is lib/main.dart in the iot0x03flutter directory.
Now, check for first run:
> cd ./iot0x03flutter
> flutter run
If everything is alright then simple flutter app with button press cound will be launched on connected device/emulator.
Adding push notificationsNow, I'm going to add firebase into this flutter application. To do this, I copy 'manifest package' value from 'android/app/src/main/AndroidManifest.xml'. Then I open Firebase console, go to project settings and add Android app. Paste value copied before into 'Android package name'. Download 'google-services.json' for created application and place it into 'android/app/' folder.
Add to 'android/build.gradle'
dependencies {
...
classpath 'com.google.gms:google-services:3.2.0'
}
In 'android/app/build.gradle' add as a last line:
dependencies {
...
}
apply plugin: 'com.google.gms.google-services'
And, finally, add to 'app/src/main/AndroidManifest.xml'
<activity
...>
...
<intent-filter>
<action android:name="FLUTTER_NOTIFICATION_CLICK" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
Now, install firebase_messaging package.
To do so, add dependency to pubspec.yaml file:
dependencies:
firebase_messaging: "^1.0.3"
Now, run:
> flutter packages get
Let's go to the source code.
lib/main.dart:
import 'package:flutter/material.dart';
import 'package:firebase_messaging/firebase_messaging.dart';
void main() => runApp(new MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return new MaterialApp(
title: 'Flutter Demo',
theme: new ThemeData(
primarySwatch: Colors.blue,
),
home: new MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
@override
_MyHomePageState createState() => new _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
FirebaseMessaging _firebaseMessaging = new FirebaseMessaging();
@override
void initState() {
super.initState();
_firebaseMessaging.configure(
onMessage: (Map<String, dynamic> message) {
print('on message $message');
},
onResume: (Map<String, dynamic> message) {
print('on resume $message');
},
onLaunch: (Map<String, dynamic> message) {
print('on launch $message');
},
);
_firebaseMessaging.requestNotificationPermissions(
const IosNotificationSettings(sound: true, badge: true, alert: true));
_firebaseMessaging.getToken().then((token){
print(token);
});
}
@override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text(widget.title),
)
);
}
}
Now, let's run.
There is printed device token in the output, so. I paste it into functions/index.js as MY_DEV_TOKEN const. Redeploy firebase functions:
> firebase deploy --only functions
i functions: updating function handleCriticalTemp...
β functions[handleCriticalTemp]: Successful update operation.
β Deploy complete!
Project Console: https://console.firebase.google.com/project/iot0x03/overview
Now it's ready to check!
DemoOf course, there more that can be done. Firebase platform allows to implement authorization, information storing by using firestore/storage, machine learning my ML Kit. Authorization can be implemented by using different providers, such a Google, Facebook, etc. Database data will be protected by security rules. So, there is a lot can be done.
My case is just prototype, so there I send notification direcly to device, which token I set explicitely in cloud function.
What could I do better: simple interface that shows current temperature, critical parameters, etc. Implement authorization, storing data in database, storing device fcm token in database. I'm still novice in Flutter, but it seems like a promising way to go, so, I have a lot to learn and will do so implementing ideas how to combine IoT, Firebase, Flutter.
ConclusionHelium Atom is the easy way to connect your sensors to cloud channels. It allows you reduce amount of work if you want to use cloud services with your embedded devices. First example usage is simple sensors of temperature, humidity, air quality, etc. Second example: simple thermostat with relays output(for example). Atom config allows to change setpoint and embedded application change relays state depending on temperature delta. There is lack of API which allow to change config variables from mobile app for example, but I guess it may be changed in time.
Helium may seems excessive to single-board computers that run linux due to ability use google/aws/etc cloud libraries and tools on it but it will be impossible to replace in embedded systems where developer can no care more about implementing protocol stacks.
Google Cloud, Firebase is actively developing platforms. Well documented, there is client libraries for bunch of programming languages. Authentication, data storage, IoT, hosting, functions - there is a lot of tools and features for implementing ideas.
Flutter seems like a promising platform to develop mobile applications. It compiles to native platform(iOS, Android) code from Dart lang. After messing around I'd say I will definetely learn how to flutter more and bring my ideas to life.
Links- IoT overview. Overview page with general information about IoT.
- GPS tracking with Google Cloud. Helpful examples showing how to work with Cloud Functions
- Cloud Functions FCM example. Simple example that shows how to send notifications when database has changed.
- Flutter push notifications with FCM. Here is described how to add firebase to flutter app and send push notifications.
Comments