Skip to content

Commit c893b68

Browse files
authored
Merge branch 'master' into feat/matter_water_freeze_detector_ep
2 parents 5bdd818 + e540af2 commit c893b68

File tree

26 files changed

+2536
-71
lines changed

26 files changed

+2536
-71
lines changed

CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,7 @@ set(ARDUINO_LIBRARY_Matter_SRCS
194194
libraries/Matter/src/MatterEndpoints/MatterHumiditySensor.cpp
195195
libraries/Matter/src/MatterEndpoints/MatterContactSensor.cpp
196196
libraries/Matter/src/MatterEndpoints/MatterWaterFreezeDetector.cpp
197+
libraries/Matter/src/MatterEndpoints/MatterRainSensor.cpp
197198
libraries/Matter/src/MatterEndpoints/MatterPressureSensor.cpp
198199
libraries/Matter/src/MatterEndpoints/MatterOccupancySensor.cpp
199200
libraries/Matter/src/MatterEndpoints/MatterOnOffPlugin.cpp

cores/esp32/HardwareSerial.cpp

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,31 @@ HardwareSerial Serial5(5);
6161
extern void HWCDCSerialEvent(void) __attribute__((weak));
6262
#endif
6363

64+
// C-callable helper used by HAL when pins are detached and the high-level
65+
// HardwareSerial instance must be finalized.
66+
extern "C" void hal_uart_notify_pins_detached(int uart_num) {
67+
log_d("hal_uart_notify_pins_detached: Notifying HardwareSerial for UART%d", uart_num);
68+
switch (uart_num) {
69+
case 0: Serial0.end(); break;
70+
#if SOC_UART_NUM > 1
71+
case 1: Serial1.end(); break;
72+
#endif
73+
#if SOC_UART_NUM > 2
74+
case 2: Serial2.end(); break;
75+
#endif
76+
#if SOC_UART_NUM > 3
77+
case 3: Serial3.end(); break;
78+
#endif
79+
#if SOC_UART_NUM > 4
80+
case 4: Serial4.end(); break;
81+
#endif
82+
#if SOC_UART_NUM > 5
83+
case 5: Serial5.end(); break;
84+
#endif
85+
default: log_e("hal_uart_notify_pins_detached: UART%d not handled!", uart_num); break;
86+
}
87+
}
88+
6489
#if USB_SERIAL_IS_DEFINED == 1 // Native USB CDC Event
6590
// Used by Hardware Serial for USB CDC events
6691
extern void USBSerialEvent(void) __attribute__((weak));
@@ -483,9 +508,6 @@ void HardwareSerial::end() {
483508
// including any tasks or debug message channel (log_x()) - but not for IDF log messages!
484509
_onReceiveCB = NULL;
485510
_onReceiveErrorCB = NULL;
486-
if (uartGetDebug() == _uart_nr) {
487-
uartSetDebug(0);
488-
}
489511
_rxFIFOFull = 0;
490512
uartEnd(_uart_nr); // fully detach all pins and delete the UART driver
491513
_destroyEventTask(); // when IDF uart driver is deleted, _eventTask must finish too

cores/esp32/chip-debug-report.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -291,7 +291,7 @@ static void printPerimanInfo(void) {
291291

292292
void printBeforeSetupInfo(void) {
293293
#if ARDUINO_USB_CDC_ON_BOOT
294-
Serial.begin(0);
294+
Serial.begin();
295295
Serial.setDebugOutput(true);
296296
uint8_t t = 0;
297297
while (!Serial && (t++ < 200)) {

cores/esp32/esp32-hal-uart.c

Lines changed: 73 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,9 @@
4242
static int s_uart_debug_nr = 0; // UART number for debug output
4343
#define REF_TICK_BAUDRATE_LIMIT 250000 // this is maximum UART badrate using REF_TICK as clock
4444

45+
/* C prototype for the notifier implemented in HardwareSerial.cpp */
46+
extern void hal_uart_notify_pins_detached(int uart_num);
47+
4548
struct uart_struct_t {
4649

4750
#if !CONFIG_DISABLE_HAL_LOCKS
@@ -282,29 +285,67 @@ static bool _uartDetachPins(uint8_t uart_num, int8_t rxPin, int8_t txPin, int8_t
282285
// Peripheral Manager detach callback for each specific UART PIN
283286
static bool _uartDetachBus_RX(void *busptr) {
284287
// sanity check - it should never happen
285-
assert(busptr && "_uartDetachBus_RX bus NULL pointer.");
288+
if (busptr == NULL) {
289+
log_e("_uartDetachBus_RX: busptr is NULL");
290+
return false;
291+
}
286292
uart_t *bus = (uart_t *)busptr;
293+
if (bus->_rxPin < 0) {
294+
log_d("_uartDetachBus_RX: RX pin already detached for UART%d", bus->num);
295+
return true;
296+
}
297+
if (bus->_txPin < 0) { // both rx and tx pins are detached, terminate the uart driver
298+
log_d("_uartDetachBus_RX: both RX and TX pins detached for UART%d, terminating driver", bus->num);
299+
hal_uart_notify_pins_detached(bus->num);
300+
return true;
301+
}
287302
return _uartDetachPins(bus->num, bus->_rxPin, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE);
288303
}
289304

290305
static bool _uartDetachBus_TX(void *busptr) {
291306
// sanity check - it should never happen
292-
assert(busptr && "_uartDetachBus_TX bus NULL pointer.");
307+
if (busptr == NULL) {
308+
log_e("_uartDetachBus_TX: busptr is NULL");
309+
return false;
310+
}
293311
uart_t *bus = (uart_t *)busptr;
312+
if (bus->_txPin < 0) {
313+
log_d("_uartDetachBus_TX: TX pin already detached for UART%d", bus->num);
314+
return true;
315+
}
316+
if (bus->_rxPin < 0) { // both rx and tx pins are detached, terminate the uart driver
317+
log_d("_uartDetachBus_TX: both RX and TX pins detached for UART%d, terminating driver", bus->num);
318+
hal_uart_notify_pins_detached(bus->num);
319+
return true;
320+
}
294321
return _uartDetachPins(bus->num, UART_PIN_NO_CHANGE, bus->_txPin, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE);
295322
}
296323

297324
static bool _uartDetachBus_CTS(void *busptr) {
298325
// sanity check - it should never happen
299-
assert(busptr && "_uartDetachBus_CTS bus NULL pointer.");
326+
if (busptr == NULL) {
327+
log_e("_uartDetachBus_CTS: busptr is NULL");
328+
return false;
329+
}
300330
uart_t *bus = (uart_t *)busptr;
331+
if (bus->_ctsPin < 0) {
332+
log_d("_uartDetachBus_CTS: CTS pin already detached for UART%d", bus->num);
333+
return true;
334+
}
301335
return _uartDetachPins(bus->num, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE, bus->_ctsPin, UART_PIN_NO_CHANGE);
302336
}
303337

304338
static bool _uartDetachBus_RTS(void *busptr) {
305339
// sanity check - it should never happen
306-
assert(busptr && "_uartDetachBus_RTS bus NULL pointer.");
340+
if (busptr == NULL) {
341+
log_e("_uartDetachBus_RTS: busptr is NULL");
342+
return false;
343+
}
307344
uart_t *bus = (uart_t *)busptr;
345+
if (bus->_rtsPin < 0) {
346+
log_d("_uartDetachBus_RTS: RTS pin already detached for UART%d", bus->num);
347+
return true;
348+
}
308349
return _uartDetachPins(bus->num, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE, bus->_rtsPin);
309350
}
310351

@@ -629,6 +670,16 @@ bool uartSetPins(uint8_t uart_num, int8_t rxPin, int8_t txPin, int8_t ctsPin, in
629670
//log_v("setting UART%d pins: prev->new RX(%d->%d) TX(%d->%d) CTS(%d->%d) RTS(%d->%d)", uart_num,
630671
// uart->_rxPin, rxPin, uart->_txPin, txPin, uart->_ctsPin, ctsPin, uart->_rtsPin, rtsPin); vTaskDelay(10);
631672

673+
// mute bus detaching callbacks to avoid terminating the UART driver when both RX and TX pins are detached
674+
peripheral_bus_deinit_cb_t rxDeinit = perimanGetBusDeinit(ESP32_BUS_TYPE_UART_RX);
675+
peripheral_bus_deinit_cb_t txDeinit = perimanGetBusDeinit(ESP32_BUS_TYPE_UART_TX);
676+
peripheral_bus_deinit_cb_t ctsDeinit = perimanGetBusDeinit(ESP32_BUS_TYPE_UART_CTS);
677+
peripheral_bus_deinit_cb_t rtsDeinit = perimanGetBusDeinit(ESP32_BUS_TYPE_UART_RTS);
678+
perimanClearBusDeinit(ESP32_BUS_TYPE_UART_RX);
679+
perimanClearBusDeinit(ESP32_BUS_TYPE_UART_TX);
680+
perimanClearBusDeinit(ESP32_BUS_TYPE_UART_CTS);
681+
perimanClearBusDeinit(ESP32_BUS_TYPE_UART_RTS);
682+
632683
// First step: detaches all previous UART pins
633684
bool rxPinChanged = rxPin >= 0 && rxPin != uart->_rxPin;
634685
if (rxPinChanged) {
@@ -660,6 +711,21 @@ bool uartSetPins(uint8_t uart_num, int8_t rxPin, int8_t txPin, int8_t ctsPin, in
660711
if (rtsPinChanged) {
661712
retCode &= _uartAttachPins(uart->num, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE, rtsPin);
662713
}
714+
715+
// restore bus detaching callbacks
716+
if (rxDeinit != NULL) {
717+
perimanSetBusDeinit(ESP32_BUS_TYPE_UART_RX, rxDeinit);
718+
}
719+
if (txDeinit != NULL) {
720+
perimanSetBusDeinit(ESP32_BUS_TYPE_UART_TX, txDeinit);
721+
}
722+
if (ctsDeinit != NULL) {
723+
perimanSetBusDeinit(ESP32_BUS_TYPE_UART_CTS, ctsDeinit);
724+
}
725+
if (rtsDeinit != NULL) {
726+
perimanSetBusDeinit(ESP32_BUS_TYPE_UART_RTS, rtsDeinit);
727+
}
728+
663729
UART_MUTEX_UNLOCK();
664730

665731
if (!retCode) {
@@ -986,6 +1052,9 @@ void uartEnd(uint8_t uart_num) {
9861052
if (uart_is_driver_installed(uart_num)) {
9871053
uart_driver_delete(uart_num);
9881054
}
1055+
if (uartGetDebug() == uart_num) {
1056+
uartSetDebug(0);
1057+
}
9891058
UART_MUTEX_UNLOCK();
9901059
}
9911060

docs/en/api/serial.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,10 @@ with additional features for advanced use cases.
2323
* **Event callbacks**: Receive and error event callbacks
2424
* **Configurable buffers**: Adjustable RX and TX buffer sizes
2525

26+
.. note::
27+
In case that both pins, RX and TX are detached from UART, the driver will be stopped.
28+
Detaching may occur when, for instance, starting another peripheral using RX and TX pins, such as Wire.begin(RX0, TX0).
29+
2630
UART Availability
2731
-----------------
2832

docs/en/matter/ep_rain_sensor.rst

Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
###################
2+
MatterRainSensor
3+
###################
4+
5+
About
6+
-----
7+
8+
The ``MatterRainSensor`` class provides a rain sensor endpoint for Matter networks. This endpoint implements the Matter rain sensing standard for detecting rain presence (detected/not detected states).
9+
10+
**Features:**
11+
* Rain detection state reporting (detected/not detected)
12+
* Simple boolean state
13+
* Read-only sensor (no control functionality)
14+
* Automatic state updates
15+
* Integration with Apple HomeKit, Amazon Alexa, and Google Home
16+
* Matter standard compliance
17+
18+
**Use Cases:**
19+
* Weather monitoring systems
20+
* Irrigation control systems
21+
* Outdoor sensor networks
22+
* Smart home automation triggers
23+
* Rain detection for automated systems
24+
25+
API Reference
26+
-------------
27+
28+
Constructor
29+
***********
30+
31+
MatterRainSensor
32+
^^^^^^^^^^^^^^^^
33+
34+
Creates a new Matter rain sensor endpoint.
35+
36+
.. code-block:: arduino
37+
38+
MatterRainSensor();
39+
40+
Initialization
41+
**************
42+
43+
begin
44+
^^^^^
45+
46+
Initializes the Matter rain sensor endpoint with an initial rain detection state.
47+
48+
.. code-block:: arduino
49+
50+
bool begin(bool _rainState = false);
51+
52+
* ``_rainState`` - Initial rain detection state (``true`` = detected, ``false`` = not detected, default: ``false``)
53+
54+
This function will return ``true`` if successful, ``false`` otherwise.
55+
56+
end
57+
^^^
58+
59+
Stops processing Matter rain sensor events.
60+
61+
.. code-block:: arduino
62+
63+
void end();
64+
65+
Rain Detection State Control
66+
****************************
67+
68+
setRain
69+
^^^^^^^
70+
71+
Sets the rain detection state.
72+
73+
.. code-block:: arduino
74+
75+
bool setRain(bool _rainState);
76+
77+
* ``_rainState`` - Rain detection state (``true`` = detected, ``false`` = not detected)
78+
79+
This function will return ``true`` if successful, ``false`` otherwise.
80+
81+
getRain
82+
^^^^^^^
83+
84+
Gets the current rain detection state.
85+
86+
.. code-block:: arduino
87+
88+
bool getRain();
89+
90+
This function will return ``true`` if rain is detected, ``false`` if not detected.
91+
92+
Operators
93+
*********
94+
95+
bool operator
96+
^^^^^^^^^^^^^
97+
98+
Returns the current rain detection state.
99+
100+
.. code-block:: arduino
101+
102+
operator bool();
103+
104+
Example:
105+
106+
.. code-block:: arduino
107+
108+
if (mySensor) {
109+
Serial.println("Rain is detected");
110+
} else {
111+
Serial.println("Rain is not detected");
112+
}
113+
114+
Assignment operator
115+
^^^^^^^^^^^^^^^^^^^
116+
117+
Sets the rain detection state.
118+
119+
.. code-block:: arduino
120+
121+
void operator=(bool _rainState);
122+
123+
Example:
124+
125+
.. code-block:: arduino
126+
127+
mySensor = true; // Set rain detection to detected
128+
mySensor = false; // Set rain detection to not detected
129+
130+
Example
131+
-------
132+
133+
Rain Sensor
134+
***********
135+
136+
.. literalinclude:: ../../../libraries/Matter/examples/MatterRainSensor/MatterRainSensor.ino
137+
:language: arduino

docs/en/matter/matter.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,7 @@ The library provides specialized endpoint classes for different device types. Ea
127127
* ``MatterPressureSensor``: Pressure sensor (read-only)
128128
* ``MatterContactSensor``: Contact sensor (open/closed state)
129129
* ``MatterWaterFreezeDetector``: Water freeze detector (detected/not detected state)
130+
* ``MatterRainSensor``: Rain sensor (detected/not detected state)
130131
* ``MatterOccupancySensor``: Occupancy sensor (occupied/unoccupied state)
131132

132133
**Control Endpoints:**

0 commit comments

Comments
 (0)