Een thermostaat slim maken

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

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
}