ESPHome 2026.11.0-dev
Loading...
Searching...
No Matches
ufm01.h
Go to the documentation of this file.
1#pragma once
2
5#ifdef USE_BINARY_SENSOR
7#endif
8#ifdef USE_SENSOR
10#endif
11#ifdef USE_TEXT_SENSOR
13#endif
15
16#include <array>
17#include <cstdint>
18
19// component API definition at https://www.sciosense.com/wp-content/uploads/2025/06/UFM-01-Datasheet-1.pdf
20
21namespace esphome::ufm01 {
22
23namespace testing {
24class TestableUFM01;
25} // namespace testing
26
27static constexpr size_t FRAME_SIZE = 32;
28static constexpr size_t PASSIVE_FRAME_SIZE = 23;
29static constexpr size_t PASSIVE_FRAME_WITH_ID_SIZE = 39;
30#ifdef USE_UFM01_METER_ID
31static constexpr size_t PASSIVE_FRAME_MAX_SIZE = PASSIVE_FRAME_WITH_ID_SIZE;
32#else
33static constexpr size_t PASSIVE_FRAME_MAX_SIZE = PASSIVE_FRAME_SIZE;
34#endif
35static constexpr size_t SOFTWARE_VERSION_RESPONSE_SIZE = 7;
36static constexpr size_t DEVICE_ID_LENGTH = 5;
37static constexpr size_t DEVICE_ID_STRING_LENGTH = 10;
38static constexpr size_t SOFTWARE_VERSION_LENGTH = 4;
39static constexpr size_t SOFTWARE_VERSION_STRING_LENGTH = 8;
40
41enum class OperatingMode : uint8_t {
42 STARTUP = 0,
43 ACTIVE_STREAM = 1,
44 PASSIVE_POLL = 2,
45};
46
47enum class StartupPhase : uint8_t {
48 WAIT,
52#ifdef USE_UFM01_SOFTWARE_VERSION
54#endif
58};
59
60enum class ReadResult : uint8_t {
64};
65
67#ifdef USE_SENSOR
68 SUB_SENSOR(accumulated_flow)
69 SUB_SENSOR(flow)
70 SUB_SENSOR(temperature)
71#endif
72
73#ifdef USE_BINARY_SENSOR
74 SUB_BINARY_SENSOR(ufc_chip_error)
75 SUB_BINARY_SENSOR(flow_direction_wrong)
76 SUB_BINARY_SENSOR(empty_tube)
77 SUB_BINARY_SENSOR(flow_rate_out_of_range)
78#endif
79
80#ifdef USE_UFM01_METER_ID
81 SUB_TEXT_SENSOR(meter_id)
82#endif
83#ifdef USE_UFM01_SOFTWARE_VERSION
84 SUB_TEXT_SENSOR(software_version)
85#endif
86
87 public:
88 void setup() override;
89
90 void dump_config() override;
91
92 void loop() override;
93
94#ifdef USE_UFM01_CLEAR_ACCUMULATED_FLOW_ACTION
96 void request_clear_accumulated_flow();
97#endif
98
99 float get_setup_priority() const override;
100
101 private:
102#ifdef USE_UFM01_CLEAR_ACCUMULATED_FLOW_ACTION
103 bool can_start_clear_action_() const;
104 void loop_pending_clear_action_(uint32_t now);
105 void finish_pending_clear_();
106#endif
107 void send_command_no_wait_(const std::array<uint8_t, 7> &command);
108 bool consume_ack_();
109 void flush_rx_();
110 bool process_active_stream_(uint32_t now);
111 void on_active_frame_(uint8_t data[FRAME_SIZE], uint32_t now);
112#ifdef USE_UFM01_METER_ID
113 void publish_meter_id_from_frame_(const uint8_t data[FRAME_SIZE]);
114#endif
115 void publish_stale_flow_and_temperature_();
116#ifdef USE_UFM01_SOFTWARE_VERSION
117 void start_software_version_read_(uint32_t now);
118 ReadResult continue_software_version_read_(uint32_t now);
119 void finish_software_version_read_(ReadResult result, uint32_t now);
120 bool service_software_version_(uint32_t now);
121#endif
122
123 void loop_startup_(uint32_t now);
124 void loop_active_stream_(uint32_t now);
125 void loop_passive_poll_(uint32_t now);
126 void set_mode_(OperatingMode mode, uint32_t now);
127 void set_startup_phase_(StartupPhase phase, uint32_t now);
128 void send_reset_(const LogString *status, uint32_t now);
129 void enter_active_stream_(const LogString *reason, uint32_t now);
130 void enter_passive_from_stale_(uint32_t now);
131 void restart_startup_(const LogString *reason, uint32_t now);
132 void start_passive_read_(uint32_t now);
133 ReadResult continue_passive_read_(uint32_t now);
134 void note_passive_poll_result_(bool success, uint32_t now);
135
136 uint32_t phase_start_ms_{0};
137 uint32_t startup_wait_ms_{0};
138 uint32_t last_valid_frame_ms_{0};
139 uint32_t last_poll_ms_{0};
140 // Shared by the passive read and the software version read, which never overlap
141 uint32_t passive_start_ms_{0};
142#ifdef USE_UFM01_SOFTWARE_VERSION
143 uint32_t last_software_version_attempt_ms_{0};
144#endif
145#ifdef USE_UFM01_CLEAR_ACCUMULATED_FLOW_ACTION
146 uint32_t pending_clear_start_ms_{0};
147#endif
148 int32_t read_index_{0};
149
150 OperatingMode operating_mode_{OperatingMode::STARTUP};
151 StartupPhase startup_phase_{StartupPhase::WAIT};
152 bool reset_retried_{false};
153 bool passive_read_pending_{false};
154 uint8_t consecutive_passive_failures_{0};
155 uint8_t passive_index_{0};
156 uint8_t passive_expected_size_{PASSIVE_FRAME_SIZE};
157 uint8_t passive_start_byte_2_{0};
158#ifdef USE_UFM01_SOFTWARE_VERSION
159 bool software_version_published_{false};
160 bool software_version_read_pending_{false};
161 uint8_t software_version_failures_{0};
162#endif
163#ifdef USE_UFM01_METER_ID
164 bool meter_id_published_{false};
165 bool meter_id_invalid_logged_{false};
166#endif
167#ifdef USE_UFM01_CLEAR_ACCUMULATED_FLOW_ACTION
168 bool clear_pending_{false};
169 bool pending_clear_sent_{false};
170#endif
171
172 uint8_t passive_frame_[PASSIVE_FRAME_MAX_SIZE];
173 uint8_t data_[FRAME_SIZE];
174
175 friend class testing::TestableUFM01;
176};
177
178} // namespace esphome::ufm01
BedjetMode mode
BedJet operating mode.
uint8_t status
Definition bl0942.h:8
virtual void setup()
Where the component's initialization should happen.
Definition component.cpp:84
static void uint32_t
uint16_t temperature
Definition sun_gtil2.cpp:12