Aan de slag met OpenHAB 2: RFXCom en MiLight

Door GENETX op woensdag 27 april 2016 11:28 - Reacties (12)
Categorie: Home Automation met OpenHAB, Views: 8.033

Een hele hele lange tijd geleden begon ik eens te stoeien met domotica, en wel met het OpenHAB platform. Later begon ik ook eens aan een blogje daarvoor, maar verder dan deze opening kwam ik niet... Onlangs ben ik overgestapt op de tweede beta van OpenHAB 2.0, iets dat goed werkt. Met een opgeschoonde config vond ik het tijd om het blog maar weer eens op te pakken! Dus hierbij, een eerste tutorial over hoe je aan de slag kan met OpenHAB 2!

OpenHAB 2, what's new?

OpenHAB 2.0 verschilt relatief weinig van OpenHAB 1.0. De structuur is in grote lijnen hetzelfde, oude rules werken nog, sitemaps zijn hetzelfde en er wordt nog steeds mooi modulair gewerkt met bindings! Wat is er dan wel nieuw? Met name een nieuwe, moderne, interface en de mogelijkheid om met 2.0-bindings ook apparatuur te detecteren. Uiteindelijk zal alles via een UI kunnen, maar deze die-hard tweaker blijft toch grotendeels bij het aanpassen van configs middels tekstbestanden ;)

OpenHAB, what's different

Alvorens we beginnen met het installeren en configureren van OpenHAB wil ik nog even kort stilstaan bij het OpenHAB platform en wat het anders maakt dan bijvoorbeeld Domoticz. Er zit een filosofie achter dat het platform erg flexibel maakt, maar daarmee de learning curve ook iets ingewikkelder maakt. Als je eenmaal gewend bent, dan zul je het nut inzien en ben je, net als mij, om ;) . OpenHAB werkt met een aantal basis-elementen:

Items: Items zijn (virtuele) schakelaars, dimmers, sensoren, variabelen en dergelijke. Op zichzelf doen ze niets, maar vormen de basis van je setup.
Things: Things zijn de daadwerkelijke apparaten. Een apparaat kan bestaan uit meerdere things, zoals meerdere losse sensoren of schakelaars. De individuele things kun je koppelen aan je virtuele items. Daarmee is het later makkelijk om een apparaat (thing) in je huis te vervangen zonder de rest aan te moeten passen.
Sitemaps: Uiteraard heb je ook een interface nodig om je huis te bedienen. Dit doe je met een sitemap, waar je items aan toe kan voegen. Sitemaps kun je helemaal naar wens aanmaken en je hoeft niet alle items toe te voegen. Dat stelt je in staat om een simpele en cleane interface te maken. Je kan ook meerdere sitemaps aanmaken, wat potentieel een positief effect op de WAF heeft ;)
Rules: Middels rules kun je de boel automatiseren. Hier horen ook de scripts bij die je kan maken. Het handige aan het rule-systeem in OpenHAB is dat het een "sensitivity"-list bevat. Je kan er voor kiezen om rules alleen bij bepaalde veranderingen (zoals een opgaande flank) te triggeren. Het lijkt daarmee een beetje op VHDL voor de kenners, iets wat een uitstekende keuze is vanwege de vele parallelle events die een domoticasysteem kan triggeren. Hier ga ik in dit blog nog niet op in.
Persistence: Middels persistence kun je waarden en updates wegschrijven naar een database. Ook hier ga ik nu niet op in.

Naast configs in tekstbestanden kun je ook via de browser alles configureren en is er ook een blocky-editor voor als je niet zo sterk bent in code. Daarvoor heb je HABMin nodig: https://github.com/cdjackson/HABmin2 .

Setup

In deze blog zal ik je helpen bij het opzetten van communicatie met een RFXCom en MiLight lampen, maar voor we starten moeten we natuurlijk een installatie hebben. Download de OpenHAB 2.0b2 Online Distro van de OpenHAB website: http://www.openhab.org/getting-started/downloads.html . Pak de bestanden uit en start het programma vanaf een commandline met start.sh (of .bat, al heb ik enkel met de Linux variant ervaring). De eerste keer zal OpenHAB nog heel wat moeten downloaden, maar na een tijdje zou je http://localhost:8080 moeten kunnen openen.

http://static.tweakers.net/ext/f/98LsJVvYwgQVQ2MXbN5TZmRw/full.png

Je krijgt dan 4 opties voor je neus geschoteld: De Paper UI, Basic UI, Classic UI en REST API. Wij gaan aan de slag met de eerste 2 opties. Als je op Basic UI klikt zou je een demo te zien moeten krijgen (dat is de demo.sitemap). De Basic UI laat je dus de sitemaps zien. De Paper UI is er voor de configuratie in de browser. Mooi, alles werkt, dus kunnen we aan de slag!

Opbouwen van de items

We beginnen in deze blog met het koppelen van een schakelaar middels de RFXCom en een MiLight RGBWW-lamp. Daarvoor zullen we eerst een aantal items aan moeten maken die we later gaan koppelen aan de fysieke apparaten.

De schakelaar zal van het Switch-type zijn en de MiLight lamp is opgebouwd uit een Color-item, een Switch-item (om hem naar white-mode te kunnen resetten) en een Number-item (die laatste kunnen we aan een slider koppelen). Maak een bestand met de naam "verlichting.items" aan in de conf/items/-map. De inhoud is als volgt:

code:
1
2
3
4
5
6
7
Group   LIGHT   (All)

Switch  Lamp_RFXCom         "RFXCom"        <light>         (LIGHT) 

Dimmer  Lamp_MiLight        "MiLight"       <slider>        (LIGHT)     
Switch  Lamp_MiLight_White  "MiLight wit"   <light>         (LIGHT)
Color   Lamp_MiLight_Colour "MiLight kleur" <colorwheel>    (LIGHT)



Mogelijk dat het er een beetje cryptisch uitziet, maar dat is gewenning. Ik zal vandaag niet ingaan op de Groups (al zijn ze wel erg handig, dus heb ze alvast toegevoegd). De opbouw van een item is als volgt:

code:
1
Type Identifier "Omschriving voor interface" <icoon> (Groep1, Groep2) { commando's }


Over de commando's verderop meer. De beschikbare icons kun je hier vinden. Meer informatie over beschikbare items staat hier.

Interface maken

Met deze items alleen kunnen we nog niet zo heel veel, Dus laten we ze eerst toevoegen aan een sitemap. Ga naar de conf/sitemaps-map en voeg daar "example.sitemap" toe. Deze gaan we vullen met de zojuist gemaaktde items:

code:
1
2
3
4
5
6
7
8
9
sitemap example label="Huis"
{   
    Frame label="Verlichting" {
        Switch item=Lamp_RFXCom
        Slider item=Lamp_MiLight
        Switch item=Lamp_MiLight_White mappings=[ON=RESET]
        Colorpicker item=Lamp_MiLight_Colour
    }
}


Zie hier hoe alle zojuist aangemaakte items terugkomen in een frame. Binnen een sitemap het ook mogelijk om icons, labels en opties te overschrijven. Meer informatie over beschikbare controls en trucs kun je hier vinden.

Je kan het zo complex maken met meerdere lagen (zie maar eens in mijn code, link staat onderaan). Wat ook belangrijk is is de eerste regel. We definiŰren dus een sitemap met de naam "example". Die laatste hoeft niet identiek te zijn aan de bestandsnaam, maar aangeraden wordt het wel. Hoe dan ook, dit hebben we nodig om de pagina te openen. Standaard gaat de basic UI namelijk naar de demo sitemap die met OpenHAB werd ge´nstalleerd. De zojuist aangemaakte sitemap kun je vinden op:
http://localhost:8080/basicui/app?sitemap=example

Dan zou je dit te zien moeten krijgen:
http://static.tweakers.net/ext/f/LY7YUl82nbTTXeTN36zVdC3C/full.png

We kunnen echter de eigen sitemap ook als default instellen zodat je deze altijd krijgt als je op Basic UI klikt. Ga daarvoor naar http://localhost:8080 en kies voor de Paper UI. Ga naar Configuration -> Services. Klik vervolgens op "configure" bij Basic UI en type "example" bij de default sitemap. Klik op save en nu zou de knop Basic UI je direct naar de zojuist gemaakte sitemap moeten leiden.

De RFXCom toevoegen

Nu de basis staat, is het tijd om het eerste apparaat te koppelen, namelijk de RFXCom. Daarvoor hebben we eerst de RFXCom binding nodig. Ga daarvoor naar de Paper UI -> Extensions -> Bindings en zoek naar RFXCom en druk op Install. Normaliter zou nu alles nu correct moeten staan, ware het niet dat de default RFXCom 2.0 binding nog een fouten bevat. We gaan een nieuwere build nodig hebben. Pak de terminal er bij en voer de volgende commando's door:

code:
1
2
3
4
bundle:stop org.openhab.binding.rfxcom
bundle:uninstall org.openhab.binding.rfxcom
bundle:install https://openhab.ci.cloudbees.com/job/openHAB2-Addons/lastSuccessfulBuild/artifact/addons/binding/org.openhab.binding.rfxcom/target/org.openhab.binding.rfxcom-2.0.0-SNAPSHOT.jar
bundle:start org.openhab.binding.rfxcom



De RFXCom binding is een native 2.0 binding en kun je dus geheel via de Paper UI configureren. Dat geldt ook voor bijvoorbeeld Philips Hue lampen en als je de Network Binding installeert dan zul je ook al snel alle apparaten die in je netwerk hangen zien op basis van het IP-adres.

Dat zelflerende van RFXCom is helaas niet altijd helemaal van toepassing. Zo heb ik een Elro-set thuis (AB400D) waarvan de remote het Lighting4-commando gebruikt, maar de schakelaars reageren op Lighting1-commando's. Hiervoor werkt de zelflerende modus dus niet en moet je handmatig configureren. Daar ga ik verderop op in.

Ik zal eerst door de UI-stappen gaan. Voor alle duidelijkheid, ik ga er vanuit dat je, als je Linux draait, de juiste rechten hebt toegekend zodat je de RFXCom kan benaderen. Daar zijn zat tutorials voor te vinden (of als je lazy bent, draai OpenHAB als root voor nu om te spelen):
UI Based toevoegen van de RFXCom
Note: Deze beschrijving is mogelijk niet helemaal accuraat omdat ik een handgeschreven config gebruik
Stap 1: Ga terug naar de Paper UI en dan Setup Wizard. Klik op de blauwe knop met plus-teken bovenin en kies voor RFXCom. Mogelijk dat de RFXCom Bridge al gedetecteerd is. Klik anders op "Add manually" onderaan de pagina. Klik op de RFXCom USB Tranceiver die je hebt, geef het een naam en druk op de knop met het vinkje.

[bStap 2:[/b] Ga nu naar de Things-sectie in de Paper UI en klik op het zojuist aangemaakte RFXCom "thing" en vervolgens op het potloodje bovenin voor bewerking. Vul de serial port in waar de RFXCom is aangesloten. Voor de meesten zal dat "/dev/ttyUSB0 zijn. Druk weer op het vinkje om te bevestigen.

Stap 3: Ga terug naar de Setup wizard pagina. Hierin komen alle apparaten te staan die gedetecteerd worden. Druk nu op de afstandsbediening knop van de schakelaar die je wilt koppelen. Een nieuw apparaat zou moeten verschijnen. Klik er op en geef het een duidelijke naam. Vervolgens druk je op "add as Thing".

http://static.tweakers.net/ext/f/I37oejJuUAFDdKENT4BrEjrL/full.png

Stap 4: Ga vervolgens weer naar de Things-pagina en zoek het apparaat op. Klik er op zodat we een item aan de fysieke schakelaar kunnen koppelen. Druk op het blauwe rondje bij "Command" en selecteer het Lamp_RFXCom item. Druk op link en klaar ben je. Als het goed is moet je nu je eerste schakelaar via OpenHAB kunnen schakelen. Ga naar de Basic UI en probeer het!

http://static.tweakers.net/ext/f/uZ0OVRe6BHMXRK4Bd5rXhBxc/full.png

Werkt het niet? Wellicht heb je net als mij een Elro setje. Kijk eens naar de guide hieronder, de documentatie van de RFXCom binding, de input die je in Domoticz/RFXCom manager gebruikt, om handmatig de config goed te krijgen. Werkt het niet? Vraag ons in het OpenHAB Topic!
Handmatig toevoegen van de RFXCom
Zoals gezegd, het werkt niet altijd goed... Gelukkig kun je nog meer opties handmatig en met behulp van de binding-documentatie opzetten. Allereerst, de documentatie kun je hier vinden:
https://github.com/openha...rg.openhab.binding.rfxcom

Maar die is, zoals je kan zien, heel spartaans. De 1.x-binding documentatie geeft nog iets meer details en hints. Let wel op dat de 2.0 binding nog veel ondersteuning mist zoals bijvoorbeeld mijn deurbel... Helaas is de 1.x-binding niet compatible met OpenHAB 2.
https://github.com/openhab/openhab/wiki/RFXCOM-Binding

Na wat gepuzzel het gebruiken van de RFXCom manager onder Windows en het doorlezen van de source-code kon ik mijn Elro afstandsbediening aan de praat krijgen. Ik geef alleen de config, omdat we per case beter kunnen uitzoeken hoe het werkt.

De volgende config zet je in conf/things/ onder de naam rfxcom.things.

code:
1
2
3
Bridge rfxcom:bridge:usb0 [ serialPort="/dev/ttyUSB0" ] {
    Thing lighting1 Schakelaar  [ deviceId="L.10", subType="AB400D" ]
}


Uiteraard hangt het Thing af van je apparaat. Let op, je kunt hiermee stap 1 t/m 3 van de beschrijving hierboven overslaan. Enkel het koppelen met een item zoals in stap 4 staat beschreven is nu nog nodig.

MiLight toevoegen

De MiLight-binding is nog wel een pure 1.x-binding en moet dus wel grotendeels handmatig. Allereerst, de documentatie is hier te vinden:
https://github.com/openhab/openhab/wiki/Milight-Binding

De binding toevoegen gaat weer wel via de Paper UI. Ga wederom naar de Extensions-pagina en zoek naar de MiLight-binding en druk op installeren.

De volgende stap is om de config aan te maken in conf/services/. Voorheen (in OpenHAB 1.x) was er ÚÚn config.cfg bestand, nu zijn het losse configs met de naam van de binding. Er is nog een verschil: Je maakt geen gebruik meer van de binding-naam in de config. Op die punten is OpenHAB 2 anders en daar moet je mee opletten bij het lezen van 1.x-documentatie. Verder wordt er soms een template bestand aangemaakt. Indien "milight.cfg" niet bestaat maak je deze aan. De volgende inhoud moet er in komen:

code:
1
2
milight1.host=192.168.1.6
milight1.port=8899


Uiteraard zelf de juiste poort en IP invullen. Je kan ook meerderer bridges toevoegen, dan herhaal je de code, maar geef je de bridge de naam "milight2" ipv "milight1". Let op, zoals je kan zien is de config dus net iets anders dan de documentatie. Daarin had ik "milight.milight1.host=192.168.1.6" moeten gebruiken. Dit klopt dus voor 2.0!

De volgende stap is om de items te koppelen aan de fysieke lamp. Hiervoor moeten we de items-config aanpassen. Open nog eens conf/items/verlichting.items en pas deze aan door het commando toe te voegen aan de juiste items:

code:
1
2
3
4
5
6
7
Group   LIGHT   (All)

Switch  Lamp_RFXCom         "RFXCom"        <light>         (LIGHT)     

Dimmer  Lamp_MiLight        "MiLight"       <slider>        (LIGHT)     {milight="milight1;7;brightness;27"}    
Switch  Lamp_MiLight_White  "MiLight wit"   <light>         (LIGHT)     {milight="milight1;7;whiteMode"}
Color   Lamp_MiLight_Colour "MiLight kleur" <colorwheel>    (LIGHT)     {milight="milight1;7;rgb"}


Het stuk tussen accolades is de Binding config (zoals je onderaan deze pagina kan lezen). We binden het item dus aan de milight-binding (het stuk "{milight="). Het stuk tussen de quotes is dus de milight-specifieke config. In dit geval koppel ik dus de items aan de bridge "milight1" (zoals in de config), vervolgens aan kanaal 7 (wat dus groep 1 voor RGB-leds is, zie hieronder) en dan het juiste commando. Pas dus met name het kanaal aan op je eigen setup!

Het kanaal hangt af van het type lamp, zoals ook in de documentatie staat:
The channelNumber corresponds to the bulbs/channels on your bridge, where 0 reflects all white bulbs, 1-4 white bulb channels and 5 all rgb bulbs. For the new RGBW bulbs use channel number 6 (all RGBW bulbs), 7-10 (RGBW channels 1 to 4)
Als je alles goed hebt gedaan zou je nu ook de milight-lamp moeten kunnen bedienen!

gouden tips

Nog een belangrijke tip voor debuggen is de log. Hierin kun je zien of alles correct gaat. Tijdens het testen/configureren/spelen is het handig om dus OpenHAB zelf te starten in een terminal. Dan kun je namelijk hetvolgende commando gebruiken om te zien wat OpenHAB aan het doen is:

code:
1
log:tail



Het log sluiten doe je overigens met Ctrl-C. Ctrl-D laat OpenHAB stoppen!

Meer info

Als je nog verder wilt, dan kun je natuurlijk altijd terecht in het OpenHAB Topic en door mijn configs sneupen op https://github.com/GENETX/openhab2 . Daar staan ook nog wat meer 433MHz RFXCom apparaten in. Rest mij enkel nog deze blog af te ronden met een screenshot van mijn huidige interface :P

http://static.tweakers.net/ext/f/nVsQZaCqie3AGCp7LqyUlOa3/medium.png

Een thermostaat slim maken

Door GENETX op donderdag 18 februari 2016 21:27 - Reacties (7)
Categorie: -, Views: 4.755

Als je een slimme thermostaat wil dan kun je natuurlijk een dure, niet modulerende, Nest v3 halen of natuurlijk een "gratis" slimme thermostaat krijgen bij een jarenlang wurgcontract bij een energieboer. Maar als tweaker is dat niet waar ik zoveel trek in had met een operationeel domoticasysteem met OpenHAB. Dan kan een OpenTherm Gateway bijvoorbeeld ook uitkomst bieden, of zoals in mijn geval, de Honeywell Round Connected Modulation (HRCM). Afaik de goedkoopste, fatsoenlijke, thermostaat met Opentherm die ook nog eens via het internet te bedienen is :) .En al helemaal te integreren met dit script: https://github.com/watchforstock/evohome-client .

Over de thermostaat zelf gaat deze blog echter niet, maar meer wat we er zelf aan kunnen verbeteren. Het nadeel van de HRCM is dat het enkel een klokthermostaat is die ook via de app te bedienen is. Geen mogelijkheid dus om intelligent te gaan voorverwarmen zodat het mooi op temperatuur is in huis. Nu heb ik al een hele thermostaat interface in mijn OpenHAB installatie gebakken, inclusief schema's waardoor ik middels cron jobs ook de klokthermostaatwerking mooi ge´ntegreerd had.

Intelligent voorverwarmen
Maar ik wilde meer, een verwarmingsmodule met Model Predictive Control (MPC) en een zelf (her)lerend script om de parameters van mijn huis (en dus van het model) te leren. Met die informatie kun je uiteindelijk vooruit gaan simuleren om er achter te komen of het setpoint van de thermostaat al omhoog moet om op tijd de kamer op temperatuur te hebben.

Met die gedachte, en een bak meetdata, ging ik aan de slag in Python om een simpel prototype te bakken wat exact dat doet. Nu de eerste bevindingen gematigd positief is (er is altijd ruimte voor verbetering) en er op GoT vraag naar was, deel ik op dit blog wat van mijn scripts.

Let op: Het is echt work-in-progress en zeker geen code die zomaar bij jou gaat werken. Als je dit aan je eigen domoticasysteem met slimme thermostaat/OTGW wil koppelen, dan zul je zelf ook aan de bak moeten. Maar hopelijk geeft de code een goede zet in de rug!

Aan de slag!
Aan het werk dan maar. Hoe pakken we dit aan?

1. Je hebt een bak meetdata nodig van buitentemperatuur, binnentemperatuur en het setpoint. Daarvoor laat ik OpenHAB middels persistence naar een MySQL database loggen.
2. Een aantal elementen in je domoticasysteem om coefficienten in op te slaan en uiteraard je voorkeuren in te geven
3. Een script om de coefficienten van het kamermodel te trainen
4. En een script om het model door te rekenen!

Het model
Dan allereerst het model! Het is momenteel een simpel model, mede door het gebrek aan een luchtvochtigeheidssensor. Het simpele model dat ik nu gebruik is een simpele differentievergelijking:


code:
1
Ti[t+1] = Ti[t]  +  a*(Ti[t] - To[t]) +  b*heating  +  c*(Ts[t]-Ti[t])



De binnentemperatuur Ti op het volgende interval (t+1) wordt gegeven door de huidige binnentemperatuur (tijd t) plus het verlies naar buiten (a*Ti-To) plus de opwarming (binaire waarde heating) en een temperatuurverschil afhankelijke opwarming (tussen het setpoint Ts en de binnentemperatuur). De impact van deze factoren hangt af van de coŰfficienten a, b en c. Deze coŰfficienten moeten we dus zien te vinden.

De coefficiŰnten vinden
Dat kan met een curve fit op een hele rits data. Maar daarvoor moeten we die zogenaamde trainingsdata wel uit een database trekken en slechte data wegfilteren. Gelukkig zijn er allemaal tools om een dergelijke curve fit te doen, zo ook de functie curve_fit() in de scipy, een Scientific Python module. De onderstaande code doet exact dat!

Allereerst zie je het model dat ik hierboven beschreef. Vervolgens laadt ik een aantal tekstbestanden in. Dit zijn eigenlijk CSV-bestanden van uit de MySQL database en de ItemX zijn de tabelnamen zoals OpenHAB die voor mij heeft aangemaakt. Dat is iets dat je zelf moet uitzoeken. Na het inlezen van 4 weken aan data (en het converteren van de tijdsnotatie naar handigere Unix timestamps) loop ik door de data heen en probeer 4 waarden te vinden:
1. Een nieuwe binnentemperatuur
2. De vorige (of oudere) binnentemperatuur van 5 minuten geleden
3. Een buitentemperatuur die ook rond dat tijdstip is gemeten (komt niet zo precies, die fluctueert niet zo hard)
4. En het setpoint van 5 minuten geleden.

Dat is exact de data van het model! De nieuwe binnentemperatuur gooi ik in array Y, de array met de uitkomsten van de vergelijking. De andere waarden gaan in matrix X. Dat zijn de binaire waarden, het temperatuurverschil binnentemperatuur-buitentemperatuur en setpoint-binnentemperatuur. Ik ben daarbij in 3 situaties ge´ntereseerd:
1. Opwarmen van de ruimte. In dat geval is het setpoint minstens 0,5 graad hoger dan de binnentemperatuur
2. Afkoelen, dan is het setpoint minstens 0,5 graad lager dan de temperatuur
3. Op temperatuur houden, waar we niet echt wat mee kunnen verder.

Vervolgens roep ik de curve_fit functie aan om a, b en c te bepalen. Deze stuur ik vervolgens naar de REST API van OpenHAB. Voor de kenners, ik gebruik Number items.

thermoLearn.py:

Python:
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
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
#!/usr/bin/python3

#Some imports
import csv
from datetime import datetime, date, time
from scipy.optimize import curve_fit
import time
import scipy
import numpy
import requests

#A note on beforehand: I only use this script to estimate the heating of the room at the moment. Cooling can also be done, but that's not what I am in interested currently.

##### This is the actual function that describes the model itself #####

# Ti[t+1] = Ti[t]  +  a*(Ti[t] - To[t])  +  b*heating  +  c*(Ts[t]-Ti[t])

# with:
# Ti is the indoor temperature, To the outside temperature and Ts the setpoint
# heating and cooling are booleans specifying whether the heating is on
# heating is on when Ts[t] > tTi[t]
# t is time

def fn(x, a, b, c):
    return xn[0] + a*xn[1]*x[2] + b*xn[3] + c*xn[4]







##### Arrays to store data in #####
y = []                          # The output values
x = [[] for x in range(5)]      # The input alues for the curve fit

#define how much data must be used. 
#currently I use data up to 4 weeks old:
timeBegin = int(time.time()) - 4*7*24*60*60
            
#Arrays to store the temperature data in (dates and value)
tempOutDate =       []
tempInDate =        []
tempSetpointDate =  []
tempOut =           []
tempIn =        []
tempSetpoint =      []






##### reading the data from CSV files: ######

#Inside temperature data
reader = csv.reader(open('Item13.txt', 'r')) #Change accordingly
for row in reader:
    dt = datetime.strptime(row[0], "%Y-%m-%d %H:%M:%S")
    dt = int(time.mktime(dt.timetuple()))
    if(dt >= timeBegin):
        tempInDate.append(dt)
        tempIn.append(float(row[1]))
    
#Outside temperature data   
reader = csv.reader(open('Item5.txt', 'r')) #Change accordingly
for row in reader:
    dt = datetime.strptime(row[0], "%Y-%m-%d %H:%M:%S") 
    dt = int(time.mktime(dt.timetuple()))
    if(dt >= timeBegin):
        tempOutDate.append(dt)
        tempOut.append(float(row[1]))
     
#Thermostat setpoint data    
reader = csv.reader(open('Item10.txt', 'r')) #Change accordingly
for row in reader:
    dt = datetime.strptime(row[0], "%Y-%m-%d %H:%M:%S") 
    dt = int(time.mktime(dt.timetuple())) 
    if(dt >= timeBegin):
        tempSetpointDate.append(dt)
        tempSetpoint.append(float(row[1]))  
    
    
    
    
    
##### Init code #####   
ji = 0 # Pointer for indoor temperature index
jo = 0 # Pointer for outdoor temperature index
js = 0 # Pointer for Setpoint index
lastIndex = 0

# The time between two used samples (in seconds)
# I use 5minute intervals. Must be larger dan 1 minute
deltaTime = 300

##### Code to extract good data samples #####

# I loop through all the data 

for i in range(1, len(tempIn)):
    
    #select two samples from the indoor temperatures that are approximately deltaTime apart
    if(((tempInDate[i] - (deltaTime-30)) > tempInDate[lastIndex]) and ((tempInDate[i] - (deltaTime+30)) < tempInDate[lastIndex])):
        
        #now loop through the outdoor temperature to select a measurement sample that is relative close to the time that the previous indoor sample was taken
        while(tempOutDate[jo] < tempInDate[lastIndex] and len(tempOutDate) > jo+1):
            jo += 1
            #Note, for now I do not a strict check on time as I don't experience to much problems with reading the weather station data.
            
        #Do the same for the setpoint   
        while(tempSetpointDate[js] < tempInDate[lastIndex] and len(tempSetpointDate) > js+1):
            js += 1
            #I read indoor temperature and setpoint at the same time from the Honeywell Round Connected Modulation. No need to verify the date.
            
        #for the sake of completeness, set ji as well
        ji = i
        
        

        #Now starts the magic
        #first check if setpoint an indoor temperature are taken at the same time.
        if((tempSetpointDate[js]+10 > tempInDate[lastIndex]) and (tempSetpointDate[js]-10 < tempInDate[lastIndex])): 
            #append the expected output of the function for time t
            y.append(tempIn[ji])
            
            #and the input measurements for time t-timeDelta
            #current temperature
            x[0].append(tempIn[lastIndex])
                        
            #delta temperature
            x[1].append(tempIn[ji]-tempOut[jo])
                
            #setpoint - temperature (error)
            # Heating when error >= 0.5 degrees and setpoint > indoor temperature
            if((tempSetpoint[js]-0.5) > tempIn[lastIndex]):
                x[2].append(1)                                     #cooling
                x[3].append(1)                                     #heating                                 
                x[4].append(tempSetpoint[js] - tempIn[lastIndex])  #error
            #Else, when heating to keep the room at temperature 
            elif(tempSetpoint[js] > 15):
                x[2].append(0)                                     #cooling
                x[3].append(0)                                      #heating
                x[4].append(0)                                      # error is set to zero (thermostat keeps the room at temperature, so it cannot really be seen as the curve that heats the room#heating
            #otherwise, we are cooling!
            elif(tempIn[jo]) > 14.5:
                x[2].append(1)      
                x[3].append(0)
                x[4].append(0)
            #and in the last case were keeping a low temperature at approx 14 degrees
            else:
                x[2].append(0)      
                x[3].append(0)
                x[4].append(0)
            
            #and update the lastIndex:
            lastIndex = i
            
    elif((tempInDate[i] - (deltaTime+60)) > tempInDate[lastIndex]):
        #if the difference is more than timeDelta, also update the last index:
        lastIndex = i
        
        
        
##### Start the magic here! #####       
        
# Now, for scipy we need to copy the arrays to numpy arrays. It is kinda version specific (I didn't need this for my desktop, but my server was not so cooperating...)      
xn = []     
xn.append(numpy.asarray(x[0]))
xn.append(numpy.asarray(x[1]))
xn.append(numpy.asarray(x[2]))
xn.append(numpy.asarray(x[3]))
xn.append(numpy.asarray(x[4]))
yn = numpy.asarray(y)


#And now do a curve fit!
popt, pcov = curve_fit(fn, xn, yn)


#Storing the three resulting paramters
#I simply use OpenHAB Number items to store the state.
requests.put('http://192.168.1.14:8086/rest/items/ThermoParamA/state', data=str(popt[0]))
requests.put('http://192.168.1.14:8086/rest/items/ThermoParamB/state', data=str(popt[1]))
requests.put('http://192.168.1.14:8086/rest/items/ThermoParamC/state', data=str(popt[2]))

#in case you'd like to get some useful output :)
#print("coefficients:")
#print(popt)
#print("used samples:")
#print(len(y))



De input data moet oplopend zijn in tijd in dit geval! Een voorbeeld van mijn input, zoals Item5.txt, ziet er als volgt uit:

Item5.txt

code:
1
2
3
4
2016-02-17 13:57:58,1.56
2016-02-17 14:02:58,1.56
2016-02-17 14:07:59,3.76
2016-02-17 14:12:59,1.56



Verder ben ik lui :) . Ik was begonnen met de code vanuit wat csv exports en heb daarom nog geen tijd besteed aan het direct inelzen vanuit MySQL met Python. Is dat moeilijk? Nee, maar een tekstbestand uit een database trekken werkt ook ;) . Iedere nacht laat ik de coŰfficienten opnieuw bepalen. Dat doe ik met een cron-job die het volgende script aanroept:

learn.sh

Bash:
1
2
3
4
5
6
7
#!/bin/sh
cd /pad/naar/je/thermostat/scripts
mysqldump -u root -pMijnPasswordKrijgJeNiet -t -T/pad/naar/je/thermostat/scripts openhab Item5 --fields-terminated-by=','
mysqldump -u root -pMijnPasswordKrijgJeNiet -t -T/pad/naar/je/thermostat/scripts openhab Item10 --fields-terminated-by=','
mysqldump -u root -pMijnPasswordKrijgJeNiet -t -T/pad/naar/je/thermostat/scripts openhab Item13 --fields-terminated-by=','
python /pad/naar/je/thermostat/scripts/thermoLearn.py
rm Item*



En that's that! Een zelflerend systeem dat iedere dag het model van je huis opnieuw bepaald aan de hand van recentere meetdata. Momenteel zijn dit mijn coeŰfficienten:
a = -0.00111237337891
b = 0.17487391382
c = -0.00892335422198

Opvallend is dat c zelfs negatief is, wat niet echt logisch is, maar kan worden verklaard doordat het even duurt voor de radiatoren warm zijn. ie tijd (de vertraging tussen een hoger setpoint en het moment dat de kamer echt warm wordt) zou het model beter kunnen maken, amar dan moet ik ook een thermometer hebben die niet selectief afrond. De Honeywell rondt ineens naar boven af als je het setpoint verhoogt en omlaag bij een verlaging. Zo "win" je instantaan 0,5 graad... .Zoals gezegd, het is allemaal work in progress en dit is dan ook de eerste werkende alpha versie ;)

Het model gebruiken
Nu we een compleet model hebben, kunnen we deze inzetten om intelligenter te verwarmen! Ik heb dit zelf "SmartStart" genoemd binnen mijn domoticasysteem. Het werkt als volgt: Ik kies een tijd en gewenste tijd en temperatuur Setpoint en zet deze SmartStart aan. Daarnaast mag de temperatuur bij mij 1 graad afwijken (DeltaT)(sowieso raadt ik aan om een afwijking van minstens 0,5 graad toe te staan) aangezien het toch al wat warmer voelt als er warmte in de radiatoren zit en je van buiten komt. Vanaf dat moment wordt er iedere minuut een script getriggerd om te kijken of de verwarming al aan moet (en het setpoint dus moet worden verhoogd).

Dat script werkt dus met MPC en gaat voorspellen wat de temperatuur gaat doen. Eerst simuleer ik 5 minuten met de verwarming uit, daarna zet ik de verwarming aan in het model en simuleer ik wat de temperatuur doet. Als het model dan [b]Setpoint - DeltaT[b] bereikt voor de ingestelde tijd, dan hoef ik de verwarming nog niet aan te gooien en kijk over ene minuut weer wat de status is. Lukt dat niet? Dan heb ik dus die 5 minuten nodig en moet de verwarming nu direct aan :) . Ik doe dat weer via OpenHAB, maar je kan ook direct je thermostaat of OTGW aanroepen. Dit is de code:

smartStart.py

Python:
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
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
#!/usr/bin/python
from datetime import datetime, date, time 
import sys
import requests
#from evohomeclient import EvohomeClient

#set the timedelta, this has to be the same as in the other model! However, here it is given in minutes!!!
# So in my case thats 5:
timeDelta = 5

#Obtain the current time
#Note that all times in this script are given in minutes since the start of THIS day!
timeNow = datetime.now().minute + 60*datetime.now().hour

#Obtain the coefficients that were found using the learning script from the OpenHAB API
a = float(requests.get('http://localhost:8086/rest/items/ThermoParamA/state').text)
b = float(requests.get('http://localhost:8086/rest/items/ThermoParamB/state').text)
c = float(requests.get('http://localhost:8086/rest/items/ThermoParamC/state').text)

#Get the other user predefined settings:
setpointHour = int(requests.get('http://localhost:8086/rest/items/CV_SStart_Hour/state').text)      # Hour for which the new setpoint should be reached
setpointMin = int(requests.get('http://localhost:8086/rest/items/CV_SStart_Min/state').text)        # Idem for the minute
tempSet = float(requests.get('http://localhost:8086/rest/items/CV_SStart_Setpoint/state').text)     # The actual new setpoint to be reached
tempIn  = float(requests.get('http://localhost:8086/rest/items/CV_Temperature/state').text)         # The current indoor temperature
tempOut = float(requests.get('http://localhost:8086/rest/items/Weather_Temperature/state').text)    # The current outdoor temperature
tempDev = float(requests.get('http://localhost:8086/rest/items/CV_SStart_Dev/state').text)          # The allowed deviation (e.g., reaching setpoint-deviation by the time is enough) 
# Note: This should be at least 0.5 degrees!

#calculate the time of this day at which the setpoint has to be reached
timeSetpoint = setpointMin + setpointHour*60

if(timeSetpoint < timeNow-30):
    #We are probably talking about a setpoint to be reached the next day, add 24 hours:
    timeSetpoint += (60*24)

#first try 5 minutes without heating
tempIn = tempIn + a * (tempIn - tempOut)
timeRequired = timeDelta

#Now simulate heating (MPC) the room using the model:

while((timeRequired < timeDelta*100) and (tempIn < (tempSet - tempDev))): #stop either with simulation if we reach our setpoint, or it takes too long
    timeRequired += timeDelta                           
    tempIn = tempIn + a * (tempIn - tempOut) + b + c * (tempSet - tempIn) #calculate the next temperature


# Check if we reach the temperature in time:
if(timeNow + timeRequired >= timeSetpoint):
    # Well apparently we don't.
    # But note, we tried to start heating in 5 minutes.
    # Hence we need those 5 minutes and should start heating NOW! No way we can postpone this.
    
    #We need to heat
    #DISABLED: Let OpenHAB handle this instead to synchronize with me being home!
    #client = EvohomeClient('ik@example.com', 'MijnPinCodeKrijgJeOokNiet')
    #client.set_temperature('Kamer', tempSet)
        
    ##indicate that we have succesfully executed a smartstart
    requests.put('http://localhost:8086/rest/items/CV_SStart_Enabled/state', 'OFF')
        
    #and change the setpoint in the interface too
    requests.put('http://localhost:8086/rest/items/CV_Setpoint/state', data=str(tempSet))
        
    #and change the setpoint in the interface too
    requests.put('http://localhost:8086/rest/items/CV_ProgramSP/state', data=str(tempSet))



Et voila! Je zult zelf moeten kijken hoe je deze aansturing in je domoticasysteem bakt, al ga ik zo wel wat van mijn OpenHAB code hieronder dumpen ter referentie. Die instellingen voor SmartStart activeer ik nu via cron jobs in OpenHAB middels mijn thermostaatschema's. Ik activeer SmartStart een uur voor de gewenste temperatuur om er voor te zorgen dat ik bij een fout niet uren sta te stoken, het blijft een alpha ;) . De code zorgt er dan wel voor dat ik in een warm huis kom vanuit het werk of bed :) .

Conclusie
De eerste alpha werkt al aardig goed, al blijft het wat experimenteren. Verder, wat zijn goede waarden? IK leer nu met 4 weken aan data, maar misschien moet het korter om nog sterker de huidige weersinvloeden mee te nemen. En wie weet is 5 minuten te weinig. Het blijft spelen, maar toch werkt het al redelijk. De echte verbeterpunten zijn als volgt:

1. Een luchtvochtigheidsensor toevoegen en meenemen in het model (waarschijnlijk 2, ook eentje om het effect van verwarming op de luchtvochtigheid te bepalen)
2. Wellicht een beter thermodynamisch model erachter
3. Een losse thermometer gebruiken die nauwkeuriger is dan 0,5 graad en niet aan selectief afronden doet ;)
4. Opstarttijd bepalen (tijd tussen verhogen setpoint en het meten van warmtestijging.

Maar voor dat alles heb ik eerst een thermometer nodig (Cresta TX320 waarschijnlijk) en wat meetdata. Ik zou zeggen: Doe je voordeel er mee. Uiteindelijk moet ik dit ook weer eens naar GitHub gooien, maar dan wil ik nog wat meer in mijn domoticasysteem opruimen. Wind en lcuhtvochtigeheid buiten werden me eerder al aangeraden, maar deze gaven niet echt verbetering.

Appendix
Nuttige OpenHAB code voor kenners! Ik wil mijn thermostaatmodule ook nog eens opschonen en in zijn geheel ergens posten. Zo heb ik 2 schema's (werkdag en vrije dag) en verder nog 2 andere opties (uit en manual) met behoorlijk wat code om alles in te stellen. Hieronder alleen het stuk dat echt nuttig is voor SmartStart

Items

code:
1
2
3
4
5
6
7
8
9
10
11
Number  Weather_Temperature "Temperatuur buiten [%.1f ░C]"  <temperature>   (Weather_Chart, Graph_TempOut)      { http="<[openweathermap:300000:XSLT(openweathermap.org_temperature.xsl)]" }

Number  CV_Setpoint "Setpoint Honeywell [%.1f ░C]"  <temperature>   (Weather_Chart, Graph_TempIn)   
Number  CV_Temperature  "Temperatuur Honeywell [%.1f ░C]"   <temperature>   (Weather_Chart, Graph_TempIn)   
Number  CV_Current  "Huidig setpoint [%.1f ░C]" <heating>

Number CV_SStart_Hour "SmartStart uur [%d]" <clock-on>
Number CV_SStart_Min "SmartStart minuut [%d]" <clock-on>
Number CV_SStart_Setpoint "SmartStart setpoint [%.1f ░C]" <temperature>
Number CV_SStart_Dev "SmartStart deviation [%.1f ░C]" <temperature>
Switch CV_SStart_Enabled "SmartStart aan" <switch>



Sitemap

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
Text item=CV_Temperature label="Thermostaat [%.1f ░C]" icon="heating"{
            Frame{
                Setpoint item=CV_Current minValue=14.0 maxValue=22 step=0.5
                Text item=CV_Temperature 
                
                Text label="SmartStart" icon="clock-on" {   
                    Frame {
                        Switch item=CV_SStart_Enabled
                        Setpoint item=CV_SStart_Hour minValue=0 maxValue=23 step=1
                        Setpoint item=CV_SStart_Min minValue=0 maxValue=55 step=10
                        Setpoint item=CV_SStart_Setpoint minValue=14 maxValue=22 step=0.5
                        Setpoint item=CV_SStart_Dev minValue=0 maxValue=2 step=0.5
                    }
                }
            }
        }



Rules

code:
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
rule "CV Setpoint Honeywell gewijzigd"
when
    Item CV_Setpoint changed
then
    sendCommand(CV_Current, CV_Setpoint.state.toString())
    executeCommandLine("python ../extern/honeywell/setHoneywellTemp.py")
end

/*  Normal program */
rule "CV Schema 1 - Smartstart voorverwarmen in de ochtend"
when 
    Time cron "0 30 6 * * ?"  
then
    if(CV_Today.state==1){
        sendCommand(CV_SStart_Hour, 7)
        sendCommand(CV_SStart_Min, 30)
        sendCommand(CV_SStart_Setpoint, CV_TempMorning.state.toString())
        sendCommand(CV_SStart_Enabled, ON)
    }
end

rule "CV Smartstart"
when
    Time cron "30 * * * * ?"  
then
    if(CV_SStart_Enabled.state == ON){
        executeCommandLine("python ../extern/honeywell/smartStart.py")
    }
end


Honeywell scripts: https://github.com/GENETX...ee/master/extra/honeywell
(meer van mijn huidige interface, maar dan zonder deze SmartStart code vindt je daar ook)

MySQL Persistence:

code:
1
2
3
4
5
6
7
8
9
Strategies {
    default = everyChange 
}

Items {
    Weather_Temperature : strategy = everyChange, everyUpdate
    CV_Setpoint : strategy = everyChange, everyUpdate
    CV_Temperature : strategy = everyChange, everyUpdate
}

Domotica met OpenHAB - Proloog

Door GENETX op dinsdag 30 december 2014 13:26 - Reacties (3)
Categorie: Home Automation met OpenHAB, Views: 3.761

Dit is de start van Domoticablog #zoveel. Dat is niet vreemd. Domotica is hip en hot. Zie naar de successen van Homey op kickstarter, een subforum dat binnen no-time geŰxplodeerd is, de irritante reclamespotjes van Gira en geweldige opensource projecten zoals Domoticz en pilight. Talloze blogs over dat alles te vinden, en toch start ook ik er eentje, deze over OpenHAB.

In deze serie blogs ga je lezen hoe je een aantal zaken kan automatiseren. Uiteraard uitgewerkt in OpenHAB, maar de gedachtegang en ideeŰn zijn ook voor anderen met een domoticasysteem mogelijk interessant. Daarbij ondersteund OpenHAB diverse apparaten en domoticaoplossingen. Onder andere RFCOM en pilight worden ondersteund. Het is geschreven in Java en draait daarmee eigenlijk op ieder platform. Apps voor Android en iOS zijn ook beschikbaar.
De eerste stapjes
Een aantal jaar geleden kwam ik al wat in aanraking met domotica tijdens de studie. Wat spelen met een systeem genaamd Echelon en een docent die zijn huis vol had hangen met Plugwise schakelaars. Reuze interessant en ooit zou ook mijn huis er aan moeten geloven.

Nadat ik mijn studentenkamer had ingeruild voor een huisje, zag ik deze zomer een goedkoop setje van 3 Elro AB440 schakelaars in een aanbiedingenbak liggen bij de Mediamarkt. Een impulsaankoop dus. Ja, ik had wat lastig te bereiken lampschakelaars, maar dit was toch ook overkill eigenlijk. Het toppunt van luiheid, of toch niet? Ik had al gelezen over Domoticz en pilight. Met de aanschaf van dat setje was de drang naat het automatiseren niet meer te stoppen. No way back! Het huis zou en moest slim worden :)

De 433MHz transmitter en receiver werden bij CurlyMo, de geestelijke vader van pilight, besteld. De Raspberry Pi werd ontdaan van zijn stof en gereanimeerd. Een eerste prototype werd opgezet en de schakelaar werd bediend met pilight en Pimatic. Over die laatste combinatie was ik echter niet tevreden. De mogelijkheden tot het opstellen van automatiseringsregels was te beperkend voor de regels die ik voor ogen had.
OpenHAB
In mijn zoektocht naar een geavanceerd framework voor domotica stuitte ik op de Open Home Automation Bus, ofwel OpenHAB. Een opensource framework dat onderdeel is van de AllSeen alliantie voor domotica met een solide basis en zeer veel plugins. Het doel van het project is om een open en universeel platform te maken waarin apparatuur van diverse domoticafabrikanten samen komt. Zo heb je geen vendor lock-in. De basis van OpenHAB zit nu ook in het Eclipse Smarthome platform, dat nu ook door andere domoticabouwers wordt gebruikt.

OpenHAB heeft wel als nadeel dat het relatief zwaar is. Ik draai het op mijn servertje en dan gaat het prima. Op een Raspberry Pi is het niet aan te raden. OpenHAB 2 wordt echter lichter en lijkt grotendeels compatible te blijven. Mijn setup draait echter versie nummertje 1.6.1. De scripttaal is een stuk uitgebreider, maar daardoor ook lastiger te leren. Het doel van dit blog is dan ook om voorbeelden te geven om dat nadeel wat te verzachten.

Het grootste voordeel was wel dat sfinx destijds net een plugin had gemaakt om OpenHAB en pilight te koppelen. Dat maakt de keuze nogal makkelijk, want mijn hardware had daarmee geen aanpassing nodig in tegenstelling tot alle andere domotica systemen.
Het huidige systeem
Inmiddels zijn er een aantal maanden verder en is het eerste deel van het systeem in OpenHAB dan ook af. Zo'n hobby stopt en verveelt niet snel, dus het kan altijd mooier en beter. Maar op dit punt heb ik wel iets gemaakt waar ik tevreden over ben en iets dat ik graag met jullie deel via dit blog. De basis van de setup is als volgt:

Ik gebruik nog altijd pilight op de Raspberry Pi om de commando's naar de hardware door te sturen. OpenHAB draait op mijn servertje (1.6GHz ondergeklokte Celeron G1610, 4GB RAM) en bevat alle logica om slimme beslissingen te maken. Middels de OpenHAB pilight binding worden de acties doorgestuurd naar pilight om de schakelaars te schakelen. Aangezien ik nog wat meer sensoren wil toevoegen heb ik tot nu toe slechts een prototype op een breadboard met de 433 transmitter en receiver en een DHT22 temperatuursensor:

Hradware

Wat betreft hardware heb ik op het moment 9 Elro AB440 afstandsbedieningen, een network connected Pioneer VSX-923 receiver, een Honeywell Round Connected thermostaat en Kodi op mijn server. Dit zit, samen met mijn telefoon, computers en tablet in mijn domotica-systeem verwerkt en aan elkaar gekoppeld. De user interface ziet er nu zo uit:

http://tweakers.net/ext/f/4tJQFAHYROJomXfM5nUtIaKe/medium.jpg

http://tweakers.net/ext/f/LBcbch6SBaWBBhiDIJHN18KU/medium.jpg

In de komende blogs leg ik uit hoe je onder andere:

- verlichting automatisch aan laat gaan als de zon onder gaat;
- je kan detecteren of er iemand thuis is, en daarmee standby verbruik kan verlagen;
- Kodi op pauze zet en je receiver op mute als je aan het bellen bent;
- een Honeywell Round Modulation Connected in je domotica opneemt;
- nutteloze remotes hergebruikt om oa Kodi op pauze te zetten;
- een hele interface maakt om meterstanden bij te houden en graaddagen berekend;
- je receiver automatisch aanzet als je muziek of een film start met Kodi;
- en vast nog meer :)

Verder hoeft domotica niet duur te zijn. Een setje van 2 of drie schakelaars heb je al tussen de 10-20 euro (afhankelijk of je ze bij de Action haalt, compatible met pilight). Een pi haal je voor 35 euro en een paar 433MHz voor 12,50 bij pilight. SD kaartje er bij, USB voeding en voor zo'n 75 euro zou je zelf ook kunnen spelen met domotica :)

In het volgende blog zal ik het hebben over de integratie met pilight en de basis om een user interface te maken en schakelaars te schakelen. Voor wie niet kan wachten, meer informatie is beschikbaar in het OpenHAB topic op GoT: Het Grote OpenHAB topic - deel 1. Tevens zijn mijn scripts opensource, dus neem een kijkje op:
https://github.com/GENETX/openhab

Voor wie al OpenHAB draait en ook mijn eigen gemodificeerde skin wil, zie deze post: http://gathering.tweakers...message/43472881#43472881