-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathrego600.cpp
335 lines (268 loc) · 8.52 KB
/
rego600.cpp
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
333
334
335
#include "rego600.h"
#include "rego600_definitions.h"
using namespace esphome;
using namespace esphome::uart;
#ifndef millis
#define millis(x) esphome::millis(x)
#endif
std::optional<std::vector<uint8_t>> rego600::read_serial(size_t len)
{
size_t pos = 0;
uint32_t start = millis();
if(m_last_timeout != 0)
{
if(start - m_last_timeout > m_timeout_holdoff)
{
m_last_timeout = 0;
}
else
{
return std::nullopt;
}
}
std::vector<uint8_t> result;
while (pos < len) {
if (millis() - start > m_timeout) {
m_last_timeout = millis();
return std::nullopt;
}
App.feed_wdt();
if (m_uart.available()) {
uint8_t c;
if (m_uart.read_byte(&c)) {
result.push_back(c);
pos++;
}
}
}
return result;
}
void rego600::flush_receive()
{
while (m_uart.available()) {
uint8_t c;
m_uart.read_byte(&c);
}
}
bool rego600::write_serial(const std::vector<uint8_t>& data)
{
m_uart.write_array(data);
return true;
}
int16_t rego600::read_integer(const uint8_t* data)
{
int16_t res = ((int16_t) * (data) << 14) | ((int16_t) * (data + 1) << 7) | (int16_t) * (data + 2);
return res;
}
float rego600::integer_to_float(int16_t i)
{
float temp = 0.1 * (float)i;
return temp;
}
int16_t rego600::float_to_integer(float f)
{
int16_t temp = (int16_t)(f * 10);
return temp;
}
void rego600::write_integer(int16_t val, uint8_t* data)
{
*(data + 2) = (uint8_t)val & 0x7F;
*(data + 1) = (uint8_t)(val >> 7) & 0x7F;
*data = (uint8_t)(val >> 14) & 0x03;
}
uint8_t rego600::calculate_checksum(const uint8_t* data, size_t len)
{
uint8_t result = 0;
for (size_t i = 0; i < len; i++) {
result ^= data[i];
}
return result;
}
bool rego600::read_ack_response()
{
auto response = read_serial(1);
if (!response) {
ESP_LOGE(TAG, "Timeout waiting for response");
return false;
}
auto c = response.value()[0];
if (c != PC_TARGET) {
ESP_LOGE(TAG, "Unexpected response, expected 0x01, got 0x%02x", c);
return false;
}
return true;
}
std::optional<int16_t> rego600::read_response()
{
const size_t response_length = 5;
auto response = read_serial(response_length);
if (!response) {
ESP_LOGE(TAG, "Timeout waiting for response");
return std::nullopt;
}
auto resp = response.value();
if (resp[0] != PC_TARGET) {
ESP_LOGE(TAG, "Wrong target for response, got 0x%02x", resp[0]);
return std::nullopt;
}
if (calculate_checksum(&resp[1], response_length - 1) != 0) {
ESP_LOGE(TAG, "Incorrect checksum in response");
return std::nullopt;
}
return read_integer(&resp[1]);
}
std::optional<std::vector<uint8_t>> rego600::read_long_response()
{
const size_t long_response_length = 42;
auto response = read_serial(long_response_length);
if (!response) {
ESP_LOGE(TAG, "Timeout waiting for long response");
return std::nullopt;
}
auto resp = response.value();
if (resp[0] != PC_TARGET) {
ESP_LOGE(TAG, "Wrong target for long response, got 0x%02x", resp[0]);
return std::nullopt;
}
if (calculate_checksum(&resp[1], long_response_length - 1) != 0) {
ESP_LOGE(TAG, "Incorrect checksum in long response");
return std::nullopt;
}
std::vector<uint8_t> result;
for (size_t i = 1; i < long_response_length - 1; i += 2) {
result.push_back(((resp[i] & 0xf) << 4) | (resp[i + 1] & 0xf));
}
return result;
}
std::optional<float> rego600::read_sensor_register(sensor_register_t reg)
{
auto response = run_command<FIVE_BYTE_RESPONSE>(REGO_TARGET, READ_SYSTEM_REGISTER, reg, 0);
if (!response) {
return std::nullopt;
}
return integer_to_float(response.value());
}
bool rego600::write_button_register(front_panel_button_t reg, uint16_t val)
{
return run_command<ONE_BYTE_RESPONSE>(REGO_TARGET, WRITE_FRONT_PANEL, reg, val);
}
std::optional<bool> rego600::read_light_register(front_panel_light_t reg)
{
auto response = run_command<FIVE_BYTE_RESPONSE>(REGO_TARGET, READ_FRONT_PANEL, reg, 0);
if (!response) {
return std::nullopt;
}
if (response.value()) {
return true;
} else {
return false;
}
}
std::optional<float> rego600::read_control_register(control_register_t reg)
{
auto response = run_command<FIVE_BYTE_RESPONSE>(REGO_TARGET, READ_SYSTEM_REGISTER, reg, 0);
if (!response) {
return std::nullopt;
}
return integer_to_float(response.value());
}
std::optional<std::vector<uint8_t>> rego600::read_display_line(uint8_t line)
{
if(line > 3)
{
ESP_LOGE(TAG, "Read from invalid display line");
return std::nullopt;
}
return run_command<FOURTYTWO_BYTE_RESPONSE>(REGO_TARGET, READ_DISPLAY, line, line);
}
bool rego600::write_control_register(control_register_t reg, float val)
{
int16_t tmp = float_to_integer(val);
return run_command<ONE_BYTE_RESPONSE>(REGO_TARGET, WRITE_SYSTEM_REGISTER, reg, tmp);
}
bool rego600::press_button(front_panel_button_t button)
{
front_panel_button_t reg;
int16_t val;
if (button == WHEEL_LEFT) {
reg = WHEEL;
val = WHEEL_LEFT_VALUE;
} else if (button == WHEEL_RIGHT) {
reg = WHEEL;
val = WHEEL_RIGHT_VALUE;
} else {
reg = button;
val = 0x0001;
}
if (!write_button_register(reg, val)) {
ESP_LOGE(TAG, "Failed to send command");
}
return true;
}
std::optional<bool> rego600::read_panel_light(front_panel_light_t reg)
{
auto response = read_light_register(reg);
if (!response) {
return std::nullopt;
} else {
if (response.value()) {
return true;
} else {
return false;
}
}
}
std::optional<int16_t> rego600::read_status(status_register_t reg)
{
return run_command<FIVE_BYTE_RESPONSE>(REGO_TARGET, READ_SYSTEM_REGISTER, reg, 0);
}
std::optional<float> rego600::read_decimal_sensor(sensor_register_t reg) { return read_sensor_register(reg); }
temperatures_t rego600::read_all_sensors()
{
temperatures_t temps;
temps.radiator_return = read_decimal_sensor(RADIATOR_RETURN_TEMPERATURE);
temps.outdoor = read_decimal_sensor(OUTDOOR_TEMPERATURE);
temps.indoor = read_decimal_sensor(ROOM_TEMPERATURE);
temps.warm_water = read_decimal_sensor(WARM_WATER_TEMPERATURE);
temps.radiator_forward = read_decimal_sensor(RADIATOR_FORWARD_TEMPERATURE);
temps.heat_fluid_in = read_decimal_sensor(HEAT_FLUID_IN_TEMPERATURE);
temps.heat_fluid_out = read_decimal_sensor(HEAT_FLUID_OUT_TEMPERATURE);
temps.cold_fluid_in = read_decimal_sensor(COLD_FLUID_IN_TEMPERATURE);
temps.cold_fluid_out = read_decimal_sensor(COLD_FLUID_OUT_TEMPERATURE);
temps.compressor = read_decimal_sensor(COMPRESSOR_TEMPERATURE);
return temps;
}
targets_t rego600::read_all_targets()
{
targets_t targets;
targets.radiator_return_target = read_decimal_sensor(RADIATOR_RETURN_TARGET_TEMPERATURE);
targets.radiator_return_on = read_decimal_sensor(RADIATOR_RETURN_ON_TEMPERATURE);
targets.radiator_return_off = read_decimal_sensor(RADIATOR_RETURN_OFF_TEMPERATURE);
targets.warm_water_target = read_decimal_sensor(WARM_WATER_TARGET_TEMPERATURE);
targets.warm_water_on = read_decimal_sensor(WARM_WATER_ON_TEMPERATURE);
targets.warm_water_off = read_decimal_sensor(WARM_WATER_OFF_TEMPERATURE);
targets.add_heat_percentage = read_decimal_sensor(ADD_HEAT_PERCENTAGE);
return targets;
}
std::optional<std::vector<std::string>> rego600::read_display()
{
auto l1 = read_display_line(0);
auto l2 = read_display_line(1);
auto l3 = read_display_line(2);
auto l4 = read_display_line(3);
if(!l1.has_value() || !l2.has_value() || !l3.has_value() || !l4.has_value())
{
ESP_LOGE(TAG, "Failed to read display line");
return std::nullopt;
}
auto line1 = l1.value();
auto line2 = l2.value();
auto line3 = l3.value();
auto line4 = l4.value();
std::vector<std::string> result;
result.push_back(std::string(line1.begin(), line1.end()));
result.push_back(std::string(line2.begin(), line2.end()));
result.push_back(std::string(line3.begin(), line3.end()));
result.push_back(std::string(line4.begin(), line4.end()));
return result;
}