Skip to content

Commit 0f61b4f

Browse files
authored
Merge branch 'master' into rmt_loop_count
2 parents 7a5df40 + 7436eab commit 0f61b4f

33 files changed

+2073
-148
lines changed

.flake8

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,6 @@
55
doctests = True
66
# W503 and W504 are mutually exclusive. PEP 8 recommends line break before.
77
ignore = W503,E203
8-
max-complexity = 20
8+
max-complexity = 30
99
max-line-length = 120
1010
select = E,W,F,C,N

.github/pytools/Sign-File.ps1

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ function FindSignTool {
1919
if (Test-Path -Path $SignTool -PathType Leaf) {
2020
return $SignTool
2121
}
22-
$sdkVers = "10.0.22000.0", "10.0.20348.0", "10.0.19041.0", "10.0.17763.0"
22+
$sdkVers = "10.0.22000.0", "10.0.20348.0", "10.0.19041.0", "10.0.17763.0", "10.0.14393.0", "10.0.15063.0", "10.0.16299.0", "10.0.17134.0", "10.0.26100.0"
2323
Foreach ($ver in $sdkVers)
2424
{
2525
$SignTool = "${env:ProgramFiles(x86)}\Windows Kits\10\bin\${ver}\x64\signtool.exe"

.github/scripts/get_affected.py

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -626,11 +626,9 @@ def find_affected_sketches(changed_files: list[str]) -> None:
626626
q = queue.Queue()
627627

628628
if component_mode:
629-
print(f"Affected IDF component examples:", file=sys.stderr)
630629
# Get all available component examples once for efficiency
631630
all_examples = list_idf_component_examples()
632631
else:
633-
print(f"Affected sketches:", file=sys.stderr)
634632
all_examples = []
635633

636634
for file in changed_files:
@@ -648,11 +646,9 @@ def find_affected_sketches(changed_files: list[str]) -> None:
648646
# Check if this file belongs to an IDF component example
649647
for example in all_examples:
650648
if file.startswith(example + "/") and example not in affected_sketches:
651-
print(example, file=sys.stderr)
652649
affected_sketches.append(example)
653650
else:
654651
if file.endswith('.ino') and file not in affected_sketches:
655-
print(file, file=sys.stderr)
656652
affected_sketches.append(file)
657653

658654
# Continue with reverse dependency traversal
@@ -687,18 +683,24 @@ def find_affected_sketches(changed_files: list[str]) -> None:
687683
if should_traverse:
688684
q.put(dependency)
689685
if dependency_example and dependency_example not in affected_sketches:
690-
print(dependency_example, file=sys.stderr)
691686
affected_sketches.append(dependency_example)
692687
else:
693688
q.put(dependency)
694689
if dependency.endswith('.ino') and dependency not in affected_sketches:
695-
print(dependency, file=sys.stderr)
696690
affected_sketches.append(dependency)
697691

698692
if component_mode:
699693
print(f"Total affected IDF component examples: {len(affected_sketches)}", file=sys.stderr)
694+
if affected_sketches:
695+
print("Affected IDF component examples:", file=sys.stderr)
696+
for example in affected_sketches:
697+
print(f" {example}", file=sys.stderr)
700698
else:
701699
print(f"Total affected sketches: {len(affected_sketches)}", file=sys.stderr)
700+
if affected_sketches:
701+
print("Affected sketches:", file=sys.stderr)
702+
for sketch in affected_sketches:
703+
print(f" {sketch}", file=sys.stderr)
702704

703705
def save_dependencies_as_json(output_file: str = "dependencies.json") -> None:
704706
"""

.github/scripts/merge_packages.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,8 @@
1717

1818

1919
def load_package(filename):
20-
pkg = json.load(open(filename))["packages"][0]
20+
with open(filename) as f:
21+
pkg = json.load(f)["packages"][0]
2122
print("Loaded package {0} from {1}".format(pkg["name"], filename), file=sys.stderr)
2223
print("{0} platform(s), {1} tools".format(len(pkg["platforms"]), len(pkg["tools"])), file=sys.stderr)
2324
return pkg

.github/workflows/pre-commit-status.yml

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ on:
99

1010
permissions:
1111
statuses: write
12+
pull-requests: write
1213

1314
jobs:
1415
report-success:
@@ -62,3 +63,71 @@ jobs:
6263
target_url: 'https://github.com/${{ github.repository }}/actions/runs/${{ github.event.workflow_run.id }}'
6364
})).data;
6465
core.info(`${name} is ${state}`);
66+
67+
manage-labels:
68+
name: Manage PR labels
69+
if: github.event.workflow_run.event == 'pull_request'
70+
runs-on: ubuntu-latest
71+
steps:
72+
- name: Download and Extract Artifacts
73+
uses: dawidd6/action-download-artifact@07ab29fd4a977ae4d2b275087cf67563dfdf0295 # v9
74+
continue-on-error: true
75+
with:
76+
run_id: ${{ github.event.workflow_run.id }}
77+
name: pr-artifacts
78+
path: ./pr-artifacts
79+
80+
- name: Get PR information
81+
id: pr-info
82+
run: |
83+
if [ -f "./pr-artifacts/pr_number.txt" ]; then
84+
pr_number=$(cat ./pr-artifacts/pr_number.txt | tr -cd '[:digit:]')
85+
pre_commit_outcome=$(cat ./pr-artifacts/pre_commit_outcome.txt | tr -cd '[:alpha:]_')
86+
pending_commit=$(cat ./pr-artifacts/pending_commit.txt | tr -cd '[:digit:]')
87+
has_retrigger_label=$(cat ./pr-artifacts/has_retrigger_label.txt | tr -cd '[:alpha:]')
88+
89+
echo "pr_number=$pr_number" >> $GITHUB_OUTPUT
90+
echo "pre_commit_outcome=$pre_commit_outcome" >> $GITHUB_OUTPUT
91+
echo "pending_commit=$pending_commit" >> $GITHUB_OUTPUT
92+
echo "has_retrigger_label=$has_retrigger_label" >> $GITHUB_OUTPUT
93+
echo "artifacts_found=true" >> $GITHUB_OUTPUT
94+
95+
echo "PR number: $pr_number"
96+
echo "Pre-commit outcome: $pre_commit_outcome"
97+
echo "Pending commit: $pending_commit"
98+
echo "Has retrigger label: $has_retrigger_label"
99+
else
100+
echo "No PR artifacts found"
101+
echo "artifacts_found=false" >> $GITHUB_OUTPUT
102+
fi
103+
104+
- name: Remove re-trigger label if it was present
105+
if: |
106+
steps.pr-info.outputs.artifacts_found == 'true' &&
107+
steps.pr-info.outputs.has_retrigger_label == 'true'
108+
continue-on-error: true
109+
run: |
110+
gh pr edit ${{ steps.pr-info.outputs.pr_number }} --repo ${{ github.repository }} --remove-label 'Re-trigger Pre-commit Hooks'
111+
env:
112+
GH_TOKEN: ${{ github.token }}
113+
114+
- name: Add label if pre-commit fixes are required
115+
if: |
116+
steps.pr-info.outputs.artifacts_found == 'true' &&
117+
steps.pr-info.outputs.pre_commit_outcome == 'failure' &&
118+
steps.pr-info.outputs.pending_commit == '0'
119+
continue-on-error: true
120+
run: |
121+
gh pr edit ${{ steps.pr-info.outputs.pr_number }} --repo ${{ github.repository }} --add-label 'Status: Pre-commit fixes required ⚠️'
122+
env:
123+
GH_TOKEN: ${{ github.token }}
124+
125+
- name: Remove label if pre-commit was successful
126+
if: |
127+
steps.pr-info.outputs.artifacts_found == 'true' &&
128+
steps.pr-info.outputs.pre_commit_outcome == 'success'
129+
continue-on-error: true
130+
run: |
131+
gh pr edit ${{ steps.pr-info.outputs.pr_number }} --repo ${{ github.repository }} --remove-label 'Status: Pre-commit fixes required ⚠️'
132+
env:
133+
GH_TOKEN: ${{ github.token }}

.github/workflows/pre-commit.yml

Lines changed: 14 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -31,13 +31,6 @@ jobs:
3131
with:
3232
fetch-depth: 2
3333

34-
- name: Remove Label
35-
if: contains(github.event.pull_request.labels.*.name, 'Re-trigger Pre-commit Hooks')
36-
run: gh pr edit ${{ github.event.number }} --remove-label 'Re-trigger Pre-commit Hooks'
37-
continue-on-error: true
38-
env:
39-
GH_TOKEN: ${{ github.token }}
40-
4134
- name: Set up Python 3
4235
uses: actions/setup-python@42375524e23c412d93fb67b49958b491fce71c38 # v5.0.4
4336
with:
@@ -85,19 +78,20 @@ jobs:
8578
with:
8679
msg: "ci(pre-commit): Apply automatic fixes"
8780

88-
- name: Add label if no commits are pending
89-
if: ${{ failure() && steps.pre-commit.outcome == 'failure' && steps.pre-commit.outputs.pending_commit == '0' && github.event_name == 'pull_request' }}
90-
continue-on-error: true
81+
- name: Save workflow information for labeling
82+
if: ${{ always() && github.event_name == 'pull_request' }}
9183
run: |
92-
gh pr edit ${{ github.event.number }} --add-label 'Status: Pre-commit fixes required ⚠️'
93-
env:
94-
GH_TOKEN: ${{ github.token }}
84+
mkdir -p ./pr-artifacts
85+
echo "${{ github.event.number }}" > ./pr-artifacts/pr_number.txt
86+
echo "${{ steps.pre-commit.outcome }}" > ./pr-artifacts/pre_commit_outcome.txt
87+
echo "${{ steps.pre-commit.outputs.pending_commit }}" > ./pr-artifacts/pending_commit.txt
88+
echo "${{ contains(github.event.pull_request.labels.*.name, 'Re-trigger Pre-commit Hooks') }}" > ./pr-artifacts/has_retrigger_label.txt
9589
96-
- name: Remove label if everything was fixed
97-
if: ${{ success() && github.event_name == 'pull_request' }}
98-
continue-on-error: true
99-
run: |
100-
gh pr edit ${{ github.event.number }} --remove-label 'Status: Pre-commit fixes required ⚠️'
101-
env:
102-
GH_TOKEN: ${{ github.token }}
90+
- name: Upload PR artifacts
91+
if: ${{ always() && github.event_name == 'pull_request' }}
92+
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
93+
with:
94+
name: pr-artifacts
95+
path: ./pr-artifacts/
96+
retention-days: 1
10397

CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -315,6 +315,7 @@ set(ARDUINO_LIBRARY_Zigbee_SRCS
315315
libraries/Zigbee/src/ep/ZigbeeBinary.cpp
316316
libraries/Zigbee/src/ep/ZigbeePowerOutlet.cpp
317317
libraries/Zigbee/src/ep/ZigbeeFanControl.cpp
318+
libraries/Zigbee/src/ep/ZigbeeMultistate.cpp
318319
)
319320

320321
set(ARDUINO_LIBRARY_BLE_SRCS

cores/esp32/esp32-hal-periman.c

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ typedef struct ATTR_PACKED {
1616
int8_t bus_channel;
1717
} peripheral_pin_item_t;
1818

19-
static peripheral_bus_deinit_cb_t deinit_functions[ESP32_BUS_TYPE_MAX];
19+
static peripheral_bus_deinit_cb_t deinit_functions[ESP32_BUS_TYPE_MAX] = {NULL};
2020
static peripheral_pin_item_t pins[SOC_GPIO_PIN_COUNT];
2121

2222
#define GPIO_NOT_VALID(p) ((p >= SOC_GPIO_PIN_COUNT) || ((SOC_GPIO_VALID_GPIO_MASK & (1ULL << p)) == 0))
@@ -236,6 +236,14 @@ bool perimanSetBusDeinit(peripheral_bus_type_t type, peripheral_bus_deinit_cb_t
236236
return true;
237237
}
238238

239+
peripheral_bus_deinit_cb_t perimanGetBusDeinit(peripheral_bus_type_t type) {
240+
if (type >= ESP32_BUS_TYPE_MAX || type == ESP32_BUS_TYPE_INIT) {
241+
log_e("Invalid type: %s (%u)", perimanGetTypeName(type), (unsigned int)type);
242+
return NULL;
243+
}
244+
return deinit_functions[type];
245+
}
246+
239247
bool perimanPinIsValid(uint8_t pin) {
240248
return !(GPIO_NOT_VALID(pin));
241249
}

cores/esp32/esp32-hal-periman.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,10 @@ int8_t perimanGetPinBusChannel(uint8_t pin);
134134
// Sets the peripheral destructor callback. Used to destroy bus when pin is assigned another function
135135
bool perimanSetBusDeinit(peripheral_bus_type_t type, peripheral_bus_deinit_cb_t cb);
136136

137+
// Get the peripheral destructor callback. It allows changing/restoring the peripheral pin function detaching, if necessary
138+
// returns NULL if none is set
139+
peripheral_bus_deinit_cb_t perimanGetBusDeinit(peripheral_bus_type_t type);
140+
137141
// Check if given pin is a valid GPIO number
138142
bool perimanPinIsValid(uint8_t pin);
139143

docs/en/zigbee/ep_binary.rst

Lines changed: 114 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,7 @@ About
77

88
The ``ZigbeeBinary`` class provides an endpoint for binary input/output sensors in Zigbee networks. This endpoint implements the Zigbee Home Automation (HA) standard for binary sensors, supporting various application types for HVAC, security, and general binary sensing.
99
Binary Input (BI) is meant to be used for sensors that provide a binary signal, such as door/window sensors, motion detectors, etc. to be sent to the network.
10-
11-
.. note::
12-
13-
Binary Output (BO) is not supported yet.
10+
Binary Output (BO) is used for controlling binary devices such as relays, switches, or actuators that can be turned on/off remotely.
1411

1512
API Reference
1613
-------------
@@ -63,6 +60,33 @@ Security Application Types
6360
#define BINARY_INPUT_APPLICATION_TYPE_SECURITY_HEAT_DETECTION 0x01000008
6461
#define BINARY_INPUT_APPLICATION_TYPE_SECURITY_OTHER 0x0100FFFF
6562
63+
Binary Output Application Types
64+
*******************************
65+
66+
HVAC Application Types
67+
^^^^^^^^^^^^^^^^^^^^^^
68+
69+
.. code-block:: arduino
70+
71+
#define BINARY_OUTPUT_APPLICATION_TYPE_HVAC_BOILER 0x00000003
72+
#define BINARY_OUTPUT_APPLICATION_TYPE_HVAC_CHILLER 0x0000000D
73+
#define BINARY_OUTPUT_APPLICATION_TYPE_HVAC_FAN 0x00000022
74+
#define BINARY_OUTPUT_APPLICATION_TYPE_HVAC_HEATING_VALVE 0x0000002C
75+
#define BINARY_OUTPUT_APPLICATION_TYPE_HVAC_HUMIDIFIER 0x00000033
76+
#define BINARY_OUTPUT_APPLICATION_TYPE_HVAC_PREHEAT 0x00000034
77+
#define BINARY_OUTPUT_APPLICATION_TYPE_HVAC_OTHER 0x0000FFFF
78+
79+
Security Application Types
80+
^^^^^^^^^^^^^^^^^^^^^^^^^^
81+
82+
.. code-block:: arduino
83+
84+
#define BINARY_OUTPUT_APPLICATION_TYPE_SECURITY_ARM_DISARM_COMMAND 0x01000000
85+
#define BINARY_OUTPUT_APPLICATION_TYPE_SECURITY_OCCUPANCY_CONTROL 0x01000001
86+
#define BINARY_OUTPUT_APPLICATION_TYPE_SECURITY_ENABLE_CONTROL 0x01000002
87+
#define BINARY_OUTPUT_APPLICATION_TYPE_SECURITY_ACCESS_CONTROL 0x01000003
88+
#define BINARY_OUTPUT_APPLICATION_TYPE_SECURITY_OTHER 0x0100FFFF
89+
6690
API Methods
6791
***********
6892

@@ -127,11 +151,94 @@ Manually reports the current binary input value.
127151
128152
This function will return ``true`` if successful, ``false`` otherwise.
129153

154+
addBinaryOutput
155+
^^^^^^^^^^^^^^^
156+
157+
Adds a binary output cluster to the endpoint.
158+
159+
.. code-block:: arduino
160+
161+
bool addBinaryOutput();
162+
163+
This function will return ``true`` if successful, ``false`` otherwise.
164+
165+
setBinaryOutputApplication
166+
^^^^^^^^^^^^^^^^^^^^^^^^^^
167+
168+
Sets the application type for the binary output.
169+
170+
.. code-block:: arduino
171+
172+
bool setBinaryOutputApplication(uint32_t application_type);
173+
174+
* ``application_type`` - Application type constant (see Binary Output Application Types above)
175+
176+
This function will return ``true`` if successful, ``false`` otherwise.
177+
178+
setBinaryOutputDescription
179+
^^^^^^^^^^^^^^^^^^^^^^^^^^
180+
181+
Sets a custom description for the binary output.
182+
183+
.. code-block:: arduino
184+
185+
bool setBinaryOutputDescription(const char *description);
186+
187+
* ``description`` - Description string
188+
189+
This function will return ``true`` if successful, ``false`` otherwise.
190+
191+
onBinaryOutputChange
192+
^^^^^^^^^^^^^^^^^^^^^
193+
194+
Sets a callback function to be called when the binary output value changes.
195+
196+
.. code-block:: arduino
197+
198+
void onBinaryOutputChange(void (*callback)(bool binary_output));
199+
200+
* ``callback`` - Function pointer to callback that receives the new binary output value
201+
202+
setBinaryOutput
203+
^^^^^^^^^^^^^^^
204+
205+
Sets the binary output value.
206+
207+
.. code-block:: arduino
208+
209+
bool setBinaryOutput(bool output);
210+
211+
* ``output`` - Binary value (true/false)
212+
213+
This function will return ``true`` if successful, ``false`` otherwise.
214+
215+
getBinaryOutput
216+
^^^^^^^^^^^^^^^
217+
218+
Gets the current binary output value.
219+
220+
.. code-block:: arduino
221+
222+
bool getBinaryOutput();
223+
224+
This function returns the current binary output state.
225+
226+
reportBinaryOutput
227+
^^^^^^^^^^^^^^^^^^
228+
229+
Manually reports the current binary output value.
230+
231+
.. code-block:: arduino
232+
233+
bool reportBinaryOutput();
234+
235+
This function will return ``true`` if successful, ``false`` otherwise.
236+
130237
Example
131238
-------
132239

133-
Binary Input Implementation
134-
****************************
240+
Binary Input and Output Implementation
241+
**************************************
135242

136-
.. literalinclude:: ../../../libraries/Zigbee/examples/Zigbee_Binary_Input/Zigbee_Binary_Input.ino
243+
.. literalinclude:: ../../../libraries/Zigbee/examples/Zigbee_Binary_Input_Output/Zigbee_Binary_Input_Output.ino
137244
:language: arduino

0 commit comments

Comments
 (0)