mirror of
https://github.com/esphome/esphome.git
synced 2025-01-31 18:20:53 +00:00
sim7670 gnss
This commit is contained in:
parent
9bfde3b3ab
commit
4ec62a2be6
@ -42,7 +42,7 @@ CONF_ON_NOT_RESPONDING = "on_not_responding"
|
|||||||
CONF_ENABLE_CMUX = "enable_cmux"
|
CONF_ENABLE_CMUX = "enable_cmux"
|
||||||
CONF_ENABLE_GNSS = "enable_gnss"
|
CONF_ENABLE_GNSS = "enable_gnss"
|
||||||
|
|
||||||
MODEM_MODELS = ["BG96", "SIM800", "SIM7000", "SIM7600", "GENERIC"]
|
MODEM_MODELS = ["BG96", "SIM800", "SIM7000", "SIM7600", "SIM7670", "GENERIC"]
|
||||||
MODEM_MODELS_POWER = {
|
MODEM_MODELS_POWER = {
|
||||||
"BG96": {"ton": 600, "tonuart": 4900, "toff": 650, "toffuart": 2000},
|
"BG96": {"ton": 600, "tonuart": 4900, "toff": 650, "toffuart": 2000},
|
||||||
"SIM800": {"ton": 1300, "tonuart": 3000, "toff": 200, "toffuart": 3000},
|
"SIM800": {"ton": 1300, "tonuart": 3000, "toff": 200, "toffuart": 3000},
|
||||||
@ -50,6 +50,12 @@ MODEM_MODELS_POWER = {
|
|||||||
"SIM7600": {"ton": 500, "tonuart": 12000, "toff": 2800, "toffuart": 25000},
|
"SIM7600": {"ton": 500, "tonuart": 12000, "toff": 2800, "toffuart": 25000},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MODEM_MODELS_POWER["SIM7670"] = MODEM_MODELS_POWER["SIM7600"]
|
||||||
|
|
||||||
|
# SIM70xx doesn't support AT+CGNSSINFO, so gnss is not available
|
||||||
|
MODEM_MODELS_GNSS_POWER = {"SIM7600": "AT+CGPS=1", "SIM7670": "AT+CGNSSPWR=1"}
|
||||||
|
|
||||||
|
|
||||||
modem_ns = cg.esphome_ns.namespace("modem")
|
modem_ns = cg.esphome_ns.namespace("modem")
|
||||||
ModemComponent = modem_ns.class_("ModemComponent", cg.Component)
|
ModemComponent = modem_ns.class_("ModemComponent", cg.Component)
|
||||||
ModemComponentState = modem_ns.enum("ModemComponentState")
|
ModemComponentState = modem_ns.enum("ModemComponentState")
|
||||||
@ -119,19 +125,12 @@ def final_validate_platform(config):
|
|||||||
|
|
||||||
|
|
||||||
def _final_validate(config):
|
def _final_validate(config):
|
||||||
# if config.get(CONF_POWER_PIN, None) and not config.get(CONF_STATUS_PIN, None):
|
|
||||||
# raise cv.Invalid(
|
|
||||||
# f"'{CONF_STATUS_PIN}' must be declared if using '{CONF_POWER_PIN}'"
|
|
||||||
# )
|
|
||||||
|
|
||||||
# uncomment after PR#4091 merged
|
# uncomment after PR#4091 merged
|
||||||
# if wifi_config := fv.full_config.get().get(CONF_WIFI, None):
|
# if wifi_config := fv.full_config.get().get(CONF_WIFI, None):
|
||||||
# if wifi_has_sta(wifi_config):
|
# if wifi_has_sta(wifi_config):
|
||||||
# raise cv.Invalid("Wifi must be AP only when using ethernet")
|
# raise cv.Invalid("Wifi must be AP only when using ethernet")
|
||||||
if config.get(CONF_STATUS_PIN, None):
|
if config.get(CONF_STATUS_PIN, None):
|
||||||
_LOGGER.warning("Using '%s' is experimental", CONF_STATUS_PIN)
|
_LOGGER.warning("Using '%s' is experimental", CONF_STATUS_PIN)
|
||||||
if config[CONF_ENABLE_CMUX]:
|
|
||||||
_LOGGER.warning("Using '%s: True' is experimental", CONF_ENABLE_CMUX)
|
|
||||||
if not config[CONF_ENABLE_ON_BOOT]:
|
if not config[CONF_ENABLE_ON_BOOT]:
|
||||||
_LOGGER.warning("Using '%s: False' is experimental", CONF_ENABLE_ON_BOOT)
|
_LOGGER.warning("Using '%s: False' is experimental", CONF_ENABLE_ON_BOOT)
|
||||||
if config.get(CONF_POWER_PIN, None):
|
if config.get(CONF_POWER_PIN, None):
|
||||||
@ -139,6 +138,11 @@ def _final_validate(config):
|
|||||||
raise cv.Invalid(
|
raise cv.Invalid(
|
||||||
f"Modem model '{config[CONF_MODEL]}' has no power power specs."
|
f"Modem model '{config[CONF_MODEL]}' has no power power specs."
|
||||||
)
|
)
|
||||||
|
if config.get(CONF_ENABLE_GNSS, None):
|
||||||
|
if config[CONF_MODEL] not in MODEM_MODELS_GNSS_POWER:
|
||||||
|
raise cv.Invalid(
|
||||||
|
f"Modem model '{config[CONF_MODEL]}' has no GNSS support with AT+CGNSSINFO."
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
FINAL_VALIDATE_SCHEMA = _final_validate
|
FINAL_VALIDATE_SCHEMA = _final_validate
|
||||||
@ -185,10 +189,6 @@ async def to_code(config):
|
|||||||
if config[CONF_ENABLE_CMUX]:
|
if config[CONF_ENABLE_CMUX]:
|
||||||
cg.add(var.enable_cmux())
|
cg.add(var.enable_cmux())
|
||||||
|
|
||||||
if config[CONF_ENABLE_GNSS]:
|
|
||||||
cg.add_define("USE_MODEM_GNSS")
|
|
||||||
cg.add(var.enable_gnss())
|
|
||||||
|
|
||||||
if config[CONF_DEBUG]:
|
if config[CONF_DEBUG]:
|
||||||
cg.add(var.enable_debug())
|
cg.add(var.enable_debug())
|
||||||
|
|
||||||
@ -200,6 +200,10 @@ async def to_code(config):
|
|||||||
cg.add_define("USE_MODEM_MODEL", modem_model)
|
cg.add_define("USE_MODEM_MODEL", modem_model)
|
||||||
cg.add_define(f"USE_MODEM_MODEL_{modem_model}")
|
cg.add_define(f"USE_MODEM_MODEL_{modem_model}")
|
||||||
|
|
||||||
|
if config[CONF_ENABLE_GNSS]:
|
||||||
|
cg.add_define("USE_MODEM_GNSS")
|
||||||
|
cg.add(var.set_gnss_power_command(MODEM_MODELS_GNSS_POWER[modem_model]))
|
||||||
|
|
||||||
if power_spec := MODEM_MODELS_POWER.get(modem_model, None):
|
if power_spec := MODEM_MODELS_POWER.get(modem_model, None):
|
||||||
cg.add_define("USE_MODEM_POWER")
|
cg.add_define("USE_MODEM_POWER")
|
||||||
for spec, value in power_spec.items():
|
for spec, value in power_spec.items():
|
||||||
|
@ -473,7 +473,6 @@ void ModemComponent::modem_lazy_init_() {
|
|||||||
if (this->dte_->set_mode(modem_mode::COMMAND_MODE)) {
|
if (this->dte_->set_mode(modem_mode::COMMAND_MODE)) {
|
||||||
ESP_LOGD(TAG, "dte in command mode");
|
ESP_LOGD(TAG, "dte in command mode");
|
||||||
}
|
}
|
||||||
|
|
||||||
esp_modem_dce_config_t dce_config = ESP_MODEM_DCE_DEFAULT_CONFIG(this->apn_.c_str());
|
esp_modem_dce_config_t dce_config = ESP_MODEM_DCE_DEFAULT_CONFIG(this->apn_.c_str());
|
||||||
|
|
||||||
#if defined(USE_MODEM_MODEL_GENERIC)
|
#if defined(USE_MODEM_MODEL_GENERIC)
|
||||||
@ -484,12 +483,11 @@ void ModemComponent::modem_lazy_init_() {
|
|||||||
this->dce = create_SIM800_dce(&dce_config, this->dte_, this->ppp_netif_);
|
this->dce = create_SIM800_dce(&dce_config, this->dte_, this->ppp_netif_);
|
||||||
#elif defined(USE_MODEM_MODEL_SIM7000)
|
#elif defined(USE_MODEM_MODEL_SIM7000)
|
||||||
this->dce = create_SIM7000_dce(&dce_config, this->dte_, this->ppp_netif_);
|
this->dce = create_SIM7000_dce(&dce_config, this->dte_, this->ppp_netif_);
|
||||||
#elif defined(USE_MODEM_MODEL_SIM7600)
|
#elif defined(USE_MODEM_MODEL_SIM7600) || defined(USE_MODEM_MODEL_SIM7670)
|
||||||
this->dce = create_SIM7600_dce(&dce_config, this->dte_, this->ppp_netif_);
|
this->dce = create_SIM7600_dce(&dce_config, this->dte_, this->ppp_netif_);
|
||||||
#else
|
#else
|
||||||
#error Modem model not known
|
#error Modem model not known
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// flow control not fully implemented, but kept here for future work
|
// flow control not fully implemented, but kept here for future work
|
||||||
// if (dte_config.uart_config.flow_control == ESP_MODEM_FLOW_CONTROL_HW) {
|
// if (dte_config.uart_config.flow_control == ESP_MODEM_FLOW_CONTROL_HW) {
|
||||||
// if (command_result::OK != this->dce->set_flow_control(2, 2)) {
|
// if (command_result::OK != this->dce->set_flow_control(2, 2)) {
|
||||||
@ -508,6 +506,7 @@ bool ModemComponent::modem_sync_() {
|
|||||||
|
|
||||||
uint32_t start_ms = millis();
|
uint32_t start_ms = millis();
|
||||||
uint32_t elapsed_ms;
|
uint32_t elapsed_ms;
|
||||||
|
std::string result;
|
||||||
|
|
||||||
ESP_LOGV(TAG, "Checking if the modem is synced...");
|
ESP_LOGV(TAG, "Checking if the modem is synced...");
|
||||||
bool status = this->modem_ready(true);
|
bool status = this->modem_ready(true);
|
||||||
@ -516,8 +515,6 @@ bool ModemComponent::modem_sync_() {
|
|||||||
// Try to exit CMUX_MANUAL_DATA or DATA_MODE, if any
|
// Try to exit CMUX_MANUAL_DATA or DATA_MODE, if any
|
||||||
ESP_LOGD(TAG, "Connecting to the the modem...");
|
ESP_LOGD(TAG, "Connecting to the the modem...");
|
||||||
|
|
||||||
std::string result;
|
|
||||||
|
|
||||||
auto command_mode = [this]() -> bool {
|
auto command_mode = [this]() -> bool {
|
||||||
ESP_LOGVV(TAG, "trying command mode");
|
ESP_LOGVV(TAG, "trying command mode");
|
||||||
this->dce->set_mode(modem_mode::UNDEF);
|
this->dce->set_mode(modem_mode::UNDEF);
|
||||||
@ -553,16 +550,15 @@ bool ModemComponent::modem_sync_() {
|
|||||||
// First time the modem is synced, or modem recovered
|
// First time the modem is synced, or modem recovered
|
||||||
this->internal_state_.modem_synced = true;
|
this->internal_state_.modem_synced = true;
|
||||||
|
|
||||||
// Fail on 7600, because esp_modem use internally AT+CGNSPWR? that is unsupported (should be AT+CGPS?)
|
if (!this->gnss_power_command_.empty()) {
|
||||||
// int gnss_power;
|
command_result err;
|
||||||
// ESPMODEM_ERROR_CHECK(this->dce->get_gnss_power_mode(gnss_power), "Getting GNSS power state");
|
ESP_LOGD(TAG, "Enabling GNSS with command: %s", this->gnss_power_command_.c_str());
|
||||||
// ESP_LOGD(TAG, "GNSS power mode: %d", gnss_power);
|
err = this->dce->at(this->gnss_power_command_, result, this->command_delay_);
|
||||||
|
if (err == command_result::FAIL) {
|
||||||
// enabling GNSS seems to return an error, if already enabled
|
// AT+CGPS=1 for SIM7600 or AT+CGNSSPWR=1 for SIM7670 often fail, but seems to be working anyway
|
||||||
// Fail on 7670, because esp_modem use internally AT+CGPS=1 that is unsupported (should be AT+CGNSSPWR=1 not
|
ESP_LOGD(TAG, "GNSS power command failed. Ignoring, as the status is often FAIL, while it works later.");
|
||||||
// (AT+CGNSPWR?))
|
}
|
||||||
// So SIM7670 should add AT+CGNSSPWR=1 to init_at
|
}
|
||||||
ESPMODEM_ERROR_CHECK(this->dce->set_gnss_power_mode(this->gnss_), "Enabling/disabling GNSS");
|
|
||||||
// ESPMODEM_ERROR_CHECK(this->dce->set_gnss_power_mode(0), "Enabling/disabling GNSS");
|
// ESPMODEM_ERROR_CHECK(this->dce->set_gnss_power_mode(0), "Enabling/disabling GNSS");
|
||||||
|
|
||||||
// delay(200); // NOLINT
|
// delay(200); // NOLINT
|
||||||
@ -678,7 +674,6 @@ bool ModemComponent::stop_ppp_() {
|
|||||||
if (this->cmux_) {
|
if (this->cmux_) {
|
||||||
status = this->dce->set_mode(modem_mode::CMUX_MANUAL_COMMAND);
|
status = this->dce->set_mode(modem_mode::CMUX_MANUAL_COMMAND);
|
||||||
} else {
|
} else {
|
||||||
// assert(this->dce->set_mode(modem_mode::COMMAND_MODE)); // OK on 7600, nok on 7670...
|
|
||||||
status = this->dce->set_mode(modem_mode::COMMAND_MODE);
|
status = this->dce->set_mode(modem_mode::COMMAND_MODE);
|
||||||
}
|
}
|
||||||
if (!status) {
|
if (!status) {
|
||||||
|
@ -58,9 +58,9 @@ class ModemComponent : public Component {
|
|||||||
void set_password(const std::string &password) { this->password_ = password; }
|
void set_password(const std::string &password) { this->password_ = password; }
|
||||||
void set_pin_code(const std::string &pin_code) { this->pin_code_ = pin_code; }
|
void set_pin_code(const std::string &pin_code) { this->pin_code_ = pin_code; }
|
||||||
void set_apn(const std::string &apn) { this->apn_ = apn; }
|
void set_apn(const std::string &apn) { this->apn_ = apn; }
|
||||||
|
void set_gnss_power_command(const std::string &at_command) { this->gnss_power_command_ = at_command; }
|
||||||
void set_not_responding_cb(Trigger<> *not_responding_cb) { this->not_responding_cb_ = not_responding_cb; }
|
void set_not_responding_cb(Trigger<> *not_responding_cb) { this->not_responding_cb_ = not_responding_cb; }
|
||||||
void enable_cmux() { this->cmux_ = true; }
|
void enable_cmux() { this->cmux_ = true; }
|
||||||
void enable_gnss() { this->gnss_ = true; }
|
|
||||||
void enable_debug() { esp_log_level_set("command_lib", ESP_LOG_VERBOSE); }
|
void enable_debug() { esp_log_level_set("command_lib", ESP_LOG_VERBOSE); }
|
||||||
void add_init_at_command(const std::string &cmd) { this->init_at_commands_.push_back(cmd); }
|
void add_init_at_command(const std::string &cmd) { this->init_at_commands_.push_back(cmd); }
|
||||||
bool is_connected() { return this->component_state_ == ModemComponentState::CONNECTED; }
|
bool is_connected() { return this->component_state_ == ModemComponentState::CONNECTED; }
|
||||||
@ -122,7 +122,7 @@ class ModemComponent : public Component {
|
|||||||
std::vector<std::string> init_at_commands_;
|
std::vector<std::string> init_at_commands_;
|
||||||
std::string use_address_;
|
std::string use_address_;
|
||||||
bool cmux_{false};
|
bool cmux_{false};
|
||||||
bool gnss_{false};
|
std::string gnss_power_command_;
|
||||||
// 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, ModemComponentState)> on_state_callback_;
|
CallbackManager<void(ModemComponentState, ModemComponentState)> on_state_callback_;
|
||||||
|
@ -39,6 +39,7 @@ void ModemSensor::update() {
|
|||||||
ESP_LOGD(TAG, "Modem sensor update");
|
ESP_LOGD(TAG, "Modem sensor update");
|
||||||
if (modem::global_modem_component->dce && modem::global_modem_component->modem_ready()) {
|
if (modem::global_modem_component->dce && modem::global_modem_component->modem_ready()) {
|
||||||
this->update_signal_sensors_();
|
this->update_signal_sensors_();
|
||||||
|
App.feed_wdt();
|
||||||
this->update_gnss_sensors_();
|
this->update_gnss_sensors_();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -182,7 +183,7 @@ void ModemSensor::update_gnss_sensors_() {
|
|||||||
float alt = std::stof(parts["altitude"]);
|
float alt = std::stof(parts["altitude"]);
|
||||||
float speed_knots = std::stof(parts["speed"]);
|
float speed_knots = std::stof(parts["speed"]);
|
||||||
float speed_kmh = speed_knots * 1.852; // Convert speed from knots to km/h
|
float speed_kmh = speed_knots * 1.852; // Convert speed from knots to km/h
|
||||||
float cog = std::stof(parts["cog"]);
|
float cog = parts["cog"].empty() ? NAN : std::stof(parts["cog"]);
|
||||||
float pdop = std::stof(parts["pdop"]);
|
float pdop = std::stof(parts["pdop"]);
|
||||||
float hdop = std::stof(parts["hdop"]);
|
float hdop = std::stof(parts["hdop"]);
|
||||||
float vdop = std::stof(parts["vdop"]);
|
float vdop = std::stof(parts["vdop"]);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user