176 lines
5.7 KiB
C++
176 lines
5.7 KiB
C++
|
#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!");
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if(data[0] != 1 && data[0] != 255){
|
||
|
ESP_LOGW(TAG, "Read status code of %d, (Operation: %d)", data[0], action);
|
||
|
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);
|
||
|
}
|
||
|
|
||
|
}
|
||
|
}
|