filter state cb from previous state

This commit is contained in:
oarcher 2024-08-01 15:58:02 +02:00
parent 1b9c9e9ccb
commit 00b9e83d0e
3 changed files with 88 additions and 56 deletions

View file

@ -21,7 +21,7 @@ class ModemOnNotRespondingTrigger : public Trigger<> {
class ModemOnConnectTrigger : public Trigger<> { class ModemOnConnectTrigger : public Trigger<> {
public: public:
explicit ModemOnConnectTrigger(ModemComponent *parent) { explicit ModemOnConnectTrigger(ModemComponent *parent) {
parent->add_on_state_callback([this, parent](ModemComponentState state) { parent->add_on_state_callback([this, parent](ModemComponentState old_state, ModemComponentState state) {
if (!parent->is_failed() && state == ModemComponentState::CONNECTED) { if (!parent->is_failed() && state == ModemComponentState::CONNECTED) {
this->trigger(); this->trigger();
} }
@ -32,9 +32,12 @@ class ModemOnConnectTrigger : public Trigger<> {
class ModemOnDisconnectTrigger : public Trigger<> { class ModemOnDisconnectTrigger : public Trigger<> {
public: public:
explicit ModemOnDisconnectTrigger(ModemComponent *parent) { explicit ModemOnDisconnectTrigger(ModemComponent *parent) {
parent->add_on_state_callback([this, parent](ModemComponentState state) { parent->add_on_state_callback([this, parent](ModemComponentState old_state, ModemComponentState state) {
if (!parent->is_failed() && state == ModemComponentState::DISCONNECTED) { if (!parent->is_failed() && state == ModemComponentState::DISCONNECTED) {
this->trigger(); // filter useless old_state
if (old_state == ModemComponentState::CONNECTED) {
this->trigger();
}
} }
}); });
} }

View file

@ -20,6 +20,7 @@
#include <cstring> #include <cstring>
#include <iostream> #include <iostream>
#include <sstream>
#ifndef USE_MODEM_MODEL #ifndef USE_MODEM_MODEL
#define USE_MODEM_MODEL "GENERIC" #define USE_MODEM_MODEL "GENERIC"
@ -248,9 +249,12 @@ bool ModemComponent::modem_sync_() {
if (!this->prepare_sim_()) { if (!this->prepare_sim_()) {
// fatal error // fatal error
this->disable(); this->disable();
status = false;
} }
} }
this->modem_synced_ = status;
return status; return status;
} }
@ -350,8 +354,12 @@ void ModemComponent::ip_event_handler(void *arg, esp_event_base_t event_base, in
global_modem_component->got_ipv4_address_ = true; global_modem_component->got_ipv4_address_ = true;
global_modem_component->connected_ = true; global_modem_component->connected_ = true;
break; break;
case IP_EVENT_PPP_LOST_IP: case IP_EVENT_PPP_LOST_IP:
ESP_LOGD(TAG, "[IP event] Lost IP"); if (global_modem_component->connected_) {
// do not log message if we are not connected
ESP_LOGD(TAG, "[IP event] Lost IP");
}
global_modem_component->got_ipv4_address_ = false; global_modem_component->got_ipv4_address_ = false;
global_modem_component->connected_ = false; global_modem_component->connected_ = false;
break; break;
@ -395,6 +403,7 @@ void ModemComponent::loop() {
} else { } else {
ESP_LOGI(TAG, "Modem powered ON"); ESP_LOGI(TAG, "Modem powered ON");
this->powered_on_ = true; this->powered_on_ = true;
this->modem_synced_ = false;
this->watchdog_.reset(); this->watchdog_.reset();
} }
break; break;
@ -415,6 +424,7 @@ void ModemComponent::loop() {
} else { } else {
ESP_LOGI(TAG, "Modem powered OFF"); ESP_LOGI(TAG, "Modem powered OFF");
this->powered_on_ = false; this->powered_on_ = false;
this->modem_synced_ = false;
this->watchdog_.reset(); this->watchdog_.reset();
} }
break; break;
@ -431,7 +441,6 @@ void ModemComponent::loop() {
ESP_LOGI(TAG, "Modem recovered"); ESP_LOGI(TAG, "Modem recovered");
this->status_clear_warning(); this->status_clear_warning();
this->state_ = ModemComponentState::DISCONNECTED; this->state_ = ModemComponentState::DISCONNECTED;
last_state = this->state_; // disable on_disconnect cb
} else { } else {
if (!this->powered_on_) { if (!this->powered_on_) {
this->poweron_(); this->poweron_();
@ -447,44 +456,25 @@ void ModemComponent::loop() {
} }
break; break;
// disconnected, want to connect
case ModemComponentState::DISCONNECTED: case ModemComponentState::DISCONNECTED:
if (this->enabled_) { if (this->enabled_) {
if (last_state == ModemComponentState::DISABLED) { // be sure the modem is on and synced
last_state = this->state_; // disable on_disconnect cb
}
if (!this->powered_on_) { if (!this->powered_on_) {
this->poweron_(); this->poweron_();
break; break;
} else if (!this->modem_synced_) {
if (!this->modem_sync_()) {
ESP_LOGE(TAG, "Modem not responding");
this->state_ = ModemComponentState::NOT_RESPONDING;
}
} }
if (this->start_) { if (this->start_) {
if (connecting) { // want to connect
if (this->connected_) { if (!connecting) {
connecting = false; // wait for the modem be attached to a network, start ppp, and set connecting=true
ESP_LOGI(TAG, "Connected via Modem");
this->state_ = ModemComponentState::CONNECTED;
this->dump_connect_params_();
this->status_clear_warning();
this->watchdog_.reset();
} else if (millis() - this->connect_begin_ > 15000) {
ESP_LOGW(TAG, "Connecting via Modem failed! Re-connecting...");
// TODO: exit data/cmux without error check
connecting = false;
} else {
// Wait for IP from PPP event
next_loop_millis = millis() + 1000; // delay for next loop
}
} else {
if (!this->watchdog_) if (!this->watchdog_)
this->watchdog_ = std::make_shared<watchdog::WatchdogManager>(60000); this->watchdog_ = std::make_shared<watchdog::WatchdogManager>(60000);
// want to start connect, make sure the modem is ready
if (!this->modem_sync_()) {
ESP_LOGE(TAG, "Modem not responding");
this->state_ = ModemComponentState::NOT_RESPONDING;
break;
}
if (is_network_attached_()) { if (is_network_attached_()) {
network_attach_retry = 10; network_attach_retry = 10;
if (this->start_ppp_()) { if (this->start_ppp_()) {
@ -505,6 +495,27 @@ void ModemComponent::loop() {
} }
next_loop_millis = millis() + 1000; // delay to retry next_loop_millis = millis() + 1000; // delay to retry
} }
} else {
// connecting
if (!this->connected_) {
// wait until this->connected_ set to true by IP_EVENT_PPP_GOT_IP
next_loop_millis = millis() + 1000; // delay for next loop
// connecting timeout
if (millis() - this->connect_begin_ > 15000) {
ESP_LOGW(TAG, "Connecting via Modem failed! Re-connecting...");
// TODO: exit data/cmux without error check
connecting = false;
}
} else {
connecting = false;
ESP_LOGI(TAG, "Connected via Modem");
this->state_ = ModemComponentState::CONNECTED;
this->dump_connect_params_();
this->status_clear_warning();
this->watchdog_.reset();
}
} }
} else { } else {
this->start_ = true; this->start_ = true;
@ -524,6 +535,7 @@ void ModemComponent::loop() {
disconnecting = false; disconnecting = false;
} else { } else {
if (this->connected_) { if (this->connected_) {
// connected but disbled, so disconnect
if (!disconnecting) { if (!disconnecting) {
disconnecting = true; disconnecting = true;
ip_lost_retries = 10; ip_lost_retries = 10;
@ -541,22 +553,20 @@ void ModemComponent::loop() {
if (ip_info.ip.addr == 0) { if (ip_info.ip.addr == 0) {
// lost IP // lost IP
esp_event_post(IP_EVENT, IP_EVENT_PPP_LOST_IP, nullptr, 0, 0); esp_event_post(IP_EVENT, IP_EVENT_PPP_LOST_IP, nullptr, 0, 0);
} else {
ESP_LOGD(TAG, "Waiting for lost IP... (retries %" PRIu8 ")", ip_lost_retries);
ip_lost_retries--;
if (ip_lost_retries == 0) {
// Something goes wrong, we have still an IP
ESP_LOGE(TAG, "No IP lost event recieved. Sending one manually");
esp_event_post(IP_EVENT, IP_EVENT_PPP_LOST_IP, nullptr, 0, 0);
}
} }
ESP_LOGD(TAG, "Waiting for lost IP... (retries %" PRIu8 ")", ip_lost_retries);
ip_lost_retries--;
if (ip_lost_retries == 0) {
// Something goes wrong, we have still an IP
ESP_LOGE(TAG, "No IP lost event recieved. Sending one manually");
esp_event_post(IP_EVENT, IP_EVENT_PPP_LOST_IP, nullptr, 0, 0);
}
next_loop_millis = millis() + 2000; // delay for next loop next_loop_millis = millis() + 2000; // delay for next loop
} }
} else { // if (this->connected_) } else { // if (this->connected_)
// ip lost as expected // ip lost as expected
ESP_LOGI(TAG, "PPPoS disconnected"); ESP_LOGI(TAG, "PPPoS disconnected");
this->dump_connect_params_();
this->state_ = ModemComponentState::DISCONNECTED; this->state_ = ModemComponentState::DISCONNECTED;
} }
} }
@ -565,7 +575,6 @@ void ModemComponent::loop() {
case ModemComponentState::DISABLED: case ModemComponentState::DISABLED:
if (this->enabled_) { if (this->enabled_) {
this->state_ = ModemComponentState::DISCONNECTED; this->state_ = ModemComponentState::DISCONNECTED;
last_state = this->state_; // disable on_disconnect cb
ESP_LOGE(TAG, "here"); ESP_LOGE(TAG, "here");
} else if (this->powered_on_) { } else if (this->powered_on_) {
this->poweroff_(); this->poweroff_();
@ -577,7 +586,7 @@ void ModemComponent::loop() {
if (this->state_ != last_state) { if (this->state_ != last_state) {
ESP_LOGV(TAG, "State changed: %s -> %s", state_to_string(last_state).c_str(), ESP_LOGV(TAG, "State changed: %s -> %s", state_to_string(last_state).c_str(),
state_to_string(this->state_).c_str()); state_to_string(this->state_).c_str());
this->on_state_callback_.call(this->state_); this->on_state_callback_.call(last_state, this->state_);
last_state = this->state_; last_state = this->state_;
} }
@ -668,21 +677,39 @@ bool ModemComponent::is_network_attached_() {
void ModemComponent::dump_dce_status_() { void ModemComponent::dump_dce_status_() {
ESP_LOGCONFIG(TAG, "Modem status:"); ESP_LOGCONFIG(TAG, "Modem status:");
int network_attachment_state; command_result err;
std::string result; std::string result;
command_result err = this->dce->get_network_attachment_state(network_attachment_state); err = this->dce->get_module_name(result);
if (err != command_result::OK) {
result = "command " + command_result_to_string(err);
}
ESP_LOGCONFIG(TAG, " Module name : %s", result.c_str());
int rssi;
int ber;
err = this->dce->get_signal_quality(rssi, ber);
if (err != command_result::OK) {
result = "command " + command_result_to_string(err);
} else {
float ber_f;
if (ber != 99) {
ber_f = float(ber);
} else
ber_f = {};
std::ostringstream oss;
oss << "rssi " << rssi << "(" << (rssi * 100) / 31 << "%), ber " << ber << "(" << (ber_f * 100) / 7 << "%)";
result = oss.str();
}
ESP_LOGCONFIG(TAG, " Signal quality : %s", result.c_str());
int network_attachment_state;
err = this->dce->get_network_attachment_state(network_attachment_state);
if (err == command_result::OK) { if (err == command_result::OK) {
result = network_attachment_state ? "Yes" : "No"; result = network_attachment_state ? "Yes" : "No";
} else { } else {
result = "command " + command_result_to_string(err); result = "command " + command_result_to_string(err);
} }
ESP_LOGCONFIG(TAG, " Attached to network: %s", result.c_str()); ESP_LOGCONFIG(TAG, " Attached to network: %s", result.c_str());
this->dce->get_module_name(result);
if (err != command_result::OK) {
result = "command " + command_result_to_string(err);
}
ESP_LOGCONFIG(TAG, " Module name : %s", result.c_str());
} }
std::string ModemComponent::send_at(const std::string &cmd) { std::string ModemComponent::send_at(const std::string &cmd) {
@ -733,7 +760,7 @@ bool ModemComponent::modem_ready() {
return false; return false;
} }
void ModemComponent::add_on_state_callback(std::function<void(ModemComponentState)> &&callback) { void ModemComponent::add_on_state_callback(std::function<void(ModemComponentState, ModemComponentState)> &&callback) {
this->on_state_callback_.add(std::move(callback)); this->on_state_callback_.add(std::move(callback));
} }

View file

@ -76,7 +76,7 @@ class ModemComponent : public Component {
bool modem_ready(); bool modem_ready();
void enable(); void enable();
void disable(); void disable();
void add_on_state_callback(std::function<void(ModemComponentState)> &&callback); void add_on_state_callback(std::function<void(ModemComponentState, ModemComponentState)> &&callback);
std::unique_ptr<DCE> dce{nullptr}; std::unique_ptr<DCE> dce{nullptr};
protected: protected:
@ -115,6 +115,8 @@ class ModemComponent : public Component {
bool enabled_{false}; bool enabled_{false};
bool connected_{false}; bool connected_{false};
bool got_ipv4_address_{false}; bool got_ipv4_address_{false};
// true if modem_sync_ was sucessfull
bool modem_synced_{false};
// date start (millis()) // date start (millis())
uint32_t connect_begin_; uint32_t connect_begin_;
std::string use_address_; std::string use_address_;
@ -130,7 +132,7 @@ class ModemComponent : public Component {
#endif // USE_MODEM_POWER #endif // USE_MODEM_POWER
// separate handler for `on_not_responding` (we want to know when it's ended) // separate handler for `on_not_responding` (we want to know when it's ended)
Trigger<> *not_responding_cb_{nullptr}; Trigger<> *not_responding_cb_{nullptr};
CallbackManager<void(ModemComponentState)> on_state_callback_; CallbackManager<void(ModemComponentState, ModemComponentState)> on_state_callback_;
}; };
// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables) // NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables)