mirror of
https://github.com/Laxilef/OTGateway.git
synced 2025-12-13 19:54:28 +05:00
196 lines
5.3 KiB
C++
196 lines
5.3 KiB
C++
#include <Arduino.h>
|
|
#include <OpenTherm.h>
|
|
|
|
class CustomOpenTherm : public OpenTherm {
|
|
public:
|
|
typedef std::function<void(unsigned int)> DelayCallback;
|
|
typedef std::function<void(unsigned long, uint8_t)> BeforeSendRequestCallback;
|
|
typedef std::function<void(unsigned long, unsigned long, OpenThermResponseStatus, uint8_t)> AfterSendRequestCallback;
|
|
|
|
CustomOpenTherm(int inPin = 4, int outPin = 5, bool isSlave = false, bool alwaysReceive = false) : OpenTherm(inPin, outPin, isSlave, alwaysReceive) {}
|
|
~CustomOpenTherm() {}
|
|
|
|
CustomOpenTherm* setDelayCallback(DelayCallback callback = nullptr) {
|
|
this->delayCallback = callback;
|
|
|
|
return this;
|
|
}
|
|
|
|
CustomOpenTherm* setBeforeSendRequestCallback(BeforeSendRequestCallback callback = nullptr) {
|
|
this->beforeSendRequestCallback = callback;
|
|
|
|
return this;
|
|
}
|
|
|
|
CustomOpenTherm* setAfterSendRequestCallback(AfterSendRequestCallback callback = nullptr) {
|
|
this->afterSendRequestCallback = callback;
|
|
|
|
return this;
|
|
}
|
|
|
|
unsigned long sendRequest(unsigned long request) override {
|
|
this->sendRequestAttempt++;
|
|
|
|
while (!this->isReady()) {
|
|
if (this->delayCallback) {
|
|
this->delayCallback(150);
|
|
}
|
|
|
|
this->process();
|
|
}
|
|
|
|
if (this->beforeSendRequestCallback) {
|
|
this->beforeSendRequestCallback(request, this->sendRequestAttempt);
|
|
}
|
|
|
|
if (this->sendRequestAsync(request)) {
|
|
do {
|
|
if (this->delayCallback) {
|
|
this->delayCallback(150);
|
|
}
|
|
|
|
this->process();
|
|
} while (this->status != OpenThermStatus::READY && this->status != OpenThermStatus::DELAY);
|
|
}
|
|
|
|
if (this->afterSendRequestCallback) {
|
|
this->afterSendRequestCallback(request, this->response, this->responseStatus, this->sendRequestAttempt);
|
|
}
|
|
|
|
if (this->responseStatus == OpenThermResponseStatus::SUCCESS || this->responseStatus == OpenThermResponseStatus::INVALID) {
|
|
this->sendRequestAttempt = 0;
|
|
return this->response;
|
|
|
|
} else if (this->sendRequestAttempt >= this->sendRequestMaxAttempts) {
|
|
this->sendRequestAttempt = 0;
|
|
return this->response;
|
|
|
|
} else {
|
|
return this->sendRequest(request);
|
|
}
|
|
}
|
|
|
|
inline auto sendBoilerReset() {
|
|
return this->sendRequestCode(1);
|
|
}
|
|
|
|
inline auto sendServiceReset() {
|
|
return this->sendRequestCode(10);
|
|
}
|
|
|
|
inline auto sendWaterFilling() {
|
|
return this->sendRequestCode(2);
|
|
}
|
|
|
|
bool sendRequestCode(const uint8_t requestCode) {
|
|
unsigned long response = this->sendRequest(buildRequest(
|
|
OpenThermMessageType::WRITE_DATA,
|
|
OpenThermMessageID::RemoteRequest,
|
|
static_cast<unsigned int>(requestCode) << 8
|
|
));
|
|
|
|
if (!isValidResponse(response) || !isValidResponseId(response, OpenThermMessageID::RemoteRequest)) {
|
|
return false;
|
|
}
|
|
|
|
const uint8_t responseRequestCode = (response & 0xFFFF) >> 8;
|
|
const uint8_t responseCode = response & 0xFF;
|
|
if (responseRequestCode != requestCode || responseCode < 128) {
|
|
return false;
|
|
}
|
|
|
|
// reset
|
|
this->sendRequest(buildRequest(
|
|
OpenThermMessageType::WRITE_DATA,
|
|
OpenThermMessageID::RemoteRequest,
|
|
0u << 8
|
|
));
|
|
|
|
return true;
|
|
}
|
|
|
|
bool getStr(OpenThermMessageID id, char* buffer, uint16_t length = 50) {
|
|
if (buffer == nullptr || length == 0) {
|
|
return false;
|
|
}
|
|
|
|
unsigned long response;
|
|
uint8_t index = 0;
|
|
uint8_t maxIndex = 255;
|
|
|
|
while (index <= maxIndex && index < length) {
|
|
response = this->sendRequest(buildRequest(
|
|
OpenThermMessageType::READ_DATA,
|
|
id,
|
|
static_cast<unsigned int>(index) << 8
|
|
));
|
|
|
|
if (!isValidResponse(response) || !isValidResponseId(response, id)) {
|
|
break;
|
|
}
|
|
|
|
const uint8_t character = response & 0xFF;
|
|
if (character == 0) {
|
|
break;
|
|
}
|
|
|
|
if (index == 0) {
|
|
maxIndex = (response & 0xFFFF) >> 8;
|
|
}
|
|
|
|
buffer[index++] = static_cast<char>(character);
|
|
}
|
|
|
|
buffer[index] = '\0';
|
|
return index > 0;
|
|
}
|
|
|
|
static bool isCh2Active(unsigned long response) {
|
|
return response & 0x20;
|
|
}
|
|
|
|
static bool isValidResponseId(unsigned long response, OpenThermMessageID id) {
|
|
const uint8_t responseId = (response >> 16) & 0xFF;
|
|
|
|
return static_cast<uint8_t>(id) == responseId;
|
|
}
|
|
|
|
static uint8_t getResponseMessageTypeId(unsigned long response) {
|
|
return (response << 1) >> 29;
|
|
}
|
|
|
|
static const char* getResponseMessageTypeString(unsigned long response) {
|
|
uint8_t msgType = getResponseMessageTypeId(response);
|
|
|
|
switch (msgType) {
|
|
case static_cast<uint8_t>(OpenThermMessageType::READ_ACK):
|
|
case static_cast<uint8_t>(OpenThermMessageType::WRITE_ACK):
|
|
case static_cast<uint8_t>(OpenThermMessageType::DATA_INVALID):
|
|
case static_cast<uint8_t>(OpenThermMessageType::UNKNOWN_DATA_ID):
|
|
return CustomOpenTherm::messageTypeToString(
|
|
static_cast<OpenThermMessageType>(msgType)
|
|
);
|
|
|
|
default:
|
|
return "UNKNOWN";
|
|
}
|
|
}
|
|
|
|
// converters
|
|
template <class T>
|
|
static unsigned int toFloat(const T val) {
|
|
return (unsigned int)(val * 256);
|
|
}
|
|
|
|
static short getInt(const unsigned long response) {
|
|
return response & 0xffff;
|
|
}
|
|
|
|
protected:
|
|
const uint8_t sendRequestMaxAttempts = 5;
|
|
uint8_t sendRequestAttempt = 0;
|
|
DelayCallback delayCallback;
|
|
BeforeSendRequestCallback beforeSendRequestCallback;
|
|
AfterSendRequestCallback afterSendRequestCallback;
|
|
};
|