Merge pull request 'feat: 变更架构为广播,发送到所有绑定的端口' (#19) from feature/route into develop
Reviewed-on: #19
This commit was merged in pull request #19.
This commit is contained in:
Generated
+247
@@ -1,6 +1,253 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="BackendCodeEditorSettings">
|
||||
<option name="/Default/CodeInspection/GeneratedCode/GeneratedCodeRegions/=Component_0020Designer_0020generated_0020code/@EntryIndexedValue" value="Component Designer generated code" type="string" />
|
||||
<option name="/Default/CodeInspection/GeneratedCode/GeneratedCodeRegions/=Designer_0020generated_0020code/@EntryIndexedValue" value="Designer generated code" type="string" />
|
||||
<option name="/Default/CodeInspection/GeneratedCode/GeneratedCodeRegions/=Web_0020Form_0020Designer_0020generated_0020code/@EntryIndexedValue" value="Web Form Designer generated code" type="string" />
|
||||
<option name="/Default/CodeInspection/GeneratedCode/GeneratedCodeRegions/=Windows_0020Form_0020Designer_0020generated_0020code/@EntryIndexedValue" value="Windows Form Designer generated code" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CDeclarationWithImplicitIntType/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CommentTypo/@EntryIndexedValue" value="DO_NOT_SHOW" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=ConstevalIfIsAlwaysConstant/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppAbstractClassWithoutSpecifier/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppAbstractFinalClass/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppAbstractVirtualFunctionCallInCtor/@EntryIndexedValue" value="ERROR" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppAccessSpecifierWithNoDeclarations/@EntryIndexedValue" value="SUGGESTION" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppAwaiterTypeIsNotClass/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppBooleanIncrementExpression/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppBoostFormatBadCode/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppBoostFormatLegacyCode/@EntryIndexedValue" value="SUGGESTION" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppBoostFormatMixedArgs/@EntryIndexedValue" value="ERROR" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppBoostFormatTooFewArgs/@EntryIndexedValue" value="ERROR" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppBoostFormatTooManyArgs/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppCStyleCast/@EntryIndexedValue" value="SUGGESTION" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppCVQualifierCanNotBeAppliedToReference/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppClassCanBeFinal/@EntryIndexedValue" value="DO_NOT_SHOW" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppClassIsIncomplete/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppClassNeedsConstructorBecauseOfUninitializedMember/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppClassNeverUsed/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppCompileTimeConstantCanBeReplacedWithBooleanConstant/@EntryIndexedValue" value="SUGGESTION" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppConceptNeverUsed/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppConditionalExpressionCanBeSimplified/@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/=CppCoroutineCallResolveError/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFAArrayIndexOutOfBounds/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFAConstantConditions/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFAConstantFunctionResult/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFAConstantParameter/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFADeletedPointer/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFAEndlessLoop/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFAInfiniteRecursion/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFAInvalidatedMemory/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFALocalValueEscapesFunction/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFALocalValueEscapesScope/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFALoopConditionNotUpdated/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFAMemoryLeak/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFANotInitializedField/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFANullDereference/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFATimeOver/@EntryIndexedValue" value="HINT" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFAUnreachableCode/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFAUnreachableFunctionCall/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFAUnreadVariable/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDFAUnusedValue/@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/=CppDeclarationSpecifierWithoutDeclarators/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDeclaratorDisambiguatedAsFunction/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDeclaratorNeverUsed/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDeclaratorUsedBeforeInitialization/@EntryIndexedValue" value="ERROR" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDefaultCaseNotHandledInSwitchStatement/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDefaultInitializationWithNoUserConstructor/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDefaultIsUsedAsIdentifier/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDefaultedSpecialMemberFunctionIsImplicitlyDeleted/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDefinitionsOrder/@EntryIndexedValue" value="HINT" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDeletingVoidPointer/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDependentTemplateWithoutTemplateKeyword/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDependentTypeWithoutTypenameKeyword/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDeprecatedEntity/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDeprecatedOverridenMethod/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDeprecatedRegisterStorageClassSpecifier/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDereferenceOperatorLimitExceeded/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDiscardedPostfixOperatorResult/@EntryIndexedValue" value="SUGGESTION" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDoxygenSyntaxError/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDoxygenUndocumentedParameter/@EntryIndexedValue" value="SUGGESTION" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppDoxygenUnresolvedReference/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppEmptyDeclaration/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppEnforceCVQualifiersOrder/@EntryIndexedValue" value="DO_NOT_SHOW" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppEnforceCVQualifiersPlacement/@EntryIndexedValue" value="DO_NOT_SHOW" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppEnforceDoStatementBraces/@EntryIndexedValue" value="DO_NOT_SHOW" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppEnforceForStatementBraces/@EntryIndexedValue" value="DO_NOT_SHOW" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppEnforceFunctionDeclarationStyle/@EntryIndexedValue" value="DO_NOT_SHOW" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppEnforceIfStatementBraces/@EntryIndexedValue" value="DO_NOT_SHOW" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppEnforceNestedNamespacesStyle/@EntryIndexedValue" value="HINT" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppEnforceOverridingDestructorStyle/@EntryIndexedValue" value="SUGGESTION" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppEnforceOverridingFunctionStyle/@EntryIndexedValue" value="SUGGESTION" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppEnforceTypeAliasCodeStyle/@EntryIndexedValue" value="DO_NOT_SHOW" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppEnforceWhileStatementBraces/@EntryIndexedValue" value="DO_NOT_SHOW" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppEntityAssignedButNoRead/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppEntityUsedOnlyInUnevaluatedContext/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppEnumeratorNeverUsed/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppEqualOperandsInBinaryExpression/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppEvaluationFailure/@EntryIndexedValue" value="ERROR" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppExplicitSpecializationInNonNamespaceScope/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppExpressionWithoutSideEffects/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppFinalFunctionInFinalClass/@EntryIndexedValue" value="SUGGESTION" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppFinalNonOverridingVirtualFunction/@EntryIndexedValue" value="SUGGESTION" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppForLoopCanBeReplacedWithWhile/@EntryIndexedValue" value="SUGGESTION" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppForwardEnumDeclarationWithoutUnderlyingType/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppFunctionDoesntReturnValue/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppFunctionIsNotImplemented/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppFunctionResultShouldBeUsed/@EntryIndexedValue" value="HINT" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppFunctionalStyleCast/@EntryIndexedValue" value="SUGGESTION" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppHeaderHasBeenAlreadyIncluded/@EntryIndexedValue" value="HINT" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppHiddenFunction/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppHidingFunction/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppIdenticalOperandsInBinaryExpression/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppIfCanBeReplacedByConstexprIf/@EntryIndexedValue" value="SUGGESTION" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppImplicitDefaultConstructorNotAvailable/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppIncompatiblePointerConversion/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppIncompleteSwitchStatement/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppInconsistentNaming/@EntryIndexedValue" value="DO_NOT_SHOW" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppIntegralToPointerConversion/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppInvalidLineContinuation/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppJoinDeclarationAndAssignment/@EntryIndexedValue" value="SUGGESTION" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppLambdaCaptureNeverUsed/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppLocalVariableMayBeConst/@EntryIndexedValue" value="HINT" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppLocalVariableMightNotBeInitialized/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppLocalVariableWithNonTrivialDtorIsNeverUsed/@EntryIndexedValue" value="DO_NOT_SHOW" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppLongFloat/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppMemberFunctionMayBeConst/@EntryIndexedValue" value="SUGGESTION" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppMemberFunctionMayBeStatic/@EntryIndexedValue" value="SUGGESTION" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppMemberInitializersOrder/@EntryIndexedValue" value="SUGGESTION" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppMismatchedClassTags/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppMissingIncludeGuard/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppMissingKeywordThrow/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppModulePartitionWithSeveralPartitionUnits/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppMsExtAddressOfClassRValue/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppMsExtBindingRValueToLvalueReference/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppMsExtCopyElisionInCopyInitDeclarator/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppMsExtDoubleUserConversionInCopyInit/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppMsExtNotInitializedStaticConstLocalVar/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppMsExtReinterpretCastFromNullptr/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppMultiCharacterLiteral/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppMultiCharacterWideLiteral/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppMustBePublicVirtualToImplementInterface/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppMutableSpecifierOnReferenceMember/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppNoDiscardExpression/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppNodiscardFunctionWithoutReturnValue/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppNonExceptionSafeResourceAcquisition/@EntryIndexedValue" value="HINT" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppNonExplicitConversionOperator/@EntryIndexedValue" value="HINT" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppNonExplicitConvertingConstructor/@EntryIndexedValue" value="HINT" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppNonInlineFunctionDefinitionInHeaderFile/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppNonInlineVariableDefinitionInHeaderFile/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppNotAllPathsReturnValue/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppObjectMemberMightNotBeInitialized/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppOutParameterMustBeWritten/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppParameterMayBeConst/@EntryIndexedValue" value="HINT" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppParameterMayBeConstPtrOrRef/@EntryIndexedValue" value="SUGGESTION" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppParameterNamesMismatch/@EntryIndexedValue" value="HINT" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppParameterNeverUsed/@EntryIndexedValue" value="HINT" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppPassValueParameterByConstReference/@EntryIndexedValue" value="SUGGESTION" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppPointerConversionDropsQualifiers/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppPointerToIntegralConversion/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppPolymorphicClassWithNonVirtualPublicDestructor/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppPossiblyErroneousEmptyStatements/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppPossiblyUninitializedMember/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppPossiblyUnintendedObjectSlicing/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppPrecompiledHeaderIsNotIncluded/@EntryIndexedValue" value="ERROR" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppPrecompiledHeaderNotFound/@EntryIndexedValue" value="ERROR" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppPrintfBadFormat/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppPrintfExtraArg/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppPrintfMissedArg/@EntryIndexedValue" value="ERROR" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppPrintfRiskyFormat/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppPrivateSpecialMemberFunctionIsNotImplemented/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRangeBasedForIncompatibleReference/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedefinitionOfDefaultArgumentInOverrideFunction/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantAccessSpecifier/@EntryIndexedValue" value="HINT" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantBaseClassAccessSpecifier/@EntryIndexedValue" value="HINT" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantBaseClassInitializer/@EntryIndexedValue" value="SUGGESTION" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantBooleanExpressionArgument/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantCastExpression/@EntryIndexedValue" value="HINT" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantComplexityInComparison/@EntryIndexedValue" value="SUGGESTION" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantConditionalExpression/@EntryIndexedValue" value="SUGGESTION" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantConstSpecifier/@EntryIndexedValue" value="HINT" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantControlFlowJump/@EntryIndexedValue" value="HINT" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantDereferencingAndTakingAddress/@EntryIndexedValue" value="SUGGESTION" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantElaboratedTypeSpecifier/@EntryIndexedValue" value="HINT" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantElseKeyword/@EntryIndexedValue" value="HINT" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantElseKeywordInsideCompoundStatement/@EntryIndexedValue" value="HINT" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantEmptyDeclaration/@EntryIndexedValue" value="HINT" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantEmptyStatement/@EntryIndexedValue" value="HINT" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantExportKeyword/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantFwdClassOrEnumSpecifier/@EntryIndexedValue" value="SUGGESTION" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantInlineSpecifier/@EntryIndexedValue" value="HINT" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantLambdaParameterList/@EntryIndexedValue" value="HINT" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantMemberInitializer/@EntryIndexedValue" value="SUGGESTION" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantNamespaceDefinition/@EntryIndexedValue" value="SUGGESTION" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantParentheses/@EntryIndexedValue" value="HINT" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantQualifier/@EntryIndexedValue" value="HINT" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantQualifierADL/@EntryIndexedValue" value="DO_NOT_SHOW" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantStaticSpecifierOnMemberAllocationFunction/@EntryIndexedValue" value="HINT" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantStaticSpecifierOnThreadLocalLocalVariable/@EntryIndexedValue" value="HINT" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantTemplateArguments/@EntryIndexedValue" value="HINT" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantTemplateKeyword/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantTypenameKeyword/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantVoidArgumentList/@EntryIndexedValue" value="SUGGESTION" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRedundantZeroInitializerInAggregateInitialization/@EntryIndexedValue" value="SUGGESTION" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppReinterpretCastFromVoidPtr/@EntryIndexedValue" value="SUGGESTION" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppRemoveRedundantBraces/@EntryIndexedValue" value="DO_NOT_SHOW" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppReplaceMemsetWithZeroInitialization/@EntryIndexedValue" value="SUGGESTION" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppReplaceTieWithStructuredBinding/@EntryIndexedValue" value="SUGGESTION" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppReturnNoValueInNonVoidFunction/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppSmartPointerVsMakeFunction/@EntryIndexedValue" value="SUGGESTION" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppSomeObjectMembersMightNotBeInitialized/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppSpecialFunctionWithoutNoexceptSpecification/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppStaticAssertFailure/@EntryIndexedValue" value="ERROR" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppStaticDataMemberInUnnamedStruct/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppStaticSpecifierOnAnonymousNamespaceMember/@EntryIndexedValue" value="SUGGESTION" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppStringLiteralToCharPointerConversion/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppTabsAreDisallowed/@EntryIndexedValue" value="DO_NOT_SHOW" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppTemplateArgumentsCanBeDeduced/@EntryIndexedValue" value="HINT" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppTemplateParameterNeverUsed/@EntryIndexedValue" value="HINT" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppTemplateParameterShadowing/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppThrowExpressionCanBeReplacedWithRethrow/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppTooWideScope/@EntryIndexedValue" value="SUGGESTION" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppTooWideScopeInitStatement/@EntryIndexedValue" value="HINT" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppTypeAliasNeverUsed/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUninitializedDependentBaseClass/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUninitializedNonStaticDataMember/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUnionMemberOfReferenceType/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUnmatchedPragmaEndRegionDirective/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUnmatchedPragmaRegionDirective/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUnnamedNamespaceInHeaderFile/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUnnecessaryWhitespace/@EntryIndexedValue" value="DO_NOT_SHOW" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUnsignedZeroComparison/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUnusedIncludeDirective/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUseAlgorithmWithCount/@EntryIndexedValue" value="SUGGESTION" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUseAssociativeContains/@EntryIndexedValue" value="SUGGESTION" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUseAuto/@EntryIndexedValue" value="HINT" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUseAutoForNumeric/@EntryIndexedValue" value="HINT" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUseElementsView/@EntryIndexedValue" value="SUGGESTION" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUseEraseAlgorithm/@EntryIndexedValue" value="SUGGESTION" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUseFamiliarTemplateSyntaxForGenericLambdas/@EntryIndexedValue" value="SUGGESTION" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUseRangeAlgorithm/@EntryIndexedValue" value="SUGGESTION" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUseStdSize/@EntryIndexedValue" value="SUGGESTION" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUseStructuredBinding/@EntryIndexedValue" value="HINT" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUseTypeTraitAlias/@EntryIndexedValue" value="SUGGESTION" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUserDefinedLiteralSuffixDoesNotStartWithUnderscore/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppUsingResultOfAssignmentAsCondition/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppVariableCanBeMadeConstexpr/@EntryIndexedValue" value="SUGGESTION" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppVirtualFunctionCallInsideCtor/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppVirtualFunctionInFinalClass/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppVolatileParameterInDeclaration/@EntryIndexedValue" value="SUGGESTION" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppWarningDirective/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppWrongIncludesOrder/@EntryIndexedValue" value="HINT" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppWrongSlashesInIncludeDirective/@EntryIndexedValue" value="HINT" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppZeroConstantCanBeReplacedWithNullptr/@EntryIndexedValue" value="SUGGESTION" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=CppZeroValuedExpressionUsedAsNullPointer/@EntryIndexedValue" value="WARNING" type="string" />
|
||||
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=IdentifierTypo/@EntryIndexedValue" value="DO_NOT_SHOW" 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/=StringLiteralTypo/@EntryIndexedValue" value="DO_NOT_SHOW" type="string" />
|
||||
</component>
|
||||
</project>
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
## 1. 设计目标
|
||||
|
||||
轻量级 C 语言数据路由库。发送与接收能力分开声明,每个端口独立设置发送类型和接收类型,支持多外设一对多广播路由。
|
||||
轻量级 C 语言数据路由库。发送与接收能力分开声明,端口绑定 `send_type` 和外设 handler 列表。调用 `datarouter_send_<id>(data, len)` 时自动遍历端口表,广播到所有 `send_type` 匹配的端口。
|
||||
|
||||
### 核心设计
|
||||
|
||||
@@ -12,27 +12,25 @@ DATAROUTER_SEND_CAPABILITIES DATAROUTER_RECV_CAPABILITIES
|
||||
DATAROUTER_SEND(status, ...) DATAROUTER_RECV(command, ...)
|
||||
│ │
|
||||
▼ ▼
|
||||
send_sensor(port, data) on_recv_rtcm(port, data)
|
||||
send_status(port, data) on_recv_command(port, data)
|
||||
send_sensor(data, len) on_recv_rtcm(port, data, len)
|
||||
│ (用户实现回调)
|
||||
▼
|
||||
端口校验 → for each handler(port, data)
|
||||
遍历端口表 → send_type 匹配?
|
||||
│
|
||||
┌────────┼────────┐
|
||||
▼ ▼ ▼
|
||||
UART TCP CAN
|
||||
▼
|
||||
for each handler(port, data) ─── UART / TCP / CAN
|
||||
```
|
||||
|
||||
**关键区别**:sensor 只声明发送,不生成接收回调;rtcm 只声明接收,不生成发送函数。端口可独立设置 send_type 和 recv_type,互不干扰。
|
||||
**关键**:send 无 port_id 参数,自动路由到所有匹配端口。
|
||||
|
||||
### 设计原则
|
||||
|
||||
| 原则 | 说明 |
|
||||
|------|------|
|
||||
| 收发分离 | 发送能力和接收能力在配置中分开声明,按需组合 |
|
||||
| 收发分离 | 发送/接收能力在配置中分开声明,按需组合 |
|
||||
| 编译期确定能力 | 所有能力在 `datarouter_config.h` 中声明,库自动生成代码 |
|
||||
| 运行期绑定外设 | 端口创建后,通过 `add_handler` 注册物理外设发送函数 |
|
||||
| 一对多广播 | 一个端口可注册多个 handler,发送时逐一调用 |
|
||||
| 自动广播 | `send_<id>(data, len)` 遍历所有端口,自动匹配 send_type |
|
||||
| 不关心物理外设 | 库不依赖任何外设 API,只调用用户提供的 handler |
|
||||
| 零动态内存 | 纯静态数组,无 malloc/free |
|
||||
|
||||
@@ -47,23 +45,22 @@ DATAROUTER_SEND_CAPABILITIES DATAROUTER_RECV_CAPABILITIES
|
||||
left to right direction
|
||||
|
||||
rectangle "用户代码" as User {
|
||||
component "应用逻辑" as App
|
||||
component "datarouter_config.h\n声明发送+接收能力" as Cfg
|
||||
component "应用逻辑\n调 send_<id>(data, len)" as App
|
||||
component "datarouter_config.h\n声明能力" as Cfg
|
||||
component "外设 handler\nUART / TCP / CAN" as Handlers
|
||||
component "接收回调\n处理收到的报文" as Callbacks
|
||||
component "接收回调\non_recv_<id>()" as Callbacks
|
||||
}
|
||||
|
||||
database "DataRouter 库" as Lib {
|
||||
component "datarouter.h\n公共 API + X-macro 展开" as Hdr
|
||||
component "datarouter.c\n端口表 + handler 遍历" as Impl
|
||||
component "datarouter.h\n公共 API + X-macro" as Hdr
|
||||
component "datarouter.c\n端口表+遍历路由" as Impl
|
||||
}
|
||||
|
||||
App --> Hdr
|
||||
Cfg --> Hdr
|
||||
Impl --> Cfg
|
||||
Handlers --> Impl : 注册 handler
|
||||
Handlers --> Impl : add_handler
|
||||
Callbacks --> Impl : 实现 on_recv_<id>
|
||||
|
||||
@enduml
|
||||
```
|
||||
|
||||
@@ -71,11 +68,11 @@ Callbacks --> Impl : 实现 on_recv_<id>
|
||||
|
||||
| 文件 | 职责 |
|
||||
|------|------|
|
||||
| `datarouter_config.h` | 分别声明 `SEND_CAPABILITIES` 和 `RECV_CAPABILITIES` |
|
||||
| `datarouter.h` | 公共 API + X-macro 展开(两组枚举 + 声明) |
|
||||
| `datarouter.c` | 端口表 + handler 列表遍历 + 弱符号回调 |
|
||||
| `example.c` | 收发分离示例 |
|
||||
| `tests/test_datarouter.c` | 27 个单元测试 |
|
||||
| `datarouter_config.h` | 声明 `SEND_CAPABILITIES` 和 `RECV_CAPABILITIES` |
|
||||
| `datarouter.h` | 公共 API + X-macro 展开 |
|
||||
| `datarouter.c` | 端口表 + send 遍历 + 弱符号回调 |
|
||||
| `example.c` | 使用示例 |
|
||||
| `tests/test_datarouter.c` | 22 个单元测试 |
|
||||
|
||||
---
|
||||
|
||||
@@ -84,12 +81,10 @@ Callbacks --> Impl : 实现 on_recv_<id>
|
||||
### 3.1 配置声明
|
||||
|
||||
```c
|
||||
// 发送能力 —— 只生成发送触发函数
|
||||
#define DATAROUTER_SEND_CAPABILITIES \
|
||||
DATAROUTER_SEND(sensor, "Sensor data report") \
|
||||
DATAROUTER_SEND(status, "Device status report")
|
||||
|
||||
// 接收能力 —— 只生成接收回调声明
|
||||
#define DATAROUTER_RECV_CAPABILITIES \
|
||||
DATAROUTER_RECV(rtcm, "RTCM correction data") \
|
||||
DATAROUTER_RECV(command, "Remote control command")
|
||||
@@ -99,75 +94,58 @@ Callbacks --> Impl : 实现 on_recv_<id>
|
||||
|
||||
```
|
||||
DATAROUTER_SEND_CAPABILITIES 展开:
|
||||
enum: DATAROUTER_SEND_sensor = 0,
|
||||
DATAROUTER_SEND_status = 1,
|
||||
DATAROUTER_SEND_CAP_COUNT = 2
|
||||
发送函数: int datarouter_send_sensor(port, data, len);
|
||||
int datarouter_send_status(port, data, len);
|
||||
enum: sensor = 0, status = 1, SEND_CAP_COUNT = 2
|
||||
发送函数: int datarouter_send_sensor(const void *data, size_t len);
|
||||
int datarouter_send_status(const void *data, size_t len);
|
||||
元数据: send_names[] = {"sensor", "status"}
|
||||
send_descs[] = {"Sensor data report", "Device status report"}
|
||||
|
||||
DATAROUTER_RECV_CAPABILITIES 展开:
|
||||
enum: DATAROUTER_RECV_rtcm = 0,
|
||||
DATAROUTER_RECV_command = 1,
|
||||
DATAROUTER_RECV_CAP_COUNT = 2
|
||||
接收回调: void datarouter_on_recv_rtcm(port, data, len);
|
||||
void datarouter_on_recv_command(port, data, len);
|
||||
弱符号默认: 每个回调提供空的 weak 实现,用户覆盖
|
||||
enum: rtcm = 0, command = 1, RECV_CAP_COUNT = 2
|
||||
接收回调: void datarouter_on_recv_rtcm(uint32_t port, const void*, size_t);
|
||||
void datarouter_on_recv_command(uint32_t port, const void*, size_t);
|
||||
弱符号默认: 空实现,用户覆盖
|
||||
元数据: recv_names[] = {"rtcm", "command"}
|
||||
recv_descs[] = {"RTCM correction data", "Remote control command"}
|
||||
```
|
||||
|
||||
### 3.3 端口组合示例
|
||||
### 3.3 端口示例
|
||||
|
||||
```
|
||||
端口 A: send_type = sensor, recv_type = -1 → 只发送
|
||||
端口 B: send_type = -1, recv_type = rtcm → 只接收
|
||||
端口 C: send_type = status, recv_type = command → 同时收发
|
||||
端口 D: send_type = -1, recv_type = -1 → 无功能
|
||||
端口 A: send_type = sensor, handlers=[uart_send, tcp_send]
|
||||
端口 B: send_type = sensor, handlers=[can_send]
|
||||
端口 C: send_type = status, handlers=[uart_send]
|
||||
```
|
||||
|
||||
调用 `send_sensor("temp", 4)` → A 和 B 同时触发。
|
||||
|
||||
---
|
||||
|
||||
## 4. X-macro 代码生成
|
||||
|
||||
### 4.1 展开流程
|
||||
|
||||
```plantuml
|
||||
@startuml
|
||||
== datarouter.h:4 次展开 ==
|
||||
== datarouter.h ==
|
||||
|
||||
-> datarouter_config.h: 获得两组宏列表
|
||||
|
||||
datarouter.h -> "第 1 遍":
|
||||
#define DATAROUTER_SEND(id,desc) DATAROUTER_SEND_##id,
|
||||
DATAROUTER_SEND_CAPABILITIES → 发送 enum
|
||||
datarouter.h -> "1": #define DATAROUTER_SEND(id,desc) DATAROUTER_SEND_##id,
|
||||
note right: 发送 enum
|
||||
|
||||
datarouter.h -> "第 2 遍":
|
||||
#define DATAROUTER_RECV(id,desc) DATAROUTER_RECV_##id,
|
||||
DATAROUTER_RECV_CAPABILITIES → 接收 enum
|
||||
datarouter.h -> "2": #define DATAROUTER_RECV(id,desc) DATAROUTER_RECV_##id,
|
||||
note right: 接收 enum
|
||||
|
||||
datarouter.h -> "第 3 遍":
|
||||
#define DATAROUTER_SEND(id,desc) int datarouter_send_##id(...);
|
||||
DATAROUTER_SEND_CAPABILITIES → 发送函数声明
|
||||
datarouter.h -> "3": #define DATAROUTER_SEND(id,desc) int send_##id(data, len);
|
||||
note right: 发送函数声明
|
||||
|
||||
datarouter.h -> "第 4 遍":
|
||||
#define DATAROUTER_RECV(id,desc) void datarouter_on_recv_##id(...);
|
||||
DATAROUTER_RECV_CAPABILITIES → 接收回调声明
|
||||
datarouter.h -> "4": #define DATAROUTER_RECV(id,desc) void on_recv_##id(...);
|
||||
note right: 接收回调声明
|
||||
|
||||
== datarouter.c:4 次展开 ==
|
||||
|
||||
datarouter.c -> "第 5 遍":
|
||||
弱符号回调默认实现(DATAROUTER_RECV 展开)
|
||||
|
||||
datarouter.c -> "第 6 遍":
|
||||
发送函数实现 body(DATAROUTER_SEND 展开)
|
||||
校验 → 遍历 handler 列表
|
||||
|
||||
datarouter.c -> "第 7 ~ 8 遍":
|
||||
send_names[] / send_descs[]
|
||||
recv_names[] / recv_descs[]
|
||||
== datarouter.c ==
|
||||
|
||||
datarouter.c -> "5": 弱符号回调默认实现
|
||||
datarouter.c -> "6": 发送函数实现(遍历端口表)
|
||||
datarouter.c -> "7~8": send_names[] / send_descs[] / recv_names[] / recv_descs[]
|
||||
@enduml
|
||||
```
|
||||
|
||||
@@ -181,21 +159,11 @@ datarouter.c -> "第 7 ~ 8 遍":
|
||||
@startuml
|
||||
skinparam classAttributeIconSize 0
|
||||
|
||||
enum "datarouter_send_cap" as S {
|
||||
SENSOR
|
||||
STATUS
|
||||
SEND_CAP_COUNT
|
||||
}
|
||||
|
||||
enum "datarouter_recv_cap" as R {
|
||||
RTCM
|
||||
COMMAND
|
||||
RECV_CAP_COUNT
|
||||
}
|
||||
enum "datarouter_send_cap" as S { SENSOR, STATUS, SEND_CAP_COUNT }
|
||||
enum "datarouter_recv_cap" as R { RTCM, COMMAND, RECV_CAP_COUNT }
|
||||
|
||||
class "port_entry_t" as Entry {
|
||||
- int send_type
|
||||
- int recv_type
|
||||
- datarouter_send_handler_t handlers[]
|
||||
- int count
|
||||
- uint8_t in_use
|
||||
@@ -206,8 +174,8 @@ class "datarouter_send_handler_t" as Handler {
|
||||
}
|
||||
|
||||
class "发送函数" as Send {
|
||||
+ int send_sensor(port, data, len)
|
||||
+ int send_status(port, data, len)
|
||||
+ int send_sensor(data, len)
|
||||
+ int send_status(data, len)
|
||||
}
|
||||
|
||||
class "接收回调" as Recv {
|
||||
@@ -215,10 +183,9 @@ class "接收回调" as Recv {
|
||||
+ void on_recv_command(port, data, len)
|
||||
}
|
||||
|
||||
Entry --> S : send_type ∈ S enum / -1
|
||||
Entry --> R : recv_type ∈ R enum / -1
|
||||
Entry --> Handler : handlers[] 数组
|
||||
Send --> Entry : 校验 send_type + 遍历 handlers
|
||||
Entry --> S : send_type
|
||||
Entry --> Handler : handlers[]
|
||||
Send --> Entry : 遍历端口表 → 匹配 send_type → 遍历 handlers
|
||||
Recv --> Entry : 用户根据业务调对应回调
|
||||
@enduml
|
||||
```
|
||||
@@ -226,13 +193,12 @@ Recv --> Entry : 用户根据业务调对应回调
|
||||
### 5.2 `port_entry_t`
|
||||
|
||||
```c
|
||||
#define DATAROUTER_MAX_HANDLERS_PER_PORT 4 // 每端口最多 4 个外设
|
||||
#define DATAROUTER_MAX_HANDLERS_PER_PORT 4
|
||||
|
||||
typedef struct {
|
||||
int send_type; // DATAROUTER_SEND_xxx / -1
|
||||
int recv_type; // DATAROUTER_RECV_xxx / -1
|
||||
int send_type;
|
||||
datarouter_send_handler_t handlers[DATAROUTER_MAX_HANDLERS_PER_PORT];
|
||||
int count; // 当前 handler 数量
|
||||
int count;
|
||||
uint8_t in_use;
|
||||
} port_entry_t;
|
||||
```
|
||||
@@ -259,28 +225,26 @@ void datarouter_reset(void); // 重置全部状态
|
||||
### 6.2 端口管理
|
||||
|
||||
```c
|
||||
datarouter_port_t datarouter_port_create(void); // 创建
|
||||
void datarouter_port_delete(datarouter_port_t port); // 删除
|
||||
datarouter_port_t datarouter_port_create(void);
|
||||
void datarouter_port_delete(datarouter_port_t port);
|
||||
|
||||
void datarouter_port_set_send_type(port, int cap_id); // 设置发送类型
|
||||
int datarouter_port_get_send_type(port); // -1 表示未设置
|
||||
void datarouter_port_set_recv_type(port, int cap_id); // 设置接收类型
|
||||
int datarouter_port_get_recv_type(port); // -1 表示未设置
|
||||
void datarouter_port_set_send_type(port, int cap_id);
|
||||
int datarouter_port_get_send_type(port);
|
||||
|
||||
int datarouter_port_add_handler(port, handler); // 注册外设 handler
|
||||
int datarouter_port_remove_handler(port, handler); // 移除
|
||||
void datarouter_port_clear_handlers(port); // 清除全部
|
||||
int datarouter_port_handler_count(port); // 数量
|
||||
int datarouter_port_add_handler(port, handler);
|
||||
int datarouter_port_remove_handler(port, handler);
|
||||
void datarouter_port_clear_handlers(port);
|
||||
int datarouter_port_handler_count(port);
|
||||
```
|
||||
|
||||
### 6.3 发送触发函数(每个 SEND 能力生成一个)
|
||||
|
||||
```c
|
||||
int datarouter_send_sensor(port, data, len);
|
||||
int datarouter_send_status(port, data, len);
|
||||
int datarouter_send_sensor(const void *data, size_t len);
|
||||
int datarouter_send_status(const void *data, size_t len);
|
||||
```
|
||||
|
||||
返回值:0 成功 / -1 未初始化 / -2 端口无效 / -3 send_type 不匹配 / -4 无 handler
|
||||
返回值:0 成功 / -1 未初始化 / -2 无端口匹配该 send_type
|
||||
|
||||
### 6.4 接收回调(每个 RECV 能力生成一个声明)
|
||||
|
||||
@@ -289,17 +253,15 @@ void datarouter_on_recv_rtcm(uint32_t port_id, const void *data, size_t len);
|
||||
void datarouter_on_recv_command(uint32_t port_id, const void *data, size_t len);
|
||||
```
|
||||
|
||||
库提供弱符号默认空实现,用户定义同名函数覆盖。
|
||||
库提供弱符号默认空实现。
|
||||
|
||||
### 6.5 能力元数据(两组独立)
|
||||
### 6.5 能力元数据
|
||||
|
||||
```c
|
||||
// 发送能力
|
||||
int datarouter_send_cap_count(void);
|
||||
const char *datarouter_send_cap_name(int cap_id);
|
||||
const char *datarouter_send_cap_desc(int cap_id);
|
||||
|
||||
// 接收能力
|
||||
int datarouter_recv_cap_count(void);
|
||||
const char *datarouter_recv_cap_name(int cap_id);
|
||||
const char *datarouter_recv_cap_desc(int cap_id);
|
||||
@@ -315,33 +277,35 @@ const char *datarouter_recv_cap_desc(int cap_id);
|
||||
@startuml
|
||||
actor "应用" as App
|
||||
participant "datarouter_send_sensor()" as Send
|
||||
participant "端口表" as Table
|
||||
participant "端口表 ports[]" as Table
|
||||
participant "handlers[]" as HList
|
||||
participant "外设" as Dev
|
||||
|
||||
App -> Send : send_sensor(port=2, data, len)
|
||||
App -> Send : send_sensor("temp:25.3", 9)
|
||||
|
||||
group 校验
|
||||
group 初始化检查
|
||||
Send -> Send : initialized?
|
||||
alt 否 → return -1
|
||||
end
|
||||
Send -> Table : ports[2].in_use?
|
||||
alt 否 → return -2
|
||||
end
|
||||
Send -> Table : ports[2].send_type == SENSOR?
|
||||
alt 否 → return -3
|
||||
end
|
||||
Send -> Table : ports[2].count > 0?
|
||||
alt 否 → return -4
|
||||
end
|
||||
end
|
||||
|
||||
loop for each handler in ports[2].handlers[]
|
||||
Send -> HList : handlers[i](port, data, len)
|
||||
group 遍历端口表
|
||||
loop for p in 0..MAX_PORTS-1
|
||||
Send -> Table : ports[p].in_use && ports[p].send_type == SENSOR ?
|
||||
alt 匹配
|
||||
loop for h in 0..count-1
|
||||
Send -> HList : handlers[h](p, data, len)
|
||||
HList -> Dev : 实际外设写入
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
alt 至少调了一次 handler
|
||||
Send --> App : return 0
|
||||
else 无匹配端口
|
||||
Send --> App : return -2
|
||||
end
|
||||
@enduml
|
||||
```
|
||||
|
||||
@@ -353,7 +317,7 @@ actor "外设" as Dev
|
||||
participant "用户分发代码" as Dispatch
|
||||
participant "on_recv_rtcm()" as Callback
|
||||
|
||||
Dev -> Dispatch : 收到数据,识别为 rtcm 类型
|
||||
Dev -> Dispatch : 收到数据,识别为 rtcm
|
||||
Dispatch -> Callback : on_recv_rtcm(port_id, data, len)
|
||||
Callback --> Dispatch : void
|
||||
@enduml
|
||||
@@ -364,19 +328,14 @@ Callback --> Dispatch : void
|
||||
```plantuml
|
||||
@startuml
|
||||
state "空闲" as Idle
|
||||
state "已创建\nsend=-1 recv=-1" as Created
|
||||
state "已创建\nsend_type=-1\ncount=0" as Created
|
||||
state "已配置" as Config
|
||||
|
||||
[*] --> Idle : reset / 启动
|
||||
|
||||
Idle --> Created : port_create()
|
||||
|
||||
Created --> Config : set_send_type / set_recv_type / add_handler
|
||||
|
||||
Config --> Config : 独立切换 send_type / recv_type\n增删 handler
|
||||
|
||||
Config --> Created : set_send_type(-1) / set_recv_type(-1)\nclear_handlers
|
||||
|
||||
Created --> Config : set_send_type / add_handler
|
||||
Config --> Config : 切换 send_type\n增删 handler
|
||||
Config --> Created : set_send_type(-1) / clear_handlers
|
||||
Created --> Idle : port_delete()
|
||||
Config --> Idle : port_delete()
|
||||
Idle --> Created : 复用 ID
|
||||
@@ -387,42 +346,38 @@ Idle --> Created : 复用 ID
|
||||
|
||||
## 8. 路由场景
|
||||
|
||||
### 场景 1:传感器只发送(sensor → UART + TCP)
|
||||
### 场景 1:sensor 广播到 UART + TCP + CAN
|
||||
|
||||
```c
|
||||
datarouter_port_t p = datarouter_port_create();
|
||||
datarouter_port_set_send_type(p, DATAROUTER_SEND_sensor);
|
||||
datarouter_port_add_handler(p, uart_send);
|
||||
datarouter_port_add_handler(p, tcp_send);
|
||||
datarouter_port_t p1 = datarouter_port_create();
|
||||
datarouter_port_set_send_type(p1, DATAROUTER_SEND_sensor);
|
||||
datarouter_port_add_handler(p1, uart_send);
|
||||
datarouter_port_add_handler(p1, tcp_send);
|
||||
|
||||
datarouter_send_sensor(p, "temp:25.3", 9);
|
||||
// → uart_send(p, "temp:25.3", 9)
|
||||
// → tcp_send(p, "temp:25.3", 9)
|
||||
datarouter_port_t p2 = datarouter_port_create();
|
||||
datarouter_port_set_send_type(p2, DATAROUTER_SEND_sensor);
|
||||
datarouter_port_add_handler(p2, can_send);
|
||||
|
||||
datarouter_send_sensor("temp:25.3", 9);
|
||||
// → uart_send(p1, "temp:25.3", 9)
|
||||
// → tcp_send(p1, "temp:25.3", 9)
|
||||
// → can_send(p2, "temp:25.3", 9)
|
||||
```
|
||||
|
||||
### 场景 2:RTCM 只接收
|
||||
### 场景 2:仅接收
|
||||
|
||||
```c
|
||||
datarouter_port_t p = datarouter_port_create();
|
||||
datarouter_port_set_recv_type(p, DATAROUTER_RECV_rtcm);
|
||||
// 无 send_type,不注册 handler
|
||||
|
||||
// 外设收到数据后由用户调回调:
|
||||
datarouter_on_recv_rtcm(p, data, len);
|
||||
void datarouter_on_recv_rtcm(uint32_t port_id, const void *data, size_t len) {
|
||||
apply_rtcm_correction(data, len);
|
||||
}
|
||||
// 外设收到后:datarouter_on_recv_rtcm(port, data, len);
|
||||
```
|
||||
|
||||
### 场景 3:双向端口(status 发送 + command 接收)
|
||||
### 场景 3:运行时移除 handler
|
||||
|
||||
```c
|
||||
datarouter_port_t p = datarouter_port_create();
|
||||
datarouter_port_set_send_type(p, DATAROUTER_SEND_status);
|
||||
datarouter_port_set_recv_type(p, DATAROUTER_RECV_command);
|
||||
datarouter_port_add_handler(p, uart_send);
|
||||
|
||||
// 发送
|
||||
datarouter_send_status(p, "status:OK", 9);
|
||||
// 接收
|
||||
datarouter_on_recv_command(p, "reboot", 6);
|
||||
datarouter_port_remove_handler(p1, tcp_send);
|
||||
// 下次 send_sensor 不再触发 tcp
|
||||
```
|
||||
|
||||
---
|
||||
@@ -451,30 +406,24 @@ Weak ..> Result : 后备
|
||||
|
||||
| 返回值 | 含义 |
|
||||
|:------:|------|
|
||||
| 0 | 成功,所有 handler 被调用 |
|
||||
| 0 | 成功,至少有一个 handler 被调用 |
|
||||
| -1 | 库未初始化(未调 init) |
|
||||
| -2 | 端口无效(越界/未创建/已删除) |
|
||||
| -3 | 端口 send_type 与调用的发送函数不匹配 |
|
||||
| -4 | 端口 handler 列表为空(count == 0) |
|
||||
| -2 | 无端口匹配该 send_type(或匹配端口均无 handler) |
|
||||
|
||||
---
|
||||
|
||||
## 11. 配置扩展
|
||||
|
||||
### 增加能力
|
||||
|
||||
```c
|
||||
#define DATAROUTER_SEND_CAPABILITIES \
|
||||
DATAROUTER_SEND(sensor, "Sensor data") \
|
||||
DATAROUTER_SEND(debug, "Debug log") /* 新增发送能力 */
|
||||
DATAROUTER_SEND(debug, "Debug log") /* 新增 */
|
||||
|
||||
#define DATAROUTER_RECV_CAPABILITIES \
|
||||
DATAROUTER_RECV(rtcm, "RTCM data") \
|
||||
DATAROUTER_RECV(ota, "OTA firmware") /* 新增接收能力 */
|
||||
DATAROUTER_RECV(ota, "OTA firmware") /* 新增 */
|
||||
```
|
||||
|
||||
### 自定义限制
|
||||
|
||||
```bash
|
||||
cmake -DCMAKE_C_FLAGS="-DDATAROUTER_MAX_PORTS=128 -DDATAROUTER_MAX_HANDLERS_PER_PORT=8"
|
||||
```
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
# DataRouter
|
||||
|
||||
轻量级 C 语言数据路由库。**发送能力和接收能力分开声明**,端口独立设置 send_type 和 recv_type,支持多外设一对多广播路由。
|
||||
轻量级 C 语言数据路由库。**发送能力和接收能力分开声明**,端口绑定 `send_type` 和外设 handler 列表。调用 `datarouter_send_<id>(data, len)` 时自动广播到所有匹配端口。
|
||||
|
||||
## 概念
|
||||
|
||||
| 术语 | 说明 |
|
||||
|------|------|
|
||||
| **发送能力 (Send Capability)** | 编译期声明的可发送报文类型,生成 `datarouter_send_<id>()` |
|
||||
| **接收能力 (Recv Capability)** | 编译期声明的可接收报文类型,生成 `datarouter_on_recv_<id>()` |
|
||||
| **端口 (Port)** | 运行期连接点,独立设置 send_type + recv_type + handler 列表 |
|
||||
| **发送能力 (Send Capability)** | 编译期声明的可发送报文类型,生成 `datarouter_send_<id>(data, len)` |
|
||||
| **接收能力 (Recv Capability)** | 编译期声明的可接收报文类型,生成 `datarouter_on_recv_<id>(port, data, len)` |
|
||||
| **端口 (Port)** | 运行期创建的连接点,包含 `send_type` + handler 列表 |
|
||||
| **Handler** | 用户实现的物理外设发送函数,一个端口可注册多个(默认上限 4) |
|
||||
|
||||
## 快速开始
|
||||
@@ -27,14 +27,11 @@
|
||||
DATAROUTER_RECV(command, "Remote control command")
|
||||
```
|
||||
|
||||
> 库默认自带一份示例配置。将你的 `datarouter_config.h` 放到项目目录,
|
||||
> 编译时添加 `-I /path/to/your/config` 即可覆盖。无需修改库源代码。
|
||||
> 库自带默认配置。将你的 `datarouter_config.h` 放到项目目录,
|
||||
> 编译时添加 `-I /path/to/your/config` 即可覆盖。无需修改库源码。
|
||||
>
|
||||
> **注意**:确保你的配置目录在包含路径中出现在库目录之前,否则编译 `datarouter.c`
|
||||
> 时仍会使用库的默认配置。在 CMake 中可参考:
|
||||
> ```cmake
|
||||
> # 你的 CMakeLists.txt
|
||||
> include_directories(BEFORE ${CMAKE_CURRENT_SOURCE_DIR}) # 全局优先
|
||||
> include_directories(BEFORE ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
> add_subdirectory(path/to/DataRouter)
|
||||
> target_link_libraries(my_app DataRouter)
|
||||
> ```
|
||||
@@ -56,26 +53,17 @@ static void tcp_send(uint32_t port_id, const void *data, size_t len) {
|
||||
```c
|
||||
datarouter_init();
|
||||
|
||||
/* —— 只发送:传感器上报 —— */
|
||||
/* —— 传感器上报:sensor 报文走 UART + TCP —— */
|
||||
datarouter_port_t tx = datarouter_port_create();
|
||||
datarouter_port_set_send_type(tx, DATAROUTER_SEND_sensor);
|
||||
datarouter_port_add_handler(tx, uart_send);
|
||||
datarouter_port_add_handler(tx, tcp_send);
|
||||
datarouter_send_sensor(tx, "temperature:25.3", 16); // → UART + TCP
|
||||
|
||||
/* —— 只接收:RTCM 修正 —— */
|
||||
datarouter_port_t rx = datarouter_port_create();
|
||||
datarouter_port_set_recv_type(rx, DATAROUTER_RECV_rtcm);
|
||||
// 外设收到数据后由用户调回调:
|
||||
datarouter_on_recv_rtcm(rx, data, len);
|
||||
/* 不指定端口,库自动广播到所有 send_type=sensor 的端口 */
|
||||
datarouter_send_sensor("temperature:25.3", 16); // → UART + TCP
|
||||
|
||||
/* —— 同时收发:状态上报 + 命令接收 —— */
|
||||
datarouter_port_t bi = datarouter_port_create();
|
||||
datarouter_port_set_send_type(bi, DATAROUTER_SEND_status);
|
||||
datarouter_port_set_recv_type(bi, DATAROUTER_RECV_command);
|
||||
datarouter_port_add_handler(bi, uart_send);
|
||||
datarouter_send_status(bi, "status:OK", 9);
|
||||
datarouter_on_recv_command(bi, "reboot", 6);
|
||||
/* —— 接收:实现回调,外设数据到达后自行调用 —— */
|
||||
datarouter_on_recv_rtcm(rx_port, data, len);
|
||||
```
|
||||
|
||||
### 4. 实现接收回调
|
||||
@@ -84,10 +72,6 @@ datarouter_on_recv_command(bi, "reboot", 6);
|
||||
void datarouter_on_recv_rtcm(uint32_t port_id, const void *data, size_t len) {
|
||||
apply_rtcm_correction(data, len);
|
||||
}
|
||||
|
||||
void datarouter_on_recv_command(uint32_t port_id, const void *data, size_t len) {
|
||||
execute_command(data, len);
|
||||
}
|
||||
```
|
||||
|
||||
## API 一览
|
||||
@@ -107,8 +91,6 @@ void datarouter_port_delete(datarouter_port_t port); // 删除
|
||||
|
||||
void datarouter_port_set_send_type(port, int cap_id); // 设置发送类型
|
||||
int datarouter_port_get_send_type(port); // -1 = 未设置
|
||||
void datarouter_port_set_recv_type(port, int cap_id); // 设置接收类型
|
||||
int datarouter_port_get_recv_type(port); // -1 = 未设置
|
||||
|
||||
int datarouter_port_add_handler(port, handler); // 注册外设 handler
|
||||
int datarouter_port_remove_handler(port, handler); // 移除
|
||||
@@ -119,12 +101,13 @@ int datarouter_port_handler_count(port); // 当前数量
|
||||
### 发送触发(每个 SEND 能力生成一个)
|
||||
|
||||
```c
|
||||
int datarouter_send_sensor(port, data, len); // 0 成功 / -1 未初始化
|
||||
int datarouter_send_status(port, data, len); // -2 端口无效
|
||||
// -3 send_type 不匹配
|
||||
// -4 无 handler
|
||||
int datarouter_send_sensor(const void *data, size_t len); // 0 成功
|
||||
int datarouter_send_status(const void *data, size_t len); // -1 未初始化
|
||||
// -2 无匹配端口
|
||||
```
|
||||
|
||||
不指定端口,库遍历所有端口,`send_type` 匹配的逐一调用其全部 handler。
|
||||
|
||||
### 接收回调(每个 RECV 能力生成一个声明)
|
||||
|
||||
```c
|
||||
@@ -149,17 +132,18 @@ const char *datarouter_recv_cap_desc(int cap_id);
|
||||
## 路由模型
|
||||
|
||||
```
|
||||
send_sensor(port, data, len)
|
||||
datarouter_send_sensor("temperature:25.3", 16)
|
||||
│
|
||||
├─→ handler[0] = uart_send → UART
|
||||
├─→ handler[1] = tcp_send → TCP
|
||||
└─→ handler[2] = can_send → CAN
|
||||
├─→ port 0 (send_type=sensor) handlers[0]=uart_send → UART
|
||||
│ handlers[1]=tcp_send → TCP
|
||||
└─→ port 1 (send_type=sensor) handlers[0]=can_send → CAN
|
||||
```
|
||||
|
||||
- 一个端口可注册多个 handler(一对多广播)
|
||||
- 调用 `send_<id>(data, len)` 时,库遍历所有端口,自动匹配 `send_type`
|
||||
- 每个端口可注册多个 handler(一对多广播)
|
||||
- 同一 handler 可注册到多个端口(多路复用)
|
||||
- 运行时通过 `add_handler` / `remove_handler` 动态改变路由
|
||||
- 清空 handler 列表后发送返回 -4
|
||||
- 运行时通过 `add_handler` / `remove_handler` / `port_delete` 动态改变路由
|
||||
- 无任何端口匹配该 `send_type` 时返回 -2
|
||||
|
||||
## 编译
|
||||
|
||||
@@ -183,16 +167,17 @@ ctest --test-dir build
|
||||
./build/test_datarouter
|
||||
```
|
||||
|
||||
当前 27 个测试用例,覆盖端口管理、send_type/recv_type 独立设置、handler 增删、一对多广播、接收回调、能力元数据、错误边界。
|
||||
当前 22 个测试用例,覆盖端口管理、send_type 与 handler 设置、自动广播路由、接收回调、能力元数据。
|
||||
|
||||
## 文件结构
|
||||
|
||||
```
|
||||
datarouter_config.h 发送 + 接收能力配置(用户编辑)
|
||||
datarouter_config.h 发送 + 接收能力配置(用户可覆盖)
|
||||
datarouter.h 公共 API + X-macro 展开
|
||||
datarouter.c 实现(端口表 + handler 遍历)
|
||||
example.c 收发分离使用示例
|
||||
tests/test_datarouter.c 单元测试(27 用例)
|
||||
datarouter.c 实现(端口表 + send 遍历)
|
||||
datarouter_config_template.h 外部配置模板
|
||||
example.c 使用示例
|
||||
tests/test_datarouter.c 单元测试(22 用例)
|
||||
DESIGN.md 详细设计文档(含 PlantUML 图)
|
||||
TEST_CASES.md 测试用例文档
|
||||
```
|
||||
|
||||
+27
-45
@@ -17,7 +17,6 @@
|
||||
cmake -S . -B build
|
||||
cmake --build build
|
||||
ctest --test-dir build
|
||||
# 或直接运行:
|
||||
./build/test_datarouter
|
||||
```
|
||||
|
||||
@@ -27,68 +26,53 @@ ctest --test-dir build
|
||||
|
||||
| # | 测试名 | 描述 | 步骤 | 预期 |
|
||||
|---|--------|------|------|------|
|
||||
| 1 | `error_uninit` | 未 init 时发送 | 不调 init 直接 `send_sensor(0, ...)` | 返回 -1 |
|
||||
| 1 | `error_uninit` | 未 init 时发送 | `send_sensor("d", 1)` | 返回 -1 |
|
||||
|
||||
### 2. 端口管理(4 个)
|
||||
|
||||
| # | 测试名 | 描述 | 步骤 | 预期 |
|
||||
|---|--------|------|------|------|
|
||||
| 2 | `port_create_basic` | 基本创建 | `port_create()` | 返回 ≥ 0 |
|
||||
| 3 | `port_create_max` | 满容量(64) | 循环创建到满再尝试 | 64 个成功,第 65 个 INVALID |
|
||||
| 3 | `port_create_max` | 满容量 64 | 循环创建到满再尝试 | 64 个成功,第 65 个 INVALID |
|
||||
| 4 | `port_delete_invalid` | 删除无效 ID | `delete(-1)` + `delete(999)` | 不崩溃 |
|
||||
| 5 | `port_default_state` | 默认状态 | 创建端口,查 send/recv/handler | send_type=-1, recv_type=-1, count=0 |
|
||||
| 5 | `port_default_state` | 默认状态 | 新建端口,查 send_type / handler count | `send_type=-1`, `count=0` |
|
||||
|
||||
### 3. send_type / recv_type 独立设置(6 个)
|
||||
### 3. send_type 与 handler(3 个)
|
||||
|
||||
| # | 测试名 | 描述 | 步骤 | 预期 |
|
||||
|---|--------|------|------|------|
|
||||
| 6 | `send_type_set_get` | 设置发送类型 | `set_send_type(sensor)` → `get_send_type()` | 返回 sensor |
|
||||
| 7 | `recv_type_set_get` | 设置接收类型 | `set_recv_type(rtcm)` → `get_recv_type()` | 返回 rtcm |
|
||||
| 8 | `types_independent` | 收发互不干扰 | 同时 `set_send_type(sensor)` + `set_recv_type(command)` | get_send=sensor, get_recv=command |
|
||||
| 9 | `send_type_clear` | 清除发送类型 | `set_send_type(sensor)` → `set_send_type(-1)` | `get_send_type()` == -1 |
|
||||
| 10 | `recv_type_clear` | 清除接收类型 | `set_recv_type(rtcm)` → `set_recv_type(-1)` | `get_recv_type()` == -1 |
|
||||
| 11 | `types_from_invalid` | 无效端口查类型 | `get_send_type(-1/999)` / `get_recv_type(-1/999)` | 均返回 -1 |
|
||||
| 6 | `send_type_set_get` | 设置并清除 send_type | `set_send_type(sensor)` → `get` → `set(-1)` → `get` | sensor → -1 |
|
||||
| 7 | `handler_add_remove` | 添加后移除 handler | add(h) count=1 → remove(h) count=0 | count 正确 |
|
||||
| 8 | `handler_clear` | 清除全部 handler | add → clear | count == 0 |
|
||||
|
||||
### 4. handler 增删(2 个)
|
||||
### 4. 发送 — 自动广播(11 个)
|
||||
|
||||
| # | 测试名 | 描述 | 步骤 | 预期 |
|
||||
|---|--------|------|------|------|
|
||||
| 12 | `handler_add_remove` | 添加后移除 | ① add(a) add(b) count=2 ② remove(a) count=1 | count 正确 |
|
||||
| 13 | `handler_clear` | 清除全部 | add 后 clear | count == 0 |
|
||||
| 9 | `send_no_match_port` | 无匹配端口 | 不创建任何端口,直接 `send_sensor` | 返回 -2 |
|
||||
| 10 | `send_one_port_one_handler` | 单端口单 handler | 创建端口中 send_type + add(h) → send | 返回 0;handler 1 次 |
|
||||
| 11 | `send_one_port_multi_handler` | 单端口双 handler | add(h) + add(h2) → send | handler 2 次 |
|
||||
| 12 | `send_multi_ports_same_type` | 两端口同类型 | p1(sensor,h) + p2(sensor,h) → send | handler 2 次,各端口一次 |
|
||||
| 13 | `send_multi_port_multi_handler` | 多端口多 handler | p1(h,h2) + p2(h3) → send | handler 3 次 |
|
||||
| 14 | `send_type_filter` | 类型过滤 | p1(sensor,h) + p2(status,h) → `send_sensor` | 只触发 p1 |
|
||||
| 15 | `send_after_remove_handler` | 移除 handler 后 | add(h) → send count=1 → remove(h) → send | 第二次返回 -2 |
|
||||
| 16 | `send_after_delete_port` | 删除端口后 | 创建→设好→删除→send | 返回 -2 |
|
||||
| 17 | `send_zero_length` | 零长度数据 | send("x", 0) | 返回 0;handler 被调 |
|
||||
| 18 | `send_null_data` | NULL 数据 | send(NULL, 0) | 返回 0;handler 被调 |
|
||||
| 19 | `send_multi_cap` | 多能力独立 | p1(sensor) + p2(status) → 分别 send_sensor + send_status | 各触发匹配的端口 |
|
||||
|
||||
### 5. 发送触发(9 个)
|
||||
### 5. 接收回调(1 个)
|
||||
|
||||
| # | 测试名 | 描述 | 步骤 | 预期 |
|
||||
|---|--------|------|------|------|
|
||||
| 14 | `send_one_handler` | 单 handler 发送 | send_type + add_handler → send_sensor | 返回 0;handler 被调用 1 次 |
|
||||
| 15 | `send_multi_handlers` | 三个 handler 广播 | 注册 3 个 handler 后 send | 返回 0;handler 被调用 3 次 |
|
||||
| 16 | `send_type_mismatch` | 发送类型不匹配 | set_send_type(sensor) 但调用 send_status | 返回 -3;handler 不被调用 |
|
||||
| 17 | `send_no_handler` | 未注册 handler | 只 set_send_type 不 add_handler | 返回 -4 |
|
||||
| 18 | `send_no_send_type` | 没有 send_type | 端口只有 recv_type,调 send_sensor | 返回 -3 |
|
||||
| 19 | `send_remove_handler` | 移除后少广播 | 注册 2 handler → send count=2 → remove 1 → send count=1 | 数量正确 |
|
||||
| 20 | `send_clear_handlers` | 清空后无法发送 | add → clear → send | 返回 -4 |
|
||||
| 21 | `send_zero_length` | 零长度数据 | send(port, "x", 0) | 返回 0;handler 被调用 |
|
||||
| 22 | `send_null_data` | NULL 数据 | send(port, NULL, 0) | 返回 0;handler 被调用 |
|
||||
| 20 | `recv_callback` | 用户实现接收回调 | `on_recv_rtcm(0, "d", 1)` | 回调被触发 |
|
||||
|
||||
### 6. 接收回调(1 个)
|
||||
### 6. 能力元数据(2 个)
|
||||
|
||||
| # | 测试名 | 描述 | 步骤 | 预期 |
|
||||
|---|--------|------|------|------|
|
||||
| 23 | `recv_callbacks` | 用户实现接收回调 | ① `on_recv_rtcm(0, ...)` ② `on_recv_command(1, ...)` | 各自触发,互不干扰 |
|
||||
|
||||
### 7. 能力元数据(2 个)
|
||||
|
||||
| # | 测试名 | 描述 | 步骤 | 预期 |
|
||||
|---|--------|------|------|------|
|
||||
| 24 | `send_cap_meta` | 发送能力元数据 | 查 count / name / desc / 边界 | SEND 两组正确 |
|
||||
| 25 | `recv_cap_meta` | 接收能力元数据 | 查 count / name / desc / 边界 | RECV 两组正确 |
|
||||
|
||||
### 8. 错误处理(2 个)
|
||||
|
||||
| # | 测试名 | 描述 | 步骤 | 预期 |
|
||||
|---|--------|------|------|------|
|
||||
| 26 | `error_invalid_port` | 无效端口 | `send_sensor(999/-1, ...)` | 均返回 -2 |
|
||||
| 27 | `error_deleted_port` | 已删除端口 | 创建→设好→删除→send | 返回 -2 |
|
||||
| 21 | `send_cap_meta` | 发送能力元数据 | count / name / desc / 边界 | SEND 两组正确 |
|
||||
| 22 | `recv_cap_meta` | 接收能力元数据 | count / name / desc / 边界 | RECV 两组正确 |
|
||||
|
||||
## 覆盖矩阵
|
||||
|
||||
@@ -96,11 +80,9 @@ ctest --test-dir build
|
||||
|----------|:------:|------------|
|
||||
| 未初始化 | 1 | send → -1 |
|
||||
| 端口管理 | 4 | 创建/满容量/删除异常/默认状态 |
|
||||
| send_type / recv_type | 6 | 设置/清除/独立/无效端口 |
|
||||
| handler 增删 | 2 | 添加/移除/清空 |
|
||||
| 发送触发 | 9 | 单播/多播/类型不匹配/无handler/无send_type/移除后/清空后/零长/NULL |
|
||||
| send_type & handler | 3 | 设置/清除/添加/移除/清空 |
|
||||
| 发送自动广播 | 11 | 无匹配/单播/多 handler 单端口/多端口同类型/多端口多 handler/类型过滤/移除后/删除后/零长/NULL/多能力独立 |
|
||||
| 接收回调 | 1 | 用户实现覆盖弱符号 |
|
||||
| 能力元数据 | 2 | SEND 与 RECV 两组独立查询 |
|
||||
| 错误处理 | 2 | 无效端口/已删除端口 |
|
||||
|
||||
**总计:27 个测试用例**
|
||||
**总计:22 个测试用例**
|
||||
|
||||
Binary file not shown.
Binary file not shown.
+21
-64
@@ -1,6 +1,5 @@
|
||||
/**
|
||||
* @file datarouter.c
|
||||
* @brief 数据路由库 —— 实现
|
||||
*/
|
||||
|
||||
#include "datarouter.h"
|
||||
@@ -18,7 +17,6 @@
|
||||
|
||||
typedef struct {
|
||||
int send_type;
|
||||
int recv_type;
|
||||
datarouter_send_handler_t handlers[DATAROUTER_MAX_HANDLERS_PER_PORT];
|
||||
int count;
|
||||
uint8_t in_use;
|
||||
@@ -27,7 +25,7 @@ typedef struct {
|
||||
static port_entry_t ports[DATAROUTER_MAX_PORTS];
|
||||
static uint8_t initialized;
|
||||
|
||||
/* ---- 发送能力元数据 ---- */
|
||||
/* ---- 元数据 ---- */
|
||||
|
||||
static const char *send_names[] = {
|
||||
#define DATAROUTER_SEND(id, desc) #id,
|
||||
@@ -41,8 +39,6 @@ static const char *send_descs[] = {
|
||||
#undef DATAROUTER_SEND
|
||||
};
|
||||
|
||||
/* ---- 接收能力元数据 ---- */
|
||||
|
||||
static const char *recv_names[] = {
|
||||
#define DATAROUTER_RECV(id, desc) #id,
|
||||
DATAROUTER_RECV_CAPABILITIES
|
||||
@@ -55,29 +51,31 @@ static const char *recv_descs[] = {
|
||||
#undef DATAROUTER_RECV
|
||||
};
|
||||
|
||||
/* ---- 弱符号接收回调默认实现 ---- */
|
||||
/* ---- 弱符号接收回调 ---- */
|
||||
|
||||
#define DATAROUTER_RECV(id, desc) \
|
||||
DATAROUTER_WEAK void datarouter_on_recv_##id( \
|
||||
uint32_t port_id, const void *data, size_t len) \
|
||||
{ \
|
||||
(void)port_id; (void)data; (void)len; \
|
||||
}
|
||||
{ (void)port_id; (void)data; (void)len; }
|
||||
DATAROUTER_RECV_CAPABILITIES
|
||||
#undef DATAROUTER_RECV
|
||||
|
||||
/* ---- 发送触发函数实现 ---- */
|
||||
/* ---- 发送触发函数 ---- */
|
||||
|
||||
#define DATAROUTER_SEND(id, desc) \
|
||||
int datarouter_send_##id(uint32_t port_id, const void *data, size_t len) \
|
||||
int datarouter_send_##id(const void *data, size_t len) \
|
||||
{ \
|
||||
if (!initialized) return -1; \
|
||||
if (port_id >= DATAROUTER_MAX_PORTS || !ports[port_id].in_use) return -2; \
|
||||
if (ports[port_id].send_type != DATAROUTER_SEND_##id) return -3; \
|
||||
if (ports[port_id].count == 0) return -4; \
|
||||
for (int _i = 0; _i < ports[port_id].count; _i++) \
|
||||
ports[port_id].handlers[_i](port_id, data, len); \
|
||||
return 0; \
|
||||
int called = 0; \
|
||||
for (uint32_t _p = 0; _p < DATAROUTER_MAX_PORTS; _p++) { \
|
||||
if (!ports[_p].in_use) continue; \
|
||||
if (ports[_p].send_type != DATAROUTER_SEND_##id) continue; \
|
||||
for (int _h = 0; _h < ports[_p].count; _h++) { \
|
||||
ports[_p].handlers[_h](_p, data, len); \
|
||||
called = 1; \
|
||||
} \
|
||||
} \
|
||||
return called ? 0 : -2; \
|
||||
}
|
||||
DATAROUTER_SEND_CAPABILITIES
|
||||
#undef DATAROUTER_SEND
|
||||
@@ -104,7 +102,6 @@ datarouter_port_t datarouter_port_create(void)
|
||||
if (!ports[i].in_use) {
|
||||
ports[i].in_use = 1;
|
||||
ports[i].send_type = -1;
|
||||
ports[i].recv_type = -1;
|
||||
ports[i].count = 0;
|
||||
return (datarouter_port_t)i;
|
||||
}
|
||||
@@ -133,20 +130,6 @@ int datarouter_port_get_send_type(datarouter_port_t port)
|
||||
return ports[port].send_type;
|
||||
}
|
||||
|
||||
void datarouter_port_set_recv_type(datarouter_port_t port, int cap_id)
|
||||
{
|
||||
if (!initialized) return;
|
||||
if (port < 0 || port >= DATAROUTER_MAX_PORTS || !ports[port].in_use) return;
|
||||
ports[port].recv_type = cap_id;
|
||||
}
|
||||
|
||||
int datarouter_port_get_recv_type(datarouter_port_t port)
|
||||
{
|
||||
if (!initialized) return -1;
|
||||
if (port < 0 || port >= DATAROUTER_MAX_PORTS || !ports[port].in_use) return -1;
|
||||
return ports[port].recv_type;
|
||||
}
|
||||
|
||||
int datarouter_port_add_handler(datarouter_port_t port, datarouter_send_handler_t handler)
|
||||
{
|
||||
if (!initialized) return -1;
|
||||
@@ -187,36 +170,10 @@ int datarouter_port_handler_count(datarouter_port_t port)
|
||||
|
||||
/* ---- 元数据查询 ---- */
|
||||
|
||||
int datarouter_send_cap_count(void)
|
||||
{
|
||||
return DATAROUTER_SEND_CAP_COUNT;
|
||||
}
|
||||
int datarouter_send_cap_count(void) { return DATAROUTER_SEND_CAP_COUNT; }
|
||||
const char *datarouter_send_cap_name(int c) { return (c<0||c>=DATAROUTER_SEND_CAP_COUNT)?NULL:send_names[c]; }
|
||||
const char *datarouter_send_cap_desc(int c) { return (c<0||c>=DATAROUTER_SEND_CAP_COUNT)?NULL:send_descs[c]; }
|
||||
|
||||
const char *datarouter_send_cap_name(int cap_id)
|
||||
{
|
||||
if (cap_id < 0 || cap_id >= DATAROUTER_SEND_CAP_COUNT) return NULL;
|
||||
return send_names[cap_id];
|
||||
}
|
||||
|
||||
const char *datarouter_send_cap_desc(int cap_id)
|
||||
{
|
||||
if (cap_id < 0 || cap_id >= DATAROUTER_SEND_CAP_COUNT) return NULL;
|
||||
return send_descs[cap_id];
|
||||
}
|
||||
|
||||
int datarouter_recv_cap_count(void)
|
||||
{
|
||||
return DATAROUTER_RECV_CAP_COUNT;
|
||||
}
|
||||
|
||||
const char *datarouter_recv_cap_name(int cap_id)
|
||||
{
|
||||
if (cap_id < 0 || cap_id >= DATAROUTER_RECV_CAP_COUNT) return NULL;
|
||||
return recv_names[cap_id];
|
||||
}
|
||||
|
||||
const char *datarouter_recv_cap_desc(int cap_id)
|
||||
{
|
||||
if (cap_id < 0 || cap_id >= DATAROUTER_RECV_CAP_COUNT) return NULL;
|
||||
return recv_descs[cap_id];
|
||||
}
|
||||
int datarouter_recv_cap_count(void) { return DATAROUTER_RECV_CAP_COUNT; }
|
||||
const char *datarouter_recv_cap_name(int c) { return (c<0||c>=DATAROUTER_RECV_CAP_COUNT)?NULL:recv_names[c]; }
|
||||
const char *datarouter_recv_cap_desc(int c) { return (c<0||c>=DATAROUTER_RECV_CAP_COUNT)?NULL:recv_descs[c]; }
|
||||
|
||||
+12
-26
@@ -4,20 +4,16 @@
|
||||
*
|
||||
* ## 概念
|
||||
*
|
||||
* - **发送能力 (Send Capability)**:编译期声明的可发送报文类型
|
||||
* - **接收能力 (Recv Capability)**:编译期声明的可接收报文类型
|
||||
* - **端口 (Port)**:运行期连接点,独立设置 send_type + recv_type + 外设 handler 列表
|
||||
* - **发送能力**:编译期声明的可发送报文类型,生成 datarouter_send_<id>(data, len)
|
||||
* - **接收能力**:编译期声明的可接收报文类型,生成 datarouter_on_recv_<id>(port, data, len)
|
||||
* - **端口**:运行期创建的连接点,包含 send_type + handler 列表
|
||||
*
|
||||
* ## 使用流程
|
||||
* ## 路由
|
||||
*
|
||||
* 1. 创建 datarouter_config.h 声明发送和接收能力(见 datarouter_config_template.h)
|
||||
* 2. 编译时通过 -I 指向你的配置目录;若无,库使用内置默认配置
|
||||
* 3. datarouter_init() 初始化
|
||||
* 4. port_create() 创建端口
|
||||
* 5. port_set_send_type() 设置发送类型 / port_set_recv_type() 设置接收类型
|
||||
* 6. port_add_handler() 注册外设发送函数
|
||||
* 7. 调 datarouter_send_<id>() 触发发送(库调用所有 handler)
|
||||
* 8. 实现 datarouter_on_recv_<id>() 处理接收数据
|
||||
* 调用 datarouter_send_<id>(data, len) 时,库遍历所有端口,
|
||||
* 找到 send_type 匹配的端口,逐一调用其全部 handler。无需指定从哪个端口发送。
|
||||
*
|
||||
* 接收侧由用户自行调用 datarouter_on_recv_<id>(port, data, len) 处理外设收到的数据。
|
||||
*/
|
||||
|
||||
#ifndef DATAROUTER_H
|
||||
@@ -26,14 +22,6 @@
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
/*
|
||||
* 配置加载策略:
|
||||
* 1. 优先从 include path 搜索 <datarouter_config.h>(用户提供的版本)
|
||||
* 2. 找不到则回退到库自带的 "datarouter_config.h"(默认配置)
|
||||
*
|
||||
* 用户只需将自己的 datarouter_config.h 放到项目目录,
|
||||
* 编译时添加 -I /path/to/your/config 即可覆盖内置配置。
|
||||
*/
|
||||
#if defined(__has_include)
|
||||
# if __has_include(<datarouter_config.h>)
|
||||
# include <datarouter_config.h>
|
||||
@@ -66,7 +54,7 @@ enum datarouter_recv_cap {
|
||||
DATAROUTER_RECV_CAP_COUNT
|
||||
};
|
||||
|
||||
/* ========== 外设发送 handler 类型 ========== */
|
||||
/* ========== 外设发送 handler ========== */
|
||||
|
||||
typedef void (*datarouter_send_handler_t)(uint32_t port_id, const void *data, size_t len);
|
||||
|
||||
@@ -74,14 +62,14 @@ typedef void (*datarouter_send_handler_t)(uint32_t port_id, const void *data, si
|
||||
#define DATAROUTER_MAX_HANDLERS_PER_PORT 4
|
||||
#endif
|
||||
|
||||
/* ========== 发送触发函数(每个发送能力生成一个) ========== */
|
||||
/* ========== 发送触发函数 ========== */
|
||||
|
||||
#define DATAROUTER_SEND(id, desc) \
|
||||
int datarouter_send_##id(uint32_t port_id, const void *data, size_t len);
|
||||
int datarouter_send_##id(const void *data, size_t len);
|
||||
DATAROUTER_SEND_CAPABILITIES
|
||||
#undef DATAROUTER_SEND
|
||||
|
||||
/* ========== 接收回调声明(每个接收能力生成一个,用户实现) ========== */
|
||||
/* ========== 接收回调声明 ========== */
|
||||
|
||||
#define DATAROUTER_RECV(id, desc) \
|
||||
void datarouter_on_recv_##id(uint32_t port_id, const void *data, size_t len);
|
||||
@@ -101,8 +89,6 @@ void datarouter_port_delete(datarouter_port_t port);
|
||||
|
||||
void datarouter_port_set_send_type(datarouter_port_t port, int cap_id);
|
||||
int datarouter_port_get_send_type(datarouter_port_t port);
|
||||
void datarouter_port_set_recv_type(datarouter_port_t port, int cap_id);
|
||||
int datarouter_port_get_recv_type(datarouter_port_t port);
|
||||
|
||||
int datarouter_port_add_handler(datarouter_port_t port, datarouter_send_handler_t handler);
|
||||
int datarouter_port_remove_handler(datarouter_port_t port, datarouter_send_handler_t handler);
|
||||
|
||||
@@ -1,93 +1,73 @@
|
||||
/**
|
||||
* @file example.c
|
||||
* @brief 数据路由库使用示例
|
||||
*
|
||||
* 展示:
|
||||
* - 发送能力和接收能力分开声明(sensor 只发送,rtcm 只接收)
|
||||
* - 端口独立设置 send_type 和 recv_type
|
||||
* - 一个端口可同时拥有发送和接收能力
|
||||
* 调用 datarouter_send_sensor(data, len) 无需指定端口,
|
||||
* 库自动广播到所有 send_type=sensor 的端口。
|
||||
*/
|
||||
|
||||
#include "datarouter.h"
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
/* ---- 外设发送 handler ---- */
|
||||
|
||||
static void uart_send(uint32_t port_id, const void *data, size_t len)
|
||||
{
|
||||
printf("[UART] port %u: %.*s\n", port_id, (int)len, (const char *)data);
|
||||
printf("[UART port %u] %.*s\n", port_id, (int)len, (const char *)data);
|
||||
}
|
||||
|
||||
static void tcp_send(uint32_t port_id, const void *data, size_t len)
|
||||
{
|
||||
printf("[TCP] port %u: %.*s\n", port_id, (int)len, (const char *)data);
|
||||
printf("[TCP port %u] %.*s\n", port_id, (int)len, (const char *)data);
|
||||
}
|
||||
|
||||
/* ---- 接收回调实现 ---- */
|
||||
|
||||
void datarouter_on_recv_rtcm(uint32_t port_id, const void *data, size_t len)
|
||||
static void can_send(uint32_t port_id, const void *data, size_t len)
|
||||
{
|
||||
printf("[RX:rtcm] port %u: %.*s\n", port_id, (int)len, (const char *)data);
|
||||
printf("[CAN port %u] %.*s\n", port_id, (int)len, (const char *)data);
|
||||
}
|
||||
|
||||
void datarouter_on_recv_command(uint32_t port_id, const void *data, size_t len)
|
||||
{
|
||||
printf("[RX:cmd] port %u: %.*s\n", port_id, (int)len, (const char *)data);
|
||||
printf("[RX:cmd port %u] %.*s\n", port_id, (int)len, (const char *)data);
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
datarouter_init();
|
||||
|
||||
/* 查询能力 */
|
||||
printf("Send capabilities: %d\n", datarouter_send_cap_count());
|
||||
printf("Capabilities:\n");
|
||||
for (int i = 0; i < datarouter_send_cap_count(); i++)
|
||||
printf(" SEND [%d] %s - %s\n", i,
|
||||
datarouter_send_cap_name(i), datarouter_send_cap_desc(i));
|
||||
|
||||
printf("Recv capabilities: %d\n", datarouter_recv_cap_count());
|
||||
for (int i = 0; i < datarouter_recv_cap_count(); i++)
|
||||
printf(" RECV [%d] %s - %s\n", i,
|
||||
datarouter_recv_cap_name(i), datarouter_recv_cap_desc(i));
|
||||
|
||||
/*
|
||||
* 端口 A:只有发送能力 —— 上报传感器数据
|
||||
* 创建两个端口,都设 send_type=sensor,各绑不同外设。
|
||||
* 调用 datarouter_send_sensor() 时两个端口同时触发。
|
||||
*/
|
||||
datarouter_port_t tx_port = datarouter_port_create();
|
||||
datarouter_port_set_send_type(tx_port, DATAROUTER_SEND_sensor);
|
||||
datarouter_port_add_handler(tx_port, uart_send);
|
||||
datarouter_port_add_handler(tx_port, tcp_send);
|
||||
datarouter_port_t p1 = datarouter_port_create();
|
||||
datarouter_port_set_send_type(p1, DATAROUTER_SEND_sensor);
|
||||
datarouter_port_add_handler(p1, uart_send);
|
||||
datarouter_port_add_handler(p1, tcp_send);
|
||||
|
||||
printf("\n--- send sensor (UART + TCP) ---\n");
|
||||
datarouter_send_sensor(tx_port, "temperature:25.3", 16);
|
||||
/* 该端口没有 recv_type,不能接收任何报文 */
|
||||
datarouter_port_t p2 = datarouter_port_create();
|
||||
datarouter_port_set_send_type(p2, DATAROUTER_SEND_sensor);
|
||||
datarouter_port_add_handler(p2, can_send);
|
||||
|
||||
/*
|
||||
* 端口 B:只有接收能力 —— 接收 RTCM 修正
|
||||
*/
|
||||
datarouter_port_t rtcm_port = datarouter_port_create();
|
||||
datarouter_port_set_recv_type(rtcm_port, DATAROUTER_RECV_rtcm);
|
||||
/* 没有 send_type,也没有 handler —— 不能发送 */
|
||||
/* 不指定端口,自动广播到所有 sensor 端口 */
|
||||
printf("\n--- send_sensor (auto-route to ALL sensor ports) ---\n");
|
||||
datarouter_send_sensor("temperature:25.3", 16);
|
||||
|
||||
printf("\n--- simulate receive RTCM ---\n");
|
||||
datarouter_on_recv_rtcm(rtcm_port, "rtcm_data_v3.2", 14);
|
||||
/* 运行时移除一个 handler,下次发送不再触发它 */
|
||||
printf("\n--- remove TCP handler from p1, resend ---\n");
|
||||
datarouter_port_remove_handler(p1, tcp_send);
|
||||
datarouter_send_sensor("temperature:26.1", 16);
|
||||
|
||||
/*
|
||||
* 端口 C:同时有收发能力 —— 接收命令 + 上报状态
|
||||
*/
|
||||
datarouter_port_t bi_port = datarouter_port_create();
|
||||
datarouter_port_set_send_type(bi_port, DATAROUTER_SEND_status);
|
||||
datarouter_port_set_recv_type(bi_port, DATAROUTER_RECV_command);
|
||||
datarouter_port_add_handler(bi_port, uart_send);
|
||||
/* 接收侧:用户自行调用回调 */
|
||||
printf("\n--- recv command ---\n");
|
||||
datarouter_on_recv_command(0, "reboot", 6);
|
||||
|
||||
printf("\n--- bidirectional port ---\n");
|
||||
datarouter_send_status(bi_port, "status:OK", 9);
|
||||
datarouter_on_recv_command(bi_port, "reboot", 6);
|
||||
/* 删除一个端口,触发时不再走它 */
|
||||
printf("\n--- delete p2 (CAN), resend ---\n");
|
||||
datarouter_port_delete(p2);
|
||||
datarouter_send_sensor("temperature:27.0", 16);
|
||||
|
||||
/* 清理 */
|
||||
datarouter_port_delete(tx_port);
|
||||
datarouter_port_delete(rtcm_port);
|
||||
datarouter_port_delete(bi_port);
|
||||
datarouter_port_delete(p1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
+122
-168
@@ -1,15 +1,5 @@
|
||||
/**
|
||||
* @file test_datarouter.c
|
||||
* @brief 数据路由库单元测试
|
||||
*
|
||||
* 覆盖:
|
||||
* - 端口管理
|
||||
* - send_type / recv_type 独立设置
|
||||
* - 多 handler 增删
|
||||
* - 发送调用(一对多广播)
|
||||
* - 接收回调
|
||||
* - 发送/接收能力元数据各自独立
|
||||
* - 错误处理
|
||||
*/
|
||||
|
||||
#include "datarouter.h"
|
||||
@@ -17,7 +7,7 @@
|
||||
#include <string.h>
|
||||
|
||||
/* ================================================================
|
||||
* 测试框架
|
||||
* 框架
|
||||
* ================================================================ */
|
||||
|
||||
static int _total_run, _total_pass, _total_fail;
|
||||
@@ -66,19 +56,19 @@ cleanup: \
|
||||
* ================================================================ */
|
||||
|
||||
static int _h_cnt;
|
||||
static void _h(uint32_t p, const void *d, size_t l) { (void)p; (void)d; (void)l; _h_cnt++; }
|
||||
static void _h_a(uint32_t p, const void *d, size_t l) { (void)p; (void)d; (void)l; _h_cnt++; }
|
||||
static void _h_b(uint32_t p, const void *d, size_t l) { (void)p; (void)d; (void)l; _h_cnt++; }
|
||||
static void _h_c(uint32_t p, const void *d, size_t l) { (void)p; (void)d; (void)l; _h_cnt++; }
|
||||
static void _h_d(uint32_t p, const void *d, size_t l) { (void)p; (void)d; (void)l; _h_cnt++; }
|
||||
static void reset_h(void) { _h_cnt = 0; }
|
||||
static int _h_port[16];
|
||||
static int _h_pos;
|
||||
static void _h(uint32_t p, const void *d, size_t l) { (void)d; (void)l; _h_cnt++; if (_h_pos<16) _h_port[_h_pos++]=p; }
|
||||
static void _h2(uint32_t p, const void *d, size_t l) { (void)d; (void)l; _h_cnt++; if (_h_pos<16) _h_port[_h_pos++]=p; }
|
||||
static void _h3(uint32_t p, const void *d, size_t l) { (void)d; (void)l; _h_cnt++; if (_h_pos<16) _h_port[_h_pos++]=p; }
|
||||
static void reset_h(void) { _h_cnt = 0; _h_pos = 0; }
|
||||
|
||||
/* ================================================================
|
||||
* 1. 未初始化
|
||||
* ================================================================ */
|
||||
|
||||
TEST_START(error_uninit)
|
||||
CHECK(datarouter_send_sensor(0, "d", 1) == -1, "expected -1");
|
||||
CHECK(datarouter_send_sensor("d", 1) == -1, "expected -1");
|
||||
TEST_END()
|
||||
|
||||
/* ================================================================
|
||||
@@ -86,7 +76,7 @@ TEST_END()
|
||||
* ================================================================ */
|
||||
|
||||
TEST_START(port_create_basic)
|
||||
CHECK(FIXTURE_CREATE(&_fix) >= 0, "create failed");
|
||||
CHECK(FIXTURE_CREATE(&_fix) >= 0, NULL);
|
||||
TEST_END()
|
||||
|
||||
TEST_START(port_create_max)
|
||||
@@ -106,68 +96,28 @@ TEST_END()
|
||||
|
||||
TEST_START(port_default_state)
|
||||
datarouter_port_t p = FIXTURE_CREATE(&_fix);
|
||||
CHECK(datarouter_port_get_send_type(p) == -1, "send_type should be -1");
|
||||
CHECK(datarouter_port_get_recv_type(p) == -1, "recv_type should be -1");
|
||||
CHECK(datarouter_port_handler_count(p) == 0, "handler count 0");
|
||||
CHECK(datarouter_port_get_send_type(p) == -1, NULL);
|
||||
CHECK(datarouter_port_handler_count(p) == 0, NULL);
|
||||
TEST_END()
|
||||
|
||||
/* ================================================================
|
||||
* 3. send_type / recv_type 独立设置
|
||||
* 3. send_type 与 handler
|
||||
* ================================================================ */
|
||||
|
||||
TEST_START(send_type_set_get)
|
||||
datarouter_port_t p = FIXTURE_CREATE(&_fix);
|
||||
datarouter_port_set_send_type(p, DATAROUTER_SEND_sensor);
|
||||
CHECK(datarouter_port_get_send_type(p) == DATAROUTER_SEND_sensor, NULL);
|
||||
TEST_END()
|
||||
|
||||
TEST_START(recv_type_set_get)
|
||||
datarouter_port_t p = FIXTURE_CREATE(&_fix);
|
||||
datarouter_port_set_recv_type(p, DATAROUTER_RECV_rtcm);
|
||||
CHECK(datarouter_port_get_recv_type(p) == DATAROUTER_RECV_rtcm, NULL);
|
||||
TEST_END()
|
||||
|
||||
TEST_START(types_independent)
|
||||
/* 一个端口同时设置 send_type 和 recv_type,互不干扰 */
|
||||
datarouter_port_t p = FIXTURE_CREATE(&_fix);
|
||||
datarouter_port_set_send_type(p, DATAROUTER_SEND_sensor);
|
||||
datarouter_port_set_recv_type(p, DATAROUTER_RECV_command);
|
||||
CHECK(datarouter_port_get_send_type(p) == DATAROUTER_SEND_sensor, NULL);
|
||||
CHECK(datarouter_port_get_recv_type(p) == DATAROUTER_RECV_command, NULL);
|
||||
TEST_END()
|
||||
|
||||
TEST_START(send_type_clear)
|
||||
datarouter_port_t p = FIXTURE_CREATE(&_fix);
|
||||
datarouter_port_set_send_type(p, DATAROUTER_SEND_sensor);
|
||||
datarouter_port_set_send_type(p, -1);
|
||||
CHECK(datarouter_port_get_send_type(p) == -1, NULL);
|
||||
TEST_END()
|
||||
|
||||
TEST_START(recv_type_clear)
|
||||
datarouter_port_t p = FIXTURE_CREATE(&_fix);
|
||||
datarouter_port_set_recv_type(p, DATAROUTER_RECV_rtcm);
|
||||
datarouter_port_set_recv_type(p, -1);
|
||||
CHECK(datarouter_port_get_recv_type(p) == -1, NULL);
|
||||
TEST_END()
|
||||
|
||||
TEST_START(types_from_invalid)
|
||||
CHECK(datarouter_port_get_send_type(-1) == -1, NULL);
|
||||
CHECK(datarouter_port_get_recv_type(-1) == -1, NULL);
|
||||
CHECK(datarouter_port_get_send_type(999) == -1, NULL);
|
||||
CHECK(datarouter_port_get_recv_type(999) == -1, NULL);
|
||||
TEST_END()
|
||||
|
||||
/* ================================================================
|
||||
* 4. 多 handler
|
||||
* ================================================================ */
|
||||
|
||||
TEST_START(handler_add_remove)
|
||||
datarouter_port_t p = FIXTURE_CREATE(&_fix);
|
||||
CHECK(datarouter_port_add_handler(p, _h_a) == 0, NULL);
|
||||
CHECK(datarouter_port_add_handler(p, _h_b) == 0, NULL);
|
||||
CHECK(datarouter_port_handler_count(p) == 2, NULL);
|
||||
CHECK(datarouter_port_remove_handler(p, _h_a) == 0, NULL);
|
||||
CHECK(datarouter_port_add_handler(p, _h) == 0, NULL);
|
||||
CHECK(datarouter_port_handler_count(p) == 1, NULL);
|
||||
CHECK(datarouter_port_remove_handler(p, _h) == 0, NULL);
|
||||
CHECK(datarouter_port_handler_count(p) == 0, NULL);
|
||||
TEST_END()
|
||||
|
||||
TEST_START(handler_clear)
|
||||
@@ -178,67 +128,93 @@ TEST_START(handler_clear)
|
||||
TEST_END()
|
||||
|
||||
/* ================================================================
|
||||
* 5. 发送触发
|
||||
* 4. 发送 — 自动广播
|
||||
* ================================================================ */
|
||||
|
||||
TEST_START(send_one_handler)
|
||||
TEST_START(send_no_match_port)
|
||||
/* 没有端口配置该 send_type */
|
||||
CHECK(datarouter_send_sensor("d", 1) == -2, "expected -2");
|
||||
TEST_END()
|
||||
|
||||
TEST_START(send_one_port_one_handler)
|
||||
datarouter_port_t p = FIXTURE_CREATE(&_fix);
|
||||
datarouter_port_set_send_type(p, DATAROUTER_SEND_sensor);
|
||||
datarouter_port_add_handler(p, _h);
|
||||
reset_h();
|
||||
CHECK(datarouter_send_sensor(p, "d", 1) == 0, NULL);
|
||||
CHECK(_h_cnt == 1, "handler called %d times", _h_cnt);
|
||||
CHECK(datarouter_send_sensor("d", 1) == 0, NULL);
|
||||
CHECK(_h_cnt == 1, "cnt=%d", _h_cnt);
|
||||
CHECK(_h_port[0] == (int)p, "port=%d", _h_port[0]);
|
||||
TEST_END()
|
||||
|
||||
TEST_START(send_multi_handlers)
|
||||
datarouter_port_t p = FIXTURE_CREATE(&_fix);
|
||||
datarouter_port_set_send_type(p, DATAROUTER_SEND_sensor);
|
||||
datarouter_port_add_handler(p, _h_a);
|
||||
datarouter_port_add_handler(p, _h_b);
|
||||
datarouter_port_add_handler(p, _h_c);
|
||||
reset_h();
|
||||
CHECK(datarouter_send_sensor(p, "d", 1) == 0, NULL);
|
||||
CHECK(_h_cnt == 3, "handler called %d times", _h_cnt);
|
||||
TEST_END()
|
||||
|
||||
TEST_START(send_type_mismatch)
|
||||
TEST_START(send_one_port_multi_handler)
|
||||
datarouter_port_t p = FIXTURE_CREATE(&_fix);
|
||||
datarouter_port_set_send_type(p, DATAROUTER_SEND_sensor);
|
||||
datarouter_port_add_handler(p, _h);
|
||||
datarouter_port_add_handler(p, _h2);
|
||||
reset_h();
|
||||
CHECK(datarouter_send_status(p, "d", 1) == -3, "expected -3");
|
||||
CHECK(_h_cnt == 0, NULL);
|
||||
CHECK(datarouter_send_sensor("d", 1) == 0, NULL);
|
||||
CHECK(_h_cnt == 2, "cnt=%d", _h_cnt);
|
||||
TEST_END()
|
||||
|
||||
TEST_START(send_no_handler)
|
||||
datarouter_port_t p = FIXTURE_CREATE(&_fix);
|
||||
datarouter_port_set_send_type(p, DATAROUTER_SEND_sensor);
|
||||
CHECK(datarouter_send_sensor(p, "d", 1) == -4, "expected -4");
|
||||
TEST_START(send_multi_ports_same_type)
|
||||
/* 两个端口同类型,各一个 handler */
|
||||
datarouter_port_t p1 = FIXTURE_CREATE(&_fix);
|
||||
datarouter_port_t p2 = FIXTURE_CREATE(&_fix);
|
||||
datarouter_port_set_send_type(p1, DATAROUTER_SEND_sensor);
|
||||
datarouter_port_set_send_type(p2, DATAROUTER_SEND_sensor);
|
||||
datarouter_port_add_handler(p1, _h);
|
||||
datarouter_port_add_handler(p2, _h);
|
||||
reset_h();
|
||||
CHECK(datarouter_send_sensor("d", 1) == 0, NULL);
|
||||
CHECK(_h_cnt == 2, "cnt=%d", _h_cnt);
|
||||
/* p1 和 p2 各触发一次 */
|
||||
CHECK((_h_port[0]==p1 && _h_port[1]==p2) ||
|
||||
(_h_port[0]==p2 && _h_port[1]==p1), "ports %d,%d", _h_port[0], _h_port[1]);
|
||||
TEST_END()
|
||||
|
||||
TEST_START(send_no_send_type)
|
||||
/* 端口只有 recv_type,没有 send_type */
|
||||
datarouter_port_t p = FIXTURE_CREATE(&_fix);
|
||||
datarouter_port_set_recv_type(p, DATAROUTER_RECV_rtcm);
|
||||
CHECK(datarouter_send_sensor(p, "d", 1) == -3, "expected -3 (send_type unset)");
|
||||
TEST_START(send_multi_port_multi_handler)
|
||||
datarouter_port_t p1 = FIXTURE_CREATE(&_fix);
|
||||
datarouter_port_t p2 = FIXTURE_CREATE(&_fix);
|
||||
datarouter_port_set_send_type(p1, DATAROUTER_SEND_sensor);
|
||||
datarouter_port_set_send_type(p2, DATAROUTER_SEND_sensor);
|
||||
datarouter_port_add_handler(p1, _h);
|
||||
datarouter_port_add_handler(p1, _h2); /* p1 两个 */
|
||||
datarouter_port_add_handler(p2, _h3); /* p2 一个 */
|
||||
reset_h();
|
||||
CHECK(datarouter_send_sensor("d", 1) == 0, NULL);
|
||||
CHECK(_h_cnt == 3, "cnt=%d", _h_cnt);
|
||||
TEST_END()
|
||||
|
||||
TEST_START(send_remove_handler)
|
||||
datarouter_port_t p = FIXTURE_CREATE(&_fix);
|
||||
datarouter_port_set_send_type(p, DATAROUTER_SEND_sensor);
|
||||
datarouter_port_add_handler(p, _h_a);
|
||||
datarouter_port_add_handler(p, _h_b);
|
||||
reset_h(); datarouter_send_sensor(p, "d", 1); CHECK(_h_cnt == 2, NULL);
|
||||
datarouter_port_remove_handler(p, _h_a);
|
||||
reset_h(); datarouter_send_sensor(p, "d", 1); CHECK(_h_cnt == 1, NULL);
|
||||
TEST_START(send_type_filter)
|
||||
/* 两个端口不同类型,只触发匹配的 */
|
||||
datarouter_port_t p1 = FIXTURE_CREATE(&_fix);
|
||||
datarouter_port_t p2 = FIXTURE_CREATE(&_fix);
|
||||
datarouter_port_set_send_type(p1, DATAROUTER_SEND_sensor);
|
||||
datarouter_port_set_send_type(p2, DATAROUTER_SEND_status);
|
||||
datarouter_port_add_handler(p1, _h);
|
||||
datarouter_port_add_handler(p2, _h);
|
||||
reset_h();
|
||||
CHECK(datarouter_send_sensor("d", 1) == 0, NULL);
|
||||
CHECK(_h_cnt == 1, "cnt=%d", _h_cnt);
|
||||
CHECK(_h_port[0] == (int)p1, "only p1 should fire");
|
||||
TEST_END()
|
||||
|
||||
TEST_START(send_clear_handlers)
|
||||
TEST_START(send_after_remove_handler)
|
||||
datarouter_port_t p = FIXTURE_CREATE(&_fix);
|
||||
datarouter_port_set_send_type(p, DATAROUTER_SEND_sensor);
|
||||
datarouter_port_add_handler(p, _h);
|
||||
datarouter_port_clear_handlers(p);
|
||||
CHECK(datarouter_send_sensor(p, "d", 1) == -4, "expected -4");
|
||||
reset_h(); datarouter_send_sensor("d", 1); CHECK(_h_cnt == 1, NULL);
|
||||
datarouter_port_remove_handler(p, _h);
|
||||
CHECK(datarouter_send_sensor("d", 1) == -2, "expected -2 after remove");
|
||||
TEST_END()
|
||||
|
||||
TEST_START(send_after_delete_port)
|
||||
datarouter_port_t p = FIXTURE_CREATE(&_fix);
|
||||
datarouter_port_set_send_type(p, DATAROUTER_SEND_sensor);
|
||||
datarouter_port_add_handler(p, _h);
|
||||
datarouter_port_delete(p);
|
||||
CHECK(datarouter_send_sensor("d", 1) == -2, "expected -2");
|
||||
_fix.count--;
|
||||
TEST_END()
|
||||
|
||||
TEST_START(send_zero_length)
|
||||
@@ -246,7 +222,7 @@ TEST_START(send_zero_length)
|
||||
datarouter_port_set_send_type(p, DATAROUTER_SEND_sensor);
|
||||
datarouter_port_add_handler(p, _h);
|
||||
reset_h();
|
||||
CHECK(datarouter_send_sensor(p, "x", 0) == 0, NULL);
|
||||
CHECK(datarouter_send_sensor("x", 0) == 0, NULL);
|
||||
CHECK(_h_cnt == 1, NULL);
|
||||
TEST_END()
|
||||
|
||||
@@ -255,38 +231,47 @@ TEST_START(send_null_data)
|
||||
datarouter_port_set_send_type(p, DATAROUTER_SEND_sensor);
|
||||
datarouter_port_add_handler(p, _h);
|
||||
reset_h();
|
||||
CHECK(datarouter_send_sensor(p, NULL, 0) == 0, NULL);
|
||||
CHECK(datarouter_send_sensor(NULL, 0) == 0, NULL);
|
||||
CHECK(_h_cnt == 1, NULL);
|
||||
TEST_END()
|
||||
|
||||
/* ================================================================
|
||||
* 6. 接收回调
|
||||
* ================================================================ */
|
||||
|
||||
static int _rx_r, _rx_c;
|
||||
void datarouter_on_recv_rtcm(uint32_t p, const void *d, size_t l)
|
||||
{ (void)p; (void)d; (void)l; _rx_r++; }
|
||||
void datarouter_on_recv_command(uint32_t p, const void *d, size_t l)
|
||||
{ (void)p; (void)d; (void)l; _rx_c++; }
|
||||
|
||||
TEST_START(recv_callbacks)
|
||||
_rx_r = _rx_c = 0;
|
||||
datarouter_on_recv_rtcm(0, "d", 1);
|
||||
CHECK(_rx_r == 1 && _rx_c == 0, "rtcm=%d cmd=%d", _rx_r, _rx_c);
|
||||
datarouter_on_recv_command(1, "d", 1);
|
||||
CHECK(_rx_r == 1 && _rx_c == 1, "rtcm=%d cmd=%d", _rx_r, _rx_c);
|
||||
TEST_START(send_multi_cap)
|
||||
/* 发送 status 不影响 sensor 端口 */
|
||||
datarouter_port_t p1 = FIXTURE_CREATE(&_fix);
|
||||
datarouter_port_t p2 = FIXTURE_CREATE(&_fix);
|
||||
datarouter_port_set_send_type(p1, DATAROUTER_SEND_sensor);
|
||||
datarouter_port_set_send_type(p2, DATAROUTER_SEND_status);
|
||||
datarouter_port_add_handler(p1, _h);
|
||||
datarouter_port_add_handler(p2, _h);
|
||||
reset_h();
|
||||
CHECK(datarouter_send_sensor("d", 1) == 0, NULL);
|
||||
CHECK(_h_cnt == 1, "sensor: cnt=%d", _h_cnt);
|
||||
CHECK(datarouter_send_status("d", 1) == 0, NULL);
|
||||
CHECK(_h_cnt == 2, "status: cnt=%d", _h_cnt);
|
||||
TEST_END()
|
||||
|
||||
/* ================================================================
|
||||
* 7. 能力元数据(两组独立)
|
||||
* 5. 接收回调
|
||||
* ================================================================ */
|
||||
|
||||
static int _rx_r;
|
||||
void datarouter_on_recv_rtcm(uint32_t p, const void *d, size_t l)
|
||||
{ (void)p; (void)d; (void)l; _rx_r++; }
|
||||
|
||||
TEST_START(recv_callback)
|
||||
_rx_r = 0;
|
||||
datarouter_on_recv_rtcm(0, "d", 1);
|
||||
CHECK(_rx_r == 1, "cnt=%d", _rx_r);
|
||||
TEST_END()
|
||||
|
||||
/* ================================================================
|
||||
* 6. 能力元数据
|
||||
* ================================================================ */
|
||||
|
||||
TEST_START(send_cap_meta)
|
||||
CHECK(datarouter_send_cap_count() == 2, NULL);
|
||||
CHECK(strcmp(datarouter_send_cap_name(0), "sensor") == 0, NULL);
|
||||
CHECK(strcmp(datarouter_send_cap_desc(0), "Sensor data report") == 0, NULL);
|
||||
CHECK(strcmp(datarouter_send_cap_name(1), "status") == 0, NULL);
|
||||
CHECK(strcmp(datarouter_send_cap_desc(1), "Device status report") == 0, NULL);
|
||||
CHECK(datarouter_send_cap_name(-1) == NULL, NULL);
|
||||
CHECK(datarouter_send_cap_name(99) == NULL, NULL);
|
||||
TEST_END()
|
||||
@@ -295,35 +280,15 @@ TEST_START(recv_cap_meta)
|
||||
CHECK(datarouter_recv_cap_count() == 2, NULL);
|
||||
CHECK(strcmp(datarouter_recv_cap_name(0), "rtcm") == 0, NULL);
|
||||
CHECK(strcmp(datarouter_recv_cap_desc(0), "RTCM correction data") == 0, NULL);
|
||||
CHECK(strcmp(datarouter_recv_cap_name(1), "command") == 0, NULL);
|
||||
CHECK(strcmp(datarouter_recv_cap_desc(1), "Remote control command") == 0, NULL);
|
||||
CHECK(datarouter_recv_cap_name(-1) == NULL, NULL);
|
||||
CHECK(datarouter_recv_cap_desc(99) == NULL, NULL);
|
||||
TEST_END()
|
||||
|
||||
/* ================================================================
|
||||
* 8. 错误
|
||||
* ================================================================ */
|
||||
|
||||
TEST_START(error_invalid_port)
|
||||
CHECK(datarouter_send_sensor(999, "d", 1) == -2, NULL);
|
||||
CHECK(datarouter_send_sensor(-1, "d", 1) == -2, NULL);
|
||||
TEST_END()
|
||||
|
||||
TEST_START(error_deleted_port)
|
||||
datarouter_port_t p = FIXTURE_CREATE(&_fix);
|
||||
datarouter_port_set_send_type(p, DATAROUTER_SEND_sensor);
|
||||
datarouter_port_add_handler(p, _h);
|
||||
datarouter_port_delete(p);
|
||||
CHECK(datarouter_send_sensor(p, "d", 1) == -2, NULL);
|
||||
_fix.count--;
|
||||
TEST_END()
|
||||
|
||||
/* ================================================================
|
||||
* 主函数
|
||||
* ================================================================ */
|
||||
|
||||
#define RUN(name) do { reset_h(); test_##name(); } while (0)
|
||||
#define RUN(name) do { reset_h(); _rx_r = 0; test_##name(); } while (0)
|
||||
|
||||
int main(void)
|
||||
{
|
||||
@@ -342,34 +307,28 @@ int main(void)
|
||||
printf("\n");
|
||||
|
||||
datarouter_reset(); datarouter_init();
|
||||
printf("[send_type / recv_type]\n");
|
||||
printf("[send_type & handler]\n");
|
||||
RUN(send_type_set_get);
|
||||
RUN(recv_type_set_get);
|
||||
RUN(types_independent);
|
||||
RUN(send_type_clear);
|
||||
RUN(recv_type_clear);
|
||||
RUN(types_from_invalid);
|
||||
printf("\n");
|
||||
|
||||
printf("[handler add/remove]\n");
|
||||
RUN(handler_add_remove);
|
||||
RUN(handler_clear);
|
||||
printf("\n");
|
||||
|
||||
printf("[send trigger]\n");
|
||||
RUN(send_one_handler);
|
||||
RUN(send_multi_handlers);
|
||||
RUN(send_type_mismatch);
|
||||
RUN(send_no_handler);
|
||||
RUN(send_no_send_type);
|
||||
RUN(send_remove_handler);
|
||||
RUN(send_clear_handlers);
|
||||
printf("[send — auto broadcast]\n");
|
||||
RUN(send_no_match_port);
|
||||
RUN(send_one_port_one_handler);
|
||||
RUN(send_one_port_multi_handler);
|
||||
RUN(send_multi_ports_same_type);
|
||||
RUN(send_multi_port_multi_handler);
|
||||
RUN(send_type_filter);
|
||||
RUN(send_after_remove_handler);
|
||||
RUN(send_after_delete_port);
|
||||
RUN(send_zero_length);
|
||||
RUN(send_null_data);
|
||||
RUN(send_multi_cap);
|
||||
printf("\n");
|
||||
|
||||
printf("[receive callback]\n");
|
||||
RUN(recv_callbacks);
|
||||
RUN(recv_callback);
|
||||
printf("\n");
|
||||
|
||||
printf("[capability metadata]\n");
|
||||
@@ -377,11 +336,6 @@ int main(void)
|
||||
RUN(recv_cap_meta);
|
||||
printf("\n");
|
||||
|
||||
printf("[error handling]\n");
|
||||
RUN(error_invalid_port);
|
||||
RUN(error_deleted_port);
|
||||
printf("\n");
|
||||
|
||||
printf("==============================\n");
|
||||
printf(" total: %d | pass: %d | fail: %d\n\n",
|
||||
_total_run, _total_pass, _total_fail);
|
||||
|
||||
Reference in New Issue
Block a user