It’s been a while since my last post, so just a short one this time. I invested in VELUX ACTIVE with NETATMO in 2019 for controlling my skylights. I knew it was a cloud-based solution with all its cons, and even without any API for integration. This obviously sucks, but suddenly ClientID and ClientSecret was published in an openHAB Community thread, so I no longer had the excuse that I didn’t want to spend time reverse engineering the APK for Android. Now it was just a matter of implementing an integration.
Since I didn’t have experience with Python yet, I decided I wanted to try to use that for an implementation. It was my impression that it had everything I needed: HTTPS, JSON and MQTT. And I was right, so after 90 minutes of google-coding, this is my implementation for fetching my data from my sensor switch (CO2, temperature and humidity). Implementation is based on https://github.com/nougad/velux-cli.
First script is run to get a token which will be used for authentication. Script will ask for the password for the corresponding Velux account:
#!/usr/bin/python3 import getpass import requests URL='https://app.velux-active.com/oauth2/token' # From Android app reverse engineering CLIENT_ID='' CLIENT_SECRET='' # My account USERNAME='veluxaccount@email.address' try: password = getpass.getpass() except Exception as error: print('Error:', error) data = { 'grant_type': 'password', 'client_id': CLIENT_ID, 'client_secret': CLIENT_SECRET, 'username': USERNAME, 'password': password, 'user_prefix': 'velux' } response = requests.post(URL, data=data) if response.status_code == 200: file = open('token.json', 'w') file.write(response.text) file.close() else: print('Error:', response)
A file ‘token.json’ will be saved in current directory. Next script will refresh the token, so this must be run once per every few hours. I don’t remember exact expiration period, but it’s in the response.
#!/usr/bin/python3 import json import requests URL='https://app.velux-active.com/oauth2/token' # From Android app reverse engineering CLIENT_ID='' CLIENT_SECRET='' file = open('token.json', 'r') body = file.read() file.close() token = json.loads(body) data = { 'grant_type': 'refresh_token', 'refresh_token': token['refresh_token'], 'client_id': CLIENT_ID, 'client_secret': CLIENT_SECRET } response = requests.post(URL, data=data) if response.status_code == 200: file = open('token.json', 'w') file.write(response.text) file.close() else: print('Error:', response)
And finally this last script is run every 5 minutes which seems to be the frequency for new measurements:
#!/usr/bin/python3 import json import requests import paho.mqtt.client as mqtt URL='https://app.velux-active.com/api/homestatus' MQTT_BROKER='192.168.0.236' HOME_ID='your_home_id' file = open('token.json', 'r') body = file.read() file.close() token = json.loads(body) data = { 'access_token': token['access_token'], 'home_id': HOME_ID } response = requests.post(URL, data=data) if response.status_code != 200: print('Error:', response) exit() data = json.loads(response.text) home = data['body']['home'] rooms = home.get('rooms') if rooms: room = rooms[0] else: print('Unexpected response:', response.text) exit() client = mqtt.Client() client.connect(MQTT_BROKER) client.publish('velux/hallway/co2', payload=room['co2'], qos=0, retain=False) client.publish('velux/hallway/humidity', payload=room['humidity'], qos=0, retain=False) client.publish('velux/hallway/temperature', payload=(room['temperature']/10), qos=0, retain=False) client.publish('velux/hallway/lux', payload=room['lux'], qos=0, retain=False) for module in data['body']['home']['modules']: if module['type'] == 'NXD': # Departure switch client.publish('velux/departure_switch/battery_percent', payload=module['battery_percent'], qos=0, retain=False) if module['type'] == 'NXS': # Sensor client.publish('velux/sensor1/battery_percent', payload=module['battery_percent'], qos=0, retain=False)
In openHAB I have configured a thing to receive these MQTT updates, so I have them persisted in MySQL, shown in sitemaps, etc.