551 lines
18 KiB
C++
551 lines
18 KiB
C++
#include "tw7100.h"
|
|
#include "esphome/core/log.h"
|
|
#include "esphome/core/defines.h"
|
|
#include "esphome/core/helpers.h"
|
|
#include "esphome/components/uart/uart.h"
|
|
|
|
#ifdef USE_SELECT
|
|
#include "select/tw7100_select.h"
|
|
#endif
|
|
|
|
namespace esphome {
|
|
namespace tw7100 {
|
|
|
|
bool powered = false;
|
|
bool waiting_for_answer = false;
|
|
bool waiting_for_error_report = false;
|
|
unsigned long waiting_for_answer_since = 0;
|
|
std::deque<std::string> cmd_queue;
|
|
unsigned long last_set_cmd_timestamp;
|
|
|
|
std::vector<std::string> pwr_off_query_cmds{
|
|
"PWR?",
|
|
#ifdef USE_SENSOR
|
|
"LAMP?"
|
|
#endif
|
|
};
|
|
std::vector<std::string> pwr_on_query_cmds{
|
|
#ifdef USE_SENSOR
|
|
"SIGNAL?",
|
|
#endif
|
|
#ifdef USE_NUMBER
|
|
"VOL?",
|
|
"VKEYSTONE?",
|
|
"HKEYSTONE?",
|
|
"BRIGHT?",
|
|
"CONTRAST?",
|
|
"DENSITY?",
|
|
"TINT?",
|
|
"CTEMP?",
|
|
"FCOLOR?",
|
|
"NRS?",
|
|
"MPEGNRS?",
|
|
"OFFSETR?",
|
|
"OFFSETG?",
|
|
"OFFSETB?",
|
|
"GAINR?",
|
|
"GAING?",
|
|
"GAINB?",
|
|
"SHRF?",
|
|
"SHRS?",
|
|
"DERANGE?",
|
|
"DESTRENGTH?",
|
|
#endif
|
|
#ifdef USE_SWITCH
|
|
"BTAUDIO?",
|
|
"4KENHANCE?",
|
|
"IMGPROC?",
|
|
"AUDIOOUT?",
|
|
"HREVERSE?",
|
|
"VREVERSE?",
|
|
"ILLUM?",
|
|
"STANDBYCONF?",
|
|
"AUTOHOME?",
|
|
"WLPWR?",
|
|
"LOGTO?",
|
|
"MUTE?",
|
|
#endif
|
|
#ifdef USE_SELECT
|
|
"LUMINANCE?",
|
|
"SOURCE?",
|
|
"ASPECT?",
|
|
"OVSCAN?",
|
|
"CMODE?",
|
|
"GAMMA?",
|
|
"IMGPRESET?",
|
|
"MCFI?",
|
|
"CLRSPACE?",
|
|
"DYNRANGE?",
|
|
"MSEL?",
|
|
"SPEED?",
|
|
#endif
|
|
// TODO:
|
|
// "HDRPQ?", // number 01-16
|
|
// "HDRHLG?", // number 01-16
|
|
// "CSEL?",
|
|
|
|
// "SNO?" // Pushed on demand if sensor value is empty (e.g. after boot-up)
|
|
/*
|
|
"PRODUCT?", // produces ERR
|
|
"SOURCELIST?" // Parser present in git history but removed until esphome can update selects after api connections are established
|
|
"SOURCELISTA?", // same as SOURCELIST
|
|
"QC?",
|
|
"CORRECTMET?",
|
|
*/
|
|
};
|
|
|
|
void tw7100Component::setup() {
|
|
static const char *const TAG = "setup()";
|
|
ESP_LOGV(TAG, "SETUP");
|
|
#ifdef USE_SELECT
|
|
if (source_select_) source_select_->setup();
|
|
if (luminance_select_) luminance_select_->setup();
|
|
if (aspect_select_) aspect_select_->setup();
|
|
if (cmode_select_) cmode_select_->setup();
|
|
if (gamma_select_) gamma_select_->setup();
|
|
if (imgpreset_select_) imgpreset_select_->setup();
|
|
if (mcfi_select_) mcfi_select_->setup();
|
|
if (ovscan_select_) ovscan_select_->setup();
|
|
if (clrspace_select_) clrspace_select_->setup();
|
|
if (dynrange_select_) dynrange_select_->setup();
|
|
if (msel_select_) msel_select_->setup();
|
|
if (speed_select_) speed_select_->setup();
|
|
#endif
|
|
};
|
|
|
|
void tw7100Component::update() {
|
|
static const char *const TAG = "update()";
|
|
if (cmd_queue.empty()) {
|
|
for (auto &cmd : pwr_off_query_cmds) {
|
|
cmd_queue.push_back(cmd);
|
|
}
|
|
if (powered) {
|
|
#ifdef USE_TEXT_SENSOR
|
|
if (this->serial_->state.length() < 1) {
|
|
cmd_queue.push_back("SNO?");
|
|
}
|
|
#endif
|
|
for (auto &cmd : pwr_on_query_cmds) {
|
|
cmd_queue.push_back(cmd);
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
void tw7100Component::loop() {
|
|
static const char *const TAG = "loop()";
|
|
unsigned long _startMillis; // used for timeout measurement
|
|
|
|
_startMillis = millis();
|
|
do {
|
|
std::string response = readStringUntil(':');
|
|
|
|
if (response == "") { // no response on bus, we can use our time to do something else
|
|
if (!cmd_queue.empty() && !waiting_for_answer && (millis() - last_set_cmd_timestamp > std::max(_timeout_after_cmd, _specialTimeoutMillis))) {
|
|
std::string cmd = cmd_queue.front();
|
|
cmd_queue.pop_front();
|
|
ESP_LOGV(TAG, "sending out command: %s", cmd.c_str());
|
|
write_str((cmd + "\r\n").c_str());
|
|
flush();
|
|
if (cmd.find("?") != std::string::npos) { // only wait for response on CMD? requests
|
|
_specialTimeoutMillis = 0;
|
|
waiting_for_answer = true;
|
|
waiting_for_answer_since = millis();
|
|
} else {
|
|
last_set_cmd_timestamp = millis();
|
|
}
|
|
}
|
|
if (waiting_for_answer && (millis() - waiting_for_answer_since > 1000)) {
|
|
ESP_LOGE(TAG, "no response for last request since 1000ms, timing out!");
|
|
waiting_for_answer = false;
|
|
}
|
|
} else { // response found, handle eventual errors
|
|
ESP_LOGV(TAG, "buffer content: %s", response.c_str());
|
|
std::pair<std::string, std::string> parsed_response = parse_response(response);
|
|
if (parsed_response.first == "ERR" && parsed_response.second == "ERR") {
|
|
if (powered && !waiting_for_error_report) {
|
|
ESP_LOGW(TAG, "found ERR response, pushing request to fetch full error");
|
|
waiting_for_error_report = true;
|
|
cmd_queue.push_front("ERR?");
|
|
} else {
|
|
ESP_LOGW(TAG, "got ERR while projector is off or waiting for a previous error report");
|
|
}
|
|
} else if (parsed_response.first == "ERR") {
|
|
waiting_for_error_report = false;
|
|
ESP_LOGE(TAG, "found ERR report, reason is: %s", parsed_response.second.c_str());
|
|
// TODO: Handle error
|
|
} else {
|
|
update_sensor(parsed_response);
|
|
}
|
|
waiting_for_answer = false;
|
|
}
|
|
//ESP_LOGV(TAG, "read processing finished");
|
|
} while (millis() - _startMillis < _max_loop_time);
|
|
//ESP_LOGV(TAG, "inner timed loop done");
|
|
};
|
|
|
|
void tw7100Component::dump_config() {
|
|
static const char *const TAG = "dump_config()";
|
|
ESP_LOGCONFIG(TAG, "TW7100:");
|
|
this->check_uart_settings(9600);
|
|
};
|
|
|
|
void tw7100Component::push_cmd(std::string cmd, std::string param) {
|
|
static const char *const TAG = "push_cmd()";
|
|
if (powered) {
|
|
if (cmd == "PWR" && param == "OFF") {
|
|
_specialTimeoutMillis = 5000; // time to wait after PWR OFF until projector responds again
|
|
cmd_queue.clear(); // clear eventual existing query commands to avoid errors
|
|
}
|
|
if ((cmd == "SOURCE")||(cmd == "MUTE")) {
|
|
_specialTimeoutMillis = 4000; // time to wait after source change or AV mute
|
|
}
|
|
ESP_LOGV(TAG, "pushing priority cmd (%s) from external component", cmd.c_str());
|
|
cmd_queue.push_front(cmd + "?");
|
|
cmd_queue.push_front(cmd + " " + param);
|
|
} else if (cmd == "PWR" && param == "ON") {
|
|
_specialTimeoutMillis = 30000; // time to wait after PWR ON until projector responds again
|
|
cmd_queue.clear(); // clear eventual existing query commands to avoid errors
|
|
cmd_queue.push_front(cmd + "?");
|
|
cmd_queue.push_front(cmd + " " + param);
|
|
}
|
|
}
|
|
|
|
void tw7100Component::update_sensor(std::pair<std::string, std::string> data) {
|
|
static const char *const TAG = "update_sensor()";
|
|
const std::string cmd = data.first;
|
|
const std::string value_string = data.second;
|
|
if (cmd == "PWR") {
|
|
ESP_LOGV(TAG, "updating power sensors");
|
|
int value = std::stoi(value_string);
|
|
powered = (value > 0);
|
|
#ifdef USE_BINARY_SENSOR
|
|
//if (powered_) powered_->publish_state(value > 0);
|
|
#endif
|
|
#ifdef USE_SWITCH
|
|
if (power_switch_) power_switch_->publish_state(value > 0); // ack previous cmd or update switch
|
|
#endif
|
|
#ifdef USE_SENSOR
|
|
if (power_status_) power_status_->publish_state(value);
|
|
#endif
|
|
} else if (cmd == "LAMP") {
|
|
ESP_LOGV(TAG, "updating lamp sensors");
|
|
#ifdef USE_SENSOR
|
|
int value = std::stoi(value_string);
|
|
if (lamp_hours_) lamp_hours_->publish_state(value);
|
|
#endif
|
|
} else if (cmd == "SIGNAL") {
|
|
ESP_LOGV(TAG, "updating signal sensors");
|
|
#ifdef USE_BINARY_SENSOR
|
|
int value = std::stoi(value_string);
|
|
if (has_signal_) has_signal_->publish_state(value > 0);
|
|
#endif
|
|
if (signal_status_) signal_status_->publish_state(value);
|
|
} else if (cmd == "LUMINANCE") {
|
|
ESP_LOGV(TAG, "updating luminance sensors");
|
|
#ifdef USE_SENSOR
|
|
int value = std::stoi(value_string);
|
|
if (luminance_level_) luminance_level_->publish_state(value);
|
|
#endif
|
|
#ifdef USE_SELECT
|
|
if (luminance_select_) {
|
|
if(tw7100Select::luminance.find(value_string) != tw7100Select::luminance.end()) {
|
|
auto call = luminance_select_->make_call();
|
|
call.set_option(tw7100Select::luminance[value_string]);
|
|
call.perform();
|
|
} else {
|
|
ESP_LOGE(TAG, "Result %s not present in options", value_string);
|
|
}
|
|
}
|
|
#endif
|
|
} else if (cmd == "SOURCE") {
|
|
ESP_LOGV(TAG, "updating source select");
|
|
#ifdef USE_SELECT
|
|
if (source_select_) {
|
|
if(tw7100Select::sources.find(value_string) != tw7100Select::sources.end()) {
|
|
auto call = source_select_->make_call();
|
|
call.set_option(tw7100Select::sources[value_string]);
|
|
call.perform();
|
|
} else {
|
|
ESP_LOGE(TAG, "Result %s not present in options", value_string);
|
|
}
|
|
}
|
|
#endif
|
|
} else if (cmd == "ASPECT") {
|
|
ESP_LOGV(TAG, "updating aspect select");
|
|
#ifdef USE_SELECT
|
|
if (aspect_select_) {
|
|
if(tw7100Select::aspect.find(value_string) != tw7100Select::aspect.end()) {
|
|
auto call = aspect_select_->make_call();
|
|
call.set_option(tw7100Select::aspect[value_string]);
|
|
call.perform();
|
|
} else {
|
|
ESP_LOGE(TAG, "Result %s not present in options", value_string);
|
|
}
|
|
}
|
|
#endif
|
|
} else if (cmd == "OVSCAN") {
|
|
ESP_LOGV(TAG, "updating ovscan select");
|
|
} else if (cmd == "CMODE") {
|
|
ESP_LOGV(TAG, "updating cmode select");
|
|
} else if (cmd == "GAMMA") {
|
|
ESP_LOGV(TAG, "updating gamma select");
|
|
} else if (cmd == "IMGPRESET") {
|
|
ESP_LOGV(TAG, "updating imgpreset select");
|
|
} else if (cmd == "MCFI") {
|
|
ESP_LOGV(TAG, "updating mcfi select");
|
|
} else if (cmd == "CLRSPACE") {
|
|
ESP_LOGV(TAG, "updating clrspace select");
|
|
} else if (cmd == "DYNRANGE") {
|
|
ESP_LOGV(TAG, "updating dynrange select");
|
|
} else if (cmd == "MSEL") {
|
|
ESP_LOGV(TAG, "updating msel select");
|
|
} else if (cmd == "SPEED") {
|
|
ESP_LOGV(TAG, "updating speed select");
|
|
#ifdef USE_TEXT_SENSOR
|
|
} else if (cmd == "SNO") {
|
|
if (serial_ != nullptr) serial_->publish_state(value_string);
|
|
#endif
|
|
} else if (cmd == "BTAUDIO") {
|
|
ESP_LOGV(TAG, "updating btaudio switch");
|
|
#ifdef USE_SWITCH
|
|
int value = std::stoi(value_string);
|
|
if (btaudio_switch_) btaudio_switch_->publish_state(value > 0);
|
|
#endif
|
|
} else if (cmd == "4KENHANCE") {
|
|
ESP_LOGV(TAG, "updating 4kenhance switch");
|
|
#ifdef USE_SWITCH
|
|
int value = std::stoi(value_string);
|
|
if (_4kenhance_switch_) _4kenhance_switch_->publish_state(value > 0);
|
|
#endif
|
|
} else if (cmd == "IMGPROC") {
|
|
ESP_LOGV(TAG, "updating imgproc switch");
|
|
#ifdef USE_SWITCH
|
|
int value = std::stoi(value_string);
|
|
if (img_processing_switch_) img_processing_switch_->publish_state(value > 1);
|
|
#endif
|
|
} else if (cmd == "AUDIOOUT") {
|
|
ESP_LOGV(TAG, "updating audioout switch");
|
|
#ifdef USE_SWITCH
|
|
int value = std::stoi(value_string);
|
|
if (audioout_switch_) audioout_switch_->publish_state(value == 11);
|
|
#endif
|
|
} else if (cmd == "HREVERSE") {
|
|
ESP_LOGV(TAG, "updating hflip switch");
|
|
#ifdef USE_SWITCH
|
|
if (hflip_switch_) hflip_switch_->publish_state(value_string == "ON");
|
|
#endif
|
|
} else if (cmd == "VREVERSE") {
|
|
ESP_LOGV(TAG, "updating vflip switch");
|
|
#ifdef USE_SWITCH
|
|
if (vflip_switch_) vflip_switch_->publish_state(value_string == "ON");
|
|
#endif
|
|
} else if (cmd == "ILLUM") {
|
|
ESP_LOGV(TAG, "updating illumination switch");
|
|
#ifdef USE_SWITCH
|
|
int value = std::stoi(value_string);
|
|
if (illumination_switch_) illumination_switch_->publish_state(value == 1);
|
|
#endif
|
|
} else if (cmd == "STANDBYCONF") {
|
|
ESP_LOGV(TAG, "updating standbyconf switch");
|
|
#ifdef USE_SWITCH
|
|
int value = std::stoi(value_string);
|
|
if (standbyconf_switch_) standbyconf_switch_->publish_state(value == 1);
|
|
#endif
|
|
} else if (cmd == "AUTOHOME") {
|
|
ESP_LOGV(TAG, "updating autohome switch");
|
|
#ifdef USE_SWITCH
|
|
int value = std::stoi(value_string);
|
|
if (autohome_switch_) autohome_switch_->publish_state(value == 1);
|
|
#endif
|
|
} else if (cmd == "WLPWR") {
|
|
ESP_LOGV(TAG, "updating wlan power switch");
|
|
#ifdef USE_SWITCH
|
|
int value = std::stoi(value_string);
|
|
if (wlan_power_switch_) wlan_power_switch_->publish_state(value == 1);
|
|
#endif
|
|
} else if (cmd == "LOGTO") {
|
|
ESP_LOGV(TAG, "updating logto switch");
|
|
#ifdef USE_SWITCH
|
|
int value = std::stoi(value_string);
|
|
if (logto_switch_) logto_switch_->publish_state(value == 1);
|
|
#endif
|
|
} else if (cmd == "MUTE") {
|
|
ESP_LOGV(TAG, "updating mute switch with value %s", value_string.c_str());
|
|
#ifdef USE_SWITCH
|
|
if (mute_switch_) mute_switch_->publish_state(value_string == "ON");
|
|
#endif
|
|
} else if (cmd == "VOL") {
|
|
ESP_LOGV(TAG, "updating volume number with value %s", value_string.c_str());
|
|
#ifdef USE_NUMBER
|
|
int value = std::stoi(value_string);
|
|
if (volume_number_) volume_number_->publish_state(value);
|
|
#endif
|
|
} else if (cmd == "VKEYSTONE") {
|
|
ESP_LOGV(TAG, "updating vkeystone number with value %s", value_string.c_str());
|
|
#ifdef USE_NUMBER
|
|
int value = std::stoi(value_string);
|
|
if (vkeystone_number_) vkeystone_number_->publish_state(value);
|
|
#endif
|
|
} else if (cmd == "HKEYSTONE") {
|
|
ESP_LOGV(TAG, "updating hkeystone number with value %s", value_string.c_str());
|
|
#ifdef USE_NUMBER
|
|
int value = std::stoi(value_string);
|
|
if (hkeystone_number_) hkeystone_number_->publish_state(value);
|
|
#endif
|
|
} else if (cmd == "BRIGHT") {
|
|
ESP_LOGV(TAG, "updating brightness number with value %s", value_string.c_str());
|
|
#ifdef USE_NUMBER
|
|
int value = std::stoi(value_string);
|
|
if (brightness_number_) brightness_number_->publish_state(value);
|
|
#endif
|
|
} else if (cmd == "CONTRAST") {
|
|
ESP_LOGV(TAG, "updating contrast number with value %s", value_string.c_str());
|
|
#ifdef USE_NUMBER
|
|
int value = std::stoi(value_string);
|
|
if (contrast_number_) contrast_number_->publish_state(value);
|
|
#endif
|
|
} else if (cmd == "DENSITY") {
|
|
ESP_LOGV(TAG, "updating density number with value %s", value_string.c_str());
|
|
#ifdef USE_NUMBER
|
|
int value = std::stoi(value_string);
|
|
if (density_number_) density_number_->publish_state(value);
|
|
#endif
|
|
} else if (cmd == "TINT") {
|
|
ESP_LOGV(TAG, "updating tint number with value %s", value_string.c_str());
|
|
#ifdef USE_NUMBER
|
|
int value = std::stoi(value_string);
|
|
if (tint_number_) tint_number_->publish_state(value);
|
|
#endif
|
|
} else if (cmd == "CTEMP") {
|
|
ESP_LOGV(TAG, "updating ctemp number with value %s", value_string.c_str());
|
|
#ifdef USE_NUMBER
|
|
int value = std::stoi(value_string);
|
|
if (ctemp_number_) ctemp_number_->publish_state(value);
|
|
#endif
|
|
} else if (cmd == "FCOLOR") {
|
|
ESP_LOGV(TAG, "updating fcolor number with value %s", value_string.c_str());
|
|
#ifdef USE_NUMBER
|
|
int value = std::stoi(value_string);
|
|
if (fcolor_number_) fcolor_number_->publish_state(value);
|
|
#endif
|
|
} else if (cmd == "NRS") {
|
|
ESP_LOGV(TAG, "updating nrs number with value %s", value_string.c_str());
|
|
#ifdef USE_NUMBER
|
|
int value = std::stoi(value_string);
|
|
if (nrs_number_) nrs_number_->publish_state(value);
|
|
#endif
|
|
} else if (cmd == "MPEGNRS") {
|
|
ESP_LOGV(TAG, "updating mpegngs number with value %s", value_string.c_str());
|
|
#ifdef USE_NUMBER
|
|
int value = std::stoi(value_string);
|
|
if (mpegnrs_number_) mpegnrs_number_->publish_state(value);
|
|
#endif
|
|
} else if (cmd == "OFFSETR") {
|
|
ESP_LOGV(TAG, "updating offsetr number with value %s", value_string.c_str());
|
|
#ifdef USE_NUMBER
|
|
int value = std::stoi(value_string);
|
|
if (offsetr_number_) offsetr_number_->publish_state(value);
|
|
#endif
|
|
} else if (cmd == "OFFSETG") {
|
|
ESP_LOGV(TAG, "updating offsetg number with value %s", value_string.c_str());
|
|
#ifdef USE_NUMBER
|
|
int value = std::stoi(value_string);
|
|
if (offsetg_number_) offsetg_number_->publish_state(value);
|
|
#endif
|
|
} else if (cmd == "OFFSETB") {
|
|
ESP_LOGV(TAG, "updating offsetb number with value %s", value_string.c_str());
|
|
#ifdef USE_NUMBER
|
|
int value = std::stoi(value_string);
|
|
if (offsetb_number_) offsetb_number_->publish_state(value);
|
|
#endif
|
|
} else if (cmd == "GAINR") {
|
|
ESP_LOGV(TAG, "updating gainr number with value %s", value_string.c_str());
|
|
#ifdef USE_NUMBER
|
|
int value = std::stoi(value_string);
|
|
if (gainr_number_) gainr_number_->publish_state(value);
|
|
#endif
|
|
} else if (cmd == "GAING") {
|
|
ESP_LOGV(TAG, "updating gaing number with value %s", value_string.c_str());
|
|
#ifdef USE_NUMBER
|
|
int value = std::stoi(value_string);
|
|
if (gaing_number_) gaing_number_->publish_state(value);
|
|
#endif
|
|
} else if (cmd == "GAINB") {
|
|
ESP_LOGV(TAG, "updating gainb number with value %s", value_string.c_str());
|
|
#ifdef USE_NUMBER
|
|
int value = std::stoi(value_string);
|
|
if (gainb_number_) gainb_number_->publish_state(value);
|
|
#endif
|
|
} else if (cmd == "SHRF") {
|
|
ESP_LOGV(TAG, "updating shrf number with value %s", value_string.c_str());
|
|
#ifdef USE_NUMBER
|
|
int value = std::stoi(value_string);
|
|
if (shrf_number_) shrf_number_->publish_state(value);
|
|
#endif
|
|
} else if (cmd == "SHRS") {
|
|
ESP_LOGV(TAG, "updating shrs number with value %s", value_string.c_str());
|
|
#ifdef USE_NUMBER
|
|
int value = std::stoi(value_string);
|
|
if (shrs_number_) shrs_number_->publish_state(value);
|
|
#endif
|
|
} else if (cmd == "DERANGE") {
|
|
ESP_LOGV(TAG, "updating derange number with value %s", value_string.c_str());
|
|
#ifdef USE_NUMBER
|
|
int value = std::stoi(value_string);
|
|
if (derange_number_) derange_number_->publish_state(value);
|
|
#endif
|
|
} else if (cmd == "DESTRENGTH") {
|
|
ESP_LOGV(TAG, "updating destrength number with value %s", value_string.c_str());
|
|
#ifdef USE_NUMBER
|
|
int value = std::stoi(value_string);
|
|
if (destrength_number_) destrength_number_->publish_state(value);
|
|
#endif
|
|
} else {
|
|
ESP_LOGW(TAG, "Command %s unknown, skipping updating sensor with value", cmd.c_str());
|
|
}
|
|
}
|
|
|
|
std::pair<std::string, std::string> tw7100Component::parse_response(std::string data) {
|
|
static const char *const TAG = "parse_response()";
|
|
std::string key = "";
|
|
std::string value = "";
|
|
data.erase(std::remove(data.begin(), data.end(), '\r'), data.cend());
|
|
data.erase(std::remove(data.begin(), data.end(), '\n'), data.cend());
|
|
if (data != "") {
|
|
key = data.substr(0, data.find("="));
|
|
value = data.substr(data.find("=") + 1, data.length());
|
|
}
|
|
|
|
ESP_LOGV(TAG, "parsed response into (key: %s, value: %s)", key.c_str(), value.c_str());
|
|
return std::make_pair(key, value);
|
|
}
|
|
|
|
int tw7100Component::timedRead() {
|
|
unsigned long _startMillis; // used for timeout measurement
|
|
int c;
|
|
_startMillis = millis();
|
|
do {
|
|
if (this->available() > 0) {
|
|
c = this->read();
|
|
//ESP_LOGV("timedRead()", "timed read byte: %c (%x)", c, c);
|
|
if (c >= 0) {
|
|
return c;
|
|
}
|
|
}
|
|
} while (millis() - _startMillis < _readStringUntil_timeout);
|
|
return -1; // -1 indicates timeout
|
|
}
|
|
|
|
std::string tw7100Component::readStringUntil(char terminator) {
|
|
std::string line="";
|
|
int c = timedRead();
|
|
while (c >= 0 && (char)c != terminator) {
|
|
line += (char)c;
|
|
c = timedRead();
|
|
}
|
|
return line;
|
|
};
|
|
|
|
} // namespace tw7100
|
|
} // namespace esphome
|