forked from ALLTERCO/shelly-script-examples
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathscript-temperature-adjust.js
More file actions
232 lines (199 loc) · 8.61 KB
/
script-temperature-adjust.js
File metadata and controls
232 lines (199 loc) · 8.61 KB
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
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
// ---------------------------------------------------------------------------------------------------------------------
// SCRIPT FOR READING EXTERNAL DHT22 SENSOR WITH SHELLY WALL DISPLAY
// Luca Bartolini - Larciano (PT) Italy - luca@bitcon.it
// Indipendent Developer
// written in August 2024
// this script runs inside a shelly plus with Addon and DHT22 sensor
// it reads temperature/humidity from DHT22 wired sensor, and then put adjustments (delta) to a shelly wall-display
// in this way the wall display will show temp/humi from DHT22, and not from its local sensors.
// ---------------------------------------------------------------------------------------------------------------------
let CONFIG = {
// url address of shelly wall display
urlTermostato: "http://192.168.0.10",
// url address of shelly plus with temperature sensor DHT22
// this is the address where this program is running on
urlSensoreInterno: "http://192.168.0.16",
// http timeout query thermostat
httpTimeout: 10,
// timer in seconds for thermostat status polling.
lkTime: 10,
// timer in seconds for temperature adjustments.
lkTimeLungo: 60,
// default value for temperature reading error.
lkErrorValue: -273,
// if set to 1 the module will print detailed informations in general log.
lkDebugEnable: 0,
};
let tmpTimer = null;
let pingTimer = null;
let pingTimer_temperaturePoll = null;
let pingTimer_temperatureAdj = null;
let pingTimer_humidityPoll = null;
// structure to save values in asyncronous calls
let obj_temp = {
f_offset_temp:0,
f_offset_humi:0,
f_disp_temp:0,
f_disp_humi:0,
f_sensor_temp:0,
f_sensor_humi:0,
}
// print a info string in general log, if debug is enabled
function fnPrintDebug(par_s) {
if (CONFIG.lkDebugEnable==1) {
print('[luke_script_temperature]' + par_s);
}
}
// print error in gemeral log
function fnPrintError(par_s) {
print('[luke_script_temperature] ERROR ' + par_s);
}
// read thermostat status (short timer)
function fnPolling() {
fnLeggiStatusTermostato();
}
// read temperature (long timer)
function fnTemperaturePoll() {
fnLeggiParametro(CONFIG.urlTermostato + '/rpc/Temperature.GetConfig?id=0', 'offset_C', 'f_offset_temp');
fnLeggiParametro(CONFIG.urlTermostato + '/rpc/Temperature.GetStatus?id=0', 'tC', 'f_disp_temp');
fnLeggiParametro(CONFIG.urlSensoreInterno + '/rpc/Temperature.GetStatus?id=100', 'tC', 'f_sensor_temp');
}
// read humidity (long timer)
function fnHumidityPoll() {
fnLeggiParametro(CONFIG.urlTermostato + '/rpc/Humidity.GetConfig?id=0', 'offset', 'f_offset_humi');
fnLeggiParametro(CONFIG.urlTermostato + '/rpc/Humidity.GetStatus?id=0', 'rh', 'f_disp_humi');
fnLeggiParametro(CONFIG.urlSensoreInterno + '/rpc/Humidity.GetStatus?id=100', 'rh', 'f_sensor_humi');
}
// temp/umidity adjustments (long timer)
function fnTemperatureAdjust() {
fnPrintDebug("[fnTemperatureAdjust] DEBUG - f_sensor_temp : " + obj_temp['f_sensor_temp']);
fnPrintDebug("[fnTemperatureAdjust] DEBUG - f_disp_temp: " + obj_temp['f_disp_temp']);
fnPrintDebug("[fnTemperatureAdjust] DEBUG - f_offset_temp: " + obj_temp['f_offset_temp']);
fnPrintDebug("[fnTemperatureAdjust] DEBUG - f_sensor_humi : " + obj_temp['f_sensor_humi']);
fnPrintDebug("[fnTemperatureAdjust] DEBUG - f_disp_humi: " + obj_temp['f_disp_humi']);
fnPrintDebug("[fnTemperatureAdjust] DEBUG - f_offset_humi: " + obj_temp['f_offset_humi']);
// calculate new temperature adn humidity offset
f_New_offset_temp = obj_temp['f_sensor_temp'] - (obj_temp['f_disp_temp'] - obj_temp['f_offset_temp']);
f_New_offset_humi = obj_temp['f_sensor_humi'] - (obj_temp['f_disp_humi'] - obj_temp['f_offset_humi']);
if (f_New_offset_humi>50) {
f_New_offset_humi=50;
}
if (f_New_offset_humi<-50) {
f_New_offset_humi=-50;
}
fnPrintDebug("[fnTemperatureAdjust] DEBUG - new offset temp: " + f_New_offset_temp);
fnPrintDebug("[fnTemperatureAdjust] DEBUG - new offset humi: " + f_New_offset_humi);
// write new offsets in wall display
fnScriviParametro(CONFIG.urlTermostato + '/rpc/Temperature.SetConfig?id=0&config={"offset_C":' + f_New_offset_temp + '}');
fnScriviParametro(CONFIG.urlTermostato + '/rpc/Humidity.SetConfig?id=0&config={"offset":' + f_New_offset_humi + '}');
}
// function to set a local variable (KVS)
function kvsSet(key, value) {
Shelly.call(
"KVS.Set",
{ "key": key, "value": value }
);
}
// generic function that reads a parameter with http get.
// p_url: address of device to read
// p_nome: parameter to read from json response
// p_variablename: name of variable where store value in structure "obj_temp" (this because the variable writing is asyncronous)
function fnLeggiParametro(p_url, p_nome, p_variablename) {
Shelly.call(
"http.get",
{ url: p_url, timeout: CONFIG.httpTimeout },
function (response, error_code, error_message) {
if (error_code != 0) {
fnPrintError("[fnLeggiParametro] Failed to fetch, error(" + error_code + ") " + error_message + ' - url: ' + p_url);
} else {
if (response === undefined) {
fnPrintError("[fnLeggiParametro] ERROR response undefined");
} else {
responseData = JSON.parse(response.body);
obj_temp[p_variablename] = responseData[p_nome];
fnPrintDebug("[fnLeggiParametro] DEBUG lettura " + p_variablename + ' ' + p_nome + ' ' + responseData[p_nome]);
}
}
}
);
}
// generic function that writes a parameter with http get
// p_url: address of device to write
function fnScriviParametro(p_url) {
Shelly.call(
"http.get",
{ url: p_url, timeout: CONFIG.httpTimeout },
function (response, error_code, error_message) {
if (error_code != 0) {
fnPrintError("[fnScriviParametro] Failed to fetch, error(" + error_code + ") " + error_message + ' - url: ' + p_url);
} else {
// tutto ok
if (response === undefined) {
fnPrintError("[fnScriviParametro] ERROR response undefined");
} else {
responseData = JSON.parse(response.body);
fnPrintDebug("[fnScriviParametro] DEBUG response: " + response.body);
}
}
}
);
}
// function that periodically reads wall display config to retrieve "season" informations
// the season information is stored in a KVS variable "par_stagione"
function fnLeggiStatusTermostato() {
fnPrintDebug("Leggi Termostato");
Shelly.call(
"http.get",
{ url: CONFIG.urlTermostato + '/rpc/Thermostat.GetConfig?id=0', timeout: CONFIG.httpTimeout },
function (response, error_code, error_message) {
if (error_code != 0) {
fnPrintError("[fnLeggiStatusTermostato] Failed to fetch, error(" + error_code + ") " + CONFIG.urlTermostato);
} else {
// all ok
if (response === undefined) {
fnPrintError("[fnLeggiStatusTermostato] ERROR response ");
} else {
let responseData = JSON.parse(response.body);
if (responseData["type"]=="cooling") {
// set a value in current shelly to define SUMMER season. (cooling mode)
fnPrintDebug("SUMMER Season");
kvsSet("par_stagione","cooling");
}
if (responseData["type"]=="heating") {
// set a value in current shelly to define WINTER season. (heating mode)
fnPrintDebug("WINTER Season");
kvsSet("par_stagione","heating");
}
}
}
}
);
}
// delay to shedule ciclic temperature poll
function fnScheduleTemperaturePoll() {
fnPrintDebug("Start watchdog timer fnTemperaturePoll");
Timer.clear(tmpTimer);
// schedule temperature poll
pingTimer_temperaturePoll = Timer.set(CONFIG.lkTimeLungo * 1000, true, fnTemperaturePoll);
// delayed start timer to schedule humidity polling
tmpTimer = Timer.set(6000, false, fnScheduleHumidityPoll);
}
function fnScheduleHumidityPoll() {
fnPrintDebug("Start watchdog timer fnHumidityPoll");
Timer.clear(tmpTimer);
// schedule humidity polling
pingTimer_humidityPoll = Timer.set(CONFIG.lkTimeLungo * 1000, true, fnHumidityPoll);
// ddelayed start timer to schedule temp/humi adjustments
tmpTimer = Timer.set(6000, false, fnScheduleTemperatureAdjust);
}
function fnScheduleTemperatureAdjust() {
fnPrintDebug("Start watchdog timer fnTemperatureAdjust");
Timer.clear(tmpTimer);
// schedule temp/humi adjustments
pingTimer_temperatureAdj = Timer.set(CONFIG.lkTimeLungo * 1000, true, fnTemperatureAdjust);
}
fnPrintDebug("Start watchdog main timer");
// schedule main polling routine (short timer)
pingTimer = Timer.set(CONFIG.lkTime * 1000, true, fnPolling);
// delayed schedule of temperature polling
tmpTimer = Timer.set(6000, false, fnScheduleTemperaturePoll);