Compare commits

1 Commits

Author SHA1 Message Date
0504f8d800 wip? 2026-10-09 00:18:35 +02:00
13 changed files with 1558 additions and 740 deletions

135
.idea/editor.xml generated
View File

@@ -27,25 +27,25 @@
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppConstParameterInDeclaration/@EntryIndexedValue" value="SUGGESTION" type="string" /> <option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppConstParameterInDeclaration/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppConstValueFunctionReturnType/@EntryIndexedValue" value="SUGGESTION" type="string" /> <option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppConstValueFunctionReturnType/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppCoroutineCallResolveError/@EntryIndexedValue" value="WARNING" type="string" /> <option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppCoroutineCallResolveError/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFAArrayIndexOutOfBounds/@EntryIndexedValue" value="WARNING" type="string" /> <option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFAArrayIndexOutOfBounds/@EntryIndexedValue" value="DO_NOT_SHOW" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFAConstantConditions/@EntryIndexedValue" value="WARNING" type="string" /> <option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFAConstantConditions/@EntryIndexedValue" value="DO_NOT_SHOW" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFAConstantFunctionResult/@EntryIndexedValue" value="WARNING" type="string" /> <option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFAConstantFunctionResult/@EntryIndexedValue" value="DO_NOT_SHOW" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFAConstantParameter/@EntryIndexedValue" value="WARNING" type="string" /> <option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFAConstantParameter/@EntryIndexedValue" value="DO_NOT_SHOW" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFADeletedPointer/@EntryIndexedValue" value="WARNING" type="string" /> <option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFADeletedPointer/@EntryIndexedValue" value="DO_NOT_SHOW" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFAEndlessLoop/@EntryIndexedValue" value="WARNING" type="string" /> <option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFAEndlessLoop/@EntryIndexedValue" value="DO_NOT_SHOW" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFAInfiniteRecursion/@EntryIndexedValue" value="WARNING" type="string" /> <option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFAInfiniteRecursion/@EntryIndexedValue" value="DO_NOT_SHOW" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFAInvalidatedMemory/@EntryIndexedValue" value="WARNING" type="string" /> <option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFAInvalidatedMemory/@EntryIndexedValue" value="DO_NOT_SHOW" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFALocalValueEscapesFunction/@EntryIndexedValue" value="WARNING" type="string" /> <option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFALocalValueEscapesFunction/@EntryIndexedValue" value="DO_NOT_SHOW" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFALocalValueEscapesScope/@EntryIndexedValue" value="WARNING" type="string" /> <option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFALocalValueEscapesScope/@EntryIndexedValue" value="DO_NOT_SHOW" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFALoopConditionNotUpdated/@EntryIndexedValue" value="WARNING" type="string" /> <option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFALoopConditionNotUpdated/@EntryIndexedValue" value="DO_NOT_SHOW" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFAMemoryLeak/@EntryIndexedValue" value="WARNING" type="string" /> <option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFAMemoryLeak/@EntryIndexedValue" value="DO_NOT_SHOW" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFANotInitializedField/@EntryIndexedValue" value="WARNING" type="string" /> <option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFANotInitializedField/@EntryIndexedValue" value="DO_NOT_SHOW" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFANullDereference/@EntryIndexedValue" value="WARNING" type="string" /> <option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFANullDereference/@EntryIndexedValue" value="DO_NOT_SHOW" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFATimeOver/@EntryIndexedValue" value="HINT" type="string" /> <option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFATimeOver/@EntryIndexedValue" value="DO_NOT_SHOW" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFAUnreachableCode/@EntryIndexedValue" value="WARNING" type="string" /> <option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFAUnreachableCode/@EntryIndexedValue" value="DO_NOT_SHOW" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFAUnreachableFunctionCall/@EntryIndexedValue" value="WARNING" type="string" /> <option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFAUnreachableFunctionCall/@EntryIndexedValue" value="DO_NOT_SHOW" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFAUnreadVariable/@EntryIndexedValue" value="WARNING" type="string" /> <option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFAUnreadVariable/@EntryIndexedValue" value="DO_NOT_SHOW" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFAUnusedValue/@EntryIndexedValue" value="WARNING" type="string" /> <option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFAUnusedValue/@EntryIndexedValue" value="DO_NOT_SHOW" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDeclarationHidesLocal/@EntryIndexedValue" value="WARNING" type="string" /> <option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDeclarationHidesLocal/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDeclarationHidesUncapturedLocal/@EntryIndexedValue" value="HINT" type="string" /> <option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDeclarationHidesUncapturedLocal/@EntryIndexedValue" value="HINT" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDeclarationSpecifierWithoutDeclarators/@EntryIndexedValue" value="WARNING" type="string" /> <option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDeclarationSpecifierWithoutDeclarators/@EntryIndexedValue" value="WARNING" type="string" />
@@ -245,18 +245,101 @@
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=IfStdIsConstantEvaluatedCanBeReplaced/@EntryIndexedValue" value="SUGGESTION" type="string" /> <option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=IfStdIsConstantEvaluatedCanBeReplaced/@EntryIndexedValue" value="SUGGESTION" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=StdIsConstantEvaluatedWillAlwaysEvaluateToConstant/@EntryIndexedValue" value="WARNING" type="string" /> <option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=StdIsConstantEvaluatedWillAlwaysEvaluateToConstant/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=StringLiteralTypo/@EntryIndexedValue" value="DO_NOT_SHOW" type="string" /> <option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=StringLiteralTypo/@EntryIndexedValue" value="DO_NOT_SHOW" type="string" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALLOW_COMMENT_AFTER_LBRACE/@EntryValue" value="true" type="bool" /> <option name="/Default/CodeStyle/CodeFormatting/CppClangFormat/EnableClangFormatSupport/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_MULTILINE_ARGUMENT/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_MULTILINE_BINARY_EXPRESSIONS_CHAIN/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_MULTILINE_CALLS_CHAIN/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_MULTILINE_EXPRESSION/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_MULTILINE_EXTENDS_LIST/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_MULTILINE_FOR_STMT/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_MULTILINE_PARAMETER/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_MULTILINE_TYPE_ARGUMENT/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_MULTILINE_TYPE_PARAMETER/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_MULTIPLE_DECLARATION/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_TERNARY/@EntryValue" value="ALIGN_ALL" type="string" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ANONYMOUS_METHOD_DECLARATION_BRACES/@EntryValue" value="END_OF_LINE" type="string" /> <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ANONYMOUS_METHOD_DECLARATION_BRACES/@EntryValue" value="END_OF_LINE" type="string" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/BLANK_LINES_AROUND_CLASS_DEFINITION/@EntryValue" value="1" type="int" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/BLANK_LINES_AROUND_DECLARATIONS/@EntryValue" value="0" type="int" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/BLANK_LINES_AROUND_FUNCTION_DECLARATION/@EntryValue" value="1" type="int" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/BLANK_LINES_AROUND_FUNCTION_DEFINITION/@EntryValue" value="1" type="int" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/BREAK_TEMPLATE_DECLARATION/@EntryValue" value="LINE_BREAK" type="string" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/CASE_BLOCK_BRACES/@EntryValue" value="END_OF_LINE" type="string" /> <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/CASE_BLOCK_BRACES/@EntryValue" value="END_OF_LINE" type="string" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/EMPTY_BLOCK_STYLE/@EntryValue" value="TOGETHER" type="string" /> <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/CONTINUOUS_LINE_INDENT/@EntryValue" value="Double" type="string" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/EXPORT_DECLARATION_BRACES/@EntryValue" value="END_OF_LINE" type="string" /> <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/INDENT_ACCESS_SPECIFIERS_FROM_CLASS/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/EXPRESSION_BRACES/@EntryValue" value="OUTSIDE_AND_INSIDE" type="string" /> <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/INDENT_CASE_FROM_SWITCH/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/INDENT_CLASS_MEMBERS_FROM_ACCESS_SPECIFIERS/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/INDENT_COMMENT/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/INDENT_SIZE/@EntryValue" value="4" type="int" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/INDENT_STYLE/@EntryValue" value="Space" type="string" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/INITIALIZER_BRACES/@EntryValue" value="END_OF_LINE_NO_SPACE" type="string" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/INT_ALIGN_EQ/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/INVOCABLE_DECLARATION_BRACES/@EntryValue" value="END_OF_LINE" type="string" /> <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/INVOCABLE_DECLARATION_BRACES/@EntryValue" value="END_OF_LINE" type="string" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/KEEP_BLANK_LINES_IN_CODE/@EntryValue" value="2" type="int" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/KEEP_BLANK_LINES_IN_DECLARATIONS/@EntryValue" value="2" type="int" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/KEEP_USER_LINEBREAKS/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/LINE_BREAK_AFTER_COLON_IN_MEMBER_INITIALIZER_LISTS/@EntryValue" value="ON_SINGLE_LINE" type="string" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/MEMBER_INITIALIZER_LIST_STYLE/@EntryValue" value="DO_NOT_CHANGE" type="string" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/NAMESPACE_DECLARATION_BRACES/@EntryValue" value="END_OF_LINE" type="string" /> <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/NAMESPACE_DECLARATION_BRACES/@EntryValue" value="END_OF_LINE" type="string" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/NAMESPACE_INDENTATION/@EntryValue" value="All" type="string" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/OTHER_BRACES/@EntryValue" value="END_OF_LINE" type="string" /> <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/OTHER_BRACES/@EntryValue" value="END_OF_LINE" type="string" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/REQUIRES_EXPRESSION_BRACES/@EntryValue" value="END_OF_LINE" type="string" /> <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/PLACE_CATCH_ON_NEW_LINE/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SIMPLE_BLOCK_STYLE/@EntryValue" value="ON_SINGLE_LINE" type="string" /> <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/PLACE_ELSE_ON_NEW_LINE/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/PLACE_NAMESPACE_DEFINITIONS_ON_SAME_LINE/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/PLACE_WHILE_ON_NEW_LINE/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SIMPLE_BLOCK_STYLE/@EntryValue" value="DO_NOT_CHANGE" type="string" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_CAST_EXPRESSION_PARENTHESES/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_COLON_IN_BITFIELD_DECLARATOR/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_COMMA_IN_TEMPLATE_ARGS/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_COMMA_IN_TEMPLATE_PARAMS/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_EXTENDS_COLON/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_FOR_COLON/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_FOR_SEMICOLON/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_PTR_IN_DATA_MEMBER/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_PTR_IN_DATA_MEMBERS/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_PTR_IN_METHOD/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_PTR_IN_NESTED_DECLARATOR/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_REF_IN_DATA_MEMBER/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_REF_IN_DATA_MEMBERS/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_REF_IN_METHOD/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_UNARY_OPERATOR/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_COLON_IN_BITFIELD_DECLARATOR/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_EXTENDS_COLON/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_FOR_COLON/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_FOR_SEMICOLON/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_PTR_IN_ABSTRACT_DECL/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_PTR_IN_DATA_MEMBER/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_PTR_IN_DATA_MEMBERS/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_PTR_IN_METHOD/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_REF_IN_ABSTRACT_DECL/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_REF_IN_DATA_MEMBER/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_REF_IN_DATA_MEMBERS/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_REF_IN_METHOD/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_TEMPLATE_ARGS/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_TEMPLATE_PARAMS/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BETWEEN_CLOSING_ANGLE_BRACKETS_IN_TEMPLATE_ARGS/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_WITHIN_ARRAY_ACCESS_BRACKETS/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_WITHIN_CAST_EXPRESSION_PARENTHESES/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_WITHIN_DECLARATION_PARENTHESES/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_WITHIN_EMPTY_BLOCKS/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_WITHIN_EMPTY_INITIALIZER_BRACES/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_WITHIN_EMPTY_METHOD_PARENTHESES/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_WITHIN_EMPTY_TEMPLATE_PARAMS/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_WITHIN_INITIALIZER_BRACES/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_WITHIN_TEMPLATE_ARGS/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_WITHIN_TEMPLATE_PARAMS/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPECIAL_ELSE_IF_TREATMENT/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/TAB_WIDTH/@EntryValue" value="4" type="int" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/TYPE_DECLARATION_BRACES/@EntryValue" value="END_OF_LINE" type="string" /> <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/TYPE_DECLARATION_BRACES/@EntryValue" value="END_OF_LINE" type="string" />
<option name="/Default/CodeStyle/CppIncludeDirective/SortIncludeDirectives/@EntryValue" value="true" type="bool" /> <option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_AFTER_BINARY_OPSIGN/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_AFTER_DECLARATION_LPAR/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_AFTER_INVOCATION_LPAR/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_ARGUMENTS_STYLE/@EntryValue" value="WRAP_IF_LONG" type="string" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_BEFORE_DECLARATION_LPAR/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_BEFORE_DECLARATION_RPAR/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_BEFORE_INVOCATION_LPAR/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_BEFORE_INVOCATION_RPAR/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_BEFORE_TERNARY_OPSIGNS/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_PARAMETERS_STYLE/@EntryValue" value="WRAP_IF_LONG" type="string" />
<option name="/Default/CodeStyle/EditorConfig/EnableClangFormatSupport/@EntryValue" value="true" type="bool" />
</component> </component>
</project> </project>

27
.idea/vcs.xml generated
View File

@@ -2,32 +2,5 @@
<project version="4"> <project version="4">
<component name="VcsDirectoryMappings"> <component name="VcsDirectoryMappings">
<mapping directory="" vcs="Git" /> <mapping directory="" vcs="Git" />
<mapping directory="$USER_HOME$/esp/esp-idf" vcs="Git" />
<mapping directory="$USER_HOME$/esp/esp-idf/components/bootloader/subproject/components/micro-ecc/micro-ecc" vcs="Git" />
<mapping directory="$USER_HOME$/esp/esp-idf/components/bt/controller/lib_esp32" vcs="Git" />
<mapping directory="$USER_HOME$/esp/esp-idf/components/bt/controller/lib_esp32c2/esp32c2-bt-lib" vcs="Git" />
<mapping directory="$USER_HOME$/esp/esp-idf/components/bt/controller/lib_esp32c3_family" vcs="Git" />
<mapping directory="$USER_HOME$/esp/esp-idf/components/bt/controller/lib_esp32c5/esp32c5-bt-lib" vcs="Git" />
<mapping directory="$USER_HOME$/esp/esp-idf/components/bt/controller/lib_esp32c6/esp32c6-bt-lib" vcs="Git" />
<mapping directory="$USER_HOME$/esp/esp-idf/components/bt/controller/lib_esp32h2/esp32h2-bt-lib" vcs="Git" />
<mapping directory="$USER_HOME$/esp/esp-idf/components/bt/esp_ble_mesh/lib/lib" vcs="Git" />
<mapping directory="$USER_HOME$/esp/esp-idf/components/bt/host/nimble/nimble" vcs="Git" />
<mapping directory="$USER_HOME$/esp/esp-idf/components/cmock/CMock" vcs="Git" />
<mapping directory="$USER_HOME$/esp/esp-idf/components/cmock/CMock/vendor/c_exception" vcs="Git" />
<mapping directory="$USER_HOME$/esp/esp-idf/components/cmock/CMock/vendor/unity" vcs="Git" />
<mapping directory="$USER_HOME$/esp/esp-idf/components/esp_coex/lib" vcs="Git" />
<mapping directory="$USER_HOME$/esp/esp-idf/components/esp_phy/lib" vcs="Git" />
<mapping directory="$USER_HOME$/esp/esp-idf/components/esp_wifi/lib" vcs="Git" />
<mapping directory="$USER_HOME$/esp/esp-idf/components/heap/tlsf" vcs="Git" />
<mapping directory="$USER_HOME$/esp/esp-idf/components/json/cJSON" vcs="Git" />
<mapping directory="$USER_HOME$/esp/esp-idf/components/lwip/lwip" vcs="Git" />
<mapping directory="$USER_HOME$/esp/esp-idf/components/mbedtls/mbedtls" vcs="Git" />
<mapping directory="$USER_HOME$/esp/esp-idf/components/mqtt/esp-mqtt" vcs="Git" />
<mapping directory="$USER_HOME$/esp/esp-idf/components/openthread/lib" vcs="Git" />
<mapping directory="$USER_HOME$/esp/esp-idf/components/openthread/openthread" vcs="Git" />
<mapping directory="$USER_HOME$/esp/esp-idf/components/protobuf-c/protobuf-c" vcs="Git" />
<mapping directory="$USER_HOME$/esp/esp-idf/components/spiffs/spiffs" vcs="Git" />
<mapping directory="$USER_HOME$/esp/esp-idf/components/unity/unity" vcs="Git" />
<mapping directory="$USER_HOME$/esp/esp-zigbee-sdk" vcs="Git" />
</component> </component>
</project> </project>

View File

@@ -2,7 +2,7 @@
# CMakeLists in this exact order for cmake to work correctly # CMakeLists in this exact order for cmake to work correctly
cmake_minimum_required(VERSION 3.16) cmake_minimum_required(VERSION 3.16)
set(EXTRA_COMPONENT_DIRS $ENV{IDF_PATH}/../esp-zigbee-sdk/components) # set(EXTRA_COMPONENT_DIRS $ENV{IDF_PATH}/../esp-zigbee-sdk/components)
include($ENV{IDF_PATH}/tools/cmake/project.cmake) include($ENV{IDF_PATH}/tools/cmake/project.cmake)
project(zigbee_light) project(zigbee_light)

View File

@@ -1,24 +1,6 @@
dependencies: dependencies:
esp-zigbee-lib: espressif/esp-zigbee-lib:
dependencies: [] component_hash: d508f9b91c4b1973e6563fe840923fad2f15b23637f3d743dba1f5a719e1baab
source:
path: /home/drath/esp/esp-zigbee-sdk/components/esp-zigbee-lib
type: local
version: 1.6.8
espressif/cmake_utilities:
component_hash:
351350613ceafba240b761b4ea991e0f231ac7a9f59a9ee901f751bddc0bb18f
dependencies:
- name: idf
require: private
version: '>=4.1'
source:
registry_url: https://components.espressif.com/
type: service
version: 0.5.3
espressif/esp-zboss-lib:
component_hash:
321883d142421f65009972408287441794250057668a11abbdfd8bec77c3309a
dependencies: dependencies:
- name: idf - name: idf
require: private require: private
@@ -26,16 +8,14 @@ dependencies:
source: source:
registry_url: https://components.espressif.com/ registry_url: https://components.espressif.com/
type: service type: service
version: 1.6.4 version: 2.0.4
idf: idf:
source: source:
type: idf type: idf
version: 5.5.2 version: 6.1.0
direct_dependencies: direct_dependencies:
- espressif/cmake_utilities
- espressif/esp-zboss-lib
- espressif/esp-zigbee-lib - espressif/esp-zigbee-lib
- idf - idf
manifest_hash: 4baf2465d72df3c01363578f8fdebf1c18e30bd7ec1be43833075c7bcadab4fc manifest_hash: f102844a1023b7743673c929ac298c85e5378544cf153ff658bd7704a7f010c9
target: esp32c6 target: esp32c6
version: 2.0.0 version: 3.0.0

View File

@@ -10,7 +10,7 @@
void light_driver_set_level(uint8_t level); void light_driver_set_level(uint8_t level);
void light_driver_set_power(bool power); void light_driver_set_power(bool power);
void light_driver_identify(void); void light_driver_identify();
void light_driver_task(void *pvParameter); void light_driver_task(void *pvParameter);
#endif //LIGHT_DRIVER_H #endif //LIGHT_DRIVER_H

View File

@@ -6,7 +6,7 @@ typedef struct zcl_basic_manufacturer_info_s {
char *model_identifier; char *model_identifier;
} zcl_basic_manufacturer_info_t; } zcl_basic_manufacturer_info_t;
void zigbee_init(void); void zigbee_init();
void zigbee_task(void* pvParameters); void zigbee_task(void* pvParameters);
#endif #endif

View File

@@ -1,5 +1,5 @@
idf_component_register( idf_component_register(
SRC_DIRS "." SRC_DIRS "."
INCLUDE_DIRS "../include" INCLUDE_DIRS "../include"
REQUIRES esp_driver_ledc nvs_flash REQUIRES esp_driver_ledc nvs_flash esp_timer
) )

View File

@@ -1,7 +1,6 @@
## IDF Component Manager Manifest File ## IDF Component Manager Manifest File
dependencies: dependencies:
espressif/esp-zboss-lib: "~1.6.0" espressif/esp-zigbee-lib: "^2.0.0"
espressif/esp-zigbee-lib: "~1.6.0"
## Required IDF version ## Required IDF version
idf: idf:
version: ">=5.0.0" version: ">=6.0.0"

View File

@@ -3,7 +3,6 @@
#include "driver/ledc.h" #include "driver/ledc.h"
#include "esp_log.h" #include "esp_log.h"
#include "esp_err.h" #include "esp_err.h"
#include <stdbool.h>
#include <math.h> #include <math.h>
#include <freertos/FreeRTOS.h> #include <freertos/FreeRTOS.h>
#include <freertos/semphr.h> #include <freertos/semphr.h>
@@ -11,23 +10,23 @@
static const char* TAG = "light_driver"; static const char* TAG = "light_driver";
/* tweakable stuff */ /* tweakable stuff */
static const uint8_t light_gpio = 2; static constexpr uint8_t light_gpio = 2;
static const uint16_t light_pwm_freq = 65000; static constexpr uint16_t light_pwm_freq = 65000;
static const ledc_timer_bit_t light_pwm_resolution = LEDC_TIMER_10_BIT; static constexpr ledc_timer_bit_t light_pwm_resolution = LEDC_TIMER_10_BIT;
static const double light_lowest_duty_pct = 0.001; // lowest duty percentage where the LEDs still light up nice static constexpr double light_lowest_duty_pct = 0.001; // lowest duty percentage where the LEDs still light up nice
static const uint8_t light_identify_level_delta = 80; static constexpr uint8_t light_identify_level_delta = 80;
/* no need to tweak this stuff */ /* no need to tweak this stuff */
static const ledc_channel_t light_ledc_channel = LEDC_CHANNEL_0; static constexpr ledc_channel_t light_ledc_channel = LEDC_CHANNEL_0;
static const ledc_mode_t light_ledc_speed_mode = LEDC_LOW_SPEED_MODE; static constexpr ledc_mode_t light_ledc_speed_mode = LEDC_LOW_SPEED_MODE;
static const uint32_t light_brightness_steps = (1 << light_pwm_resolution) - 1; static constexpr uint32_t light_brightness_steps = (1 << light_pwm_resolution) - 1;
SemaphoreHandle_t light_sem = NULL; static SemaphoreHandle_t light_sem = nullptr;
/* global vars */ /* global vars */
static uint8_t light_target_level = 0; static uint8_t light_target_level = 0;
static uint16_t gamma_lut[ZIGBEE_LIGHT_LEVELS + 1]; static uint16_t gamma_lut[ZIGBEE_LIGHT_LEVELS + 1];
uint16_t light_driver_get_level(void) { static uint16_t light_driver_get_level() {
xSemaphoreTake(light_sem, portMAX_DELAY); xSemaphoreTake(light_sem, portMAX_DELAY);
const uint16_t lvl = light_target_level; const uint16_t lvl = light_target_level;
xSemaphoreGive(light_sem); xSemaphoreGive(light_sem);
@@ -44,7 +43,7 @@ void light_driver_set_power(const bool power) {
light_driver_set_level(power ? light_driver_get_level() : 0); light_driver_set_level(power ? light_driver_get_level() : 0);
} }
void light_driver_identify(void) { void light_driver_identify() {
const uint8_t level = light_driver_get_level(); const uint8_t level = light_driver_get_level();
if (level > 128) if (level > 128)
light_driver_set_level(level - light_identify_level_delta); light_driver_set_level(level - light_identify_level_delta);

View File

@@ -5,8 +5,8 @@
#include "status_led.h" #include "status_led.h"
void app_main(void) { void app_main() {
xTaskCreate(status_led_task, "status LED", 4096, NULL, 10, NULL); xTaskCreate(status_led_task, "status LED", 4096, NULL, 10, nullptr);
ESP_ERROR_CHECK(nvs_flash_init()); ESP_ERROR_CHECK(nvs_flash_init());
xTaskCreate(zigbee_task, "Zigbee_main", 4096, NULL, 5, NULL); xTaskCreate(zigbee_task, "Zigbee_main", 4096, NULL, 5, nullptr);
} }

View File

@@ -15,8 +15,8 @@ enum led_states_t {
}; };
static const char* TAG = "status_led"; static const char* TAG = "status_led";
SemaphoreHandle_t status_sem = NULL; static SemaphoreHandle_t status_sem = nullptr;
static const uint8_t status_led_pin = 15; static constexpr uint8_t status_led_pin = 15;
static enum led_states_t current_state = STATUS_OFF; static enum led_states_t current_state = STATUS_OFF;
static bool led_on = false; static bool led_on = false;
@@ -41,22 +41,22 @@ void set_status_error_or_resetting() {
ESP_LOGI(TAG, "status error or resetting"); ESP_LOGI(TAG, "status error or resetting");
} }
static void set_led_on(void) { static void set_led_on() {
led_on = true; led_on = true;
gpio_set_level(status_led_pin, false); gpio_set_level(status_led_pin, false);
} }
static void set_led_off(void) { static void set_led_off() {
led_on = false; led_on = false;
gpio_set_level(status_led_pin, true); gpio_set_level(status_led_pin, true);
} }
static void set_led_toggle(void) { static void set_led_toggle() {
led_on = !led_on; led_on = !led_on;
gpio_set_level(status_led_pin, !led_on); gpio_set_level(status_led_pin, !led_on);
} }
static enum led_states_t get_state(void) { static enum led_states_t get_state() {
xSemaphoreTake(status_sem, portMAX_DELAY); xSemaphoreTake(status_sem, portMAX_DELAY);
const enum led_states_t s = current_state; const enum led_states_t s = current_state;
xSemaphoreGive(status_sem); xSemaphoreGive(status_sem);

View File

@@ -1,277 +1,302 @@
// #include "ha/esp_zigbee_ha_standard.h"
#include "zigbee.h" #include "zigbee.h"
#include "esp_zigbee_core.h" #include "status_led.h"
#include "light_driver.h" #include "light_driver.h"
#include <freertos/FreeRTOS.h>
#include <freertos/task.h>
#include <esp_zigbee.h>
#include <ezbee/zha.h>
#include <esp_log.h> #include <esp_log.h>
#include <esp_err.h> #include <esp_err.h>
#include "status_led.h" #include <esp_timer.h>
#include <nvs_flash.h>
#include <esp_check.h> #include <esp_check.h>
static const char* TAG = "zigbee"; static const char *TAG = "zigbee";
#define ZB_STORAGE_PARTITION "zb_storage" /* must be subtype nvs in partitions.csv, not fat */
#define ZB_ROUTER_MAX_CHILDREN 10 /* v1 ZR default */
#define ZB_COMMISSIONING_RETRY_MS 1000
static char manufacturer[] = "\x05""Drath"; static char manufacturer[] = "\x05""Drath";
static char model[] = "\x15""Dimmable Zigbee Light"; static char model[] = "\x15""Dimmable Zigbee Light";
static const uint8_t endpoint_no = 1; static constexpr uint8_t endpoint_no = 1;
static esp_err_t deferred_driver_init(void) { static esp_timer_handle_t retry_timer = nullptr;
static volatile ezb_bdb_comm_mode_mask_t retry_mode = 0;
static esp_err_t deferred_driver_init() {
static bool is_inited = false; static bool is_inited = false;
if (!is_inited) { if (!is_inited) {
xTaskCreate(light_driver_task, "light task", 4096, NULL, 6, NULL); xTaskCreate(light_driver_task, "light task", 4096, nullptr, 6, nullptr);
is_inited = true; is_inited = true;
} }
return is_inited ? ESP_OK : ESP_FAIL; return is_inited ? ESP_OK : ESP_FAIL;
} }
/* caller must hold the zigbee lock (esp_zigbee_lock_acquire) unless it's running inside a stack callback */
void zigbee_report_on_off_level(const bool on, const uint8_t level) { void zigbee_report_on_off_level(const bool on, const uint8_t level) {
esp_zb_zcl_set_attribute_val(endpoint_no, ESP_ZB_ZCL_CLUSTER_ID_ON_OFF, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE, ESP_ZB_ZCL_ATTR_ON_OFF_ON_OFF_ID, (uint8_t*)&on, false); bool on_val = on;
esp_zb_zcl_set_attribute_val(endpoint_no, ESP_ZB_ZCL_CLUSTER_ID_LEVEL_CONTROL, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE, ESP_ZB_ZCL_ATTR_LEVEL_CONTROL_CURRENT_LEVEL_ID, (uint8_t*)&level, false); uint8_t level_val = level;
ezb_zcl_status_t st = ezb_zcl_set_attr_value(endpoint_no, EZB_ZCL_CLUSTER_ID_ON_OFF, EZB_ZCL_CLUSTER_SERVER,
EZB_ZCL_ATTR_ON_OFF_ON_OFF_ID, EZB_ZCL_STD_MANUF_CODE, &on_val, false);
if (st != EZB_ZCL_STATUS_SUCCESS) { ESP_LOGW(TAG, "Failed to set on/off attribute (status 0x%02x)", st); }
st = ezb_zcl_set_attr_value(endpoint_no, EZB_ZCL_CLUSTER_ID_LEVEL, EZB_ZCL_CLUSTER_SERVER,
EZB_ZCL_ATTR_LEVEL_CURRENT_LEVEL_ID, EZB_ZCL_STD_MANUF_CODE, &level_val, false);
if (st != EZB_ZCL_STATUS_SUCCESS) { ESP_LOGW(TAG, "Failed to set level attribute (status 0x%02x)", st); }
} }
static void commissioning_task_cb(void *ctx) {
static void bdb_start_top_level_commissioning_cb(const uint8_t mode_mask) { const ezb_bdb_comm_mode_mask_t mode = (ezb_bdb_comm_mode_mask_t) (uintptr_t) ctx;
ESP_RETURN_ON_FALSE(esp_zb_bdb_start_top_level_commissioning(mode_mask) == ESP_OK, , TAG, "Failed to start Zigbee commissioning"); const ezb_err_t err = ezb_bdb_start_top_level_commissioning(mode);
ESP_RETURN_ON_FALSE(err == EZB_ERR_NONE, , TAG, "Failed to start Zigbee commissioning (0x%x)", (unsigned)err);
} }
esp_err_t zigbee_utility_add_ep_basic_manufacturer_info(esp_zb_ep_list_t *ep_list, const uint8_t endpoint_id, const zcl_basic_manufacturer_info_t *info) { static void commissioning_timer_cb(void *arg) {
esp_zb_cluster_list_t *cluster_list = NULL; if (esp_zigbee_task_queue_post(commissioning_task_cb, (void *) (uintptr_t) retry_mode) != ESP_OK)
esp_zb_attribute_list_t *basic_cluster = NULL; ESP_LOGW(TAG, "Failed to post commissioning retry to zigbee task");
cluster_list = esp_zb_ep_list_get_ep(ep_list, endpoint_id);
ESP_RETURN_ON_FALSE(cluster_list, ESP_ERR_INVALID_ARG, TAG, "Failed to find endpoint id: %d in list: %p", endpoint_id, ep_list);
basic_cluster = esp_zb_cluster_list_get_cluster(cluster_list, ESP_ZB_ZCL_CLUSTER_ID_BASIC, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE);
ESP_RETURN_ON_FALSE(basic_cluster, ESP_ERR_INVALID_ARG, TAG, "Failed to find basic cluster in endpoint: %d", endpoint_id);
ESP_RETURN_ON_FALSE((info && info->manufacturer_name), ESP_ERR_INVALID_ARG, TAG, "Invalid manufacturer name");
ESP_ERROR_CHECK(esp_zb_basic_cluster_add_attr(basic_cluster, ESP_ZB_ZCL_ATTR_BASIC_MANUFACTURER_NAME_ID, info->manufacturer_name));
ESP_RETURN_ON_FALSE((info && info->model_identifier), ESP_ERR_INVALID_ARG, TAG, "Invalid model identifier");
ESP_ERROR_CHECK(esp_zb_basic_cluster_add_attr(basic_cluster, ESP_ZB_ZCL_ATTR_BASIC_MODEL_IDENTIFIER_ID, info->model_identifier));
return ESP_OK;
} }
static void zigbee_schedule_commissioning(const ezb_bdb_comm_mode_mask_t mode, const uint32_t delay_ms) {
if (!retry_timer) {
const esp_timer_create_args_t args = {
.callback = commissioning_timer_cb,
.name = "zb_commissioning",
};
ESP_RETURN_ON_FALSE(esp_timer_create(&args, &retry_timer) == ESP_OK, , TAG, "Failed to create retry timer");
}
esp_timer_stop(retry_timer); /* errors if not running, fine */
retry_mode = mode;
ESP_RETURN_ON_FALSE(esp_timer_start_once(retry_timer, (uint64_t)delay_ms * 1000ULL) == ESP_OK, , TAG,
"Failed to start retry timer");
}
static esp_err_t zigbee_attribute_handler(const esp_zb_zcl_set_attr_value_message_t* message) { static ezb_err_t zigbee_utility_add_ep_basic_manufacturer_info(ezb_af_ep_desc_t ep_desc,
ESP_RETURN_ON_FALSE(message, ESP_FAIL, TAG, "Empty message"); const zcl_basic_manufacturer_info_t *info) {
ESP_RETURN_ON_FALSE(message->info.status == ESP_ZB_ZCL_STATUS_SUCCESS, ESP_ERR_INVALID_ARG, TAG, "Received message: error status(%d)", message->info.status); ESP_RETURN_ON_FALSE(info && info->manufacturer_name, EZB_ERR_INV_ARG, TAG, "Invalid manufacturer name");
ESP_RETURN_ON_FALSE(info->model_identifier, EZB_ERR_INV_ARG, TAG, "Invalid model identifier");
if (message->info.dst_endpoint == endpoint_no) { ezb_zcl_cluster_desc_t basic_cluster = ezb_af_endpoint_get_cluster_desc(
switch (message->info.cluster) { ep_desc, EZB_ZCL_CLUSTER_ID_BASIC, EZB_ZCL_CLUSTER_SERVER);
ESP_RETURN_ON_FALSE(basic_cluster != EZB_INVALID_ZCL_CLUSTER_DESC, EZB_ERR_NOT_FOUND, TAG,
"Failed to find basic cluster in endpoint: %d", endpoint_no);
case ESP_ZB_ZCL_CLUSTER_ID_IDENTIFY: ezb_err_t err = ezb_zcl_basic_cluster_desc_add_attr(basic_cluster, EZB_ZCL_ATTR_BASIC_MANUFACTURER_NAME_ID,
ESP_LOGI(TAG, "Identify requested"); info->manufacturer_name);
light_driver_identify(); ESP_RETURN_ON_FALSE(err == EZB_ERR_NONE, err, TAG, "Failed to add manufacturer name (0x%x)", (unsigned)err);
break;
case ESP_ZB_ZCL_CLUSTER_ID_ON_OFF: err = ezb_zcl_basic_cluster_desc_add_attr(basic_cluster, EZB_ZCL_ATTR_BASIC_MODEL_IDENTIFIER_ID,
if (message->attribute.id == ESP_ZB_ZCL_ATTR_ON_OFF_ON_OFF_ID && message->attribute.data.type == ESP_ZB_ZCL_ATTR_TYPE_BOOL) { info->model_identifier);
bool light_state = false; ESP_RETURN_ON_FALSE(err == EZB_ERR_NONE, err, TAG, "Failed to add model identifier (0x%x)", (unsigned)err);
light_state = message->attribute.data.value ? *(bool*)message->attribute.data.value : light_state; return EZB_ERR_NONE;
ESP_LOGI(TAG, "Light sets to %s", light_state ? "On" : "Off"); }
light_driver_set_power(light_state);
}
break;
case ESP_ZB_ZCL_CLUSTER_ID_LEVEL_CONTROL: static void zigbee_attribute_handler(ezb_zcl_set_attr_value_message_t *message) {
if (message->attribute.id == ESP_ZB_ZCL_ATTR_LEVEL_CONTROL_CURRENT_LEVEL_ID && message->attribute.data.type == ESP_ZB_ZCL_ATTR_TYPE_U8) { ESP_RETURN_ON_FALSE(message, , TAG, "Empty message");
uint8_t light_level = 0;
light_level = message->attribute.data.value ? *(uint8_t*)message->attribute.data.value : light_level;
light_driver_set_level(light_level);
ESP_LOGI(TAG, "Light level changes to %d", light_level);
}
break;
default: /* v2: no return value, the verdict goes back to the stack through out.result */
ESP_LOGW(TAG, "Unhandled zigbee message, data: cluster(0x%x), attribute(0x%x) ", message->info.cluster, message->attribute.id); message->out.result = EZB_ZCL_STATUS_SUCCESS;
if (message->info.status != EZB_ZCL_STATUS_SUCCESS) {
ESP_LOGW(TAG, "Received message: error status(%d)", message->info.status);
message->out.result = EZB_ZCL_STATUS_FAIL;
return;
}
if (message->info.dst_ep == endpoint_no) {
const ezb_zcl_attribute_t *attr = &message->in.attribute;
switch (message->info.cluster_id) {
case EZB_ZCL_CLUSTER_ID_IDENTIFY:
if (attr->id == EZB_ZCL_ATTR_IDENTIFY_IDENTIFY_TIME_ID) {
ESP_LOGI(TAG, "Identify requested");
light_driver_identify();
}
break;
case EZB_ZCL_CLUSTER_ID_ON_OFF:
if (attr->id == EZB_ZCL_ATTR_ON_OFF_ON_OFF_ID && attr->data.type == EZB_ZCL_ATTR_TYPE_BOOL) {
bool light_state = false;
light_state = attr->data.value ? *(bool *) attr->data.value : light_state;
ESP_LOGI(TAG, "Light sets to %s", light_state ? "On" : "Off");
light_driver_set_power(light_state);
}
break;
case EZB_ZCL_CLUSTER_ID_LEVEL:
if (attr->id == EZB_ZCL_ATTR_LEVEL_CURRENT_LEVEL_ID && attr->data.type == EZB_ZCL_ATTR_TYPE_UINT8) {
uint8_t light_level = 0;
light_level = attr->data.value ? *(uint8_t *) attr->data.value : light_level;
light_driver_set_level(light_level);
ESP_LOGI(TAG, "Light level changes to %d", light_level);
}
break;
default:
ESP_LOGW(TAG, "Unhandled zigbee message, data: cluster(0x%x), attribute(0x%x) ",
message->info.cluster_id, attr->id);
} }
} }
return ESP_OK;
} }
static esp_err_t zigbee_action_handler(esp_zb_core_action_callback_id_t callback_id, const void* message) { static void zigbee_action_handler(ezb_zcl_core_action_callback_id_t callback_id, void *message) {
esp_err_t ret = ESP_OK; if (callback_id == EZB_ZCL_CORE_SET_ATTR_VALUE_CB_ID) {
switch (callback_id) { zigbee_attribute_handler(message);
return;
case ESP_ZB_CORE_SET_ATTR_VALUE_CB_ID:
ret = zigbee_attribute_handler((esp_zb_zcl_set_attr_value_message_t*)message);
break;
default:
ESP_LOGW(TAG, "Receive Zigbee action(0x%x) callback", callback_id);
break;
} }
return ret;
ESP_LOGW(TAG, "Receive Zigbee action(0x%lx) callback", (unsigned long)callback_id);
} }
/*
* ZHA helper builds the whole endpoint now: basic, identify, groups, scenes, on/off, level
* (device id 0x0101 / HA profile are set by it). ota is still left out. maybe one day
*/
static ezb_af_ep_desc_t zigbee_endpoint_create() {
ezb_zha_dimmable_light_config_t light_cfg = EZB_ZHA_DIMMABLE_LIGHT_CONFIG();
light_cfg.basic_cfg.power_source = EZB_ZCL_BASIC_POWER_SOURCE_DC_SOURCE;
ezb_af_ep_desc_t ep_desc = ezb_zha_create_dimmable_light(endpoint_no, &light_cfg);
ESP_RETURN_ON_FALSE(ep_desc != EZB_INVALID_AF_EP_DESC, EZB_INVALID_AF_EP_DESC, TAG,
"Failed to create dimmable light endpoint");
void zigbee_clusterfuck_init(esp_zb_cluster_list_t *cluster_list) {
esp_zb_basic_cluster_cfg_t basic_cfg = {
.zcl_version = ESP_ZB_ZCL_BASIC_ZCL_VERSION_DEFAULT_VALUE,
.power_source = ESP_ZB_ZCL_BASIC_POWER_SOURCE_DC_SOURCE,
};
esp_zb_identify_cluster_cfg_t identify_cfg = {
.identify_time = ESP_ZB_ZCL_IDENTIFY_IDENTIFY_TIME_DEFAULT_VALUE
};
esp_zb_groups_cluster_cfg_t group_cfg = {
.groups_name_support_id = ESP_ZB_ZCL_GROUPS_NAME_SUPPORT_DEFAULT_VALUE,
};
esp_zb_scenes_cluster_cfg_t scenes_cfg = {
.scenes_count = ESP_ZB_ZCL_SCENES_SCENE_COUNT_DEFAULT_VALUE,
.current_scene = ESP_ZB_ZCL_SCENES_CURRENT_SCENE_DEFAULT_VALUE,
.current_group = ESP_ZB_ZCL_SCENES_CURRENT_GROUP_DEFAULT_VALUE,
.scene_valid = ESP_ZB_ZCL_SCENES_SCENE_VALID_DEFAULT_VALUE,
.name_support = ESP_ZB_ZCL_SCENES_NAME_SUPPORT_DEFAULT_VALUE,
};
esp_zb_on_off_cluster_cfg_t on_off_cfg = {
.on_off = ESP_ZB_ZCL_ON_OFF_ON_OFF_DEFAULT_VALUE
};
esp_zb_level_cluster_cfg_t level_cfg = {
.current_level = ESP_ZB_ZCL_LEVEL_CONTROL_CURRENT_LEVEL_DEFAULT_VALUE,
};
// esp_zb_ota_cluster_cfg_t ota_cfg = {
// 0
// };
esp_zb_attribute_list_t *basic_cluster = esp_zb_basic_cluster_create(&basic_cfg);
esp_zb_attribute_list_t *identify_cluster = esp_zb_identify_cluster_create(&identify_cfg);
esp_zb_attribute_list_t *groups_cluster = esp_zb_groups_cluster_create(&group_cfg);
esp_zb_attribute_list_t *scenes_cluster = esp_zb_scenes_cluster_create(&scenes_cfg);
esp_zb_attribute_list_t *on_off_cluster = esp_zb_on_off_cluster_create(&on_off_cfg);
esp_zb_attribute_list_t *level_cluster = esp_zb_level_cluster_create(&level_cfg);
// esp_zb_attribute_list_t *ota_cluster = esp_zb_ota_cluster_create(&ota_cfg);
esp_zb_cluster_list_add_basic_cluster(cluster_list, basic_cluster, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE);
esp_zb_cluster_list_add_identify_cluster(cluster_list, identify_cluster, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE);
esp_zb_cluster_list_add_groups_cluster(cluster_list, groups_cluster, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE);
esp_zb_cluster_list_add_scenes_cluster(cluster_list, scenes_cluster, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE);
esp_zb_cluster_list_add_on_off_cluster(cluster_list, on_off_cluster, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE);
esp_zb_cluster_list_add_level_cluster(cluster_list, level_cluster, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE);
// esp_zb_cluster_list_add_ota_cluster(cluster_list, ota_cluster, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE); // disabling for now, not ready. maybe one day
}
void zigbee_endpoint_init(esp_zb_ep_list_t *ep_list, esp_zb_cluster_list_t *cluster_list) {
const zcl_basic_manufacturer_info_t mfg_info = { const zcl_basic_manufacturer_info_t mfg_info = {
.manufacturer_name = manufacturer, .manufacturer_name = manufacturer,
.model_identifier = model, .model_identifier = model,
}; };
if (zigbee_utility_add_ep_basic_manufacturer_info(ep_desc, &mfg_info) != EZB_ERR_NONE) {
const esp_zb_endpoint_config_t ep_cfg = { ezb_af_free_endpoint_desc(ep_desc);
.endpoint = endpoint_no, return EZB_INVALID_AF_EP_DESC;
.app_device_id = 0x0101, }
.app_profile_id = 0x0104, return ep_desc;
.app_device_version = 0,
};
esp_zb_ep_list_add_ep(ep_list, cluster_list, ep_cfg);
zigbee_utility_add_ep_basic_manufacturer_info(ep_list, ep_cfg.endpoint, &mfg_info);
} }
/* appearently you cant rename this? */ /* v2: not a magic symbol anymore, registered with ezb_app_signal_add_handler(). return true = handled */
void esp_zb_app_signal_handler(esp_zb_app_signal_t* signal_s) { static bool zigbee_app_signal_handler(const ezb_app_signal_t *signal_s) {
uint32_t* p_sg_p = signal_s->p_app_signal; const ezb_app_signal_type_t sig_type = ezb_app_signal_get_type(signal_s);
const esp_err_t err_status = signal_s->esp_err_status; const void *params = ezb_app_signal_get_params(signal_s);
const esp_zb_app_signal_type_t sig_type = *p_sg_p;
switch (sig_type) { switch (sig_type) {
case EZB_ZDO_SIGNAL_SKIP_STARTUP:
/* v2 doesn't run initialization (rejoin) by itself anymore, kick it here */
ESP_LOGI(TAG, "Initialize Zigbee stack");
ezb_bdb_start_top_level_commissioning(EZB_BDB_MODE_INITIALIZATION);
return true;
case ESP_ZB_ZDO_SIGNAL_SKIP_STARTUP: case EZB_BDB_SIGNAL_DEVICE_FIRST_START:
ESP_LOGI(TAG, "Initialize Zigbee stack"); case EZB_BDB_SIGNAL_DEVICE_REBOOT: {
esp_zb_bdb_start_top_level_commissioning(ESP_ZB_BDB_MODE_INITIALIZATION); const uint8_t status = params
break; ? ((const ezb_bdb_signal_simple_params_t *) params)->status
: (uint8_t) EZB_BDB_STATUS_SUCCESS;
case ESP_ZB_BDB_SIGNAL_DEVICE_FIRST_START: if (status == EZB_BDB_STATUS_SUCCESS) {
case ESP_ZB_BDB_SIGNAL_DEVICE_REBOOT: ESP_LOGI(TAG, "Deferred driver initialization %s", deferred_driver_init() ? "failed" : "successful");
if (err_status == ESP_OK) { ESP_LOGI(TAG, "Device started up in%s factory-reset mode", ezb_bdb_is_factory_new() ? "" : " non");
ESP_LOGI(TAG, "Deferred driver initialization %s", deferred_driver_init() ? "failed" : "successful"); if (ezb_bdb_is_factory_new()) {
ESP_LOGI(TAG, "Device started up in%s factory-reset mode", esp_zb_bdb_is_factory_new() ? "" : " non"); ESP_LOGI(TAG, "Start network steering");
if (esp_zb_bdb_is_factory_new()) { ezb_bdb_start_top_level_commissioning(EZB_BDB_MODE_NETWORK_STEERING);
ESP_LOGI(TAG, "Start network steering"); } else {
esp_zb_bdb_start_top_level_commissioning(ESP_ZB_BDB_MODE_NETWORK_STEERING); ESP_LOGI(TAG, "Device rebooted, steering anyway");
ezb_bdb_start_top_level_commissioning(EZB_BDB_MODE_NETWORK_STEERING);
}
} else {
ESP_LOGW(TAG, "%s failed with status: 0x%02x, retrying", ezb_app_signal_to_string(sig_type), status);
zigbee_schedule_commissioning(EZB_BDB_MODE_INITIALIZATION, ZB_COMMISSIONING_RETRY_MS);
set_status_error_or_resetting();
} }
else return true;
{ }
ESP_LOGI(TAG, "Device rebooted, steering anyway");
esp_zb_bdb_start_top_level_commissioning(ESP_ZB_BDB_MODE_NETWORK_STEERING); case EZB_BDB_SIGNAL_STEERING: {
const uint8_t status = params
? ((const ezb_bdb_signal_simple_params_t *) params)->status
: (uint8_t) EZB_BDB_STATUS_SUCCESS;
if (status == EZB_BDB_STATUS_SUCCESS) {
ezb_extpanid_t extended_pan_id;
ezb_get_extended_panid(&extended_pan_id);
ESP_LOGI(
TAG,
"Joined network successfully (Extended PAN ID: %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x, PAN ID: 0x%04hx, Channel:%d, Short Address: 0x%04hx)",
extended_pan_id.u8[7], extended_pan_id.u8[6], extended_pan_id.u8[5], extended_pan_id.u8[4],
extended_pan_id.u8[3], extended_pan_id.u8[2], extended_pan_id.u8[1], extended_pan_id.u8[0],
ezb_get_panid(), ezb_get_current_channel(), ezb_get_short_address());
zigbee_report_on_off_level(false, 254); /* we're in a stack callback, lock is already held */
set_status_joined();
} else {
ESP_LOGI(TAG, "Network steering was not successful (status: 0x%02x)", status);
zigbee_schedule_commissioning(EZB_BDB_MODE_NETWORK_STEERING, ZB_COMMISSIONING_RETRY_MS);
set_status_error_or_resetting();
} }
return true;
} }
else {
ESP_LOGW(TAG, "%s failed with status: %s, retrying", esp_zb_zdo_signal_to_string(sig_type),
esp_err_to_name(err_status));
esp_zb_scheduler_alarm((esp_zb_callback_t)bdb_start_top_level_commissioning_cb, ESP_ZB_BDB_MODE_INITIALIZATION, 1000);
set_status_error_or_resetting();
}
break;
case ESP_ZB_BDB_SIGNAL_STEERING: case EZB_NWK_SIGNAL_PERMIT_JOIN_STATUS: {
if (err_status == ESP_OK) { /* no err_status in v2, the signal just fires on open/close */
esp_zb_ieee_addr_t extended_pan_id; const uint8_t duration = params
esp_zb_get_extended_pan_id(extended_pan_id); ? ((const ezb_nwk_signal_permit_join_status_params_t *) params)->duration
ESP_LOGI(TAG, "Joined network successfully (Extended PAN ID: %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x, PAN ID: 0x%04hx, Channel:%d, Short Address: 0x%04hx)", : 0;
extended_pan_id[7], extended_pan_id[6], extended_pan_id[5], extended_pan_id[4], if (duration) {
extended_pan_id[3], extended_pan_id[2], extended_pan_id[1], extended_pan_id[0], ESP_LOGI(TAG, "Network(0x%04hx) is open for %d seconds", ezb_get_panid(), duration);
esp_zb_get_pan_id(), esp_zb_get_current_channel(), esp_zb_get_short_address()); } else { ESP_LOGW(TAG, "Network(0x%04hx) closed, devices joining not allowed.", ezb_get_panid()); }
zigbee_report_on_off_level(false, 254); return true;
set_status_joined();
} }
else {
ESP_LOGI(TAG, "Network steering was not successful (status: %s)", esp_err_to_name(err_status));
esp_zb_scheduler_alarm((esp_zb_callback_t)bdb_start_top_level_commissioning_cb, ESP_ZB_BDB_MODE_NETWORK_STEERING, 1000);
set_status_error_or_resetting();
}
break;
case ESP_ZB_NWK_SIGNAL_PERMIT_JOIN_STATUS: default:
if (err_status == ESP_OK) { ESP_LOGI(TAG, "ZDO signal: %s (0x%x)", ezb_app_signal_to_string(sig_type), sig_type);
if (*(uint8_t*)esp_zb_app_signal_get_params(p_sg_p)) { return false;
ESP_LOGI(TAG, "Network(0x%04hx) is open for %d seconds", esp_zb_get_pan_id(), *(uint8_t *)esp_zb_app_signal_get_params(p_sg_p));
}
else { ESP_LOGW(TAG, "Network(0x%04hx) closed, devices joining not allowed.", esp_zb_get_pan_id()); }
}
break;
default:
ESP_LOGI(TAG, "ZDO signal: %s (0x%x), status: %s", esp_zb_zdo_signal_to_string(sig_type), sig_type, esp_err_to_name(err_status));
break;
} }
} }
void zigbee_task(void* pvParameters) { void zigbee_task(void *pvParameters) {
esp_zb_platform_config_t zb_platform_config = { /* v2 keeps its persistent data in nvs, not fat. old v1 data in this partition is not migrated */
.radio_config = { esp_err_t nvs_err = nvs_flash_init_partition(ZB_STORAGE_PARTITION);
.radio_mode = ZB_RADIO_MODE_NATIVE, if (nvs_err == ESP_ERR_NVS_NO_FREE_PAGES || nvs_err == ESP_ERR_NVS_NEW_VERSION_FOUND) {
}, ESP_LOGW(TAG, "%s is not valid nvs (old v1 fat data?), erasing, device will need to re-pair",
.host_config = { ZB_STORAGE_PARTITION);
.host_connection_mode = ZB_HOST_CONNECTION_MODE_NONE, ESP_ERROR_CHECK(nvs_flash_erase_partition(ZB_STORAGE_PARTITION));
} nvs_err = nvs_flash_init_partition(ZB_STORAGE_PARTITION);
}; }
ESP_ERROR_CHECK(nvs_err);
esp_zb_cfg_t zb_nwk_cfg = { const esp_zigbee_config_t zb_config = {
.esp_zb_role = ESP_ZB_DEVICE_TYPE_ROUTER, .device_config = {
.install_code_policy = false, .device_type = EZB_NWK_DEVICE_TYPE_ROUTER,
.nwk_cfg.zczr_cfg = { .install_code_policy = false,
.max_children = 10, .zczr_config = {
.max_children = ZB_ROUTER_MAX_CHILDREN,
},
},
.platform_config = {
.storage_partition_name = ZB_STORAGE_PARTITION,
.radio_config = {
.radio_mode = ESP_ZIGBEE_RADIO_MODE_NATIVE,
},
}, },
}; };
ESP_ERROR_CHECK(esp_zb_platform_config(&zb_platform_config)); ESP_ERROR_CHECK(esp_zigbee_init(&zb_config));
esp_zb_init(&zb_nwk_cfg);
set_status_connecting(); set_status_connecting();
esp_zb_cluster_list_t *cluster_list = esp_zb_zcl_cluster_list_create(); ESP_ERROR_CHECK(ezb_app_signal_add_handler(zigbee_app_signal_handler) == EZB_ERR_NONE ? ESP_OK : ESP_FAIL);
esp_zb_ep_list_t *endpoint_list = esp_zb_ep_list_create();
zigbee_clusterfuck_init(cluster_list); ezb_af_device_desc_t device_desc = ezb_af_create_device_desc();
zigbee_endpoint_init(endpoint_list, cluster_list); ESP_ERROR_CHECK(device_desc != EZB_INVALID_AF_DEVICE_DESC ? ESP_OK : ESP_FAIL);
esp_zb_device_register(endpoint_list); ezb_af_ep_desc_t ep_desc = zigbee_endpoint_create();
esp_zb_core_action_handler_register(zigbee_action_handler); ESP_ERROR_CHECK(ep_desc != EZB_INVALID_AF_EP_DESC ? ESP_OK : ESP_FAIL);
esp_zb_set_primary_network_channel_set(ESP_ZB_TRANSCEIVER_ALL_CHANNELS_MASK);
ESP_ERROR_CHECK(esp_zb_start(false)); ESP_ERROR_CHECK(ezb_af_device_add_endpoint_desc(device_desc, ep_desc) == EZB_ERR_NONE ? ESP_OK : ESP_FAIL);
ESP_ERROR_CHECK(ezb_af_device_desc_register(device_desc) == EZB_ERR_NONE ? ESP_OK : ESP_FAIL);
esp_zb_stack_main_loop(); // blocking, holds the task here ezb_zcl_core_action_handler_register(zigbee_action_handler);
/* channel mask: v2 scans all channels by default, ESP_ZB_TRANSCEIVER_ALL_CHANNELS_MASK is gone */
ESP_ERROR_CHECK(esp_zigbee_start(false));
esp_zigbee_launch_mainloop(); // blocking, holds the task here until esp_zigbee_stop()
esp_zigbee_deinit();
vTaskDelete(nullptr);
} }

1603
sdkconfig

File diff suppressed because it is too large Load Diff