1
0
mirror of https://github.com/esphome/esphome.git synced 2025-10-23 20:23:50 +01:00

Merge branch 'bluetooth_connection_churn' into integration

This commit is contained in:
J. Nick Koston
2025-08-01 10:41:46 -10:00
74 changed files with 2633 additions and 269 deletions

View File

@@ -342,6 +342,11 @@ def create_field_type_info(
# Check if this repeated field has fixed_array_size option
if (fixed_size := get_field_opt(field, pb.fixed_array_size)) is not None:
return FixedArrayRepeatedType(field, fixed_size)
# Check if this repeated field has fixed_array_size_define option
if (
size_define := get_field_opt(field, pb.fixed_array_size_define)
) is not None:
return FixedArrayRepeatedType(field, size_define)
return RepeatedTypeInfo(field)
# Check for fixed_array_size option on bytes fields
@@ -1065,9 +1070,10 @@ class FixedArrayRepeatedType(TypeInfo):
control how many items we receive when decoding.
"""
def __init__(self, field: descriptor.FieldDescriptorProto, size: int) -> None:
def __init__(self, field: descriptor.FieldDescriptorProto, size: int | str) -> None:
super().__init__(field)
self.array_size = size
self.is_define = isinstance(size, str)
# Check if we should skip encoding when all elements are zero
# Use getattr to handle older versions of api_options_pb2
self.skip_zero = get_field_opt(
@@ -1124,6 +1130,14 @@ class FixedArrayRepeatedType(TypeInfo):
# If skip_zero is enabled, wrap encoding in a zero check
if self.skip_zero:
if self.is_define:
# When using a define, we need to use a loop-based approach
o = f"for (const auto &it : this->{self.field_name}) {{\n"
o += " if (it != 0) {\n"
o += f" {encode_element('it')}\n"
o += " }\n"
o += "}"
return o
# Build the condition to check if at least one element is non-zero
non_zero_checks = " || ".join(
[f"this->{self.field_name}[{i}] != 0" for i in range(self.array_size)]
@@ -1134,6 +1148,13 @@ class FixedArrayRepeatedType(TypeInfo):
]
return f"if ({non_zero_checks}) {{\n" + "\n".join(encode_lines) + "\n}"
# When using a define, always use loop-based approach
if self.is_define:
o = f"for (const auto &it : this->{self.field_name}) {{\n"
o += f" {encode_element('it')}\n"
o += "}"
return o
# Unroll small arrays for efficiency
if self.array_size == 1:
return encode_element(f"this->{self.field_name}[0]")
@@ -1164,6 +1185,14 @@ class FixedArrayRepeatedType(TypeInfo):
def get_size_calculation(self, name: str, force: bool = False) -> str:
# If skip_zero is enabled, wrap size calculation in a zero check
if self.skip_zero:
if self.is_define:
# When using a define, we need to use a loop-based approach
o = f"for (const auto &it : {name}) {{\n"
o += " if (it != 0) {\n"
o += f" {self._ti.get_size_calculation('it', True)}\n"
o += " }\n"
o += "}"
return o
# Build the condition to check if at least one element is non-zero
non_zero_checks = " || ".join(
[f"{name}[{i}] != 0" for i in range(self.array_size)]
@@ -1174,6 +1203,13 @@ class FixedArrayRepeatedType(TypeInfo):
]
return f"if ({non_zero_checks}) {{\n" + "\n".join(size_lines) + "\n}"
# When using a define, always use loop-based approach
if self.is_define:
o = f"for (const auto &it : {name}) {{\n"
o += f" {self._ti.get_size_calculation('it', True)}\n"
o += "}"
return o
# For fixed arrays, we always encode all elements
# Special case for single-element arrays - no loop needed
@@ -1197,6 +1233,11 @@ class FixedArrayRepeatedType(TypeInfo):
def get_estimated_size(self) -> int:
# For fixed arrays, estimate underlying type size * array size
underlying_size = self._ti.get_estimated_size()
if self.is_define:
# When using a define, we don't know the actual size so just guess 3
# This is only used for documentation and never actually used since
# fixed arrays are only for SOURCE_SERVER (encode-only) messages
return underlying_size * 3
return underlying_size * self.array_size

View File

@@ -205,7 +205,12 @@ def main():
parser.add_argument(
"-c", "--changed", action="store_true", help="only run on changed files"
)
parser.add_argument("-g", "--grep", help="only run on files containing value")
parser.add_argument(
"-g",
"--grep",
action="append",
help="only run on files containing value",
)
parser.add_argument(
"--split-num", type=int, help="split the files into X jobs.", default=None
)

View File

@@ -338,12 +338,12 @@ def filter_changed(files: list[str]) -> list[str]:
return files
def filter_grep(files: list[str], value: str) -> list[str]:
def filter_grep(files: list[str], value: list[str]) -> list[str]:
matched = []
for file in files:
with open(file, encoding="utf-8") as handle:
contents = handle.read()
if value in contents:
if any(v in contents for v in value):
matched.append(file)
return matched

View File

@@ -25,6 +25,7 @@ int main() { return 0;}
Path(zephyr_dir / "prj.conf").write_text(
"""
CONFIG_NEWLIB_LIBC=y
CONFIG_ADC=y
""",
encoding="utf-8",
)