signal strength text sensor

This commit is contained in:
oarcher 2024-08-15 19:05:48 +02:00
parent 2c9c6aea30
commit 24a4845991
6 changed files with 170 additions and 67 deletions

View file

@ -49,6 +49,142 @@ std::string state_to_string(ModemComponentState state) {
return str; return str;
} }
std::string network_system_mode_to_string(int mode) {
std::string network_type = "Not available";
// Access Technology from AT+CNSMOD?
// see https://www.waveshare.com/w/upload/a/af/SIM7500_SIM7600_Series_AT_Command_Manual_V3.00.pdf, page 109
switch (mode) {
case 0:
network_type = "No service";
break;
case 1:
network_type = "GSM";
break;
case 2:
network_type = "GPRS";
break;
case 3:
network_type = "EGPRS (EDGE)";
break;
case 4:
network_type = "WCDMA";
break;
case 5:
network_type = "HSDPA only (WCDMA)";
break;
case 6:
network_type = "HSUPA only (WCDMA)";
break;
case 7:
network_type = "HSPA (HSDPA and HSUPA, WCDMA)";
break;
case 8:
network_type = "LTE";
break;
case 9:
network_type = "TDS-CDMA";
break;
case 10:
network_type = "TDS-HSDPA only";
break;
case 11:
network_type = "TDS-HSUPA only";
break;
case 12:
network_type = "TDS-HSPA (HSDPA and HSUPA)";
break;
case 13:
network_type = "CDMA";
break;
case 14:
network_type = "EVDO";
break;
case 15:
network_type = "HYBRID (CDMA and EVDO)";
break;
case 16:
network_type = "1XLTE (CDMA and LTE)";
break;
case 23:
network_type = "EHRPD";
break;
case 24:
network_type = "HYBRID (CDMA and EHRPD)";
break;
default:
network_type = "Unknown";
}
return network_type;
}
std::string get_signal_bars(float rssi) { return get_signal_bars(rssi, true); }
std::string get_signal_bars(float rssi, bool color) {
// adapted from wifi_component.cpp
// LOWER ONE QUARTER BLOCK
// Unicode: U+2582, UTF-8: E2 96 82
// LOWER HALF BLOCK
// Unicode: U+2584, UTF-8: E2 96 84
// LOWER THREE QUARTERS BLOCK
// Unicode: U+2586, UTF-8: E2 96 86
// FULL BLOCK
// Unicode: U+2588, UTF-8: E2 96 88
if (!color) {
if (std::isnan(rssi)) {
return {};
} else if (rssi >= -50) {
return "High";
} else if (rssi >= -65) {
return "Good";
} else if (rssi >= -85) {
return "Medium";
} else {
return "Low";
}
} else {
if (std::isnan(rssi)) {
return "\033[0;31m" // red
"!"
"\033[0;37m"
"\xe2\x96\x84"
"\xe2\x96\x86"
"\xe2\x96\x88"
"\033[0m";
} else if (rssi >= -50) {
return "\033[0;32m" // green
"\xe2\x96\x82"
"\xe2\x96\x84"
"\xe2\x96\x86"
"\xe2\x96\x88"
"\033[0m";
} else if (rssi >= -65) {
return "\033[0;33m" // yellow
"\xe2\x96\x82"
"\xe2\x96\x84"
"\xe2\x96\x86"
"\033[0;37m"
"\xe2\x96\x88"
"\033[0m";
} else if (rssi >= -85) {
return "\033[0;33m" // yellow
"\xe2\x96\x82"
"\xe2\x96\x84"
"\033[0;37m"
"\xe2\x96\x86"
"\xe2\x96\x88"
"\033[0m";
} else {
return "\033[0;31m" // red
"\xe2\x96\x82"
"\033[0;37m"
"\xe2\x96\x84"
"\xe2\x96\x86"
"\xe2\x96\x88"
"\033[0m";
}
}
}
} // namespace modem } // namespace modem
} // namespace esphome } // namespace esphome
#endif // USE_ESP_IDF #endif // USE_ESP_IDF

View file

@ -10,8 +10,10 @@ namespace esphome {
namespace modem { namespace modem {
std::string command_result_to_string(command_result err); std::string command_result_to_string(command_result err);
std::string state_to_string(ModemComponentState state); std::string state_to_string(ModemComponentState state);
std::string network_system_mode_to_string(int mode);
std::string get_signal_bars(float rssi);
std::string get_signal_bars(float rssi, bool color);
} // namespace modem } // namespace modem
} // namespace esphome } // namespace esphome

View file

@ -1,7 +1,7 @@
import esphome.codegen as cg import esphome.codegen as cg
from esphome.components import text_sensor from esphome.components import text_sensor
import esphome.config_validation as cv import esphome.config_validation as cv
from esphome.const import CONF_ID, DEVICE_CLASS_EMPTY from esphome.const import CONF_ID, CONF_SIGNAL_STRENGTH, DEVICE_CLASS_EMPTY
from .. import MODEM_COMPONENT_SCHEMA, final_validate_platform, modem_ns from .. import MODEM_COMPONENT_SCHEMA, final_validate_platform, modem_ns
@ -24,6 +24,9 @@ CONFIG_SCHEMA = cv.All(
cv.Optional(CONF_NETWORK_TYPE): text_sensor.text_sensor_schema( cv.Optional(CONF_NETWORK_TYPE): text_sensor.text_sensor_schema(
device_class=DEVICE_CLASS_EMPTY, device_class=DEVICE_CLASS_EMPTY,
), ),
cv.Optional(CONF_SIGNAL_STRENGTH): text_sensor.text_sensor_schema(
device_class=DEVICE_CLASS_EMPTY,
),
} }
) )
.extend(MODEM_COMPONENT_SCHEMA) .extend(MODEM_COMPONENT_SCHEMA)
@ -40,4 +43,8 @@ async def to_code(config):
network_type_text_sensor = await text_sensor.new_text_sensor(network_type) network_type_text_sensor = await text_sensor.new_text_sensor(network_type)
cg.add(var.set_network_type_text_sensor(network_type_text_sensor)) cg.add(var.set_network_type_text_sensor(network_type_text_sensor))
if signal_strength := config.get(CONF_SIGNAL_STRENGTH, None):
signal_strength_text_sensor = await text_sensor.new_text_sensor(signal_strength)
cg.add(var.set_signal_strength_text_sensor(signal_strength_text_sensor))
await cg.register_component(var, config) await cg.register_component(var, config)

View file

@ -11,6 +11,7 @@
#include "esphome/core/application.h" #include "esphome/core/application.h"
#include "../modem_component.h" #include "../modem_component.h"
#include "../helpers.h"
#define ESPHL_ERROR_CHECK(err, message) \ #define ESPHL_ERROR_CHECK(err, message) \
if ((err) != ESP_OK) { \ if ((err) != ESP_OK) { \
@ -38,6 +39,7 @@ void ModemTextSensor::update() {
ESP_LOGD(TAG, "Modem text_sensor update"); ESP_LOGD(TAG, "Modem text_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_network_type_text_sensor_(); this->update_network_type_text_sensor_();
this->update_signal_strength_text_sensor_();
} }
} }
@ -46,74 +48,22 @@ void ModemTextSensor::update_network_type_text_sensor_() {
int act; int act;
std::string network_type = "Not available"; std::string network_type = "Not available";
if (modem::global_modem_component->dce->get_network_system_mode(act) == command_result::OK) { if (modem::global_modem_component->dce->get_network_system_mode(act) == command_result::OK) {
// Access Technology from AT+CNSMOD? network_type = network_system_mode_to_string(act);
// see https://www.waveshare.com/w/upload/a/af/SIM7500_SIM7600_Series_AT_Command_Manual_V3.00.pdf, page 109
switch (act) {
case 0:
network_type = "No service";
break;
case 1:
network_type = "GSM";
break;
case 2:
network_type = "GPRS";
break;
case 3:
network_type = "EGPRS (EDGE)";
break;
case 4:
network_type = "WCDMA";
break;
case 5:
network_type = "HSDPA only (WCDMA)";
break;
case 6:
network_type = "HSUPA only (WCDMA)";
break;
case 7:
network_type = "HSPA (HSDPA and HSUPA, WCDMA)";
break;
case 8:
network_type = "LTE";
break;
case 9:
network_type = "TDS-CDMA";
break;
case 10:
network_type = "TDS-HSDPA only";
break;
case 11:
network_type = "TDS-HSUPA only";
break;
case 12:
network_type = "TDS-HSPA (HSDPA and HSUPA)";
break;
case 13:
network_type = "CDMA";
break;
case 14:
network_type = "EVDO";
break;
case 15:
network_type = "HYBRID (CDMA and EVDO)";
break;
case 16:
network_type = "1XLTE (CDMA and LTE)";
break;
case 23:
network_type = "EHRPD";
break;
case 24:
network_type = "HYBRID (CDMA and EHRPD)";
break;
default:
network_type = "Unknown";
}
} }
this->network_type_text_sensor_->publish_state(network_type); this->network_type_text_sensor_->publish_state(network_type);
} }
} }
void ModemTextSensor::update_signal_strength_text_sensor_() {
if (modem::global_modem_component->modem_ready() && this->network_type_text_sensor_) {
float rssi, ber;
if (modem::global_modem_component->get_signal_quality(rssi, ber)) {
std::string bars = get_signal_bars(rssi, false);
this->signal_strength_text_sensor_->publish_state(bars);
}
}
}
} // namespace modem } // namespace modem
} // namespace esphome } // namespace esphome

View file

@ -18,6 +18,9 @@ class ModemTextSensor : public PollingComponent {
void set_network_type_text_sensor(text_sensor::TextSensor *network_type_text_sensor) { void set_network_type_text_sensor(text_sensor::TextSensor *network_type_text_sensor) {
this->network_type_text_sensor_ = network_type_text_sensor; this->network_type_text_sensor_ = network_type_text_sensor;
} }
void set_signal_strength_text_sensor(text_sensor::TextSensor *signal_strength_text_sensor) {
this->signal_strength_text_sensor_ = signal_strength_text_sensor;
}
// ========== INTERNAL METHODS ========== // ========== INTERNAL METHODS ==========
// (In most use cases you won't need these) // (In most use cases you won't need these)
@ -28,7 +31,9 @@ class ModemTextSensor : public PollingComponent {
protected: protected:
text_sensor::TextSensor *network_type_text_sensor_{nullptr}; text_sensor::TextSensor *network_type_text_sensor_{nullptr};
text_sensor::TextSensor *signal_strength_text_sensor_{nullptr};
void update_network_type_text_sensor_(); void update_network_type_text_sensor_();
void update_signal_strength_text_sensor_();
}; };
} // namespace modem } // namespace modem

View file

@ -12,19 +12,22 @@ modem:
pin_code: "0000" pin_code: "0000"
enable_on_boot: True enable_on_boot: True
enable_cmux: True enable_cmux: True
reboot_timeout: 5min
init_at: init_at:
- AT - AT
on_not_responding: on_not_responding:
logger.log: "modem not responding" logger.log: "modem not responding"
on_connect: on_connect:
logger.log: "got IP" logger.log: "modem connected"
on_disconnect: on_disconnect:
logger.log: "lost IP" logger.log: "modem disconnected"
text_sensor: text_sensor:
- platform: modem - platform: modem
network_type: network_type:
name: network type name: network type
signal_strength:
name: Signal strength
sensor: sensor:
- platform: modem - platform: modem