forked from absalom-muc/MHI-AC-Ctrl
-
Notifications
You must be signed in to change notification settings - Fork 0
/
MHI-AC-Ctrl.ino
332 lines (323 loc) · 11 KB
/
MHI-AC-Ctrl.ino
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
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
// MHI-AC-Ctrl v2.03 by absalom-muc
// read + write data via SPI controlled by MQTT
#include "MHI-AC-Ctrl-core.h"
#include "MHI-AC-Ctrl.h"
#include "support.h"
MHI_AC_Ctrl_Core mhi_ac_ctrl_core;
void MQTT_subscribe_callback(const char* topic, byte* payload, unsigned int length) {
payload[length] = 0; // we need a string
Serial.printf_P(PSTR("MQTT_subscribe_callback, topic=%s payload=%s payload_length=%i\n"), topic, (char*)payload, length);
#ifndef POWERON_WHEN_CHANGING_MODE
if (strcmp_P(topic, PSTR(MQTT_SET_PREFIX TOPIC_POWER)) == 0) {
if (strcmp_P((char*)payload, PSTR(PAYLOAD_POWER_ON)) == 0) {
mhi_ac_ctrl_core.set_power(power_on);
publish_cmd_ok();
}
else if (strcmp_P((char*)payload, PSTR(PAYLOAD_POWER_OFF)) == 0) {
mhi_ac_ctrl_core.set_power(power_off);
publish_cmd_ok();
}
else
publish_cmd_invalidparameter();
}
else
#endif
if (strcmp_P(topic, PSTR(MQTT_SET_PREFIX TOPIC_MODE)) == 0) {
#ifdef POWERON_WHEN_CHANGING_MODE
if (strcmp_P((char*)payload, PSTR(PAYLOAD_POWER_OFF)) == 0) {
mhi_ac_ctrl_core.set_power(power_off);
publish_cmd_ok();
} else
#endif
if (strcmp_P((char*)payload, PSTR(PAYLOAD_MODE_AUTO)) == 0) {
mhi_ac_ctrl_core.set_mode(mode_auto);
#ifdef POWERON_WHEN_CHANGING_MODE
mhi_ac_ctrl_core.set_power(power_on);
#endif
publish_cmd_ok();
}
else if (strcmp_P((char*)payload, PSTR(PAYLOAD_MODE_DRY)) == 0) {
mhi_ac_ctrl_core.set_mode(mode_dry);
#ifdef POWERON_WHEN_CHANGING_MODE
mhi_ac_ctrl_core.set_power(power_on);
#endif
publish_cmd_ok();
}
else if (strcmp_P((char*)payload, PSTR(PAYLOAD_MODE_COOL)) == 0) {
mhi_ac_ctrl_core.set_mode(mode_cool);
#ifdef POWERON_WHEN_CHANGING_MODE
mhi_ac_ctrl_core.set_power(power_on);
#endif
publish_cmd_ok();
}
else if (strcmp_P((char*)payload, PSTR(PAYLOAD_MODE_FAN)) == 0) {
mhi_ac_ctrl_core.set_mode(mode_fan);
#ifdef POWERON_WHEN_CHANGING_MODE
mhi_ac_ctrl_core.set_power(power_on);
#endif
publish_cmd_ok();
}
else if (strcmp_P((char*)payload, PSTR(PAYLOAD_MODE_HEAT)) == 0) {
mhi_ac_ctrl_core.set_mode(mode_heat);
#ifdef POWERON_WHEN_CHANGING_MODE
mhi_ac_ctrl_core.set_power(power_on);
#endif
publish_cmd_ok();
}
else
publish_cmd_invalidparameter();
}
else if (strcmp_P(topic, PSTR(MQTT_SET_PREFIX TOPIC_TSETPOINT)) == 0) {
if ((atoi((char*)payload) >= 18) & (atoi((char*)payload) <= 30)) {
mhi_ac_ctrl_core.set_tsetpoint(atoi((char*)payload));
publish_cmd_ok();
}
else
publish_cmd_invalidparameter();
}
else if (strcmp_P(topic, PSTR(MQTT_SET_PREFIX TOPIC_FAN)) == 0) {
if ((atoi((char*)payload) >= 1) & (atoi((char*)payload) <= 4)) {
mhi_ac_ctrl_core.set_fan(atoi((char*)payload));
publish_cmd_ok();
}
else
publish_cmd_invalidparameter();
}
else if (strcmp_P(topic, PSTR(MQTT_SET_PREFIX TOPIC_VANES)) == 0) {
if (strcmp_P((char*)payload, PSTR(PAYLOAD_VANES_SWING)) == 0) {
mhi_ac_ctrl_core.set_vanes(vanes_swing);
publish_cmd_ok();
}
else {
if ((atoi((char*)payload) >= 1) & (atoi((char*)payload) <= 5)) {
mhi_ac_ctrl_core.set_vanes(atoi((char*)payload));
publish_cmd_ok();
}
else
publish_cmd_invalidparameter();
}
}
else if (strcmp_P(topic, PSTR(MQTT_SET_PREFIX TOPIC_REQUEST_ERROPDATA)) == 0) {
mhi_ac_ctrl_core.request_ErrOpData();
publish_cmd_ok();
}
else if (strcmp_P(topic, PSTR(MQTT_SET_PREFIX TOPIC_REQUEST_RESET)) == 0) {
if (strcmp_P((char*)payload, PSTR(PAYLOAD_REQUEST_RESET)) == 0) {
publish_cmd_ok();
delay(500);
ESP.restart();
}
else
publish_cmd_invalidparameter();
}
else
publish_cmd_unknown();
}
class StatusHandler : public CallbackInterface_Status {
public:
void cbiStatusFunction(ACStatus status, int value) {
char strtmp[10];
static int mode_tmp = 0xff;
Serial.printf_P(PSTR("status=%i value=%i\n"), status, value);
switch (status) {
case status_fsck:
itoa(value, strtmp, 10);
output_P(status, PSTR(TOPIC_FSCK), strtmp);
break;
case status_fmosi:
itoa(value, strtmp, 10);
output_P(status, PSTR(TOPIC_FMOSI), strtmp);
break;
case status_fmiso:
itoa(value, strtmp, 10);
output_P(status, PSTR(TOPIC_FMISO), strtmp);
break;
case status_power:
if (value == power_on){
output_P(status, (TOPIC_POWER), PSTR(PAYLOAD_POWER_ON));
#ifdef POWERON_WHEN_CHANGING_MODE
cbiStatusFunction(status_mode, mode_tmp);
#endif
}
else {
output_P(status, (TOPIC_POWER), (PAYLOAD_POWER_OFF));
#ifdef POWERON_WHEN_CHANGING_MODE
output_P(status, PSTR(TOPIC_MODE), PSTR(PAYLOAD_MODE_OFF));
#endif
}
break;
case status_mode:
mode_tmp = value;
case opdata_mode:
case erropdata_mode:
switch (value) {
case mode_auto:
if (status != erropdata_mode)
output_P(status, PSTR(TOPIC_MODE), PSTR(PAYLOAD_MODE_AUTO));
else
output_P(status, PSTR(TOPIC_MODE), PSTR(PAYLOAD_MODE_STOP));
break;
case mode_dry:
output_P(status, PSTR(TOPIC_MODE), PSTR(PAYLOAD_MODE_DRY));
break;
case mode_cool:
output_P(status, PSTR(TOPIC_MODE), PSTR(PAYLOAD_MODE_COOL));
break;
case mode_fan:
output_P(status, PSTR(TOPIC_MODE), PSTR(PAYLOAD_MODE_FAN));
break;
case mode_heat:
output_P(status, PSTR(TOPIC_MODE), PSTR(PAYLOAD_MODE_HEAT));
break;
}
break;
case status_fan:
itoa(value + 1, strtmp, 10);
output_P(status, TOPIC_FAN, strtmp);
break;
case status_vanes:
switch (value) {
case vanes_unknown:
output_P(status, PSTR(TOPIC_VANES), PSTR(PAYLOAD_VANES_UNKNOWN));
break;
case vanes_swing:
output_P(status, PSTR(TOPIC_VANES), PSTR(PAYLOAD_VANES_SWING));
break;
default:
itoa(value, strtmp, 10);
output_P(status, PSTR(TOPIC_VANES), strtmp);
}
break;
case status_troom:
dtostrf((value - 61) / 4.0, 0, 2, strtmp);
output_P(status, PSTR(TOPIC_TROOM), strtmp);
break;
case status_tsetpoint:
case opdata_tsetpoint:
case erropdata_tsetpoint:
itoa(value, strtmp, 10);
output_P(status, PSTR(TOPIC_TSETPOINT), strtmp);
break;
case status_errorcode:
case erropdata_errorcode:
itoa(value, strtmp, 10);
output_P(status, PSTR(TOPIC_ERRORCODE), strtmp);
break;
case opdata_return_air:
case erropdata_return_air:
dtostrf(value * 0.25f - 15, 0, 2, strtmp);
output_P(status, PSTR(TOPIC_RETURNAIR), strtmp);
break;
case opdata_thi_r1:
case erropdata_thi_r1:
itoa(0.327f * value - 11.4f, strtmp, 10); // only rough approximation
output_P(status, PSTR(TOPIC_THI_R1), strtmp);
break;
case opdata_thi_r2:
case erropdata_thi_r2:
itoa(0.327f * value - 11.4f, strtmp, 10); // formula for calculation not known
output_P(status, PSTR(TOPIC_THI_R2), strtmp);
break;
case opdata_thi_r3:
case erropdata_thi_r3:
itoa(0.327f * value - 11.4f, strtmp, 10); // only rough approximation
output_P(status, PSTR(TOPIC_THI_R3), strtmp);
break;
case opdata_iu_fanspeed:
case erropdata_iu_fanspeed:
itoa(value, strtmp, 10);
output_P(status, PSTR(TOPIC_IU_FANSPEED), strtmp);
break;
case opdata_total_iu_run:
case erropdata_total_iu_run:
itoa(value * 100, strtmp, 10);
output_P(status, PSTR(TOPIC_TOTAL_IU_RUN), strtmp);
break;
case erropdata_outdoor:
case opdata_outdoor:
dtostrf((value - 94) * 0.25f, 0, 2, strtmp);
output_P(status, PSTR(TOPIC_OUTDOOR), strtmp);
break;
case opdata_tho_r1:
case erropdata_tho_r1:
itoa(0.327f * value - 11.4f, strtmp, 10); // formula for calculation not known
output_P(status, PSTR(TOPIC_THO_R1), strtmp);
break;
case opdata_comp:
case erropdata_comp:
dtostrf(highByte(value) * 25.6f + 0.1f * lowByte(value), 0, 2, strtmp); // to be confirmed
output_P(status, PSTR(TOPIC_COMP), strtmp);
break;
case erropdata_td:
case opdata_td:
if (value < 0x12)
strcpy(strtmp, "<=30");
else
itoa(value / 2 + 32, strtmp, 10);
output_P(status, PSTR(TOPIC_TD), strtmp);
break;
case opdata_ct:
case erropdata_ct:
dtostrf(value * 14 / 51.0f, 0, 2, strtmp);
output_P(status, PSTR(TOPIC_CT), strtmp);
break;
case opdata_tdsh:
itoa(value, strtmp, 10); // formula for calculation not known
output_P(status, PSTR(TOPIC_TDSH), strtmp);
break;
case opdata_protection_no:
itoa(value, strtmp, 10);
output_P(status, PSTR(TOPIC_PROTECTION_NO), strtmp);
break;
case opdata_ou_fanspeed:
case erropdata_ou_fanspeed:
itoa(value, strtmp, 10);
output_P(status, PSTR(TOPIC_OU_FANSPEED), strtmp);
break;
case opdata_defrost:
if (value)
output_P(status, PSTR(TOPIC_DEFROST), PSTR(PAYLOAD_OP_DEFROST_ON));
else
output_P(status, PSTR(TOPIC_DEFROST), PSTR(PAYLOAD_OP_DEFROST_OFF));
break;
case opdata_total_comp_run:
case erropdata_total_comp_run:
itoa(value * 100, strtmp, 10);
output_P(status, PSTR(TOPIC_TOTAL_COMP_RUN), strtmp);
break;
case opdata_ou_eev1:
case erropdata_ou_eev1:
itoa(value, strtmp, 10);
output_P(status, PSTR(TOPIC_OU_EEV1), strtmp);
break;
}
}
};
StatusHandler mhiStatusHandler;
void setup() {
Serial.begin(115200);
Serial.println();
Serial.println(F("MHI-AC-Ctrl starting"));
Serial.printf_P(PSTR("CPU frequency[Hz]=%lu\n"), F_CPU);
#if TEMP_MEASURE_PERIOD > 0
setup_ds18x20();
#endif
setupWiFi();
setupOTA();
MQTTclient.setServer(MQTT_SERVER, MQTT_PORT);
MQTTclient.setCallback(MQTT_subscribe_callback);
MQTTreconnect();
mhi_ac_ctrl_core.MHIAcCtrlStatus(&mhiStatusHandler);
mhi_ac_ctrl_core.init();
}
void loop() {
if (MQTTloop())
mhi_ac_ctrl_core.reset_old_values(); // after a reconnect
ArduinoOTA.handle();
#if TEMP_MEASURE_PERIOD > 0
getDs18x20Temperature(25);
#endif
int ret = mhi_ac_ctrl_core.loop(100);
if (ret < 0)
Serial.printf_P(PSTR("mhi_ac_ctrl_core.loop error: %i\n"), ret);
}