ESPMegaPRO-v3-SDK/ESPMegaPRO-firmware/lib/ESPMegaPRO/ClimateCard.cpp

214 lines
5.2 KiB
C++

#include <ClimateCard.hpp>
ClimateCard::ClimateCard(uint8_t ir_pin)
{
this->ir_pin = ir_pin;
// Initialize Pointers
this->dht = nullptr;
this->ds18b20 = nullptr;
this->fram = nullptr;
// Initialize Variables
this->fram_address = 0;
this->fram_auto_save = false;
this->state.ac_temperature = 0;
this->state.ac_mode = 0;
this->state.ac_fan_speed = 0;
this->humidity = 0;
this->room_temperature = 0;
// Initialize state
this->state.ac_temperature = 25;
this->state.ac_mode = 0;
this->state.ac_fan_speed = 0;
// Initialize RMT
gpio_num_t gpio_num = gpio_num_t(ir_pin);
rmt_config_t rmt_tx = RMT_DEFAULT_CONFIG_TX(gpio_num, RMT_TX_CHANNEL);
rmt_tx.clk_div = 80; // 1MHz clock
rmt_config(&rmt_tx);
rmt_driver_install(rmt_tx.channel, 0, 0);
}
ClimateCard::~ClimateCard()
{
delete dht;
delete ds18b20;
rmt_driver_uninstall(RMT_TX_CHANNEL);
}
bool ClimateCard::begin(AirConditioner ac, uint8_t sensor_type, uint8_t sensor_pin)
{
this->ac = ac;
this->sensor_type = sensor_type;
this->sensor_pin = sensor_pin;
switch (sensor_type)
{
case AC_SENSOR_TYPE_DHT22:
dht = new DHTNEW(sensor_pin);
break;
case AC_SENSOR_TYPE_DS18B20:
OneWire oneWire(sensor_pin);
ds18b20 = new DS18B20(&oneWire);
break;
}
updateAirConditioner();
}
bool ClimateCard::begin(AirConditioner ac)
{
this->begin(ac, AC_SENSOR_TYPE_NONE, 0);
}
void ClimateCard::loop()
{
static uint32_t last_sensor_update = 0;
if (millis() - last_sensor_update >= AC_SENSOR_READ_INTERVAL)
{
last_sensor_update = millis();
updateSensor();
}
}
void ClimateCard::bindFRAM(FRAM *fram, uint16_t fram_address)
{
this->fram = fram;
this->fram_address = fram_address;
}
void ClimateCard::setFRAMAutoSave(bool autoSave)
{
this->fram_auto_save = autoSave;
}
void ClimateCard::saveStateToFRAM()
{
fram->writeObject(fram_address, this->state);
}
void ClimateCard::loadStateFromFRAM()
{
fram->readObject(fram_address, this->state);
}
void ClimateCard::setTemperature(uint8_t temperature)
{
this->state.ac_temperature = temperature;
updateAirConditioner();
if (fram_auto_save)
saveStateToFRAM();
}
void ClimateCard::setMode(uint8_t mode)
{
this->state.ac_mode = mode;
updateAirConditioner();
if (fram_auto_save)
saveStateToFRAM();
}
void ClimateCard::setFanSpeed(uint8_t fan_speed)
{
this->state.ac_fan_speed = fan_speed;
updateAirConditioner();
if (fram_auto_save)
saveStateToFRAM();
}
void ClimateCard::registerChangeCallback(std::function<void(uint8_t, uint8_t, uint8_t)> callback)
{
callbacks.push_back(callback);
}
uint8_t ClimateCard::getType()
{
return CARD_TYPE_CLIMATE;
}
void ClimateCard::updateSensor()
{
if (sensor_type == AC_SENSOR_TYPE_NONE)
return;
// Read sensor data and update variables
switch (sensor_type)
{
case AC_SENSOR_TYPE_DHT22:
if (millis() - dht->lastRead() < AC_SENSOR_READ_INTERVAL)
return;
dht->read();
room_temperature = dht->getTemperature();
humidity = dht->getHumidity();
break;
case AC_SENSOR_TYPE_DS18B20:
ds18b20->requestTemperatures();
uint32_t start = millis();
while (!ds18b20->isConversionComplete())
{
if (millis() - start >= AC_SENSOR_READ_TIMEOUT)
{
return;
}
}
room_temperature = ds18b20->getTempC();
break;
}
for (uint8_t i = 0; i < sensor_callbacks.size(); i++)
{
sensor_callbacks[i](room_temperature, humidity);
}
}
void ClimateCard::updateAirConditioner()
{
size_t itemCount = sizeof(ac.infraredCodes[this->state.ac_mode][this->state.ac_fan_speed][this->state.ac_temperature]) / sizeof(ac.infraredCodes[this->state.ac_mode][this->state.ac_fan_speed][this->state.ac_temperature][0]);
rmt_item32_t items[itemCount];
// Convert IR timing array to RMT items
for (size_t i = 0; i < itemCount; i++)
{
items[i].level0 = 1;
items[i].duration0 = ac.infraredCodes[this->state.ac_mode][this->state.ac_fan_speed][this->state.ac_temperature][i];
items[i].level1 = 0;
items[i].duration1 = ac.infraredCodes[this->state.ac_mode][this->state.ac_fan_speed][this->state.ac_temperature][i];
}
// Send IR signal
rmt_write_items(RMT_TX_CHANNEL, items, itemCount, true);
rmt_wait_tx_done(RMT_TX_CHANNEL, portMAX_DELAY);
// Publish state
for (uint8_t i = 0; i < callbacks.size(); i++)
{
callbacks[i](this->state.ac_mode, this->state.ac_fan_speed, this->state.ac_temperature);
}
}
uint8_t ClimateCard::getSensorType()
{
return sensor_type;
}
float ClimateCard::getRoomTemperature()
{
return room_temperature;
}
float ClimateCard::getHumidity()
{
return humidity;
}
uint8_t ClimateCard::getTemperature()
{
return state.ac_temperature;
}
uint8_t ClimateCard::getMode()
{
return state.ac_mode;
}
uint8_t ClimateCard::getFanSpeed()
{
return state.ac_fan_speed;
}
void ClimateCard::registerSensorCallback(std::function<void(float, float)> callback)
{
sensor_callbacks.push_back(callback);
}