The files contained in this repository can be downloaded to your computer using a svn client.
On Linux you simply type the command displayed below.

This URL has Read-Only access.

Statistics
| Revision:

root / trunk / DomotiGaServer / Thermostat.module @ 769

History | View | Annotate | Download (10.3 kB)

1
' Gambas module file
2
3
' Description:
4
' Thermostat.module
5
' Support for thermostat functionality.
6
7
' Development Status:
8
' Started.
9
10
' DomotiGa - an open source home automation program.
11
' Copyright(C) 2008-2011 Ron Klinkien
12
13
' Read file called COPYING for license details.
14
15
PUBLIC tThermostat AS Timer
16
PUBLIC NO_TEMP AS Integer = 1000
17
PRIVATE aDerogatedHeating AS NEW Collection
18
PRIVATE aPreviousRequestedTemperature AS NEW Collection
19
20
PUBLIC SUB Run()
21
22
  ' start poll timer for digitemp
23
  tThermostat = NEW Timer AS "tThermostat"
24
  tThermostat.Delay = Main.iThermostatPollTime * 1000 
25
  tThermostat.Start
26
27
END
28
29
'~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
30
' gets called at each timer event
31
'~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
32
PUBLIC SUB tThermostat_Timer()
33
34
  ' do the job
35
  DoTheJob()
36
37
END
38
39
PUBLIC SUB DoTheJob()
40
41
  DIM dtCurrent AS Date
42
  DIM iScen, iHeat AS Integer
43
  DIM rSched, rHeat AS Result
44
  DIM fRequestedTemp, fMeasuredTemp AS Float
45
  DIM sStatusDev, sStatusReg, sDeviceName, sRegulatorName AS String
46
  DIM sOnDev AS String = "On"
47
  DIM sOffDev AS String = "Off"
48
  DIM sOnReg AS String = "On"
49
  DIM sOffReg AS String = "Off"
50
  DIM bOutOfDeviceOffset AS Boolean
51
52
  ' get current date/time
53
  dtCurrent = Now()
54
  ' get active scenario
55
  iScen = GetActiveScenario()
56
  ' get scenario's schedules
57
  rSched = Main.hDB.Exec("SELECT * FROM thermostat_schedule WHERE scenario=&1", iScen)
58
  IF rSched THEN
59
    IF rSched.Count THEN
60
    ' for each schedule
61
      FOR EACH rSched
62
        ' get schedule's heating
63
        iHeat = rSched!heating
64
        rHeat = Main.hDB.Exec("SELECT * FROM thermostat_heating WHERE id=&1", iHeat)
65
        IF rHeat THEN
66
          IF rHeat.Count THEN
67
            IF Main.bThermostatDebug THEN Main.WriteDebugLog("[Thermostat] Working on heating : " & rHeat!name)
68
            ' check for constant change
69
            fRequestedTemp = GetRequestedTempForHeating(iScen, iHeat)
70
            IF aPreviousRequestedTemperature.Exist(iHeat) THEN
71
              IF aPreviousRequestedTemperature[iHeat] <> fRequestedTemp THEN
72
                DeleteDerogateHeating(iHeat)
73
                IF Main.bThermostatDebug THEN Main.WriteDebugLog("[Thermostat] Ending derogation for : " & rHeat!name)
74
              ENDIF
75
              aPreviousRequestedTemperature[iHeat] = fRequestedTemp
76
            ELSE
77
              aPreviousRequestedTemperature.Add(fRequestedTemp, iHeat)
78
            ENDIF
79
            ' get requested temp
80
            fRequestedTemp = GetDerogateHeating(iHeat)
81
            IF fRequestedTemp = NO_TEMP THEN
82
              fRequestedTemp = GetRequestedTempForHeating(iScen, iHeat)
83
            ENDIF
84
            ' get real temp
85
            fMeasuredTemp = CFloat(Replace(Devices.GetCurrentValueForDevice(rHeat!sensor, 1), ",", ".", gb.String)) 
86
            IF Main.bThermostatDebug THEN Main.WriteDebugLog("[Thermostat] Requested temp is : " & fRequestedTemp & "/Measured temp is : " & fMeasuredTemp)
87
            sDeviceName = Devices.FindNameForDevice(rHeat!device)
88
            sStatusDev = Devices.GetValueForDevice(sDeviceName)
89
            IF rHeat!regulator <> 0 THEN 
90
              sRegulatorName = Devices.FindNameForDevice(rHeat!regulator)
91
              IF sRegulatorName THEN
92
                  sStatusReg = Devices.GetValueForDevice(sRegulatorName)
93
              END IF
94
            ELSE 
95
              sRegulatorName = ""
96
            ENDIF
97
            IF rHeat!deviceInverted = TRUE THEN
98
              sOnDev = "Off"
99
              sOffDev = "On"
100
            ELSE
101
              sOnDev = "On"
102
              sOffDev = "Off"
103
            ENDIF
104
            IF rHeat!regulatorInverted = TRUE THEN
105
              sOnReg = "Off"
106
              sOffReg = "On"
107
            ELSE
108
              sOnReg = "On"
109
              sOffReg = "Off"
110
            ENDIF
111
            bOutOfDeviceOffset = FALSE
112
            IF NOT (isInsideLatency(rHeat!device, rHeat!deviceLatency)) THEN
113
              ' compare requested temp to sensor's one
114
              IF fMeasuredTemp + rHeat!deviceOffsetBottom <= fRequestedTemp THEN
115
              ' too cold
116
              bOutOfDeviceOffset = TRUE
117
              
118
                IF String.Comp(sStatusDev, sOffDev, gb.text) = 0 THEN
119
                  IF Main.bThermostatDebug THEN Main.WriteDebugLog("[Thermostat] Too cold here. Switching On device : " & sDeviceName)
120
                  Devices.SetDevice(sDeviceName, sOnDev)
121
                  sStatusDev = sOnReg
122
                ENDIF
123
                IF sRegulatorName THEN 
124
                  IF String.Comp(sStatusReg, sOffReg, gb.text) = 0 THEN
125
                    IF Main.bThermostatDebug THEN Main.WriteDebugLog("[Thermostat] Too cold here. Switching On regulator : " & sRegulatorName)
126
                    Devices.SetDevice(sRegulatorName, sOnReg)
127
                    sStatusReg = sOnReg
128
                  ENDIF 
129
                ENDIF 
130
              ENDIF
131
              IF fMeasuredTemp - rHeat!deviceOffsetTop >= fRequestedTemp THEN
132
              ' too hot
133
                bOutOfDeviceOffset = TRUE
134
                IF String.Comp(sStatusDev, sOnDev, gb.text) = 0 THEN
135
                  IF Main.bThermostatDebug THEN Main.WriteDebugLog("[Thermostat] Too hot here. Switching Off device : " & sDeviceName)
136
                  Devices.SetDevice(sDeviceName, sOffDev)
137
                  sStatusDev = sOffReg
138
                ENDIF
139
                IF sRegulatorName THEN 
140
                  IF String.Comp(sStatusReg, sOnReg, gb.text) = 0 THEN
141
                    IF Main.bThermostatDebug THEN Main.WriteDebugLog("[Thermostat] Too hot here. Switching Off regulator : " & sRegulatorName)
142
                    Devices.SetDevice(sRegulatorName, sOffReg)
143
                    sStatusReg = sOffReg
144
                  ENDIF 
145
                ENDIF 
146
              ENDIF
147
              IF NOT (bOutOfDeviceOffset) AND (String.Comp(sStatusDev, sOnDev, gb.text) = 0) THEN
148
                IF sRegulatorName THEN
149
                  sStatusReg = Devices.GetValueForDevice(sRegulatorName)
150
                  IF fMeasuredTemp + rHeat!regulatorOffsetBottom <= fRequestedTemp THEN
151
                  ' little cold
152
                    IF String.Comp(sStatusReg, sOffReg, gb.text) = 0 THEN
153
                      IF Main.bThermostatDebug THEN Main.WriteDebugLog("[Thermostat] Little cold here. Switching On regulator : " & sRegulatorName)
154
                      Devices.SetDevice(sRegulatorName, sOnReg)
155
                      sStatusReg = sOnReg
156
                    ENDIF
157
                  ENDIF
158
                  IF fMeasuredTemp - rHeat!regulatorOffsetTop >= fRequestedTemp THEN
159
                  ' little hot
160
                    IF String.Comp(sStatusReg, sOnReg, gb.text) = 0 THEN
161
                      IF Main.bThermostatDebug THEN Main.WriteDebugLog("[Thermostat] Little hot here. Switching Off regulator : " & sRegulatorName)
162
                      Devices.SetDevice(sRegulatorName, sOffReg)
163
                      sStatusReg = sOffReg
164
                    ENDIF
165
                  ENDIF
166
                ENDIF
167
              ENDIF
168
            ENDIF
169
          ENDIF
170
        ENDIF
171
      NEXT
172
    ENDIF
173
  ENDIF
174
175
END
176
177
PRIVATE FUNCTION GetActiveScenario() AS Integer
178
179
  DIM rResultScen AS result
180
181
  rResultScen = Main.hDB.Exec("SELECT id, name FROM thermostat_scenarii WHERE name=&1", Main.GlobalVar["Thermostat_Mode"])
182
  IF rResultScen THEN
183
    IF rResultScen.Count >= 1 THEN
184
      IF Main.bThermostatDebug THEN Main.WriteDebugLog("[Thermostat] Active scenario is : " & Main.GlobalVar["Thermostat_Mode"])
185
      RETURN rResultScen!id
186
    ENDIF
187
  ENDIF
188
  RETURN 0
189
190
END
191
192
PUBLIC FUNCTION GetRequestedTempForHeating(iScenario AS Integer, iHeating AS Integer) AS Float
193
194
  DIM sSql AS String
195
  DIM rTemp AS Result
196
  DIM fReturn AS Float
197
198
  sSql = "SELECT curtime() as curtime, dayofweek(curdate()) as curday, day, time,name, value FROM `thermostat_schedule_entry` se , `thermostat_constant` "
199
  sSql &= " c where c.id=se.constant AND dayofweek(curdate()) = Day AND se.scenario = &1 AND se.heating = &2 order by Day, Time "
200
  rTemp = Main.hDB.Exec(sSql, iScenario, iHeating)
201
  IF rTemp THEN
202
    IF rTemp.Count THEN
203
      FOR EACH rTemp
204
        IF rTemp!curtime >= rTemp!time AND rTemp!curday >= rTemp!day THEN
205
          fReturn = rTemp!value
206
        ELSE
207
          BREAK
208
        ENDIF
209
      NEXT
210
      RETURN fReturn
211
    ENDIF
212
  ENDIF
213
  RETURN NO_TEMP
214
215
END
216
217
PUBLIC FUNCTION GetNextRequestedTempForHeating(iScenario AS Integer, iHeating AS Integer) AS Float
218
219
  DIM sSql AS String
220
  DIM rTemp AS Result
221
  DIM fCurrentReq, fReturn AS Float
222
223
  sSql = "SELECT curtime() as curtime,  time,name, value FROM `thermostat_schedule_entry` se , `thermostat_constant` "
224
  sSql = sSql & " c where c.id=se.constant AND dayofweek(curdate()) = Day AND se.scenario = &1 AND se.heating = &2 order by Time "
225
  rTemp = Main.hDB.Exec(sSql, iScenario, iHeating)
226
  IF rTemp THEN
227
    IF rTemp.Count THEN
228
      FOR EACH rTemp
229
        IF rTemp!curtime >= rTemp!time THEN
230
          ' before now
231
          fCurrentReq = rTemp!value
232
        ELSE
233
          fReturn = rTemp!value
234
          IF fCurrentReq <> fReturn THEN RETURN fReturn
235
        ENDIF
236
      NEXT
237
    ENDIF
238
  ENDIF
239
  RETURN NO_TEMP
240
241
END
242
243
PRIVATE FUNCTION isInsideLatency(iDevice AS Integer, iLatency AS Integer) AS Boolean
244
245
  DIM rDev AS Result
246
247
  rDev = Main.hDB.Exec("select * from devices where id=&1", iDevice)
248
  IF rDev THEN
249
    IF rDev.Count >= 1 THEN
250
      IF rDev!lastchanged THEN
251
        IF DateDiff(rDev!lastchanged, Now(), gb.Minute) <= iLatency THEN
252
          IF Main.bThermostatDebug THEN Main.WriteDebugLog("[Thermostat] Inside latency, nothing to do here.")
253
          RETURN TRUE
254
        ENDIF
255
      ENDIF
256
    ENDIF
257
  ENDIF
258
  RETURN FALSE
259
260
END
261
262
PUBLIC SUB SetDerogateHeating(iScen AS Integer, iHeat AS Integer, fTemp AS Float)
263
264
  IF aDerogatedHeating.Exist(iHeat) THEN
265
    IF GetRequestedTempForHeating(iscen, iheat) = fTemp THEN
266
      aDerogatedHeating.Remove(iHeat)
267
    ELSE
268
      aDerogatedHeating[iHeat] = fTemp
269
    ENDIF
270
  ELSE
271
    ' not found
272
    aDerogatedHeating.Add(fTemp, iHeat)
273
  ENDIF
274
275
END
276
277
PUBLIC FUNCTION GetDerogateHeating(iHeat AS Integer) AS Float
278
279
  IF aDerogatedHeating.Exist(iHeat) THEN
280
    RETURN aDerogatedHeating[iHeat]
281
  ELSE
282
    RETURN NO_TEMP
283
  ENDIF
284
285
END
286
287
PUBLIC SUB DeleteAllDerogateHeating()
288
289
  IF aDerogatedHeating.Count THEN
290
    Main.WriteLog("[Thermostat] Ending all derogated temp.")
291
    aDerogatedHeating.Clear
292
  ENDIF
293
294
END
295
296
PUBLIC SUB DeleteDerogateHeating(iHeat AS Integer)
297
298
  IF aDerogatedHeating.Exist(iHeat) THEN aDerogatedHeating.Remove(iHeat)
299
300
END