espHome-NBS-files/external_components/ezo_orp_i2c/ezo_orp.cpp

180 lines
5.8 KiB
C++
Raw Permalink Normal View History

#include "ezo_orp.h"
namespace esphome {
namespace ezo_orp_i2c {
static const char *const TAG = "ezo_orp_i2c.sensor";
static const uint8_t COMMAND_READ[] = {0x52}; // R
static const uint8_t COMMAND_PERFERM_CALIBRATION[] = {0x43, 0x61, 0x6C}; //Cal
static const uint8_t COMMAND_IS_CALIBRATED[] = {0x43, 0x61, 0x6C, 0x2C, 0x3F}; //Cal
static const uint8_t COMMAND_EXPORT_CALIBRATION[] = {0x45, 0x78, 0x70, 0x6F, 0x72, 0x74}; // Export
static const uint8_t COMMAND_INFORMATION[] = {0x69}; // i (DON'T ASK ME WHY THAT IS ONLY A SMALL LETTER
static const uint8_t COMMAND_STATUS[] = {0x53, 0x74, 0x61, 0x74, 0x75, 0x73}; // STATUS
static const uint8_t COMMAND_FACTORY_RESET[] = {0x46, 0x61, 0x63, 0x74, 0x6F, 0x72, 0x79}; // Factory
static const uint8_t COMMMAND_TO_ARGS_SEPERATOR = {0x2C};
static const int PROCESSING_DELAY_MS = 300; // FOR SOME OPERATIONS
static const int READING_DELAY_MS = 900; // FOR BASICALLY EVERYTHING WHERE LARGE DATA IS READ/SENT
void EzoOrpSensor::setup(){
ESP_LOGCONFIG(TAG, "Setting up EzoOrpI2C '%s'...", this->get_name().c_str());
ESP_LOGCONFIG(TAG, "EzoOrpI2C '%s' setup finished!", this->get_name().c_str());
scheduleNextAction(SensorAction::IS_CALIBRATED, nullptr, 0, 450);
}
void EzoOrpSensor::update() {
scheduleNextAction(SensorAction::READ, nullptr, 0, 900);
}
void EzoOrpSensor::read_response(int maxLength, SensorAction action) {
uint8_t data[maxLength];
if(SensorAction::CALIBRATE == action){
ESP_LOGD(TAG, "Device Calibrated");
busy_ = false;
runScheduledAction();
return;
}
if(i2c::ERROR_OK != this->read(data, maxLength)){
ESP_LOGW(TAG, "Error Occured while reading respnse!");
busy_ = false;
runScheduledAction();
return;
}
if(data[0] != 1 && data[0] != 255){
ESP_LOGW(TAG, "Read status code of %d, (Operation: %d)", data[0], action);
busy_ = false;
runScheduledAction();
return;
}
if(SensorAction::READ == action){
float value;
sscanf((const char*) &data[1], "%f", &value);
this->publish_state(value);
}
else if(SensorAction::IS_CALIBRATED == action){
ESP_LOGD(TAG, "%s", data[6] == 0x31 ? "Device has been calibrated" : "Device has NOT been calibrated");
}
else if(SensorAction::INFORMATION == action){
ESP_LOGD(TAG, "Device Printed the following information: %s", &data[1]);
}
busy_ = false;
runScheduledAction();
}
void EzoOrpSensor::calibrate_to_target(int target){
char targetArray[3];
sprintf(targetArray, "%d", target);
ESP_LOGD(TAG, "Calibrating to: %3s", targetArray);
scheduleNextAction(SensorAction::CALIBRATE, (uint8_t*) &targetArray, 3, 4000);
}
float EzoOrpSensor::get_setup_priority() const { return setup_priority::DATA; }
void EzoOrpSensor::dump_config(){
LOG_SENSOR("", "EzoOrpI2C Sensor", this);
LOG_UPDATE_INTERVAL(this);
LOG_I2C_DEVICE(this);
}
bool EzoOrpSensor::is_busy(){
return this->busy_;
}
void EzoOrpSensor::runScheduledAction(){
if(scheduledAction_ == SensorAction::NOTHING) return;
scheduleNextAction(scheduledAction_, scheduledActionData_, scheduledActionDataSize_, scheduledActionTime_);
scheduledAction_ = SensorAction::NOTHING;
scheduledActionDataSize_ = 0;
}
void EzoOrpSensor::scheduleNextAction(SensorAction action, uint8_t* data, int size, int expected_response_time){
if(busy_){
if(scheduledAction_ == action) return; // Queued Action cannot has no need of being repeated;
if(scheduledAction_ != SensorAction::NOTHING) return; // Ehh... Felt better lol
scheduledAction_ = action;
if(data != nullptr){
for(int i = 0;i < size; ++i){
scheduledActionData_[i] = data[i];
}
}
scheduledActionDataSize_ = size;
scheduledActionTime_ = expected_response_time;
return;
}
switch(action){
case SensorAction::NOTHING:
return;
case SensorAction::READ:
busy_ = true;
send_command(COMMAND_READ, sizeof(COMMAND_READ));
this->set_timeout(expected_response_time, [this](){ this->read_response(9, SensorAction::READ); });
break;
case SensorAction::CALIBRATE:
busy_ = true;
send_command(COMMAND_PERFERM_CALIBRATION, sizeof(COMMAND_PERFERM_CALIBRATION), scheduledActionData_, scheduledActionDataSize_);
this->set_timeout(expected_response_time, [this](){ this->read_response(2, SensorAction::CALIBRATE); });
break;
case SensorAction::IS_CALIBRATED:
busy_ = true;
send_command(COMMAND_IS_CALIBRATED, sizeof(COMMAND_IS_CALIBRATED));
this->set_timeout(expected_response_time, [this](){ this->read_response(8, SensorAction::IS_CALIBRATED); });
break;
case SensorAction::INFORMATION:
busy_ = true;
send_command(COMMAND_STATUS, sizeof(COMMAND_STATUS));
this->set_timeout(expected_response_time, [this](){ this->read_response(18, SensorAction::INFORMATION); });
break;
default:
break;
}
}
bool EzoOrpSensor::send_command(const uint8_t* data, size_t dataSize){
return send_command(data, dataSize, nullptr, 0);
}
bool EzoOrpSensor::send_command(const uint8_t* data, size_t dataSize, const uint8_t* parameterData, size_t parameterSize){
if(parameterData == nullptr){
if(i2c::ERROR_OK != this->write(data, dataSize)){
ESP_LOGW(TAG, "send_command failed writing data!");
return false;
}
return true;
}
uint8_t completeData[dataSize + 1 + parameterSize];
for(int i = 0;i < dataSize; ++i){
completeData[i] = data[i];
}
completeData[dataSize++] = COMMMAND_TO_ARGS_SEPERATOR;
for(int i = 0; i < parameterSize; ++i){
completeData[dataSize + i] = parameterData[i];
}
if(i2c::ERROR_OK != this->write(completeData, sizeof(completeData))){
ESP_LOGW(TAG, "send_command failed writing data!");
return false;
}
return true;
}
void EzoOrpSensor::print_info(){
scheduleNextAction(SensorAction::INFORMATION, nullptr, 0, 300);
}
}
}