mirror of
https://github.com/esphome/esphome.git
synced 2024-11-25 00:18:11 +01:00
Mopeka Pro Check improvement to allow user to configure the sensor reporting for lower quality readings (#7475)
This commit is contained in:
parent
90b076eccd
commit
0dab280440
4 changed files with 108 additions and 24 deletions
|
@ -17,6 +17,8 @@ void MopekaProCheck::dump_config() {
|
||||||
LOG_SENSOR(" ", "Temperature", this->temperature_);
|
LOG_SENSOR(" ", "Temperature", this->temperature_);
|
||||||
LOG_SENSOR(" ", "Battery Level", this->battery_level_);
|
LOG_SENSOR(" ", "Battery Level", this->battery_level_);
|
||||||
LOG_SENSOR(" ", "Reading Distance", this->distance_);
|
LOG_SENSOR(" ", "Reading Distance", this->distance_);
|
||||||
|
LOG_SENSOR(" ", "Read Quality", this->read_quality_);
|
||||||
|
LOG_SENSOR(" ", "Ignored Reads", this->ignored_reads_);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -66,20 +68,34 @@ bool MopekaProCheck::parse_device(const esp32_ble_tracker::ESPBTDevice &device)
|
||||||
this->battery_level_->publish_state(level);
|
this->battery_level_->publish_state(level);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get the quality value
|
||||||
|
SensorReadQuality quality_value = this->parse_read_quality_(manu_data.data);
|
||||||
|
if (this->read_quality_ != nullptr) {
|
||||||
|
this->read_quality_->publish_state(static_cast<int>(quality_value));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Determine if we have a good enough quality of read to report level and distance
|
||||||
|
// sensors. This sensor is reported regardless of distance or level sensors being enabled
|
||||||
|
if (quality_value < this->min_signal_quality_) {
|
||||||
|
ESP_LOGW(TAG, "Read Quality too low to report distance or level");
|
||||||
|
this->ignored_read_count_++;
|
||||||
|
} else {
|
||||||
|
// reset to zero since read quality was sufficient
|
||||||
|
this->ignored_read_count_ = 0;
|
||||||
|
}
|
||||||
|
// Report number of contiguous ignored reads if sensor defined
|
||||||
|
if (this->ignored_reads_ != nullptr) {
|
||||||
|
this->ignored_reads_->publish_state(this->ignored_read_count_);
|
||||||
|
}
|
||||||
|
|
||||||
// Get distance and level if either are sensors
|
// Get distance and level if either are sensors
|
||||||
if ((this->distance_ != nullptr) || (this->level_ != nullptr)) {
|
if ((this->distance_ != nullptr) || (this->level_ != nullptr)) {
|
||||||
uint32_t distance_value = this->parse_distance_(manu_data.data);
|
uint32_t distance_value = this->parse_distance_(manu_data.data);
|
||||||
SensorReadQuality quality_value = this->parse_read_quality_(manu_data.data);
|
|
||||||
ESP_LOGD(TAG, "Distance Sensor: Quality (0x%X) Distance (%" PRId32 "mm)", quality_value, distance_value);
|
ESP_LOGD(TAG, "Distance Sensor: Quality (0x%X) Distance (%" PRId32 "mm)", quality_value, distance_value);
|
||||||
if (quality_value < QUALITY_HIGH) {
|
|
||||||
ESP_LOGW(TAG, "Poor read quality.");
|
|
||||||
}
|
|
||||||
if (quality_value < QUALITY_MED) {
|
|
||||||
// if really bad reading set to 0
|
|
||||||
ESP_LOGW(TAG, "Setting distance to 0");
|
|
||||||
distance_value = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
// only update distance and level sensors if read quality was sufficient. This can be determined by
|
||||||
|
// if the ignored_read_count is zero.
|
||||||
|
if (this->ignored_read_count_ == 0) {
|
||||||
// update distance sensor
|
// update distance sensor
|
||||||
if (this->distance_ != nullptr) {
|
if (this->distance_ != nullptr) {
|
||||||
this->distance_->publish_state(distance_value);
|
this->distance_->publish_state(distance_value);
|
||||||
|
@ -96,6 +112,7 @@ bool MopekaProCheck::parse_device(const esp32_ble_tracker::ESPBTDevice &device)
|
||||||
this->level_->publish_state(tank_level);
|
this->level_->publish_state(tank_level);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Get temperature of sensor
|
// Get temperature of sensor
|
||||||
if (this->temperature_ != nullptr) {
|
if (this->temperature_ != nullptr) {
|
||||||
|
@ -131,6 +148,8 @@ uint32_t MopekaProCheck::parse_distance_(const std::vector<uint8_t> &message) {
|
||||||
uint8_t MopekaProCheck::parse_temperature_(const std::vector<uint8_t> &message) { return (message[2] & 0x7F) - 40; }
|
uint8_t MopekaProCheck::parse_temperature_(const std::vector<uint8_t> &message) { return (message[2] & 0x7F) - 40; }
|
||||||
|
|
||||||
SensorReadQuality MopekaProCheck::parse_read_quality_(const std::vector<uint8_t> &message) {
|
SensorReadQuality MopekaProCheck::parse_read_quality_(const std::vector<uint8_t> &message) {
|
||||||
|
// Since a 8 bit value is being shifted and truncated to 2 bits all possible values are defined as enumeration
|
||||||
|
// value and the static cast is safe.
|
||||||
return static_cast<SensorReadQuality>(message[4] >> 6);
|
return static_cast<SensorReadQuality>(message[4] >> 6);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -24,9 +24,9 @@ enum SensorType {
|
||||||
};
|
};
|
||||||
|
|
||||||
// Sensor read quality. If sensor is poorly placed or tank level
|
// Sensor read quality. If sensor is poorly placed or tank level
|
||||||
// gets too low the read quality will show and the distanace
|
// gets too low the read quality will show and the distance
|
||||||
// measurement may be inaccurate.
|
// measurement may be inaccurate.
|
||||||
enum SensorReadQuality { QUALITY_HIGH = 0x3, QUALITY_MED = 0x2, QUALITY_LOW = 0x1, QUALITY_NONE = 0x0 };
|
enum SensorReadQuality { QUALITY_HIGH = 0x3, QUALITY_MED = 0x2, QUALITY_LOW = 0x1, QUALITY_ZERO = 0x0 };
|
||||||
|
|
||||||
class MopekaProCheck : public Component, public esp32_ble_tracker::ESPBTDeviceListener {
|
class MopekaProCheck : public Component, public esp32_ble_tracker::ESPBTDeviceListener {
|
||||||
public:
|
public:
|
||||||
|
@ -35,11 +35,14 @@ class MopekaProCheck : public Component, public esp32_ble_tracker::ESPBTDeviceLi
|
||||||
bool parse_device(const esp32_ble_tracker::ESPBTDevice &device) override;
|
bool parse_device(const esp32_ble_tracker::ESPBTDevice &device) override;
|
||||||
void dump_config() override;
|
void dump_config() override;
|
||||||
float get_setup_priority() const override { return setup_priority::DATA; }
|
float get_setup_priority() const override { return setup_priority::DATA; }
|
||||||
|
void set_min_signal_quality(SensorReadQuality min) { this->min_signal_quality_ = min; };
|
||||||
|
|
||||||
void set_level(sensor::Sensor *level) { level_ = level; };
|
void set_level(sensor::Sensor *level) { level_ = level; };
|
||||||
void set_temperature(sensor::Sensor *temperature) { temperature_ = temperature; };
|
void set_temperature(sensor::Sensor *temperature) { temperature_ = temperature; };
|
||||||
void set_battery_level(sensor::Sensor *bat) { battery_level_ = bat; };
|
void set_battery_level(sensor::Sensor *bat) { battery_level_ = bat; };
|
||||||
void set_distance(sensor::Sensor *distance) { distance_ = distance; };
|
void set_distance(sensor::Sensor *distance) { distance_ = distance; };
|
||||||
|
void set_signal_quality(sensor::Sensor *rq) { read_quality_ = rq; };
|
||||||
|
void set_ignored_reads(sensor::Sensor *ir) { ignored_reads_ = ir; };
|
||||||
void set_tank_full(float full) { full_mm_ = full; };
|
void set_tank_full(float full) { full_mm_ = full; };
|
||||||
void set_tank_empty(float empty) { empty_mm_ = empty; };
|
void set_tank_empty(float empty) { empty_mm_ = empty; };
|
||||||
|
|
||||||
|
@ -49,9 +52,13 @@ class MopekaProCheck : public Component, public esp32_ble_tracker::ESPBTDeviceLi
|
||||||
sensor::Sensor *temperature_{nullptr};
|
sensor::Sensor *temperature_{nullptr};
|
||||||
sensor::Sensor *distance_{nullptr};
|
sensor::Sensor *distance_{nullptr};
|
||||||
sensor::Sensor *battery_level_{nullptr};
|
sensor::Sensor *battery_level_{nullptr};
|
||||||
|
sensor::Sensor *read_quality_{nullptr};
|
||||||
|
sensor::Sensor *ignored_reads_{nullptr};
|
||||||
|
|
||||||
uint32_t full_mm_;
|
uint32_t full_mm_;
|
||||||
uint32_t empty_mm_;
|
uint32_t empty_mm_;
|
||||||
|
uint32_t ignored_read_count_ = 0;
|
||||||
|
SensorReadQuality min_signal_quality_ = QUALITY_MED;
|
||||||
|
|
||||||
uint8_t parse_battery_level_(const std::vector<uint8_t> &message);
|
uint8_t parse_battery_level_(const std::vector<uint8_t> &message);
|
||||||
uint32_t parse_distance_(const std::vector<uint8_t> &message);
|
uint32_t parse_distance_(const std::vector<uint8_t> &message);
|
||||||
|
|
|
@ -5,9 +5,12 @@ from esphome.const import (
|
||||||
CONF_DISTANCE,
|
CONF_DISTANCE,
|
||||||
CONF_MAC_ADDRESS,
|
CONF_MAC_ADDRESS,
|
||||||
CONF_ID,
|
CONF_ID,
|
||||||
|
ICON_COUNTER,
|
||||||
ICON_THERMOMETER,
|
ICON_THERMOMETER,
|
||||||
ICON_RULER,
|
ICON_RULER,
|
||||||
|
ICON_SIGNAL,
|
||||||
UNIT_PERCENT,
|
UNIT_PERCENT,
|
||||||
|
UNIT_EMPTY,
|
||||||
CONF_LEVEL,
|
CONF_LEVEL,
|
||||||
CONF_TEMPERATURE,
|
CONF_TEMPERATURE,
|
||||||
DEVICE_CLASS_TEMPERATURE,
|
DEVICE_CLASS_TEMPERATURE,
|
||||||
|
@ -16,11 +19,15 @@ from esphome.const import (
|
||||||
STATE_CLASS_MEASUREMENT,
|
STATE_CLASS_MEASUREMENT,
|
||||||
CONF_BATTERY_LEVEL,
|
CONF_BATTERY_LEVEL,
|
||||||
DEVICE_CLASS_BATTERY,
|
DEVICE_CLASS_BATTERY,
|
||||||
|
ENTITY_CATEGORY_DIAGNOSTIC,
|
||||||
)
|
)
|
||||||
|
|
||||||
CONF_TANK_TYPE = "tank_type"
|
CONF_TANK_TYPE = "tank_type"
|
||||||
CONF_CUSTOM_DISTANCE_FULL = "custom_distance_full"
|
CONF_CUSTOM_DISTANCE_FULL = "custom_distance_full"
|
||||||
CONF_CUSTOM_DISTANCE_EMPTY = "custom_distance_empty"
|
CONF_CUSTOM_DISTANCE_EMPTY = "custom_distance_empty"
|
||||||
|
CONF_SIGNAL_QUALITY = "signal_quality"
|
||||||
|
CONF_MINIMUM_SIGNAL_QUALITY = "minimum_signal_quality"
|
||||||
|
CONF_IGNORED_READS = "ignored_reads"
|
||||||
|
|
||||||
ICON_PROPANE_TANK = "mdi:propane-tank"
|
ICON_PROPANE_TANK = "mdi:propane-tank"
|
||||||
|
|
||||||
|
@ -56,6 +63,14 @@ MopekaProCheck = mopeka_pro_check_ns.class_(
|
||||||
"MopekaProCheck", esp32_ble_tracker.ESPBTDeviceListener, cg.Component
|
"MopekaProCheck", esp32_ble_tracker.ESPBTDeviceListener, cg.Component
|
||||||
)
|
)
|
||||||
|
|
||||||
|
SensorReadQuality = mopeka_pro_check_ns.enum("SensorReadQuality")
|
||||||
|
SIGNAL_QUALITIES = {
|
||||||
|
"ZERO": SensorReadQuality.QUALITY_ZERO,
|
||||||
|
"LOW": SensorReadQuality.QUALITY_LOW,
|
||||||
|
"MEDIUM": SensorReadQuality.QUALITY_MED,
|
||||||
|
"HIGH": SensorReadQuality.QUALITY_HIGH,
|
||||||
|
}
|
||||||
|
|
||||||
CONFIG_SCHEMA = (
|
CONFIG_SCHEMA = (
|
||||||
cv.Schema(
|
cv.Schema(
|
||||||
{
|
{
|
||||||
|
@ -89,6 +104,21 @@ CONFIG_SCHEMA = (
|
||||||
device_class=DEVICE_CLASS_BATTERY,
|
device_class=DEVICE_CLASS_BATTERY,
|
||||||
state_class=STATE_CLASS_MEASUREMENT,
|
state_class=STATE_CLASS_MEASUREMENT,
|
||||||
),
|
),
|
||||||
|
cv.Optional(CONF_SIGNAL_QUALITY): sensor.sensor_schema(
|
||||||
|
unit_of_measurement=UNIT_EMPTY,
|
||||||
|
icon=ICON_SIGNAL,
|
||||||
|
accuracy_decimals=0,
|
||||||
|
state_class=STATE_CLASS_MEASUREMENT,
|
||||||
|
),
|
||||||
|
cv.Optional(CONF_IGNORED_READS): sensor.sensor_schema(
|
||||||
|
unit_of_measurement=UNIT_EMPTY,
|
||||||
|
icon=ICON_COUNTER,
|
||||||
|
accuracy_decimals=0,
|
||||||
|
entity_category=ENTITY_CATEGORY_DIAGNOSTIC,
|
||||||
|
),
|
||||||
|
cv.Optional(CONF_MINIMUM_SIGNAL_QUALITY, default="MEDIUM"): cv.enum(
|
||||||
|
SIGNAL_QUALITIES, upper=True
|
||||||
|
),
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
.extend(esp32_ble_tracker.ESP_BLE_DEVICE_SCHEMA)
|
.extend(esp32_ble_tracker.ESP_BLE_DEVICE_SCHEMA)
|
||||||
|
@ -119,6 +149,11 @@ async def to_code(config):
|
||||||
cg.add(var.set_tank_empty(CONF_SUPPORTED_TANKS_MAP[t][0]))
|
cg.add(var.set_tank_empty(CONF_SUPPORTED_TANKS_MAP[t][0]))
|
||||||
cg.add(var.set_tank_full(CONF_SUPPORTED_TANKS_MAP[t][1]))
|
cg.add(var.set_tank_full(CONF_SUPPORTED_TANKS_MAP[t][1]))
|
||||||
|
|
||||||
|
if (
|
||||||
|
minimum_signal_quality := config.get(CONF_MINIMUM_SIGNAL_QUALITY, None)
|
||||||
|
) is not None:
|
||||||
|
cg.add(var.set_min_signal_quality(minimum_signal_quality))
|
||||||
|
|
||||||
if CONF_TEMPERATURE in config:
|
if CONF_TEMPERATURE in config:
|
||||||
sens = await sensor.new_sensor(config[CONF_TEMPERATURE])
|
sens = await sensor.new_sensor(config[CONF_TEMPERATURE])
|
||||||
cg.add(var.set_temperature(sens))
|
cg.add(var.set_temperature(sens))
|
||||||
|
@ -131,3 +166,9 @@ async def to_code(config):
|
||||||
if CONF_BATTERY_LEVEL in config:
|
if CONF_BATTERY_LEVEL in config:
|
||||||
sens = await sensor.new_sensor(config[CONF_BATTERY_LEVEL])
|
sens = await sensor.new_sensor(config[CONF_BATTERY_LEVEL])
|
||||||
cg.add(var.set_battery_level(sens))
|
cg.add(var.set_battery_level(sens))
|
||||||
|
if CONF_SIGNAL_QUALITY in config:
|
||||||
|
sens = await sensor.new_sensor(config[CONF_SIGNAL_QUALITY])
|
||||||
|
cg.add(var.set_signal_quality(sens))
|
||||||
|
if CONF_IGNORED_READS in config:
|
||||||
|
sens = await sensor.new_sensor(config[CONF_IGNORED_READS])
|
||||||
|
cg.add(var.set_ignored_reads(sens))
|
||||||
|
|
|
@ -14,3 +14,20 @@ sensor:
|
||||||
name: Propane test distance
|
name: Propane test distance
|
||||||
battery_level:
|
battery_level:
|
||||||
name: Propane test battery level
|
name: Propane test battery level
|
||||||
|
|
||||||
|
- platform: mopeka_pro_check
|
||||||
|
mac_address: AA:BB:CC:DD:EE:FF
|
||||||
|
tank_type: 20LB_V
|
||||||
|
temperature:
|
||||||
|
name: "Propane test2 temp"
|
||||||
|
level:
|
||||||
|
name: "Propane test2 level"
|
||||||
|
distance:
|
||||||
|
name: "Propane test2 distance"
|
||||||
|
battery_level:
|
||||||
|
name: "Propane test2 battery level"
|
||||||
|
signal_quality:
|
||||||
|
name: "propane test2 read quality"
|
||||||
|
ignored_reads:
|
||||||
|
name: "propane test2 ignored reads"
|
||||||
|
minimum_signal_quality: "LOW"
|
||||||
|
|
Loading…
Reference in a new issue