-
Notifications
You must be signed in to change notification settings - Fork 0
/
HeatPump.h
235 lines (203 loc) · 9.37 KB
/
HeatPump.h
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
/*
HeatPump.h - Mitsubishi Heat Pump control library for Arduino
Copyright (c) 2017 Al Betschart. All right reserved.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __HeatPump_H__
#define __HeatPump_H__
#include <stdint.h>
#include <WString.h>
#include <math.h>
#include <HardwareSerial.h>
#if defined(ARDUINO) && ARDUINO >= 100
#include "Arduino.h"
#else
#include "WProgram.h"
#endif
/*
* Callback function definitions. Code differs for the ESP8266 platform, which requires the functional library.
* Based on callback implementation in the Arduino Client for MQTT library (https://github.com/knolleary/pubsubclient)
*/
#ifdef ESP8266
#include <functional>
#define ON_CONNECT_CALLBACK_SIGNATURE std::function<void()> onConnectCallback
#define SETTINGS_CHANGED_CALLBACK_SIGNATURE std::function<void()> settingsChangedCallback
#define STATUS_CHANGED_CALLBACK_SIGNATURE std::function<void(heatpumpStatus newStatus)> statusChangedCallback
#define PACKET_CALLBACK_SIGNATURE std::function<void(byte* packet, unsigned int length, char* packetDirection)> packetCallback
#define ROOM_TEMP_CHANGED_CALLBACK_SIGNATURE std::function<void(float currentRoomTemperature)> roomTempChangedCallback
#else
#define ON_CONNECT_CALLBACK_SIGNATURE void (*onConnectCallback)()
#define SETTINGS_CHANGED_CALLBACK_SIGNATURE void (*settingsChangedCallback)()
#define STATUS_CHANGED_CALLBACK_SIGNATURE void (*statusChangedCallback)(heatpumpStatus newStatus)
#define PACKET_CALLBACK_SIGNATURE void (*packetCallback)(byte* packet, unsigned int length, char* packetDirection)
#define ROOM_TEMP_CHANGED_CALLBACK_SIGNATURE void (*roomTempChangedCallback)(float currentRoomTemperature)
#endif
typedef uint8_t byte;
struct heatpumpSettings {
String power;
String mode;
float temperature;
String fan;
String vane; //vertical vane, up/down
String wideVane; //horizontal vane, left/right
bool iSee; //iSee sensor, at the moment can only detect it, not set it
bool connected;
};
bool operator==(const heatpumpSettings& lhs, const heatpumpSettings& rhs);
bool operator!=(const heatpumpSettings& lhs, const heatpumpSettings& rhs);
struct heatpumpTimers {
String mode;
int onMinutesSet;
int onMinutesRemaining;
int offMinutesSet;
int offMinutesRemaining;
};
bool operator==(const heatpumpTimers& lhs, const heatpumpTimers& rhs);
bool operator!=(const heatpumpTimers& lhs, const heatpumpTimers& rhs);
struct heatpumpStatus {
float roomTemperature;
bool operating; // if true, the heatpump is operating to reach the desired temperature
heatpumpTimers timers;
};
class HeatPump
{
private:
static const int PACKET_LEN = 22;
static const int PACKET_SENT_INTERVAL_MS = 100; //was 1000 bhc
static const int PACKET_INFO_INTERVAL_MS = 50; //was 2000 bhc
static const int PACKET_TYPE_DEFAULT = 99;
static const int CONNECT_LEN = 8;
const byte CONNECT[CONNECT_LEN] = {0xfc, 0x5a, 0x01, 0x30, 0x02, 0xca, 0x01, 0xa8};
static const int HEADER_LEN = 8;
const byte HEADER[HEADER_LEN] = {0xfc, 0x41, 0x01, 0x30, 0x10, 0x01, 0x00, 0x00};
const byte INFOHEADER[5] = {0xfc, 0x42, 0x01, 0x30, 0x10};
static const int INFOHEADER_LEN = 5;
static const int INFOMODE_LEN = 6;
const byte INFOMODE[INFOMODE_LEN] = {
0x02, // request a settings packet - RQST_PKT_SETTINGS
0x03, // request the current room temp - RQST_PKT_ROOM_TEMP
0x04, // unknown
0x05, // request the timers - RQST_PKT_TIMERS
0x06, // request status - RQST_PKT_STATUS
0x09 // request standby mode (maybe?) RQST_PKT_STANDBY
};
const int RCVD_PKT_FAIL = 0;
const int RCVD_PKT_CONNECT_SUCCESS = 1;
const int RCVD_PKT_SETTINGS = 2;
const int RCVD_PKT_ROOM_TEMP = 3;
const int RCVD_PKT_UPDATE_SUCCESS = 4;
const int RCVD_PKT_STATUS = 5;
const int RCVD_PKT_TIMER = 6;
const byte CONTROL_PACKET_1[5] = {0x01, 0x02, 0x04, 0x08, 0x10};
//{"POWER","MODE","TEMP","FAN","VANE"};
const byte CONTROL_PACKET_2[1] = {0x01};
//{"WIDEVANE"};
const byte POWER[2] = {0x00, 0x01};
const String POWER_MAP[2] = {"OFF", "ON"};
const byte MODE[5] = {0x01, 0x02, 0x03, 0x07, 0x08};
const String MODE_MAP[5] = {"HEAT", "DRY", "COOL", "FAN", "AUTO"};
const byte TEMP[16] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f};
const int TEMP_MAP[16] = {31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16};
const byte FAN[6] = {0x00, 0x01, 0x02, 0x03, 0x05, 0x06};
const String FAN_MAP[6] = {"AUTO", "QUIET", "1", "2", "3", "4"};
const byte VANE[7] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x07};
const String VANE_MAP[7] = {"AUTO", "1", "2", "3", "4", "5", "SWING"};
const byte WIDEVANE[7] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x08, 0x0c};
const String WIDEVANE_MAP[7] = {"<<", "<", "|", ">", ">>", "<>", "SWING"};
const byte ROOM_TEMP[32] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f};
const int ROOM_TEMP_MAP[32] = {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};
const byte TIMER_MODE[4] = {0x00, 0x01, 0x02, 0x03};
const String TIMER_MODE_MAP[4] = {"NONE", "OFF", "ON", "BOTH"};
static const int TIMER_INCREMENT_MINUTES = 10;
// these settings will be initialised in connect()
heatpumpSettings currentSettings;
heatpumpSettings wantedSettings;
heatpumpStatus currentStatus;
HardwareSerial * _HardSerial;
unsigned long lastSend;
int infoMode;
unsigned long lastRecv;
bool autoUpdate;
bool firstRun;
bool tempMode;
bool externalUpdate;
bool connected = false;
String lookupByteMapValue(const String valuesMap[], const byte byteMap[], int len, byte byteValue);
int lookupByteMapValue(const int valuesMap[], const byte byteMap[], int len, byte byteValue);
int lookupByteMapIndex(const String valuesMap[], int len, String lookupValue);
int lookupByteMapIndex(const int valuesMap[], int len, int lookupValue);
bool canSend(bool isInfo);
byte checkSum(byte bytes[], int len);
void createPacket(byte *packet, heatpumpSettings settings);
void createInfoPacket(byte *packet, byte packetType);
int readPacket();
void writePacket(byte *packet, int length);
// callbacks
ON_CONNECT_CALLBACK_SIGNATURE;
SETTINGS_CHANGED_CALLBACK_SIGNATURE;
STATUS_CHANGED_CALLBACK_SIGNATURE;
PACKET_CALLBACK_SIGNATURE;
ROOM_TEMP_CHANGED_CALLBACK_SIGNATURE;
public:
// indexes for INFOMODE array (public so they can be optionally passed to sync())
const int RQST_PKT_SETTINGS = 0;
const int RQST_PKT_ROOM_TEMP = 1;
const int RQST_PKT_TIMERS = 2;
const int RQST_PKT_STATUS = 3;
const int RQST_PKT_STANDBY = 4;
// general
HeatPump();
bool connect(HardwareSerial *serial);
bool update();
void sync(byte packetType = PACKET_TYPE_DEFAULT);
void enableExternalUpdate();
void enableAutoUpdate();
void disableAutoUpdate();
// settings
heatpumpSettings getSettings();
void setSettings(heatpumpSettings settings);
void setPowerSetting(bool setting);
bool getPowerSettingBool();
String getPowerSetting();
void setPowerSetting(String setting);
String getModeSetting();
void setModeSetting(String setting);
float getTemperature();
void setTemperature(float setting);
void setRemoteTemperature(float setting);
String getFanSpeed();
void setFanSpeed(String setting);
String getVaneSetting();
void setVaneSetting(String setting);
String getWideVaneSetting();
void setWideVaneSetting(String setting);
bool getIseeBool();
// status
heatpumpStatus getStatus();
float getRoomTemperature();
bool getOperating();
// helpers
float FahrenheitToCelsius(int tempF);
int CelsiusToFahrenheit(float tempC);
// callbacks
void setOnConnectCallback(ON_CONNECT_CALLBACK_SIGNATURE);
void setSettingsChangedCallback(SETTINGS_CHANGED_CALLBACK_SIGNATURE);
void setStatusChangedCallback(STATUS_CHANGED_CALLBACK_SIGNATURE);
void setPacketCallback(PACKET_CALLBACK_SIGNATURE);
void setRoomTempChangedCallback(ROOM_TEMP_CHANGED_CALLBACK_SIGNATURE); // need to deprecate this, is available from setStatusChangedCallback
// expert users only!
void sendCustomPacket(byte data[], int len);
};
#endif