ESPHome 2026.6.0-dev
Loading...
Searching...
No Matches
binary_sensor_map.cpp
Go to the documentation of this file.
1#include "binary_sensor_map.h"
2#include "esphome/core/log.h"
3
5
6static const char *const TAG = "binary_sensor_map";
7
8void BinarySensorMap::dump_config() { LOG_SENSOR(" ", "binary_sensor_map", this); }
9
11 switch (this->sensor_type_) {
13 this->process_group_();
14 break;
16 this->process_sum_();
17 break;
19 this->process_bayesian_();
20 break;
21 }
22}
23
25 float total_current_value = 0.0;
26 uint8_t num_active_sensors = 0;
27 uint64_t mask = 0x00;
28
29 // - check all binary_sensors for its state
30 // - if active, add its value to total_current_value.
31 // - creates a bitmask for the binary_sensor states on all channels
32 for (size_t i = 0; i < this->channels_.size(); i++) {
33 auto bs = this->channels_[i];
34 if (bs.binary_sensor->state) {
35 num_active_sensors++;
36 total_current_value += bs.parameters.sensor_value;
37 mask |= 1ULL << i;
38 }
39 }
40
41 // potentially update state only if a binary_sensor is active
42 if (mask != 0ULL) {
43 // publish the average if the bitmask has changed
44 if (this->last_mask_ != mask) {
45 float publish_value = total_current_value / num_active_sensors;
46 this->publish_state(publish_value);
47 }
48 } else if (this->last_mask_ != 0ULL) {
49 // no buttons are pressed and the states have changed since last run, so publish NAN
50 ESP_LOGV(TAG, "'%s' - No binary sensor active, publishing NAN", this->name_.c_str());
51 this->publish_state(NAN);
52 }
53
54 this->last_mask_ = mask;
55}
56
58 float total_current_value = 0.0;
59 uint64_t mask = 0x00;
60
61 // - check all binary_sensor states
62 // - if active, add its value to total_current_value
63 // - creates a bitmask for the binary_sensor states on all channels
64 for (size_t i = 0; i < this->channels_.size(); i++) {
65 auto bs = this->channels_[i];
66 if (bs.binary_sensor->state) {
67 total_current_value += bs.parameters.sensor_value;
68 mask |= 1ULL << i;
69 }
70 }
71
72 // update state only if any binary_sensor states have changed or if no state has ever been sent on boot
73 if ((this->last_mask_ != mask) || (!this->has_state())) {
74 this->publish_state(total_current_value);
75 }
76
77 this->last_mask_ = mask;
78}
79
81 float posterior_probability = this->bayesian_prior_;
82 uint64_t mask = 0x00;
83
84 // - compute the posterior probability by taking the product of the predicate probablities for each observation
85 // - create a bitmask for the binary_sensor states on all channels/observations
86 for (size_t i = 0; i < this->channels_.size(); i++) {
87 auto bs = this->channels_[i];
88
89 posterior_probability *=
90 this->bayesian_predicate_(bs.binary_sensor->state, posterior_probability,
91 bs.parameters.probabilities.given_true, bs.parameters.probabilities.given_false);
92
93 mask |= ((uint64_t) (bs.binary_sensor->state)) << i;
94 }
95
96 // update state only if any binary_sensor states have changed or if no state has ever been sent on boot
97 if ((this->last_mask_ != mask) || (!this->has_state())) {
98 this->publish_state(posterior_probability);
99 }
100
101 this->last_mask_ = mask;
102}
103
104float BinarySensorMap::bayesian_predicate_(bool sensor_state, float prior, float prob_given_true,
105 float prob_given_false) {
106 float prob_state_source_true = prob_given_true;
107 float prob_state_source_false = prob_given_false;
108
109 // if sensor is off, then we use the probabilities for the observation's complement
110 if (!sensor_state) {
111 prob_state_source_true = 1 - prob_given_true;
112 prob_state_source_false = 1 - prob_given_false;
113 }
114
115 return prob_state_source_true / (prior * prob_state_source_true + (1.0 - prior) * prob_state_source_false);
116}
117
119 BinarySensorMapChannel sensor_channel{
120 .binary_sensor = sensor,
121 .parameters{
122 .sensor_value = value,
123 },
124 };
125 this->channels_.push_back(sensor_channel);
126}
127
128void BinarySensorMap::add_channel(binary_sensor::BinarySensor *sensor, float prob_given_true, float prob_given_false) {
129 BinarySensorMapChannel sensor_channel{
130 .binary_sensor = sensor,
131 .parameters{
132 .probabilities{
133 .given_true = prob_given_true,
134 .given_false = prob_given_false,
135 },
136 },
137 };
138 this->channels_.push_back(sensor_channel);
139}
140} // namespace esphome::binary_sensor_map
bool has_state() const
constexpr const char * c_str() const
Definition string_ref.h:73
Base class for all binary_sensor-type classes.
void add_channel(binary_sensor::BinarySensor *sensor, float value)
Add binary_sensors to the group when only one parameter is needed for the configured mapping type.
float bayesian_predicate_(bool sensor_state, float prior, float prob_given_true, float prob_given_false)
Computes the Bayesian predicate for a specific observation If the sensor state is false,...
void loop() override
The loop calls the configured type processing method.
std::vector< BinarySensorMapChannel > channels_
void process_group_()
Methods to process the binary_sensor_maps types.
void publish_state(float state)
Publish a new state to the front-end.
Definition sensor.cpp:68