From 0a882bde6ad75c143f96a89fa88c22932c244e5e Mon Sep 17 00:00:00 2001 From: Geoff Phillips Date: Mon, 25 Sep 2023 13:50:59 +0200 Subject: [PATCH] Release v1.0.8 --- .github/template/fwe-build/action.yml | 2 +- .github/workflows/ci.yml | 14 +- .pre-commit-config.yaml | 46 +- CHANGELOG.md | 26 + CMakeLists.txt | 428 ++++++++++++- README.md | 4 +- THIRD-PARTY-LICENSES | 4 +- cmake/AwsIotFweConfig.cmake.in | 18 + cmake/compiler_gcc.cmake | 5 - cmake/doxygen.cmake | 2 - cmake/protobufs.cmake | 93 --- cmake/snappy.cmake | 54 -- .../README.md => docs/custom-data-source.md | 0 .../edge-agent-dev-guide-nxp-s32g.md | 77 ++- .../edge-agent-dev-guide-renesas-rcar-s4.md | 71 ++- docs/dev-guide/edge-agent-dev-guide.md | 559 +++++++++-------- docs/dev-guide/images/software_libraries.png | Bin 73506 -> 0 bytes docs/iwave-g26-tutorial/iwave-g26-tutorial.md | 136 +++-- .../iwave-g26-tutorial/iwave-gps-setup.md | 6 +- docs/metrics.md | 11 +- docs/rpi-tutorial/raspberry-pi-tutorial.md | 134 +++-- .../aaosvhal/src => }/AaosVhalSource.cpp | 12 +- .../aaosvhal/include => }/AaosVhalSource.h | 13 +- .../aws/bootstrap/src => }/AwsBootstrap.cpp | 25 +- .../aws/bootstrap/include => }/AwsBootstrap.h | 5 +- .../aws/iotcpp/src => }/AwsGGChannel.cpp | 45 +- .../aws/iotcpp/include => }/AwsGGChannel.h | 51 +- .../src => }/AwsGGConnectivityModule.cpp | 23 +- .../include => }/AwsGGConnectivityModule.h | 28 +- .../aws/iotcpp/src => }/AwsIotChannel.cpp | 60 +- .../aws/iotcpp/include => }/AwsIotChannel.h | 35 +- .../src => }/AwsIotConnectivityModule.cpp | 159 +++-- .../include => }/AwsIotConnectivityModule.h | 28 +- .../src => }/AwsSDKMemoryManager.cpp | 10 +- .../include => }/AwsSDKMemoryManager.h | 6 +- .../CANDataConsumer.cpp | 14 +- .../include => }/CANDataConsumer.h | 10 +- .../vehicledatasource => }/CANDataSource.cpp | 14 +- .../include => }/CANDataSource.h | 16 +- .../types/include => }/CANDataTypes.h | 5 - .../datadecoding/src => }/CANDecoder.cpp | 8 +- .../datadecoding/include => }/CANDecoder.h | 8 +- .../include => }/CANInterfaceIDTranslator.h | 4 - src/CMakeLists.txt | 39 -- .../src => }/CPUUsageInfo.cpp | 15 +- .../include => }/CPUUsageInfo.h | 14 +- .../src => }/CacheAndPersist.cpp | 11 +- .../include => }/CacheAndPersist.h | 15 +- .../src => }/CheckinAndPersistency.cpp | 10 +- .../linux/timemanagement/include => }/Clock.h | 7 - .../timemanagement/src => }/ClockHandler.cpp | 12 +- .../include => }/ClockHandler.h | 8 - .../CollectionInspectionAPITypes.h | 70 ++- .../src => }/CollectionInspectionEngine.cpp | 12 +- .../include => }/CollectionInspectionEngine.h | 37 +- .../CollectionInspectionWorkerThread.cpp | 13 +- .../CollectionInspectionWorkerThread.h | 40 +- .../src => }/CollectionSchemeIngestion.cpp | 95 ++- .../include => }/CollectionSchemeIngestion.h | 29 +- .../CollectionSchemeIngestionList.cpp | 10 +- .../CollectionSchemeIngestionList.h | 11 +- .../CollectionSchemeManagementListener.h | 4 +- .../src => }/CollectionSchemeManager.cpp | 11 +- .../include => }/CollectionSchemeManager.h | 32 +- .../logmanagement/src => }/ConsoleLogger.cpp | 24 +- .../include => }/ConsoleLogger.h | 18 +- .../generic/src => }/CustomDataSource.cpp | 11 +- .../generic/include => }/CustomDataSource.h | 17 +- .../include => }/DataReduction.h | 3 - .../datasender/src => }/DataSenderManager.cpp | 53 +- .../include => }/DataSenderManager.h | 38 +- src/DataSenderManagerWorkerThread.cpp | 239 ++++++++ .../DataSenderManagerWorkerThread.h | 43 +- .../src => }/DataSenderProtoWriter.cpp | 8 +- .../include => }/DataSenderProtoWriter.h | 12 +- .../src => }/DecoderDictionaryExtractor.cpp | 13 +- .../src => }/DecoderManifestIngestion.cpp | 15 +- .../include => }/DecoderManifestIngestion.h | 16 +- .../utility/include => }/EnumUtility.h | 11 +- .../types/include => }/EventTypes.h | 4 +- .../ExternalCANDataSource.cpp | 5 - .../include => }/ExternalCANDataSource.h | 10 +- .../src => }/ExternalGpsSource.cpp | 17 +- .../include => }/ExternalGpsSource.h | 13 +- .../types/src => }/Geohash.cpp | 5 +- .../types/include => }/Geohash.h | 4 +- .../src/location => }/GeohashFunctionNode.cpp | 6 +- .../include => }/GeohashFunctionNode.h | 10 +- .../types/include => }/GeohashInfo.h | 7 +- .../IActiveCollectionSchemesListener.h | 5 +- .../include => }/IActiveConditionProcessor.h | 6 +- .../IActiveDecoderDictionaryListener.h | 7 +- .../include => }/ICollectionScheme.h | 9 +- .../include => }/ICollectionSchemeList.h | 4 - .../include => }/ICollectionSchemeManager.h | 6 - .../api/include => }/IConnectionTypes.h | 6 - .../api/include => }/IConnectivityChannel.h | 8 +- .../api/include => }/IConnectivityModule.h | 5 - .../IDataReadyToPublishListener.h | 4 +- .../include => }/IDecoderDictionary.h | 4 - .../include => }/IDecoderManifest.h | 4 +- .../logmanagement/include => }/ILogger.h | 8 +- .../api/include => }/IReceiver.h | 7 +- .../datatypes => }/ISOTPOverCANOptions.h | 6 +- .../src => }/ISOTPOverCANReceiver.cpp | 22 +- .../businterfaces => }/ISOTPOverCANReceiver.h | 16 +- .../src => }/ISOTPOverCANSender.cpp | 22 +- .../businterfaces => }/ISOTPOverCANSender.h | 16 +- .../src => }/ISOTPOverCANSenderReceiver.cpp | 19 +- .../ISOTPOverCANSenderReceiver.h | 17 +- .../api/include => }/ISender.h | 13 +- .../iwavegps/src => }/IWaveGpsSource.cpp | 11 +- .../iwavegps/include => }/IWaveGpsSource.h | 12 +- .../include => }/InspectionEventListener.h | 4 +- .../src => }/InspectionMatrixExtractor.cpp | 12 +- .../src => }/IoTFleetWiseConfig.cpp | 4 - .../include => }/IoTFleetWiseConfig.h | 4 - .../src => }/IoTFleetWiseEngine.cpp | 65 +- .../include => }/IoTFleetWiseEngine.h | 54 +- .../src => }/IoTFleetWiseVersion.cpp.in | 0 .../include => }/IoTFleetWiseVersion.h | 0 .../include => }/Listener.h | 9 +- .../logmanagement/include => }/LogLevel.h | 19 +- .../logmanagement/src => }/LoggingModule.cpp | 43 +- .../include => }/LoggingModule.h | 107 ++-- .../src => }/MemoryUsageInfo.cpp | 12 +- .../include => }/MemoryUsageInfo.h | 10 - .../types/include => }/MessageTypes.h | 4 +- src/MqttClientWrapper.h | 57 ++ src/MqttConnectionWrapper.h | 193 ++++++ .../datadecoding/src => }/OBDDataDecoder.cpp | 9 +- .../include => }/OBDDataDecoder.h | 13 +- .../types/include => }/OBDDataTypes.h | 10 +- .../src/diag => }/OBDOverCANECU.cpp | 13 +- .../include => }/OBDOverCANECU.h | 22 +- .../src/diag => }/OBDOverCANModule.cpp | 36 +- .../include => }/OBDOverCANModule.h | 27 +- .../aws/iotcpp/src => }/PayloadManager.cpp | 20 +- .../aws/iotcpp/include => }/PayloadManager.h | 51 +- .../aws/iotcpp/src => }/RemoteProfiler.cpp | 17 +- .../aws/iotcpp/include => }/RemoteProfiler.h | 14 +- .../aws/iotcpp/src => }/RetryThread.cpp | 10 +- .../aws/iotcpp/include => }/RetryThread.h | 8 +- .../datamanager/src => }/Schema.cpp | 9 +- .../datamanager/include => }/Schema.h | 14 +- .../datamanager/include => }/SchemaListener.h | 4 +- .../threadingmanagement/include => }/Signal.h | 9 +- .../types/include => }/SignalTypes.h | 3 - .../threadingmanagement/src => }/Thread.cpp | 12 +- .../threadingmanagement/include => }/Thread.h | 16 +- .../timemanagement/include => }/TimeTypes.h | 8 - .../linux/timemanagement/include => }/Timer.h | 9 +- .../logmanagement/src => }/TraceModule.cpp | 8 - .../logmanagement/include => }/TraceModule.h | 11 +- .../datatypes => }/VehicleDataSourceTypes.h | 3 - .../src => }/android_shared_library.cpp | 15 +- src/datamanagement/CMakeLists.txt | 9 - src/datamanagement/custom/CMakeLists.txt | 132 ----- .../custom/example/iwavegps/test/.clang-tidy | 2 - .../custom/generic/test/.clang-tidy | 2 - .../custom/generic/test/valgrind.supp | 16 - .../datacollection/CMakeLists.txt | 85 --- .../datacollection/test/.clang-tidy | 2 - .../datacollection/test/valgrind.supp | 41 -- .../datadecoding/CMakeLists.txt | 93 --- .../datadecoding/test/.clang-tidy | 2 - .../datadecoding/test/valgrind.supp | 41 -- .../datainspection/CMakeLists.txt | 107 ---- .../datainspection/test/.clang-tidy | 2 - .../di-collection-policy-example-reduced.json | 86 --- .../test/di-collection-policy-example.json | 263 -------- .../di-collection-scheme-example-reduced.json | 86 --- .../test/di-collection-scheme-example.json | 263 -------- .../datainspection/test/valgrind.supp | 41 -- src/datamanagement/datamanager/CMakeLists.txt | 106 ---- .../datamanager/test/.clang-tidy | 2 - .../datamanager/test/valgrind.supp | 41 -- src/datamanagement/datasender/CMakeLists.txt | 96 --- .../src/DataSenderManagerWorkerThread.cpp | 249 -------- .../datasender/test/.clang-tidy | 2 - .../test/dm-collection-scheme-example.json | 130 ---- .../datasender/test/valgrind.supp | 32 - src/datamanagement/types/CMakeLists.txt | 74 --- src/datamanagement/types/test/.clang-tidy | 2 - src/datamanagement/types/test/valgrind.supp | 8 - src/executionmanagement/CMakeLists.txt | 129 ---- src/executionmanagement/test/.clang-tidy | 2 - src/executionmanagement/test/valgrind.supp | 42 -- src/{executionmanagement/src => }/main.cpp | 19 +- src/offboardconnectivity/CMakeLists.txt | 2 - src/offboardconnectivity/api/CMakeLists.txt | 13 - .../implementation/aws/CMakeLists.txt | 24 - .../aws/bootstrap/CMakeLists.txt | 33 -- .../implementation/aws/iotcpp/CMakeLists.txt | 135 ----- .../aws/iotcpp/test/include/AwsIotSdkMock.h | 132 ----- .../aws-iot-cpp-sdk-mock/aws/crt/Api.h | 137 ----- .../aws-iot-cpp-sdk-mock/aws/crt/Types.h | 70 --- .../aws-iot-cpp-sdk-mock/aws/crt/UUID.h | 26 - .../aws-iot-cpp-sdk-mock/aws/iot/MqttClient.h | 119 ---- .../aws/iotcpp/test/src/.clang-tidy | 2 - .../aws/iotcpp/test/src/AwsIotSdkMock.cpp | 108 ---- .../aws/iotcpp/test/src/MqttClient.cpp | 59 -- .../iotcpp/test/src/RemoteProfilerTest.cpp | 89 --- .../aws/iotcpp/test/valgrind.supp | 17 - src/platform/CMakeLists.txt | 37 -- src/platform/linux/CMakeLists.txt | 156 ----- .../linux/logmanagement/test/.clang-tidy | 2 - .../persistencymanagement/test/.clang-tidy | 2 - .../linux/resourcemanagement/test/.clang-tidy | 2 - src/platform/linux/test/valgrind.supp | 8 - .../threadingmanagement/test/.clang-tidy | 2 - .../linux/timemanagement/test/.clang-tidy | 2 - src/platform/utility/CMakeLists.txt | 25 - src/testingsupport/CMakeLists.txt | 76 --- src/testingsupport/src/main.cpp | 20 - src/testingsupport/test/.clang-tidy | 2 - src/testingsupport/test/valgrind.supp | 8 - src/vehiclenetwork/CMakeLists.txt | 95 --- src/vehiclenetwork/test/.clang-tidy | 2 - src/vehiclenetwork/test/valgrind.supp | 17 - .../test => test/unit}/AaosVhalSourceTest.cpp | 22 +- .../unit}/AwsIotConnectivityModuleTest.cpp | 421 +++++++------ .../test => test/unit}/CANDataSourceTest.cpp | 28 +- .../test => test/unit}/CANDecoderTest.cpp | 16 +- .../test => test/unit}/CPUUsageInfoTest.cpp | 18 +- .../unit}/CacheAndPersistTest.cpp | 18 +- .../unit}/CheckinAndPersistencyTest.cpp | 19 +- .../unit}/ClockHandlerBenchmarkTest.cpp | 12 +- .../test => test/unit}/ClockHandlerTest.cpp | 12 +- .../unit}/CollectionInspectionEngineTest.cpp | 25 +- .../CollectionInspectionWorkerThreadTest.cpp | 28 +- .../unit}/CollectionSchemeManagerGtest.cpp | 18 +- .../unit}/CollectionSchemeManagerTest.cpp | 15 +- .../unit}/CustomDataSourceTest.cpp | 20 +- test/unit/DataSenderManagerTest.cpp | 561 ++++++++++++++++++ .../DataSenderManagerWorkerThreadTest.cpp | 150 +++++ .../unit}/DataSenderProtoWriterTest.cpp | 34 +- .../unit}/DecoderDictionaryExtractorTest.cpp | 16 +- .../unit}/ExternalCANDataSourceTest.cpp | 22 +- .../unit}/ExternalGpsSourceTest.cpp | 20 +- .../test => test/unit}/FakeSystemTimeTest.cpp | 15 +- .../unit}/GeohashFunctionNodeTest.cpp | 11 +- .../types/test => test/unit}/GeohashTest.cpp | 10 +- .../unit}/ISOTPOverCANProtocolTest.cpp | 27 +- .../test => test/unit}/IWaveGpsSourceTest.cpp | 22 +- .../unit}/InspectionMatrixExtractorTest.cpp | 19 +- .../unit}/IoTFleetWiseConfigTest.cpp | 11 +- .../unit}/IoTFleetWiseEngineTest.cpp | 32 +- test/unit/LoggingModuleTest.cpp | 23 + .../unit}/MemoryUsageInfoTest.cpp | 8 +- .../test => test/unit}/OBDDataDecoderTest.cpp | 25 +- .../unit}/OBDOverCANModuleTest.cpp | 116 ++-- .../src => test/unit}/PayloadManagerTest.cpp | 27 +- test/unit/RemoteProfilerTest.cpp | 64 ++ .../test => test/unit}/SchemaTest.cpp | 306 +++++----- .../test => test/unit}/ThreadTest.cpp | 13 +- .../test => test/unit}/TimerTest.cpp | 10 +- .../test => test/unit}/TraceModuleTest.cpp | 10 +- .../test => test/unit}/WaitUntilTest.cpp | 14 +- .../support}/CollectionSchemeManagerMock.h | 13 +- .../support}/CollectionSchemeManagerTest.h | 46 +- test/unit/support/ConnectivityModuleMock.h | 34 ++ test/unit/support/DataSenderManagerMock.h | 62 ++ .../include => test/unit/support}/Faketime.h | 5 +- test/unit/support/MqttClientWrapperMock.h | 36 ++ test/unit/support/MqttConnectionWrapperMock.h | 69 +++ .../unit/support}/OBDDataTypesUnitTestOnly.h | 6 - test/unit/support/PayloadManagerMock.h | 45 ++ test/unit/support/SenderMock.h | 66 +++ .../include => test/unit/support}/Testing.h | 54 +- .../include => test/unit/support}/WaitUntil.h | 3 - test/unit/support/main.cpp | 21 + .../unit/support/static-config-corrupt.json | 0 .../support/static-config-inline-creds.json | 0 .../unit/support/static-config-ok.json | 0 tools/android-app/README.md | 15 +- tools/cansim/canigen.py | 10 +- tools/cfn-templates/fwdemo.yml | 4 +- tools/cloud/.gitignore | 4 +- tools/cloud/clean-up.sh | 21 +- tools/cloud/demo.sh | 169 ++++-- tools/cloud/firehose-to-html.py | 74 +++ tools/cloud/install-deps.sh | 12 +- tools/cloud/s3-to-html.py | 79 --- tools/code_check/compile_db_remove_test.py | 9 +- tools/container/Dockerfile | 12 +- tools/greengrassV2/README.md | 58 +- tools/install-deps-cross-android.sh | 82 +-- tools/install-deps-cross-arm64.sh | 122 +++- tools/install-deps-cross-armhf.sh | 122 +++- tools/install-deps-native.sh | 89 ++- tools/install-deps-versions.sh | 6 +- tools/install-fwe.sh | 6 +- .../setup-socketcan/setup-socketcan.bb | 4 +- 294 files changed, 5303 insertions(+), 6493 deletions(-) create mode 100644 cmake/AwsIotFweConfig.cmake.in delete mode 100644 cmake/protobufs.cmake delete mode 100644 cmake/snappy.cmake rename src/datamanagement/custom/README.md => docs/custom-data-source.md (100%) delete mode 100644 docs/dev-guide/images/software_libraries.png rename src/datamanagement/custom/example/iwavegps/README.md => docs/iwave-g26-tutorial/iwave-gps-setup.md (88%) rename src/{datamanagement/custom/example/aaosvhal/src => }/AaosVhalSource.cpp (86%) rename src/{datamanagement/custom/example/aaosvhal/include => }/AaosVhalSource.h (89%) rename src/{offboardconnectivity/implementation/aws/bootstrap/src => }/AwsBootstrap.cpp (92%) rename src/{offboardconnectivity/implementation/aws/bootstrap/include => }/AwsBootstrap.h (93%) rename src/{offboardconnectivity/implementation/aws/iotcpp/src => }/AwsGGChannel.cpp (92%) rename src/{offboardconnectivity/implementation/aws/iotcpp/include => }/AwsGGChannel.h (80%) rename src/{offboardconnectivity/implementation/aws/iotcpp/src => }/AwsGGConnectivityModule.cpp (82%) rename src/{offboardconnectivity/implementation/aws/iotcpp/include => }/AwsGGConnectivityModule.h (80%) rename src/{offboardconnectivity/implementation/aws/iotcpp/src => }/AwsIotChannel.cpp (84%) rename src/{offboardconnectivity/implementation/aws/iotcpp/include => }/AwsIotChannel.h (81%) rename src/{offboardconnectivity/implementation/aws/iotcpp/src => }/AwsIotConnectivityModule.cpp (66%) rename src/{offboardconnectivity/implementation/aws/iotcpp/include => }/AwsIotConnectivityModule.h (87%) rename src/{offboardconnectivity/implementation/aws/bootstrap/src => }/AwsSDKMemoryManager.cpp (94%) rename src/{offboardconnectivity/implementation/aws/bootstrap/include => }/AwsSDKMemoryManager.h (94%) rename src/{datamanagement/datainspection/src/vehicledatasource => }/CANDataConsumer.cpp (97%) rename src/{datamanagement/datainspection/include => }/CANDataConsumer.h (92%) rename src/{datamanagement/datainspection/src/vehicledatasource => }/CANDataSource.cpp (98%) rename src/{datamanagement/datainspection/include => }/CANDataSource.h (93%) rename src/{datamanagement/types/include => }/CANDataTypes.h (93%) rename src/{datamanagement/datadecoding/src => }/CANDecoder.cpp (99%) rename src/{datamanagement/datadecoding/include => }/CANDecoder.h (93%) rename src/{datamanagement/datacollection/include => }/CANInterfaceIDTranslator.h (95%) delete mode 100644 src/CMakeLists.txt rename src/{platform/linux/resourcemanagement/src => }/CPUUsageInfo.cpp (97%) rename src/{platform/linux/resourcemanagement/include => }/CPUUsageInfo.h (97%) rename src/{platform/linux/persistencymanagement/src => }/CacheAndPersist.cpp (99%) rename src/{platform/linux/persistencymanagement/include => }/CacheAndPersist.h (98%) rename src/{datamanagement/datamanager/src => }/CheckinAndPersistency.cpp (97%) rename src/{platform/linux/timemanagement/include => }/Clock.h (96%) rename src/{platform/linux/timemanagement/src => }/ClockHandler.cpp (97%) rename src/{platform/linux/timemanagement/include => }/ClockHandler.h (90%) rename src/{datamanagement/types/include => }/CollectionInspectionAPITypes.h (89%) rename src/{datamanagement/datainspection/src => }/CollectionInspectionEngine.cpp (99%) rename src/{datamanagement/datainspection/include => }/CollectionInspectionEngine.h (97%) rename src/{datamanagement/datainspection/src => }/CollectionInspectionWorkerThread.cpp (98%) rename src/{datamanagement/datainspection/include => }/CollectionInspectionWorkerThread.h (76%) rename src/{datamanagement/datacollection/src => }/CollectionSchemeIngestion.cpp (81%) rename src/{datamanagement/datacollection/include => }/CollectionSchemeIngestion.h (78%) rename src/{datamanagement/datacollection/src => }/CollectionSchemeIngestionList.cpp (95%) rename src/{datamanagement/datacollection/include => }/CollectionSchemeIngestionList.h (88%) rename src/{datamanagement/datamanager/include => }/CollectionSchemeManagementListener.h (95%) rename src/{datamanagement/datamanager/src => }/CollectionSchemeManager.cpp (99%) rename src/{datamanagement/datamanager/include => }/CollectionSchemeManager.h (94%) rename src/{platform/linux/logmanagement/src => }/ConsoleLogger.cpp (95%) rename src/{platform/linux/logmanagement/include => }/ConsoleLogger.h (85%) rename src/{datamanagement/custom/generic/src => }/CustomDataSource.cpp (97%) rename src/{datamanagement/custom/generic/include => }/CustomDataSource.h (93%) rename src/{datamanagement/datainspection/include => }/DataReduction.h (97%) rename src/{datamanagement/datasender/src => }/DataSenderManager.cpp (81%) rename src/{datamanagement/datasender/include => }/DataSenderManager.h (77%) create mode 100644 src/DataSenderManagerWorkerThread.cpp rename src/{datamanagement/datasender/include => }/DataSenderManagerWorkerThread.h (60%) rename src/{datamanagement/datasender/src => }/DataSenderProtoWriter.cpp (97%) rename src/{datamanagement/datasender/include => }/DataSenderProtoWriter.h (93%) rename src/{datamanagement/datamanager/src => }/DecoderDictionaryExtractor.cpp (98%) rename src/{datamanagement/datadecoding/src => }/DecoderManifestIngestion.cpp (96%) rename src/{datamanagement/datadecoding/include => }/DecoderManifestIngestion.h (94%) rename src/{platform/utility/include => }/EnumUtility.h (79%) rename src/{datamanagement/types/include => }/EventTypes.h (85%) rename src/{datamanagement/datainspection/src/vehicledatasource => }/ExternalCANDataSource.cpp (94%) rename src/{datamanagement/datainspection/include => }/ExternalCANDataSource.h (92%) rename src/{datamanagement/custom/example/externalgps/src => }/ExternalGpsSource.cpp (86%) rename src/{datamanagement/custom/example/externalgps/include => }/ExternalGpsSource.h (89%) rename src/{datamanagement/types/src => }/Geohash.cpp (98%) rename src/{datamanagement/types/include => }/Geohash.h (97%) rename src/{datamanagement/datainspection/src/location => }/GeohashFunctionNode.cpp (98%) rename src/{datamanagement/datainspection/include => }/GeohashFunctionNode.h (93%) rename src/{datamanagement/types/include => }/GeohashInfo.h (87%) rename src/{datamanagement/datamanager/include => }/IActiveCollectionSchemesListener.h (94%) rename src/{datamanagement/datainspection/include => }/IActiveConditionProcessor.h (91%) rename src/{datamanagement/datadecoding/include => }/IActiveDecoderDictionaryListener.h (89%) rename src/{datamanagement/datacollection/include => }/ICollectionScheme.h (98%) rename src/{datamanagement/datacollection/include => }/ICollectionSchemeList.h (98%) rename src/{datamanagement/datamanager/include => }/ICollectionSchemeManager.h (95%) rename src/{offboardconnectivity/api/include => }/IConnectionTypes.h (83%) rename src/{offboardconnectivity/api/include => }/IConnectivityChannel.h (79%) rename src/{offboardconnectivity/api/include => }/IConnectivityModule.h (83%) rename src/{datamanagement/datainspection/include => }/IDataReadyToPublishListener.h (89%) rename src/{datamanagement/datadecoding/include => }/IDecoderDictionary.h (97%) rename src/{datamanagement/datadecoding/include => }/IDecoderManifest.h (99%) rename src/{platform/linux/logmanagement/include => }/ILogger.h (93%) rename src/{offboardconnectivity/api/include => }/IReceiver.h (90%) rename src/{vehiclenetwork/include/datatypes => }/ISOTPOverCANOptions.h (98%) rename src/{vehiclenetwork/src => }/ISOTPOverCANReceiver.cpp (91%) rename src/{vehiclenetwork/include/businterfaces => }/ISOTPOverCANReceiver.h (90%) rename src/{vehiclenetwork/src => }/ISOTPOverCANSender.cpp (88%) rename src/{vehiclenetwork/include/businterfaces => }/ISOTPOverCANSender.h (88%) rename src/{vehiclenetwork/src => }/ISOTPOverCANSenderReceiver.cpp (95%) rename src/{vehiclenetwork/include/businterfaces => }/ISOTPOverCANSenderReceiver.h (91%) rename src/{offboardconnectivity/api/include => }/ISender.h (89%) rename src/{datamanagement/custom/example/iwavegps/src => }/IWaveGpsSource.cpp (98%) rename src/{datamanagement/custom/example/iwavegps/include => }/IWaveGpsSource.h (94%) rename src/{datamanagement/datainspection/include => }/InspectionEventListener.h (98%) rename src/{datamanagement/datamanager/src => }/InspectionMatrixExtractor.cpp (98%) rename src/{executionmanagement/src => }/IoTFleetWiseConfig.cpp (86%) rename src/{executionmanagement/include => }/IoTFleetWiseConfig.h (86%) rename src/{executionmanagement/src => }/IoTFleetWiseEngine.cpp (96%) rename src/{executionmanagement/include => }/IoTFleetWiseEngine.h (89%) rename src/{executionmanagement/src => }/IoTFleetWiseVersion.cpp.in (100%) rename src/{executionmanagement/include => }/IoTFleetWiseVersion.h (100%) rename src/{platform/linux/threadingmanagement/include => }/Listener.h (98%) rename src/{platform/linux/logmanagement/include => }/LogLevel.h (61%) rename src/{platform/linux/logmanagement/src => }/LoggingModule.cpp (58%) rename src/{platform/linux/logmanagement/include => }/LoggingModule.h (96%) rename src/{platform/linux/resourcemanagement/src => }/MemoryUsageInfo.cpp (91%) rename src/{platform/linux/resourcemanagement/include => }/MemoryUsageInfo.h (90%) rename src/{datamanagement/types/include => }/MessageTypes.h (96%) create mode 100644 src/MqttClientWrapper.h create mode 100644 src/MqttConnectionWrapper.h rename src/{datamanagement/datadecoding/src => }/OBDDataDecoder.cpp (99%) rename src/{datamanagement/datadecoding/include => }/OBDDataDecoder.h (97%) rename src/{datamanagement/types/include => }/OBDDataTypes.h (96%) rename src/{datamanagement/datainspection/src/diag => }/OBDOverCANECU.cpp (98%) rename src/{datamanagement/datainspection/include => }/OBDOverCANECU.h (95%) rename src/{datamanagement/datainspection/src/diag => }/OBDOverCANModule.cpp (97%) rename src/{datamanagement/datainspection/include => }/OBDOverCANModule.h (96%) rename src/{offboardconnectivity/implementation/aws/iotcpp/src => }/PayloadManager.cpp (88%) rename src/{offboardconnectivity/implementation/aws/iotcpp/include => }/PayloadManager.h (53%) rename src/{offboardconnectivity/implementation/aws/iotcpp/src => }/RemoteProfiler.cpp (96%) rename src/{offboardconnectivity/implementation/aws/iotcpp/include => }/RemoteProfiler.h (96%) rename src/{offboardconnectivity/implementation/aws/iotcpp/src => }/RetryThread.cpp (95%) rename src/{offboardconnectivity/implementation/aws/iotcpp/include => }/RetryThread.h (94%) rename src/{datamanagement/datamanager/src => }/Schema.cpp (93%) rename src/{datamanagement/datamanager/include => }/Schema.h (96%) rename src/{datamanagement/datamanager/include => }/SchemaListener.h (94%) rename src/{platform/linux/threadingmanagement/include => }/Signal.h (96%) rename src/{datamanagement/types/include => }/SignalTypes.h (98%) rename src/{platform/linux/threadingmanagement/src => }/Thread.cpp (90%) rename src/{platform/linux/threadingmanagement/include => }/Thread.h (90%) rename src/{platform/linux/timemanagement/include => }/TimeTypes.h (87%) rename src/{platform/linux/timemanagement/include => }/Timer.h (96%) rename src/{platform/linux/logmanagement/src => }/TraceModule.cpp (99%) rename src/{platform/linux/logmanagement/include => }/TraceModule.h (99%) rename src/{vehiclenetwork/include/datatypes => }/VehicleDataSourceTypes.h (91%) rename src/{executionmanagement/src => }/android_shared_library.cpp (95%) delete mode 100644 src/datamanagement/CMakeLists.txt delete mode 100644 src/datamanagement/custom/CMakeLists.txt delete mode 100644 src/datamanagement/custom/example/iwavegps/test/.clang-tidy delete mode 100644 src/datamanagement/custom/generic/test/.clang-tidy delete mode 100644 src/datamanagement/custom/generic/test/valgrind.supp delete mode 100644 src/datamanagement/datacollection/CMakeLists.txt delete mode 100644 src/datamanagement/datacollection/test/.clang-tidy delete mode 100644 src/datamanagement/datacollection/test/valgrind.supp delete mode 100644 src/datamanagement/datadecoding/CMakeLists.txt delete mode 100644 src/datamanagement/datadecoding/test/.clang-tidy delete mode 100644 src/datamanagement/datadecoding/test/valgrind.supp delete mode 100644 src/datamanagement/datainspection/CMakeLists.txt delete mode 100644 src/datamanagement/datainspection/test/.clang-tidy delete mode 100644 src/datamanagement/datainspection/test/di-collection-policy-example-reduced.json delete mode 100644 src/datamanagement/datainspection/test/di-collection-policy-example.json delete mode 100644 src/datamanagement/datainspection/test/di-collection-scheme-example-reduced.json delete mode 100644 src/datamanagement/datainspection/test/di-collection-scheme-example.json delete mode 100644 src/datamanagement/datainspection/test/valgrind.supp delete mode 100644 src/datamanagement/datamanager/CMakeLists.txt delete mode 100644 src/datamanagement/datamanager/test/.clang-tidy delete mode 100644 src/datamanagement/datamanager/test/valgrind.supp delete mode 100644 src/datamanagement/datasender/CMakeLists.txt delete mode 100644 src/datamanagement/datasender/src/DataSenderManagerWorkerThread.cpp delete mode 100644 src/datamanagement/datasender/test/.clang-tidy delete mode 100644 src/datamanagement/datasender/test/dm-collection-scheme-example.json delete mode 100644 src/datamanagement/datasender/test/valgrind.supp delete mode 100644 src/datamanagement/types/CMakeLists.txt delete mode 100644 src/datamanagement/types/test/.clang-tidy delete mode 100644 src/datamanagement/types/test/valgrind.supp delete mode 100644 src/executionmanagement/CMakeLists.txt delete mode 100644 src/executionmanagement/test/.clang-tidy delete mode 100644 src/executionmanagement/test/valgrind.supp rename src/{executionmanagement/src => }/main.cpp (89%) delete mode 100644 src/offboardconnectivity/CMakeLists.txt delete mode 100644 src/offboardconnectivity/api/CMakeLists.txt delete mode 100644 src/offboardconnectivity/implementation/aws/CMakeLists.txt delete mode 100644 src/offboardconnectivity/implementation/aws/bootstrap/CMakeLists.txt delete mode 100644 src/offboardconnectivity/implementation/aws/iotcpp/CMakeLists.txt delete mode 100644 src/offboardconnectivity/implementation/aws/iotcpp/test/include/AwsIotSdkMock.h delete mode 100644 src/offboardconnectivity/implementation/aws/iotcpp/test/include/aws-iot-cpp-sdk-mock/aws/crt/Api.h delete mode 100644 src/offboardconnectivity/implementation/aws/iotcpp/test/include/aws-iot-cpp-sdk-mock/aws/crt/Types.h delete mode 100644 src/offboardconnectivity/implementation/aws/iotcpp/test/include/aws-iot-cpp-sdk-mock/aws/crt/UUID.h delete mode 100644 src/offboardconnectivity/implementation/aws/iotcpp/test/include/aws-iot-cpp-sdk-mock/aws/iot/MqttClient.h delete mode 100644 src/offboardconnectivity/implementation/aws/iotcpp/test/src/.clang-tidy delete mode 100644 src/offboardconnectivity/implementation/aws/iotcpp/test/src/AwsIotSdkMock.cpp delete mode 100644 src/offboardconnectivity/implementation/aws/iotcpp/test/src/MqttClient.cpp delete mode 100644 src/offboardconnectivity/implementation/aws/iotcpp/test/src/RemoteProfilerTest.cpp delete mode 100644 src/offboardconnectivity/implementation/aws/iotcpp/test/valgrind.supp delete mode 100644 src/platform/CMakeLists.txt delete mode 100644 src/platform/linux/CMakeLists.txt delete mode 100644 src/platform/linux/logmanagement/test/.clang-tidy delete mode 100644 src/platform/linux/persistencymanagement/test/.clang-tidy delete mode 100644 src/platform/linux/resourcemanagement/test/.clang-tidy delete mode 100644 src/platform/linux/test/valgrind.supp delete mode 100644 src/platform/linux/threadingmanagement/test/.clang-tidy delete mode 100644 src/platform/linux/timemanagement/test/.clang-tidy delete mode 100644 src/platform/utility/CMakeLists.txt delete mode 100644 src/testingsupport/CMakeLists.txt delete mode 100644 src/testingsupport/src/main.cpp delete mode 100644 src/testingsupport/test/.clang-tidy delete mode 100644 src/testingsupport/test/valgrind.supp delete mode 100644 src/vehiclenetwork/CMakeLists.txt delete mode 100644 src/vehiclenetwork/test/.clang-tidy delete mode 100644 src/vehiclenetwork/test/valgrind.supp rename {src/datamanagement/custom/example/aaosvhal/test => test/unit}/AaosVhalSourceTest.cpp (87%) rename {src/offboardconnectivity/implementation/aws/iotcpp/test/src => test/unit}/AwsIotConnectivityModuleTest.cpp (61%) rename {src/datamanagement/datainspection/test => test/unit}/CANDataSourceTest.cpp (96%) rename {src/datamanagement/datadecoding/test => test/unit}/CANDecoderTest.cpp (98%) rename {src/platform/linux/resourcemanagement/test => test/unit}/CPUUsageInfoTest.cpp (85%) rename {src/platform/linux/persistencymanagement/test => test/unit}/CacheAndPersistTest.cpp (98%) rename {src/datamanagement/datamanager/test => test/unit}/CheckinAndPersistencyTest.cpp (96%) rename {src/platform/linux/timemanagement/test => test/unit}/ClockHandlerBenchmarkTest.cpp (61%) rename {src/platform/linux/timemanagement/test => test/unit}/ClockHandlerTest.cpp (73%) rename {src/datamanagement/datainspection/test => test/unit}/CollectionInspectionEngineTest.cpp (99%) rename {src/datamanagement/datainspection/test => test/unit}/CollectionInspectionWorkerThreadTest.cpp (97%) rename {src/datamanagement/datamanager/test => test/unit}/CollectionSchemeManagerGtest.cpp (98%) rename {src/datamanagement/datamanager/test => test/unit}/CollectionSchemeManagerTest.cpp (97%) rename {src/datamanagement/custom/generic/test => test/unit}/CustomDataSourceTest.cpp (92%) create mode 100644 test/unit/DataSenderManagerTest.cpp create mode 100644 test/unit/DataSenderManagerWorkerThreadTest.cpp rename {src/datamanagement/datasender/test => test/unit}/DataSenderProtoWriterTest.cpp (91%) rename {src/datamanagement/datamanager/test => test/unit}/DecoderDictionaryExtractorTest.cpp (99%) rename {src/datamanagement/datainspection/test => test/unit}/ExternalCANDataSourceTest.cpp (94%) rename {src/datamanagement/custom/example/externalgps/test => test/unit}/ExternalGpsSourceTest.cpp (90%) rename {src/testingsupport/test => test/unit}/FakeSystemTimeTest.cpp (94%) rename {src/datamanagement/datainspection/test => test/unit}/GeohashFunctionNodeTest.cpp (98%) rename {src/datamanagement/types/test => test/unit}/GeohashTest.cpp (95%) rename {src/vehiclenetwork/test => test/unit}/ISOTPOverCANProtocolTest.cpp (96%) rename {src/datamanagement/custom/example/iwavegps/test => test/unit}/IWaveGpsSourceTest.cpp (92%) rename {src/datamanagement/datamanager/test => test/unit}/InspectionMatrixExtractorTest.cpp (95%) rename {src/executionmanagement/test => test/unit}/IoTFleetWiseConfigTest.cpp (78%) rename {src/executionmanagement/test => test/unit}/IoTFleetWiseEngineTest.cpp (85%) create mode 100644 test/unit/LoggingModuleTest.cpp rename {src/platform/linux/resourcemanagement/test => test/unit}/MemoryUsageInfoTest.cpp (83%) rename {src/datamanagement/datadecoding/test => test/unit}/OBDDataDecoderTest.cpp (99%) rename {src/datamanagement/datainspection/test => test/unit}/OBDOverCANModuleTest.cpp (91%) rename {src/offboardconnectivity/implementation/aws/iotcpp/test/src => test/unit}/PayloadManagerTest.cpp (94%) create mode 100644 test/unit/RemoteProfilerTest.cpp rename {src/datamanagement/datamanager/test => test/unit}/SchemaTest.cpp (81%) rename {src/platform/linux/threadingmanagement/test => test/unit}/ThreadTest.cpp (83%) rename {src/platform/linux/timemanagement/test => test/unit}/TimerTest.cpp (87%) rename {src/platform/linux/logmanagement/test => test/unit}/TraceModuleTest.cpp (93%) rename {src/testingsupport/test => test/unit}/WaitUntilTest.cpp (93%) rename {src/datamanagement/datamanager/test/include => test/unit/support}/CollectionSchemeManagerMock.h (96%) rename {src/datamanagement/datamanager/test/include => test/unit/support}/CollectionSchemeManagerTest.h (93%) create mode 100644 test/unit/support/ConnectivityModuleMock.h create mode 100644 test/unit/support/DataSenderManagerMock.h rename {src/testingsupport/include => test/unit/support}/Faketime.h (98%) create mode 100644 test/unit/support/MqttClientWrapperMock.h create mode 100644 test/unit/support/MqttConnectionWrapperMock.h rename {src/vehiclenetwork/include/datatypes => test/unit/support}/OBDDataTypesUnitTestOnly.h (99%) create mode 100644 test/unit/support/PayloadManagerMock.h create mode 100644 test/unit/support/SenderMock.h rename {src/testingsupport/include => test/unit/support}/Testing.h (69%) rename {src/testingsupport/include => test/unit/support}/WaitUntil.h (99%) create mode 100644 test/unit/support/main.cpp rename src/executionmanagement/test/em-example-config-corrupt.json => test/unit/support/static-config-corrupt.json (100%) rename src/executionmanagement/test/em-example-config-inline-creds.json => test/unit/support/static-config-inline-creds.json (100%) rename src/executionmanagement/test/em-example-config.json => test/unit/support/static-config-ok.json (100%) create mode 100755 tools/cloud/firehose-to-html.py delete mode 100755 tools/cloud/s3-to-html.py diff --git a/.github/template/fwe-build/action.yml b/.github/template/fwe-build/action.yml index c90c6063..cf5475d4 100644 --- a/.github/template/fwe-build/action.yml +++ b/.github/template/fwe-build/action.yml @@ -58,7 +58,7 @@ runs: with: name: build-${{ inputs.upload-arch }} path: | - build/src/executionmanagement/aws-iot-fleetwise-edge + build/aws-iot-fleetwise-edge build/aws-iot-fleetwise-edge-${{ inputs.upload-arch }}.tar.gz build/Testing/Temporary/ build/**/report-*.xml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9f8eb575..8431c58f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -38,7 +38,7 @@ jobs: build-arch: "native" upload-arch: "amd64" cache-paths: /usr/local/x86_64-linux-gnu - dist-files: build/src/executionmanagement/aws-iot-fleetwise-edge:. + dist-files: build/aws-iot-fleetwise-edge:. build-arm64: runs-on: ubuntu-20.04 @@ -49,7 +49,7 @@ jobs: build-arch: "cross-arm64" upload-arch: "arm64" cache-paths: /usr/local/aarch64-linux-gnu:/usr/local/x86_64-linux-gnu - dist-files: build/src/executionmanagement/aws-iot-fleetwise-edge:. + dist-files: build/aws-iot-fleetwise-edge:. build-armhf: runs-on: ubuntu-20.04 @@ -60,7 +60,7 @@ jobs: build-arch: "cross-armhf" upload-arch: "armhf" cache-paths: /usr/local/arm-linux-gnueabihf:/usr/local/x86_64-linux-gnu - dist-files: build/src/executionmanagement/aws-iot-fleetwise-edge:. + dist-files: build/aws-iot-fleetwise-edge:. build-android: runs-on: ubuntu-20.04 @@ -70,11 +70,11 @@ jobs: with: build-arch: "cross-android" upload-arch: "android" - cache-paths: /usr/local/aarch64-linux-android:/usr/local/armv7a-linux-androideabi:/usr/local/x86_64-linux-gnu + cache-paths: /usr/local/x86_64-linux-android:/usr/local/aarch64-linux-android:/usr/local/armv7a-linux-androideabi:/usr/local/x86_64-linux-gnu dist-files: - build/x86_64/src/executionmanagement/libaws-iot-fleetwise-edge.so:x86_64 - build/armeabi-v7a/src/executionmanagement/libaws-iot-fleetwise-edge.so:armeabi-v7a - build/arm64-v8a/src/executionmanagement/libaws-iot-fleetwise-edge.so:arm64-v8a + build/x86_64/libaws-iot-fleetwise-edge.so:x86_64 + build/armeabi-v7a/libaws-iot-fleetwise-edge.so:armeabi-v7a + build/arm64-v8a/libaws-iot-fleetwise-edge.so:arm64-v8a - name: build-app run: | mkdir -p tools/android-app/app/src/main/jniLibs diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index f077b3b1..56ddc595 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -26,6 +26,23 @@ repos: - id: detect-aws-credentials args: [--allow-missing-credentials] - id: detect-private-key + - repo: local + hooks: + - id: replace-c-headers + name: replace-c-headers + entry: | + sed -i -e 's/#include /#include /' + -e 's/#include /#include /' + -e 's/#include /#include /' + -e 's/#include /#include /' + -e 's/#include /#include /' + -e 's/#include /#include /' + -e 's/#include /#include /' + -e 's/#include /#include /' + -e 's/#include /#include /' + language: system + verbose: true + types: [c++] - repo: https://github.com/pre-commit/mirrors-clang-format rev: v10.0.1 hooks: @@ -81,27 +98,32 @@ repos: hooks: - id: validate-static-config name: validate-static-config - # pre-commit intentionally pass all files as args to the command. - # Since the json command only takes one file at once we need some shell script to split the args. entry: - bash -c 'for x in "$@"; do echo "Validating file $x"; json validate --schema-file - interfaces/protobuf/schemas/edgeConfiguration/staticConfiguration.json --document-file - "$x"; done' -- + check-jsonschema --schemafile + interfaces/protobuf/schemas/edgeConfiguration/staticConfiguration.json -- language: python files: "configuration/static-config.json|tools/android-app/app/src/main/assets/config-0.json" types: [json] - additional_dependencies: ["json-spec==0.10.1"] + additional_dependencies: ["check-jsonschema==0.25.0"] verbose: true - id: validate-persistency-metadata name: validate-persistency-metadata - # pre-commit intentionally pass all files as args to the command. - # Since the json command only takes one file at once we need some shell script to split the args. entry: - bash -c 'for x in "$@"; do echo "Validating file $x"; json validate --schema-file - interfaces/persistency/schemas/persistencyMetadataFormat.json --document-file "$x"; done' - -- + check-jsonschema --schemafile + interfaces/persistency/schemas/persistencyMetadataFormat.json -- language: python files: "interfaces/persistency/examples/persistencyMetadataFormat.json" types: [json] - additional_dependencies: ["json-spec==0.10.1"] + additional_dependencies: ["check-jsonschema==0.25.0"] + verbose: true + - id: validate-build-files + name: validate-build-files + entry: + bash -e -c 'FILE_MISSING=false; for FILE in "$@"; do if ! grep -q "${FILE}" + CMakeLists.txt; then echo "${FILE} is missing from CMakeLists.txt"; FILE_MISSING=true; fi; + done; if ${FILE_MISSING}; then exit -1; fi' -- + language: python + files: "^src|^test/unit" + exclude: "^test/unit/support" + types: [c++] verbose: true diff --git a/CHANGELOG.md b/CHANGELOG.md index 5bbbf62c..703fec33 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,31 @@ # Change Log +## v1.0.8 (2023-09-25) + +Bug fixes: + +- Update AWS C++ SDK to v1.11.148, which includes an + [important bugfix](https://github.com/awslabs/aws-c-mqtt/pull/311) for MQTT 3.1.1 clients. + +Improvements: + +- Add support for building as a library exported by CMake. Set the CMake option + `FWE_BUILD_EXECUTABLE` to `OFF`, then use `find_package(AwsIotFwe)`, `${AwsIotFwe_INCLUDE_DIR}` + and link with `AwsIotFwe::AwsIotFwe`. +- Non-functional source code improvements: + - Simplify `src/` folder structure, removing sub-namespaces & sub-libraries, and moving unit test + files to `test/unit/`. + - Correct `#include`s using + [`include-what-you-use`](https://github.com/include-what-you-use/include-what-you-use). + - Move from compile-time mocking to link-time mocking of AWS C++ SDK using Google Mock. +- Fix GitHub CI: support separate Ubuntu package mirror file, fix caching of Android install files. +- Add support for shared libraries to dependency install scripts. +- Developer guide and demo script improvements: + - Add clean up instructions. + - Better support existing S3 buckets, with check for same region & ACLs being disabled, and allow + setting of bucket policy. + - Allow HTML generation of results for custom DBC files. + ## v1.0.7 (2023-08-01) Features: diff --git a/CMakeLists.txt b/CMakeLists.txt index 3d8110a3..73441ec6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,14 +2,12 @@ cmake_minimum_required(VERSION 3.10.2) -project(iotfleetwise VERSION 1.0.7) +project(iotfleetwise VERSION 1.0.8) # FWE uses C++14 for compatibility reasons with Automotive middlewares (Adaptive AUTOSAR, ROS2) set(CMAKE_CXX_STANDARD 14) set(CMAKE_CXX_STANDARD_REQUIRED True) -message(STATUS "Hello from the FWE build system!") - # Print out the compile commands which is useful for IDEs set(CMAKE_EXPORT_COMPILE_COMMANDS ON) @@ -30,7 +28,7 @@ option(FWE_FEATURE_CUSTOM_DATA_SOURCE "Include the custom data source interface" option(FWE_FEATURE_IWAVE_GPS "Include the IWave GPS example for a custom data source" OFF) option(FWE_FEATURE_EXTERNAL_GPS "Include the external GPS example for a custom data source" OFF) option(FWE_FEATURE_AAOS_VHAL "Include the Android Automotive VHAL example for a custom data source" OFF) -option(FWE_BUILD_EXECUTABLE "Build the executable" ON) +option(FWE_BUILD_EXECUTABLE "Build the executable, otherwise build a library" ON) option(FWE_BUILD_ANDROID_SHARED_LIBRARY "Build the android shared library" OFF) if(FWE_FEATURE_IWAVE_GPS) add_compile_options("-DFWE_FEATURE_IWAVE_GPS") @@ -50,19 +48,421 @@ if(NOT CMAKE_BUILD_TYPE) set(CMAKE_BUILD_TYPE Release) endif() -include(cmake/graphviz.cmake) include(cmake/compiler_gcc.cmake) -include(cmake/protobufs.cmake) -include(cmake/snappy.cmake) -include(CTest) -include(cmake/unit_test.cmake) -include(cmake/valgrind.cmake) -include(cmake/clang_tidy.cmake) +include(GNUInstallDirs) if(FWE_BUILD_DOC) + include(cmake/graphviz.cmake) include(cmake/doxygen.cmake) endif() - -add_subdirectory(src) +include(CTest) +if(BUILD_TESTING) + include(cmake/unit_test.cmake) + include(cmake/valgrind.cmake) + include(cmake/clang_tidy.cmake) +endif() # Disallow cycles -set_property( GLOBAL PROPERTY GLOBAL_DEPENDS_NO_CYCLES ON ) +set_property(GLOBAL PROPERTY GLOBAL_DEPENDS_NO_CYCLES ON) + +# Version +execute_process(COMMAND git -C "${CMAKE_CURRENT_SOURCE_DIR}" rev-parse HEAD + OUTPUT_VARIABLE VERSION_GIT_SHA + ERROR_QUIET) +execute_process(COMMAND git -C "${CMAKE_CURRENT_SOURCE_DIR}" describe --tags --abbrev=0 + OUTPUT_VARIABLE VERSION_GIT_TAG + ERROR_QUIET) +string(STRIP "${VERSION_GIT_SHA}" VERSION_GIT_SHA) +string(STRIP "${VERSION_GIT_TAG}" VERSION_GIT_TAG) +string(TIMESTAMP VERSION_CURRENT_TIME "%Y-%m-%d %H:%M:%S" UTC) +configure_file(src/IoTFleetWiseVersion.cpp.in ${CMAKE_CURRENT_BINARY_DIR}/IoTFleetWiseVersion.cpp) + +# Protobuf +find_package(Protobuf REQUIRED) +protobuf_generate_cpp(PROTO_SRCS PROTO_HDRS + interfaces/protobuf/schemas/cloudToEdge/collection_schemes.proto + interfaces/protobuf/schemas/cloudToEdge/decoder_manifest.proto + interfaces/protobuf/schemas/edgeToCloud/checkin.proto + interfaces/protobuf/schemas/edgeToCloud/vehicle_data.proto +) +add_library(fwe-proto OBJECT + ${PROTO_SRCS} + ${PROTO_HDRS} +) +target_include_directories(fwe-proto PUBLIC + ${Protobuf_INCLUDE_DIRS} +) +# Protobuf does not support -Wall https://github.com/protocolbuffers/protobuf/issues/6781 +set_source_files_properties(${PROTO_SRCS} PROPERTIES COMPILE_FLAGS "-Wno-conversion -Wno-pedantic") + +set(HEADER_FILES + src/AwsBootstrap.h + src/AwsIotChannel.h + src/AwsIotConnectivityModule.h + src/AwsSDKMemoryManager.h + src/CacheAndPersist.h + src/CANDataConsumer.h + src/CANDataSource.h + src/CANDataTypes.h + src/CANDecoder.h + src/CANInterfaceIDTranslator.h + src/Clock.h + src/ClockHandler.h + src/CollectionInspectionAPITypes.h + src/CollectionInspectionEngine.h + src/CollectionInspectionWorkerThread.h + src/CollectionSchemeIngestion.h + src/CollectionSchemeIngestionList.h + src/CollectionSchemeManagementListener.h + src/CollectionSchemeManager.h + src/ConsoleLogger.h + src/CPUUsageInfo.h + src/DataReduction.h + src/DataSenderManager.h + src/DataSenderManagerWorkerThread.h + src/DataSenderProtoWriter.h + src/DecoderManifestIngestion.h + src/EnumUtility.h + src/EventTypes.h + src/ExternalCANDataSource.h + src/GeohashFunctionNode.h + src/Geohash.h + src/GeohashInfo.h + src/IActiveCollectionSchemesListener.h + src/IActiveConditionProcessor.h + src/IActiveDecoderDictionaryListener.h + src/ICollectionScheme.h + src/ICollectionSchemeList.h + src/ICollectionSchemeManager.h + src/IConnectionTypes.h + src/IConnectivityChannel.h + src/IConnectivityModule.h + src/IDataReadyToPublishListener.h + src/IDecoderDictionary.h + src/IDecoderManifest.h + src/ILogger.h + src/InspectionEventListener.h + src/IoTFleetWiseConfig.h + src/IoTFleetWiseEngine.h + src/IoTFleetWiseVersion.h + src/IReceiver.h + src/ISender.h + src/ISOTPOverCANOptions.h + src/ISOTPOverCANReceiver.h + src/ISOTPOverCANSender.h + src/ISOTPOverCANSenderReceiver.h + src/Listener.h + src/LoggingModule.h + src/LogLevel.h + src/MemoryUsageInfo.h + src/MessageTypes.h + src/MqttClientWrapper.h + src/MqttConnectionWrapper.h + src/OBDDataDecoder.h + src/OBDDataTypes.h + src/OBDOverCANECU.h + src/OBDOverCANModule.h + src/PayloadManager.h + src/RemoteProfiler.h + src/RetryThread.h + src/Schema.h + src/SchemaListener.h + src/Signal.h + src/SignalTypes.h + src/Thread.h + src/Timer.h + src/TimeTypes.h + src/TraceModule.h + src/VehicleDataSourceTypes.h +) + +# Source files +set(SRC_FILES + src/AwsBootstrap.cpp + src/AwsIotChannel.cpp + src/AwsIotConnectivityModule.cpp + src/AwsSDKMemoryManager.cpp + src/CacheAndPersist.cpp + src/CANDataConsumer.cpp + src/CANDataSource.cpp + src/CANDecoder.cpp + src/CheckinAndPersistency.cpp + src/ClockHandler.cpp + src/CollectionInspectionEngine.cpp + src/CollectionInspectionWorkerThread.cpp + src/CollectionSchemeIngestion.cpp + src/CollectionSchemeIngestionList.cpp + src/CollectionSchemeManager.cpp + src/ConsoleLogger.cpp + src/CPUUsageInfo.cpp + src/DataSenderManager.cpp + src/DataSenderManagerWorkerThread.cpp + src/DataSenderProtoWriter.cpp + src/DecoderDictionaryExtractor.cpp + src/DecoderManifestIngestion.cpp + src/ExternalCANDataSource.cpp + src/Geohash.cpp + src/GeohashFunctionNode.cpp + src/InspectionMatrixExtractor.cpp + src/IoTFleetWiseConfig.cpp + src/IoTFleetWiseEngine.cpp + src/ISOTPOverCANReceiver.cpp + src/ISOTPOverCANSender.cpp + src/ISOTPOverCANSenderReceiver.cpp + src/LoggingModule.cpp + src/MemoryUsageInfo.cpp + src/OBDDataDecoder.cpp + src/OBDOverCANECU.cpp + src/OBDOverCANModule.cpp + src/PayloadManager.cpp + src/RemoteProfiler.cpp + src/RetryThread.cpp + src/Schema.cpp + src/Thread.cpp + src/TraceModule.cpp + ${CMAKE_CURRENT_BINARY_DIR}/IoTFleetWiseVersion.cpp +) + +# Test files +set(TEST_FILES + test/unit/AwsIotConnectivityModuleTest.cpp + test/unit/CacheAndPersistTest.cpp + test/unit/CANDataSourceTest.cpp + test/unit/CANDecoderTest.cpp + test/unit/CheckinAndPersistencyTest.cpp + test/unit/ClockHandlerBenchmarkTest.cpp + test/unit/ClockHandlerTest.cpp + test/unit/CollectionInspectionEngineTest.cpp + test/unit/CollectionInspectionWorkerThreadTest.cpp + test/unit/CollectionSchemeManagerGtest.cpp + test/unit/CollectionSchemeManagerTest.cpp + test/unit/CPUUsageInfoTest.cpp + test/unit/DataSenderManagerTest.cpp + test/unit/DataSenderManagerWorkerThreadTest.cpp + test/unit/DataSenderProtoWriterTest.cpp + test/unit/DecoderDictionaryExtractorTest.cpp + test/unit/ExternalCANDataSourceTest.cpp + test/unit/GeohashFunctionNodeTest.cpp + test/unit/GeohashTest.cpp + test/unit/InspectionMatrixExtractorTest.cpp + test/unit/IoTFleetWiseConfigTest.cpp + test/unit/IoTFleetWiseEngineTest.cpp + test/unit/ISOTPOverCANProtocolTest.cpp + test/unit/LoggingModuleTest.cpp + test/unit/MemoryUsageInfoTest.cpp + test/unit/OBDDataDecoderTest.cpp + test/unit/OBDOverCANModuleTest.cpp + test/unit/PayloadManagerTest.cpp + test/unit/RemoteProfilerTest.cpp + test/unit/SchemaTest.cpp + test/unit/ThreadTest.cpp + test/unit/TimerTest.cpp + test/unit/TraceModuleTest.cpp + test/unit/WaitUntilTest.cpp +) + +set(BENCHMARK_FILES # Also in list TEST_FILES above, but will be tested using Benchmark + test/unit/ClockHandlerBenchmarkTest.cpp +) + +# Optional files +if(FWE_FEATURE_IWAVE_GPS) + set(SRC_FILES ${SRC_FILES} src/IWaveGpsSource.cpp) + set(TEST_FILES ${TEST_FILES} test/unit/IWaveGpsSourceTest.cpp) + set(HEADER_FILES ${HEADER_FILES} src/IWaveGpsSource.h) +endif() +if(FWE_FEATURE_EXTERNAL_GPS) + set(SRC_FILES ${SRC_FILES} src/ExternalGpsSource.cpp) + set(TEST_FILES ${TEST_FILES} test/unit/ExternalGpsSourceTest.cpp) + set(HEADER_FILES ${HEADER_FILES} src/ExternalGpsSource.h) +endif() +if(FWE_FEATURE_AAOS_VHAL) + set(SRC_FILES ${SRC_FILES} src/AaosVhalSource.cpp) + set(TEST_FILES ${TEST_FILES} test/unit/AaosVhalSourceTest.cpp) + set(HEADER_FILES ${HEADER_FILES} src/AaosVhalSource.h) +endif() +if(FWE_FEATURE_CUSTOM_DATA_SOURCE) + set(SRC_FILES ${SRC_FILES} src/CustomDataSource.cpp) + set(TEST_FILES ${TEST_FILES} test/unit/CustomDataSourceTest.cpp) + set(HEADER_FILES ${HEADER_FILES} src/CustomDataSource.h) +endif() +if(FWE_FEATURE_GREENGRASSV2) + set(SRC_FILES ${SRC_FILES} src/AwsGGConnectivityModule.cpp src/AwsGGChannel.cpp) + set(HEADER_FILES ${HEADER_FILES} src/AwsGGChannel.h src/AwsGGConnectivityModule.h) +endif() +if(FWE_TEST_FAKETIME) + set(TEST_FILES ${TEST_FILES} test/unit/FakeSystemTimeTest.cpp) + set(FAKETIME_FILES # Also in list TEST_FILES above, but will be tested using FakeTime + test/unit/FakeSystemTimeTest.cpp + ) +endif() + +# Dependencies +set(REQUIRED_BOOST_COMPONENTS "thread;filesystem") +find_package(Boost 1.71.0 REQUIRED COMPONENTS ${REQUIRED_BOOST_COMPONENTS}) + +find_path(JSONCPP_INCLUDE_DIR "json/json.h" PATH_SUFFIXES "jsoncpp") +find_library(JSONCPP_LIBRARY NAMES jsoncpp) + +find_path(SNAPPY_INCLUDE_DIR "snappy.h") +find_library(SNAPPY_LIBRARY NAMES snappy) + +# Extra libraries are required to statically link with the AWS SDK. These are not always found by CMake, hence: +# - When FWE_STATIC_LINK is ON and FWE_AWS_SDK_EXTRA_LIBS is ON, automatically find the standard libraries: libcurl, libssl, libcrypto, libz +# - When FWE_AWS_SDK_EXTRA_LIBS is a list of libs, use those +# - When FWE_AWS_SDK_EXTRA_LIBS is OFF, don't link any extra libs +if(FWE_AWS_SDK_EXTRA_LIBS STREQUAL "ON") + if(NOT FWE_STATIC_LINK) + set(FWE_AWS_SDK_EXTRA_LIBS "") + else() + set(OLD_CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_FIND_LIBRARY_SUFFIXES}) + set(CMAKE_FIND_LIBRARY_SUFFIXES ".a") + find_library(CURL_LIBRARY NAMES curl) + find_library(OPENSSL_SSL_LIBRARY NAMES ssl) + find_library(OPENSSL_CRYPTO_LIBRARY NAMES crypto) + find_package(ZLIB REQUIRED) + set(FWE_AWS_SDK_EXTRA_LIBS "${CURL_LIBRARY} ${OPENSSL_SSL_LIBRARY} ${OPENSSL_CRYPTO_LIBRARY} ZLIB::ZLIB") + set(CMAKE_FIND_LIBRARY_SUFFIXES ${OLD_CMAKE_FIND_LIBRARY_SUFFIXES}) + endif() +elseif(FWE_AWS_SDK_EXTRA_LIBS STREQUAL "OFF") + set(FWE_AWS_SDK_EXTRA_LIBS "") +endif() +separate_arguments(FWE_AWS_SDK_EXTRA_LIBS) + +set(REQUIRED_AWS_SDK_COMPONENTS "core") +set(OLD_BUILD_SHARED_LIBS ${BUILD_SHARED_LIBS}) +set(BUILD_SHARED_LIBS ${FWE_AWS_SDK_SHARED_LIBS}) +# Note: this should only be called once +find_package(AWSSDK REQUIRED COMPONENTS ${REQUIRED_AWS_SDK_COMPONENTS}) +set(BUILD_SHARED_LIBS ${OLD_BUILD_SHARED_LIBS}) + +if(FWE_FEATURE_GREENGRASSV2) + find_package(GreengrassIpc-cpp REQUIRED) +endif() + +# Object lib used in output binary and unit tests +add_library(fwe OBJECT + ${SRC_FILES} +) + +# Include dirs +target_include_directories(fwe PUBLIC + ${JSONCPP_INCLUDE_DIR} + ${SNAPPY_INCLUDE_DIR} + ${Protobuf_INCLUDE_DIRS} + $ + $ +) + +# Link libraries +target_link_libraries(fwe + $<$:AWS::GreengrassIpc-cpp> + ${AWSSDK_LINK_LIBRARIES} + ${FWE_AWS_SDK_EXTRA_LIBS} + ${SNAPPY_LIBRARY} + ${JSONCPP_LIBRARY} + ${Protobuf_LIBRARIES} + Boost::thread + Boost::filesystem +) + +# Executable or library output binary +if(FWE_BUILD_EXECUTABLE) + add_executable(aws-iot-fleetwise-edge + src/main.cpp + ) + install(TARGETS aws-iot-fleetwise-edge + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} + ) + target_link_libraries(aws-iot-fleetwise-edge + -Xlinker + -Map=aws-iot-fleetwise-edge.map + ) +elseif(FWE_BUILD_ANDROID_SHARED_LIBRARY) + add_library(aws-iot-fleetwise-edge SHARED + src/android_shared_library.cpp + ) + target_link_libraries(aws-iot-fleetwise-edge + log + android + ) +else() + add_library(aws-iot-fleetwise-edge + $ + ) + set_target_properties(aws-iot-fleetwise-edge + PROPERTIES PUBLIC_HEADER "${HEADER_FILES};${PROTO_HDRS}" + ) + install(TARGETS aws-iot-fleetwise-edge fwe fwe-proto + EXPORT AwsIotFweTargets + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + PUBLIC_HEADER DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/aws/iotfleetwise" + ) + install(EXPORT AwsIotFweTargets + FILE AwsIotFweTargets.cmake + NAMESPACE AwsIotFwe:: + DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/AwsIotFwe + ) + include(CMakePackageConfigHelpers) + configure_package_config_file(cmake/AwsIotFweConfig.cmake.in + ${CMAKE_CURRENT_BINARY_DIR}/AwsIotFweConfig.cmake + INSTALL_DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/AwsIotFwe + ) + write_basic_package_version_file( + ${CMAKE_CURRENT_BINARY_DIR}/AwsIotFweConfigVersion.cmake + VERSION ${PROJECT_VERSION} + COMPATIBILITY SameMajorVersion + ) + install( + FILES ${CMAKE_CURRENT_BINARY_DIR}/AwsIotFweConfig.cmake + ${CMAKE_CURRENT_BINARY_DIR}/AwsIotFweConfigVersion.cmake + DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/AwsIotFwe + ) +endif() +target_link_libraries(aws-iot-fleetwise-edge + fwe + fwe-proto +) +set_target_properties(aws-iot-fleetwise-edge fwe fwe-proto + PROPERTIES POSITION_INDEPENDENT_CODE ON +) + +# Unit tests +if(${BUILD_TESTING}) + file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/test/unit/support/static-config-ok.json DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) + file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/test/unit/support/static-config-corrupt.json DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) + file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/test/unit/support/static-config-inline-creds.json DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) + find_package(benchmark REQUIRED) + find_package(GTest REQUIRED) + find_library(GMOCK_LIB NAMES gmock) + foreach(TEST_FILE ${TEST_FILES}) + get_filename_component(TEST_NAME ${TEST_FILE} NAME_WE) + set(TEST_SRC ${TEST_FILE}) + set(TEST_LIBS + fwe + fwe-proto + ) + if(${TEST_FILE} IN_LIST BENCHMARK_FILES) + set(TEST_LIBS ${TEST_LIBS} benchmark::benchmark) + else() + set(TEST_SRC ${TEST_SRC} test/unit/support/main.cpp) + set(TEST_LIBS ${TEST_LIBS} ${GMOCK_LIB} GTest::GTest) + endif() + add_executable(${TEST_NAME} ${TEST_SRC}) + target_include_directories(${TEST_NAME} PUBLIC + src + test/unit/support + ${CMAKE_CURRENT_BINARY_DIR} + ) + target_link_libraries(${TEST_NAME} ${TEST_LIBS}) + if(${TEST_FILE} IN_LIST FAKETIME_FILES) + if(FWE_TEST_FAKETIME) + add_unit_test_with_faketime(${TEST_NAME}) + endif() + elseif(${TEST_FILE} IN_LIST BENCHMARK_FILES) + add_test(NAME ${TEST_NAME} COMMAND ${TEST_NAME} --benchmark_out=benchmark-report-${TEST_NAME}.txt --benchmark_out_format=console) + else() + add_unit_test(${TEST_NAME}) + add_valgrind_test(${TEST_NAME}) + endif() + endforeach() +endif() diff --git a/README.md b/README.md index 44b702ad..da52b2ac 100644 --- a/README.md +++ b/README.md @@ -107,7 +107,7 @@ See [SECURITY](./SECURITY.md) for more information FWE depends on the following open source libraries. Refer to the corresponding links for more information. -- [AWS SDK for C++: v1.11.111](https://github.com/aws/aws-sdk-cpp) +- [AWS SDK for C++: v1.11.148](https://github.com/aws/aws-sdk-cpp) - [Curl: v7.58.0](https://github.com/curl/curl) - [OpenSSL: v1.1.1](https://github.com/openssl/openssl) - [zlib: v1.2.11](https://github.com/madler/zlib) @@ -121,7 +121,7 @@ information. Optional: The following dependencies are only required when the option `FWE_FEATURE_GREENGRASSV2` is enabled. -- [AWS IoT Device SDK for C++ v2: v1.22.0](https://github.com/aws/aws-iot-device-sdk-cpp-v2) +- [AWS IoT Device SDK for C++ v2: v1.29.0](https://github.com/aws/aws-iot-device-sdk-cpp-v2) See [LICENSE](./LICENSE) for more information. diff --git a/THIRD-PARTY-LICENSES b/THIRD-PARTY-LICENSES index 1fcd86be..9f44e06a 100644 --- a/THIRD-PARTY-LICENSES +++ b/THIRD-PARTY-LICENSES @@ -1,8 +1,8 @@ The Reference Implementation for AWS IoT FleetWise includes the following third-party software/licensing: -** AWS SDK for C++: v1.11.111 - https://github.com/aws/aws-sdk-cpp -** AWS IoT Device SDK for C++ v2: v1.22.0 - https://github.com/aws/aws-iot-device-sdk-cpp-v2 +** AWS SDK for C++: v1.11.148 - https://github.com/aws/aws-sdk-cpp +** AWS IoT Device SDK for C++ v2: v1.29.0 - https://github.com/aws/aws-iot-device-sdk-cpp-v2 ** Google Benchmark: v1.6.1 - https://github.com/google/benchmark ** OpenSSL: v1.1.1 - https://github.com/openssl/openssl diff --git a/cmake/AwsIotFweConfig.cmake.in b/cmake/AwsIotFweConfig.cmake.in new file mode 100644 index 00000000..ca016e4d --- /dev/null +++ b/cmake/AwsIotFweConfig.cmake.in @@ -0,0 +1,18 @@ +include(CMakeFindDependencyMacro) + +@PACKAGE_INIT@ + +if(@FWE_STATIC_LINK@) + set(Boost_USE_STATIC_LIBS ON) + find_dependency(Boost REQUIRED COMPONENTS @REQUIRED_BOOST_COMPONENTS@) + find_dependency(AWSSDK REQUIRED COMPONENTS @REQUIRED_AWS_SDK_COMPONENTS@) + find_dependency(ZLIB REQUIRED) +endif() + +if(NOT TARGET aws-iot-fleetwise-edge) + include("${CMAKE_CURRENT_LIST_DIR}/AwsIotFweTargets.cmake") + set_target_properties(AwsIotFwe::aws-iot-fleetwise-edge PROPERTIES IMPORTED_GLOBAL TRUE) + add_library(AwsIotFwe::AwsIotFwe ALIAS AwsIotFwe::aws-iot-fleetwise-edge) +endif() + +set(AwsIotFwe_INCLUDE_DIR "@CMAKE_INSTALL_PREFIX@/@CMAKE_INSTALL_INCLUDEDIR@") diff --git a/cmake/compiler_gcc.cmake b/cmake/compiler_gcc.cmake index 00888731..ecd5bdad 100644 --- a/cmake/compiler_gcc.cmake +++ b/cmake/compiler_gcc.cmake @@ -27,11 +27,6 @@ add_compile_options( $<$:-DDEBUG> ) -# For UNIX like systems, set the Linux macro -if(UNIX) - add_compile_options("-DIOTFLEETWISE_LINUX") -endif() - # Add compiler flags for security. if(FWE_SECURITY_COMPILE_FLAGS) add_compile_options("-fstack-protector") diff --git a/cmake/doxygen.cmake b/cmake/doxygen.cmake index 552ce167..b73b2e9c 100644 --- a/cmake/doxygen.cmake +++ b/cmake/doxygen.cmake @@ -6,7 +6,6 @@ if(DOXYGEN_FOUND) message(STATUS "Building documentation") set(DOXYGEN_DOT_IMAGE_FORMAT svg) - set(DOXYGEN_EXCLUDE_PATTERNS "*/test/*") set(DOXYGEN_EXPAND_ONLY_PREDEF YES) set(DOXYGEN_EXTRACT_ALL YES) set(DOXYGEN_EXTRACT_PRIVATE YES) @@ -24,7 +23,6 @@ if(DOXYGEN_FOUND) set(DOXYGEN_JAVADOC_AUTOBRIEF YES) set(DOXYGEN_MACRO_EXPANSION YES) set(DOXYGEN_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/docs") - set(DOXYGEN_PREDEFINED IOTFLEETWISE_LINUX) set(DOXYGEN_PROJECT_NAME "Reference Implementation for AWS IoT FleetWise") set(DOXYGEN_QUIET YES) set(DOXYGEN_SOURCE_BROWSER YES) diff --git a/cmake/protobufs.cmake b/cmake/protobufs.cmake deleted file mode 100644 index 6f27c7b1..00000000 --- a/cmake/protobufs.cmake +++ /dev/null @@ -1,93 +0,0 @@ -# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. - -# This generates protobuf library for proto files in another package -# Consumers need only declare the libraryAliasName in their target_link_libraries - -find_package(Protobuf REQUIRED) - -set(CMAKE_CXX_CLANG_TIDY "") - -# These are the library names and aliases -set(libraryTargetName iotfleetwise.proto) -set(libraryAliasName IoTFleetWise::Proto) - - -# This directory will contain proto files and autogenerated source and headers -set(protoDir ${CMAKE_BINARY_DIR}/proto/) - -set(schemasRoot "${CMAKE_CURRENT_SOURCE_DIR}/interfaces/protobuf") -message(STATUS "Schema root is: ${schemasRoot}") - -# Make a list of all the proto files -file(GLOB_RECURSE protoFilesExternal FOLLOW_SYMLINKS ${schemasRoot}/*.proto) - -# Copy the proto files to a proto directory in the build tree. Do this because -# the file paths we have are symlinked file paths and can't easily be made -# relative to build path for the protoc to work. -# These will be symlinks -file(COPY ${protoFilesExternal} DESTINATION ${protoDir}) - -foreach(protoFileName ${protoFilesExternal}) - get_filename_component(protoFile ${protoFileName} NAME) - - message(STATUS "File name of proto is: ${protoFile}") - - if(protoFile) - message(STATUS "Protobuf file found.") - else() - message(FATAL_ERROR "Protobuf file not found.") - endif() - - # Replace .proto -> .pb.cc - string(REGEX REPLACE "[.]proto$" ".pb.cc" outputSource ${protoFile}) - string(PREPEND outputSource ${protoDir}) - # Replace .proto -> .pb.h - string(REGEX REPLACE "[.]proto$" ".pb.h" outputHeader ${protoFile}) - string(PREPEND outputHeader ${protoDir}) - - # At this point we have a list of headers and source files with a full paths - add_custom_command( - DEPENDS ${protoFileName} - OUTPUT ${outputSource} ${outputHeader} - COMMAND protoc -I=${protoDir} --cpp_out=${protoDir} ${protoFile} - WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} - COMMENT "Generating protobuf source for ${protoFile}" - ) - - message(STATUS "Output source: ${outputSource}") - message(STATUS "Output header: ${outputHeader}") - - list(APPEND outputSourcesList ${outputSource}) - list(APPEND outputHeadersList ${outputHeader}) -endforeach() - -# Ignore warnings due to this issue https://github.com/protocolbuffers/protobuf/pull/7913 -# Fixed in protobuf v3.15.5 -set_source_files_properties(${outputSourcesList} PROPERTIES COMPILE_FLAGS -Wno-array-bounds) - - -# create a target that includes some_file, this gives us a name that we can use later -add_custom_target(protoGenTarget DEPENDS ${outputSourcesList} ${outputHeadersList}) - -add_library( - ${libraryTargetName} - ${outputSourcesList} -) - -# This links the protobuf library we are creating with -add_dependencies(${libraryTargetName} protoGenTarget) - -target_link_libraries( - ${libraryTargetName} - PUBLIC - protobuf::libprotobuf -) - -target_include_directories( - ${libraryTargetName} - PUBLIC - ${protoDir} -) - -# Export the alias library that will be consumed by dependencies -add_library(${libraryAliasName} ALIAS ${libraryTargetName}) diff --git a/cmake/snappy.cmake b/cmake/snappy.cmake deleted file mode 100644 index 6a1ba405..00000000 --- a/cmake/snappy.cmake +++ /dev/null @@ -1,54 +0,0 @@ -# -# Tries to find Snappy headers and libraries. -# -# Usage of this module as follows: -# -# find_package(Snappy) -# -# Variables used by this module: -# -# SNAPPY_ROOT_DIR Set this variable to the root installation of -# Snappy if the module has problems finding -# the proper installation path. -# -# Variables defined by this module: -# -# SNAPPY_LIBRARIES The Snappy libraries -# SNAPPY_INCLUDE_DIR The location of Snappy headers - -# Find Snappy Library -find_package(Snappy REQUIRED) - -# Set Library Alias -set(SNAPPY_PKG libsnappy) - -# find a directory containing the NAMES -find_path( - SNAPPY_INCLUDE_DIR - NAMES snappy.h - HINTS ${SNAPPY_ROOT_DIR}/include) - -message(STATUS "Snappy Libray Found") - -# Search for Custom Library Location -find_library( - SNAPPY_LIBRARIES - NAMES snappy - HINTS ${SNAPPY_ROOT_DIR}/lib -) - - -include(FindPackageHandleStandardArgs) - -# Finds the package(s), package(s) are considered found if all variables listed contain -# valid results, e.g. valid file paths. -find_package_handle_standard_args( - Snappy DEFAULT_MSG - SNAPPY_LIBRARIES - SNAPPY_INCLUDE_DIR -) - -message(STATUS "SNAPPY_LIBRARY: ${SNAPPY_LIBRARIES}") -message(STATUS "SNAPPY_INCLUDE_DIR: ${SNAPPY_INCLUDE_DIR}") - -include_directories(${SNAPPY_INCLUDE_DIR}) diff --git a/src/datamanagement/custom/README.md b/docs/custom-data-source.md similarity index 100% rename from src/datamanagement/custom/README.md rename to docs/custom-data-source.md diff --git a/docs/dev-guide/edge-agent-dev-guide-nxp-s32g.md b/docs/dev-guide/edge-agent-dev-guide-nxp-s32g.md index 1384748e..47a36d35 100644 --- a/docs/dev-guide/edge-agent-dev-guide-nxp-s32g.md +++ b/docs/dev-guide/edge-agent-dev-guide-nxp-s32g.md @@ -14,9 +14,9 @@ This section describes how to get started on an NXP S32G-VNP-RDB2 board. ```bash cd ~/aws-iot-fleetwise-edge \ - && sudo -H ./tools/install-deps-cross-arm64.sh \ - && rm -rf build \ - && ./tools/build-fwe-cross-arm64.sh + && sudo -H ./tools/install-deps-cross-arm64.sh \ + && rm -rf build \ + && ./tools/build-fwe-cross-arm64.sh ``` - **Internet Router with Ethernet:** The S32G-VNP-RDB2 must be connected to an internet router via @@ -36,14 +36,14 @@ required by FWE, an updated version of the `canutils` package and a `systemd` se ```bash cd ~/aws-iot-fleetwise-edge \ - && sudo ./tools/install-deps-yocto.sh + && sudo ./tools/install-deps-yocto.sh ``` 1. Run the following to create a build folder and setup the Yocto project: ```bash mkdir -p ~/yocto-build && cd ~/yocto-build \ - && ~/aws-iot-fleetwise-edge/tools/setup-yocto-s32g.sh + && ~/aws-iot-fleetwise-edge/tools/setup-yocto-s32g.sh ``` 1. Run the following to run `bitbake` to create the SD-card image and compress it. This can take @@ -52,8 +52,8 @@ required by FWE, an updated version of the `canutils` package and a `systemd` se ```bash source sources/poky/oe-init-build-env build_s32g274ardb2ubuntu \ - && bitbake fsl-image-ubuntu \ - && gzip -fk tmp/deploy/images/s32g274ardb2/fsl-image-ubuntu-s32g274ardb2.sdcard + && bitbake fsl-image-ubuntu \ + && gzip -fk tmp/deploy/images/s32g274ardb2/fsl-image-ubuntu-s32g274ardb2.sdcard ``` 1. Run the following _on your local machine_ to download the compressed SD-card image: @@ -96,26 +96,28 @@ above), to create an IoT Thing and provision credentials for it. Your Edge Agent configuration files will be packaged into a ZIP file ready to be deployed to the board. ```bash -mkdir -p ~/aws-iot-fleetwise-deploy && cd ~/aws-iot-fleetwise-deploy \ +mkdir -p ~/aws-iot-fleetwise-deploy \ +&& cd ~/aws-iot-fleetwise-deploy \ && cp -r ~/aws-iot-fleetwise-edge/tools . \ -&& mkdir -p build/src/executionmanagement \ -&& cp ~/aws-iot-fleetwise-edge/build/src/executionmanagement/aws-iot-fleetwise-edge \ - build/src/executionmanagement/ \ -&& mkdir -p config && cd config \ +&& mkdir -p build \ +&& cp ~/aws-iot-fleetwise-edge/build/aws-iot-fleetwise-edge build \ +&& mkdir -p config \ +&& cd config \ && ../tools/provision.sh \ - --vehicle-name fwdemo-s32g \ - --certificate-pem-outfile certificate.pem \ - --private-key-outfile private-key.key \ - --endpoint-url-outfile endpoint.txt \ - --vehicle-name-outfile vehicle-name.txt \ + --vehicle-name fwdemo-s32g \ + --certificate-pem-outfile certificate.pem \ + --private-key-outfile private-key.key \ + --endpoint-url-outfile endpoint.txt \ + --vehicle-name-outfile vehicle-name.txt \ && ../tools/configure-fwe.sh \ - --input-config-file ~/aws-iot-fleetwise-edge/configuration/static-config.json \ - --output-config-file config-0.json \ - --log-color Yes \ - --vehicle-name `cat vehicle-name.txt` \ - --endpoint-url `cat endpoint.txt` \ - --can-bus0 can0 \ -&& cd .. && zip -r aws-iot-fleetwise-deploy.zip . + --input-config-file ~/aws-iot-fleetwise-edge/configuration/static-config.json \ + --output-config-file config-0.json \ + --log-color Yes \ + --vehicle-name `cat vehicle-name.txt` \ + --endpoint-url `cat endpoint.txt` \ + --can-bus0 can0 \ +&& cd .. \ +&& zip -r aws-iot-fleetwise-deploy.zip . ``` ## Deploy Edge Agent on NXP S32G board @@ -139,11 +141,12 @@ mkdir -p ~/aws-iot-fleetwise-deploy && cd ~/aws-iot-fleetwise-deploy \ your Edge Agent as a service: ```bash - mkdir -p ~/aws-iot-fleetwise-deploy && cd ~/aws-iot-fleetwise-deploy \ - && unzip -o ~/aws-iot-fleetwise-deploy.zip \ - && sudo mkdir -p /etc/aws-iot-fleetwise \ - && sudo cp config/* /etc/aws-iot-fleetwise \ - && sudo ./tools/install-fwe.sh + mkdir -p ~/aws-iot-fleetwise-deploy \ + && cd ~/aws-iot-fleetwise-deploy \ + && unzip -o ~/aws-iot-fleetwise-deploy.zip \ + && sudo mkdir -p /etc/aws-iot-fleetwise \ + && sudo cp config/* /etc/aws-iot-fleetwise \ + && sudo ./tools/install-fwe.sh ``` 1. Run the following **_on the S32G_** to view and follow the log (press CTRL+C to exit): @@ -159,5 +162,19 @@ mkdir -p ~/aws-iot-fleetwise-deploy && cd ~/aws-iot-fleetwise-deploy \ ```bash cd ~/aws-iot-fleetwise-edge/tools/cloud \ - && ./demo.sh --vehicle-name fwdemo-s32g --campaign-file campaign-obd-heartbeat.json + && ./demo.sh --vehicle-name fwdemo-s32g --campaign-file campaign-obd-heartbeat.json ``` + +## Clean up + +Run the following _on the development machine_ to clean up resources created by the `provision.sh` +and `demo.sh` scripts. **Note:** The Amazon Timestream resources are not deleted. + +```bash +cd ~/aws-iot-fleetwise-edge/tools/cloud \ +&& clean-up.sh \ +&& ../provision.sh \ + --vehicle-name fwdemo-s32g \ + --region us-east-1 \ + --only-clean-up +``` diff --git a/docs/dev-guide/edge-agent-dev-guide-renesas-rcar-s4.md b/docs/dev-guide/edge-agent-dev-guide-renesas-rcar-s4.md index 65146cfb..f466fc5d 100644 --- a/docs/dev-guide/edge-agent-dev-guide-renesas-rcar-s4.md +++ b/docs/dev-guide/edge-agent-dev-guide-renesas-rcar-s4.md @@ -26,8 +26,8 @@ This section describes how to get started on a Renesas ```bash cd ~/aws-iot-fleetwise-edge sudo -H ./tools/install-deps-cross-arm64.sh \ - && rm -rf build \ - && ./tools/build-fwe-cross-arm64.sh + && rm -rf build \ + && ./tools/build-fwe-cross-arm64.sh ``` - **Internet Router with Ethernet:** The R-Car S4 Spider board must be connected to an internet @@ -49,8 +49,8 @@ on the Ubuntu variant of the Renesas Linux BSP version 5.10.41. 1. Run the following to build SD-card image: ```bash - cd ~/aws-iot-fleetwise-edge \ - && sudo ./tools/renesas-rcar-s4/make-rootfs.sh 20.04.5 spider -sd + cd ~/aws-iot-fleetwise-edge \ + && sudo ./tools/renesas-rcar-s4/make-rootfs.sh 20.04.5 spider -sd ``` ## Flash the SD-Card Image @@ -58,7 +58,7 @@ on the Ubuntu variant of the Renesas Linux BSP version 5.10.41. 1. Run the following to write the image to micro SD-card: ```bash - sudo dd if=./Ubuntu-20.04.5-rootfs-image-rcar-spider-sdcard.ext4 of=/dev/sdc bs=1M status=progress + sudo dd if=./Ubuntu-20.04.5-rootfs-image-rcar-spider-sdcard.ext4 of=/dev/sdc bs=1M status=progress ``` ## Specify Initial Board Configuration @@ -84,14 +84,14 @@ on the Ubuntu variant of the Renesas Linux BSP version 5.10.41. 1. Enter following settings to flash the micro SD-card data to board ```bash - setenv _booti 'booti 0x48080000 - 0x48000000' - setenv sd1 'setenv bootargs rw root=/dev/mmcblk0p1 rootwait ip=dhcp maxcpus=1' - setenv sd2 ext4load mmc 0:1 0x48080000 /boot/Image - setenv sd3 ext4load mmc 0:1 0x48000000 /boot/r8a779f0-spider.dtb - setenv sd 'run sd1; run sd2; run sd3; run _booti' - setenv bootcmd 'run sd' - saveenv - boot + setenv _booti 'booti 0x48080000 - 0x48000000' + setenv sd1 'setenv bootargs rw root=/dev/mmcblk0p1 rootwait ip=dhcp maxcpus=1' + setenv sd2 ext4load mmc 0:1 0x48080000 /boot/Image + setenv sd3 ext4load mmc 0:1 0x48000000 /boot/r8a779f0-spider.dtb + setenv sd 'run sd1; run sd2; run sd3; run _booti' + setenv bootcmd 'run sd' + saveenv + boot ``` 1. Connect to the R-Car S4 Spider board via SSH, entering password `rcar`: @@ -107,12 +107,13 @@ Edge Agent binary and its configuration files will be packaged into a ZIP file r to the board. ```bash -mkdir -p ~/aws-iot-fleetwise-deploy && cd ~/aws-iot-fleetwise-deploy \ +mkdir -p ~/aws-iot-fleetwise-deploy \ +&& cd ~/aws-iot-fleetwise-deploy \ && cp -r ~/aws-iot-fleetwise-edge/tools . \ -&& mkdir -p build/src/executionmanagement \ -&& cp ~/aws-iot-fleetwise-edge/build/src/executionmanagement/aws-iot-fleetwise-edge \ - build/src/executionmanagement/ \ -&& mkdir -p config && cd config \ +&& mkdir -p build \ +&& cp ~/aws-iot-fleetwise-edge/build/aws-iot-fleetwise-edge build \ +&& mkdir -p config \ +&& cd config \ && ../tools/provision.sh \ --vehicle-name fwdemo-rcars4 \ --certificate-pem-outfile certificate.pem \ @@ -126,7 +127,8 @@ mkdir -p ~/aws-iot-fleetwise-deploy && cd ~/aws-iot-fleetwise-deploy \ --vehicle-name `cat vehicle-name.txt` \ --endpoint-url `cat endpoint.txt` \ --can-bus0 vcan0 \ -&& cd .. && zip -r aws-iot-fleetwise-deploy.zip . +&& cd .. \ +&& zip -r aws-iot-fleetwise-deploy.zip . ``` ## Deploy Edge Agent on R-Car S4 Spider board @@ -150,14 +152,15 @@ mkdir -p ~/aws-iot-fleetwise-deploy && cd ~/aws-iot-fleetwise-deploy \ Spider board_** to install your Edge Agent as a service: ```bash - mkdir -p ~/aws-iot-fleetwise-deploy && cd ~/aws-iot-fleetwise-deploy \ - && unzip -o ~/aws-iot-fleetwise-deploy.zip \ - && sudo mkdir -p /etc/aws-iot-fleetwise \ - && sudo cp config/* /etc/aws-iot-fleetwise - - sudo ./tools/install-socketcan.sh - sed -i -e 's/^After/# After/' -e 's/^Wants/#Wants/' ./tools/cansim/cansim@.service - sudo -H ./tools/install-cansim.sh + mkdir -p ~/aws-iot-fleetwise-deploy \ + && cd ~/aws-iot-fleetwise-deploy \ + && unzip -o ~/aws-iot-fleetwise-deploy.zip \ + && sudo mkdir -p /etc/aws-iot-fleetwise \ + && sudo cp config/* /etc/aws-iot-fleetwise + + sudo ./tools/install-socketcan.sh + sed -i -e 's/^After/# After/' -e 's/^Wants/#Wants/' ./tools/cansim/cansim@.service + sudo -H ./tools/install-cansim.sh ``` 1. Run the following **_on the R-Car S4 Spider board_** to view and follow the log (press CTRL+C to @@ -177,3 +180,17 @@ mkdir -p ~/aws-iot-fleetwise-deploy && cd ~/aws-iot-fleetwise-deploy \ sudo -H ./install-deps.sh ./demo.sh --vehicle-name fwdemo-rcars4 --campaign-file campaign-obd-heartbeat.json ``` + +## Clean up + +Run the following _on the development machine_ to clean up resources created by the `provision.sh` +and `demo.sh` scripts. **Note:** The Amazon Timestream resources are not deleted. + +```bash +cd ~/aws-iot-fleetwise-edge/tools/cloud \ +&& clean-up.sh \ +&& ../provision.sh \ + --vehicle-name fwdemo-rcars4 \ + --region us-east-1 \ + --only-clean-up +``` diff --git a/docs/dev-guide/edge-agent-dev-guide.md b/docs/dev-guide/edge-agent-dev-guide.md index 5411ce72..0df0812a 100644 --- a/docs/dev-guide/edge-agent-dev-guide.md +++ b/docs/dev-guide/edge-agent-dev-guide.md @@ -87,7 +87,7 @@ FleetWise at a more detailed technical level, see the - [Prerequisites for quick start demo](#prerequisites-for-quick-start-demo) - [Deploy Edge Agent](#deploy-edge-agent) - [Use the AWS IoT FleetWise demo](#use-the-aws-iot-fleetwise-demo) -- [Explore collected data](#explore-collected-data) +- [Clean up resources](#clean-up-resources) ## Prerequisites for quick start demo @@ -126,109 +126,118 @@ vehicle model, register the virtual vehicle created in the previous section and collect data from it. 1. Open the AWS CloudShell: [Launch CloudShell](https://console.aws.amazon.com/cloudshell/home) -1. Copy and paste the following commands to clone the latest FWE software from GitHub, install the - dependencies of the demo script and enable latest IoT FleetWise commands in the AWS CLI. +1. Copy and paste the following commands to clone the latest FWE software from GitHub and install + the dependencies of the demo script. ```bash git clone https://github.com/aws/aws-iot-fleetwise-edge.git ~/aws-iot-fleetwise-edge \ - && cd ~/aws-iot-fleetwise-edge/tools/cloud \ - && pip3 install wrapt==1.10.0 plotly==5.3.1 pandas==1.3.5 cantools==36.4.0 boto3==1.18.60 fastparquet==0.8.1 + && cd ~/aws-iot-fleetwise-edge/tools/cloud \ + && sudo -H ./install-deps.sh ``` - If you are using the AWS CLI v<2.11.24, update the CLI by running: + The above command installs the following PIP packages: `wrapt plotly pandas cantools fastparquet` + +1. If you are using the AWS CLI with a version lower than v2.11.24, update the CLI by running: ```bash - curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip" - unzip awscliv2.zip - sudo ./aws/install --update - rm -rf ./aws* + curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip" \ + && unzip -q awscliv2.zip \ + && sudo ./aws/install --update \ + && rm -rf ./aws* ``` - The AWS IoT FleetWise demo script performs the following: - - - Registers your AWS account with AWS IoT FleetWise, if not already registered - - Creates Timestream database and table for collected data for Timestream campaigns, if not - already created - - Creates S3 bucket for collected data for S3 campaigns, if not already created - - Creates IAM role and policy required for the service to write data to the Timestream resources - - Creates a signal catalog, firstly based on `obd-nodes.json` to add standard OBD signals, and - secondly based on the DBC file `hscan.dbc` to add CAN signals in a flat signal list - - Creates a model manifest that references the signal catalog with all of the OBD and DBC signals - - Activates the model manifest - - Creates a decoder manifest linked to the model manifest using `obd-decoders.json` for decoding - OBD signals from the network interfaces defined in `network-interfaces.json` - - Imports the CAN signal decoding information from `hscan.dbc` to the decoder manifest - - Updates the decoder manifest to set the status as `ACTIVE` - - Creates a vehicle with a name equal to `fwdemo` which is the same as the name given to the - CloudFormation Stack name in the previous section - - Creates a fleet - - Associates the vehicle with the fleet - - Creates a campaign from `campaign-brake-event.json` that contains a condition-based collection - scheme to capture the engine torque and the brake pressure when the brake pressure is above - 7000, and targets the campaign at the fleet. - - Approves created campaign - - Waits until the campaign status is `HEALTHY`, which means the campaign has been deployed to the - fleet - - Waits 30 seconds and then downloads the collected data from Timestream - - Saves the data to an HTML file - - You can enable S3 upload destination by passing the option `--enable-s3-upload`. You can pass - your bucket name as option `--bucket-name`. The demo script will additionally: - - - Create S3 bucket for collected data for S3 campaigns, if not already created - - Create IAM roles and policies required for the service to write data to the S3 resources - - Creates 2 additional campaigns from `campaign-brake-event.json`. One campaign will upload data - to to S3 in JSON format, one to S3 in parquet format - - Wait 20 minutes for the data to propagate to S3 and then downloads it - - Save the data to an HTML file - - This script will not delete Timestream and S3 resources. - 1. Run the demo script: ```bash ./demo.sh --vehicle-name fwdemo ``` - 1. (Optional) To enable S3 upload, append the option `--enable-s3-upload` - - ```bash - ./demo.sh --vehicle-name fwdemo --enable-s3-upload - ``` - - 1. (Optional) If you selected a `FleetSize` of greater than one above, append the option - `--fleet-size `, where `` is the number selected. - 1. (Optional) If you changed `IoTCoreRegion` above, append the option `--region `, where - `` is the selected region. - 1. (Optional) If you changed `Stack name` when creating the stack above, pass the new stack name - to the `--vehicle-name` option. - - For example, if you chose to create two AWS IoT things in Europe (Frankfurt) with a stack named - `myfwdemo`, you must pass those values when calling `demo.sh`: - - ```bash - ./demo.sh --vehicle-name myfwdemo --fleet-size 2 --region eu-central-1 - ``` - -1. When the script completes, a path to an HTML file is given in the format - `/home/cloudshell-user/aws-iot-fleetwise-edge/fwdemo-*.html`. Copy the path, then click on the + - (Optional) To enable S3 upload, append the option `--enable-s3-upload` + + ```bash + ./demo.sh --vehicle-name fwdemo --enable-s3-upload + ``` + + - (Optional) If you selected a `FleetSize` of greater than one above, append the option + `--fleet-size `, where `` is the number selected. + - (Optional) If you changed `IoTCoreRegion` above, append the option `--region `, where + `` is the selected region. + - (Optional) If you changed `Stack name` when creating the stack above, pass the new stack name + to the `--vehicle-name` option. + + For example, if you chose to create two AWS IoT things in Europe (Frankfurt) with a stack named + `myfwdemo`, you must pass those values when calling `demo.sh`: + + ```bash + ./demo.sh --vehicle-name myfwdemo --fleet-size 2 --region eu-central-1 + ``` + + The demo script: + + 1. Registers your AWS account with AWS IoT FleetWise, if not already registered. + 1. Creates an Amazon Timestream database and table. + 1. Creates IAM role and policy required for the service to write data to Amazon Timestream. + 1. Creates a signal catalog, firstly based on `obd-nodes.json` to add standard OBD signals, and + secondly based on the DBC file `hscan.dbc` to add CAN signals in a flat signal list. + 1. Creates a model manifest that references the signal catalog with all of the OBD and DBC + signals. + 1. Activates the model manifest. + 1. Creates a decoder manifest linked to the model manifest using `obd-decoders.json` for decoding + OBD signals from the network interfaces defined in `network-interfaces.json`. + 1. Imports the CAN signal decoding information from `hscan.dbc` to the decoder manifest. + 1. Updates the decoder manifest to set the status as `ACTIVE`. + 1. Creates a vehicle with a name equal to `fwdemo` which is the same as the name given to the + CloudFormation Stack name in the previous section. + 1. Creates a fleet. + 1. Associates the vehicle with the fleet. + 1. Creates a campaign from `campaign-brake-event.json` that contains a condition-based collection + scheme to capture the engine torque and the brake pressure when the brake pressure is above + 7000, and targets the campaign at the fleet. + 1. Approves the campaign. + 1. Waits until the campaign status is `HEALTHY`, which means the campaign has been deployed to + the fleet. + 1. Waits 30 seconds and then downloads the collected data from Amazon Timestream. + 1. Saves the data to an HTML file. + + If S3 upload is enabled, the demo script will additionally: + + 1. Create an S3 bucket with a bucket policy that allows AWS IoT FleetWise to write data to the + bucket. + 1. Creates 2 additional campaigns from `campaign-brake-event.json`. One campaign will upload data + to to S3 in JSON format, one to S3 in parquet format. + 1. Wait 20 minutes for the data to propagate to S3 and then download it. + 1. Save the data to an HTML file. + + This script will not delete Amazon Timestream or S3 resources. + +1. When the script completes, a path to an HTML file is given. Copy the path, then click on the Actions drop down menu in the top-right corner of the CloudShell window and choose **Download file**. Paste the path to the file, choose **Download**, and open the downloaded file in your browser. - If you enabled S3 upload, results are stored in - `/home/cloudshell-user/aws-iot-fleetwise-edge/fwdemo-*-s3-json-result.html` and - `/home/cloudshell-user/aws-iot-fleetwise-edge/fwdemo-*-s3-parquet-result.html` - -## Explore collected data - 1. To explore the collected data, you can click and drag to zoom in. The red line shows the simulated brake pressure signal. As you can see that when hard braking events occur (value above 7000), collection is triggered and the engine torque signal data is collected. - 1. Alternatively, if your AWS account is enrolled with Amazon QuickSight or Grafana, you may use - them to browse the data from Amazon Timestream directly. -![](./images/collected_data_plot.png) + Alternatively, if your AWS account is enrolled with Amazon QuickSight or Amazon Managed Grafana, + you may use them to browse the data from Amazon Timestream directly. + + ![](./images/collected_data_plot.png) + +## Clean up resources + +Copy and paste the following commands to AWS CloudShell to clean up resources created by the +`provision.sh` and `demo.sh` scripts. **Note:** The Amazon Timestream and S3 resources are not +deleted. + +```bash +cd ~/aws-iot-fleetwise-edge/tools/cloud \ +&& clean-up.sh \ +&& ../provision.sh \ + --vehicle-name fwdemo \ + --region us-east-1 \ + --only-clean-up +``` # Getting started guide @@ -252,6 +261,7 @@ higher level that does not require use of a development machine, see the - [Compile your Edge Agent](#compile-your-edge-agent) - [Deploy your Edge Agent](#deploy-your-edge-agent) - [Run the AWS IoT FleetWise demo script](#run-the-aws-iot-fleetwise-demo-script) + - [Clean up](#clean-up) - [Getting started on an NXP S32G board](./edge-agent-dev-guide-nxp-s32g.md) - [Prerequisites for NXP S32G](./edge-agent-dev-guide-nxp-s32g.md#prerequisites) - [Build an SD-Card Image](./edge-agent-dev-guide-nxp-s32g.md#build-an-sd-card-image) @@ -260,6 +270,7 @@ higher level that does not require use of a development machine, see the - [Provision AWS IoT Credentials](./edge-agent-dev-guide-nxp-s32g.md#provision-aws-iot-credentials) - [Deploy Edge Agent on NXP S32G board](./edge-agent-dev-guide-nxp-s32g.md#deploy-edge-agent-on-nxp-s32g-board) - [Collect OBD Data](./edge-agent-dev-guide-nxp-s32g.md#collect-obd-data) + - [Clean up](./edge-agent-dev-guide-nxp-s32g.md#clean-up) - [Getting started on a Renesas R-Car S4 board](./edge-agent-dev-guide-renesas-rcar-s4.md) - [Prerequisites](./edge-agent-dev-guide-renesas-rcar-s4.md#prerequisites) - [Build an SD-Card Image](./edge-agent-dev-guide-renesas-rcar-s4.md#build-an-sd-card-image) @@ -268,6 +279,7 @@ higher level that does not require use of a development machine, see the - [Provision AWS IoT Credentials](./edge-agent-dev-guide-renesas-rcar-s4.md#provision-aws-iot-credentials) - [Deploy Edge Agent on R-Car S4 Spider board](./edge-agent-dev-guide-renesas-rcar-s4.md#deploy-edge-agent-on-r-car-s4-spider-board) - [Collect OBD Data](./edge-agent-dev-guide-renesas-rcar-s4.md#collect-obd-data) + - [Clean up](./edge-agent-dev-guide-renesas-rcar-s4.md#clean-up) ## Getting started on a development machine @@ -313,7 +325,7 @@ launch an AWS EC2 Graviton (arm64) instance. Pricing for EC2 can be found, ```bash git clone https://github.com/aws/aws-iot-fleetwise-edge.git ~/aws-iot-fleetwise-edge \ - && cd ~/aws-iot-fleetwise-edge + && cd ~/aws-iot-fleetwise-edge ``` 1. Review, modify and supplement [the FWE source code](../../src/) to ensure it meets your use case @@ -321,7 +333,13 @@ launch an AWS EC2 Graviton (arm64) instance. Pricing for EC2 can be found, 1. Install the dependencies for FWE by running the commands below. - The commands below will: + ```bash + sudo -H ./tools/install-deps-native.sh \ + && sudo -H ./tools/install-socketcan.sh \ + && sudo -H ./tools/install-cansim.sh + ``` + + The commands above will: 1. Install the following Ubuntu packages: `libssl-dev libboost-system-dev libboost-log-dev libboost-thread-dev build-essential cmake unzip git wget curl zlib1g-dev libcurl4-openssl-dev libsnappy-dev default-jre libasio-dev`. @@ -331,17 +349,10 @@ launch an AWS EC2 Graviton (arm64) instance. Pricing for EC2 can be found, following: `can-isotp`. It also installs a systemd service called `setup-socketcan` that brings up the virtual SocketCAN interface `vcan0` at startup. 1. Install the following Ubuntu packages: `python3 python3-pip`. It then installs the following - PIP packages: - `wrapt cantools prompt_toolkit python-can can-isotp matplotlib boto3 fastparquet`. It also + PIP packages: `wrapt cantools prompt_toolkit python-can can-isotp matplotlib`. It also installs a systemd service called `cansim` that periodically transmits data on the virtual SocketCAN bus `vcan0` to simulate vehicle data. - ```bash - sudo -H ./tools/install-deps-native.sh \ - && sudo -H ./tools/install-socketcan.sh \ - && sudo -H ./tools/install-cansim.sh - ``` - 1. Run the following to compile your own Edge Agent: ```bash @@ -358,20 +369,20 @@ launch an AWS EC2 Graviton (arm64) instance. Pricing for EC2 can be found, ```bash sudo mkdir -p /etc/aws-iot-fleetwise \ - && sudo ./tools/provision.sh \ - --vehicle-name fwdemo-ec2 \ - --certificate-pem-outfile /etc/aws-iot-fleetwise/certificate.pem \ - --private-key-outfile /etc/aws-iot-fleetwise/private-key.key \ - --endpoint-url-outfile /etc/aws-iot-fleetwise/endpoint.txt \ - --vehicle-name-outfile /etc/aws-iot-fleetwise/vehicle-name.txt \ - && sudo ./tools/configure-fwe.sh \ - --input-config-file configuration/static-config.json \ - --output-config-file /etc/aws-iot-fleetwise/config-0.json \ - --log-color Yes \ - --vehicle-name `cat /etc/aws-iot-fleetwise/vehicle-name.txt` \ - --endpoint-url `cat /etc/aws-iot-fleetwise/endpoint.txt` \ - --can-bus0 vcan0 \ - && sudo ./tools/install-fwe.sh + && sudo ./tools/provision.sh \ + --vehicle-name fwdemo-ec2 \ + --certificate-pem-outfile /etc/aws-iot-fleetwise/certificate.pem \ + --private-key-outfile /etc/aws-iot-fleetwise/private-key.key \ + --endpoint-url-outfile /etc/aws-iot-fleetwise/endpoint.txt \ + --vehicle-name-outfile /etc/aws-iot-fleetwise/vehicle-name.txt \ + && sudo ./tools/configure-fwe.sh \ + --input-config-file configuration/static-config.json \ + --output-config-file /etc/aws-iot-fleetwise/config-0.json \ + --log-color Yes \ + --vehicle-name `cat /etc/aws-iot-fleetwise/vehicle-name.txt` \ + --endpoint-url `cat /etc/aws-iot-fleetwise/endpoint.txt` \ + --can-bus0 vcan0 \ + && sudo ./tools/install-fwe.sh ``` 1. At this point your Edge Agent is running and periodically sending 'checkins' to AWS IoT @@ -392,27 +403,26 @@ launch an AWS EC2 Graviton (arm64) instance. Pricing for EC2 can be found, ### Run the AWS IoT FleetWise demo script The instructions below will register your AWS account for AWS IoT FleetWise, create a demonstration -vehicle model, register the virtual vehicle created in the previous section, and run a campaign to +vehicle model, register the virtual vehicle created in the previous section and run a campaign to collect data from it. -1. Run the following _on the development machine_ to install the dependencies of the AWS IoT - FleetWise demo script: - - 1. Following command installs the following Ubuntu packages: `python3 python3-pip`. It then - installs the following PIP packages: `wrapt plotly pandas cantools boto3 fastparquet` +1. Run the following _on the development machine_ to install the dependencies of the demo script: ```bash cd ~/aws-iot-fleetwise-edge/tools/cloud \ - && sudo -H ./install-deps.sh + && sudo -H ./install-deps.sh ``` - 1. If you are using the AWS CLI v<2.11.24, update the CLI by running: + The above command installs the following Ubuntu packages: `python3 python3-pip`. It then installs + the following PIP packages: `wrapt plotly pandas cantools fastparquet` + +1. If you are using the AWS CLI with a version lower than v2.11.24, update the CLI by running: ```bash - curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip" - unzip awscliv2.zip - sudo ./aws/install --update - rm -rf ./aws* + curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip" \ + && unzip -q awscliv2.zip \ + && sudo ./aws/install --update \ + && rm -rf ./aws* ``` 1. Run the following to explore the AWS IoT FleetWise CLI: @@ -427,73 +437,72 @@ collect data from it. ./demo.sh --vehicle-name fwdemo-ec2 ``` - 1. (Optional) To enable S3 upload, append the option `--enable-s3-upload`. You can pass your - bucket name as option `--bucket-name`. - - ```bash - ./demo.sh --vehicle-name fwdemo-ec2 --enable-s3-upload - ``` - - 1. (Optional) If you changed the `--region` option to `provision.sh` above, append the option - `--region `, where `` is the selected region. For example, if you chose to - create the AWS IoT thing in Europe (Frankfurt), you must configure `--region` to - `eu-central-1` in the demo.sh file. - - ```bash - ./demo.sh --vehicle-name fwdemo-ec2 --region eu-central-1 - ``` - - 1. The demo script: - 1. Registers your AWS account with AWS IoT FleetWise, if not already registered - 1. Creates Timestream database and table for collected data for Timestream campaigns, if not - already created - 1. Creates IAM roles and policies required for the service to write data to the Timestream - 1. Creates a signal catalog, firstly based on `obd-nodes.json` to add standard OBD signals, - and secondly based on the DBC file `hscan.dbc` to add CAN signals in a flat signal list - 1. Creates a model manifest that references the signal catalog with all of the OBD and DBC - signals - 1. Activates the model manifest - 1. Creates a decoder manifest linked to the model manifest using `obd-decoders.json` for - decoding OBD signals from the network interfaces defined in `network-interfaces.json` - 1. Imports the CAN signal decoding information from `hscan.dbc` to the decoder manifest - 1. Updates the decoder manifest to set the status as `ACTIVE` - 1. Creates a vehicle with a name equal to `fwdemo-ec2` which is the same as the name given to - the CloudFormation Stack name in the previous section - 1. Creates a fleet - 1. Associates the vehicle with the fleet - 1. Create a campaign from `campaign-brake-event.json` that contain a condition1.based - collection scheme to capture the engine torque and the brake pressure when the brake - pressure is above 7000, and targets the campaign at the fleet. - 1. Approves created campaign - 1. Waits until the campaign status is `HEALTHY`, which means the campaign has been deployed to - the fleet - 1. Waits 30 seconds and then downloads the collected data from Timestream - 1. Saves the data to an HTML file - - If you enabled S3 upload destination, the demo script will additionally: - - - Create S3 bucket for collected data for S3 campaigns, if not already created - - Create IAM roles and policies required for the service to write data to the S3 resources - - Creates 2 additional campaigns from `campaign-brake-event.json`. One campaign will upload data - to to S3 in JSON format, one to S3 in parquet format - - Wait 20 minutes for the data to propagate to S3 and then downloads it - - Save the data to an HTML file - - This script will not delete Timestream and S3 resources - -1. When the script completes, the path to the output HTML file is given. _On your local machine_, - use `scp` to download it, then open it in your web browser: + - (Optional) To enable S3 upload, append the option `--enable-s3-upload` + + ```bash + ./demo.sh --vehicle-name fwdemo-ec2 --enable-s3-upload + ``` + + - (Optional) If you changed the `--region` option to `provision.sh` above, append the option + `--region `, where `` is the selected region. For example, if you chose to + create the AWS IoT thing in Europe (Frankfurt), you must configure `--region` to `eu-central-1` + in the demo.sh file. + + ```bash + ./demo.sh --vehicle-name fwdemo-ec2 --region eu-central-1 + ``` + + The demo script: + + 1. Registers your AWS account with AWS IoT FleetWise, if not already registered. + 1. Creates an Amazon Timestream database and table. + 1. Creates IAM role and policy required for the service to write data to Amazon Timestream. + 1. Creates a signal catalog, firstly based on `obd-nodes.json` to add standard OBD signals, and + secondly based on the DBC file `hscan.dbc` to add CAN signals in a flat signal list. + 1. Creates a model manifest that references the signal catalog with all of the OBD and DBC + signals. + 1. Activates the model manifest. + 1. Creates a decoder manifest linked to the model manifest using `obd-decoders.json` for decoding + OBD signals from the network interfaces defined in `network-interfaces.json`. + 1. Imports the CAN signal decoding information from `hscan.dbc` to the decoder manifest. + 1. Updates the decoder manifest to set the status as `ACTIVE`. + 1. Creates a vehicle with a name equal to `fwdemo-ec2`, the same as the name passed to + `provision.sh`. + 1. Creates a fleet. + 1. Associates the vehicle with the fleet. + 1. Creates a campaign from `campaign-brake-event.json` that contains a condition-based collection + scheme to capture the engine torque and the brake pressure when the brake pressure is above + 7000, and targets the campaign at the fleet. + 1. Approves the campaign. + 1. Waits until the campaign status is `HEALTHY`, which means the campaign has been deployed to + the fleet. + 1. Waits 30 seconds and then downloads the collected data from Amazon Timestream. + 1. Saves the data to an HTML file. + + If S3 upload is enabled, the demo script will additionally: + + 1. Create an S3 bucket with a bucket policy that allows AWS IoT FleetWise to write data to the + bucket. + 1. Creates 2 additional campaigns from `campaign-brake-event.json`. One campaign will upload data + to to S3 in JSON format, one to S3 in parquet format. + 1. Wait 20 minutes for the data to propagate to S3 and then download it. + 1. Save the data to an HTML file. + + This script will not delete Amazon Timestream or S3 resources. + +1. When the script completes, a path to an HTML file is given. _On your local machine_, use `scp` to + download it, then open it in your web browser: ```bash scp -i ubuntu@: . ``` - To explore the collected data, you can click and drag on the graph to zoom in. The red line shows - the simulated brake pressure signal. As you can see that when hard braking events occur (value - above 7000), collection is triggered and the engine torque signal data is collected. +1. To explore the collected data, you can click and drag to zoom in. The red line shows the + simulated brake pressure signal. As you can see that when hard braking events occur (value above + 7000), collection is triggered and the engine torque signal data is collected. - Alternatively, if your AWS account is enrolled with QuickSight or Grafana, you may use them to - browse the data from Amazon Timestream directly. + Alternatively, if your AWS account is enrolled with Amazon QuickSight or Amazon Managed Grafana, + you may use them to browse the data from Amazon Timestream directly. ![](./images/collected_data_plot.png) @@ -526,6 +535,20 @@ collect data from it. ./demo.sh --vehicle-name fwdemo-ec2 --dbc-file --campaign-file --region eu-central-1 ``` +### Clean up + +Run the following _on the development machine_ to clean up resources created by the `provision.sh` +and `demo.sh` scripts. **Note:** The Amazon Timestream and S3 resources are not deleted. + +```bash +cd ~/aws-iot-fleetwise-edge/tools/cloud \ +&& clean-up.sh \ +&& ../provision.sh \ + --vehicle-name fwdemo-ec2 \ + --region us-east-1 \ + --only-clean-up +``` + ## Getting started on a NXP S32G board [Getting started on an NXP S32G board](./edge-agent-dev-guide-nxp-s32g.md) @@ -538,12 +561,11 @@ collect data from it. AWS IoT FleetWise is an AWS service that enables automakers to collect, store, organize, and monitor data from vehicles. Automakers need the ability to connect remotely to their fleet of vehicles and -collect vehicle ECU and sensor data. The following diagram illustrates a high-level architecture of -the system. AWS IoT FleetWise can be used by OEM engineers and data scientists to build vehicle -models that can be used to create custom data collection schemes. These data collection schemes -enable OEMs to optimize the data collection process by defining what signals to collect, how often -to collect them, and most importantly the trigger conditions, or events, that enable the collection -process. +collect vehicle ECU and sensor data. AWS IoT FleetWise can be used by OEM engineers and data +scientists to build vehicle models that can be used to create custom data collection schemes. These +data collection schemes enable OEMs to optimize the data collection process by defining what signals +to collect, how often to collect them, and most importantly the trigger conditions, or events, that +enable the collection process. This document reviews the architecture, operation, and key features of the Reference Implementation for AWS IoT FleetWise ("FWE"). @@ -650,7 +672,7 @@ as the conditions are met. Once a snapshot of the signal data is available, this the data to the offboard connectivity layer for further processing. The mechanism of data transmission between these two layers uses also a message queue with a predefined maximum size. -**Scheme Management** +**Collection Scheme Management** The Cloud control plane serves FWE with data collection scheme and decoder manifests. A decoder manifest is an artifact that defines the vehicle signal catalog and the way each signal can get @@ -670,41 +692,53 @@ data back to the Data Plane. This layer ensures that FWE has valid credentials to communicate securely with the Cloud APIs. -**Service Control** +**Execution Management** This layer owns the execution context of FWE within the target hardware in the vehicle. It manages the lifecycle of FWE, including the startup/shutdown sequences, along with acting as a local -monitoring module to ensure smooth execution of the service. The configuration of the service is -validated and loaded into the system in this layer of the software. +monitoring module to ensure smooth execution of the application. The configuration of the +application is validated and loaded into the system in this layer of the software. -### Overview of the software libraries +### Overview of the software modules -The code base of the Reference Implementation consists of 6 C++ libraries that implement the -functionalities of the layers described above. All these libraries are loaded in a POSIX user space -application running a single process. +The code base of the Reference Implementation consists of C++ modules that implement the +functionalities of the layers described above. All these modules are compiled into a POSIX user +space application running a single process. -![software libraries](./images/software_libraries.png) +**BSP Modules** -These libraries are: - -**BSP Library** +``` +CacheAndPersist +ClockHandler +ConsoleLogger +CPUUsageInfo +LoggingModule +MemoryUsageInfo +Thread +TraceModule +``` -This library includes a set of APIs and utility functions that the rest of the system use to : +These modules include a set of APIs and utility functions that the rest of the system use to: - Create and manage platform threads via a Thread and Signal APIs. - Create and manage timers and clocks via a Timer and Clock APIs. - Create loggers and metrics via Trace and logger APIs - Monitor the CPU, IO and RAM usage of a module via CPU/IO/RAM utility functions. - Persist data into a storage location via a Persistency API. This is used to persist and reload - collection schemes and decoder manifest during shutdown and startup of the service. + collection schemes and decoder manifest during shutdown and startup of the application. -This library is used uniformly by all the other libraries in the service. +These modules are used uniformly by all the other modules in the application. -**Vehicle Network Management Library** +**Vehicle Network Management Modules** -This library implements a set of wrappers around the in vehicle network communication protocols, and -realizes the function of vehicle data acquisition. In this version of the software, this library -includes : +``` +ISOTPOverCANReceiver +ISOTPOverCANSender +ISOTPOverCANSenderReceiver +``` + +These modules implement a set of wrappers around the in vehicle network communication protocols, and +realize the function of vehicle data acquisition. These modules include: - An implementation of the Linux CAN APIs, to acquire standard CAN Traffic from the network using raw sockets. @@ -713,25 +747,54 @@ includes : Each of the CAN Interfaces configured in the system will have a dedicated socket open. For the Diagnostic session i.e. to request OBD II PIDs, a separate socket is open for writing and reading -CAN Frames. This library abstracts away all the Socket and Linux networking details from the rest of -the system, and exposes only a circular buffer for each network interface configured, exposing the -raw CAN Frames to be consumed by the Data Inspection Library. +CAN Frames. These modules abstract away all the Socket and Linux networking details from the rest of +the system, and expose only a circular buffer for each network interface configured, exposing the +raw CAN Frames to be consumed by the Data Inspection Modules. -**Data Management Library** +**Data Management Modules** -This library implements all raw data decoders. It offers a Raw CAN Data Decoder (Standard CAN), an +``` +CANDecoder +CheckinAndPersistency +CollectionSchemeIngestion +CollectionSchemeIngestionList +CollectionSchemeManager +DataSenderManager +DataSenderManagerWorkerThread +DataSenderProtoWriter +DecoderDictionaryExtractor +DecoderManifestIngestion +Geohash +InspectionMatrixExtractor +OBDDataDecoder +Schema +``` + +These modules implement all raw data decoders. It offers a Raw CAN Data Decoder (Standard CAN), an OBD II (according to J1979 specification) decoder. Additionally, it implements the decoders for the Collection Schemes and Decoder manifests. -This library is used by the Data Inspection Library to normalize and decode the raw CAN Frames, and -by the Execution Management library to initiate the Collection Scheme and decoder Manifest decoding. +These modules are used by the Data Inspection Modules to normalize and decode the raw CAN Frames, +and by the Execution Management Modules to initiate the Collection Scheme and decoder Manifest +decoding. -The library also implements a serialization module to serialize the data FWE wants to send to the +These modules also implement a serialization module to serialize the data FWE wants to send to the data plane. The serialization schema is described below in the data model. -**Data Inspection Library** +**Data Inspection Modules** + +``` +CANDataConsumer +CANDataSource +CollectionInspectionEngine +CollectionInspectionWorkerThread +ExternalCANDataSource +GeohashFunctionNode +OBDOverCANECU +OBDOverCANModule +``` -This library implements a software module for each of the following: +These modules implement each of the following: - Consume, decode and normalize of the CAN Raw Frames according to the Decoder Manifest available in the system. @@ -741,55 +804,69 @@ This library implements a software module for each of the following: provided in the Inspection Matrix. - Cache of the needed signals in a signal history buffer. -Upon fulfillment of one or more trigger conditions, this library extracts from the signal history -buffer a data snapshot that's shared with the offboard connectivity library for further processing. -Again here a circular buffer is used as a transport mechanism of the data between the two libraries. +Upon fulfillment of one or more trigger conditions, these modules extract from the signal history +buffer a data snapshot that's shared with the offboard connectivity modules for further processing. +Again here a circular buffer is used as a transport mechanism of the data. -**Connectivity Library** +**Offboard Connectivity Modules** -This library implements the communication routines between FWE and the Cloud Control and Data Plane. +``` +AwsBootstrap +AwsGGChannel +AwsGGConnectivityModule +AwsIotChannel +AwsIotConnectivityModule +AwsSDKMemoryManager +PayloadManager +RetryThread +RemoteProfiler +``` + +These modules implement the communication routines between FWE and the cloud Control Plane and Data +Plane. Since all the communication between the device and the cloud occurs over a secure MQTT connection, -this library uses the AWS IoT Device SDK for C++ v2 as an MQTT client. It creates exactly one -connection to the MQTT broker. +these modules uses the AWS SDK for C++ as an MQTT client. It creates exactly one connection to the +MQTT broker. -This library then publishes the data snapshot through that connection (through a dedicated MQTT +These modules then publish the data snapshot through that connection (through a dedicated MQTT topic) and subscribes to the Scheme and decoder manifest topic (dedicated MQTT topic) for eventual -updates. On the subscribe side, this library notifies the rest of the system on the arrival of an +updates. On the subscribe side, these modules notifies the rest of the system on the arrival of an update of either the Scheme or the decoder manifests, which are enacted accordant in near real time. -**Execution Management Library** +**Execution Management Module** -This library implements the bootstrap sequence of FWE. It parses the provided configuration and -ensures that are the above libraries are provided with their corresponding settings. During -shutdown, it ensures that all the modules and corresponding system resources (threads, loggers, and -sockets) are stopped/closed properly. +``` +IoTFleetWiseEngine +``` -If there is no connectivity, or during shutdown of the service , this library persists the data -snapshots that are queued for sending to the cloud. Upon re-connection, this library will attempt to -send the data to the cloud. The persistency module in the BSP library ensures that the disk space is -not exhausted, so this library just invokes the persistency module when it wants to read or write -data to disk. +This module implements the bootstrap sequence of FWE. It parses the provided configuration and +ensures that are the other modules are provided with their corresponding settings. During shutdown, +it ensures that all the modules and corresponding system resources (threads, loggers, and sockets) +are stopped/closed properly. -The SystemD service communicates directly with this library as it runs the main thread of the -application. +If there is no connectivity, or during shutdown of the application, this module persists the data +snapshots that are queued for sending to the cloud. Upon re-connection, this module will attempt to +send the data to the cloud. The `CacheAndPersist` module ensures that the disk space is not +exhausted, so this module just invokes the persistency module when it wants to read or write data to +disk. ## Programming and Execution model FWE implements a concurrent and event-based multithreading system. -- **In the Vehicle Network Management library,** each CAN Network Interface spawns one thread to +- **In the Vehicle Network Management Modules,** each CAN Network Interface spawns one thread to take care of opening a Socket to the network device. E.g. if the device has 4 CAN Networks configured, there will be one thread per network mainly doing message reception from the network and insertion into the corresponding circular buffer in a lock free fashion. Each of the threads raises a notification via a listener interface in case the underlying socket communication is interrupted. These threads operate in a polling mode i.e. wait on socket read in non blocking mode. -- **In the Data Management Library**, one thread is created that manages the life cycle of the +- **In the Data Management Modules**, one thread is created that manages the life cycle of the collection Scheme and decode manifest. This thread is busy waiting and wakes up only during an arrival of new collection schemes/manifest from the cloud, or during the expiry of any of the collection schemes in the system. -- **In the Data Inspection Library**, each of the following modules spawn threads: +- **In the Data Inspection Modules**, each of the following modules spawn threads: - The inspection rule engine that does active inspection of the signals having one thread. - One thread for each CAN Network consuming the data and decoding/normalizing, working in polling mode, and using a lock free container to read and write CAN Messages. @@ -798,11 +875,11 @@ FWE implements a concurrent and event-based multithreading system. shutting down the sockets if a CAN IF is interrupted. - One thread that does run a Diagnostic session at a given time frequency (running J1979 PID and DTC request) -- **In the Connectivity Library**, most of the execution runs in the context of the main application +- **In the Connectivity Modules**, most of the execution runs in the context of the main application thread. Callbacks and notifications from the MQTT stack happen in the context of the AWS IoT Device SDK thread. This module intercepts the notifications and switches the thread context to one of FWE threads so that no real data processing happens in the MQTT connection thread. -- **In the Execution Management Library**, there are two threads +- **In the Execution Management Modules**, there are two threads - One thread which is managing all the bootstrap sequence and intercepting SystemD signals i.e. application main thread - One orchestration thread: This thread acts as a shadow for the MQTT thread i.e. swallows @@ -858,7 +935,7 @@ with the cloud services. The persistency operates on three types of documents: - Decoder Manifest Data: This data set is persisted during shutdown of FWE, and re-loaded upon startup. - Data Snapshots: This data set is persisted when there is no connectivity in the system. Upon the - next startup of the service, the data is reloaded and send if there is connectivity. + next startup of the application, the data is reloaded and send if there is connectivity. The persistency module operates on a fixed/configurable maximum partition size. If there is no space left, the module does not persist the data. @@ -937,7 +1014,7 @@ described below in the configuration section. Each log entry includes the follow | publishToCloudParameters | maxPublishMessageCount | Maximum messages that can be published to the cloud in one payload | integer | | | collectionSchemeManagementCheckinIntervalMs | Time interval between collection schemes checkins(in milliseconds) | integer | | mqttConnection | endpointUrl | AWS account's IoT device endpoint | string | -| | connectionType | The connection module type, it can be iotCore or iotGreengrassV2 | string | +| | connectionType | The connection module type. It can be `iotCore`, or `iotGreengrassV2` when `FWE_FEATURE_GREENGRASSV2` is enabled. | string | | | clientId | The ID that uniquely identifies this device in the AWS Region | string | | | collectionSchemeListTopic | Topic for subscribing to Collection Scheme | string | | | decoderManifestTopic | Topic for subscribing to Decoder Manifest | string | diff --git a/docs/dev-guide/images/software_libraries.png b/docs/dev-guide/images/software_libraries.png deleted file mode 100644 index 436b53e2257fae929e32894a25bae215189698e1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 73506 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 BF;M^j diff --git a/docs/iwave-g26-tutorial/iwave-g26-tutorial.md b/docs/iwave-g26-tutorial/iwave-g26-tutorial.md index d74b967a..05edf8d2 100644 --- a/docs/iwave-g26-tutorial/iwave-g26-tutorial.md +++ b/docs/iwave-g26-tutorial/iwave-g26-tutorial.md @@ -12,6 +12,7 @@ - [Step 5: Deploy Edge Agent](#step-5-deploy-edge-agent) - [Step 6: Connect the iWave G26 TCU to the vehicle](#step-6-connect-the-tcu-to-the-vehicle) - [Step 7: Collect OBD Data](#step-7-collect-obd-data) +- [Step 8: Clean up](#step-8-clean-up) **Copyright (C) Amazon Web Services, Inc. and/or its affiliates. All rights reserved.** @@ -81,9 +82,8 @@ to take action based on your use of AWS IoT FleetWise._** Follow the steps in this tutorial to set up and configure the iWave G26 TCU device hardware to work with your Edge Agent compiled from the FWE source code. You can then connect the device to a vehicle so that it collects vehicle J1979 OBD-II data and transfers it to the AWS IoT FleetWise service. To -additionally also collected GPS data more steps described here -[iwavegps](../../src/datamanagement/custom/example/iwavegps/README.md) are required. They require -the steps below to be executed first. +additionally also collected GPS data more steps described [here](./iwave-gps-setup.md) are required. +They require the steps below to be executed first. **Estimated Time**: 60 minutes @@ -394,26 +394,28 @@ following command. Your Edge Agent binary and its configuration files are packag that is ready for deployment to the TCU. ```bash -mkdir -p ~/aws-iot-fleetwise-deploy && cd ~/aws-iot-fleetwise-deploy \ - && cp -r ~/aws-iot-fleetwise-edge/tools . \ - && mkdir -p build/src/executionmanagement \ - && cp ~/aws-iot-fleetwise-edge/build/src/executionmanagement/aws-iot-fleetwise-edge \ - build/src/executionmanagement/ \ - && mkdir -p config && cd config \ - && ../tools/provision.sh \ - --vehicle-name fwdemo-g26 \ - --certificate-pem-outfile certificate.pem \ - --private-key-outfile private-key.key \ - --endpoint-url-outfile endpoint.txt \ - --vehicle-name-outfile vehicle-name.txt \ - && ../tools/configure-fwe.sh \ - --input-config-file ~/aws-iot-fleetwise-edge/configuration/static-config.json \ - --output-config-file config-0.json \ - --log-color Yes \ - --vehicle-name `cat vehicle-name.txt` \ - --endpoint-url `cat endpoint.txt` \ - --can-bus0 can0 \ - && cd .. && zip -r aws-iot-fleetwise-deploy.zip . +mkdir -p ~/aws-iot-fleetwise-deploy \ +&& cd ~/aws-iot-fleetwise-deploy \ +&& cp -r ~/aws-iot-fleetwise-edge/tools . \ +&& mkdir -p build \ +&& cp ~/aws-iot-fleetwise-edge/build/aws-iot-fleetwise-edge build \ +&& mkdir -p config \ +&& cd config \ +&& ../tools/provision.sh \ + --vehicle-name fwdemo-g26 \ + --certificate-pem-outfile certificate.pem \ + --private-key-outfile private-key.key \ + --endpoint-url-outfile endpoint.txt \ + --vehicle-name-outfile vehicle-name.txt \ +&& ../tools/configure-fwe.sh \ + --input-config-file ~/aws-iot-fleetwise-edge/configuration/static-config.json \ + --output-config-file config-0.json \ + --log-color Yes \ + --vehicle-name `cat vehicle-name.txt` \ + --endpoint-url `cat endpoint.txt` \ + --can-bus0 can0 \ +&& cd .. \ +&& zip -r aws-iot-fleetwise-deploy.zip . ``` ## Step 5: Deploy Edge Agent @@ -437,11 +439,12 @@ mkdir -p ~/aws-iot-fleetwise-deploy && cd ~/aws-iot-fleetwise-deploy \ command: ```bash - mkdir -p ~/aws-iot-fleetwise-deploy && cd ~/aws-iot-fleetwise-deploy \ - && unzip -o ~/aws-iot-fleetwise-deploy.zip \ - && mkdir -p /etc/aws-iot-fleetwise \ - && cp config/* /etc/aws-iot-fleetwise \ - && ./tools/install-fwe.sh + mkdir -p ~/aws-iot-fleetwise-deploy \ + && cd ~/aws-iot-fleetwise-deploy \ + && unzip -o ~/aws-iot-fleetwise-deploy.zip \ + && mkdir -p /etc/aws-iot-fleetwise \ + && cp config/* /etc/aws-iot-fleetwise \ + && ./tools/install-fwe.sh ``` 1. On the TCU, view and follow your Edge Agent log (press CTRL+C to exit) by running the following @@ -475,67 +478,62 @@ mkdir -p ~/aws-iot-fleetwise-deploy && cd ~/aws-iot-fleetwise-deploy \ ## Step 7: Collect OBD data -1. On the development machine, install the AWS IoT FleetWise demo script dependencies by running the - following commands. The script installs the following Ubuntu packages: `python3 python3-pip`, and - then installs the following PIP packages: `wrapt plotly pandas cantools`. +1. Run the following _on the development machine_ to install the dependencies of the demo script: ```bash cd ~/aws-iot-fleetwise-edge/tools/cloud \ - && sudo -H ./install-deps.sh + && sudo -H ./install-deps.sh ``` -1. On the development machine, deploy a heartbeat campaign that periodically collects OBD data by - running the following commands: + The above command installs the following Ubuntu packages: `python3 python3-pip`. It then installs + the following PIP packages: `wrapt plotly pandas cantools fastparquet` + +1. Deploy a heartbeat campaign that periodically collects OBD data by running the following + commands: ```bash ./demo.sh --vehicle-name fwdemo-g26 --campaign-file campaign-obd-heartbeat.json ``` - The demo script does the following: - - 1. Registers your AWS account with AWS IoT FleetWise, if it's not already registered. - 1. Creates a signal catalog. First, the demo script adds standard OBD signals based on - `obd-nodes.json`. Next, it adds CAN signals in a flat signal list based on the DBC file - `hscan.dbc`. - 1. Creates a vehicle model, or _model manifest_, that references the signal catalog with every - OBD and DBC signal. - 1. Activates the vehicle model. - 1. Creates a decoder manifest linked to the vehicle model using `obd-decoders.json` for decoding + The demo script: + + 1. Registers your AWS account with AWS IoT FleetWise, if not already registered. + 1. Creates an Amazon Timestream database and table. + 1. Creates IAM role and policy required for the service to write data to Amazon Timestream. + 1. Creates a signal catalog, firstly based on `obd-nodes.json` to add standard OBD signals, and + secondly based on the DBC file `hscan.dbc` to add CAN signals in a flat signal list. + 1. Creates a model manifest that references the signal catalog with all of the OBD and DBC + signals. + 1. Activates the model manifest. + 1. Creates a decoder manifest linked to the model manifest using `obd-decoders.json` for decoding OBD signals from the network interfaces defined in `network-interfaces.json`. 1. Imports the CAN signal decoding information from `hscan.dbc` to the decoder manifest. 1. Updates the decoder manifest to set the status as `ACTIVE`. - 1. Creates a vehicle with an ID equal to `fwdemo-g26`, which is also the name passed to + 1. Creates a vehicle with a name equal to `fwdemo-g26`, the same as the name passed to `provision.sh`. 1. Creates a fleet. 1. Associates the vehicle with the fleet. - 1. Creates a campaign from `campaign-obd-heartbeat.json`. This contains a time-based collection + 1. Creates a campaign from `campaign-obd-heartbeat.json` that contains a time-based collection scheme that collects OBD data and targets the campaign at the fleet. 1. Approves the campaign. - 1. Waits until the campaign status is `HEALTHY`, which means the campaign was deployed to the - fleet. + 1. Waits until the campaign status is `HEALTHY`, which means the campaign has been deployed to + the fleet. 1. Waits 30 seconds and then downloads the collected data from Amazon Timestream. 1. Saves the data to an HTML file. - If you enabled S3 upload destination by passing the option `--enable-s3-upload`, the demo script - will additionally: - - - Create S3 bucket for collected data for S3 campaigns, if not already created - - Create IAM roles and policies required for the service to write data to the S3 resources - - Creates 2 additional campaigns from `campaign-brake-event.json`. One campaign will upload data - to to S3 in JSON format, one to S3 in parquet format - - Wait 20 minutes for the data to propagate to S3 and then downloads it - - Save the data to an HTML file + This script will not delete Amazon Timestream resources. - When the script completes, you receive the path to the output HTML file on your local machine. To - download it, use `scp`, and then open it in your web browser: +1. When the script completes, a path to an HTML file is given. _On your local machine_, use `scp` to + download it, then open it in your web browser: ```bash scp -i ubuntu@: . ``` -1. To explore the collected data, click and drag on the graph to zoom in. Alternatively, if your AWS - account is enrolled with QuickSight or Amazon Managed Grafana, you can use them to browse the - data from Amazon Timestream directly. +1. To explore the collected data, you can click and drag to zoom in. + + Alternatively, if your AWS account is enrolled with Amazon QuickSight or Amazon Managed Grafana, + you may use them to browse the data from Amazon Timestream directly. **Note:** @@ -544,3 +542,17 @@ mkdir -p ~/aws-iot-fleetwise-deploy && cd ~/aws-iot-fleetwise-deploy \ different vehicle models. For this reason, if you're not going to turn on the vehicle for an extended period (like a week), unplug the iWave device from the J1962 DCL port to avoid depleting the battery. + +## Step 8: Clean up + +Run the following to clean up resources created by the `provision.sh` and `demo.sh` scripts. +**Note:** The Amazon Timestream resources are not deleted. + +```bash +cd ~/aws-iot-fleetwise-edge/tools/cloud \ +&& clean-up.sh \ +&& ../provision.sh \ + --vehicle-name fwdemo-g26 \ + --region us-east-1 \ + --only-clean-up +``` diff --git a/src/datamanagement/custom/example/iwavegps/README.md b/docs/iwave-g26-tutorial/iwave-gps-setup.md similarity index 88% rename from src/datamanagement/custom/example/iwavegps/README.md rename to docs/iwave-g26-tutorial/iwave-gps-setup.md index 9291ba22..879fa39a 100644 --- a/src/datamanagement/custom/example/iwavegps/README.md +++ b/docs/iwave-g26-tutorial/iwave-gps-setup.md @@ -1,8 +1,8 @@ # IWave GPS setup -Setup the iWave device like described in the -[iwave-g26-tutorial](../../../../../docs/iwave-g26-tutorial/iwave-g26-tutorial.md) To enable the GPS -open the file `/etc/ppp/chat/gprs` and add the following (for example above the AT+CPIN line): +Setup the iWave device like described in the [iwave-g26-tutorial](iwave-g26-tutorial.md) To enable +the GPS open the file `/etc/ppp/chat/gprs` and add the following (for example above the AT+CPIN +line): ``` # Enable GPS diff --git a/docs/metrics.md b/docs/metrics.md index 2cb90162..4fe910aa 100644 --- a/docs/metrics.md +++ b/docs/metrics.md @@ -1,9 +1,9 @@ # Application level metrics The Reference Implementation for AWS IoT Fleetwise ("FWE") includes a -[TraceModule](../src/platform/linux/logmanagement/src/TraceModule.cpp). The TraceModule provides a -set of metrics that are used as an entry point to efficiently diagnose issues, saving you time since -you no longer need to review the entire log of all FWE instances running. +[TraceModule](../src/TraceModule.cpp). The TraceModule provides a set of metrics that are used as an +entry point to efficiently diagnose issues, saving you time since you no longer need to review the +entire log of all FWE instances running. - **`RFrames0` - `RFrames19`** are monotonic counters of the number of raw can frames read on each bus. If these counters remain null or remain fixed for a longer runtime, the system might either @@ -186,9 +186,8 @@ if and how to upload them to the cloud. # Adding new metrics Adding new metrics requires changing the C++ code and recompiling FWE. Add the metrics to the -`TraceVariable` enum in [TraceModule.h](../src/platform/linux/logmanagement/include/TraceModule.h) -and assign a short name in the function `getVariableName` of -[TraceModule.cpp](../src/platform/linux/logmanagement/src/TraceModule.cpp). Then you can set the +`TraceVariable` enum in [TraceModule.h](../src/TraceModule.h) and assign a short name in the +function `getVariableName` of [TraceModule.cpp](../src/TraceModule.cpp). Then you can set the metrics anywhere by using: ```cpp diff --git a/docs/rpi-tutorial/raspberry-pi-tutorial.md b/docs/rpi-tutorial/raspberry-pi-tutorial.md index bed1005e..224a8195 100644 --- a/docs/rpi-tutorial/raspberry-pi-tutorial.md +++ b/docs/rpi-tutorial/raspberry-pi-tutorial.md @@ -10,6 +10,7 @@ - [Step 4: Provision AWS IoT credentials](#step-4-provision-aws-iot-credentials) - [Step 5: Deploy Edge Agent](#step-5-deploy-edge-agent) - [Step 6: Deploy a campaign to the Raspberry Pi](#step-6-deploy-a-campaign-to-the-raspberry-pi) +- [Step 7: Clean up](#step-7-clean-up) **Copyright (C) Amazon Web Services, Inc. and/or its affiliates. All rights reserved.** @@ -106,8 +107,8 @@ to take action based on your use of AWS IoT FleetWise._** 1. Run the following to update the system and install `unzip`: ```bash sudo apt update \ - && sudo apt upgrade -y \ - && sudo apt install -y unzip + && sudo apt upgrade -y \ + && sudo apt install -y unzip ``` 1. Run ``` @@ -158,7 +159,7 @@ Next, compile FWE for the ARM 64-bit architecture of the processor present in th ```bash git clone https://github.com/aws/aws-iot-fleetwise-edge.git ~/aws-iot-fleetwise-edge \ - && cd ~/aws-iot-fleetwise-edge + && cd ~/aws-iot-fleetwise-edge ``` 1. Review, modify and supplement [the FWE source code](../../src/) to ensure it meets your use case @@ -190,26 +191,28 @@ credentials by running the following command. Your Edge Agent binary and its con packaged into a ZIP file that is ready for deployment to the Raspberry Pi. ```bash -mkdir -p ~/aws-iot-fleetwise-deploy && cd ~/aws-iot-fleetwise-deploy \ - && cp -r ~/aws-iot-fleetwise-edge/tools . \ - && mkdir -p build/src/executionmanagement \ - && cp ~/aws-iot-fleetwise-edge/build/src/executionmanagement/aws-iot-fleetwise-edge \ - build/src/executionmanagement/ \ - && mkdir -p config && cd config \ - && ../tools/provision.sh \ - --vehicle-name fwdemo-rpi \ - --certificate-pem-outfile certificate.pem \ - --private-key-outfile private-key.key \ - --endpoint-url-outfile endpoint.txt \ - --vehicle-name-outfile vehicle-name.txt \ - && ../tools/configure-fwe.sh \ - --input-config-file ~/aws-iot-fleetwise-edge/configuration/static-config.json \ - --output-config-file config-0.json \ - --log-color Yes \ - --vehicle-name `cat vehicle-name.txt` \ - --endpoint-url `cat endpoint.txt` \ - --can-bus0 can0 \ - && cd .. && zip -r aws-iot-fleetwise-deploy.zip . +mkdir -p ~/aws-iot-fleetwise-deploy \ +&& cd ~/aws-iot-fleetwise-deploy \ +&& cp -r ~/aws-iot-fleetwise-edge/tools . \ +&& mkdir -p build \ +&& cp ~/aws-iot-fleetwise-edge/build/aws-iot-fleetwise-edge build \ +&& mkdir -p config \ +&& cd config \ +&& ../tools/provision.sh \ + --vehicle-name fwdemo-rpi \ + --certificate-pem-outfile certificate.pem \ + --private-key-outfile private-key.key \ + --endpoint-url-outfile endpoint.txt \ + --vehicle-name-outfile vehicle-name.txt \ +&& ../tools/configure-fwe.sh \ + --input-config-file ~/aws-iot-fleetwise-edge/configuration/static-config.json \ + --output-config-file config-0.json \ + --log-color Yes \ + --vehicle-name `cat vehicle-name.txt` \ + --endpoint-url `cat endpoint.txt` \ + --can-bus0 can0 \ +&& cd .. \ +&& zip -r aws-iot-fleetwise-deploy.zip . ``` ## Step 5: Deploy Edge Agent @@ -234,10 +237,10 @@ mkdir -p ~/aws-iot-fleetwise-deploy && cd ~/aws-iot-fleetwise-deploy \ ```bash mkdir -p ~/aws-iot-fleetwise-deploy && cd ~/aws-iot-fleetwise-deploy \ - && unzip -o ~/aws-iot-fleetwise-deploy.zip \ - && sudo mkdir -p /etc/aws-iot-fleetwise \ - && sudo cp config/* /etc/aws-iot-fleetwise \ - && sudo ./tools/install-fwe.sh + && unzip -o ~/aws-iot-fleetwise-deploy.zip \ + && sudo mkdir -p /etc/aws-iot-fleetwise \ + && sudo cp config/* /etc/aws-iot-fleetwise \ + && sudo ./tools/install-fwe.sh ``` 1. Install the [can-isotp](https://en.wikipedia.org/wiki/ISO_15765-2) module: @@ -272,64 +275,73 @@ mkdir -p ~/aws-iot-fleetwise-deploy && cd ~/aws-iot-fleetwise-deploy \ ## Step 6: Deploy a campaign to the Raspberry Pi -1. On the development machine, install the AWS IoT FleetWise demo script dependencies by running the - following commands. The script installs the following Ubuntu packages: `python3 python3-pip`, and - then installs the following PIP packages: `wrapt plotly pandas cantools`. +1. Run the following _on the development machine_ to install the dependencies of the demo script: ```bash cd ~/aws-iot-fleetwise-edge/tools/cloud \ - && sudo -H ./install-deps.sh + && sudo -H ./install-deps.sh ``` -1. On the development machine, deploy a heartbeat campaign that periodically collects OBD data by - running the following commands: + The above command installs the following Ubuntu packages: `python3 python3-pip`. It then installs + the following PIP packages: `wrapt plotly pandas cantools fastparquet` + +1. Deploy a heartbeat campaign that periodically collects OBD data by running the following + commands: ```bash ./demo.sh --vehicle-name fwdemo-rpi --campaign-file campaign-obd-heartbeat.json ``` - The demo script does the following: - - 1. Registers your AWS account with AWS IoT FleetWise, if it's not already registered. - 1. Creates a signal catalog. First, the demo script adds standard OBD signals based on - `obd-nodes.json`. Next, it adds CAN signals in a flat signal list based on the DBC file - `hscan.dbc`. - 1. Creates a vehicle model, or _model manifest_, that references the signal catalog with every - OBD and DBC signal. - 1. Activates the vehicle model. - 1. Creates a decoder manifest linked to the vehicle model using `obd-decoders.json` for decoding + The demo script: + + 1. Registers your AWS account with AWS IoT FleetWise, if not already registered. + 1. Creates an Amazon Timestream database and table. + 1. Creates IAM role and policy required for the service to write data to Amazon Timestream. + 1. Creates a signal catalog, firstly based on `obd-nodes.json` to add standard OBD signals, and + secondly based on the DBC file `hscan.dbc` to add CAN signals in a flat signal list. + 1. Creates a model manifest that references the signal catalog with all of the OBD and DBC + signals. + 1. Activates the model manifest. + 1. Creates a decoder manifest linked to the model manifest using `obd-decoders.json` for decoding OBD signals from the network interfaces defined in `network-interfaces.json`. 1. Imports the CAN signal decoding information from `hscan.dbc` to the decoder manifest. 1. Updates the decoder manifest to set the status as `ACTIVE`. - 1. Creates a vehicle with an ID equal to `fwdemo-rpi`, which is also the name passed to + 1. Creates a vehicle with a name equal to `fwdemo-rpi`, the same as the name passed to `provision.sh`. 1. Creates a fleet. 1. Associates the vehicle with the fleet. - 1. Creates a campaign from `campaign-obd-heartbeat.json`. This contains a time-based collection + 1. Creates a campaign from `campaign-obd-heartbeat.json` that contains a time-based collection scheme that collects OBD data and targets the campaign at the fleet. 1. Approves the campaign. - 1. Waits until the campaign status is `HEALTHY`, which means the campaign was deployed to the - fleet. + 1. Waits until the campaign status is `HEALTHY`, which means the campaign has been deployed to + the fleet. 1. Waits 30 seconds and then downloads the collected data from Amazon Timestream. 1. Saves the data to an HTML file. - If you enabled S3 upload destination by passing the option `--enable-s3-upload`, the demo script - will additionally: - - - Create S3 bucket for collected data for S3 campaigns, if not already created - - Create IAM roles and policies required for the service to write data to the S3 resources - - Creates 2 additional campaigns from `campaign-brake-event.json`. One campaign will upload data - to to S3 in JSON format, one to S3 in parquet format - - Wait 20 minutes for the data to propagate to S3 and then downloads it - - Save the data to an HTML file + This script will not delete Amazon Timestream resources. - When the script completes, you receive the path to the output HTML file on your local machine. To - download it, use `scp`, and then open it in your web browser: +1. When the script completes, a path to an HTML file is given. _On your local machine_, use `scp` to + download it, then open it in your web browser: ```bash scp -i ubuntu@: . ``` -1. To explore the collected data, click and drag on the graph to zoom in. Alternatively, if your AWS - account is enrolled with QuickSight or Amazon Managed Grafana, you can use them to browse the - data from Amazon Timestream directly. +1. To explore the collected data, you can click and drag to zoom in. + + Alternatively, if your AWS account is enrolled with Amazon QuickSight or Amazon Managed Grafana, + you may use them to browse the data from Amazon Timestream directly. + +## Step 7: Clean up + +Run the following to clean up resources created by the `provision.sh` and `demo.sh` scripts. +**Note:** The Amazon Timestream resources are not deleted. + +```bash +cd ~/aws-iot-fleetwise-edge/tools/cloud \ +&& clean-up.sh \ +&& ../provision.sh \ + --vehicle-name fwdemo-rpi \ + --region us-east-1 \ + --only-clean-up +``` diff --git a/src/datamanagement/custom/example/aaosvhal/src/AaosVhalSource.cpp b/src/AaosVhalSource.cpp similarity index 86% rename from src/datamanagement/custom/example/aaosvhal/src/AaosVhalSource.cpp rename to src/AaosVhalSource.cpp index d7793b73..967f6ef4 100644 --- a/src/datamanagement/custom/example/aaosvhal/src/AaosVhalSource.cpp +++ b/src/AaosVhalSource.cpp @@ -1,19 +1,20 @@ // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 -// Includes #include "AaosVhalSource.h" #include "LoggingModule.h" #include "TraceModule.h" +#include +#include namespace Aws { namespace IoTFleetWise { -namespace DataManagement -{ -constexpr const char *AaosVhalSource::CAN_CHANNEL_NUMBER; -constexpr const char *AaosVhalSource::CAN_RAW_FRAME_ID; + +// NOLINT below due to C++17 warning of redundant declarations that are required to maintain C++14 compatibility +constexpr const char *AaosVhalSource::CAN_CHANNEL_NUMBER; // NOLINT +constexpr const char *AaosVhalSource::CAN_RAW_FRAME_ID; // NOLINT AaosVhalSource::AaosVhalSource( SignalBufferPtr signalBufferPtr ) : mSignalBufferPtr{ std::move( signalBufferPtr ) } { @@ -71,6 +72,5 @@ AaosVhalSource::pollData() { } -} // namespace DataManagement } // namespace IoTFleetWise } // namespace Aws diff --git a/src/datamanagement/custom/example/aaosvhal/include/AaosVhalSource.h b/src/AaosVhalSource.h similarity index 89% rename from src/datamanagement/custom/example/aaosvhal/include/AaosVhalSource.h rename to src/AaosVhalSource.h index aca01ce7..998ac39c 100644 --- a/src/datamanagement/custom/example/aaosvhal/include/AaosVhalSource.h +++ b/src/AaosVhalSource.h @@ -2,23 +2,20 @@ // SPDX-License-Identifier: Apache-2.0 #pragma once +#include "Clock.h" #include "ClockHandler.h" #include "CollectionInspectionAPITypes.h" #include "CustomDataSource.h" -#include "Timer.h" +#include "SignalTypes.h" #include -#include +#include +#include #include namespace Aws { namespace IoTFleetWise { -namespace DataManagement -{ -using namespace Aws::IoTFleetWise::Platform::Linux; -using namespace Aws::IoTFleetWise::VehicleNetwork; -using namespace Aws::IoTFleetWise::DataInspection; /** * To implement a custom data source create a new class and inherit from CustomDataSource @@ -73,6 +70,6 @@ class AaosVhalSource : public CustomDataSource CANChannelNumericID mCanChannel{ INVALID_CAN_SOURCE_NUMERIC_ID }; CANRawFrameID mCanRawFrameId{ 0 }; }; -} // namespace DataManagement + } // namespace IoTFleetWise } // namespace Aws diff --git a/src/offboardconnectivity/implementation/aws/bootstrap/src/AwsBootstrap.cpp b/src/AwsBootstrap.cpp similarity index 92% rename from src/offboardconnectivity/implementation/aws/bootstrap/src/AwsBootstrap.cpp rename to src/AwsBootstrap.cpp index d7455796..b9597b59 100644 --- a/src/offboardconnectivity/implementation/aws/bootstrap/src/AwsBootstrap.cpp +++ b/src/AwsBootstrap.cpp @@ -1,26 +1,24 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + #include "AwsBootstrap.h" #include "AwsSDKMemoryManager.h" #include "LoggingModule.h" - #include #include - -using namespace Aws::IoTFleetWise::OffboardConnectivityAwsIot; -using namespace Aws::IoTFleetWise::Platform::Linux; - -namespace -{ -constexpr size_t NUM_THREADS = 1; -constexpr size_t MAX_HOSTS = 1; -constexpr size_t MAX_TTL = 5; -} // namespace +#include +#include +#include +#include namespace Aws { namespace IoTFleetWise { -namespace OffboardConnectivityAwsIot -{ + +constexpr size_t NUM_THREADS = 1; +constexpr size_t MAX_HOSTS = 1; +constexpr size_t MAX_TTL = 5; struct AwsBootstrap::Impl { @@ -104,6 +102,5 @@ AwsBootstrap::getClientBootStrap() return mImpl->getClientBootStrap(); } -} // namespace OffboardConnectivityAwsIot } // namespace IoTFleetWise } // namespace Aws diff --git a/src/offboardconnectivity/implementation/aws/bootstrap/include/AwsBootstrap.h b/src/AwsBootstrap.h similarity index 93% rename from src/offboardconnectivity/implementation/aws/bootstrap/include/AwsBootstrap.h rename to src/AwsBootstrap.h index c9e27b64..16290f38 100644 --- a/src/offboardconnectivity/implementation/aws/bootstrap/include/AwsBootstrap.h +++ b/src/AwsBootstrap.h @@ -1,6 +1,6 @@ - // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 + #pragma once #include @@ -17,8 +17,6 @@ class ClientBootstrap; namespace IoTFleetWise { -namespace OffboardConnectivityAwsIot -{ /** * This module bootstrap the AWS CRT by creating event loop and client bootstrap @@ -51,6 +49,5 @@ class AwsBootstrap std::unique_ptr mImpl; }; -} // namespace OffboardConnectivityAwsIot } // namespace IoTFleetWise } // namespace Aws diff --git a/src/offboardconnectivity/implementation/aws/iotcpp/src/AwsGGChannel.cpp b/src/AwsGGChannel.cpp similarity index 92% rename from src/offboardconnectivity/implementation/aws/iotcpp/src/AwsGGChannel.cpp rename to src/AwsGGChannel.cpp index d7f23040..ffbfd0a1 100644 --- a/src/offboardconnectivity/implementation/aws/iotcpp/src/AwsGGChannel.cpp +++ b/src/AwsGGChannel.cpp @@ -3,19 +3,21 @@ #include "AwsGGChannel.h" #include "AwsSDKMemoryManager.h" +#include "CacheAndPersist.h" #include "IConnectivityModule.h" +#include "IReceiver.h" #include "LoggingModule.h" -#include -#include +#include +#include -using namespace Aws::IoTFleetWise::OffboardConnectivityAwsIot; -using namespace Aws::IoTFleetWise::OffboardConnectivity; -using namespace Aws::Crt; -using namespace Aws::Greengrass; +namespace Aws +{ +namespace IoTFleetWise +{ AwsGGChannel::AwsGGChannel( IConnectivityModule *connectivityModule, std::shared_ptr payloadManager, - std::shared_ptr &ggConnection ) + std::shared_ptr &ggConnection ) : mConnectivityModule( connectivityModule ) , mPayloadManager( std::move( payloadManager ) ) , mConnection( ggConnection ) @@ -77,8 +79,8 @@ AwsGGChannel::subscribe() return ConnectivityError::NoConnection; } mSubscribeOperation = mConnection->NewSubscribeToIoTCore( mSubscribeStreamHandler ); - SubscribeToIoTCoreRequest subscribeRequest; - subscribeRequest.SetQos( QOS_AT_LEAST_ONCE ); + Aws::Greengrass::SubscribeToIoTCoreRequest subscribeRequest; + subscribeRequest.SetQos( Aws::Greengrass::QOS_AT_LEAST_ONCE ); subscribeRequest.SetTopicName( mTopicName.c_str() != nullptr ? mTopicName.c_str() : "" ); FWE_LOG_TRACE( "Attempting to subscribe to " + mTopicName + " topic" ); @@ -141,7 +143,7 @@ AwsGGChannel::getMaxSendSize() const } ConnectivityError -AwsGGChannel::sendBuffer( const std::uint8_t *buf, size_t size, struct CollectionSchemeParams collectionSchemeParams ) +AwsGGChannel::sendBuffer( const std::uint8_t *buf, size_t size, CollectionSchemeParams collectionSchemeParams ) { std::lock_guard connectivityLock( mConnectivityMutex ); if ( !isTopicValid() ) @@ -200,11 +202,11 @@ AwsGGChannel::sendBuffer( const std::uint8_t *buf, size_t size, struct Collectio return ConnectivityError::NoConnection; } auto publishOperation = mConnection->NewPublishToIoTCore(); - PublishToIoTCoreRequest publishRequest; + Aws::Greengrass::PublishToIoTCoreRequest publishRequest; publishRequest.SetTopicName( mTopicName.c_str() != nullptr ? mTopicName.c_str() : "" ); - Vector payload( buf, buf + size ); + Aws::Crt::Vector payload( buf, buf + size ); publishRequest.SetPayload( payload ); - publishRequest.SetQos( QOS_AT_LEAST_ONCE ); + publishRequest.SetQos( Aws::Greengrass::QOS_AT_LEAST_ONCE ); FWE_LOG_TRACE( "Attempting to publish to " + mTopicName + " topic" ); auto requestStatus = publishOperation->Activate( publishRequest ).get(); @@ -259,7 +261,7 @@ AwsGGChannel::sendBuffer( const std::uint8_t *buf, size_t size, struct Collectio } ConnectivityError -AwsGGChannel::sendFile( const std::string &filePath, size_t size, struct CollectionSchemeParams collectionSchemeParams ) +AwsGGChannel::sendFile( const std::string &filePath, size_t size, CollectionSchemeParams collectionSchemeParams ) { std::lock_guard connectivityLock( mConnectivityMutex ); if ( !isTopicValid() ) @@ -318,7 +320,7 @@ AwsGGChannel::sendFile( const std::string &filePath, size_t size, struct Collect return ConnectivityError::QuotaReached; } - Vector payload( size ); + Aws::Crt::Vector payload( size ); if ( mPayloadManager->retrievePayload( payload.data(), payload.size(), filePath ) != ErrorCode::SUCCESS ) { return ConnectivityError::WrongInputData; @@ -330,17 +332,19 @@ AwsGGChannel::sendFile( const std::string &filePath, size_t size, struct Collect return ConnectivityError::NoConnection; } auto publishOperation = mConnection->NewPublishToIoTCore(); - PublishToIoTCoreRequest publishRequest; + Aws::Greengrass::PublishToIoTCoreRequest publishRequest; publishRequest.SetTopicName( mTopicName.c_str() != nullptr ? mTopicName.c_str() : "" ); publishRequest.SetPayload( payload ); - publishRequest.SetQos( QOS_AT_LEAST_ONCE ); + publishRequest.SetQos( Aws::Greengrass::QOS_AT_LEAST_ONCE ); FWE_LOG_TRACE( "Attempting to publish to " + mTopicName + " topic" ); auto requestStatus = publishOperation->Activate( publishRequest ).get(); if ( !requestStatus ) { FWE_LOG_ERROR( "Failed to publish to " + mTopicName + " topic with error " + - std::string( requestStatus.StatusToString().c_str() ) ); + std::string( requestStatus.StatusToString().c_str() != nullptr + ? requestStatus.StatusToString().c_str() + : "" ) ); return ConnectivityError::NoConnection; } @@ -392,7 +396,7 @@ AwsGGChannel::unsubscribe() std::lock_guard connectivityLock( mConnectivityMutex ); if ( mSubscribed && isAliveNotThreadSafe() ) { - mSubscribeOperation.get()->Close().wait(); + mSubscribeOperation->Close().wait(); mSubscribed = false; return true; } @@ -403,3 +407,6 @@ AwsGGChannel::~AwsGGChannel() { unsubscribe(); } + +} // namespace IoTFleetWise +} // namespace Aws diff --git a/src/offboardconnectivity/implementation/aws/iotcpp/include/AwsGGChannel.h b/src/AwsGGChannel.h similarity index 80% rename from src/offboardconnectivity/implementation/aws/iotcpp/include/AwsGGChannel.h rename to src/AwsGGChannel.h index 3fe8cee9..ead0faac 100644 --- a/src/offboardconnectivity/implementation/aws/iotcpp/include/AwsGGChannel.h +++ b/src/AwsGGChannel.h @@ -3,47 +3,44 @@ #pragma once -// Includes +#include "IConnectionTypes.h" #include "IConnectivityChannel.h" #include "IConnectivityModule.h" +#include "ISender.h" #include "PayloadManager.h" #include -#include +#include +#include #include +#include +#include +#include #include #include #include +#include +#include namespace Aws { namespace IoTFleetWise { -/** - * @brief Namespace depending on Aws Iot SDK headers - */ -namespace OffboardConnectivityAwsIot -{ - -using namespace Aws::Greengrass; -using namespace Aws::IoTFleetWise::Platform::Linux; - -using Aws::IoTFleetWise::OffboardConnectivity::CollectionSchemeParams; -using Aws::IoTFleetWise::OffboardConnectivity::ConnectivityError; using SubscribeCallback = std::function; -class SubscribeStreamHandler : public SubscribeToIoTCoreStreamHandler +class SubscribeStreamHandler : public Aws::Greengrass::SubscribeToIoTCoreStreamHandler { public: SubscribeStreamHandler( SubscribeCallback callback ) - : mCallback( callback ) + : mCallback( std::move( callback ) ) { } + virtual ~SubscribeStreamHandler() = default; private: // coverity[autosar_cpp14_a0_1_3_violation] false positive - function overrides sdk's virtual function. void - OnStreamEvent( IoTCoreMessage *response ) override + OnStreamEvent( Aws::Greengrass::IoTCoreMessage *response ) override { auto message = response->GetMessage(); @@ -71,7 +68,7 @@ class AwsGGChannel : public IConnectivityChannel public: AwsGGChannel( IConnectivityModule *connectivityModule, std::shared_ptr payloadManager, - std::shared_ptr &ggConnection ); + std::shared_ptr &ggConnection ); ~AwsGGChannel() override; AwsGGChannel( const AwsGGChannel & ) = delete; @@ -110,15 +107,13 @@ class AwsGGChannel : public IConnectivityChannel size_t getMaxSendSize() const override; - ConnectivityError sendBuffer( - const std::uint8_t *buf, - size_t size, - struct CollectionSchemeParams collectionSchemeParams = CollectionSchemeParams() ) override; + ConnectivityError sendBuffer( const std::uint8_t *buf, + size_t size, + CollectionSchemeParams collectionSchemeParams = CollectionSchemeParams() ) override; - ConnectivityError sendFile( - const std::string &filePath, - size_t size, - struct CollectionSchemeParams collectionSchemeParams = CollectionSchemeParams() ) override; + ConnectivityError sendFile( const std::string &filePath, + size_t size, + CollectionSchemeParams collectionSchemeParams = CollectionSchemeParams() ) override; void invalidateConnection() @@ -161,15 +156,15 @@ class AwsGGChannel : public IConnectivityChannel std::mutex mConnectivityMutex; std::mutex mConnectivityLambdaMutex; std::shared_ptr mPayloadManager; - std::shared_ptr &mConnection; + std::shared_ptr &mConnection; std::atomic mSubscribed; bool mSubscribeAsynchronously; std::atomic mPayloadCountSent{}; std::string mTopicName; std::shared_ptr mSubscribeStreamHandler; - std::shared_ptr mSubscribeOperation; + std::shared_ptr mSubscribeOperation; }; -} // namespace OffboardConnectivityAwsIot + } // namespace IoTFleetWise } // namespace Aws diff --git a/src/offboardconnectivity/implementation/aws/iotcpp/src/AwsGGConnectivityModule.cpp b/src/AwsGGConnectivityModule.cpp similarity index 82% rename from src/offboardconnectivity/implementation/aws/iotcpp/src/AwsGGConnectivityModule.cpp rename to src/AwsGGConnectivityModule.cpp index c86da397..650fca74 100644 --- a/src/offboardconnectivity/implementation/aws/iotcpp/src/AwsGGConnectivityModule.cpp +++ b/src/AwsGGConnectivityModule.cpp @@ -4,21 +4,13 @@ #include "AwsGGConnectivityModule.h" #include "AwsGGChannel.h" #include "LoggingModule.h" -#include "TraceModule.h" - #include -#include - -#include -#include -#include -#include - -#include "Thread.h" +#include -using namespace Aws::Crt; -using namespace Aws::Greengrass; -using namespace Aws::IoTFleetWise::OffboardConnectivityAwsIot; +namespace Aws +{ +namespace IoTFleetWise +{ AwsGGConnectivityModule::AwsGGConnectivityModule( Aws::Crt::Io::ClientBootstrap *clientBootstrap ) : mConnected( false ) @@ -38,7 +30,7 @@ AwsGGConnectivityModule::connect() mConnected = false; mLifecycleHandler = std::make_unique(); - mConnection = std::make_shared( *( mClientBootstrap ) ); + mConnection = std::make_shared( *( mClientBootstrap ) ); auto connectionStatus = mConnection->Connect( *( mLifecycleHandler.get() ) ).get(); if ( !connectionStatus ) { @@ -81,3 +73,6 @@ AwsGGConnectivityModule::~AwsGGConnectivityModule() { AwsGGConnectivityModule::disconnect(); } + +} // namespace IoTFleetWise +} // namespace Aws diff --git a/src/offboardconnectivity/implementation/aws/iotcpp/include/AwsGGConnectivityModule.h b/src/AwsGGConnectivityModule.h similarity index 80% rename from src/offboardconnectivity/implementation/aws/iotcpp/include/AwsGGConnectivityModule.h rename to src/AwsGGConnectivityModule.h index 2f176687..a79ac215 100644 --- a/src/offboardconnectivity/implementation/aws/iotcpp/include/AwsGGConnectivityModule.h +++ b/src/AwsGGConnectivityModule.h @@ -3,30 +3,29 @@ #pragma once -// Includes #include "AwsGGChannel.h" -#include "Listener.h" +#include "IConnectivityChannel.h" +#include "IConnectivityModule.h" #include "LoggingModule.h" -#include "TraceModule.h" +#include "PayloadManager.h" #include -#include +#include #include -#include +#include #include +#include namespace Aws { namespace IoTFleetWise { -namespace OffboardConnectivityAwsIot -{ -using namespace Aws::IoTFleetWise::Platform; -using namespace Aws::IoTFleetWise::Platform::Linux; -using namespace Aws::Greengrass; class IpcLifecycleHandler : public ConnectionLifecycleHandler { +public: + virtual ~IpcLifecycleHandler() = default; +private: // coverity[autosar_cpp14_a0_1_3_violation] false positive - function overrides sdk's virtual function. void OnConnectCallback() override @@ -63,6 +62,11 @@ class AwsGGConnectivityModule : public IConnectivityModule AwsGGConnectivityModule( Aws::Crt::Io::ClientBootstrap *clientBootstrap ); ~AwsGGConnectivityModule() override; + AwsGGConnectivityModule( const AwsGGConnectivityModule & ) = delete; + AwsGGConnectivityModule &operator=( const AwsGGConnectivityModule & ) = delete; + AwsGGConnectivityModule( AwsGGConnectivityModule && ) = delete; + AwsGGConnectivityModule &operator=( AwsGGConnectivityModule && ) = delete; + bool connect() override; bool disconnect() override; @@ -88,9 +92,9 @@ class AwsGGConnectivityModule : public IConnectivityModule std::atomic mConnectionEstablished; std::vector> mChannels; std::unique_ptr mLifecycleHandler; - std::shared_ptr mConnection; + std::shared_ptr mConnection; Aws::Crt::Io::ClientBootstrap *mClientBootstrap; }; -} // namespace OffboardConnectivityAwsIot + } // namespace IoTFleetWise } // namespace Aws diff --git a/src/offboardconnectivity/implementation/aws/iotcpp/src/AwsIotChannel.cpp b/src/AwsIotChannel.cpp similarity index 84% rename from src/offboardconnectivity/implementation/aws/iotcpp/src/AwsIotChannel.cpp rename to src/AwsIotChannel.cpp index 52448194..f9cf4525 100644 --- a/src/offboardconnectivity/implementation/aws/iotcpp/src/AwsIotChannel.cpp +++ b/src/AwsIotChannel.cpp @@ -3,18 +3,27 @@ #include "AwsIotChannel.h" #include "AwsSDKMemoryManager.h" +#include "CacheAndPersist.h" #include "IConnectivityModule.h" +#include "IReceiver.h" #include "LoggingModule.h" #include "TraceModule.h" +#include +#include +#include +#include #include +#include +#include -using namespace Aws::IoTFleetWise::OffboardConnectivityAwsIot; -using namespace Aws::IoTFleetWise::OffboardConnectivity; -using namespace Aws::Crt; +namespace Aws +{ +namespace IoTFleetWise +{ AwsIotChannel::AwsIotChannel( IConnectivityModule *connectivityModule, std::shared_ptr payloadManager, - std::shared_ptr &mqttConnection ) + std::shared_ptr &mqttConnection ) : mConnectivityModule( connectivityModule ) , mPayloadManager( std::move( payloadManager ) ) , mConnection( mqttConnection ) @@ -68,11 +77,11 @@ AwsIotChannel::subscribe() /* * This is invoked upon the reception of a message on a subscribed topic. */ - auto onMessage = [&]( Mqtt::MqttConnection &mqttConnection, - const String &topic, - const ByteBuf &byteBuf, + auto onMessage = [&]( MqttConnectionWrapper &mqttConnection, + const Aws::Crt::String &topic, + const Aws::Crt::ByteBuf &byteBuf, bool dup, - Mqtt::QOS qos, + Aws::Crt::Mqtt::QOS qos, bool retain ) { std::ostringstream os; (void)mqttConnection; @@ -89,10 +98,10 @@ AwsIotChannel::subscribe() * Subscribe for incoming publish messages on topic. */ std::promise subscribeFinishedPromise; - auto onSubAck = [&]( Mqtt::MqttConnection &mqttConnection, + auto onSubAck = [&]( MqttConnectionWrapper &mqttConnection, uint16_t packetId, - const String &topic, - Mqtt::QOS qos, + const Aws::Crt::String &topic, + Aws::Crt::Mqtt::QOS qos, int errorCode ) { (void)mqttConnection; mSubscribed = false; @@ -105,7 +114,7 @@ AwsIotChannel::subscribe() } else { - if ( ( packetId == 0U ) || ( qos == Mqtt::QOS::AWS_MQTT_QOS_FAILURE ) ) + if ( ( packetId == 0U ) || ( qos == Aws::Crt::Mqtt::QOS::AWS_MQTT_QOS_FAILURE ) ) { TraceModule::get().incrementAtomicVariable( TraceAtomicVariable::SUBSCRIBE_REJECT ); FWE_LOG_ERROR( "Subscribe rejected by the Remote broker" ); @@ -122,7 +131,7 @@ AwsIotChannel::subscribe() }; FWE_LOG_TRACE( "Subscribing..." ); - mConnection->Subscribe( mTopicName.c_str(), Mqtt::QOS::AWS_MQTT_QOS_AT_LEAST_ONCE, onMessage, onSubAck ); + mConnection->Subscribe( mTopicName.c_str(), Aws::Crt::Mqtt::QOS::AWS_MQTT_QOS_AT_LEAST_ONCE, onMessage, onSubAck ); // Blocked call until subscribe finished this call should quickly either fail or succeed but // depends on the network quality the Bootstrap needs to retry subscribing if failed. @@ -143,7 +152,7 @@ AwsIotChannel::getMaxSendSize() const } ConnectivityError -AwsIotChannel::sendBuffer( const std::uint8_t *buf, size_t size, struct CollectionSchemeParams collectionSchemeParams ) +AwsIotChannel::sendBuffer( const std::uint8_t *buf, size_t size, CollectionSchemeParams collectionSchemeParams ) { std::lock_guard connectivityLock( mConnectivityMutex ); if ( !isTopicValid() ) @@ -196,10 +205,10 @@ AwsIotChannel::sendBuffer( const std::uint8_t *buf, size_t size, struct Collecti return ConnectivityError::QuotaReached; } - auto payload = ByteBufNewCopy( DefaultAllocator(), (const uint8_t *)buf, size ); + auto payload = Aws::Crt::ByteBufNewCopy( Aws::Crt::DefaultAllocator(), (const uint8_t *)buf, size ); auto onPublishComplete = - [payload, size, this]( Mqtt::MqttConnection &mqttConnection, uint16_t packetId, int errorCode ) mutable { + [payload, size, this]( MqttConnectionWrapper &mqttConnection, uint16_t packetId, int errorCode ) mutable { /* This call means that the data was handed over to some lower level in the stack but not that the data is actually sent on the bus or removed from RAM*/ (void)mqttConnection; @@ -220,14 +229,13 @@ AwsIotChannel::sendBuffer( const std::uint8_t *buf, size_t size, struct Collecti FWE_LOG_ERROR( std::string( "Operation failed with error" ) + errLog ); } }; - mConnection->Publish( mTopicName.c_str(), Mqtt::QOS::AWS_MQTT_QOS_AT_MOST_ONCE, false, payload, onPublishComplete ); + mConnection->Publish( + mTopicName.c_str(), Aws::Crt::Mqtt::QOS::AWS_MQTT_QOS_AT_MOST_ONCE, false, payload, onPublishComplete ); return ConnectivityError::Success; } ConnectivityError -AwsIotChannel::sendFile( const std::string &filePath, - size_t size, - struct CollectionSchemeParams collectionSchemeParams ) +AwsIotChannel::sendFile( const std::string &filePath, size_t size, CollectionSchemeParams collectionSchemeParams ) { std::lock_guard connectivityLock( mConnectivityMutex ); if ( !isTopicValid() ) @@ -293,10 +301,11 @@ AwsIotChannel::sendFile( const std::string &filePath, return ConnectivityError::WrongInputData; } - auto payloadBuffer = ByteBufNewCopy( DefaultAllocator(), (const uint8_t *)payload.data(), payload.size() ); + auto payloadBuffer = + Aws::Crt::ByteBufNewCopy( Aws::Crt::DefaultAllocator(), (const uint8_t *)payload.data(), payload.size() ); auto onPublishComplete = - [payloadBuffer, size, this]( Mqtt::MqttConnection &mqttConnection, uint16_t packetId, int errorCode ) mutable { + [payloadBuffer, size, this]( MqttConnectionWrapper &mqttConnection, uint16_t packetId, int errorCode ) mutable { /* This call means that the data was handed over to some lower level in the stack but not that the data is actually sent on the bus or removed from RAM */ (void)mqttConnection; @@ -317,7 +326,7 @@ AwsIotChannel::sendFile( const std::string &filePath, } }; mConnection->Publish( - mTopicName.c_str(), Mqtt::QOS::AWS_MQTT_QOS_AT_MOST_ONCE, false, payloadBuffer, onPublishComplete ); + mTopicName.c_str(), Aws::Crt::Mqtt::QOS::AWS_MQTT_QOS_AT_MOST_ONCE, false, payloadBuffer, onPublishComplete ); return ConnectivityError::Success; } @@ -330,7 +339,7 @@ AwsIotChannel::unsubscribe() std::promise unsubscribeFinishedPromise; FWE_LOG_TRACE( "Unsubscribing..." ); mConnection->Unsubscribe( mTopicName.c_str(), - [&]( Mqtt::MqttConnection &mqttConnection, uint16_t packetId, int errorCode ) { + [&]( MqttConnectionWrapper &mqttConnection, uint16_t packetId, int errorCode ) { (void)mqttConnection; (void)packetId; (void)errorCode; @@ -350,3 +359,6 @@ AwsIotChannel::~AwsIotChannel() { unsubscribe(); } + +} // namespace IoTFleetWise +} // namespace Aws diff --git a/src/offboardconnectivity/implementation/aws/iotcpp/include/AwsIotChannel.h b/src/AwsIotChannel.h similarity index 81% rename from src/offboardconnectivity/implementation/aws/iotcpp/include/AwsIotChannel.h rename to src/AwsIotChannel.h index 5bcc1b4f..a6e2269a 100644 --- a/src/offboardconnectivity/implementation/aws/iotcpp/include/AwsIotChannel.h +++ b/src/AwsIotChannel.h @@ -3,16 +3,15 @@ #pragma once -// Includes +#include "IConnectionTypes.h" #include "IConnectivityChannel.h" #include "IConnectivityModule.h" -#include "IReceiver.h" #include "ISender.h" +#include "MqttConnectionWrapper.h" #include "PayloadManager.h" #include -#include #include -#include +#include #include #include #include @@ -21,14 +20,6 @@ namespace Aws { namespace IoTFleetWise { -/** - * @brief Namespace depending on Aws Iot SDK headers - */ -namespace OffboardConnectivityAwsIot -{ -using namespace Aws::IoTFleetWise::Platform::Linux; -using Aws::IoTFleetWise::OffboardConnectivity::CollectionSchemeParams; -using Aws::IoTFleetWise::OffboardConnectivity::ConnectivityError; /** * @brief a channel that can be used as IReceiver or ISender or both @@ -47,7 +38,7 @@ class AwsIotChannel : public IConnectivityChannel public: AwsIotChannel( IConnectivityModule *connectivityModule, std::shared_ptr payloadManager, - std::shared_ptr &mqttConnection ); + std::shared_ptr &mqttConnection ); ~AwsIotChannel() override; AwsIotChannel( const AwsIotChannel & ) = delete; @@ -86,15 +77,13 @@ class AwsIotChannel : public IConnectivityChannel size_t getMaxSendSize() const override; - ConnectivityError sendBuffer( - const std::uint8_t *buf, - size_t size, - struct CollectionSchemeParams collectionSchemeParams = CollectionSchemeParams() ) override; + ConnectivityError sendBuffer( const std::uint8_t *buf, + size_t size, + CollectionSchemeParams collectionSchemeParams = CollectionSchemeParams() ) override; - ConnectivityError sendFile( - const std::string &filePath, - size_t size, - struct CollectionSchemeParams collectionSchemeParams = CollectionSchemeParams() ) override; + ConnectivityError sendFile( const std::string &filePath, + size_t size, + CollectionSchemeParams collectionSchemeParams = CollectionSchemeParams() ) override; void invalidateConnection() @@ -135,7 +124,7 @@ class AwsIotChannel : public IConnectivityChannel static const size_t AWS_IOT_MAX_MESSAGE_SIZE = 131072; // = 128 KiB IConnectivityModule *mConnectivityModule; std::shared_ptr mPayloadManager; - std::shared_ptr &mConnection; + std::shared_ptr &mConnection; std::mutex mConnectivityMutex; std::mutex mConnectivityLambdaMutex; std::string mTopicName; @@ -144,6 +133,6 @@ class AwsIotChannel : public IConnectivityChannel bool mSubscribeAsynchronously; }; -} // namespace OffboardConnectivityAwsIot + } // namespace IoTFleetWise } // namespace Aws diff --git a/src/offboardconnectivity/implementation/aws/iotcpp/src/AwsIotConnectivityModule.cpp b/src/AwsIotConnectivityModule.cpp similarity index 66% rename from src/offboardconnectivity/implementation/aws/iotcpp/src/AwsIotConnectivityModule.cpp rename to src/AwsIotConnectivityModule.cpp index b0802993..ec8a3582 100644 --- a/src/offboardconnectivity/implementation/aws/iotcpp/src/AwsIotConnectivityModule.cpp +++ b/src/AwsIotConnectivityModule.cpp @@ -2,44 +2,49 @@ // SPDX-License-Identifier: Apache-2.0 #include "AwsIotConnectivityModule.h" -#include "AwsBootstrap.h" #include "LoggingModule.h" +#include "Thread.h" #include "TraceModule.h" - #include -#include -#include -#include +#include +#include +#include #include +#include -#include "Thread.h" +namespace Aws +{ +namespace IoTFleetWise +{ -using namespace Aws::IoTFleetWise::OffboardConnectivityAwsIot; -using namespace Aws::Crt; // Default MQTT Keep alive in seconds. // Defines how often an MQTT PING message is sent to the MQTT broker to keep the connection alive // Default set to 60 seconds. Every 60 seconds the stack will send an MQTT PING req. // The longer this interval is, the more the stack takes to detect the state of the TCP connection // at the lower network layers. +// This parameter is asserted in the C SDK. It shall be strictly bigger than the default +// connection ping timeout( set to 3 seconds). +// Refer to https://github.com/awslabs/aws-c-mqtt/blob/a2ee9a321fcafa19b0473b88a54e0ae8dde5fddf/source/client.c#L1461 constexpr uint16_t MQTT_CONNECT_KEEP_ALIVE_SECONDS = 60; // Default ping timeout value in milliseconds // If a response is not received within this interval, the connection will be reestablished. // If the PING request does not return within this interval, the stack will create a new one. constexpr uint32_t MQTT_PING_TIMOUT_MS = 3000; -AwsIotConnectivityModule::AwsIotConnectivityModule( std::string privateKey, - std::string certificate, - std::string rootCA, - std::string endpointUrl, - std::string clientId, - Aws::Crt::Io::ClientBootstrap *clientBootstrap, - bool asynchronous ) +AwsIotConnectivityModule::AwsIotConnectivityModule( + std::string privateKey, + std::string certificate, + std::string rootCA, + std::string endpointUrl, + std::string clientId, + std::function()> createMqttClientWrapper, + bool asynchronous ) : mPrivateKey( std::move( privateKey ) ) , mCertificate( std::move( certificate ) ) , mRootCA( std::move( rootCA ) ) , mEndpointUrl( std::move( endpointUrl ) ) , mClientId( std::move( clientId ) ) - , mClientBootstrap( clientBootstrap ) + , mCreateMqttClientWrapper( std::move( createMqttClientWrapper ) ) , mAsynchronous( asynchronous ) , mRetryThread( *this, RETRY_FIRST_CONNECTION_START_BACKOFF_MS, RETRY_FIRST_CONNECTION_MAX_BACKOFF_MS ) , mConnected( false ) @@ -124,73 +129,76 @@ AwsIotConnectivityModule::setupCallbacks() /* * This will execute when an mqtt connect has completed or failed. */ - auto onConnectionCompleted = - [&]( Mqtt::MqttConnection &mqttConnection, int errorCode, Mqtt::ReturnCode returnCode, bool sessionPresent ) { - (void)mqttConnection; - (void)sessionPresent; - if ( errorCode != 0 ) + auto onConnectionCompleted = [&]( MqttConnectionWrapper &mqttConnection, + int errorCode, + Aws::Crt::Mqtt::ReturnCode returnCode, + bool sessionPresent ) { + (void)mqttConnection; + (void)sessionPresent; + if ( errorCode != 0 ) + { + auto errString = Aws::Crt::ErrorDebugString( errorCode ); + TraceModule::get().incrementAtomicVariable( TraceAtomicVariable::CONNECTION_FAILED ); + FWE_LOG_ERROR( "Connection failed with error" ); + FWE_LOG_ERROR( errString != nullptr ? std::string( errString ) : std::string( "Unknown error" ) ); + mConnectionCompletedPromise.set_value( false ); + } + else + { + if ( returnCode != Aws::Crt::Mqtt::ReturnCode::AWS_MQTT_CONNECT_ACCEPTED ) { - auto errString = ErrorDebugString( errorCode ); - TraceModule::get().incrementAtomicVariable( TraceAtomicVariable::CONNECTION_FAILED ); - FWE_LOG_ERROR( "Connection failed with error" ); - FWE_LOG_ERROR( errString != nullptr ? std::string( errString ) : std::string( "Unknown error" ) ); + TraceModule::get().incrementAtomicVariable( TraceAtomicVariable::CONNECTION_REJECTED ); + FWE_LOG_ERROR( "Connection failed with mqtt return code" ); + FWE_LOG_ERROR( std::to_string( (int)returnCode ) ); mConnectionCompletedPromise.set_value( false ); } else { - if ( returnCode != Mqtt::ReturnCode::AWS_MQTT_CONNECT_ACCEPTED ) - { - TraceModule::get().incrementAtomicVariable( TraceAtomicVariable::CONNECTION_REJECTED ); - FWE_LOG_ERROR( "Connection failed with mqtt return code" ); - FWE_LOG_ERROR( std::to_string( (int)returnCode ) ); - mConnectionCompletedPromise.set_value( false ); - } - else - { - FWE_LOG_INFO( "Connection completed successfully" ); - mConnectionCompletedPromise.set_value( true ); - } + FWE_LOG_INFO( "Connection completed successfully" ); + mConnectionCompletedPromise.set_value( true ); } - renameEventLoopTask(); - }; + } + renameEventLoopTask(); + }; - auto onInterrupted = [&]( Mqtt::MqttConnection &mqttConnection, int error ) { + auto onInterrupted = [&]( MqttConnectionWrapper &mqttConnection, int error ) { (void)mqttConnection; TraceModule::get().incrementAtomicVariable( TraceAtomicVariable::CONNECTION_INTERRUPTED ); std::string errorString = "The MQTT Connection has been interrupted due to: "; - auto errStr = ErrorDebugString( error ); + auto errStr = Aws::Crt::ErrorDebugString( error ); errorString.append( errStr != nullptr ? std::string( errStr ) : std::string( "Unknown error" ) ); FWE_LOG_ERROR( errorString ); mConnected = false; }; - auto onResumed = [&]( Mqtt::MqttConnection &mqttConnection, Mqtt::ReturnCode connectCode, bool sessionPresent ) { - (void)mqttConnection; - (void)connectCode; - (void)sessionPresent; - TraceModule::get().incrementAtomicVariable( TraceAtomicVariable::CONNECTION_RESUMED ); - FWE_LOG_INFO( "The MQTT Connection has resumed" ); - mConnected = true; - }; + auto onResumed = + [&]( MqttConnectionWrapper &mqttConnection, Aws::Crt::Mqtt::ReturnCode connectCode, bool sessionPresent ) { + (void)mqttConnection; + (void)connectCode; + (void)sessionPresent; + TraceModule::get().incrementAtomicVariable( TraceAtomicVariable::CONNECTION_RESUMED ); + FWE_LOG_INFO( "The MQTT Connection has resumed" ); + mConnected = true; + }; - auto onDisconnect = [&]( Mqtt::MqttConnection &mqttConnection ) { - (void)mqttConnection; + auto onDisconnect = [&]( MqttConnectionWrapper &connection ) { + (void)connection; FWE_LOG_INFO( "The MQTT Connection is closed" ); mConnectionClosedPromise.set_value(); mConnected = false; mConnectionEstablished = false; }; - mConnection->OnConnectionCompleted = std::move( onConnectionCompleted ); - mConnection->OnDisconnect = std::move( onDisconnect ); - mConnection->OnConnectionInterrupted = std::move( onInterrupted ); - mConnection->OnConnectionResumed = std::move( onResumed ); + mConnection->SetOnConnectionCompleted( onConnectionCompleted ); + mConnection->SetOnDisconnect( onDisconnect ); + mConnection->SetOnConnectionInterrupted( onInterrupted ); + mConnection->SetOnConnectionResumed( onResumed ); - mConnection->SetOnMessageHandler( [&]( Mqtt::MqttConnection &mqttCon, - const String &topic, - const ByteBuf &payload, + mConnection->SetOnMessageHandler( [&]( MqttConnectionWrapper &mqttCon, + const Aws::Crt::String &topic, + const Aws::Crt::ByteBuf &payload, bool dup, - Mqtt::QOS qos, + Aws::Crt::Mqtt::QOS qos, bool retain ) { std::ostringstream os; (void)mqttCon; @@ -214,7 +222,7 @@ AwsIotConnectivityModule::setupCallbacks() void AwsIotConnectivityModule::renameEventLoopTask() { - Aws::IoTFleetWise::Platform::Linux::Thread::SetCurrentThreadName( "fwCNConnectMod" ); + Thread::setCurrentThreadName( "fwCNConnectMod" ); } bool @@ -225,23 +233,9 @@ AwsIotConnectivityModule::createMqttConnection() FWE_LOG_ERROR( "Please provide X.509 Certificate, private Key, endpoint and client-Id" ); return false; } - if ( mClientBootstrap == nullptr ) - { - FWE_LOG_ERROR( "ClientBootstrap failed with error" ); - return false; - } - else if ( !( *mClientBootstrap ) ) - { - auto errString = ErrorDebugString( mClientBootstrap->LastError() ); - FWE_LOG_ERROR( "ClientBootstrap failed with error" ); - FWE_LOG_ERROR( errString != nullptr ? std::string( errString ) : std::string( "Unknown error" ) ); - return false; - } - Aws::Iot::MqttClientConnectionConfigBuilder builder; - - builder = Aws::Iot::MqttClientConnectionConfigBuilder( Crt::ByteCursorFromCString( mCertificate.c_str() ), - Crt::ByteCursorFromCString( mPrivateKey.c_str() ) ); + auto builder = Aws::Iot::MqttClientConnectionConfigBuilder( Crt::ByteCursorFromCString( mCertificate.c_str() ), + Crt::ByteCursorFromCString( mPrivateKey.c_str() ) ); if ( !mRootCA.empty() ) { builder.WithCertificateAuthority( Crt::ByteCursorFromCString( mRootCA.c_str() ) ); @@ -254,7 +248,7 @@ AwsIotConnectivityModule::createMqttConnection() if ( !clientConfig ) { - auto errString = ErrorDebugString( clientConfig.LastError() ); + auto errString = Aws::Crt::ErrorDebugString( clientConfig.LastError() ); FWE_LOG_ERROR( "Client Configuration initialization failed with error" ); FWE_LOG_ERROR( errString != nullptr ? std::string( errString ) : std::string( "Unknown error" ) ); return false; @@ -263,10 +257,10 @@ AwsIotConnectivityModule::createMqttConnection() * Documentation of MqttClient says that the parameter objects needs to live only for the * function call so all the needed objects like bootstrap are on the stack. */ - mMqttClient = std::make_unique( *mClientBootstrap ); + mMqttClient = mCreateMqttClientWrapper(); if ( !*mMqttClient ) { - auto errString = ErrorDebugString( mMqttClient->LastError() ); + auto errString = Aws::Crt::ErrorDebugString( mMqttClient->LastError() ); FWE_LOG_ERROR( "MQTT Client Creation failed with error" ); FWE_LOG_ERROR( errString != nullptr ? std::string( errString ) : std::string( "Unknown error" ) ); return false; @@ -278,7 +272,7 @@ AwsIotConnectivityModule::createMqttConnection() // seconds) if ( !mConnection ) { - auto errString = ErrorDebugString( mMqttClient->LastError() ); + auto errString = Aws::Crt::ErrorDebugString( mMqttClient->LastError() ); auto errLog = errString != nullptr ? std::string( errString ) : std::string( "Unknown error" ); FWE_LOG_ERROR( "MQTT Connection Creation failed with error " + errLog ); return false; @@ -292,7 +286,7 @@ AwsIotConnectivityModule::attempt() if ( !mConnection->Connect( mClientId.c_str(), false, MQTT_CONNECT_KEEP_ALIVE_SECONDS, MQTT_PING_TIMOUT_MS ) ) { std::string error = "The MQTT Connection failed due to: "; - auto errString = ErrorDebugString( mConnection->LastError() ); + auto errString = Aws::Crt::ErrorDebugString( mConnection->LastError() ); error.append( errString != nullptr ? std::string( errString ) : std::string( "Unknown error" ) ); FWE_LOG_WARN( error ); return RetryStatus::RETRY; @@ -334,3 +328,6 @@ AwsIotConnectivityModule::~AwsIotConnectivityModule() { AwsIotConnectivityModule::disconnect(); } + +} // namespace IoTFleetWise +} // namespace Aws diff --git a/src/offboardconnectivity/implementation/aws/iotcpp/include/AwsIotConnectivityModule.h b/src/AwsIotConnectivityModule.h similarity index 87% rename from src/offboardconnectivity/implementation/aws/iotcpp/include/AwsIotConnectivityModule.h rename to src/AwsIotConnectivityModule.h index ef83ec69..ab6d471f 100644 --- a/src/offboardconnectivity/implementation/aws/iotcpp/include/AwsIotConnectivityModule.h +++ b/src/AwsIotConnectivityModule.h @@ -4,21 +4,24 @@ #pragma once #include "AwsIotChannel.h" -#include "Listener.h" +#include "IConnectivityChannel.h" +#include "IConnectivityModule.h" +#include "MqttClientWrapper.h" +#include "MqttConnectionWrapper.h" +#include "PayloadManager.h" #include "RetryThread.h" #include -#include -#include +#include +#include #include +#include #include +#include namespace Aws { namespace IoTFleetWise { -namespace OffboardConnectivityAwsIot -{ -using namespace Aws::IoTFleetWise::Platform::Linux; /** * @brief bootstrap of the Aws Iot SDK. Only one object of this should normally exist @@ -43,8 +46,7 @@ class AwsIotConnectivityModule : public IRetryable, public IConnectivityModule * @param endpointUrl the endpoint URL normally in the format like * "[YOUR-THING]-ats.iot.us-west-2.amazonaws.com" * @param clientId the id that is used to identify this connection instance - * @param clientBootstrap pointer to AWS client bootstrap. Note AwsBootstrap is responsible for the client - * bootstrap lifecycle + * @param createMqttClientWrapper a factory function that creates a new MqttClient instance * @param asynchronous * If asynchronous is false this function blocks until it succeeded or failed. Also if asynchronous is false * no retries are done to try to reconnected if initial connection could not be established. @@ -56,7 +58,7 @@ class AwsIotConnectivityModule : public IRetryable, public IConnectivityModule std::string rootCA, std::string endpointUrl, std::string clientId, - Aws::Crt::Io::ClientBootstrap *clientBootstrap, + std::function()> createMqttClientWrapper, bool asynchronous = false ); ~AwsIotConnectivityModule() override; @@ -100,7 +102,7 @@ class AwsIotConnectivityModule : public IRetryable, public IConnectivityModule std::shared_ptr createNewChannel( const std::shared_ptr &payloadManager ) override; - std::shared_ptr mConnection; + std::shared_ptr mConnection; private: bool createMqttConnection(); @@ -113,8 +115,8 @@ class AwsIotConnectivityModule : public IRetryable, public IConnectivityModule std::string mRootCA; std::string mEndpointUrl; std::string mClientId; - std::unique_ptr mMqttClient; - Aws::Crt::Io::ClientBootstrap *mClientBootstrap; + std::shared_ptr mMqttClient; + std::function()> mCreateMqttClientWrapper; bool mAsynchronous; RetryThread mRetryThread; @@ -125,6 +127,6 @@ class AwsIotConnectivityModule : public IRetryable, public IConnectivityModule std::vector> mChannels; }; -} // namespace OffboardConnectivityAwsIot + } // namespace IoTFleetWise } // namespace Aws diff --git a/src/offboardconnectivity/implementation/aws/bootstrap/src/AwsSDKMemoryManager.cpp b/src/AwsSDKMemoryManager.cpp similarity index 94% rename from src/offboardconnectivity/implementation/aws/bootstrap/src/AwsSDKMemoryManager.cpp rename to src/AwsSDKMemoryManager.cpp index 74d18b47..1c6b8db9 100644 --- a/src/offboardconnectivity/implementation/aws/bootstrap/src/AwsSDKMemoryManager.cpp +++ b/src/AwsSDKMemoryManager.cpp @@ -3,19 +3,14 @@ #include "AwsSDKMemoryManager.h" #include "TraceModule.h" -#include #include +#include namespace Aws { namespace IoTFleetWise { -namespace OffboardConnectivityAwsIot -{ -namespace -{ -using namespace Aws::IoTFleetWise::Platform::Linux; using Byte = unsigned char; // offset to store value of memory size allocated @@ -26,8 +21,6 @@ using Byte = unsigned char; // We are OK at the moment to not handled over-aligned types since we do not have any usage of "alignas" constexpr auto ALIGN_OFFSET = alignof( std::max_align_t ); -} // namespace - AwsSDKMemoryManager & AwsSDKMemoryManager::getInstance() { @@ -130,6 +123,5 @@ AwsSDKMemoryManager::releaseReservedMemory( std::size_t bytes ) return mMemoryUsedAndReserved; } -} // namespace OffboardConnectivityAwsIot } // namespace IoTFleetWise } // namespace Aws diff --git a/src/offboardconnectivity/implementation/aws/bootstrap/include/AwsSDKMemoryManager.h b/src/AwsSDKMemoryManager.h similarity index 94% rename from src/offboardconnectivity/implementation/aws/bootstrap/include/AwsSDKMemoryManager.h rename to src/AwsSDKMemoryManager.h index b68f20f0..de4d1cf4 100644 --- a/src/offboardconnectivity/implementation/aws/bootstrap/include/AwsSDKMemoryManager.h +++ b/src/AwsSDKMemoryManager.h @@ -2,15 +2,13 @@ // SPDX-License-Identifier: Apache-2.0 #include -#include +#include #include namespace Aws { namespace IoTFleetWise { -namespace OffboardConnectivityAwsIot -{ /** * @brief A minimal allocate implementation. @@ -79,6 +77,6 @@ class AwsSDKMemoryManager : public Aws::Utils::Memory::MemorySystemInterface size_t mMaximumAwsSDKMemorySize = MAXIMUM_AWS_SDK_HEAP_MEMORY_BYTES; }; -} // namespace OffboardConnectivityAwsIot + } // namespace IoTFleetWise } // namespace Aws diff --git a/src/datamanagement/datainspection/src/vehicledatasource/CANDataConsumer.cpp b/src/CANDataConsumer.cpp similarity index 97% rename from src/datamanagement/datainspection/src/vehicledatasource/CANDataConsumer.cpp rename to src/CANDataConsumer.cpp index b2c0603b..62dc8ce0 100644 --- a/src/datamanagement/datainspection/src/vehicledatasource/CANDataConsumer.cpp +++ b/src/CANDataConsumer.cpp @@ -1,19 +1,26 @@ // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 -// Includes #include "CANDataConsumer.h" +#include "CANDataTypes.h" #include "CANDecoder.h" +#include "EnumUtility.h" #include "LoggingModule.h" +#include "MessageTypes.h" #include "TraceModule.h" +#include +#include +#include #include +#include +#include +#include +#include namespace Aws { namespace IoTFleetWise { -namespace DataInspection -{ CANDataConsumer::CANDataConsumer( SignalBufferPtr signalBufferPtr, CANBufferPtr canBufferPtr ) : mCANBufferPtr{ std::move( canBufferPtr ) } @@ -184,6 +191,5 @@ CANDataConsumer::processMessage( CANChannelNumericID channelId, } } -} // namespace DataInspection } // namespace IoTFleetWise } // namespace Aws diff --git a/src/datamanagement/datainspection/include/CANDataConsumer.h b/src/CANDataConsumer.h similarity index 92% rename from src/datamanagement/datainspection/include/CANDataConsumer.h rename to src/CANDataConsumer.h index 093af3f7..d53f7524 100644 --- a/src/datamanagement/datainspection/include/CANDataConsumer.h +++ b/src/CANDataConsumer.h @@ -3,13 +3,11 @@ #pragma once -// Includes - -#include "CANDataTypes.h" #include "CollectionInspectionAPITypes.h" #include "IDecoderDictionary.h" #include "SignalTypes.h" #include "TimeTypes.h" +#include #include #include @@ -17,9 +15,7 @@ namespace Aws { namespace IoTFleetWise { -namespace DataInspection -{ -using namespace Aws::IoTFleetWise::Platform::Linux; + /** * @brief CAN Network Data Consumer impl, outputs data to an in-memory buffer. * Operates in Polling mode. @@ -57,6 +53,6 @@ class CANDataConsumer CANBufferPtr mCANBufferPtr; SignalBufferPtr mSignalBufferPtr; }; -} // namespace DataInspection + } // namespace IoTFleetWise } // namespace Aws diff --git a/src/datamanagement/datainspection/src/vehicledatasource/CANDataSource.cpp b/src/CANDataSource.cpp similarity index 98% rename from src/datamanagement/datainspection/src/vehicledatasource/CANDataSource.cpp rename to src/CANDataSource.cpp index 454e5e15..568fcceb 100644 --- a/src/datamanagement/datainspection/src/vehicledatasource/CANDataSource.cpp +++ b/src/CANDataSource.cpp @@ -1,27 +1,25 @@ // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 -#if defined( IOTFLEETWISE_LINUX ) -// Includes #include "CANDataSource.h" #include "EnumUtility.h" #include "LoggingModule.h" #include "TraceModule.h" #include +#include #include #include #include #include #include #include +#include +#include namespace Aws { namespace IoTFleetWise { -namespace DataInspection -{ -using namespace Aws::IoTFleetWise::Platform::Utility; CANDataSource::CANDataSource( CANChannelNumericID channelId, CanTimestampType timestampTypeToUse, @@ -167,7 +165,7 @@ CANDataSource::doWork( void *data ) // We either just started or there was a decoder manifest update that we can't use // We should sleep FWE_LOG_TRACE( "No valid decoding dictionary available, Channel going to sleep" ); - dataSource->mWait.wait( Platform::Linux::Signal::WaitWithPredicate ); + dataSource->mWait.wait( Signal::WaitWithPredicate ); wokeUpFromSleep = true; } @@ -255,6 +253,7 @@ CANDataSource::connect() mSocket = socket( PF_CAN, type, CAN_RAW ); if ( mSocket < 0 ) { + FWE_LOG_ERROR( "Failed to create socket: " + getErrnoString() ); return false; } // Switch Socket can_fd mode on or fallback with a log if it fails @@ -304,6 +303,7 @@ CANDataSource::connect() // NOLINTNEXTLINE(cppcoreguidelines-pro-type-cstyle-cast) if ( bind( mSocket, (struct sockaddr *)&interfaceAddress, sizeof( interfaceAddress ) ) < 0 ) { + FWE_LOG_ERROR( "Failed to bind socket: " + getErrnoString() ); close( mSocket ); return false; } @@ -353,7 +353,5 @@ CANDataSource::onChangeOfActiveDictionary( ConstDecoderDictionaryConstPtr &dicti } } -} // namespace DataInspection } // namespace IoTFleetWise } // namespace Aws -#endif // IOTFLEETWISE_LINUX diff --git a/src/datamanagement/datainspection/include/CANDataSource.h b/src/CANDataSource.h similarity index 93% rename from src/datamanagement/datainspection/include/CANDataSource.h rename to src/CANDataSource.h index 63e4c235..d495d3ad 100644 --- a/src/datamanagement/datainspection/include/CANDataSource.h +++ b/src/CANDataSource.h @@ -3,11 +3,9 @@ #pragma once -#if defined( IOTFLEETWISE_LINUX ) -// Includes #include "CANDataConsumer.h" +#include "Clock.h" #include "ClockHandler.h" -#include "CollectionInspectionAPITypes.h" #include "IActiveDecoderDictionaryListener.h" #include "IDecoderDictionary.h" #include "Signal.h" @@ -15,21 +13,18 @@ #include "Thread.h" #include "TimeTypes.h" #include "Timer.h" +#include "VehicleDataSourceTypes.h" #include #include #include #include #include -#include - -using namespace Aws::IoTFleetWise::Platform::Linux; +#include // IWYU pragma: keep namespace Aws { namespace IoTFleetWise { -namespace DataInspection -{ // This timestamp is used when uploading data to the cloud enum class CanTimestampType @@ -128,7 +123,7 @@ class CANDataSource : public IActiveDecoderDictionaryListener Timer mTimer; std::shared_ptr mClock = ClockHandler::getClock(); int mSocket{ -1 }; - Platform::Linux::Signal mWait; + Signal mWait; uint32_t mIdleTimeMs{ DEFAULT_THREAD_IDLE_TIME_MS }; uint64_t mReceivedMessages{ 0 }; CanTimestampType mTimestampTypeToUse{ CanTimestampType::KERNEL_SOFTWARE_TIMESTAMP }; @@ -140,8 +135,5 @@ class CANDataSource : public IActiveDecoderDictionaryListener CANDataConsumer &mConsumer; }; -} // namespace DataInspection } // namespace IoTFleetWise } // namespace Aws - -#endif // IOTFLEETWISE_LINUX diff --git a/src/datamanagement/types/include/CANDataTypes.h b/src/CANDataTypes.h similarity index 93% rename from src/datamanagement/types/include/CANDataTypes.h rename to src/CANDataTypes.h index cc140e73..cae0ddd4 100644 --- a/src/datamanagement/types/include/CANDataTypes.h +++ b/src/CANDataTypes.h @@ -3,7 +3,6 @@ #pragma once -// Includes #include "SignalTypes.h" #include "TimeTypes.h" #include @@ -12,9 +11,6 @@ namespace Aws { namespace IoTFleetWise { -namespace DataManagement -{ -using namespace Aws::IoTFleetWise::Platform::Linux; union CANPhysicalValue { double doubleVal; @@ -73,6 +69,5 @@ struct CANDecodedSignal */ static constexpr uint8_t MAX_CAN_FRAME_BYTE_SIZE = 64; -} // namespace DataManagement } // namespace IoTFleetWise } // namespace Aws diff --git a/src/datamanagement/datadecoding/src/CANDecoder.cpp b/src/CANDecoder.cpp similarity index 99% rename from src/datamanagement/datadecoding/src/CANDecoder.cpp rename to src/CANDecoder.cpp index f17a048e..39ac5133 100644 --- a/src/datamanagement/datadecoding/src/CANDecoder.cpp +++ b/src/CANDecoder.cpp @@ -1,19 +1,18 @@ // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 -// Includes #include "CANDecoder.h" #include "LoggingModule.h" #include -#include +#include +#include + #define MASK64( nbits ) ( static_cast( 0xFFFFFFFFFFFFFFFFULL ) >> ( 64 - ( nbits ) ) ) namespace Aws { namespace IoTFleetWise { -namespace DataManagement -{ bool CANDecoder::decodeCANMessage( const uint8_t *frameData, @@ -202,6 +201,5 @@ CANDecoder::extractSignalFromFrame( const uint8_t *frameData, const CANSignalFor return static_cast( result ); } -} // namespace DataManagement } // namespace IoTFleetWise } // namespace Aws diff --git a/src/datamanagement/datadecoding/include/CANDecoder.h b/src/CANDecoder.h similarity index 93% rename from src/datamanagement/datadecoding/include/CANDecoder.h rename to src/CANDecoder.h index d8bd2b95..2370b303 100644 --- a/src/datamanagement/datadecoding/include/CANDecoder.h +++ b/src/CANDecoder.h @@ -3,20 +3,19 @@ #pragma once -// Includes #include "CANDataTypes.h" #include "MessageTypes.h" #include "SignalTypes.h" +#include #include #include #include + namespace Aws { namespace IoTFleetWise { -namespace DataManagement -{ -using namespace Aws::IoTFleetWise::Platform::Linux; + /** * @brief CAN Bus decoder. Decodes a given raw message frame according * to the DBC schema @@ -51,6 +50,5 @@ class CANDecoder static int64_t extractSignalFromFrame( const uint8_t *frameData, const CANSignalFormat &signalDescription ); }; -} // namespace DataManagement } // namespace IoTFleetWise } // namespace Aws diff --git a/src/datamanagement/datacollection/include/CANInterfaceIDTranslator.h b/src/CANInterfaceIDTranslator.h similarity index 95% rename from src/datamanagement/datacollection/include/CANInterfaceIDTranslator.h rename to src/CANInterfaceIDTranslator.h index 1b110955..37c3527e 100644 --- a/src/datamanagement/datacollection/include/CANInterfaceIDTranslator.h +++ b/src/CANInterfaceIDTranslator.h @@ -10,9 +10,6 @@ namespace Aws { namespace IoTFleetWise { -namespace DataManagement -{ - /** * @brief Translate the internal used Id to the Id used in config file and decoder manifest * Adding new items is not thread safe @@ -59,6 +56,5 @@ class CANInterfaceIDTranslator CANChannelNumericID mCounter{ 0 }; }; -} // namespace DataManagement } // namespace IoTFleetWise } // namespace Aws diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt deleted file mode 100644 index 091c23ec..00000000 --- a/src/CMakeLists.txt +++ /dev/null @@ -1,39 +0,0 @@ -# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. - -# In this configuration file, applications and libraries are added to the -# compilation configuration. This is where CMake options can be added to switch -# parts on/off - -option(FWE_BUILD_PLATFORM "Build a Platform, type based on PLATFORM_TYPE." ON) -option(FWE_BUILD_VEHICLE_NETWORK "Build the vehiclenetwork library" ON) -option(FWE_BUILD_DATA_MANAGEMENT "Build the datamanagement library" ON) -option(FWE_BUILD_APP_TEST "Builds the sample app-test" ON) -option(FWE_BUILD_EXECUTION_MANAGEMENT "Build the Execution management library and application" ON) -option(FWE_BUILD_CONNECTIVITY "Build the off board connectivity module library" ON) - - -# set(CMAKE_CXX_CLANG_TIDY clang-tidy) - -if(FWE_BUILD_PLATFORM) - add_subdirectory(platform) -endif() - -if(FWE_BUILD_VEHICLE_NETWORK) - add_subdirectory(vehiclenetwork) -endif() - -if(FWE_BUILD_DATA_MANAGEMENT) - add_subdirectory(datamanagement) -endif() - -if(FWE_BUILD_EXECUTION_MANAGEMENT) - add_subdirectory(executionmanagement) -endif() - -if(FWE_BUILD_CONNECTIVITY) - add_subdirectory(offboardconnectivity) -endif() - -if(BUILD_TESTING) - add_subdirectory(testingsupport) -endif() diff --git a/src/platform/linux/resourcemanagement/src/CPUUsageInfo.cpp b/src/CPUUsageInfo.cpp similarity index 97% rename from src/platform/linux/resourcemanagement/src/CPUUsageInfo.cpp rename to src/CPUUsageInfo.cpp index 94af28ff..dd517bb9 100644 --- a/src/platform/linux/resourcemanagement/src/CPUUsageInfo.cpp +++ b/src/CPUUsageInfo.cpp @@ -1,26 +1,21 @@ // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 -#if defined( IOTFLEETWISE_LINUX ) -// Includes #include "CPUUsageInfo.h" #include +#include +#include #include #include -#include #include #include -#include #include namespace Aws { namespace IoTFleetWise { -namespace Platform -{ -namespace Linux -{ + bool CPUUsageInfo::reportCPUUsageInfo() { @@ -173,8 +168,6 @@ CPUUsageInfo::reportPerThreadUsageData( CPUUsageInfo::ThreadCPUUsageInfos &threa closedir( taskDir ); return true; } -} // namespace Linux -} // namespace Platform + } // namespace IoTFleetWise } // namespace Aws -#endif // IOTFLEETWISE_LINUX diff --git a/src/platform/linux/resourcemanagement/include/CPUUsageInfo.h b/src/CPUUsageInfo.h similarity index 97% rename from src/platform/linux/resourcemanagement/include/CPUUsageInfo.h rename to src/CPUUsageInfo.h index 54b176c6..d09d2787 100644 --- a/src/platform/linux/resourcemanagement/include/CPUUsageInfo.h +++ b/src/CPUUsageInfo.h @@ -3,10 +3,9 @@ #pragma once -#if defined( IOTFLEETWISE_LINUX ) -// Includes - +#include #include +#include #include #include #include @@ -15,10 +14,7 @@ namespace Aws { namespace IoTFleetWise { -namespace Platform -{ -namespace Linux -{ + /** * @brief Utility class to track and report CPU commutative time usage. */ @@ -179,8 +175,6 @@ CPUUsageInfo::getTotalCPUPercentage( const CPUUsageInfo &previousUsage, const do double systemTime = ( mKernelSpaceTime - previousUsage.getKernelSpaceTime() ) / mNumCPUCores; return round( ( userTime + systemTime ) / elapsedSeconds * 10000.0 ) / 100.0; } -} // namespace Linux -} // namespace Platform + } // namespace IoTFleetWise } // namespace Aws -#endif // IOTFLEETWISE_LINUX diff --git a/src/platform/linux/persistencymanagement/src/CacheAndPersist.cpp b/src/CacheAndPersist.cpp similarity index 99% rename from src/platform/linux/persistencymanagement/src/CacheAndPersist.cpp rename to src/CacheAndPersist.cpp index 50a8cb19..0c3695fc 100644 --- a/src/platform/linux/persistencymanagement/src/CacheAndPersist.cpp +++ b/src/CacheAndPersist.cpp @@ -1,7 +1,6 @@ // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 -// Includes #include "CacheAndPersist.h" #include "LoggingModule.h" #include @@ -9,8 +8,13 @@ #include #include #include +#include +#include -using namespace Aws::IoTFleetWise::Platform::Linux::PersistencyManagement; +namespace Aws +{ +namespace IoTFleetWise +{ CacheAndPersist::CacheAndPersist( const std::string &partitionPath, size_t maxPartitionSize ) : mPersistencyPath{ partitionPath } @@ -559,3 +563,6 @@ CacheAndPersist::~CacheAndPersist() writeMetadata( mPersistedMetadata ); cleanupPersistedData(); } + +} // namespace IoTFleetWise +} // namespace Aws diff --git a/src/platform/linux/persistencymanagement/include/CacheAndPersist.h b/src/CacheAndPersist.h similarity index 98% rename from src/platform/linux/persistencymanagement/include/CacheAndPersist.h rename to src/CacheAndPersist.h index b69ec89a..b13ed64e 100644 --- a/src/platform/linux/persistencymanagement/include/CacheAndPersist.h +++ b/src/CacheAndPersist.h @@ -3,13 +3,10 @@ #pragma once -// Includes +#include #include #include -#include -#include #include -#include // max buffer to be allocated for a read buffer // this matches the Max Send Size on the AWS IoT channel @@ -22,12 +19,6 @@ namespace Aws { namespace IoTFleetWise { -namespace Platform -{ -namespace Linux -{ -namespace PersistencyManagement -{ enum class ErrorCode { @@ -314,8 +305,6 @@ class CacheAndPersist */ ErrorCode cleanupDeprecatedFiles(); }; -} // namespace PersistencyManagement -} // namespace Linux -} // namespace Platform + } // namespace IoTFleetWise } // namespace Aws diff --git a/src/datamanagement/datamanager/src/CheckinAndPersistency.cpp b/src/CheckinAndPersistency.cpp similarity index 97% rename from src/datamanagement/datamanager/src/CheckinAndPersistency.cpp rename to src/CheckinAndPersistency.cpp index f592cb26..34fadfde 100644 --- a/src/datamanagement/datamanager/src/CheckinAndPersistency.cpp +++ b/src/CheckinAndPersistency.cpp @@ -1,12 +1,12 @@ // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 -// Includes #include "CollectionSchemeIngestionList.h" -#include "CollectionSchemeManager.h" +#include "CollectionSchemeManager.h" // IWYU pragma: associated #include "DecoderManifestIngestion.h" #include "EnumUtility.h" #include "LoggingModule.h" +#include #include #include @@ -14,9 +14,7 @@ namespace Aws { namespace IoTFleetWise { -namespace DataManagement -{ -using namespace Aws::IoTFleetWise::Platform::Utility; + void CollectionSchemeManager::prepareCheckinTimer() { @@ -192,6 +190,6 @@ CollectionSchemeManager::store( DataType storeType ) FWE_LOG_TRACE( logStr + " persisted successfully" ); } } -} // namespace DataManagement + } // namespace IoTFleetWise } // namespace Aws diff --git a/src/platform/linux/timemanagement/include/Clock.h b/src/Clock.h similarity index 96% rename from src/platform/linux/timemanagement/include/Clock.h rename to src/Clock.h index 1c8d811c..0ab539cc 100644 --- a/src/platform/linux/timemanagement/include/Clock.h +++ b/src/Clock.h @@ -3,7 +3,6 @@ #pragma once -// Includes #include "TimeTypes.h" #include @@ -11,10 +10,6 @@ namespace Aws { namespace IoTFleetWise { -namespace Platform -{ -namespace Linux -{ /** * @brief Clock API. Offers the time based on multiple clocks. @@ -80,7 +75,5 @@ class Clock */ TimePoint timePointFromSystemTime( const TimePoint &currTime, Timestamp systemTimeMs ); -} // namespace Linux -} // namespace Platform } // namespace IoTFleetWise } // namespace Aws diff --git a/src/platform/linux/timemanagement/src/ClockHandler.cpp b/src/ClockHandler.cpp similarity index 97% rename from src/platform/linux/timemanagement/src/ClockHandler.cpp rename to src/ClockHandler.cpp index b9b24ba8..31c49591 100644 --- a/src/platform/linux/timemanagement/src/ClockHandler.cpp +++ b/src/ClockHandler.cpp @@ -1,21 +1,21 @@ // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 -// Includes #include "ClockHandler.h" +#include "TimeTypes.h" #include +#include #include #include #include +#include +#include namespace Aws { namespace IoTFleetWise { -namespace Platform -{ -namespace Linux -{ + static std::shared_ptr gClock; static std::mutex gClockMutex; @@ -111,7 +111,5 @@ ClockHandler::setClock( std::shared_ptr clock ) gClock = std::move( clock ); } -} // namespace Linux -} // namespace Platform } // namespace IoTFleetWise } // namespace Aws diff --git a/src/platform/linux/timemanagement/include/ClockHandler.h b/src/ClockHandler.h similarity index 90% rename from src/platform/linux/timemanagement/include/ClockHandler.h rename to src/ClockHandler.h index a8aae992..ae29cfda 100644 --- a/src/platform/linux/timemanagement/include/ClockHandler.h +++ b/src/ClockHandler.h @@ -3,8 +3,6 @@ #pragma once -// Includes - #include "Clock.h" #include @@ -12,10 +10,6 @@ namespace Aws { namespace IoTFleetWise { -namespace Platform -{ -namespace Linux -{ /** * @brief This module allows users to inject an external clock into the system. @@ -39,7 +33,5 @@ class ClockHandler static void setClock( std::shared_ptr clock ); }; -} // namespace Linux -} // namespace Platform } // namespace IoTFleetWise } // namespace Aws diff --git a/src/datamanagement/types/include/CollectionInspectionAPITypes.h b/src/CollectionInspectionAPITypes.h similarity index 89% rename from src/datamanagement/types/include/CollectionInspectionAPITypes.h rename to src/CollectionInspectionAPITypes.h index 24d59063..999bb669 100644 --- a/src/datamanagement/types/include/CollectionInspectionAPITypes.h +++ b/src/CollectionInspectionAPITypes.h @@ -1,5 +1,6 @@ // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 + #pragma once #include "CANDataTypes.h" @@ -8,10 +9,10 @@ #include "MessageTypes.h" #include "OBDDataTypes.h" #include "SignalTypes.h" -// multi producer queue: -#include -// single producer queue: -#include +#include // multi producer queue +#include // single producer queue +#include +#include #include namespace Aws @@ -19,14 +20,7 @@ namespace Aws namespace IoTFleetWise { -namespace DataManagement -{ struct ExpressionNode; -} // namespace DataManagement - -namespace DataInspection -{ -using namespace Aws::IoTFleetWise::DataManagement; static constexpr uint32_t MAX_NUMBER_OF_ACTIVE_CONDITION = 256; /**< More active conditions will be ignored */ static constexpr uint32_t ALL_CONDITIONS = 0xFFFFFFFF; @@ -349,11 +343,55 @@ struct TriggeredCollectionSchemeData }; using TriggeredCollectionSchemeDataPtr = std::shared_ptr; -using CollectedDataReadyToPublish = - boost::lockfree::spsc_queue; /**< produced by Inspection and Collection Engine - consumed by Sender to cloud. As the data can be - big only a shared_ptr is handed over*/ +struct CollectedDataReadyToPublish +{ +public: + CollectedDataReadyToPublish( size_t maxSize ) + : mMaxSize( maxSize ) + { + } + bool + push( const TriggeredCollectionSchemeDataPtr &data ) + { + std::lock_guard lock( mMutex ); + if ( ( mQueue.size() + 1 ) > mMaxSize ) + { + return false; + } + mQueue.push( data ); + return true; + } + bool + pop( TriggeredCollectionSchemeDataPtr &data ) + { + std::lock_guard lock( mMutex ); + if ( mQueue.empty() ) + { + return false; + } + data = mQueue.front(); + mQueue.pop(); + return true; + } + template + size_t + consume_all( const Functor &functor ) + { + size_t consumed = 0; + TriggeredCollectionSchemeDataPtr data; + while ( pop( data ) ) + { + functor( data ); + consumed++; + } + return consumed; + } + +private: + std::mutex mMutex; + size_t mMaxSize; + std::queue mQueue; /**< As the data can be big only a shared_ptr is handed over*/ +}; -} // namespace DataInspection } // namespace IoTFleetWise } // namespace Aws diff --git a/src/datamanagement/datainspection/src/CollectionInspectionEngine.cpp b/src/CollectionInspectionEngine.cpp similarity index 99% rename from src/datamanagement/datainspection/src/CollectionInspectionEngine.cpp rename to src/CollectionInspectionEngine.cpp index c7209f20..109262bf 100644 --- a/src/datamanagement/datainspection/src/CollectionInspectionEngine.cpp +++ b/src/CollectionInspectionEngine.cpp @@ -2,17 +2,14 @@ // SPDX-License-Identifier: Apache-2.0 #include "CollectionInspectionEngine.h" -#include "ClockHandler.h" #include "TraceModule.h" #include -#include +#include namespace Aws { namespace IoTFleetWise { -namespace DataInspection -{ CollectionInspectionEngine::CollectionInspectionEngine( bool sendDataOnlyOncePerCondition ) : mSendDataOnlyOncePerCondition( sendDataOnlyOncePerCondition ) @@ -21,7 +18,7 @@ CollectionInspectionEngine::CollectionInspectionEngine( bool sendDataOnlyOncePer } bool -CollectionInspectionEngine::isSignalPartOfEval( const struct ExpressionNode *expression, +CollectionInspectionEngine::isSignalPartOfEval( const ExpressionNode *expression, InspectionSignalID signalID, int remainingStackDepth ) { @@ -1084,7 +1081,7 @@ CollectionInspectionEngine::getSampleWindowFunction( WindowFunction function, } CollectionInspectionEngine::ExpressionErrorCode -CollectionInspectionEngine::getGeohashFunctionNode( const struct ExpressionNode *expression, +CollectionInspectionEngine::getGeohashFunctionNode( const ExpressionNode *expression, ActiveCondition &condition, bool &resultValueBool ) { @@ -1112,7 +1109,7 @@ CollectionInspectionEngine::getGeohashFunctionNode( const struct ExpressionNode } CollectionInspectionEngine::ExpressionErrorCode -CollectionInspectionEngine::eval( const struct ExpressionNode *expression, +CollectionInspectionEngine::eval( const ExpressionNode *expression, ActiveCondition &condition, InspectionValue &resultValueDouble, bool &resultValueBool, @@ -1229,6 +1226,5 @@ CollectionInspectionEngine::generateEventID( InspectionTimestamp timestamp ) return eventId; } -} // namespace DataInspection } // namespace IoTFleetWise } // namespace Aws diff --git a/src/datamanagement/datainspection/include/CollectionInspectionEngine.h b/src/CollectionInspectionEngine.h similarity index 97% rename from src/datamanagement/datainspection/include/CollectionInspectionEngine.h rename to src/CollectionInspectionEngine.h index 583bf214..c26c6ba8 100644 --- a/src/datamanagement/datainspection/include/CollectionInspectionEngine.h +++ b/src/CollectionInspectionEngine.h @@ -3,25 +3,40 @@ #pragma once +#include "CANDataTypes.h" +#include "CollectionInspectionAPITypes.h" #include "DataReduction.h" +#include "EventTypes.h" #include "GeohashFunctionNode.h" #include "IActiveConditionProcessor.h" +#include "ICollectionScheme.h" #include "InspectionEventListener.h" #include "Listener.h" #include "LoggingModule.h" +#include "MessageTypes.h" +#include "OBDDataTypes.h" +#include "SignalTypes.h" +#include "TimeTypes.h" +#include +#include +#include +#include // As _Find_first() is not part of C++ standard and compiler specific other structure could be considered +#include +#include #include +#include +#include #include -// As _Find_first() is not part of C++ standard and compiler specific other structure could be considered -#include -#include +#include +#include namespace Aws { namespace IoTFleetWise { -namespace DataInspection -{ -using namespace Aws::IoTFleetWise::Platform::Linux; + +using InspectionSignalID = uint32_t; + /** * @brief Main class to implement collection and inspection engine logic * @@ -34,7 +49,6 @@ class CollectionInspectionEngine : public IActiveConditionProcessor, public Thre public: using InspectionTimestamp = uint64_t; - using InspectionSignalID = uint32_t; using InspectionValue = double; /** @@ -456,11 +470,9 @@ class CollectionInspectionEngine : public IActiveConditionProcessor, public Thre }; bool preAllocateBuffers(); - bool isSignalPartOfEval( const struct ExpressionNode *expression, - InspectionSignalID signalID, - int remainingStackDepth ); + bool isSignalPartOfEval( const ExpressionNode *expression, InspectionSignalID signalID, int remainingStackDepth ); - ExpressionErrorCode eval( const struct ExpressionNode *expression, + ExpressionErrorCode eval( const ExpressionNode *expression, ActiveCondition &condition, InspectionValue &resultValueDouble, bool &resultValueBool, @@ -479,7 +491,7 @@ class CollectionInspectionEngine : public IActiveConditionProcessor, public Thre ActiveCondition &condition, InspectionValue &result ); - ExpressionErrorCode getGeohashFunctionNode( const struct ExpressionNode *expression, + ExpressionErrorCode getGeohashFunctionNode( const ExpressionNode *expression, ActiveCondition &condition, bool &resultValueBool ); template @@ -735,6 +747,5 @@ CollectionInspectionEngine::FixedTimeWindowFunctionData::updateWindow( return true; } -} // namespace DataInspection } // namespace IoTFleetWise } // namespace Aws diff --git a/src/datamanagement/datainspection/src/CollectionInspectionWorkerThread.cpp b/src/CollectionInspectionWorkerThread.cpp similarity index 98% rename from src/datamanagement/datainspection/src/CollectionInspectionWorkerThread.cpp rename to src/CollectionInspectionWorkerThread.cpp index 29ef5a73..86ab0d70 100644 --- a/src/datamanagement/datainspection/src/CollectionInspectionWorkerThread.cpp +++ b/src/CollectionInspectionWorkerThread.cpp @@ -2,15 +2,21 @@ // SPDX-License-Identifier: Apache-2.0 #include "CollectionInspectionWorkerThread.h" +#include "CANDataTypes.h" #include "LoggingModule.h" +#include "OBDDataTypes.h" +#include "SignalTypes.h" #include "TraceModule.h" +#include +#include +#include +#include +#include namespace Aws { namespace IoTFleetWise { -namespace DataInspection -{ bool CollectionInspectionWorkerThread::init( const std::shared_ptr &inputSignalBuffer, @@ -314,7 +320,7 @@ CollectionInspectionWorkerThread::doWork( void *data ) else { // No inspection Matrix available. Wait for it from the CollectionScheme manager - consumer->fWait.wait( Platform::Linux::Signal::WaitWithPredicate ); + consumer->fWait.wait( Signal::WaitWithPredicate ); } if ( consumer->shouldStop() ) { @@ -353,6 +359,5 @@ CollectionInspectionWorkerThread::~CollectionInspectionWorkerThread() } } -} // namespace DataInspection } // namespace IoTFleetWise } // namespace Aws diff --git a/src/datamanagement/datainspection/include/CollectionInspectionWorkerThread.h b/src/CollectionInspectionWorkerThread.h similarity index 76% rename from src/datamanagement/datainspection/include/CollectionInspectionWorkerThread.h rename to src/CollectionInspectionWorkerThread.h index 03c3face..b53d3cc2 100644 --- a/src/datamanagement/datainspection/include/CollectionInspectionWorkerThread.h +++ b/src/CollectionInspectionWorkerThread.h @@ -3,21 +3,26 @@ #pragma once +#include "Clock.h" #include "ClockHandler.h" +#include "CollectionInspectionAPITypes.h" #include "CollectionInspectionEngine.h" +#include "IActiveConditionProcessor.h" #include "IDataReadyToPublishListener.h" +#include "InspectionEventListener.h" #include "Listener.h" #include "Signal.h" #include "Thread.h" -#include "Timer.h" +#include "TimeTypes.h" +#include +#include +#include +#include + namespace Aws { namespace IoTFleetWise { -namespace DataInspection -{ -using namespace Aws::IoTFleetWise::DataManagement; -using Aws::IoTFleetWise::Platform::Linux::ThreadListeners; class CollectionInspectionWorkerThread : public IActiveConditionProcessor, public ThreadListeners @@ -41,21 +46,19 @@ class CollectionInspectionWorkerThread : public IActiveConditionProcessor, /** * @brief Initialize the component by handing over all queues - * @param inputSignalBuffer IVehicleDataSourceConsumer instances will put relevant signals in this queue - * @param inputCANBuffer CANDataConsumers will put relevant raw can frames in this queue - * @param inputActiveDTCBuffer OBDModule DTC Circular buffer - * @param outputCollectedData this thread will put data that should be sent to cloud into this queue - * @param idleTimeMs if no new data is available sleep for this amount of milliseconds - * @param dataReductionProbabilityDisabled set to true to disable data reduction using probability * * @return true if initialization was successful * */ - bool init( const std::shared_ptr &inputSignalBuffer, - const std::shared_ptr &inputCANBuffer, - const std::shared_ptr &inputActiveDTCBuffer, - const std::shared_ptr &outputCollectedData, - uint32_t idleTimeMs, - bool dataReductionProbabilityDisabled = false ); + bool init( + const std::shared_ptr &inputSignalBuffer, /**< IVehicleDataSourceConsumer instances will + put relevant signals in this queue */ + const std::shared_ptr + &inputCANBuffer, /**< CANDataConsumers will put relevant raw can frames in this queue */ + const std::shared_ptr &inputActiveDTCBuffer, /**< OBDModule DTC Circular buffer */ + const std::shared_ptr + &outputCollectedData, /**< this thread will put data that should be sent to cloud into this queue */ + uint32_t idleTimeMs, /**< if no new data is available sleep for this amount of milliseconds */ + bool dataReductionProbabilityDisabled = false /**< set to true to disable data reduction using probability*/ ); /** * @brief stops the internal thread if started and wait until it finishes @@ -124,11 +127,10 @@ class CollectionInspectionWorkerThread : public IActiveConditionProcessor, std::shared_ptr fUpdatedInspectionMatrix; std::mutex fInspectionMatrixMutex; std::mutex fThreadMutex; - Platform::Linux::Signal fWait; + Signal fWait; uint32_t fIdleTimeMs{ DEFAULT_THREAD_IDLE_TIME_MS }; std::shared_ptr fClock = ClockHandler::getClock(); }; -} // namespace DataInspection } // namespace IoTFleetWise } // namespace Aws diff --git a/src/datamanagement/datacollection/src/CollectionSchemeIngestion.cpp b/src/CollectionSchemeIngestion.cpp similarity index 81% rename from src/datamanagement/datacollection/src/CollectionSchemeIngestion.cpp rename to src/CollectionSchemeIngestion.cpp index c5b3f2f6..46443661 100644 --- a/src/datamanagement/datacollection/src/CollectionSchemeIngestion.cpp +++ b/src/CollectionSchemeIngestion.cpp @@ -1,18 +1,16 @@ // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 -// Includes #include "CollectionSchemeIngestion.h" +#include "CollectionInspectionAPITypes.h" +#include "EnumUtility.h" #include "LoggingModule.h" +#include namespace Aws { namespace IoTFleetWise { -namespace DataManagement -{ - -using namespace Aws::IoTFleetWise::Schemas; CollectionSchemeIngestion::~CollectionSchemeIngestion() { @@ -28,7 +26,7 @@ CollectionSchemeIngestion::isReady() const bool CollectionSchemeIngestion::copyData( - std::shared_ptr protoCollectionSchemeMessagePtr ) + std::shared_ptr protoCollectionSchemeMessagePtr ) { mProtoCollectionSchemeMessagePtr = protoCollectionSchemeMessagePtr; return true; @@ -60,7 +58,7 @@ CollectionSchemeIngestion::build() ++signalIndex ) { // Get a reference to the SignalInformation Message in the protobuf - const CollectionSchemesMsg::SignalInformation &signalInformation = + const Schemas::CollectionSchemesMsg::SignalInformation &signalInformation = mProtoCollectionSchemeMessagePtr->signal_information( signalIndex ); SignalCollectionInfo signalInfo; @@ -80,7 +78,7 @@ CollectionSchemeIngestion::build() ++canFrameIndex ) { // Get a reference to the RAW CAN Frame in the protobuf - const CollectionSchemesMsg::RawCanFrame &rawCanFrame = + const Schemas::CollectionSchemesMsg::RawCanFrame &rawCanFrame = mProtoCollectionSchemeMessagePtr->raw_can_frames_to_collect( canFrameIndex ); CanFrameCollectionInfo rawCAN; @@ -97,11 +95,11 @@ CollectionSchemeIngestion::build() // condition node if ( mProtoCollectionSchemeMessagePtr->collection_scheme_type_case() == - CollectionSchemesMsg::CollectionScheme::kConditionBasedCollectionScheme ) + Schemas::CollectionSchemesMsg::CollectionScheme::kConditionBasedCollectionScheme ) { auto numNodes = getNumberOfNodes( mProtoCollectionSchemeMessagePtr->condition_based_collection_scheme().condition_tree(), - Aws::IoTFleetWise::DataInspection::MAX_EQUATION_DEPTH ); + MAX_EQUATION_DEPTH ); FWE_LOG_INFO( "CollectionScheme is Condition Based. Building AST with " + std::to_string( numNodes ) + " nodes" ); @@ -113,13 +111,13 @@ CollectionSchemeIngestion::build() mExpressionNode = serializeNode( mProtoCollectionSchemeMessagePtr->condition_based_collection_scheme().condition_tree(), currentIndex, - Aws::IoTFleetWise::DataInspection::MAX_EQUATION_DEPTH ); + MAX_EQUATION_DEPTH ); FWE_LOG_INFO( "AST complete" ); } // time based node // For time based node the condition is always set to true hence: currentNode.booleanValue=true else if ( mProtoCollectionSchemeMessagePtr->collection_scheme_type_case() == - CollectionSchemesMsg::CollectionScheme::kTimeBasedCollectionScheme ) + Schemas::CollectionSchemesMsg::CollectionScheme::kTimeBasedCollectionScheme ) { FWE_LOG_INFO( "CollectionScheme is Time based with interval of: " + std::to_string( mProtoCollectionSchemeMessagePtr->time_based_collection_scheme() @@ -157,26 +155,26 @@ CollectionSchemeIngestion::getAllExpressionNodes() const WindowFunction CollectionSchemeIngestion::convertFunctionType( - CollectionSchemesMsg::ConditionNode_NodeFunction_WindowFunction_WindowType function ) + Schemas::CollectionSchemesMsg::ConditionNode_NodeFunction_WindowFunction_WindowType function ) { switch ( function ) { - case CollectionSchemesMsg::ConditionNode_NodeFunction_WindowFunction_WindowType_LAST_WINDOW_MIN: + case Schemas::CollectionSchemesMsg::ConditionNode_NodeFunction_WindowFunction_WindowType_LAST_WINDOW_MIN: FWE_LOG_INFO( "Converting node to: LAST_FIXED_WINDOW_MIN" ); return WindowFunction::LAST_FIXED_WINDOW_MIN; - case CollectionSchemesMsg::ConditionNode_NodeFunction_WindowFunction_WindowType_LAST_WINDOW_MAX: + case Schemas::CollectionSchemesMsg::ConditionNode_NodeFunction_WindowFunction_WindowType_LAST_WINDOW_MAX: FWE_LOG_INFO( "Converting node to: LAST_FIXED_WINDOW_MAX" ); return WindowFunction::LAST_FIXED_WINDOW_MAX; - case CollectionSchemesMsg::ConditionNode_NodeFunction_WindowFunction_WindowType_LAST_WINDOW_AVG: + case Schemas::CollectionSchemesMsg::ConditionNode_NodeFunction_WindowFunction_WindowType_LAST_WINDOW_AVG: FWE_LOG_INFO( "Converting node to: LAST_FIXED_WINDOW_AVG" ); return WindowFunction::LAST_FIXED_WINDOW_AVG; - case CollectionSchemesMsg::ConditionNode_NodeFunction_WindowFunction_WindowType_PREV_LAST_WINDOW_MIN: + case Schemas::CollectionSchemesMsg::ConditionNode_NodeFunction_WindowFunction_WindowType_PREV_LAST_WINDOW_MIN: FWE_LOG_INFO( "Converting node to: PREV_LAST_FIXED_WINDOW_MIN" ); return WindowFunction::PREV_LAST_FIXED_WINDOW_MIN; - case CollectionSchemesMsg::ConditionNode_NodeFunction_WindowFunction_WindowType_PREV_LAST_WINDOW_MAX: + case Schemas::CollectionSchemesMsg::ConditionNode_NodeFunction_WindowFunction_WindowType_PREV_LAST_WINDOW_MAX: FWE_LOG_INFO( "Converting node to: PREV_LAST_FIXED_WINDOW_MAX" ); return WindowFunction::PREV_LAST_FIXED_WINDOW_MAX; - case CollectionSchemesMsg::ConditionNode_NodeFunction_WindowFunction_WindowType_PREV_LAST_WINDOW_AVG: + case Schemas::CollectionSchemesMsg::ConditionNode_NodeFunction_WindowFunction_WindowType_PREV_LAST_WINDOW_AVG: FWE_LOG_INFO( "Converting node to: PREV_LAST_FIXED_WINDOW_AVG" ); return WindowFunction::PREV_LAST_FIXED_WINDOW_AVG; default: @@ -186,47 +184,47 @@ CollectionSchemeIngestion::convertFunctionType( } ExpressionNodeType -CollectionSchemeIngestion::convertOperatorType( CollectionSchemesMsg::ConditionNode_NodeOperator_Operator op ) +CollectionSchemeIngestion::convertOperatorType( Schemas::CollectionSchemesMsg::ConditionNode_NodeOperator_Operator op ) { switch ( op ) { - case CollectionSchemesMsg::ConditionNode_NodeOperator_Operator_COMPARE_SMALLER: + case Schemas::CollectionSchemesMsg::ConditionNode_NodeOperator_Operator_COMPARE_SMALLER: FWE_LOG_INFO( "Converting operator to: OPERATOR_SMALLER" ); return ExpressionNodeType::OPERATOR_SMALLER; - case CollectionSchemesMsg::ConditionNode_NodeOperator_Operator_COMPARE_BIGGER: + case Schemas::CollectionSchemesMsg::ConditionNode_NodeOperator_Operator_COMPARE_BIGGER: FWE_LOG_INFO( "Converting operator to: OPERATOR_BIGGER" ); return ExpressionNodeType::OPERATOR_BIGGER; - case CollectionSchemesMsg::ConditionNode_NodeOperator_Operator_COMPARE_SMALLER_EQUAL: + case Schemas::CollectionSchemesMsg::ConditionNode_NodeOperator_Operator_COMPARE_SMALLER_EQUAL: FWE_LOG_INFO( "Converting operator to: OPERATOR_SMALLER_EQUAL" ); return ExpressionNodeType::OPERATOR_SMALLER_EQUAL; - case CollectionSchemesMsg::ConditionNode_NodeOperator_Operator_COMPARE_BIGGER_EQUAL: + case Schemas::CollectionSchemesMsg::ConditionNode_NodeOperator_Operator_COMPARE_BIGGER_EQUAL: FWE_LOG_INFO( "Converting operator to: OPERATOR_BIGGER_EQUAL" ); return ExpressionNodeType::OPERATOR_BIGGER_EQUAL; - case CollectionSchemesMsg::ConditionNode_NodeOperator_Operator_COMPARE_EQUAL: + case Schemas::CollectionSchemesMsg::ConditionNode_NodeOperator_Operator_COMPARE_EQUAL: FWE_LOG_INFO( "Converting operator to: OPERATOR_EQUAL" ); return ExpressionNodeType::OPERATOR_EQUAL; - case CollectionSchemesMsg::ConditionNode_NodeOperator_Operator_COMPARE_NOT_EQUAL: + case Schemas::CollectionSchemesMsg::ConditionNode_NodeOperator_Operator_COMPARE_NOT_EQUAL: FWE_LOG_INFO( "Converting operator NodeOperator_Operator_COMPARE_NOT_EQUAL to OPERATOR_NOT_EQUAL" ); return ExpressionNodeType::OPERATOR_NOT_EQUAL; - case CollectionSchemesMsg::ConditionNode_NodeOperator_Operator_LOGICAL_AND: + case Schemas::CollectionSchemesMsg::ConditionNode_NodeOperator_Operator_LOGICAL_AND: FWE_LOG_INFO( "Converting operator to: OPERATOR_LOGICAL_AND" ); return ExpressionNodeType::OPERATOR_LOGICAL_AND; - case CollectionSchemesMsg::ConditionNode_NodeOperator_Operator_LOGICAL_OR: + case Schemas::CollectionSchemesMsg::ConditionNode_NodeOperator_Operator_LOGICAL_OR: FWE_LOG_INFO( "Converting operator to: OPERATOR_LOGICAL_OR" ); return ExpressionNodeType::OPERATOR_LOGICAL_OR; - case CollectionSchemesMsg::ConditionNode_NodeOperator_Operator_LOGICAL_NOT: + case Schemas::CollectionSchemesMsg::ConditionNode_NodeOperator_Operator_LOGICAL_NOT: FWE_LOG_INFO( "Converting operator to: OPERATOR_LOGICAL_NOT" ); return ExpressionNodeType::OPERATOR_LOGICAL_NOT; - case CollectionSchemesMsg::ConditionNode_NodeOperator_Operator_ARITHMETIC_PLUS: + case Schemas::CollectionSchemesMsg::ConditionNode_NodeOperator_Operator_ARITHMETIC_PLUS: FWE_LOG_INFO( "Converting operator to: OPERATOR_ARITHMETIC_PLUS" ); return ExpressionNodeType::OPERATOR_ARITHMETIC_PLUS; - case CollectionSchemesMsg::ConditionNode_NodeOperator_Operator_ARITHMETIC_MINUS: + case Schemas::CollectionSchemesMsg::ConditionNode_NodeOperator_Operator_ARITHMETIC_MINUS: FWE_LOG_INFO( "Converting operator to: OPERATOR_ARITHMETIC_MINUS" ); return ExpressionNodeType::OPERATOR_ARITHMETIC_MINUS; - case CollectionSchemesMsg::ConditionNode_NodeOperator_Operator_ARITHMETIC_MULTIPLY: + case Schemas::CollectionSchemesMsg::ConditionNode_NodeOperator_Operator_ARITHMETIC_MULTIPLY: FWE_LOG_INFO( "Converting operator to: OPERATOR_ARITHMETIC_MULTIPLY" ); return ExpressionNodeType::OPERATOR_ARITHMETIC_MULTIPLY; - case CollectionSchemesMsg::ConditionNode_NodeOperator_Operator_ARITHMETIC_DIVIDE: + case Schemas::CollectionSchemesMsg::ConditionNode_NodeOperator_Operator_ARITHMETIC_DIVIDE: FWE_LOG_INFO( "Converting operator to: OPERATOR_ARITHMETIC_DIVIDE" ); return ExpressionNodeType::OPERATOR_ARITHMETIC_DIVIDE; default: @@ -235,14 +233,14 @@ CollectionSchemeIngestion::convertOperatorType( CollectionSchemesMsg::ConditionN } uint32_t -CollectionSchemeIngestion::getNumberOfNodes( const CollectionSchemesMsg::ConditionNode &node, const int depth ) +CollectionSchemeIngestion::getNumberOfNodes( const Schemas::CollectionSchemesMsg::ConditionNode &node, const int depth ) { if ( depth <= 0 ) { return 0; } uint32_t sum = 1; // this is one node so start with 1; - if ( node.node_case() == CollectionSchemesMsg::ConditionNode::kNodeOperator ) + if ( node.node_case() == Schemas::CollectionSchemesMsg::ConditionNode::kNodeOperator ) { if ( node.node_operator().has_left_child() ) { @@ -258,7 +256,7 @@ CollectionSchemeIngestion::getNumberOfNodes( const CollectionSchemesMsg::Conditi } ExpressionNode * -CollectionSchemeIngestion::serializeNode( const CollectionSchemesMsg::ConditionNode &node, +CollectionSchemeIngestion::serializeNode( const Schemas::CollectionSchemesMsg::ConditionNode &node, std::size_t &nextIndex, int remainingDepth ) { @@ -278,21 +276,21 @@ CollectionSchemeIngestion::serializeNode( const CollectionSchemesMsg::ConditionN } nextIndex++; - if ( node.node_case() == CollectionSchemesMsg::ConditionNode::kNodeSignalId ) + if ( node.node_case() == Schemas::CollectionSchemesMsg::ConditionNode::kNodeSignalId ) { currentNode->signalID = node.node_signal_id(); currentNode->nodeType = ExpressionNodeType::SIGNAL; FWE_LOG_TRACE( "Creating SIGNAL node with ID: " + std::to_string( currentNode->signalID ) ); return currentNode; } - else if ( node.node_case() == CollectionSchemesMsg::ConditionNode::kNodeDoubleValue ) + else if ( node.node_case() == Schemas::CollectionSchemesMsg::ConditionNode::kNodeDoubleValue ) { currentNode->floatingValue = node.node_double_value(); currentNode->nodeType = ExpressionNodeType::FLOAT; FWE_LOG_TRACE( "Creating FLOAT node with value: " + std::to_string( currentNode->floatingValue ) ); return currentNode; } - else if ( node.node_case() == CollectionSchemesMsg::ConditionNode::kNodeBooleanValue ) + else if ( node.node_case() == Schemas::CollectionSchemesMsg::ConditionNode::kNodeBooleanValue ) { currentNode->booleanValue = node.node_boolean_value(); currentNode->nodeType = ExpressionNodeType::BOOLEAN; @@ -300,10 +298,10 @@ CollectionSchemeIngestion::serializeNode( const CollectionSchemesMsg::ConditionN std::to_string( static_cast( currentNode->booleanValue ) ) ); return currentNode; } - else if ( node.node_case() == CollectionSchemesMsg::ConditionNode::kNodeFunction ) + else if ( node.node_case() == Schemas::CollectionSchemesMsg::ConditionNode::kNodeFunction ) { if ( node.node_function().functionType_case() == - CollectionSchemesMsg::ConditionNode_NodeFunction::kWindowFunction ) + Schemas::CollectionSchemesMsg::ConditionNode_NodeFunction::kWindowFunction ) { currentNode->signalID = node.node_function().window_function().signal_id(); currentNode->function.windowFunction = @@ -313,7 +311,7 @@ CollectionSchemeIngestion::serializeNode( const CollectionSchemesMsg::ConditionN return currentNode; } else if ( node.node_function().functionType_case() == - CollectionSchemesMsg::ConditionNode_NodeFunction::kGeohashFunction ) + Schemas::CollectionSchemesMsg::ConditionNode_NodeFunction::kGeohashFunction ) { if ( ( node.node_function().geohash_function().geohash_precision() > UINT8_MAX ) || ( node.node_function().geohash_function().gps_unit() >= @@ -348,7 +346,7 @@ CollectionSchemeIngestion::serializeNode( const CollectionSchemesMsg::ConditionN FWE_LOG_WARN( "Unsupported Function Node Type" ); } } - else if ( node.node_case() == CollectionSchemesMsg::ConditionNode::kNodeOperator ) + else if ( node.node_case() == Schemas::CollectionSchemesMsg::ConditionNode::kNodeOperator ) { // If no left node this node_operator is invalid if ( node.node_operator().has_left_child() ) @@ -496,7 +494,7 @@ CollectionSchemeIngestion::getMinimumPublishIntervalMs() const // Test if Message is TimeBasedCollectionScheme if ( mProtoCollectionSchemeMessagePtr->collection_scheme_type_case() == - CollectionSchemesMsg::CollectionScheme::kTimeBasedCollectionScheme ) + Schemas::CollectionSchemesMsg::CollectionScheme::kTimeBasedCollectionScheme ) { return mProtoCollectionSchemeMessagePtr->time_based_collection_scheme() .time_based_collection_scheme_period_ms(); @@ -504,7 +502,7 @@ CollectionSchemeIngestion::getMinimumPublishIntervalMs() const // Test if Message is ConditionBasedCollectionScheme if ( mProtoCollectionSchemeMessagePtr->collection_scheme_type_case() == - CollectionSchemesMsg::CollectionScheme::kConditionBasedCollectionScheme ) + Schemas::CollectionSchemesMsg::CollectionScheme::kConditionBasedCollectionScheme ) { return mProtoCollectionSchemeMessagePtr->condition_based_collection_scheme().condition_minimum_interval_ms(); } @@ -535,7 +533,7 @@ CollectionSchemeIngestion::getCollectRawCanFrames() const return mCollectedRawCAN; } -const struct ExpressionNode * +const ExpressionNode * CollectionSchemeIngestion::getCondition() const { if ( !mReady ) @@ -555,10 +553,10 @@ CollectionSchemeIngestion::isTriggerOnlyOnRisingEdge() const } // Test if Message is ConditionBasedCollectionScheme if ( mProtoCollectionSchemeMessagePtr->collection_scheme_type_case() == - CollectionSchemesMsg::CollectionScheme::kConditionBasedCollectionScheme ) + Schemas::CollectionSchemesMsg::CollectionScheme::kConditionBasedCollectionScheme ) { return mProtoCollectionSchemeMessagePtr->condition_based_collection_scheme().condition_trigger_mode() == - CollectionSchemesMsg::ConditionBasedCollectionScheme::ConditionTriggerMode:: + Schemas::CollectionSchemesMsg::ConditionBasedCollectionScheme::ConditionTriggerMode:: ConditionBasedCollectionScheme_ConditionTriggerMode_TRIGGER_ONLY_ON_RISING_EDGE; } @@ -579,6 +577,5 @@ CollectionSchemeIngestion::getProbabilityToSend() const return mProtoCollectionSchemeMessagePtr->probabilities().probability_to_send(); } -} // namespace DataManagement } // namespace IoTFleetWise } // namespace Aws diff --git a/src/datamanagement/datacollection/include/CollectionSchemeIngestion.h b/src/CollectionSchemeIngestion.h similarity index 78% rename from src/datamanagement/datacollection/include/CollectionSchemeIngestion.h rename to src/CollectionSchemeIngestion.h index 374f21c1..fa1129fa 100644 --- a/src/datamanagement/datacollection/include/CollectionSchemeIngestion.h +++ b/src/CollectionSchemeIngestion.h @@ -3,19 +3,17 @@ #pragma once -#include "CollectionInspectionAPITypes.h" #include "ICollectionScheme.h" -#include +#include "collection_schemes.pb.h" +#include +#include +#include +#include namespace Aws { namespace IoTFleetWise { -namespace DataManagement -{ - -using namespace Aws::IoTFleetWise::Platform::Linux; -using namespace Aws::IoTFleetWise::Schemas; /** * @brief DecoderManifestIngestion (PI = Schema) is the implementation of ICollectionScheme used by @@ -36,7 +34,7 @@ class CollectionSchemeIngestion : public ICollectionScheme bool build() override; - bool copyData( std::shared_ptr protoCollectionSchemeMessagePtr ); + bool copyData( std::shared_ptr protoCollectionSchemeMessagePtr ); const std::string &getCollectionSchemeID() const override; @@ -64,7 +62,7 @@ class CollectionSchemeIngestion : public ICollectionScheme uint32_t getPriority() const override; - const struct ExpressionNode *getCondition() const override; + const ExpressionNode *getCondition() const override; uint32_t getMinimumPublishIntervalMs() const override; @@ -74,7 +72,7 @@ class CollectionSchemeIngestion : public ICollectionScheme /** * @brief The CollectionScheme message that will hold the deserialized proto. */ - std::shared_ptr mProtoCollectionSchemeMessagePtr; + std::shared_ptr mProtoCollectionSchemeMessagePtr; /** * @brief Flag which is true if proto binary data is processed into readable data structures. @@ -104,7 +102,7 @@ class CollectionSchemeIngestion : public ICollectionScheme /** * @brief Function used to Flatten the Abstract Syntax Tree (AST) */ - ExpressionNode *serializeNode( const CollectionSchemesMsg::ConditionNode &node, + ExpressionNode *serializeNode( const Schemas::CollectionSchemesMsg::ConditionNode &node, std::size_t &nextIndex, int remainingDepth ); @@ -116,19 +114,20 @@ class CollectionSchemeIngestion : public ICollectionScheme * * @return Returns the number of nodes in the AST */ - uint32_t getNumberOfNodes( const CollectionSchemesMsg::ConditionNode &node, const int depth ); + uint32_t getNumberOfNodes( const Schemas::CollectionSchemesMsg::ConditionNode &node, const int depth ); /** * @brief Private Local Function used by the serializeNode Function to return the used Function Type */ static WindowFunction convertFunctionType( - CollectionSchemesMsg::ConditionNode_NodeFunction_WindowFunction_WindowType function ); + Schemas::CollectionSchemesMsg::ConditionNode_NodeFunction_WindowFunction_WindowType function ); /** * @brief Private Local Function used by the serializeNode Function to return the used Operator Type */ - static ExpressionNodeType convertOperatorType( CollectionSchemesMsg::ConditionNode_NodeOperator_Operator op ); + static ExpressionNodeType convertOperatorType( + Schemas::CollectionSchemesMsg::ConditionNode_NodeOperator_Operator op ); }; -} // namespace DataManagement + } // namespace IoTFleetWise } // namespace Aws diff --git a/src/datamanagement/datacollection/src/CollectionSchemeIngestionList.cpp b/src/CollectionSchemeIngestionList.cpp similarity index 95% rename from src/datamanagement/datacollection/src/CollectionSchemeIngestionList.cpp rename to src/CollectionSchemeIngestionList.cpp index a9108eca..15acade3 100644 --- a/src/datamanagement/datacollection/src/CollectionSchemeIngestionList.cpp +++ b/src/CollectionSchemeIngestionList.cpp @@ -2,15 +2,16 @@ // SPDX-License-Identifier: Apache-2.0 #include "CollectionSchemeIngestionList.h" +#include "CollectionSchemeIngestion.h" #include "LoggingModule.h" -#include +#include +#include +#include namespace Aws { namespace IoTFleetWise { -namespace DataManagement -{ const std::vector & CollectionSchemeIngestionList::getCollectionSchemes() const @@ -110,7 +111,7 @@ CollectionSchemeIngestionList::build() auto pICPPtr = std::make_shared(); // Stuff the pointer with the collectionScheme proto message data - pICPPtr->copyData( std::make_shared( + pICPPtr->copyData( std::make_shared( mCollectionSchemeListMsg.collection_schemes( i ) ) ); // Check to see if it successfully builds @@ -137,6 +138,5 @@ CollectionSchemeIngestionList::build() return true; } -} // namespace DataManagement } // namespace IoTFleetWise } // namespace Aws diff --git a/src/datamanagement/datacollection/include/CollectionSchemeIngestionList.h b/src/CollectionSchemeIngestionList.h similarity index 88% rename from src/datamanagement/datacollection/include/CollectionSchemeIngestionList.h rename to src/CollectionSchemeIngestionList.h index 6beb93a6..4ead3a71 100644 --- a/src/datamanagement/datacollection/include/CollectionSchemeIngestionList.h +++ b/src/CollectionSchemeIngestionList.h @@ -3,20 +3,16 @@ #pragma once -#include "CollectionSchemeIngestion.h" #include "ICollectionSchemeList.h" #include "collection_schemes.pb.h" +#include +#include #include namespace Aws { namespace IoTFleetWise { -namespace DataManagement -{ - -using namespace Aws::IoTFleetWise::Platform::Linux; -using namespace Aws::IoTFleetWise::Schemas; /** * @brief Setting a size limit in bytes for incoming collectionSchemes from cloud @@ -71,9 +67,8 @@ class CollectionSchemeIngestionList : public ICollectionSchemeList /** * @brief Used internally to hold the collectionSchemes message from the protobuffer */ - CollectionSchemesMsg::CollectionSchemes mCollectionSchemeListMsg; + Schemas::CollectionSchemesMsg::CollectionSchemes mCollectionSchemeListMsg; }; -} // namespace DataManagement } // namespace IoTFleetWise } // namespace Aws diff --git a/src/datamanagement/datamanager/include/CollectionSchemeManagementListener.h b/src/CollectionSchemeManagementListener.h similarity index 95% rename from src/datamanagement/datamanager/include/CollectionSchemeManagementListener.h rename to src/CollectionSchemeManagementListener.h index 6a9fd136..a0dff095 100644 --- a/src/datamanagement/datamanager/include/CollectionSchemeManagementListener.h +++ b/src/CollectionSchemeManagementListener.h @@ -10,8 +10,7 @@ namespace Aws { namespace IoTFleetWise { -namespace DataManagement -{ + using IDecoderManifestPtr = std::shared_ptr; using ICollectionSchemeListPtr = std::shared_ptr; @@ -36,6 +35,5 @@ struct CollectionSchemeManagementListener virtual void onDecoderManifestUpdate( const IDecoderManifestPtr &decoderManifest ) = 0; }; -} // namespace DataManagement } // namespace IoTFleetWise } // namespace Aws diff --git a/src/datamanagement/datamanager/src/CollectionSchemeManager.cpp b/src/CollectionSchemeManager.cpp similarity index 99% rename from src/datamanagement/datamanager/src/CollectionSchemeManager.cpp rename to src/CollectionSchemeManager.cpp index 00863975..268bb151 100644 --- a/src/datamanagement/datamanager/src/CollectionSchemeManager.cpp +++ b/src/CollectionSchemeManager.cpp @@ -1,12 +1,13 @@ // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 -// Includes #include "CollectionSchemeManager.h" +#include "ICollectionScheme.h" #include "LoggingModule.h" #include "TraceModule.h" -#include +#include #include +#include #include #include @@ -14,8 +15,6 @@ namespace Aws { namespace IoTFleetWise { -namespace DataManagement -{ const std::string CollectionSchemeManager::CHECKIN = "Checkin"; CollectionSchemeManager::CollectionSchemeManager( std::string dm_id ) @@ -271,7 +270,7 @@ CollectionSchemeManager::doWork( void *data ) auto currentMonotonicTime = collectionSchemeManager->mClock->monotonicTimeSinceEpochMs(); if ( collectionSchemeManager->mTimeLine.empty() ) { - collectionSchemeManager->mWait.wait( Platform::Linux::Signal::WaitWithPredicate ); + collectionSchemeManager->mWait.wait( Signal::WaitWithPredicate ); } else if ( currentMonotonicTime >= collectionSchemeManager->mTimeLine.top().time.monotonicTimeMs ) { @@ -903,6 +902,6 @@ CollectionSchemeManager::checkTimeLine( const TimePoint &currTime ) } return ret; } -} // namespace DataManagement + } // namespace IoTFleetWise } // namespace Aws diff --git a/src/datamanagement/datamanager/include/CollectionSchemeManager.h b/src/CollectionSchemeManager.h similarity index 94% rename from src/datamanagement/datamanager/include/CollectionSchemeManager.h rename to src/CollectionSchemeManager.h index 84e3889c..182272e0 100644 --- a/src/datamanagement/datamanager/include/CollectionSchemeManager.h +++ b/src/CollectionSchemeManager.h @@ -3,33 +3,40 @@ #pragma once -// Includes #include "CANInterfaceIDTranslator.h" +#include "CacheAndPersist.h" +#include "Clock.h" #include "ClockHandler.h" +#include "CollectionInspectionAPITypes.h" #include "CollectionSchemeManagementListener.h" #include "IActiveCollectionSchemesListener.h" #include "IActiveConditionProcessor.h" #include "IActiveDecoderDictionaryListener.h" #include "ICollectionSchemeList.h" #include "ICollectionSchemeManager.h" +#include "IDecoderDictionary.h" #include "IDecoderManifest.h" #include "Listener.h" #include "SchemaListener.h" #include "Signal.h" +#include "SignalTypes.h" #include "Thread.h" -#include "Timer.h" +#include "TimeTypes.h" +#include "VehicleDataSourceTypes.h" #include +#include +#include #include +#include #include #include +#include #include + namespace Aws { namespace IoTFleetWise { -namespace DataManagement -{ -using namespace Aws::IoTFleetWise::Platform::Linux; using SchemaListenerPtr = std::shared_ptr; @@ -89,14 +96,14 @@ class CollectionSchemeManager : public ICollectionSchemeManager, /** * @brief Initializes collectionScheme management session. * - * @param checkinIntervalMsec checkin message interval in millisecond - * @param schemaPersistencyPtr shared pointer to collectionSchemePersistency object - * @param canIDTranslator used to translate the cloud used Interface ID to the the internal channel id * @return True if successful. False otherwise. */ - bool init( uint32_t checkinIntervalMsec, - const std::shared_ptr &schemaPersistencyPtr, - CANInterfaceIDTranslator &canIDTranslator ); + bool init( uint32_t checkinIntervalMsec, /**< checkin message interval in millisecond */ + const std::shared_ptr + &schemaPersistencyPtr, /**< shared pointer to collectionSchemePersistency object */ + CANInterfaceIDTranslator &canIDTranslator /**< canIDTranslator used to translate the cloud used Interface + ID to the the internal channel id */ + ); /** * @brief Sets up connection with CollectionScheme Ingestion and start main thread. * @return True if successful. False otherwise. @@ -302,7 +309,7 @@ class CollectionSchemeManager : public ICollectionSchemeManager, mutable std::mutex mThreadMutex; // Platform signal that wakes up main thread - Platform::Linux::Signal mWait; + Signal mWait; std::shared_ptr mClock = ClockHandler::getClock(); // Shared pointer to a SchemaListener Object allow CollectionSchemeManagement to send data to Schema @@ -371,6 +378,5 @@ class CollectionSchemeManager : public ICollectionSchemeManager, CANInterfaceIDTranslator mCANIDTranslator; }; -} // namespace DataManagement } // namespace IoTFleetWise } // namespace Aws diff --git a/src/platform/linux/logmanagement/src/ConsoleLogger.cpp b/src/ConsoleLogger.cpp similarity index 95% rename from src/platform/linux/logmanagement/src/ConsoleLogger.cpp rename to src/ConsoleLogger.cpp index b7e78844..d10f205b 100644 --- a/src/platform/linux/logmanagement/src/ConsoleLogger.cpp +++ b/src/ConsoleLogger.cpp @@ -1,30 +1,25 @@ // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 -#if defined( IOTFLEETWISE_LINUX ) -// Includes - #include "ConsoleLogger.h" +#include "Clock.h" #include "ClockHandler.h" -#ifdef __ANDROID__ -#include -#endif -#include #include -#include +#include +#include #include -#include #include #include +#ifdef __ANDROID__ +#include +#endif + namespace Aws { namespace IoTFleetWise { -namespace Platform -{ -namespace Linux -{ + namespace Color { static const std::string red{ "\x1b[31m" }; @@ -196,8 +191,5 @@ ConsoleLogger::currentThreadId() return static_cast( syscall( SYS_gettid ) ); } -} // namespace Linux -} // namespace Platform } // namespace IoTFleetWise } // namespace Aws -#endif // IOTFLEETWISE_LINUX diff --git a/src/platform/linux/logmanagement/include/ConsoleLogger.h b/src/ConsoleLogger.h similarity index 85% rename from src/platform/linux/logmanagement/include/ConsoleLogger.h rename to src/ConsoleLogger.h index fcdfdbce..c3c79d2c 100644 --- a/src/platform/linux/logmanagement/include/ConsoleLogger.h +++ b/src/ConsoleLogger.h @@ -3,22 +3,16 @@ #pragma once -#if defined( IOTFLEETWISE_LINUX ) -// Includes #include "ILogger.h" #include "LogLevel.h" #include -#include #include namespace Aws { namespace IoTFleetWise { -namespace Platform -{ -namespace Linux -{ + /** * @brief This logger instance logs messages to the standard output. */ @@ -85,15 +79,15 @@ stringToLogColorOption( const std::string level, LogColorOption &outLogColorOpti { if ( level == "Auto" ) { - outLogColorOption = Aws::IoTFleetWise::Platform::Linux::LogColorOption::Auto; + outLogColorOption = LogColorOption::Auto; } else if ( level == "Yes" ) { - outLogColorOption = Aws::IoTFleetWise::Platform::Linux::LogColorOption::Yes; + outLogColorOption = LogColorOption::Yes; } else if ( level == "No" ) { - outLogColorOption = Aws::IoTFleetWise::Platform::Linux::LogColorOption::No; + outLogColorOption = LogColorOption::No; } else { @@ -103,8 +97,6 @@ stringToLogColorOption( const std::string level, LogColorOption &outLogColorOpti } extern LogColorOption gLogColorOption; -} // namespace Linux -} // namespace Platform + } // namespace IoTFleetWise } // namespace Aws -#endif // IOTFLEETWISE_LINUX diff --git a/src/datamanagement/custom/generic/src/CustomDataSource.cpp b/src/CustomDataSource.cpp similarity index 97% rename from src/datamanagement/custom/generic/src/CustomDataSource.cpp rename to src/CustomDataSource.cpp index 974b669b..b625bcb9 100644 --- a/src/datamanagement/custom/generic/src/CustomDataSource.cpp +++ b/src/CustomDataSource.cpp @@ -1,19 +1,16 @@ // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 -#if defined( IOTFLEETWISE_LINUX ) -// Includes #include "CustomDataSource.h" #include "LoggingModule.h" #include "Timer.h" +#include +#include namespace Aws { namespace IoTFleetWise { -namespace DataManagement -{ - const char * CustomDataSource::getThreadName() { @@ -107,7 +104,7 @@ CustomDataSource::doWork( void *data ) // We should sleep FWE_LOG_TRACE( "No valid decoding information available so sleep" ); // Wait here for the decoder dictionary to come. - customDataSource->mWait.wait( Platform::Linux::Signal::WaitWithPredicate ); + customDataSource->mWait.wait( Signal::WaitWithPredicate ); // At this point, we should be able to see events coming as the channel is also // woken up. } @@ -211,7 +208,5 @@ CustomDataSource::~CustomDataSource() } } -} // namespace DataManagement } // namespace IoTFleetWise } // namespace Aws -#endif diff --git a/src/datamanagement/custom/generic/include/CustomDataSource.h b/src/CustomDataSource.h similarity index 93% rename from src/datamanagement/custom/generic/include/CustomDataSource.h rename to src/CustomDataSource.h index cd4b7b66..0194e0ad 100644 --- a/src/datamanagement/custom/generic/include/CustomDataSource.h +++ b/src/CustomDataSource.h @@ -3,19 +3,22 @@ #pragma once #include "IActiveDecoderDictionaryListener.h" +#include "IDecoderDictionary.h" +#include "MessageTypes.h" +#include "Signal.h" #include "SignalTypes.h" #include "Thread.h" +#include "VehicleDataSourceTypes.h" +#include +#include +#include +#include #include namespace Aws { namespace IoTFleetWise { -namespace DataManagement -{ -using namespace Aws::IoTFleetWise::Platform::Linux; -using namespace Aws::IoTFleetWise::VehicleNetwork; -using namespace Aws::IoTFleetWise::DataInspection; /** * To implement a custom data source create a new class and inherit from CustomDataSource @@ -99,7 +102,7 @@ class CustomDataSource : public IActiveDecoderDictionaryListener std::atomic mShouldStop{ false }; std::atomic mShouldSleep{ false }; mutable std::mutex mThreadMutex; - Platform::Linux::Signal mWait; + Signal mWait; CANChannelNumericID mCanChannel = INVALID_CAN_SOURCE_NUMERIC_ID; CANRawFrameID mCanRawFrameId = 0; @@ -112,6 +115,6 @@ class CustomDataSource : public IActiveDecoderDictionaryListener static const uint32_t DEFAULT_POLL_INTERVAL_MS = 50; // Default poll every 50ms data }; -} // namespace DataManagement + } // namespace IoTFleetWise } // namespace Aws diff --git a/src/datamanagement/datainspection/include/DataReduction.h b/src/DataReduction.h similarity index 97% rename from src/datamanagement/datainspection/include/DataReduction.h rename to src/DataReduction.h index bdaa2287..cb4c384b 100644 --- a/src/datamanagement/datainspection/include/DataReduction.h +++ b/src/DataReduction.h @@ -9,8 +9,6 @@ namespace Aws { namespace IoTFleetWise { -namespace DataInspection -{ /** * @brief Utility class used by CollectionInspectionEngine for reducing data sent from FWE to cloud @@ -62,6 +60,5 @@ class DataReduction }; }; -} // namespace DataInspection } // namespace IoTFleetWise } // namespace Aws diff --git a/src/datamanagement/datasender/src/DataSenderManager.cpp b/src/DataSenderManager.cpp similarity index 81% rename from src/datamanagement/datasender/src/DataSenderManager.cpp rename to src/DataSenderManager.cpp index ba649b3a..d5eb7c16 100644 --- a/src/datamanagement/datasender/src/DataSenderManager.cpp +++ b/src/DataSenderManager.cpp @@ -3,15 +3,20 @@ #include "DataSenderManager.h" #include "CacheAndPersist.h" +#include "GeohashInfo.h" #include "LoggingModule.h" +#include "OBDDataTypes.h" #include "TraceModule.h" -#include +#include #include #include +#include +#include -using namespace Aws::IoTFleetWise::DataSender; -using namespace Aws::IoTFleetWise::DataManagement; -using namespace Aws::IoTFleetWise::Platform::Linux::PersistencyManagement; +namespace Aws +{ +namespace IoTFleetWise +{ DataSenderManager::DataSenderManager( std::shared_ptr mqttSender, std::shared_ptr payloadManager, @@ -61,26 +66,14 @@ DataSenderManager::transformTelemetryDataToProto( for ( const auto &signal : triggeredCollectionSchemeDataPtr->signals ) { { - mProtoWriter.append( signal ); - if ( mProtoWriter.getVehicleDataMsgCount() >= mTransmitThreshold ) - { - uploadProto(); - // Setup the next payload chunk - mProtoWriter.setupVehicleData( triggeredCollectionSchemeDataPtr, mCollectionSchemeParams.eventID ); - } + appendMessageToProto( triggeredCollectionSchemeDataPtr, signal ); } } // Iterate through all the raw CAN frames and add to the protobuf for ( const auto &canFrame : triggeredCollectionSchemeDataPtr->canFrames ) { - mProtoWriter.append( canFrame ); - if ( mProtoWriter.getVehicleDataMsgCount() >= mTransmitThreshold ) - { - uploadProto(); - // Setup the next payload chunk - mProtoWriter.setupVehicleData( triggeredCollectionSchemeDataPtr, mCollectionSchemeParams.eventID ); - } + appendMessageToProto( triggeredCollectionSchemeDataPtr, canFrame ); } // Add DTC info to the payload @@ -92,27 +85,14 @@ DataSenderManager::transformTelemetryDataToProto( // Iterate through all the DTC codes and add to the protobuf for ( const auto &dtc : dtcCodes ) { - mProtoWriter.append( dtc ); - - if ( mProtoWriter.getVehicleDataMsgCount() >= mTransmitThreshold ) - { - uploadProto(); - // Setup the next payload chunk - mProtoWriter.setupVehicleData( triggeredCollectionSchemeDataPtr, mCollectionSchemeParams.eventID ); - } + appendMessageToProto( triggeredCollectionSchemeDataPtr, dtc ); } } // Add Geohash to the payload if ( triggeredCollectionSchemeDataPtr->mGeohashInfo.hasItems() ) { - mProtoWriter.append( triggeredCollectionSchemeDataPtr->mGeohashInfo ); - if ( mProtoWriter.getVehicleDataMsgCount() >= mTransmitThreshold ) - { - uploadProto(); - // Setup the next payload chunk - mProtoWriter.setupVehicleData( triggeredCollectionSchemeDataPtr, mCollectionSchemeParams.eventID ); - } + appendMessageToProto( triggeredCollectionSchemeDataPtr, triggeredCollectionSchemeDataPtr->mGeohashInfo ); } // Serialize and transmit any remaining messages @@ -231,10 +211,6 @@ DataSenderManager::checkAndSendRetrievedData() } FWE_LOG_INFO( "Upload of persisted payloads is finished" ); } - else if ( status == ErrorCode::EMPTY ) - { - FWE_LOG_TRACE( "No Payloads to Retrieve" ); - } else { FWE_LOG_ERROR( "Payload Metadata Retrieval Failed" ); @@ -253,3 +229,6 @@ DataSenderManager::uploadPersistedFile( const std::string &filename, } return res; } + +} // namespace IoTFleetWise +} // namespace Aws diff --git a/src/datamanagement/datasender/include/DataSenderManager.h b/src/DataSenderManager.h similarity index 77% rename from src/datamanagement/datasender/include/DataSenderManager.h rename to src/DataSenderManager.h index 2f574f2d..6fbbbe7c 100644 --- a/src/datamanagement/datasender/include/DataSenderManager.h +++ b/src/DataSenderManager.h @@ -3,21 +3,21 @@ #pragma once +#include "CANInterfaceIDTranslator.h" +#include "CollectionInspectionAPITypes.h" #include "DataSenderProtoWriter.h" -#include "ICollectionScheme.h" -#include "ICollectionSchemeList.h" +#include "IConnectionTypes.h" #include "ISender.h" #include "PayloadManager.h" +#include +#include +#include +#include + namespace Aws { namespace IoTFleetWise { -namespace DataSender -{ - -using namespace Aws::IoTFleetWise::OffboardConnectivityAwsIot; -using namespace Aws::IoTFleetWise::OffboardConnectivity; -using namespace Aws::IoTFleetWise::DataManagement; /** * @brief Class that implements data sender logic: data preprocessing and upload @@ -35,15 +35,17 @@ class DataSenderManager CANInterfaceIDTranslator &canIDTranslator, unsigned transmitThreshold ); + virtual ~DataSenderManager() = default; + /** - * @brief Process collection scheme parameters and prepare telemetry data and rich sensor data for the upload + * @brief Process collection scheme parameters and prepare data for upload */ - void processCollectedData( const TriggeredCollectionSchemeDataPtr triggeredCollectionSchemeDataPtr ); + virtual void processCollectedData( const TriggeredCollectionSchemeDataPtr triggeredCollectionSchemeDataPtr ); /** * @brief Retrieve all the persisted data and hand it over to the correct sender */ - void checkAndSendRetrievedData(); + virtual void checkAndSendRetrievedData(); private: std::shared_ptr mMQTTSender; @@ -75,6 +77,19 @@ class DataSenderManager */ void uploadProto(); + template + void + appendMessageToProto( const TriggeredCollectionSchemeDataPtr &triggeredCollectionSchemeDataPtr, T msg ) + { + mProtoWriter.append( msg ); + if ( mProtoWriter.getVehicleDataMsgCount() >= mTransmitThreshold ) + { + uploadProto(); + // Setup the next payload chunk + mProtoWriter.setupVehicleData( triggeredCollectionSchemeDataPtr, mCollectionSchemeParams.eventID ); + } + } + /** * @brief Serializes data * @param output Output string @@ -111,6 +126,5 @@ class DataSenderManager CollectionSchemeParams collectionSchemeParams ); }; -} // namespace DataSender } // namespace IoTFleetWise } // namespace Aws diff --git a/src/DataSenderManagerWorkerThread.cpp b/src/DataSenderManagerWorkerThread.cpp new file mode 100644 index 00000000..21569f5e --- /dev/null +++ b/src/DataSenderManagerWorkerThread.cpp @@ -0,0 +1,239 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +#include "DataSenderManagerWorkerThread.h" +#include "GeohashInfo.h" +#include "LoggingModule.h" +#include "OBDDataTypes.h" +#include "SignalTypes.h" +#include "TraceModule.h" +#include +#include +#include +#include + +namespace Aws +{ +namespace IoTFleetWise +{ + +const uint32_t DataSenderManagerWorkerThread::MAX_NUMBER_OF_SIGNAL_TO_TRACE_LOG = 6; + +DataSenderManagerWorkerThread::DataSenderManagerWorkerThread( + std::shared_ptr connectivityModule, + std::shared_ptr dataSenderManager, + uint64_t persistencyUploadRetryIntervalMs, + std::shared_ptr &collectedDataQueue ) + : mCollectedDataQueue( collectedDataQueue ) + , mPersistencyUploadRetryIntervalMs{ persistencyUploadRetryIntervalMs } + , mDataSenderManager( std::move( dataSenderManager ) ) + , mConnectivityModule( std::move( connectivityModule ) ) +{ +} + +bool +DataSenderManagerWorkerThread::start() +{ + // Prevent concurrent stop/init + std::lock_guard lock( mThreadMutex ); + mShouldStop.store( false ); + if ( !mThread.create( doWork, this ) ) + { + FWE_LOG_TRACE( "Data Sender Manager Thread failed to start" ); + } + else + { + FWE_LOG_TRACE( "Data Sender Manager Thread started" ); + mThread.setThreadName( "fwDSDataSendMng" ); + } + + return mThread.isActive() && mThread.isValid(); +} + +bool +DataSenderManagerWorkerThread::stop() +{ + // It might take several seconds to finish all running S3 async PutObject requests + if ( ( !mThread.isValid() ) || ( !mThread.isActive() ) ) + { + return true; + } + std::lock_guard lock( mThreadMutex ); + mShouldStop.store( true, std::memory_order_relaxed ); + FWE_LOG_TRACE( "Request stop" ); + mWait.notify(); + mThread.release(); + FWE_LOG_TRACE( "Stop finished" ); + mShouldStop.store( false, std::memory_order_relaxed ); + return !mThread.isActive(); +} + +bool +DataSenderManagerWorkerThread::shouldStop() const +{ + return mShouldStop.load( std::memory_order_relaxed ); +} + +void +DataSenderManagerWorkerThread::doWork( void *data ) +{ + DataSenderManagerWorkerThread *sender = static_cast( data ); + + bool uploadedPersistedDataOnce = false; + + while ( !sender->shouldStop() ) + { + sender->mTimer.reset(); + uint64_t minTimeToWaitMs = UINT64_MAX; + + if ( sender->mPersistencyUploadRetryIntervalMs > 0 ) + { + uint64_t timeToWaitMs = + sender->mPersistencyUploadRetryIntervalMs - + std::min( static_cast( sender->mRetrySendingPersistedDataTimer.getElapsedMs().count() ), + sender->mPersistencyUploadRetryIntervalMs ); + minTimeToWaitMs = std::min( minTimeToWaitMs, timeToWaitMs ); + } + + if ( minTimeToWaitMs < UINT64_MAX ) + { + FWE_LOG_TRACE( "Waiting for: " + std::to_string( minTimeToWaitMs ) + " ms. Persistency " + + std::to_string( sender->mPersistencyUploadRetryIntervalMs ) + " configured, " + + std::to_string( sender->mRetrySendingPersistedDataTimer.getElapsedMs().count() ) + + " timer." ); + sender->mWait.wait( static_cast( minTimeToWaitMs ) ); + } + else + { + sender->mWait.wait( Signal::WaitWithPredicate ); + auto elapsedTimeMs = sender->mTimer.getElapsedMs().count(); + FWE_LOG_TRACE( "Event arrived. Time elapsed waiting for the event: " + std::to_string( elapsedTimeMs ) + + " ms" ); + } + + // Dequeues the collected data queue and sends the data to cloud + auto consumeData = [&]( const TriggeredCollectionSchemeDataPtr &triggeredCollectionSchemeDataPtr ) { + // Only used for trace logging + std::string firstSignalValues = "["; + uint32_t signalPrintCounter = 0; + std::string firstSignalTimestamp; + for ( auto &s : triggeredCollectionSchemeDataPtr->signals ) + { + if ( firstSignalTimestamp.empty() ) + { + firstSignalTimestamp = " first signal timestamp: " + std::to_string( s.receiveTime ); + } + signalPrintCounter++; + if ( signalPrintCounter > MAX_NUMBER_OF_SIGNAL_TO_TRACE_LOG ) + { + firstSignalValues += " ..."; + break; + } + auto signalValue = s.getValue(); + firstSignalValues += std::to_string( s.signalID ) + ":"; + switch ( signalValue.getType() ) + { + case SignalType::UINT8: + firstSignalValues += std::to_string( signalValue.value.uint8Val ) + ","; + break; + case SignalType::INT8: + firstSignalValues += std::to_string( signalValue.value.int8Val ) + ","; + break; + case SignalType::UINT16: + firstSignalValues += std::to_string( signalValue.value.uint16Val ) + ","; + break; + case SignalType::INT16: + firstSignalValues += std::to_string( signalValue.value.int16Val ) + ","; + break; + case SignalType::UINT32: + firstSignalValues += std::to_string( signalValue.value.uint32Val ) + ","; + break; + case SignalType::INT32: + firstSignalValues += std::to_string( signalValue.value.int32Val ) + ","; + break; + case SignalType::UINT64: + firstSignalValues += std::to_string( signalValue.value.uint64Val ) + ","; + break; + case SignalType::INT64: + firstSignalValues += std::to_string( signalValue.value.int64Val ) + ","; + break; + case SignalType::FLOAT: + firstSignalValues += std::to_string( signalValue.value.floatVal ) + ","; + break; + case SignalType::DOUBLE: + firstSignalValues += std::to_string( signalValue.value.doubleVal ) + ","; + break; + case SignalType::BOOLEAN: + firstSignalValues += std::to_string( static_cast( signalValue.value.boolVal ) ) + ","; + break; + } + } + firstSignalValues += "]"; + // Avoid invoking Data Collection Sender if there is nothing to send. + if ( triggeredCollectionSchemeDataPtr->signals.empty() && + triggeredCollectionSchemeDataPtr->canFrames.empty() && + triggeredCollectionSchemeDataPtr->mDTCInfo.mDTCCodes.empty() && + ( !triggeredCollectionSchemeDataPtr->mGeohashInfo.hasItems() ) ) + { + FWE_LOG_INFO( + "The trigger for Campaign: " + triggeredCollectionSchemeDataPtr->metadata.collectionSchemeID + + " activated eventID: " + std::to_string( triggeredCollectionSchemeDataPtr->eventID ) + + " but no data is available to ingest" ); + } + else + { + std::string message = + "FWE data ready to send with eventID " + + std::to_string( triggeredCollectionSchemeDataPtr->eventID ) + " from " + + triggeredCollectionSchemeDataPtr->metadata.collectionSchemeID + + " Signals:" + std::to_string( triggeredCollectionSchemeDataPtr->signals.size() ) + " " + + firstSignalValues + firstSignalTimestamp + + " trigger timestamp: " + std::to_string( triggeredCollectionSchemeDataPtr->triggerTime ) + + " raw CAN frames:" + std::to_string( triggeredCollectionSchemeDataPtr->canFrames.size() ) + + " DTCs:" + std::to_string( triggeredCollectionSchemeDataPtr->mDTCInfo.mDTCCodes.size() ) + + " Geohash:" + triggeredCollectionSchemeDataPtr->mGeohashInfo.mGeohashString; + FWE_LOG_INFO( message ); + sender->mDataSenderManager->processCollectedData( triggeredCollectionSchemeDataPtr ); + } + }; + + auto consumedElements = sender->mCollectedDataQueue->consume_all( consumeData ); + TraceModule::get().setVariable( TraceVariable::QUEUE_INSPECTION_TO_SENDER, consumedElements ); + if ( ( !uploadedPersistedDataOnce ) || + ( ( sender->mPersistencyUploadRetryIntervalMs > 0 ) && + ( static_cast( sender->mRetrySendingPersistedDataTimer.getElapsedMs().count() ) >= + sender->mPersistencyUploadRetryIntervalMs ) ) ) + { + sender->mRetrySendingPersistedDataTimer.reset(); + if ( sender->mConnectivityModule->isAlive() ) + { + sender->mDataSenderManager->checkAndSendRetrievedData(); + uploadedPersistedDataOnce = true; + } + } + } +} + +bool +DataSenderManagerWorkerThread::isAlive() +{ + return mThread.isValid() && mThread.isActive(); +} + +void +DataSenderManagerWorkerThread::onDataReadyToPublish() +{ + mWait.notify(); +} + +DataSenderManagerWorkerThread::~DataSenderManagerWorkerThread() +{ + // To make sure the thread stops during teardown of tests. + if ( isAlive() ) + { + stop(); + } +} + +} // namespace IoTFleetWise +} // namespace Aws diff --git a/src/datamanagement/datasender/include/DataSenderManagerWorkerThread.h b/src/DataSenderManagerWorkerThread.h similarity index 60% rename from src/datamanagement/datasender/include/DataSenderManagerWorkerThread.h rename to src/DataSenderManagerWorkerThread.h index 96cb1b3d..67bea24b 100644 --- a/src/datamanagement/datasender/include/DataSenderManagerWorkerThread.h +++ b/src/DataSenderManagerWorkerThread.h @@ -3,29 +3,30 @@ #pragma once +#include "CollectionInspectionAPITypes.h" #include "DataSenderManager.h" -#include "IActiveCollectionSchemesListener.h" #include "IConnectivityModule.h" #include "IDataReadyToPublishListener.h" +#include "Signal.h" #include "Thread.h" #include "Timer.h" +#include +#include +#include +#include namespace Aws { namespace IoTFleetWise { -namespace DataSender -{ -class DataSenderManagerWorkerThread : public IDataReadyToPublishListener, public IActiveCollectionSchemesListener +class DataSenderManagerWorkerThread : public IDataReadyToPublishListener { public: - DataSenderManagerWorkerThread( CANInterfaceIDTranslator &canIDTranslator, - std::shared_ptr connectivityModule, - std::shared_ptr mqttSender, - std::shared_ptr payloadManager, - unsigned maxMessageCount, - uint64_t persistencyUploadRetryInterval ); + DataSenderManagerWorkerThread( std::shared_ptr connectivityModule, + std::shared_ptr dataSenderManager, + uint64_t persistencyUploadRetryIntervalMs, + std::shared_ptr &collectedDataQueue ); ~DataSenderManagerWorkerThread() override; DataSenderManagerWorkerThread( const DataSenderManagerWorkerThread & ) = delete; @@ -41,17 +42,6 @@ class DataSenderManagerWorkerThread : public IDataReadyToPublishListener, public */ void onDataReadyToPublish() override; - // Inherited from IActiveConditionProcessor - void onChangeCollectionSchemeList( - const std::shared_ptr &activeCollectionSchemes ) override; - - /** - * @brief Initialize the component by handing over all queues - * @param collectedDataQueue this thread will empty this queue of data ready to publish - * @return true if initialization was successful - * */ - bool init( const std::shared_ptr &collectedDataQueue ); - /** * @brief Stops the internal thread if started and wait until it finishes * @@ -78,23 +68,18 @@ class DataSenderManagerWorkerThread : public IDataReadyToPublishListener, public static void doWork( void *data ); std::shared_ptr mCollectedDataQueue; + uint64_t mPersistencyUploadRetryIntervalMs{ 0 }; Thread mThread; std::atomic mShouldStop{ false }; std::mutex mThreadMutex; - Platform::Linux::Signal mWait; - DataSenderManager mDataSenderManager; - std::shared_ptr mActiveCollectionSchemes; - std::mutex mActiveCollectionSchemesMutex; - std::atomic mUpdatedCollectionSchemeListAvailable{ false }; - + Signal mWait; + std::shared_ptr mDataSenderManager; std::shared_ptr mConnectivityModule; Timer mTimer; Timer mRetrySendingPersistedDataTimer; - uint64_t mPersistencyUploadRetryIntervalMs{ 0 }; }; -} // namespace DataSender } // namespace IoTFleetWise } // namespace Aws diff --git a/src/datamanagement/datasender/src/DataSenderProtoWriter.cpp b/src/DataSenderProtoWriter.cpp similarity index 97% rename from src/datamanagement/datasender/src/DataSenderProtoWriter.cpp rename to src/DataSenderProtoWriter.cpp index 30d03c42..e2d71ed3 100644 --- a/src/datamanagement/datasender/src/DataSenderProtoWriter.cpp +++ b/src/DataSenderProtoWriter.cpp @@ -1,15 +1,16 @@ // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 -// Includes #include "DataSenderProtoWriter.h" +#include "SignalTypes.h" +#include +#include +#include namespace Aws { namespace IoTFleetWise { -namespace DataSender -{ DataSenderProtoWriter::DataSenderProtoWriter( CANInterfaceIDTranslator &canIDTranslator ) : mTriggerTime( 0U ) @@ -137,6 +138,5 @@ DataSenderProtoWriter::serializeVehicleData( std::string *out ) const return mVehicleData.SerializeToString( out ); } -} // namespace DataSender } // namespace IoTFleetWise } // namespace Aws diff --git a/src/datamanagement/datasender/include/DataSenderProtoWriter.h b/src/DataSenderProtoWriter.h similarity index 93% rename from src/datamanagement/datasender/include/DataSenderProtoWriter.h rename to src/DataSenderProtoWriter.h index 0c13c4c6..2bb0d5db 100644 --- a/src/datamanagement/datasender/include/DataSenderProtoWriter.h +++ b/src/DataSenderProtoWriter.h @@ -3,11 +3,11 @@ #pragma once -// Includes -#include "CANDataTypes.h" #include "CANInterfaceIDTranslator.h" #include "CollectionInspectionAPITypes.h" +#include "GeohashInfo.h" #include "OBDDataTypes.h" +#include "TimeTypes.h" #include "vehicle_data.pb.h" #include #include @@ -16,10 +16,6 @@ namespace Aws { namespace IoTFleetWise { -namespace DataSender -{ -using namespace Aws::IoTFleetWise::Schemas; -using namespace Aws::IoTFleetWise::DataInspection; /** * @brief Class that does the protobuf setup for the collected data @@ -107,9 +103,9 @@ class DataSenderProtoWriter private: Timestamp mTriggerTime; unsigned mVehicleDataMsgCount{}; // tracks the number of messages being sent in the edge to cloud payload - VehicleDataMsg::VehicleData mVehicleData{}; + Schemas::VehicleDataMsg::VehicleData mVehicleData{}; CANInterfaceIDTranslator mIDTranslator; }; -} // namespace DataSender + } // namespace IoTFleetWise } // namespace Aws diff --git a/src/datamanagement/datamanager/src/DecoderDictionaryExtractor.cpp b/src/DecoderDictionaryExtractor.cpp similarity index 98% rename from src/datamanagement/datamanager/src/DecoderDictionaryExtractor.cpp rename to src/DecoderDictionaryExtractor.cpp index e47ead1f..c4c9ef36 100644 --- a/src/datamanagement/datamanager/src/DecoderDictionaryExtractor.cpp +++ b/src/DecoderDictionaryExtractor.cpp @@ -1,19 +1,20 @@ // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 -// Includes -#include "CollectionSchemeManager.h" +#include "CollectionSchemeManager.h" // IWYU pragma: associated +#include "ICollectionScheme.h" #include "LoggingModule.h" -#include "TraceModule.h" +#include "MessageTypes.h" +#include #include +#include +#include #include namespace Aws { namespace IoTFleetWise { -namespace DataManagement -{ void CollectionSchemeManager::decoderDictionaryExtractor( @@ -230,6 +231,6 @@ CollectionSchemeManager::decoderDictionaryUpdater( &IActiveDecoderDictionaryListener::onChangeOfActiveDictionary, dictPtr, dict.first ); } } -} // namespace DataManagement + } // namespace IoTFleetWise } // namespace Aws diff --git a/src/datamanagement/datadecoding/src/DecoderManifestIngestion.cpp b/src/DecoderManifestIngestion.cpp similarity index 96% rename from src/datamanagement/datadecoding/src/DecoderManifestIngestion.cpp rename to src/DecoderManifestIngestion.cpp index 25a05271..10c4eb6d 100644 --- a/src/datamanagement/datadecoding/src/DecoderManifestIngestion.cpp +++ b/src/DecoderManifestIngestion.cpp @@ -2,18 +2,16 @@ // SPDX-License-Identifier: Apache-2.0 #include "DecoderManifestIngestion.h" -#include "CollectionInspectionAPITypes.h" +#include "CANDataTypes.h" +#include "EnumUtility.h" #include "LoggingModule.h" -#include +#include "OBDDataTypes.h" +#include namespace Aws { namespace IoTFleetWise { -namespace DataManagement -{ - -using namespace Aws::IoTFleetWise::Schemas; DecoderManifestIngestion::~DecoderManifestIngestion() { @@ -189,7 +187,7 @@ DecoderManifestIngestion::build() for ( int i = 0; i < mProtoDecoderManifest.can_signals_size(); i++ ) { // Get a reference to the CAN signal in the protobuf - const DecoderManifestMsg::CANSignal &canSignal = mProtoDecoderManifest.can_signals( i ); + const Schemas::DecoderManifestMsg::CANSignal &canSignal = mProtoDecoderManifest.can_signals( i ); mSignalToVehicleDataSourceProtocol[canSignal.signal_id()] = VehicleDataSourceProtocol::RAW_SOCKET; // Add an entry to the Signal to CANRawFrameID and NodeID dictionary @@ -265,7 +263,7 @@ DecoderManifestIngestion::build() for ( int i = 0; i < mProtoDecoderManifest.obd_pid_signals_size(); i++ ) { // Get a reference to the OBD PID signal in the protobuf - const DecoderManifestMsg::OBDPIDSignal &pidSignal = mProtoDecoderManifest.obd_pid_signals( i ); + const Schemas::DecoderManifestMsg::OBDPIDSignal &pidSignal = mProtoDecoderManifest.obd_pid_signals( i ); if ( ( pidSignal.service_mode() >= toUType( SID::MAX ) ) || ( pidSignal.pid() > UINT8_MAX ) || ( pidSignal.bit_right_shift() > UINT8_MAX ) || ( pidSignal.bit_mask_length() > UINT8_MAX ) ) { @@ -295,6 +293,5 @@ DecoderManifestIngestion::build() return true; } -} // namespace DataManagement } // namespace IoTFleetWise } // namespace Aws diff --git a/src/datamanagement/datadecoding/include/DecoderManifestIngestion.h b/src/DecoderManifestIngestion.h similarity index 94% rename from src/datamanagement/datadecoding/include/DecoderManifestIngestion.h rename to src/DecoderManifestIngestion.h index ee059020..af8682c5 100644 --- a/src/datamanagement/datadecoding/include/DecoderManifestIngestion.h +++ b/src/DecoderManifestIngestion.h @@ -5,19 +5,21 @@ #include "IDecoderManifest.h" #include "LoggingModule.h" +#include "MessageTypes.h" +#include "SignalTypes.h" +#include "VehicleDataSourceTypes.h" #include "decoder_manifest.pb.h" +#include +#include +#include #include +#include #include namespace Aws { namespace IoTFleetWise { -namespace DataManagement -{ - -using namespace Aws::IoTFleetWise::Platform::Linux; -using namespace Aws::IoTFleetWise::Schemas; // A dictionary type that maps CANRawFrameID's to their associated CANMessageFormats using CANFrameToMessageMap = std::unordered_map; @@ -84,7 +86,7 @@ class DecoderManifestIngestion : public IDecoderManifest /** * @brief The DecoderManifest message that will hold the deserialized proto. */ - DecoderManifestMsg::DecoderManifest mProtoDecoderManifest; + Schemas::DecoderManifestMsg::DecoderManifest mProtoDecoderManifest; /** * @brief This vector will store the binary data copied from the IReceiver callback. @@ -124,6 +126,6 @@ class DecoderManifestIngestion : public IDecoderManifest using SignalIDToTypeMap = std::unordered_map; SignalIDToTypeMap mSignalIDToTypeMap; }; -} // namespace DataManagement + } // namespace IoTFleetWise } // namespace Aws diff --git a/src/platform/utility/include/EnumUtility.h b/src/EnumUtility.h similarity index 79% rename from src/platform/utility/include/EnumUtility.h rename to src/EnumUtility.h index 7889e19f..6579a10d 100644 --- a/src/platform/utility/include/EnumUtility.h +++ b/src/EnumUtility.h @@ -1,14 +1,14 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + #pragma once #include + namespace Aws { namespace IoTFleetWise { -namespace Platform -{ -namespace Utility -{ /** * @brief Get the underlying type of an enum @@ -23,7 +23,6 @@ toUType( E enumerator ) { return static_cast>( enumerator ); } -} // namespace Utility -} // namespace Platform + } // namespace IoTFleetWise } // namespace Aws diff --git a/src/datamanagement/types/include/EventTypes.h b/src/EventTypes.h similarity index 85% rename from src/datamanagement/types/include/EventTypes.h rename to src/EventTypes.h index 3f5e3f65..d0f8663c 100644 --- a/src/datamanagement/types/include/EventTypes.h +++ b/src/EventTypes.h @@ -9,13 +9,11 @@ namespace Aws { namespace IoTFleetWise { -namespace DataManagement -{ + /** * @brief Identifier of Event triggered by a collectionScheme. */ using EventID = uint32_t; -} // namespace DataManagement } // namespace IoTFleetWise } // namespace Aws diff --git a/src/datamanagement/datainspection/src/vehicledatasource/ExternalCANDataSource.cpp b/src/ExternalCANDataSource.cpp similarity index 94% rename from src/datamanagement/datainspection/src/vehicledatasource/ExternalCANDataSource.cpp rename to src/ExternalCANDataSource.cpp index 06a98c97..8aa53699 100644 --- a/src/datamanagement/datainspection/src/vehicledatasource/ExternalCANDataSource.cpp +++ b/src/ExternalCANDataSource.cpp @@ -1,7 +1,6 @@ // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 -// Includes #include "ExternalCANDataSource.h" #include "EnumUtility.h" #include "LoggingModule.h" @@ -11,9 +10,6 @@ namespace Aws { namespace IoTFleetWise { -namespace DataInspection -{ -using namespace Aws::IoTFleetWise::Platform::Utility; ExternalCANDataSource::ExternalCANDataSource( CANDataConsumer &consumer ) : mConsumer{ consumer } @@ -69,6 +65,5 @@ ExternalCANDataSource::onChangeOfActiveDictionary( ConstDecoderDictionaryConstPt } } -} // namespace DataInspection } // namespace IoTFleetWise } // namespace Aws diff --git a/src/datamanagement/datainspection/include/ExternalCANDataSource.h b/src/ExternalCANDataSource.h similarity index 92% rename from src/datamanagement/datainspection/include/ExternalCANDataSource.h rename to src/ExternalCANDataSource.h index 8d84003c..af03b5ee 100644 --- a/src/datamanagement/datainspection/include/ExternalCANDataSource.h +++ b/src/ExternalCANDataSource.h @@ -3,28 +3,23 @@ #pragma once -// Includes #include "CANDataConsumer.h" +#include "Clock.h" #include "ClockHandler.h" -#include "CollectionInspectionAPITypes.h" #include "IActiveDecoderDictionaryListener.h" #include "IDecoderDictionary.h" -#include "Signal.h" #include "SignalTypes.h" #include "TimeTypes.h" +#include "VehicleDataSourceTypes.h" #include #include #include #include -using namespace Aws::IoTFleetWise::Platform::Linux; - namespace Aws { namespace IoTFleetWise { -namespace DataInspection -{ /** * @brief External CAN Bus implementation. Allows data from external in-process CAN bus sources to @@ -68,6 +63,5 @@ class ExternalCANDataSource : public IActiveDecoderDictionaryListener Timestamp mLastFrameTime{}; }; -} // namespace DataInspection } // namespace IoTFleetWise } // namespace Aws diff --git a/src/datamanagement/custom/example/externalgps/src/ExternalGpsSource.cpp b/src/ExternalGpsSource.cpp similarity index 86% rename from src/datamanagement/custom/example/externalgps/src/ExternalGpsSource.cpp rename to src/ExternalGpsSource.cpp index a80beb28..d19e502e 100644 --- a/src/datamanagement/custom/example/externalgps/src/ExternalGpsSource.cpp +++ b/src/ExternalGpsSource.cpp @@ -1,21 +1,23 @@ // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 -// Includes #include "ExternalGpsSource.h" #include "LoggingModule.h" #include "TraceModule.h" +#include +#include +#include namespace Aws { namespace IoTFleetWise { -namespace DataManagement -{ -constexpr const char *ExternalGpsSource::CAN_CHANNEL_NUMBER; -constexpr const char *ExternalGpsSource::CAN_RAW_FRAME_ID; -constexpr const char *ExternalGpsSource::LATITUDE_START_BIT; -constexpr const char *ExternalGpsSource::LONGITUDE_START_BIT; + +// NOLINT below due to C++17 warning of redundant declarations that are required to maintain C++14 compatibility +constexpr const char *ExternalGpsSource::CAN_CHANNEL_NUMBER; // NOLINT +constexpr const char *ExternalGpsSource::CAN_RAW_FRAME_ID; // NOLINT +constexpr const char *ExternalGpsSource::LATITUDE_START_BIT; // NOLINT +constexpr const char *ExternalGpsSource::LONGITUDE_START_BIT; // NOLINT ExternalGpsSource::ExternalGpsSource( SignalBufferPtr signalBufferPtr ) : mSignalBufferPtr{ std::move( signalBufferPtr ) } { @@ -92,6 +94,5 @@ ExternalGpsSource::validLongitude( double longitude ) return ( longitude >= -180.0 ) && ( longitude <= 180.0 ); } -} // namespace DataManagement } // namespace IoTFleetWise } // namespace Aws diff --git a/src/datamanagement/custom/example/externalgps/include/ExternalGpsSource.h b/src/ExternalGpsSource.h similarity index 89% rename from src/datamanagement/custom/example/externalgps/include/ExternalGpsSource.h rename to src/ExternalGpsSource.h index 19a6f73d..f53f969b 100644 --- a/src/datamanagement/custom/example/externalgps/include/ExternalGpsSource.h +++ b/src/ExternalGpsSource.h @@ -2,21 +2,18 @@ // SPDX-License-Identifier: Apache-2.0 #pragma once +#include "Clock.h" #include "ClockHandler.h" #include "CollectionInspectionAPITypes.h" #include "CustomDataSource.h" -#include "Timer.h" -#include +#include "SignalTypes.h" +#include +#include namespace Aws { namespace IoTFleetWise { -namespace DataManagement -{ -using namespace Aws::IoTFleetWise::Platform::Linux; -using namespace Aws::IoTFleetWise::VehicleNetwork; -using namespace Aws::IoTFleetWise::DataInspection; /** * To implement a custom data source create a new class and inherit from CustomDataSource @@ -67,6 +64,6 @@ class ExternalGpsSource : public CustomDataSource CANChannelNumericID mCanChannel{ INVALID_CAN_SOURCE_NUMERIC_ID }; CANRawFrameID mCanRawFrameId{ 0 }; }; -} // namespace DataManagement + } // namespace IoTFleetWise } // namespace Aws diff --git a/src/datamanagement/types/src/Geohash.cpp b/src/Geohash.cpp similarity index 98% rename from src/datamanagement/types/src/Geohash.cpp rename to src/Geohash.cpp index bdd16602..bf814ebc 100644 --- a/src/datamanagement/types/src/Geohash.cpp +++ b/src/Geohash.cpp @@ -1,14 +1,12 @@ // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 -// Includes #include "Geohash.h" namespace Aws { namespace IoTFleetWise { -namespace DataInspection -{ + // This is a Base 32 character map. The map index is the number. // For instance, 8 correspond to '8', 31 correspond to 'z' static constexpr char base32Map[32] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'b', @@ -108,6 +106,5 @@ Geohash::encode( double lat, double lon, uint8_t precision, std::string &hashStr return true; } -} // namespace DataInspection } // namespace IoTFleetWise } // namespace Aws diff --git a/src/datamanagement/types/include/Geohash.h b/src/Geohash.h similarity index 97% rename from src/datamanagement/types/include/Geohash.h rename to src/Geohash.h index 6f719a8d..12a5bde1 100644 --- a/src/datamanagement/types/include/Geohash.h +++ b/src/Geohash.h @@ -10,8 +10,6 @@ namespace Aws { namespace IoTFleetWise { -namespace DataInspection -{ /** * @brief This is the Geohash module that can convert GPS latitude and longitude to GeoHash @@ -63,6 +61,6 @@ class Geohash // maximum Longitude static constexpr double LON_MAX = 180.0; }; -} // namespace DataInspection + } // namespace IoTFleetWise } // namespace Aws diff --git a/src/datamanagement/datainspection/src/location/GeohashFunctionNode.cpp b/src/GeohashFunctionNode.cpp similarity index 98% rename from src/datamanagement/datainspection/src/location/GeohashFunctionNode.cpp rename to src/GeohashFunctionNode.cpp index 8c4fd71e..2c378fb3 100644 --- a/src/datamanagement/datainspection/src/location/GeohashFunctionNode.cpp +++ b/src/GeohashFunctionNode.cpp @@ -1,17 +1,16 @@ // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 -// Includes #include "GeohashFunctionNode.h" +#include "Geohash.h" #include "LoggingModule.h" #include "TraceModule.h" +#include namespace Aws { namespace IoTFleetWise { -namespace DataInspection -{ bool GeohashFunctionNode::evaluateGeohash( double latitude, @@ -108,6 +107,5 @@ GeohashFunctionNode::convertToDecimalDegree( double value, GeohashFunction::GPSU return convertedValue; } -} // namespace DataInspection } // namespace IoTFleetWise } // namespace Aws diff --git a/src/datamanagement/datainspection/include/GeohashFunctionNode.h b/src/GeohashFunctionNode.h similarity index 93% rename from src/datamanagement/datainspection/include/GeohashFunctionNode.h rename to src/GeohashFunctionNode.h index 2a347bb7..c0f44c54 100644 --- a/src/datamanagement/datainspection/include/GeohashFunctionNode.h +++ b/src/GeohashFunctionNode.h @@ -3,20 +3,14 @@ #pragma once -#include "Geohash.h" #include "GeohashInfo.h" #include "ICollectionScheme.h" -#include +#include namespace Aws { namespace IoTFleetWise { -namespace DataInspection -{ - -using namespace Aws::IoTFleetWise::Platform::Linux; -using namespace Aws::IoTFleetWise::DataManagement; /** * @brief This is the Geohash Function Node module that can be used as part of the AST tree to @@ -84,6 +78,6 @@ class GeohashFunctionNode */ bool mIsGeohashNew{ false }; }; -} // namespace DataInspection + } // namespace IoTFleetWise } // namespace Aws diff --git a/src/datamanagement/types/include/GeohashInfo.h b/src/GeohashInfo.h similarity index 87% rename from src/datamanagement/types/include/GeohashInfo.h rename to src/GeohashInfo.h index 9929a723..d5a3c249 100644 --- a/src/datamanagement/types/include/GeohashInfo.h +++ b/src/GeohashInfo.h @@ -1,3 +1,6 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + #pragma once #include @@ -6,8 +9,6 @@ namespace Aws { namespace IoTFleetWise { -namespace DataInspection -{ /** * @brief This struct encapsulates the Geohash information. @@ -31,6 +32,6 @@ struct GeohashInfo return mGeohashString.length() > 0; } }; -} // namespace DataInspection + } // namespace IoTFleetWise } // namespace Aws diff --git a/src/datamanagement/datamanager/include/IActiveCollectionSchemesListener.h b/src/IActiveCollectionSchemesListener.h similarity index 94% rename from src/datamanagement/datamanager/include/IActiveCollectionSchemesListener.h rename to src/IActiveCollectionSchemesListener.h index 22d346eb..80b4541e 100644 --- a/src/datamanagement/datamanager/include/IActiveCollectionSchemesListener.h +++ b/src/IActiveCollectionSchemesListener.h @@ -8,8 +8,7 @@ namespace Aws { namespace IoTFleetWise { -namespace DataManagement -{ + /** * @brief Interface for components interested in the currently active collection schemes. Used to prepare senders based * on campaign data before the data is collected and selected for the upload. @@ -33,6 +32,6 @@ class IActiveCollectionSchemesListener virtual ~IActiveCollectionSchemesListener() = default; }; -} // namespace DataManagement + } // namespace IoTFleetWise } // namespace Aws diff --git a/src/datamanagement/datainspection/include/IActiveConditionProcessor.h b/src/IActiveConditionProcessor.h similarity index 91% rename from src/datamanagement/datainspection/include/IActiveConditionProcessor.h rename to src/IActiveConditionProcessor.h index 2c47e654..76912a63 100644 --- a/src/datamanagement/datainspection/include/IActiveConditionProcessor.h +++ b/src/IActiveConditionProcessor.h @@ -13,9 +13,7 @@ namespace Aws { namespace IoTFleetWise { -namespace DataInspection -{ -using namespace Aws::IoTFleetWise::DataManagement; + /** * @brief Interface for components interested in the currently active conditions * @@ -36,6 +34,6 @@ class IActiveConditionProcessor virtual ~IActiveConditionProcessor() = default; }; -} // namespace DataInspection + } // namespace IoTFleetWise } // namespace Aws diff --git a/src/datamanagement/datadecoding/include/IActiveDecoderDictionaryListener.h b/src/IActiveDecoderDictionaryListener.h similarity index 89% rename from src/datamanagement/datadecoding/include/IActiveDecoderDictionaryListener.h rename to src/IActiveDecoderDictionaryListener.h index 489ecd5b..677d9f2f 100644 --- a/src/datamanagement/datadecoding/include/IActiveDecoderDictionaryListener.h +++ b/src/IActiveDecoderDictionaryListener.h @@ -3,17 +3,12 @@ #pragma once -// Includes #include "IDecoderDictionary.h" namespace Aws { namespace IoTFleetWise { -namespace DataInspection -{ - -using namespace Aws::IoTFleetWise::DataManagement; /** * @brief This is the listener interface to notify any listeners on change of Decoder Dictionary. @@ -37,6 +32,6 @@ class IActiveDecoderDictionaryListener virtual void onChangeOfActiveDictionary( ConstDecoderDictionaryConstPtr &dictionary, VehicleDataSourceProtocol networkProtocol ) = 0; }; -} // namespace DataInspection + } // namespace IoTFleetWise } // namespace Aws diff --git a/src/datamanagement/datacollection/include/ICollectionScheme.h b/src/ICollectionScheme.h similarity index 98% rename from src/datamanagement/datacollection/include/ICollectionScheme.h rename to src/ICollectionScheme.h index d115b5c6..eaf1f117 100644 --- a/src/datamanagement/datacollection/include/ICollectionScheme.h +++ b/src/ICollectionScheme.h @@ -16,8 +16,6 @@ namespace Aws { namespace IoTFleetWise { -namespace DataManagement -{ struct SignalCollectionInfo { @@ -146,12 +144,12 @@ struct ExpressionNode /** * @brief AST Construction Left Side */ - struct ExpressionNode *left{ nullptr }; + ExpressionNode *left{ nullptr }; /** * @brief AST Construction Right Side */ - struct ExpressionNode *right{ nullptr }; + ExpressionNode *right{ nullptr }; /** * @brief Node Value is a floating point @@ -323,7 +321,7 @@ class ICollectionScheme * * @return the returned pointer is either nullptr or valid as long as ICollectionScheme is alive */ - virtual const struct ExpressionNode *getCondition() const = 0; + virtual const ExpressionNode *getCondition() const = 0; /** * @brief Returns all signals that this collectionScheme wants to collect @@ -349,6 +347,5 @@ class ICollectionScheme virtual ~ICollectionScheme() = default; }; -} // namespace DataManagement } // namespace IoTFleetWise } // namespace Aws diff --git a/src/datamanagement/datacollection/include/ICollectionSchemeList.h b/src/ICollectionSchemeList.h similarity index 98% rename from src/datamanagement/datacollection/include/ICollectionSchemeList.h rename to src/ICollectionSchemeList.h index 8c3ca32b..ce63b324 100644 --- a/src/datamanagement/datacollection/include/ICollectionSchemeList.h +++ b/src/ICollectionSchemeList.h @@ -11,9 +11,6 @@ namespace Aws { namespace IoTFleetWise { -namespace DataManagement -{ - using ICollectionSchemePtr = std::shared_ptr; /** @@ -79,6 +76,5 @@ class ICollectionSchemeList virtual ~ICollectionSchemeList() = default; }; -} // namespace DataManagement } // namespace IoTFleetWise } // namespace Aws diff --git a/src/datamanagement/datamanager/include/ICollectionSchemeManager.h b/src/ICollectionSchemeManager.h similarity index 95% rename from src/datamanagement/datamanager/include/ICollectionSchemeManager.h rename to src/ICollectionSchemeManager.h index d66c2e32..f98e06f5 100644 --- a/src/datamanagement/datamanager/include/ICollectionSchemeManager.h +++ b/src/ICollectionSchemeManager.h @@ -3,7 +3,6 @@ #pragma once -// Includes #include "CacheAndPersist.h" #include "CollectionInspectionAPITypes.h" #include "CollectionSchemeManagementListener.h" @@ -12,10 +11,6 @@ namespace Aws { namespace IoTFleetWise { -namespace DataManagement -{ -using namespace Aws::IoTFleetWise::Platform::Linux::PersistencyManagement; -using namespace Aws::IoTFleetWise::DataInspection; class ICollectionSchemeManager { @@ -123,6 +118,5 @@ class ICollectionSchemeManager virtual void updateAvailable() = 0; }; -} // namespace DataManagement } // namespace IoTFleetWise } // namespace Aws diff --git a/src/offboardconnectivity/api/include/IConnectionTypes.h b/src/IConnectionTypes.h similarity index 83% rename from src/offboardconnectivity/api/include/IConnectionTypes.h rename to src/IConnectionTypes.h index 96684281..3f84c870 100644 --- a/src/offboardconnectivity/api/include/IConnectionTypes.h +++ b/src/IConnectionTypes.h @@ -7,11 +7,6 @@ namespace Aws { namespace IoTFleetWise { -/** -@brief OffboardConnectivity has all the classes responsible for communicating with the cloud -*/ -namespace OffboardConnectivity -{ /** * @brief Defines the return code used by the Connectivity API @@ -26,6 +21,5 @@ enum class ConnectivityError TypeNotSupported, /**< requested upload type is not supported by the sender */ }; -} // namespace OffboardConnectivity } // namespace IoTFleetWise } // namespace Aws diff --git a/src/offboardconnectivity/api/include/IConnectivityChannel.h b/src/IConnectivityChannel.h similarity index 79% rename from src/offboardconnectivity/api/include/IConnectivityChannel.h rename to src/IConnectivityChannel.h index 37d15560..d846ce02 100644 --- a/src/offboardconnectivity/api/include/IConnectivityChannel.h +++ b/src/IConnectivityChannel.h @@ -3,7 +3,6 @@ #pragma once -// Includes #include "IReceiver.h" #include "ISender.h" #include "PayloadManager.h" @@ -18,11 +17,7 @@ namespace Aws namespace IoTFleetWise { -namespace OffboardConnectivity -{ - -class IConnectivityChannel : public Aws::IoTFleetWise::OffboardConnectivity::ISender, - public Aws::IoTFleetWise::OffboardConnectivity::IReceiver +class IConnectivityChannel : public ISender, public IReceiver { public: ~IConnectivityChannel() override = default; @@ -39,6 +34,5 @@ class IConnectivityChannel : public Aws::IoTFleetWise::OffboardConnectivity::ISe virtual unsigned getPayloadCountSent() const = 0; }; -} // namespace OffboardConnectivity } // namespace IoTFleetWise } // namespace Aws diff --git a/src/offboardconnectivity/api/include/IConnectivityModule.h b/src/IConnectivityModule.h similarity index 83% rename from src/offboardconnectivity/api/include/IConnectivityModule.h rename to src/IConnectivityModule.h index 4a431d3f..f481e561 100644 --- a/src/offboardconnectivity/api/include/IConnectivityModule.h +++ b/src/IConnectivityModule.h @@ -15,10 +15,6 @@ namespace Aws namespace IoTFleetWise { -namespace OffboardConnectivity -{ -using Aws::IoTFleetWise::OffboardConnectivityAwsIot::PayloadManager; - class IConnectivityModule { public: @@ -34,6 +30,5 @@ class IConnectivityModule virtual bool connect() = 0; }; -} // namespace OffboardConnectivity } // namespace IoTFleetWise } // namespace Aws diff --git a/src/datamanagement/datainspection/include/IDataReadyToPublishListener.h b/src/IDataReadyToPublishListener.h similarity index 89% rename from src/datamanagement/datainspection/include/IDataReadyToPublishListener.h rename to src/IDataReadyToPublishListener.h index 8665da00..87863b09 100644 --- a/src/datamanagement/datainspection/include/IDataReadyToPublishListener.h +++ b/src/IDataReadyToPublishListener.h @@ -7,8 +7,6 @@ namespace Aws { namespace IoTFleetWise { -namespace DataInspection -{ class IDataReadyToPublishListener { @@ -20,6 +18,6 @@ class IDataReadyToPublishListener */ virtual void onDataReadyToPublish() = 0; }; -} // namespace DataInspection + } // namespace IoTFleetWise } // namespace Aws diff --git a/src/datamanagement/datadecoding/include/IDecoderDictionary.h b/src/IDecoderDictionary.h similarity index 97% rename from src/datamanagement/datadecoding/include/IDecoderDictionary.h rename to src/IDecoderDictionary.h index 83891dfe..6857a418 100644 --- a/src/datamanagement/datadecoding/include/IDecoderDictionary.h +++ b/src/IDecoderDictionary.h @@ -3,7 +3,6 @@ #pragma once -// Includes #include "IDecoderManifest.h" #include #include @@ -12,8 +11,6 @@ namespace Aws { namespace IoTFleetWise { -namespace DataManagement -{ /** * @brief enum class for message collect type. It specifies whether the message is intended to @@ -87,6 +84,5 @@ struct CANDecoderDictionary : DecoderDictionary */ using ConstDecoderDictionaryConstPtr = const std::shared_ptr; -} // namespace DataManagement } // namespace IoTFleetWise } // namespace Aws diff --git a/src/datamanagement/datadecoding/include/IDecoderManifest.h b/src/IDecoderManifest.h similarity index 99% rename from src/datamanagement/datadecoding/include/IDecoderManifest.h rename to src/IDecoderManifest.h index 358aef9b..09763fbd 100644 --- a/src/datamanagement/datadecoding/include/IDecoderManifest.h +++ b/src/IDecoderManifest.h @@ -15,8 +15,7 @@ namespace Aws { namespace IoTFleetWise { -namespace DataManagement -{ + /** * @brief An invalid CAN Message Format, set as a CANMessageFormat object initialized to all zeros */ @@ -236,6 +235,5 @@ class IDecoderManifest virtual ~IDecoderManifest() = default; }; -} // namespace DataManagement } // namespace IoTFleetWise } // namespace Aws diff --git a/src/platform/linux/logmanagement/include/ILogger.h b/src/ILogger.h similarity index 93% rename from src/platform/linux/logmanagement/include/ILogger.h rename to src/ILogger.h index c75e5e00..c71d4175 100644 --- a/src/platform/linux/logmanagement/include/ILogger.h +++ b/src/ILogger.h @@ -3,7 +3,6 @@ #pragma once -// Includes #include "LogLevel.h" #include #include @@ -13,10 +12,7 @@ namespace Aws { namespace IoTFleetWise { -namespace Platform -{ -namespace Linux -{ + class ILogger { public: @@ -53,7 +49,5 @@ class ILogger */ extern void setLogForwarding( ILogger *logForwarder ); -} // namespace Linux -} // namespace Platform } // namespace IoTFleetWise } // namespace Aws diff --git a/src/offboardconnectivity/api/include/IReceiver.h b/src/IReceiver.h similarity index 90% rename from src/offboardconnectivity/api/include/IReceiver.h rename to src/IReceiver.h index 6be786e8..c9438a60 100644 --- a/src/offboardconnectivity/api/include/IReceiver.h +++ b/src/IReceiver.h @@ -10,9 +10,6 @@ namespace Aws { namespace IoTFleetWise { -namespace OffboardConnectivity -{ -using Aws::IoTFleetWise::Platform::Linux::ThreadListeners; /** * @brief Receiver must inherit from IReceiverCallback @@ -55,7 +52,7 @@ struct IReceiverCallback * \endcode * @see IReceiverCallback */ -class IReceiver : public Aws::IoTFleetWise::Platform::Linux::ThreadListeners +class IReceiver : public ThreadListeners { public: @@ -68,6 +65,6 @@ class IReceiver : public Aws::IoTFleetWise::Platform::Linux::ThreadListeners #include @@ -11,8 +10,7 @@ namespace Aws { namespace IoTFleetWise { -namespace VehicleNetwork -{ + // According to J1979 6.2.2.7, we should wait at least P2CAN Max ( 50 ms ) // We relax that a bit e.g. up to 1000 ms for network latency. const uint32_t P2_TIMEOUT_DEFAULT_MS = 1000; // P2*CAN Max is 1 second @@ -142,6 +140,6 @@ struct ISOTPOverCANSenderReceiverOptions uint32_t mP2TimeoutMs{ P2_TIMEOUT_DEFAULT_MS }; int mBroadcastSocket{ -1 }; }; -} // namespace VehicleNetwork + } // namespace IoTFleetWise } // namespace Aws diff --git a/src/vehiclenetwork/src/ISOTPOverCANReceiver.cpp b/src/ISOTPOverCANReceiver.cpp similarity index 91% rename from src/vehiclenetwork/src/ISOTPOverCANReceiver.cpp rename to src/ISOTPOverCANReceiver.cpp index c308c0e5..b15b772f 100644 --- a/src/vehiclenetwork/src/ISOTPOverCANReceiver.cpp +++ b/src/ISOTPOverCANReceiver.cpp @@ -1,19 +1,14 @@ // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 -#if defined( IOTFLEETWISE_LINUX ) -// Includes -#include "businterfaces/ISOTPOverCANReceiver.h" -#include "ClockHandler.h" +#include "ISOTPOverCANReceiver.h" #include "LoggingModule.h" -#include -#include #include #include #include #include +#include #include -#include #include // ISO TP maximum PDU size is 4095, additional bytes are needed @@ -24,8 +19,6 @@ namespace Aws { namespace IoTFleetWise { -namespace VehicleNetwork -{ bool ISOTPOverCANReceiver::init( const ISOTPOverCANReceiverOptions &receiverOptions ) @@ -63,7 +56,8 @@ ISOTPOverCANReceiver::connect() mSocket = socket( PF_CAN, SOCK_DGRAM /*| SOCK_NONBLOCK*/, CAN_ISOTP ); if ( mSocket < 0 ) { - FWE_LOG_ERROR( "Failed to create the ISOTP Socket to IF: " + mReceiverOptions.mSocketCanIFName ); + FWE_LOG_ERROR( "Failed to create the ISOTP Socket to IF: " + mReceiverOptions.mSocketCanIFName + + " Error: " + getErrnoString() ); return false; } @@ -85,7 +79,8 @@ ISOTPOverCANReceiver::connect() // NOLINTNEXTLINE(cppcoreguidelines-pro-type-cstyle-cast) if ( bind( mSocket, (struct sockaddr *)&interfaceAddress, sizeof( interfaceAddress ) ) < 0 ) { - FWE_LOG_ERROR( "Failed to bind the ISOTP Socket to IF: " + mReceiverOptions.mSocketCanIFName ); + FWE_LOG_ERROR( "Failed to bind the ISOTP Socket to IF: " + mReceiverOptions.mSocketCanIFName + + " Error: " + getErrnoString() ); close( mSocket ); return false; } @@ -98,7 +93,8 @@ ISOTPOverCANReceiver::disconnect() const { if ( close( mSocket ) < 0 ) { - FWE_LOG_ERROR( "Failed to disconnect the ISOTP Socket from IF: " + mReceiverOptions.mSocketCanIFName ); + FWE_LOG_ERROR( "Failed to disconnect the ISOTP Socket from IF: " + mReceiverOptions.mSocketCanIFName + + " Error: " + getErrnoString() ); return false; } FWE_LOG_TRACE( "ISOTP Socket disconnected from IF: " + mReceiverOptions.mSocketCanIFName ); @@ -146,7 +142,5 @@ ISOTPOverCANReceiver::receivePDU( std::vector &pduData ) return bytesRead > 0; } -} // namespace VehicleNetwork } // namespace IoTFleetWise } // namespace Aws -#endif // IOTFLEETWISE_LINUX diff --git a/src/vehiclenetwork/include/businterfaces/ISOTPOverCANReceiver.h b/src/ISOTPOverCANReceiver.h similarity index 90% rename from src/vehiclenetwork/include/businterfaces/ISOTPOverCANReceiver.h rename to src/ISOTPOverCANReceiver.h index 80c5072e..ca8b88d4 100644 --- a/src/vehiclenetwork/include/businterfaces/ISOTPOverCANReceiver.h +++ b/src/ISOTPOverCANReceiver.h @@ -3,22 +3,19 @@ #pragma once -#if defined( IOTFLEETWISE_LINUX ) -// Includes +#include "Clock.h" #include "ClockHandler.h" +#include "ISOTPOverCANOptions.h" #include "Timer.h" -#include "datatypes/ISOTPOverCANOptions.h" -#include +#include +#include #include -using namespace Aws::IoTFleetWise::Platform::Linux; - namespace Aws { namespace IoTFleetWise { -namespace VehicleNetwork -{ + /** * @brief User Space API wrapping the ISO-TP Linux Kernel Module. * This is the Receiver API. API offers routines to receive PDUs on the @@ -83,7 +80,6 @@ class ISOTPOverCANReceiver std::shared_ptr mClock = ClockHandler::getClock(); int mSocket{}; }; -} // namespace VehicleNetwork + } // namespace IoTFleetWise } // namespace Aws -#endif // IOTFLEETWISE_LINUX diff --git a/src/vehiclenetwork/src/ISOTPOverCANSender.cpp b/src/ISOTPOverCANSender.cpp similarity index 88% rename from src/vehiclenetwork/src/ISOTPOverCANSender.cpp rename to src/ISOTPOverCANSender.cpp index 9835cf42..ba8a39bd 100644 --- a/src/vehiclenetwork/src/ISOTPOverCANSender.cpp +++ b/src/ISOTPOverCANSender.cpp @@ -1,15 +1,12 @@ // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 -#if defined( IOTFLEETWISE_LINUX ) -// Includes -#include "businterfaces/ISOTPOverCANSender.h" -#include "ClockHandler.h" +#include "ISOTPOverCANSender.h" #include "LoggingModule.h" -#include #include #include #include +#include #include #include @@ -17,8 +14,6 @@ namespace Aws { namespace IoTFleetWise { -namespace VehicleNetwork -{ bool ISOTPOverCANSender::init( const ISOTPOverCANSenderOptions &senderOptions ) @@ -51,7 +46,8 @@ ISOTPOverCANSender::connect() mSocket = socket( PF_CAN, SOCK_DGRAM /*| SOCK_NONBLOCK*/, CAN_ISOTP ); if ( mSocket < 0 ) { - FWE_LOG_ERROR( "Failed to create the ISOTP Socket to IF: " + mSenderOptions.mSocketCanIFName ); + FWE_LOG_ERROR( "Failed to create the ISOTP Socket to IF: " + mSenderOptions.mSocketCanIFName + + " Error: " + getErrnoString() ); return false; } @@ -70,7 +66,8 @@ ISOTPOverCANSender::connect() // NOLINTNEXTLINE(cppcoreguidelines-pro-type-cstyle-cast) if ( bind( mSocket, (struct sockaddr *)&interfaceAddress, sizeof( interfaceAddress ) ) < 0 ) { - FWE_LOG_ERROR( "Failed to bind the ISOTP Socket to IF: " + mSenderOptions.mSocketCanIFName ); + FWE_LOG_ERROR( "Failed to bind the ISOTP Socket to IF: " + mSenderOptions.mSocketCanIFName + + " Error: " + getErrnoString() ); close( mSocket ); return false; } @@ -83,7 +80,8 @@ ISOTPOverCANSender::disconnect() const { if ( close( mSocket ) < 0 ) { - FWE_LOG_ERROR( "Failed to disconnect the ISOTP Socket from IF: " + mSenderOptions.mSocketCanIFName ); + FWE_LOG_ERROR( "Failed to disconnect the ISOTP Socket from IF: " + mSenderOptions.mSocketCanIFName + + " Error: " + getErrnoString() ); return false; } FWE_LOG_TRACE( "ISOTP Socket disconnected from IF: " + mSenderOptions.mSocketCanIFName ); @@ -104,11 +102,9 @@ bool ISOTPOverCANSender::sendPDU( const std::vector &pduData ) const { int bytesWritten = static_cast( write( mSocket, pduData.data(), pduData.size() ) ); - FWE_LOG_TRACE( "Dent a PDU of size: " + std::to_string( bytesWritten ) ); + FWE_LOG_TRACE( "Sent a PDU of size: " + std::to_string( bytesWritten ) ); return ( ( bytesWritten > 0 ) && ( bytesWritten == static_cast( pduData.size() ) ) ); } -} // namespace VehicleNetwork } // namespace IoTFleetWise } // namespace Aws -#endif // IOTFLEETWISE_LINUX diff --git a/src/vehiclenetwork/include/businterfaces/ISOTPOverCANSender.h b/src/ISOTPOverCANSender.h similarity index 88% rename from src/vehiclenetwork/include/businterfaces/ISOTPOverCANSender.h rename to src/ISOTPOverCANSender.h index d53d73d0..eec50c08 100644 --- a/src/vehiclenetwork/include/businterfaces/ISOTPOverCANSender.h +++ b/src/ISOTPOverCANSender.h @@ -3,22 +3,19 @@ #pragma once -#if defined( IOTFLEETWISE_LINUX ) -// Includes +#include "Clock.h" #include "ClockHandler.h" +#include "ISOTPOverCANOptions.h" #include "Timer.h" -#include "datatypes/ISOTPOverCANOptions.h" -#include +#include +#include #include -using namespace Aws::IoTFleetWise::Platform::Linux; - namespace Aws { namespace IoTFleetWise { -namespace VehicleNetwork -{ + /** * @brief User Space API wrapping the ISO-TP Linux Kernel Module. * This is the Sender API. API offers routines to send PDUs on the @@ -71,7 +68,6 @@ class ISOTPOverCANSender std::shared_ptr mClock = ClockHandler::getClock(); int mSocket{}; }; -} // namespace VehicleNetwork + } // namespace IoTFleetWise } // namespace Aws -#endif // IOTFLEETWISE_LINUX diff --git a/src/vehiclenetwork/src/ISOTPOverCANSenderReceiver.cpp b/src/ISOTPOverCANSenderReceiver.cpp similarity index 95% rename from src/vehiclenetwork/src/ISOTPOverCANSenderReceiver.cpp rename to src/ISOTPOverCANSenderReceiver.cpp index 3629064f..79e5a9f7 100644 --- a/src/vehiclenetwork/src/ISOTPOverCANSenderReceiver.cpp +++ b/src/ISOTPOverCANSenderReceiver.cpp @@ -1,20 +1,15 @@ // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 -#if defined( IOTFLEETWISE_LINUX ) -// Includes -#include "businterfaces/ISOTPOverCANSenderReceiver.h" -#include "ClockHandler.h" +#include "ISOTPOverCANSenderReceiver.h" #include "LoggingModule.h" -#include -#include +#include #include #include #include #include #include #include -#include #include // ISO TP maximum PDU size is 4095, additional bytes are needed @@ -25,8 +20,6 @@ namespace Aws { namespace IoTFleetWise { -namespace VehicleNetwork -{ bool ISOTPOverCANSenderReceiver::init( const ISOTPOverCANSenderReceiverOptions &senderReceiverOptions ) @@ -69,7 +62,7 @@ ISOTPOverCANSenderReceiver::connect() if ( mSocket < 0 ) { FWE_LOG_ERROR( "Failed to create the ISOTP rx id " + mStreamRxID + - " to IF:" + mSenderReceiverOptions.mSocketCanIFName ); + " to IF:" + mSenderReceiverOptions.mSocketCanIFName + " Error: " + getErrnoString() ); return false; } @@ -94,7 +87,7 @@ ISOTPOverCANSenderReceiver::connect() if ( bind( mSocket, (struct sockaddr *)&interfaceAddress, sizeof( interfaceAddress ) ) < 0 ) { FWE_LOG_ERROR( " Failed to bind the ISOTP rx id " + mStreamRxID + - " to IF: " + mSenderReceiverOptions.mSocketCanIFName ); + " to IF: " + mSenderReceiverOptions.mSocketCanIFName + " Error: " + getErrnoString() ); close( mSocket ); return false; } @@ -108,7 +101,7 @@ ISOTPOverCANSenderReceiver::disconnect() if ( close( mSocket ) < 0 ) { FWE_LOG_ERROR( "Failed to disconnect the ISOTP rx id " + mStreamRxID + - " from IF: " + mSenderReceiverOptions.mSocketCanIFName ); + " from IF: " + mSenderReceiverOptions.mSocketCanIFName + " Error: " + getErrnoString() ); return false; } FWE_LOG_TRACE( "ISOTP rx id " + mStreamRxID + " disconnected from IF: " + mSenderReceiverOptions.mSocketCanIFName ); @@ -201,7 +194,5 @@ ISOTPOverCANSenderReceiver::sendPDU( const std::vector &pduData ) return ( ( bytesWritten > 0 ) && ( bytesWritten == static_cast( pduData.size() ) ) ); } -} // namespace VehicleNetwork } // namespace IoTFleetWise } // namespace Aws -#endif // IOTFLEETWISE_LINUX diff --git a/src/vehiclenetwork/include/businterfaces/ISOTPOverCANSenderReceiver.h b/src/ISOTPOverCANSenderReceiver.h similarity index 91% rename from src/vehiclenetwork/include/businterfaces/ISOTPOverCANSenderReceiver.h rename to src/ISOTPOverCANSenderReceiver.h index 4d3bf8ac..0496df8e 100644 --- a/src/vehiclenetwork/include/businterfaces/ISOTPOverCANSenderReceiver.h +++ b/src/ISOTPOverCANSenderReceiver.h @@ -3,22 +3,20 @@ #pragma once -#if defined( IOTFLEETWISE_LINUX ) -// Includes +#include "Clock.h" #include "ClockHandler.h" +#include "ISOTPOverCANOptions.h" #include "Timer.h" -#include "datatypes/ISOTPOverCANOptions.h" -#include +#include +#include +#include #include -using namespace Aws::IoTFleetWise::Platform::Linux; - namespace Aws { namespace IoTFleetWise { -namespace VehicleNetwork -{ + /** * @brief User Space API wrapping the ISO-TP Linux Kernel Module. * This is the Sender/Receiver API. API offers routines to send @@ -99,7 +97,6 @@ class ISOTPOverCANSenderReceiver int mSocket{}; std::string mStreamRxID; }; -} // namespace VehicleNetwork + } // namespace IoTFleetWise } // namespace Aws -#endif // IOTFLEETWISE_LINUX diff --git a/src/offboardconnectivity/api/include/ISender.h b/src/ISender.h similarity index 89% rename from src/offboardconnectivity/api/include/ISender.h rename to src/ISender.h index 0df14a24..4532f1d6 100644 --- a/src/offboardconnectivity/api/include/ISender.h +++ b/src/ISender.h @@ -10,8 +10,6 @@ namespace Aws { namespace IoTFleetWise { -namespace OffboardConnectivity -{ /** * @brief Struct that specifies the persistence and transmission attributes @@ -72,7 +70,7 @@ class ISender virtual ConnectivityError sendBuffer( const std::uint8_t *buf, size_t size, - struct CollectionSchemeParams collectionSchemeParams = CollectionSchemeParams() ) = 0; + CollectionSchemeParams collectionSchemeParams = CollectionSchemeParams() ) = 0; /** * @brief called to send data from file to the cloud @@ -86,11 +84,10 @@ class ISender * * @return SUCCESS if connection is established. */ - virtual ConnectivityError sendFile( - const std::string &filePath, - size_t size, - struct CollectionSchemeParams collectionSchemeParams = CollectionSchemeParams() ) = 0; + virtual ConnectivityError sendFile( const std::string &filePath, + size_t size, + CollectionSchemeParams collectionSchemeParams = CollectionSchemeParams() ) = 0; }; -} // namespace OffboardConnectivity + } // namespace IoTFleetWise } // namespace Aws diff --git a/src/datamanagement/custom/example/iwavegps/src/IWaveGpsSource.cpp b/src/IWaveGpsSource.cpp similarity index 98% rename from src/datamanagement/custom/example/iwavegps/src/IWaveGpsSource.cpp rename to src/IWaveGpsSource.cpp index aaf113e9..e501a67e 100644 --- a/src/datamanagement/custom/example/iwavegps/src/IWaveGpsSource.cpp +++ b/src/IWaveGpsSource.cpp @@ -1,21 +1,22 @@ // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 -#if defined( IOTFLEETWISE_LINUX ) -// Includes + #include "IWaveGpsSource.h" #include "LoggingModule.h" #include "TraceModule.h" +#include #include +#include #include #include #include +#include namespace Aws { namespace IoTFleetWise { -namespace DataManagement -{ + // NOLINT below due to C++17 warning of redundant declarations that are required to maintain C++14 compatibility constexpr const char *IWaveGpsSource::PATH_TO_NMEA; // NOLINT constexpr const char *IWaveGpsSource::CAN_CHANNEL_NUMBER; // NOLINT @@ -229,7 +230,5 @@ IWaveGpsSource::disconnect() return true; } -} // namespace DataManagement } // namespace IoTFleetWise } // namespace Aws -#endif diff --git a/src/datamanagement/custom/example/iwavegps/include/IWaveGpsSource.h b/src/IWaveGpsSource.h similarity index 94% rename from src/datamanagement/custom/example/iwavegps/include/IWaveGpsSource.h rename to src/IWaveGpsSource.h index 15b11c8d..91823314 100644 --- a/src/datamanagement/custom/example/iwavegps/include/IWaveGpsSource.h +++ b/src/IWaveGpsSource.h @@ -2,20 +2,20 @@ // SPDX-License-Identifier: Apache-2.0 #pragma once +#include "Clock.h" #include "ClockHandler.h" #include "CollectionInspectionAPITypes.h" #include "CustomDataSource.h" +#include "SignalTypes.h" #include "Timer.h" +#include +#include +#include namespace Aws { namespace IoTFleetWise { -namespace DataManagement -{ -using namespace Aws::IoTFleetWise::Platform::Linux; -using namespace Aws::IoTFleetWise::VehicleNetwork; -using namespace Aws::IoTFleetWise::DataInspection; /** * To implement a custom data source create a new class and inherit from CustomDataSource @@ -92,6 +92,6 @@ class IWaveGpsSource : public CustomDataSource CANRawFrameID mCanRawFrameId{}; char mBuffer[MAX_BYTES_READ_PER_POLL]{}; }; -} // namespace DataManagement + } // namespace IoTFleetWise } // namespace Aws diff --git a/src/datamanagement/datainspection/include/InspectionEventListener.h b/src/InspectionEventListener.h similarity index 98% rename from src/datamanagement/datainspection/include/InspectionEventListener.h rename to src/InspectionEventListener.h index 51936254..bbfccfcc 100644 --- a/src/datamanagement/datainspection/include/InspectionEventListener.h +++ b/src/InspectionEventListener.h @@ -10,8 +10,6 @@ namespace Aws { namespace IoTFleetWise { -namespace DataInspection -{ /** * @brief Metadata representing an event of interest. @@ -66,6 +64,6 @@ class InspectionEventListener */ virtual void onEventOfInterestDetected( const std::vector &eventMetadata ) = 0; }; -} // namespace DataInspection + } // namespace IoTFleetWise } // namespace Aws diff --git a/src/datamanagement/datamanager/src/InspectionMatrixExtractor.cpp b/src/InspectionMatrixExtractor.cpp similarity index 98% rename from src/datamanagement/datamanager/src/InspectionMatrixExtractor.cpp rename to src/InspectionMatrixExtractor.cpp index 8f63cf27..beef2ad8 100644 --- a/src/datamanagement/datamanager/src/InspectionMatrixExtractor.cpp +++ b/src/InspectionMatrixExtractor.cpp @@ -1,10 +1,11 @@ // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 -// Includes -#include "CollectionSchemeManager.h" +#include "CollectionSchemeManager.h" // IWYU pragma: associated +#include "ICollectionScheme.h" #include "LoggingModule.h" -#include "TraceModule.h" +#include +#include #include #include #include @@ -13,8 +14,7 @@ namespace Aws { namespace IoTFleetWise { -namespace DataManagement -{ + void CollectionSchemeManager::addConditionData( const ICollectionSchemePtr &collectionScheme, ConditionWithCollectedData &conditionData ) @@ -163,6 +163,6 @@ CollectionSchemeManager::inspectionMatrixUpdater( const std::shared_ptr &>( &IActiveConditionProcessor::onChangeInspectionMatrix, inspectionMatrix ); } -} // namespace DataManagement + } // namespace IoTFleetWise } // namespace Aws diff --git a/src/executionmanagement/src/IoTFleetWiseConfig.cpp b/src/IoTFleetWiseConfig.cpp similarity index 86% rename from src/executionmanagement/src/IoTFleetWiseConfig.cpp rename to src/IoTFleetWiseConfig.cpp index b39205fd..66c84789 100644 --- a/src/executionmanagement/src/IoTFleetWiseConfig.cpp +++ b/src/IoTFleetWiseConfig.cpp @@ -1,7 +1,6 @@ // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 -// Includes #include "IoTFleetWiseConfig.h" #include @@ -9,8 +8,6 @@ namespace Aws { namespace IoTFleetWise { -namespace ExecutionManagement -{ bool IoTFleetWiseConfig::read( const std::string &filename, Json::Value &config ) @@ -27,6 +24,5 @@ IoTFleetWiseConfig::read( const std::string &filename, Json::Value &config ) return true; } -} // namespace ExecutionManagement } // namespace IoTFleetWise } // namespace Aws diff --git a/src/executionmanagement/include/IoTFleetWiseConfig.h b/src/IoTFleetWiseConfig.h similarity index 86% rename from src/executionmanagement/include/IoTFleetWiseConfig.h rename to src/IoTFleetWiseConfig.h index fcba7f4c..ffebd0b1 100644 --- a/src/executionmanagement/include/IoTFleetWiseConfig.h +++ b/src/IoTFleetWiseConfig.h @@ -3,7 +3,6 @@ #pragma once -// Includes #include #include @@ -11,8 +10,6 @@ namespace Aws { namespace IoTFleetWise { -namespace ExecutionManagement -{ /** @brief FWE Configuration. * Reads FWE's static configuration from a JSON file. */ @@ -25,6 +22,5 @@ class IoTFleetWiseConfig private: }; -} // namespace ExecutionManagement } // namespace IoTFleetWise } // namespace Aws diff --git a/src/executionmanagement/src/IoTFleetWiseEngine.cpp b/src/IoTFleetWiseEngine.cpp similarity index 96% rename from src/executionmanagement/src/IoTFleetWiseEngine.cpp rename to src/IoTFleetWiseEngine.cpp index 5f3eb53c..734faad1 100644 --- a/src/executionmanagement/src/IoTFleetWiseEngine.cpp +++ b/src/IoTFleetWiseEngine.cpp @@ -1,25 +1,40 @@ // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 -// Includes #include "IoTFleetWiseEngine.h" #include "AwsBootstrap.h" +#include "AwsIotConnectivityModule.h" +#include "AwsSDKMemoryManager.h" #include "CollectionInspectionAPITypes.h" +#include "CollectionSchemeManagementListener.h" +#include "DataSenderManager.h" +#include "IActiveConditionProcessor.h" +#include "IActiveDecoderDictionaryListener.h" +#include "ILogger.h" +#include "LogLevel.h" #include "LoggingModule.h" +#include "MqttClientWrapper.h" +#include "SignalTypes.h" #include "TraceModule.h" -#include +#include +#include +#include +#include +#include #include -#include +#include + +#if defined( FWE_FEATURE_IWAVE_GPS ) || defined( FWE_FEATURE_EXTERNAL_GPS ) +#include +#endif +#ifdef FWE_FEATURE_GREENGRASSV2 +#include "AwsGGConnectivityModule.h" +#endif + namespace Aws { namespace IoTFleetWise { -namespace ExecutionManagement -{ -using namespace Aws::IoTFleetWise::DataInspection; -using namespace Aws::IoTFleetWise::Platform::Linux::PersistencyManagement; -using Aws::IoTFleetWise::OffboardConnectivity::CollectionSchemeParams; -using Aws::IoTFleetWise::OffboardConnectivity::ConnectivityError; static const std::string CAN_INTERFACE_TYPE = "canInterface"; static const std::string EXTERNAL_CAN_INTERFACE_TYPE = "externalCanInterface"; @@ -159,7 +174,7 @@ IoTFleetWiseEngine::connect( const Json::Value &config ) // Pass on the AWS SDK Bootstrap handle to the IoTModule. auto bootstrapPtr = AwsBootstrap::getInstance().getClientBootStrap(); std::size_t maxAwsSdkHeapMemoryBytes = 0U; - if ( config["staticConfig"]["internalParameters"]["maximumAwsSdkHeapMemoryBytes"] ) + if ( config["staticConfig"]["internalParameters"].isMember( "maximumAwsSdkHeapMemoryBytes" ) ) { maxAwsSdkHeapMemoryBytes = config["staticConfig"]["internalParameters"]["maximumAwsSdkHeapMemoryBytes"].asUInt(); @@ -220,13 +235,16 @@ IoTFleetWiseEngine::connect( const Json::Value &config ) { rootCA = getFileContents( config["staticConfig"]["mqttConnection"]["rootCAFilename"].asString() ); } + auto createMqttClientWrapper = [bootstrapPtr]() -> std::shared_ptr { + return std::make_shared( std::make_shared( *bootstrapPtr ) ); + }; mConnectivityModule = std::make_shared( privateKey, certificate, rootCA, config["staticConfig"]["mqttConnection"]["endpointUrl"].asString(), config["staticConfig"]["mqttConnection"]["clientId"].asString(), - bootstrapPtr, + createMqttClientWrapper, true ); } @@ -354,15 +372,14 @@ IoTFleetWiseEngine::connect( const Json::Value &config ) /*************************Inspection Engine bootstrap end***********************************/ /*************************DataSender bootstrap begin*********************************/ - mDataSenderManagerWorkerThread = std::make_shared( - mCANIDTranslator, - mConnectivityModule, + mDataSenderManager = std::make_shared( mConnectivityChannelSendVehicleData, mPayloadManager, - config["staticConfig"]["publishToCloudParameters"]["maxPublishMessageCount"].asUInt(), - persistencyUploadRetryIntervalMs ); - if ( ( !mDataSenderManagerWorkerThread->init( mCollectedDataReadyToPublish ) ) || - ( !mDataSenderManagerWorkerThread->start() ) ) + mCANIDTranslator, + config["staticConfig"]["publishToCloudParameters"]["maxPublishMessageCount"].asUInt() ); + mDataSenderManagerWorkerThread = std::make_shared( + mConnectivityModule, mDataSenderManager, persistencyUploadRetryIntervalMs, mCollectedDataReadyToPublish ); + if ( !mDataSenderManagerWorkerThread->start() ) { FWE_LOG_ERROR( "Failed to init and start the Data Sender" ); return false; @@ -417,15 +434,6 @@ IoTFleetWiseEngine::connect( const Json::Value &config ) return false; } - // Make sure the CollectionScheme Manager can notify the Data Sender about the availability of - // a new set of collection CollectionSchemes. - if ( !mCollectionSchemeManagerPtr->subscribeListener( - static_cast( mDataSenderManagerWorkerThread.get() ) ) ) - { - FWE_LOG_ERROR( "Failed register the Data Sender to the CollectionScheme Manager Module" ); - return false; - } - // Allow CollectionSchemeManagement to send checkins through the Schema Object Callback mCollectionSchemeManagerPtr->setSchemaListenerPtr( mSchemaPtr ); @@ -827,7 +835,7 @@ IoTFleetWiseEngine::doWork( void *data ) } else { - engine->mWait.wait( Platform::Linux::Signal::WaitWithPredicate ); + engine->mWait.wait( Signal::WaitWithPredicate ); auto elapsedTimeMs = engine->mTimer.getElapsedMs().count(); FWE_LOG_TRACE( "Event arrived. Time elapsed waiting for the event: " + std::to_string( elapsedTimeMs ) + " ms" ); @@ -950,6 +958,5 @@ IoTFleetWiseEngine::getStatusSummary() return status; } -} // namespace ExecutionManagement } // namespace IoTFleetWise } // namespace Aws diff --git a/src/executionmanagement/include/IoTFleetWiseEngine.h b/src/IoTFleetWiseEngine.h similarity index 89% rename from src/executionmanagement/include/IoTFleetWiseEngine.h rename to src/IoTFleetWiseEngine.h index 2e5a75b5..43544f31 100644 --- a/src/executionmanagement/include/IoTFleetWiseEngine.h +++ b/src/IoTFleetWiseEngine.h @@ -3,57 +3,52 @@ #pragma once -// Includes -#ifdef FWE_FEATURE_AAOS_VHAL -#include "AaosVhalSource.h" -#endif -#ifdef FWE_FEATURE_GREENGRASSV2 -#include "AwsGGConnectivityModule.h" -#endif -#include "AwsIotChannel.h" -#include "AwsIotConnectivityModule.h" -#include "AwsSDKMemoryManager.h" +#include "CANDataConsumer.h" #include "CANDataSource.h" #include "CANInterfaceIDTranslator.h" #include "CacheAndPersist.h" +#include "Clock.h" #include "ClockHandler.h" +#include "CollectionInspectionAPITypes.h" #include "CollectionInspectionWorkerThread.h" #include "CollectionSchemeManager.h" +#include "DataSenderManager.h" #include "DataSenderManagerWorkerThread.h" -#ifdef FWE_FEATURE_EXTERNAL_GPS -#include "ExternalGpsSource.h" -#endif #include "ExternalCANDataSource.h" #include "IConnectivityChannel.h" #include "IConnectivityModule.h" -#ifdef FWE_FEATURE_IWAVE_GPS -#include "IWaveGpsSource.h" -#endif +#include "OBDDataTypes.h" #include "OBDOverCANModule.h" +#include "PayloadManager.h" #include "RemoteProfiler.h" #include "Schema.h" #include "Signal.h" #include "Thread.h" +#include "TimeTypes.h" #include "Timer.h" #include +#include #include -#include +#include #include +#include +#include + +#ifdef FWE_FEATURE_AAOS_VHAL +#include "AaosVhalSource.h" +#include +#endif +#ifdef FWE_FEATURE_EXTERNAL_GPS +#include "ExternalGpsSource.h" +#endif +#ifdef FWE_FEATURE_IWAVE_GPS +#include "IWaveGpsSource.h" +#endif namespace Aws { namespace IoTFleetWise { -namespace ExecutionManagement -{ -using namespace Aws::IoTFleetWise::DataManagement; -using namespace Aws::IoTFleetWise::DataInspection; -using namespace Aws::IoTFleetWise::DataSender; -using namespace Aws::IoTFleetWise::Platform::Linux; -using namespace Aws::IoTFleetWise::Platform::Linux::PersistencyManagement; -using namespace Aws::IoTFleetWise::VehicleNetwork; -using namespace Aws::IoTFleetWise::OffboardConnectivity; -using namespace Aws::IoTFleetWise::OffboardConnectivityAwsIot; /** * @brief Main AWS IoT FleetWise Bootstrap module. @@ -156,7 +151,7 @@ class IoTFleetWiseEngine std::atomic mShouldStop{ false }; mutable std::mutex mThreadMutex; - Platform::Linux::Signal mWait; + Signal mWait; Timer mTimer; Timer mPrintMetricsCyclicTimer; @@ -182,6 +177,7 @@ class IoTFleetWiseEngine std::shared_ptr mCollectionInspectionWorkerThread; + std::shared_ptr mDataSenderManager; std::shared_ptr mDataSenderManagerWorkerThread; std::unique_ptr mRemoteProfiler; @@ -198,6 +194,6 @@ class IoTFleetWiseEngine std::shared_ptr mAaosVhalSource; #endif }; -} // namespace ExecutionManagement + } // namespace IoTFleetWise } // namespace Aws diff --git a/src/executionmanagement/src/IoTFleetWiseVersion.cpp.in b/src/IoTFleetWiseVersion.cpp.in similarity index 100% rename from src/executionmanagement/src/IoTFleetWiseVersion.cpp.in rename to src/IoTFleetWiseVersion.cpp.in diff --git a/src/executionmanagement/include/IoTFleetWiseVersion.h b/src/IoTFleetWiseVersion.h similarity index 100% rename from src/executionmanagement/include/IoTFleetWiseVersion.h rename to src/IoTFleetWiseVersion.h diff --git a/src/platform/linux/threadingmanagement/include/Listener.h b/src/Listener.h similarity index 98% rename from src/platform/linux/threadingmanagement/include/Listener.h rename to src/Listener.h index 5255bb0d..42753d92 100644 --- a/src/platform/linux/threadingmanagement/include/Listener.h +++ b/src/Listener.h @@ -3,18 +3,15 @@ #pragma once -// Includes #include #include #include + namespace Aws { namespace IoTFleetWise { -namespace Platform -{ -namespace Linux -{ + /** * @brief Template utility implementing a thread safe Subject/Observer design pattern. */ @@ -191,7 +188,5 @@ class ThreadListeners } }; -} // namespace Linux -} // namespace Platform } // namespace IoTFleetWise } // namespace Aws diff --git a/src/platform/linux/logmanagement/include/LogLevel.h b/src/LogLevel.h similarity index 61% rename from src/platform/linux/logmanagement/include/LogLevel.h rename to src/LogLevel.h index 6d6c8b1e..b7a9da94 100644 --- a/src/platform/linux/logmanagement/include/LogLevel.h +++ b/src/LogLevel.h @@ -2,16 +2,12 @@ // SPDX-License-Identifier: Apache-2.0 #pragma once -// Includes #include namespace Aws { namespace IoTFleetWise { -namespace Platform -{ -namespace Linux -{ + /** * @brief Log levels. */ @@ -29,23 +25,23 @@ stringToLogLevel( const std::string level, LogLevel &outLogLevel ) { if ( level == "Info" ) { - outLogLevel = Aws::IoTFleetWise::Platform::Linux::LogLevel::Info; + outLogLevel = LogLevel::Info; } else if ( level == "Error" ) { - outLogLevel = Aws::IoTFleetWise::Platform::Linux::LogLevel::Error; + outLogLevel = LogLevel::Error; } else if ( level == "Warning" ) { - outLogLevel = Aws::IoTFleetWise::Platform::Linux::LogLevel::Warning; + outLogLevel = LogLevel::Warning; } else if ( level == "Trace" ) { - outLogLevel = Aws::IoTFleetWise::Platform::Linux::LogLevel::Trace; + outLogLevel = LogLevel::Trace; } else if ( level == "Off" ) { - outLogLevel = Aws::IoTFleetWise::Platform::Linux::LogLevel::Off; + outLogLevel = LogLevel::Off; } else { @@ -55,7 +51,6 @@ stringToLogLevel( const std::string level, LogLevel &outLogLevel ) } extern LogLevel gSystemWideLogLevel; -} // namespace Linux -} // namespace Platform + } // namespace IoTFleetWise } // namespace Aws diff --git a/src/platform/linux/logmanagement/src/LoggingModule.cpp b/src/LoggingModule.cpp similarity index 58% rename from src/platform/linux/logmanagement/src/LoggingModule.cpp rename to src/LoggingModule.cpp index de00e9ab..411a4e83 100644 --- a/src/platform/linux/logmanagement/src/LoggingModule.cpp +++ b/src/LoggingModule.cpp @@ -1,10 +1,11 @@ // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 -#if defined( IOTFLEETWISE_LINUX ) -// Includes - #include "LoggingModule.h" +#include "ConsoleLogger.h" +#include +#include +#include #include #include @@ -12,10 +13,6 @@ namespace Aws { namespace IoTFleetWise { -namespace Platform -{ -namespace Linux -{ void LoggingModule::log( LogLevel level, @@ -49,8 +46,34 @@ getStringFromBytes( const std::vector &inputBytes ) return stream_bytes.str(); } -} // namespace Linux -} // namespace Platform +std::string +getErrnoString() +{ + // coverity[autosar_cpp14_m19_3_1_violation] + // coverity[misra_cpp_2008_rule_19_3_1_violation] using errno for logging purposes only + int lastError = errno; + + char buf[256]; + auto result = strerror_r( lastError, &buf[0], sizeof( buf ) ); + +#if defined _GNU_SOURCE && !defined __ANDROID__ + // On Linux, there is an issue with libstdc++ that doesn't allow us to use the POSIX compliant + // strerror_r function (which would require us to define _XOPEN_SOURCE, but since _GNU_SOURCE is + // always defined, we always get the GNU version): + // https://stackoverflow.com/questions/11670581/why-is-gnu-source-defined-by-default-and-how-to-turn-it-off + if ( result != nullptr ) + { + return std::string( result ); + } +#else + if ( result == 0 ) + { + return std::string( &buf[0] ); + } +#endif + FWE_LOG_ERROR( "Could not get string for errno: " + std::to_string( lastError ) ); + return std::to_string( lastError ); +} + } // namespace IoTFleetWise } // namespace Aws -#endif // IOTFLEETWISE_LINUX diff --git a/src/platform/linux/logmanagement/include/LoggingModule.h b/src/LoggingModule.h similarity index 96% rename from src/platform/linux/logmanagement/include/LoggingModule.h rename to src/LoggingModule.h index f22692e7..257be57c 100644 --- a/src/platform/linux/logmanagement/include/LoggingModule.h +++ b/src/LoggingModule.h @@ -3,64 +3,15 @@ #pragma once -// Includes - -#include "ConsoleLogger.h" -#include +#include "LogLevel.h" +#include +#include #include -/** - * @brief Log INFO function - * @param logEntry the message to be logged - */ -#define FWE_LOG_INFO( logEntry ) \ - { \ - constexpr const char *shortFilename = getShortFilename( __FILE__ ); \ - LoggingModule::log( \ - LogLevel::Info, shortFilename, static_cast( __LINE__ ), __FUNCTION__, ( logEntry ) ); \ - } - -/** - * @brief Log WARN function - * @param logEntry the message to be logged - */ -#define FWE_LOG_WARN( logEntry ) \ - { \ - constexpr const char *shortFilename = getShortFilename( __FILE__ ); \ - LoggingModule::log( \ - LogLevel::Warning, shortFilename, static_cast( __LINE__ ), __FUNCTION__, ( logEntry ) ); \ - } - -/** - * @brief Log ERROR function - * @param logEntry the message to be logged - */ -#define FWE_LOG_ERROR( logEntry ) \ - { \ - constexpr const char *shortFilename = getShortFilename( __FILE__ ); \ - LoggingModule::log( \ - LogLevel::Error, shortFilename, static_cast( __LINE__ ), __FUNCTION__, ( logEntry ) ); \ - } - -/** - * @brief Log TRACE function - * @param logEntry the message to be logged - */ -#define FWE_LOG_TRACE( logEntry ) \ - { \ - constexpr const char *shortFilename = getShortFilename( __FILE__ ); \ - LoggingModule::log( \ - LogLevel::Trace, shortFilename, static_cast( __LINE__ ), __FUNCTION__, ( logEntry ) ); \ - } - namespace Aws { namespace IoTFleetWise { -namespace Platform -{ -namespace Linux -{ /** * @brief Recursive function to extract short filename from __FILE__ at compile time @@ -130,7 +81,55 @@ class LoggingModule */ std::string getStringFromBytes( const std::vector &inputBytes ); -} // namespace Linux -} // namespace Platform +/** + * @brief Converts errno code to a string in a thread-safe way + * @return string the error description + */ +std::string getErrnoString(); + } // namespace IoTFleetWise } // namespace Aws + +/** + * @brief Log INFO function + * @param logEntry the message to be logged + */ +#define FWE_LOG_INFO( logEntry ) \ + { \ + constexpr const char *shortFilename = getShortFilename( __FILE__ ); \ + LoggingModule::log( \ + LogLevel::Info, shortFilename, static_cast( __LINE__ ), __FUNCTION__, ( logEntry ) ); \ + } + +/** + * @brief Log WARN function + * @param logEntry the message to be logged + */ +#define FWE_LOG_WARN( logEntry ) \ + { \ + constexpr const char *shortFilename = getShortFilename( __FILE__ ); \ + LoggingModule::log( \ + LogLevel::Warning, shortFilename, static_cast( __LINE__ ), __FUNCTION__, ( logEntry ) ); \ + } + +/** + * @brief Log ERROR function + * @param logEntry the message to be logged + */ +#define FWE_LOG_ERROR( logEntry ) \ + { \ + constexpr const char *shortFilename = getShortFilename( __FILE__ ); \ + LoggingModule::log( \ + LogLevel::Error, shortFilename, static_cast( __LINE__ ), __FUNCTION__, ( logEntry ) ); \ + } + +/** + * @brief Log TRACE function + * @param logEntry the message to be logged + */ +#define FWE_LOG_TRACE( logEntry ) \ + { \ + constexpr const char *shortFilename = getShortFilename( __FILE__ ); \ + LoggingModule::log( \ + LogLevel::Trace, shortFilename, static_cast( __LINE__ ), __FUNCTION__, ( logEntry ) ); \ + } diff --git a/src/platform/linux/resourcemanagement/src/MemoryUsageInfo.cpp b/src/MemoryUsageInfo.cpp similarity index 91% rename from src/platform/linux/resourcemanagement/src/MemoryUsageInfo.cpp rename to src/MemoryUsageInfo.cpp index e39b0015..8f603e90 100644 --- a/src/platform/linux/resourcemanagement/src/MemoryUsageInfo.cpp +++ b/src/MemoryUsageInfo.cpp @@ -1,11 +1,7 @@ // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 -#if defined( IOTFLEETWISE_LINUX ) -// Includes - #include "MemoryUsageInfo.h" -#include #include #include #include @@ -14,10 +10,6 @@ namespace Aws { namespace IoTFleetWise { -namespace Platform -{ -namespace Linux -{ bool MemoryUsageInfo::reportMemoryUsageInfo() @@ -65,8 +57,6 @@ MemoryUsageInfo::reportMemoryUsageInfo() return true; } } -} // namespace Linux -} // namespace Platform + } // namespace IoTFleetWise } // namespace Aws -#endif // IOTFLEETWISE_LINUX diff --git a/src/platform/linux/resourcemanagement/include/MemoryUsageInfo.h b/src/MemoryUsageInfo.h similarity index 90% rename from src/platform/linux/resourcemanagement/include/MemoryUsageInfo.h rename to src/MemoryUsageInfo.h index 956760ed..6b0c81ed 100644 --- a/src/platform/linux/resourcemanagement/include/MemoryUsageInfo.h +++ b/src/MemoryUsageInfo.h @@ -3,19 +3,12 @@ #pragma once -#if defined( IOTFLEETWISE_LINUX ) -// Includes #include -#include namespace Aws { namespace IoTFleetWise { -namespace Platform -{ -namespace Linux -{ /** * @brief Utility class to track and report Memory Consumption. @@ -77,8 +70,5 @@ MemoryUsageInfo::getVirtualMemorySize() const return mVirtualMemorySize; } -} // namespace Linux -} // namespace Platform } // namespace IoTFleetWise } // namespace Aws -#endif // IOTFLEETWISE_LINUX diff --git a/src/datamanagement/types/include/MessageTypes.h b/src/MessageTypes.h similarity index 96% rename from src/datamanagement/types/include/MessageTypes.h rename to src/MessageTypes.h index 652c4ad1..9206b46f 100644 --- a/src/datamanagement/types/include/MessageTypes.h +++ b/src/MessageTypes.h @@ -11,8 +11,7 @@ namespace Aws { namespace IoTFleetWise { -namespace DataManagement -{ + static constexpr SignalID INVALID_CAN_FRAME_ID = 0xFFFFFFFF; /** @@ -70,6 +69,5 @@ struct CANMessageFormat } }; -} // namespace DataManagement } // namespace IoTFleetWise } // namespace Aws diff --git a/src/MqttClientWrapper.h b/src/MqttClientWrapper.h new file mode 100644 index 00000000..7f081868 --- /dev/null +++ b/src/MqttClientWrapper.h @@ -0,0 +1,57 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#include "MqttConnectionWrapper.h" +#include + +namespace Aws +{ +namespace IoTFleetWise +{ + +/** + * @brief A wrapper around MqttClient so that we can provide different implementations. + * + * The original MqttClient can't be inherited from because it only declares private constructors. + **/ +class MqttClientWrapper +{ +public: + /** + * @param mqttClient the MqttClient instance to be wrapped + */ + MqttClientWrapper( std::shared_ptr mqttClient ) + : mMqttClient( std::move( mqttClient ) ){}; + virtual ~MqttClientWrapper() = default; + + MqttClientWrapper() = delete; + MqttClientWrapper( const MqttClientWrapper & ) = delete; + MqttClientWrapper &operator=( const MqttClientWrapper & ) = delete; + MqttClientWrapper( MqttClientWrapper && ) = delete; + MqttClientWrapper &operator=( MqttClientWrapper && ) = delete; + + virtual std::shared_ptr + NewConnection( const Aws::Iot::MqttClientConnectionConfig &config ) noexcept + { + return std::make_shared( mMqttClient->NewConnection( config ) ); + } + + virtual int + LastError() const noexcept + { + return mMqttClient->LastError(); + } + + virtual explicit operator bool() const noexcept + { + return *mMqttClient ? true : false; + } + +private: + std::shared_ptr mMqttClient; +}; + +} // namespace IoTFleetWise +} // namespace Aws diff --git a/src/MqttConnectionWrapper.h b/src/MqttConnectionWrapper.h new file mode 100644 index 00000000..60288e2c --- /dev/null +++ b/src/MqttConnectionWrapper.h @@ -0,0 +1,193 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#include +#include + +namespace Aws +{ +namespace IoTFleetWise +{ + +/** + * @brief A wrapper around MqttConnection so that we can provide different implementations. + * + * The original MqttConnection can't be inherited from because it only declares private constructors. + **/ +class MqttConnectionWrapper +{ +public: + /** + * @param mqttConnection the MqttConnection instance to be wrapped + */ + MqttConnectionWrapper( std::shared_ptr mqttConnection ) + : mMqttConnection( std::move( mqttConnection ) ){}; + virtual ~MqttConnectionWrapper() = default; + + MqttConnectionWrapper() = delete; + MqttConnectionWrapper( const MqttConnectionWrapper & ) = delete; + MqttConnectionWrapper &operator=( const MqttConnectionWrapper & ) = delete; + MqttConnectionWrapper( MqttConnectionWrapper && ) = delete; + MqttConnectionWrapper &operator=( MqttConnectionWrapper && ) = delete; + + using OnConnectionInterruptedHandler = std::function; + using OnConnectionResumedHandler = std::function; + using OnConnectionCompletedHandler = std::function; + using OnSubAckHandler = std::function; + using OnDisconnectHandler = std::function; + using OnMessageReceivedHandler = std::function; + using OnOperationCompleteHandler = + std::function; + + virtual explicit operator bool() const noexcept + { + return *mMqttConnection ? true : false; + } + virtual int + LastError() const noexcept + { + return mMqttConnection->LastError(); + } + virtual bool + Connect( const char *clientId, + bool cleanSession, + uint16_t keepAliveTimeSecs = 0, + uint32_t pingTimeoutMs = 0 ) noexcept + { + return mMqttConnection->Connect( clientId, cleanSession, keepAliveTimeSecs, pingTimeoutMs ); + } + virtual bool + Disconnect() noexcept + { + return mMqttConnection->Disconnect(); + } + virtual uint16_t + Subscribe( const char *topicFilter, + Aws::Crt::Mqtt::QOS qos, + OnMessageReceivedHandler &&onMessage, + OnSubAckHandler &&onSubAck ) noexcept + { + return mMqttConnection->Subscribe( + topicFilter, + qos, + [this, onMessageCallback = std::move( onMessage )]( Aws::Crt::Mqtt::MqttConnection &connection, + const Aws::Crt::String &topic, + const Aws::Crt::ByteBuf &payload, + bool dup, + Aws::Crt::Mqtt::QOS qosCallback, + bool retain ) { + static_cast( connection ); + onMessageCallback( *this, topic, payload, dup, qosCallback, retain ); + }, + [this, onSubAckCallback = std::move( onSubAck )]( Aws::Crt::Mqtt::MqttConnection &connection, + uint16_t packetId, + const Aws::Crt::String &topic, + Aws::Crt::Mqtt::QOS qosCallback, + int errorCode ) { + static_cast( connection ); + onSubAckCallback( *this, packetId, topic, qosCallback, errorCode ); + } ); + } + virtual bool + SetOnMessageHandler( OnMessageReceivedHandler &&onMessage ) noexcept + { + return mMqttConnection->SetOnMessageHandler( + [this, onMessageCallback = std::move( onMessage )]( Aws::Crt::Mqtt::MqttConnection &connection, + const Aws::Crt::String &topic, + const Aws::Crt::ByteBuf &payload, + bool dup, + Aws::Crt::Mqtt::QOS qos, + bool retain ) { + static_cast( connection ); + onMessageCallback( *this, topic, payload, dup, qos, retain ); + } ); + } + virtual uint16_t + Unsubscribe( const char *topicFilter, OnOperationCompleteHandler &&onOpComplete ) noexcept + { + return mMqttConnection->Unsubscribe( + topicFilter, + [this, onOpCompleteCallback = std::move( onOpComplete )]( + Aws::Crt::Mqtt::MqttConnection &connection, uint16_t packetId, int errorCode ) { + static_cast( connection ); + onOpCompleteCallback( *this, packetId, errorCode ); + } ); + } + virtual uint16_t + Publish( const char *topic, + Aws::Crt::Mqtt::QOS qos, + bool retain, + const Aws::Crt::ByteBuf &payload, + OnOperationCompleteHandler &&onOpComplete ) noexcept + { + return mMqttConnection->Publish( + topic, + qos, + retain, + payload, + [this, onOpCompleteCallback = std::move( onOpComplete )]( + Aws::Crt::Mqtt::MqttConnection &connection, uint16_t packetId, int errorCode ) { + static_cast( connection ); + onOpCompleteCallback( *this, packetId, errorCode ); + } ); + } + + virtual void + SetOnConnectionInterrupted( OnConnectionInterruptedHandler onConnectionInterrupted ) + { + mMqttConnection->OnConnectionInterrupted = + [this, onConnectionInterrupted]( Aws::Crt::Mqtt::MqttConnection &connection, int error ) { + static_cast( connection ); + onConnectionInterrupted( *this, error ); + }; + } + virtual void + SetOnConnectionResumed( OnConnectionResumedHandler onConnectionResumed ) + { + mMqttConnection->OnConnectionResumed = [this, onConnectionResumed]( Aws::Crt::Mqtt::MqttConnection &connection, + Aws::Crt::Mqtt::ReturnCode connectCode, + bool sessionPresent ) { + static_cast( connection ); + onConnectionResumed( *this, connectCode, sessionPresent ); + }; + } + virtual void + SetOnConnectionCompleted( OnConnectionCompletedHandler onConnectionCompleted ) + { + mMqttConnection->OnConnectionCompleted = [this, + onConnectionCompleted]( Aws::Crt::Mqtt::MqttConnection &connection, + int errorCode, + Aws::Crt::Mqtt::ReturnCode returnCode, + bool sessionPresent ) { + static_cast( connection ); + onConnectionCompleted( *this, errorCode, returnCode, sessionPresent ); + }; + } + virtual void + SetOnDisconnect( OnDisconnectHandler onDisconnect ) + { + mMqttConnection->OnDisconnect = [this, onDisconnect]( Aws::Crt::Mqtt::MqttConnection &connection ) { + static_cast( connection ); + onDisconnect( *this ); + }; + } + +private: + std::shared_ptr mMqttConnection; +}; + +} // namespace IoTFleetWise +} // namespace Aws diff --git a/src/datamanagement/datadecoding/src/OBDDataDecoder.cpp b/src/OBDDataDecoder.cpp similarity index 99% rename from src/datamanagement/datadecoding/src/OBDDataDecoder.cpp rename to src/OBDDataDecoder.cpp index 5d4e302a..eece7b52 100644 --- a/src/datamanagement/datadecoding/src/OBDDataDecoder.cpp +++ b/src/OBDDataDecoder.cpp @@ -1,15 +1,19 @@ // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 -// Includes #include "OBDDataDecoder.h" #include "EnumUtility.h" #include "LoggingModule.h" #include "TraceModule.h" #include +#include +#include #include +#include #include +#include #include + constexpr int POSITIVE_ECU_RESPONSE_BASE = 0x40; #define IS_BIT_SET( var, pos ) ( ( ( var ) & static_cast( 1U << ( pos ) ) ) != 0U ) @@ -17,8 +21,6 @@ namespace Aws { namespace IoTFleetWise { -namespace DataManagement -{ OBDDataDecoder::OBDDataDecoder( std::shared_ptr &decoderDictionary ) : mDecoderDictionary{ decoderDictionary } @@ -433,6 +435,5 @@ OBDDataDecoder::isFormulaValid( PID pid, const CANSignalFormat &formula ) return isValid; } -} // namespace DataManagement } // namespace IoTFleetWise } // namespace Aws diff --git a/src/datamanagement/datadecoding/include/OBDDataDecoder.h b/src/OBDDataDecoder.h similarity index 97% rename from src/datamanagement/datadecoding/include/OBDDataDecoder.h rename to src/OBDDataDecoder.h index 8d2ad43c..6a48f983 100644 --- a/src/datamanagement/datadecoding/include/OBDDataDecoder.h +++ b/src/OBDDataDecoder.h @@ -3,21 +3,23 @@ #pragma once -// Includes +#include "Clock.h" #include "ClockHandler.h" -#include "IDecoderDictionary.h" +#include "MessageTypes.h" #include "OBDDataTypes.h" +#include "SignalTypes.h" #include "Timer.h" +#include +#include #include +#include +#include #include namespace Aws { namespace IoTFleetWise { -namespace DataManagement -{ -using namespace Aws::IoTFleetWise::Platform::Linux; /** * @brief decoder dictionary to be used to decode OBD PID message to signals. @@ -131,6 +133,5 @@ class OBDDataDecoder bool isPIDResponseValid( const std::vector &pids, const std::vector &ecuResponse ); }; -} // namespace DataManagement } // namespace IoTFleetWise } // namespace Aws diff --git a/src/datamanagement/types/include/OBDDataTypes.h b/src/OBDDataTypes.h similarity index 96% rename from src/datamanagement/types/include/OBDDataTypes.h rename to src/OBDDataTypes.h index 80707a04..31e417ba 100644 --- a/src/datamanagement/types/include/OBDDataTypes.h +++ b/src/OBDDataTypes.h @@ -3,15 +3,15 @@ #pragma once -// Includes #include "EnumUtility.h" #include "TimeTypes.h" -#include "datatypes/VehicleDataSourceTypes.h" +#include "VehicleDataSourceTypes.h" #include #include #include #include #include + // Default Keep Alive Interval. #define OBD_KEEP_ALIVE_SECONDS 2 @@ -19,11 +19,6 @@ namespace Aws { namespace IoTFleetWise { -namespace DataManagement -{ -using namespace Aws::IoTFleetWise::VehicleNetwork; -using namespace Aws::IoTFleetWise::Platform::Linux; -using namespace Aws::IoTFleetWise::Platform::Utility; union OBDValue { double doubleVal; @@ -255,6 +250,5 @@ enum class DTCDomains // VIN Request static constexpr OBDRequest vehicleIdentificationNumberRequest = { static_cast( 0x09 ), static_cast( 0x02 ) }; -} // namespace DataManagement } // namespace IoTFleetWise } // namespace Aws diff --git a/src/datamanagement/datainspection/src/diag/OBDOverCANECU.cpp b/src/OBDOverCANECU.cpp similarity index 98% rename from src/datamanagement/datainspection/src/diag/OBDOverCANECU.cpp rename to src/OBDOverCANECU.cpp index 89916f77..6c1d9295 100644 --- a/src/datamanagement/datainspection/src/diag/OBDOverCANECU.cpp +++ b/src/OBDOverCANECU.cpp @@ -1,19 +1,25 @@ // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 -// Includes #include "OBDOverCANECU.h" +#include "EnumUtility.h" +#include "ISOTPOverCANOptions.h" #include "LoggingModule.h" +#include "SignalTypes.h" #include "TraceModule.h" +#include +#include +#include +#include +#include #include #include +#include namespace Aws { namespace IoTFleetWise { -namespace DataInspection -{ // NOLINT below due to C++17 warning of redundant declarations that are required to maintain C++14 compatibility constexpr size_t OBDOverCANECU::MAX_PID_RANGE; // NOLINT @@ -388,6 +394,5 @@ OBDOverCANECU::updatePIDRequestList( const SID sid, } } -} // namespace DataInspection } // namespace IoTFleetWise } // namespace Aws diff --git a/src/datamanagement/datainspection/include/OBDOverCANECU.h b/src/OBDOverCANECU.h similarity index 95% rename from src/datamanagement/datainspection/include/OBDOverCANECU.h rename to src/OBDOverCANECU.h index 33028ca8..1612f456 100644 --- a/src/datamanagement/datainspection/include/OBDOverCANECU.h +++ b/src/OBDOverCANECU.h @@ -3,20 +3,26 @@ #pragma once -// Includes +#include "Clock.h" +#include "ClockHandler.h" #include "CollectionInspectionAPITypes.h" +#include "ISOTPOverCANSenderReceiver.h" #include "OBDDataDecoder.h" -#include "businterfaces/ISOTPOverCANSenderReceiver.h" +#include "OBDDataTypes.h" +#include "TimeTypes.h" +#include +#include +#include +#include +#include +#include +#include namespace Aws { namespace IoTFleetWise { -namespace DataInspection -{ -using namespace Aws::IoTFleetWise::Platform::Linux; -using namespace Aws::IoTFleetWise::VehicleNetwork; -using namespace Aws::IoTFleetWise::DataManagement; + /** * @brief This class handles sending OBD PID / DTC requests to an ECU and processing corresponding responses. */ @@ -171,6 +177,6 @@ class OBDOverCANECU // Per J1979, maximum 6 PIDs can be requested in one message static constexpr size_t MAX_PID_RANGE = 6U; }; -} // namespace DataInspection + } // namespace IoTFleetWise } // namespace Aws diff --git a/src/datamanagement/datainspection/src/diag/OBDOverCANModule.cpp b/src/OBDOverCANModule.cpp similarity index 97% rename from src/datamanagement/datainspection/src/diag/OBDOverCANModule.cpp rename to src/OBDOverCANModule.cpp index f512dda2..43ef56e2 100644 --- a/src/datamanagement/datainspection/src/diag/OBDOverCANModule.cpp +++ b/src/OBDOverCANModule.cpp @@ -1,30 +1,31 @@ // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 -// Includes #include "OBDOverCANModule.h" -#include "EnumUtility.h" +#include "ISOTPOverCANOptions.h" #include "LoggingModule.h" -#include "TraceModule.h" -#include "datatypes/ISOTPOverCANOptions.h" +#include "MessageTypes.h" +#include "SignalTypes.h" #include +#include #include -#include -#include +#include +#include +#include #include -#include #include #include +#include +#include #include #include +#include +#include namespace Aws { namespace IoTFleetWise { -namespace DataInspection -{ -using namespace Aws::IoTFleetWise::VehicleNetwork; // NOLINT below due to C++17 warning of redundant declarations that are required to maintain C++14 compatibility constexpr int OBDOverCANModule::SLEEP_TIME_SECS; // NOLINT @@ -137,7 +138,7 @@ OBDOverCANModule::doWork( void *data ) { FWE_LOG_TRACE( "No valid decoding dictionary available and DTC requests disabled, Module Thread going to sleep " ); - obdModule->mDataAvailableWait.wait( Platform::Linux::Signal::WaitWithPredicate ); + obdModule->mDataAvailableWait.wait( Signal::WaitWithPredicate ); } // Now we will determine whether the ECUs are using extended IDs bool isExtendedID = false; @@ -325,7 +326,7 @@ OBDOverCANModule::autoDetectECUs( bool isExtendedID, std::vector &canI int rawSocket = socket( PF_CAN, SOCK_RAW, CAN_RAW ); if ( rawSocket < 0 ) { - FWE_LOG_ERROR( "Failed to create socket" ); + FWE_LOG_ERROR( "Failed to create socket: " + getErrnoString() ); return false; } // Set the IF name @@ -333,7 +334,7 @@ OBDOverCANModule::autoDetectECUs( bool isExtendedID, std::vector &canI if ( ioctl( rawSocket, SIOCGIFINDEX, &interfaceRequest ) != 0 ) { close( rawSocket ); - FWE_LOG_ERROR( "CAN interface is not accessible" ); + FWE_LOG_ERROR( "CAN interface is not accessible: " + getErrnoString() ); return false; } @@ -344,7 +345,7 @@ OBDOverCANModule::autoDetectECUs( bool isExtendedID, std::vector &canI if ( bind( rawSocket, reinterpret_cast( &interfaceAddress ), sizeof( interfaceAddress ) ) < 0 ) { close( rawSocket ); - FWE_LOG_ERROR( "Failed to bind" ); + FWE_LOG_ERROR( "Failed to bind socket: " + getErrnoString() ); return false; } // Set frame can_id and flags @@ -441,7 +442,8 @@ OBDOverCANModule::openISOTPBroadcastSocket( bool isExtendedID ) int broadcastSocket = socket( PF_CAN, SOCK_DGRAM, CAN_ISOTP ); if ( broadcastSocket < 0 ) { - FWE_LOG_ERROR( "Failed to create the ISOTP broadcast socket to IF: " + mGatewayCanInterfaceName ); + FWE_LOG_ERROR( "Failed to create the ISOTP broadcast socket to IF: " + mGatewayCanInterfaceName + + " Error: " + getErrnoString() ); return -1; } @@ -460,7 +462,8 @@ OBDOverCANModule::openISOTPBroadcastSocket( bool isExtendedID ) // NOLINTNEXTLINE(cppcoreguidelines-pro-type-cstyle-cast) if ( bind( broadcastSocket, (struct sockaddr *)&interfaceAddress, sizeof( interfaceAddress ) ) < 0 ) { - FWE_LOG_ERROR( "Failed to bind the ISOTP Socket to IF: " + mGatewayCanInterfaceName ); + FWE_LOG_ERROR( "Failed to bind the ISOTP Socket to IF: " + mGatewayCanInterfaceName + + " Error: " + getErrnoString() ); close( broadcastSocket ); return -1; } @@ -687,6 +690,5 @@ OBDOverCANModule::onChangeOfActiveDictionary( ConstDecoderDictionaryConstPtr &di FWE_LOG_INFO( "Decoder Manifest Updated" ); } -} // namespace DataInspection } // namespace IoTFleetWise } // namespace Aws diff --git a/src/datamanagement/datainspection/include/OBDOverCANModule.h b/src/OBDOverCANModule.h similarity index 96% rename from src/datamanagement/datainspection/include/OBDOverCANModule.h rename to src/OBDOverCANModule.h index 5d4d3172..f9b05b26 100644 --- a/src/datamanagement/datainspection/include/OBDOverCANModule.h +++ b/src/OBDOverCANModule.h @@ -3,28 +3,33 @@ #pragma once -// Includes +#include "Clock.h" #include "ClockHandler.h" #include "CollectionInspectionAPITypes.h" #include "IActiveConditionProcessor.h" #include "IActiveDecoderDictionaryListener.h" +#include "IDecoderDictionary.h" #include "OBDDataDecoder.h" +#include "OBDDataTypes.h" #include "OBDOverCANECU.h" #include "Signal.h" #include "Thread.h" #include "Timer.h" -#include -#include +#include "VehicleDataSourceTypes.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include namespace Aws { namespace IoTFleetWise { -namespace DataInspection -{ -using namespace Aws::IoTFleetWise::Platform::Linux; -using namespace Aws::IoTFleetWise::VehicleNetwork; -using namespace Aws::IoTFleetWise::DataManagement; // ECU IDs enum class ECUID @@ -199,9 +204,9 @@ class OBDOverCANModule : public IActiveDecoderDictionaryListener, public IActive mutable std::mutex mThreadMutex; std::shared_ptr mClock = ClockHandler::getClock(); // Stop signal - Platform::Linux::Signal mWait; + Signal mWait; // Decoder Manifest and campaigns availability Signal - Platform::Linux::Signal mDataAvailableWait; + Signal mDataAvailableWait; // Signal Buffer shared pointer SignalBufferPtr mSignalBufferPtr; @@ -233,6 +238,6 @@ class OBDOverCANModule : public IActiveDecoderDictionaryListener, public IActive static constexpr uint32_t MASKING_TEMPLATE_TX_ID = 0x18DA00F1; // All 29-bit tx id has the same bytes static constexpr uint32_t MASKING_REMOVE_BYTE = 0x8; }; -} // namespace DataInspection + } // namespace IoTFleetWise } // namespace Aws diff --git a/src/offboardconnectivity/implementation/aws/iotcpp/src/PayloadManager.cpp b/src/PayloadManager.cpp similarity index 88% rename from src/offboardconnectivity/implementation/aws/iotcpp/src/PayloadManager.cpp rename to src/PayloadManager.cpp index 7b89f526..6a38007b 100644 --- a/src/offboardconnectivity/implementation/aws/iotcpp/src/PayloadManager.cpp +++ b/src/PayloadManager.cpp @@ -4,12 +4,14 @@ #include "PayloadManager.h" #include "LoggingModule.h" #include "TraceModule.h" -#include +#include #include -#include +#include -using namespace Aws::IoTFleetWise::OffboardConnectivityAwsIot; -using namespace Aws::IoTFleetWise::Platform::Linux; +namespace Aws +{ +namespace IoTFleetWise +{ PayloadManager::PayloadManager( std::shared_ptr persistencyPtr ) : mPersistencyPtr( std::move( persistencyPtr ) ) @@ -17,9 +19,7 @@ PayloadManager::PayloadManager( std::shared_ptr persistencyPtr } bool -PayloadManager::storeData( const std::uint8_t *buf, - size_t size, - const struct CollectionSchemeParams &collectionSchemeParams ) +PayloadManager::storeData( const std::uint8_t *buf, size_t size, const CollectionSchemeParams &collectionSchemeParams ) { if ( mPersistencyPtr == nullptr ) { @@ -62,8 +62,9 @@ PayloadManager::storeData( const std::uint8_t *buf, void PayloadManager::storeMetadata( const std::string filename, size_t size, - const struct CollectionSchemeParams &collectionSchemeParams ) + const CollectionSchemeParams &collectionSchemeParams ) { + std::lock_guard lock( mMetadataMutex ); Json::Value metadata; metadata["filename"] = filename; metadata["payloadSize"] = static_cast( size ); @@ -114,3 +115,6 @@ PayloadManager::retrievePayload( uint8_t *buf, size_t size, const std::string &f filename ); return ErrorCode::SUCCESS; } + +} // namespace IoTFleetWise +} // namespace Aws diff --git a/src/offboardconnectivity/implementation/aws/iotcpp/include/PayloadManager.h b/src/PayloadManager.h similarity index 53% rename from src/offboardconnectivity/implementation/aws/iotcpp/include/PayloadManager.h rename to src/PayloadManager.h index 55890e80..092e1024 100644 --- a/src/offboardconnectivity/implementation/aws/iotcpp/include/PayloadManager.h +++ b/src/PayloadManager.h @@ -3,26 +3,19 @@ #pragma once -// Includes #include "CacheAndPersist.h" #include "ISender.h" -#include +#include +#include +#include #include -#include +#include #include namespace Aws { namespace IoTFleetWise { -/** - * @brief Namespace depending on Persistency and Connectivity - */ -namespace OffboardConnectivityAwsIot -{ -using namespace Aws::IoTFleetWise::OffboardConnectivity; -using Aws::IoTFleetWise::OffboardConnectivity::CollectionSchemeParams; -using namespace Aws::IoTFleetWise::Platform::Linux::PersistencyManagement; /** * @brief Class that handles offline data storage/retrieval and data compression before transmission @@ -32,29 +25,30 @@ class PayloadManager public: PayloadManager( std::shared_ptr persistencyPtr ); + virtual ~PayloadManager() = default; + /** * @brief Prepares and writes the payload data to storage. Constructs and writes payload metadata JSON object. * - * @param buf buffer containing payload - * @param size number of accessible bytes in buf - * @param collectionSchemeParams object containing collectionScheme related metadata for data persistency and - * transmission - * * @return true if data was persisted and metadata was added, else false */ - bool storeData( const std::uint8_t *buf, size_t size, const struct CollectionSchemeParams &collectionSchemeParams ); + virtual bool storeData( + const std::uint8_t *buf, /**< buffer containing payload */ + size_t size, /**< size number of accessible bytes in buf */ + const CollectionSchemeParams &collectionSchemeParams /**< object containing collectionScheme related + metadata for data persistency and transmission */ + ); /** * @brief Constructs and writes payload metadata JSON object. - * - * @param filename file to construct metadata for - * @param size size of the payload - * @param collectionSchemeParams object containing collectionScheme related metadata for data persistency and - * transmission */ - void storeMetadata( const std::string filename, - size_t size, - const struct CollectionSchemeParams &collectionSchemeParams ); + virtual void storeMetadata( + const std::string filename, /**< filename file to construct metadata for */ + size_t size, /**< size of the payload */ + const CollectionSchemeParams + &collectionSchemeParams /**< collectionSchemeParams object containing + collectionScheme related metadata for data persistency and transmission */ + ); /** * @brief Retrieves metadata for all persisted files from the JSON file and removes extracted metadata from the JSON @@ -64,7 +58,7 @@ class PayloadManager * * @return SUCCESS if metadata was successfully retrieved, FILESYSTEM_ERROR for other errors */ - ErrorCode retrievePayloadMetadata( Json::Value &files ); + virtual ErrorCode retrievePayloadMetadata( Json::Value &files ); /** * @brief Retrieves persisted payload from the file and deletes the file. @@ -75,11 +69,12 @@ class PayloadManager * * @return SUCCESS if metadata was successfully retrieved, FILESYSTEM_ERROR for other errors */ - ErrorCode retrievePayload( uint8_t *buf, size_t size, const std::string &filename ); + virtual ErrorCode retrievePayload( uint8_t *buf, size_t size, const std::string &filename ); private: std::shared_ptr mPersistencyPtr; + std::mutex mMetadataMutex; }; -} // namespace OffboardConnectivityAwsIot + } // namespace IoTFleetWise } // namespace Aws diff --git a/src/offboardconnectivity/implementation/aws/iotcpp/src/RemoteProfiler.cpp b/src/RemoteProfiler.cpp similarity index 96% rename from src/offboardconnectivity/implementation/aws/iotcpp/src/RemoteProfiler.cpp rename to src/RemoteProfiler.cpp index ef743f25..8e642f03 100644 --- a/src/offboardconnectivity/implementation/aws/iotcpp/src/RemoteProfiler.cpp +++ b/src/RemoteProfiler.cpp @@ -2,9 +2,18 @@ // SPDX-License-Identifier: Apache-2.0 #include "RemoteProfiler.h" +#include "IConnectionTypes.h" +#include "LoggingModule.h" #include "TraceModule.h" +#include +#include +#include +#include -using namespace Aws::IoTFleetWise::OffboardConnectivity; +namespace Aws +{ +namespace IoTFleetWise +{ const char *RemoteProfiler::NAME_TOP_LEVEL_LOG_ARRAY = "LogEvents"; const char *RemoteProfiler::NAME_TOP_LEVEL_LOG_PREFIX = "Prefix"; @@ -30,7 +39,7 @@ RemoteProfiler::RemoteProfiler( std::shared_ptr metricsSender, { initLogStructure(); fLastCPURUsage.reportCPUUsageInfo(); - Aws::IoTFleetWise::Platform::Linux::CPUUsageInfo::reportPerThreadUsageData( fLastThreadUsage ); + CPUUsageInfo::reportPerThreadUsageData( fLastThreadUsage ); } void @@ -213,7 +222,7 @@ RemoteProfiler::collectExecutionEnvironmentMetrics() setMetric( "CpuPercentageSum", totalCPUPercentage, "Percent" ); CPUUsageInfo::ThreadCPUUsageInfos threadStatsPrevious = fLastThreadUsage; - Aws::IoTFleetWise::Platform::Linux::CPUUsageInfo::reportPerThreadUsageData( fLastThreadUsage ); + CPUUsageInfo::reportPerThreadUsageData( fLastThreadUsage ); for ( auto currentThreadCPUUsageInfo : fLastThreadUsage ) { for ( auto previousThreadCPUUsageInfo : threadStatsPrevious ) @@ -266,3 +275,5 @@ RemoteProfiler::doWork( void *data ) } } } +} // namespace IoTFleetWise +} // namespace Aws diff --git a/src/offboardconnectivity/implementation/aws/iotcpp/include/RemoteProfiler.h b/src/RemoteProfiler.h similarity index 96% rename from src/offboardconnectivity/implementation/aws/iotcpp/include/RemoteProfiler.h rename to src/RemoteProfiler.h index 468c6d4e..d26e29aa 100644 --- a/src/offboardconnectivity/implementation/aws/iotcpp/include/RemoteProfiler.h +++ b/src/RemoteProfiler.h @@ -4,26 +4,28 @@ #pragma once #include "CPUUsageInfo.h" +#include "Clock.h" #include "ClockHandler.h" -#include "IConnectionTypes.h" #include "ILogger.h" #include "ISender.h" #include "LogLevel.h" -#include "LoggingModule.h" #include "MemoryUsageInfo.h" +#include "Signal.h" #include "Thread.h" +#include "TimeTypes.h" #include "TraceModule.h" +#include +#include #include #include +#include #include namespace Aws { namespace IoTFleetWise { -namespace OffboardConnectivity -{ -using namespace Aws::IoTFleetWise::Platform::Linux; + class RemoteProfiler : public IMetricsReceiver, public ILogger { public: @@ -154,6 +156,6 @@ class RemoteProfiler : public IMetricsReceiver, public ILogger std::string fProfilerPrefix; uint32_t fCurrentUserPayloadInLogRoot; }; -} // namespace OffboardConnectivity + } // namespace IoTFleetWise } // namespace Aws diff --git a/src/offboardconnectivity/implementation/aws/iotcpp/src/RetryThread.cpp b/src/RetryThread.cpp similarity index 95% rename from src/offboardconnectivity/implementation/aws/iotcpp/src/RetryThread.cpp rename to src/RetryThread.cpp index a8c422b1..0be32fa0 100644 --- a/src/offboardconnectivity/implementation/aws/iotcpp/src/RetryThread.cpp +++ b/src/RetryThread.cpp @@ -3,8 +3,13 @@ #include "RetryThread.h" #include "LoggingModule.h" +#include +#include -using namespace Aws::IoTFleetWise::OffboardConnectivityAwsIot; +namespace Aws +{ +namespace IoTFleetWise +{ std::atomic RetryThread::fInstanceCounter( 0 ); @@ -81,3 +86,6 @@ RetryThread::doWork( void *data ) FWE_LOG_TRACE( "Stop thread with ABORT" ); retryThread->fRetryable.onFinished( RetryStatus::ABORT ); } + +} // namespace IoTFleetWise +} // namespace Aws diff --git a/src/offboardconnectivity/implementation/aws/iotcpp/include/RetryThread.h b/src/RetryThread.h similarity index 94% rename from src/offboardconnectivity/implementation/aws/iotcpp/include/RetryThread.h rename to src/RetryThread.h index 503d43a7..4f00de17 100644 --- a/src/offboardconnectivity/implementation/aws/iotcpp/include/RetryThread.h +++ b/src/RetryThread.h @@ -3,16 +3,16 @@ #pragma once +#include "Signal.h" #include "Thread.h" #include +#include +#include namespace Aws { namespace IoTFleetWise { -namespace OffboardConnectivityAwsIot -{ -using namespace Aws::IoTFleetWise::Platform::Linux; enum class RetryStatus { @@ -93,6 +93,6 @@ class RetryThread std::mutex fThreadMutex; Signal fWait; }; -} // namespace OffboardConnectivityAwsIot + } // namespace IoTFleetWise } // namespace Aws diff --git a/src/datamanagement/datamanager/src/Schema.cpp b/src/Schema.cpp similarity index 93% rename from src/datamanagement/datamanager/src/Schema.cpp rename to src/Schema.cpp index bbb61a42..9596929c 100644 --- a/src/datamanagement/datamanager/src/Schema.cpp +++ b/src/Schema.cpp @@ -1,18 +1,14 @@ // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 -// Includes #include "Schema.h" +#include "IConnectionTypes.h" +#include namespace Aws { namespace IoTFleetWise { -namespace DataManagement -{ -using namespace Aws::IoTFleetWise::Platform::Linux; -using namespace Aws::IoTFleetWise::Schemas; -using namespace Aws::IoTFleetWise::OffboardConnectivity; Schema::Schema( std::shared_ptr receiverDecoderManifest, std::shared_ptr receiverCollectionSchemeList, @@ -112,6 +108,5 @@ Schema::transmitCheckin() } } -} // namespace DataManagement } // namespace IoTFleetWise } // namespace Aws diff --git a/src/datamanagement/datamanager/include/Schema.h b/src/Schema.h similarity index 96% rename from src/datamanagement/datamanager/include/Schema.h rename to src/Schema.h index 7242624e..254462cb 100644 --- a/src/datamanagement/datamanager/include/Schema.h +++ b/src/Schema.h @@ -3,17 +3,19 @@ #pragma once -// Includes +#include "Clock.h" #include "ClockHandler.h" #include "CollectionSchemeIngestionList.h" #include "CollectionSchemeManagementListener.h" #include "DecoderManifestIngestion.h" #include "IReceiver.h" #include "ISender.h" +#include "Listener.h" #include "LoggingModule.h" #include "SchemaListener.h" -#include "Thread.h" #include "checkin.pb.h" +#include +#include #include #include #include @@ -22,10 +24,6 @@ namespace Aws { namespace IoTFleetWise { -namespace DataManagement -{ -using namespace Aws::IoTFleetWise::Platform::Linux; -using namespace Aws::IoTFleetWise::OffboardConnectivity; /// Use shared pointers to the derived class using CollectionSchemeListPtr = std::shared_ptr; @@ -182,7 +180,7 @@ class Schema : public ThreadListeners, publi /** * @brief CheckinMsg member variable used to hold the checkin data and minimize heap fragmentation */ - CheckinMsg::Checkin mProtoCheckinMsg; + Schemas::CheckinMsg::Checkin mProtoCheckinMsg; /** * @brief Holds the serialized output of the checkin message to minimize heap fragmentation @@ -201,6 +199,6 @@ class Schema : public ThreadListeners, publi */ bool transmitCheckin(); }; -} // namespace DataManagement + } // namespace IoTFleetWise } // namespace Aws diff --git a/src/datamanagement/datamanager/include/SchemaListener.h b/src/SchemaListener.h similarity index 94% rename from src/datamanagement/datamanager/include/SchemaListener.h rename to src/SchemaListener.h index dbfe164f..6ae504b8 100644 --- a/src/datamanagement/datamanager/include/SchemaListener.h +++ b/src/SchemaListener.h @@ -10,8 +10,7 @@ namespace Aws { namespace IoTFleetWise { -namespace DataManagement -{ + /** * @brief Class to allow for CollectionSchemeManager to trigger callbacks on the Schema Class */ @@ -31,6 +30,5 @@ class SchemaListener virtual bool sendCheckin( const std::vector &documentARNs ) = 0; }; -} // namespace DataManagement } // namespace IoTFleetWise } // namespace Aws diff --git a/src/platform/linux/threadingmanagement/include/Signal.h b/src/Signal.h similarity index 96% rename from src/platform/linux/threadingmanagement/include/Signal.h rename to src/Signal.h index 8e5fbde5..864cd64c 100644 --- a/src/platform/linux/threadingmanagement/include/Signal.h +++ b/src/Signal.h @@ -3,8 +3,6 @@ #pragma once -// Includes - #include #include #include @@ -14,10 +12,7 @@ namespace Aws { namespace IoTFleetWise { -namespace Platform -{ -namespace Linux -{ + /** * @brief Wrapper on top of a condition variable. Helps Thread state transitions. */ @@ -93,7 +88,5 @@ class Signal std::mutex mMutex; }; -} // namespace Linux -} // namespace Platform } // namespace IoTFleetWise } // namespace Aws diff --git a/src/datamanagement/types/include/SignalTypes.h b/src/SignalTypes.h similarity index 98% rename from src/datamanagement/types/include/SignalTypes.h rename to src/SignalTypes.h index 63ec6f11..6e8c13b2 100644 --- a/src/datamanagement/types/include/SignalTypes.h +++ b/src/SignalTypes.h @@ -10,8 +10,6 @@ namespace Aws { namespace IoTFleetWise { -namespace DataManagement -{ /** @brief Number of bits in a byte */ static constexpr uint8_t BYTE_SIZE = 8; @@ -153,6 +151,5 @@ struct CANSignalFormat } }; -} // namespace DataManagement } // namespace IoTFleetWise } // namespace Aws diff --git a/src/platform/linux/threadingmanagement/src/Thread.cpp b/src/Thread.cpp similarity index 90% rename from src/platform/linux/threadingmanagement/src/Thread.cpp rename to src/Thread.cpp index 1869eaab..b05c1b52 100644 --- a/src/platform/linux/threadingmanagement/src/Thread.cpp +++ b/src/Thread.cpp @@ -1,9 +1,6 @@ // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 -#if defined( IOTFLEETWISE_LINUX ) -// Includes - #include "Thread.h" #include #include @@ -12,10 +9,6 @@ namespace Aws { namespace IoTFleetWise { -namespace Platform -{ -namespace Linux -{ extern "C" { @@ -109,7 +102,7 @@ Thread::setThreadName( const std::string &name ) // NOLINT(readability-make-memb } void -Thread::SetCurrentThreadName( const std::string &name ) +Thread::setCurrentThreadName( const std::string &name ) { prctl( PR_SET_NAME, name.c_str(), 0, 0, 0 ); } @@ -120,8 +113,5 @@ Thread::getThreadID() const return static_cast( mThread ); } -} // namespace Linux -} // namespace Platform } // namespace IoTFleetWise } // namespace Aws -#endif // IOTFLEETWISE_LINUX diff --git a/src/platform/linux/threadingmanagement/include/Thread.h b/src/Thread.h similarity index 90% rename from src/platform/linux/threadingmanagement/include/Thread.h rename to src/Thread.h index 32b726e8..076cf8c7 100644 --- a/src/platform/linux/threadingmanagement/include/Thread.h +++ b/src/Thread.h @@ -3,21 +3,18 @@ #pragma once -#if defined( IOTFLEETWISE_LINUX ) -// Includes #include "Signal.h" -#include +#include #include #include +#include +#include namespace Aws { namespace IoTFleetWise { -namespace Platform -{ -namespace Linux -{ + /** * @brief POSIX Thread Wrapper Implementation. * As a rule of thumb, Thread names must follow this convention i.e. @@ -67,7 +64,7 @@ class Thread /** * @brief Sets Thread name of the callee thread */ - static void SetCurrentThreadName( const std::string &name ); + static void setCurrentThreadName( const std::string &name ); // callback called from thread implementation library like pthread static void *workerFunctionWrapper( void *params ); @@ -92,8 +89,5 @@ class Thread std::unique_ptr mTerminateSignal; }; -} // namespace Linux -} // namespace Platform } // namespace IoTFleetWise } // namespace Aws -#endif // IOTFLEETWISE_LINUX diff --git a/src/platform/linux/timemanagement/include/TimeTypes.h b/src/TimeTypes.h similarity index 87% rename from src/platform/linux/timemanagement/include/TimeTypes.h rename to src/TimeTypes.h index 22a420eb..b9daefce 100644 --- a/src/platform/linux/timemanagement/include/TimeTypes.h +++ b/src/TimeTypes.h @@ -3,18 +3,12 @@ #pragma once -// Includes - #include namespace Aws { namespace IoTFleetWise { -namespace Platform -{ -namespace Linux -{ using Timestamp = std::uint64_t; @@ -32,7 +26,5 @@ struct TimePoint Timestamp monotonicTimeMs; }; -} // namespace Linux -} // namespace Platform } // namespace IoTFleetWise } // namespace Aws diff --git a/src/platform/linux/timemanagement/include/Timer.h b/src/Timer.h similarity index 96% rename from src/platform/linux/timemanagement/include/Timer.h rename to src/Timer.h index d7a435b7..abbe682a 100644 --- a/src/platform/linux/timemanagement/include/Timer.h +++ b/src/Timer.h @@ -3,18 +3,13 @@ #pragma once -// Includes - #include namespace Aws { namespace IoTFleetWise { -namespace Platform -{ -namespace Linux -{ + /** * Generic Timer utility that helps tracking execution of tasks. */ @@ -138,7 +133,5 @@ Timer::getElapsedSeconds() const return std::chrono::duration( getElapsed() ).count(); } -} // namespace Linux -} // namespace Platform } // namespace IoTFleetWise } // namespace Aws diff --git a/src/platform/linux/logmanagement/src/TraceModule.cpp b/src/TraceModule.cpp similarity index 99% rename from src/platform/linux/logmanagement/src/TraceModule.cpp rename to src/TraceModule.cpp index 76a22ff2..280be1b9 100644 --- a/src/platform/linux/logmanagement/src/TraceModule.cpp +++ b/src/TraceModule.cpp @@ -1,8 +1,6 @@ // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 -// Includes - #include "TraceModule.h" #include "LoggingModule.h" #include @@ -11,10 +9,6 @@ namespace Aws { namespace IoTFleetWise { -namespace Platform -{ -namespace Linux -{ void TraceModule::sectionBegin( TraceSection section ) @@ -398,7 +392,5 @@ TraceModule::print() } } -} // namespace Linux -} // namespace Platform } // namespace IoTFleetWise } // namespace Aws diff --git a/src/platform/linux/logmanagement/include/TraceModule.h b/src/TraceModule.h similarity index 99% rename from src/platform/linux/logmanagement/include/TraceModule.h rename to src/TraceModule.h index 98274b4b..12e68e93 100644 --- a/src/platform/linux/logmanagement/include/TraceModule.h +++ b/src/TraceModule.h @@ -3,23 +3,19 @@ #pragma once -// Includes #include "EnumUtility.h" #include "Timer.h" #include #include #include +#include #include namespace Aws { namespace IoTFleetWise { -namespace Platform -{ -namespace Linux -{ -using namespace Aws::IoTFleetWise::Platform::Utility; + /** * Different Variables defined at compile time used by all other modules * For verbose print to work it needs to be also added to getVariableName() @@ -430,7 +426,6 @@ class TraceModule Timer mTimeSinceLastObservationWindow; }; -} // namespace Linux -} // namespace Platform + } // namespace IoTFleetWise } // namespace Aws diff --git a/src/vehiclenetwork/include/datatypes/VehicleDataSourceTypes.h b/src/VehicleDataSourceTypes.h similarity index 91% rename from src/vehiclenetwork/include/datatypes/VehicleDataSourceTypes.h rename to src/VehicleDataSourceTypes.h index 45f1189e..c0e3fd6d 100644 --- a/src/vehiclenetwork/include/datatypes/VehicleDataSourceTypes.h +++ b/src/VehicleDataSourceTypes.h @@ -9,8 +9,6 @@ namespace Aws { namespace IoTFleetWise { -namespace VehicleNetwork -{ // Transport Protocol used by the Vehicle Data Source enum class VehicleDataSourceProtocol @@ -24,6 +22,5 @@ enum class VehicleDataSourceProtocol constexpr std::array SUPPORTED_NETWORK_PROTOCOL = { { VehicleDataSourceProtocol::RAW_SOCKET, VehicleDataSourceProtocol::OBD } }; -} // namespace VehicleNetwork } // namespace IoTFleetWise } // namespace Aws diff --git a/src/executionmanagement/src/android_shared_library.cpp b/src/android_shared_library.cpp similarity index 95% rename from src/executionmanagement/src/android_shared_library.cpp rename to src/android_shared_library.cpp index 333fdb7d..24ccbb91 100644 --- a/src/executionmanagement/src/android_shared_library.cpp +++ b/src/android_shared_library.cpp @@ -1,7 +1,6 @@ // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 -// Includes #include "ConsoleLogger.h" #include "IoTFleetWiseEngine.h" #include "IoTFleetWiseVersion.h" @@ -20,10 +19,8 @@ #define LOGI( x ) __android_log_print( ANDROID_LOG_INFO, LOG_TAG, "%s", ( x ).c_str() ) #define LOGD( x ) __android_log_print( ANDROID_LOG_DEBUG, LOG_TAG, "%s", ( x ).c_str() ) -using namespace Aws::IoTFleetWise::ExecutionManagement; - static std::atomic mExit; -static std::shared_ptr mEngine; +static std::shared_ptr mEngine; static void printVersion() @@ -35,10 +32,10 @@ printVersion() static void configureLogging( const Json::Value &config ) { - Aws::IoTFleetWise::Platform::Linux::LogLevel logLevel = Aws::IoTFleetWise::Platform::Linux::LogLevel::Trace; + auto logLevel = Aws::IoTFleetWise::LogLevel::Trace; stringToLogLevel( config["staticConfig"]["internalParameters"]["systemWideLogLevel"].asString(), logLevel ); - gSystemWideLogLevel = logLevel; - gLogColorOption = Aws::IoTFleetWise::Platform::Linux::LogColorOption::No; + Aws::IoTFleetWise::gSystemWideLogLevel = logLevel; + Aws::IoTFleetWise::gLogColorOption = Aws::IoTFleetWise::LogColorOption::No; } static std::string @@ -135,7 +132,7 @@ Java_com_aws_iotfleetwise_Fwe_run( JNIEnv *env, // Set system wide log level configureLogging( config ); - mEngine = std::make_shared(); + mEngine = std::make_shared(); // Connect the Engine if ( mEngine->connect( config ) && mEngine->start() ) { @@ -296,7 +293,7 @@ Java_com_aws_iotfleetwise_Fwe_ingestCanMessage( std::vector data( static_cast( len ) ); env->GetByteArrayRegion( dataJArray, 0, len, (int8_t *)data.data() ); mEngine->ingestExternalCANMessage( - interfaceId, static_cast( timestamp ), static_cast( messageId ), data ); + interfaceId, static_cast( timestamp ), static_cast( messageId ), data ); } extern "C" JNIEXPORT jstring JNICALL diff --git a/src/datamanagement/CMakeLists.txt b/src/datamanagement/CMakeLists.txt deleted file mode 100644 index ba225326..00000000 --- a/src/datamanagement/CMakeLists.txt +++ /dev/null @@ -1,9 +0,0 @@ -add_subdirectory(types) -add_subdirectory(datacollection) -add_subdirectory(datadecoding) -add_subdirectory(datainspection) -add_subdirectory(datamanager) -add_subdirectory(datasender) -if(FWE_FEATURE_CUSTOM_DATA_SOURCE) - add_subdirectory(custom) -endif() diff --git a/src/datamanagement/custom/CMakeLists.txt b/src/datamanagement/custom/CMakeLists.txt deleted file mode 100644 index 6c198d6c..00000000 --- a/src/datamanagement/custom/CMakeLists.txt +++ /dev/null @@ -1,132 +0,0 @@ -# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. -set(libraryTargetName iotfleetwise.customdata) - -# The alias name is what other targets will use as a dependency -set(libraryAliasName IoTFleetWise::CustomDataSource) - -if(FWE_FEATURE_IWAVE_GPS) - set(EXTRA_SOURCE_FILES ${EXTRA_SOURCE_FILES} example/iwavegps/src/IWaveGpsSource.cpp) -endif() -if(FWE_FEATURE_EXTERNAL_GPS) - set(EXTRA_SOURCE_FILES ${EXTRA_SOURCE_FILES} example/externalgps/src/ExternalGpsSource.cpp) -endif() -if(FWE_FEATURE_AAOS_VHAL) - set(EXTRA_SOURCE_FILES ${EXTRA_SOURCE_FILES} example/aaosvhal/src/AaosVhalSource.cpp) -endif() -set(SRCS - generic/src/CustomDataSource.cpp - ${EXTRA_SOURCE_FILES} -) - -add_library( - ${libraryTargetName} - # STATIC or SHARED left out to depend on BUILD_SHARED_LIBS - ${SRCS} -) - -if(FWE_FEATURE_IWAVE_GPS) - set(EXTRA_INCLUDE_DIRS ${EXTRA_INCLUDE_DIRS} example/iwavegps/include) -endif() -if(FWE_FEATURE_EXTERNAL_GPS) - set(EXTRA_INCLUDE_DIRS ${EXTRA_INCLUDE_DIRS} example/externalgps/include) -endif() -if(FWE_FEATURE_AAOS_VHAL) - set(EXTRA_INCLUDE_DIRS ${EXTRA_INCLUDE_DIRS} example/aaosvhal/include) -endif() -target_include_directories(${libraryTargetName} PUBLIC - generic/include - ${EXTRA_INCLUDE_DIRS} -) - -target_link_libraries( - ${libraryTargetName} - IoTFleetWise::Platform::Linux - IoTFleetWise::Vehiclenetwork - IoTFleetWise::DataInspection - IoTFleetWise::DataCollection - IoTFleetWise::DataDecoding - IoTFleetWise::OffboardConnectivityAwsIot - IoTFleetWise::Platform::Utility -) - -add_library(${libraryAliasName} ALIAS ${libraryTargetName}) - -### Install ### - -install(TARGETS ${libraryTargetName} DESTINATION lib) - -if(FWE_FEATURE_IWAVE_GPS) - set(EXTRA_INSTALL_FILES ${EXTRA_INSTALL_FILES} example/iwavegps/include/IWaveGpsSource.h) -endif() -if(FWE_FEATURE_EXTERNAL_GPS) - set(EXTRA_INSTALL_FILES ${EXTRA_INSTALL_FILES} example/externalgps/include/ExternalGpsSource.h) -endif() -if(FWE_FEATURE_AAOS_VHAL) - set(EXTRA_INSTALL_FILES ${EXTRA_INSTALL_FILES} example/aaosvhal/include/AaosVhalSource.h) -endif() -install( - FILES - generic/include/CustomDataSource.h - ${EXTRA_INSTALL_FILES} - DESTINATION include -) - - -### Tests ### -# This is a list of tests that will compiled. -# If adding a test, simply add the source file here - -if(${BUILD_TESTING}) - message(STATUS "Building tests for ${libraryTargetName}") - - find_library(GMOCK_LIB - NAMES - gmock) - - find_library(GMOCK_MAIN_LIBRARY - NAMES - gmock_main) - - if(FWE_FEATURE_IWAVE_GPS) - set(EXTRA_TEST_FILES ${EXTRA_TEST_FILES} example/iwavegps/test/IWaveGpsSourceTest.cpp) - endif() - if(FWE_FEATURE_EXTERNAL_GPS) - set(EXTRA_TEST_FILES ${EXTRA_TEST_FILES} example/externalgps/test/ExternalGpsSourceTest.cpp) - endif() - if(FWE_FEATURE_AAOS_VHAL) - set(EXTRA_TEST_FILES ${EXTRA_TEST_FILES} example/aaosvhal/test/AaosVhalSourceTest.cpp) - endif() - set( - testSources - generic/test/CustomDataSourceTest.cpp - ${EXTRA_TEST_FILES} - ) - # Add the executable targets - foreach(testSource ${testSources}) - # Need a name for each exec so use filename w/o extension - get_filename_component(testName ${testSource} NAME_WE) - - add_executable(${testName} ${testSource}) - - target_include_directories( - ${testName} - PRIVATE - include) - - # Link to the project library and testing library main - target_link_libraries( - ${testName} - PRIVATE - ${libraryTargetName} - IoTFleetWise::TestingSupport - ${GMOCK_LIB} - ) - - add_test(NAME ${testName} COMMAND ${testName} --gtest_output=xml:report-${testName}.xml) - add_valgrind_test(${testName} ${CMAKE_CURRENT_SOURCE_DIR}/generic/test/valgrind.supp) - install(TARGETS ${testName} RUNTIME DESTINATION bin/tests) - - endforeach() -else() - message(STATUS "Testing not enabled for ${libraryTargetName}") -endif() diff --git a/src/datamanagement/custom/example/iwavegps/test/.clang-tidy b/src/datamanagement/custom/example/iwavegps/test/.clang-tidy deleted file mode 100644 index 48f16d51..00000000 --- a/src/datamanagement/custom/example/iwavegps/test/.clang-tidy +++ /dev/null @@ -1,2 +0,0 @@ -# Enable only one dummy check -Checks: "-*,llvm-twine-local" diff --git a/src/datamanagement/custom/generic/test/.clang-tidy b/src/datamanagement/custom/generic/test/.clang-tidy deleted file mode 100644 index 48f16d51..00000000 --- a/src/datamanagement/custom/generic/test/.clang-tidy +++ /dev/null @@ -1,2 +0,0 @@ -# Enable only one dummy check -Checks: "-*,llvm-twine-local" diff --git a/src/datamanagement/custom/generic/test/valgrind.supp b/src/datamanagement/custom/generic/test/valgrind.supp deleted file mode 100644 index 72475585..00000000 --- a/src/datamanagement/custom/generic/test/valgrind.supp +++ /dev/null @@ -1,16 +0,0 @@ -{ - boost::lockfree::do_push - Memcheck:Cond - ... - fun:_ZN5boost8lockfree5queue* - ... -} - -{ - __libc_csu_init - Memcheck:Leak - match-leak-kinds: reachable - ... - fun:__libc_csu_init - ... -} diff --git a/src/datamanagement/datacollection/CMakeLists.txt b/src/datamanagement/datacollection/CMakeLists.txt deleted file mode 100644 index 3ac3f49b..00000000 --- a/src/datamanagement/datacollection/CMakeLists.txt +++ /dev/null @@ -1,85 +0,0 @@ -# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. -set(libraryTargetName iotfleetwise.datacollection) - -# The alias name is what other targets will use as a dependency -set(libraryAliasName IoTFleetWise::DataCollection) - -set(SRCS - src/CollectionSchemeIngestion.cpp - src/CollectionSchemeIngestionList.cpp -) - -add_library( - ${libraryTargetName} - # STATIC or SHARED left out to depend on BUILD_SHARED_LIBS - ${SRCS} -) - -find_path(JSONCPP_INCLUDE_DIR "json/json.h" PATH_SUFFIXES "jsoncpp") -find_library(JSONCPP_LIBRARY NAMES jsoncpp) - -target_include_directories(${libraryTargetName} PUBLIC include ${JSONCPP_INCLUDE_DIR}) - -find_package(Boost 1.71.0 REQUIRED COMPONENTS filesystem) - -target_link_libraries( - ${libraryTargetName} - Boost::filesystem - IoTFleetWise::DataManagementTypes - IoTFleetWise::OffboardConnectivityAwsIot - IoTFleetWise::Proto - IoTFleetWise::Platform::Linux - IoTFleetWise::Vehiclenetwork -) - -add_library(${libraryAliasName} ALIAS ${libraryTargetName}) - -### Install ### - -install(TARGETS ${libraryTargetName} DESTINATION lib) - -install( - FILES - include/CANInterfaceIDTranslator.h - include/CollectionSchemeIngestion.h - include/CollectionSchemeIngestionList.h - include/ICollectionScheme.h - include/ICollectionSchemeList.h - DESTINATION include -) - -if(${BUILD_TESTING}) - message(STATUS "Building tests for ${libraryTargetName}") - - set( - testSources - ) - - # Add the executable targets - foreach(testSource ${testSources}) - # Need a name for each exec so use filename w/o extension - get_filename_component(testName ${testSource} NAME_WE) - - add_executable(${testName} ${testSource}) - - # Link to the project library and testing library main - target_link_libraries( - ${testName} - PRIVATE - ${libraryTargetName} - IoTFleetWise::TestingSupport - ) - - target_include_directories( - ${testName} - PRIVATE - include - test/include) - - add_unit_test(${testName}) - add_valgrind_test(${testName}) - install(TARGETS ${testName} RUNTIME DESTINATION bin/tests) - - endforeach() - -endif() diff --git a/src/datamanagement/datacollection/test/.clang-tidy b/src/datamanagement/datacollection/test/.clang-tidy deleted file mode 100644 index 48f16d51..00000000 --- a/src/datamanagement/datacollection/test/.clang-tidy +++ /dev/null @@ -1,2 +0,0 @@ -# Enable only one dummy check -Checks: "-*,llvm-twine-local" diff --git a/src/datamanagement/datacollection/test/valgrind.supp b/src/datamanagement/datacollection/test/valgrind.supp deleted file mode 100644 index fb93ef2c..00000000 --- a/src/datamanagement/datacollection/test/valgrind.supp +++ /dev/null @@ -1,41 +0,0 @@ -{ - boost::lockfree::do_push - Memcheck:Cond - ... - fun:_ZN5boost8lockfree5queue* - ... -} - -{ - - Memcheck:Param - write(buf) - ... - fun:sem_open - ... -} - -{ - fastrptps_bug_remove_persistence_guid - Memcheck:Addr2 - ... - fun:*remove_persistence_guid* - ... -} - -{ - fastrptps_bug_add_persistence_guid - Memcheck:Addr2 - ... - fun:*add_persistence_guid* - ... -} - -{ - __libc_csu_init - Memcheck:Leak - match-leak-kinds: reachable - ... - fun:__libc_csu_init - ... -} diff --git a/src/datamanagement/datadecoding/CMakeLists.txt b/src/datamanagement/datadecoding/CMakeLists.txt deleted file mode 100644 index dfc3dd21..00000000 --- a/src/datamanagement/datadecoding/CMakeLists.txt +++ /dev/null @@ -1,93 +0,0 @@ -# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. - -set(libraryTargetName iotfleetwise.datadecoding) - -# The alias name is what other targets will use as a dependency -set(libraryAliasName IoTFleetWise::DataDecoding) - -add_library( - ${libraryTargetName} - # STATIC or SHARED left out to depend on BUILD_SHARED_LIBS - src/CANDecoder.cpp - src/DecoderManifestIngestion.cpp - src/OBDDataDecoder.cpp -) - -target_include_directories(${libraryTargetName} PUBLIC - include -) - -find_package(Boost 1.71.0 REQUIRED COMPONENTS filesystem) - -target_link_libraries( - ${libraryTargetName} - Boost::filesystem - IoTFleetWise::DataManagementTypes - IoTFleetWise::Proto - IoTFleetWise::Platform::Linux - IoTFleetWise::Vehiclenetwork -) - -add_library(${libraryAliasName} ALIAS ${libraryTargetName}) - -### Install ### -install(TARGETS ${libraryTargetName} DESTINATION lib) -install( - FILES - include/CANDecoder.h - include/DecoderManifestIngestion.h - include/IActiveDecoderDictionaryListener.h - include/IDecoderDictionary.h - include/IDecoderManifest.h - include/OBDDataDecoder.h - DESTINATION include -) - -### Tests ### - -if(${BUILD_TESTING}) - message(STATUS "Building tests for ${libraryTargetName}") - - find_library(GMOCK_LIB - NAMES - gmock) - - find_library(GMOCK_MAIN_LIBRARY - NAMES - gmock_main) - - set( - testSources - test/CANDecoderTest.cpp - test/OBDDataDecoderTest.cpp - ) - # Add the executable targets - foreach(testSource ${testSources}) - # Need a name for each exec so use filename w/o extension - get_filename_component(testName ${testSource} NAME_WE) - - add_executable(${testName} ${testSource}) - - # Link to the project library and testing library main - target_link_libraries( - ${testName} - PRIVATE - ${libraryTargetName} - Boost::filesystem - IoTFleetWise::TestingSupport - ${GMOCK_LIB} - ) - - target_include_directories( - ${testName} - PRIVATE - include - test/include) - - add_test(NAME ${testName} COMMAND ${testName} --gtest_output=xml:report-${testName}.xml) - add_valgrind_test(${testName}) - install(TARGETS ${testName} RUNTIME DESTINATION bin/tests) - - endforeach() - -endif() diff --git a/src/datamanagement/datadecoding/test/.clang-tidy b/src/datamanagement/datadecoding/test/.clang-tidy deleted file mode 100644 index 48f16d51..00000000 --- a/src/datamanagement/datadecoding/test/.clang-tidy +++ /dev/null @@ -1,2 +0,0 @@ -# Enable only one dummy check -Checks: "-*,llvm-twine-local" diff --git a/src/datamanagement/datadecoding/test/valgrind.supp b/src/datamanagement/datadecoding/test/valgrind.supp deleted file mode 100644 index fb93ef2c..00000000 --- a/src/datamanagement/datadecoding/test/valgrind.supp +++ /dev/null @@ -1,41 +0,0 @@ -{ - boost::lockfree::do_push - Memcheck:Cond - ... - fun:_ZN5boost8lockfree5queue* - ... -} - -{ - - Memcheck:Param - write(buf) - ... - fun:sem_open - ... -} - -{ - fastrptps_bug_remove_persistence_guid - Memcheck:Addr2 - ... - fun:*remove_persistence_guid* - ... -} - -{ - fastrptps_bug_add_persistence_guid - Memcheck:Addr2 - ... - fun:*add_persistence_guid* - ... -} - -{ - __libc_csu_init - Memcheck:Leak - match-leak-kinds: reachable - ... - fun:__libc_csu_init - ... -} diff --git a/src/datamanagement/datainspection/CMakeLists.txt b/src/datamanagement/datainspection/CMakeLists.txt deleted file mode 100644 index d93aba55..00000000 --- a/src/datamanagement/datainspection/CMakeLists.txt +++ /dev/null @@ -1,107 +0,0 @@ -# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. -set(libraryTargetName iotfleetwise.datainspection) - -# The alias name is what other targets will use as a dependency -set(libraryAliasName IoTFleetWise::DataInspection) - -set(SRCS - src/CollectionInspectionEngine.cpp - src/CollectionInspectionWorkerThread.cpp - src/diag/OBDOverCANModule.cpp - src/diag/OBDOverCANECU.cpp - src/location/GeohashFunctionNode.cpp - src/vehicledatasource/CANDataSource.cpp - src/vehicledatasource/CANDataConsumer.cpp - src/vehicledatasource/ExternalCANDataSource.cpp -) - -add_library( - ${libraryTargetName} - # STATIC or SHARED left out to depend on BUILD_SHARED_LIBS - ${SRCS} -) - -find_path(JSONCPP_INCLUDE_DIR "json/json.h" PATH_SUFFIXES "jsoncpp") -find_library(JSONCPP_LIBRARY NAMES jsoncpp) - -target_include_directories(${libraryTargetName} PUBLIC - include - ${JSONCPP_INCLUDE_DIR} -) - -target_link_libraries( - ${libraryTargetName} - IoTFleetWise::Platform::Linux - IoTFleetWise::Vehiclenetwork - IoTFleetWise::DataDecoding - IoTFleetWise::DataCollection - IoTFleetWise::Platform::Utility - ${JSONCPP_LIBRARY} -) - -add_library(${libraryAliasName} ALIAS ${libraryTargetName}) - -### Install ### - -install(TARGETS ${libraryTargetName} DESTINATION lib) - -install( - FILES - include/CollectionInspectionEngine.h - include/CollectionInspectionWorkerThread.h - include/DataReduction.h - include/GeohashFunctionNode.h - include/IActiveConditionProcessor.h - include/IDataReadyToPublishListener.h - include/InspectionEventListener.h - include/CANDataSource.h - include/CANDataConsumer.h - include/OBDOverCANModule.h - include/OBDOverCANECU.h - DESTINATION include -) - -### Tests ### -# This is a list of tests that will compiled. -# If adding a test, simply add the source file here -set( - testSources - test/GeohashFunctionNodeTest.cpp - test/OBDOverCANModuleTest.cpp - test/CollectionInspectionEngineTest.cpp - test/CollectionInspectionWorkerThreadTest.cpp - test/CANDataSourceTest.cpp - test/ExternalCANDataSourceTest.cpp -) - -if(${BUILD_TESTING}) - message(STATUS "Building tests for ${libraryTargetName}") - - # Copy the json file required for the test application - file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/test/di-collection-scheme-example.json - DESTINATION ${CMAKE_CURRENT_BINARY_DIR} ) - file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/test/di-collection-scheme-example-reduced.json - DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) - - # Add the executable targets - foreach(testSource ${testSources}) - # Need a name for each exec so use filename w/o extension - get_filename_component(testName ${testSource} NAME_WE) - - add_executable(${testName} ${testSource}) - - # Link to the project library and testing library main - target_link_libraries( - ${testName} - PRIVATE - ${libraryTargetName} - IoTFleetWise::TestingSupport - ) - add_unit_test(${testName}) - add_valgrind_test(${testName}) - install(TARGETS ${testName} RUNTIME DESTINATION bin/tests) - - endforeach() -else() - message(STATUS "Testing not enabled for ${libraryTargetName}") -endif() diff --git a/src/datamanagement/datainspection/test/.clang-tidy b/src/datamanagement/datainspection/test/.clang-tidy deleted file mode 100644 index 48f16d51..00000000 --- a/src/datamanagement/datainspection/test/.clang-tidy +++ /dev/null @@ -1,2 +0,0 @@ -# Enable only one dummy check -Checks: "-*,llvm-twine-local" diff --git a/src/datamanagement/datainspection/test/di-collection-policy-example-reduced.json b/src/datamanagement/datainspection/test/di-collection-policy-example-reduced.json deleted file mode 100644 index 8048e730..00000000 --- a/src/datamanagement/datainspection/test/di-collection-policy-example-reduced.json +++ /dev/null @@ -1,86 +0,0 @@ -{ - "version": "1.0", - "collectionSchemeID": "arn::testCollectionScheme", - "eventType": "heartbeat", - - "eventTriggers": [ - { - "triggerType": "timepoint", - "valuePredicate": { - "condition": "every", - "value": 10 - } - } - ], - "eventMessages": [ - { - "messageID": 609, - "sizeInBytes": 8, - "signals": [ - { - "signalID": 11, - "isBigEndian": true, - "isSigned": true, - "firstBitPosition": 16, - "sizeInBits": 16, - "offset": 0.0, - "factor": 0.01 - }, - { - "signalID": 12, - "isBigEndian": true, - "isSigned": true, - "firstBitPosition": 32, - "sizeInBits": 14, - "offset": 0.0, - "factor": 0.005 - }, - { - "signalID": 13, - "isBigEndian": true, - "isSigned": true, - "firstBitPosition": 48, - "sizeInBits": 16, - "offset": 0.0, - "factor": 0.005 - }, - { - "signalID": 14, - "isBigEndian": true, - "isSigned": false, - "firstBitPosition": 0, - "sizeInBits": 12, - "offset": 0.0, - "factor": 0.00544368 - }, - { - "signalID": 15, - "isBigEndian": true, - "isSigned": false, - "firstBitPosition": 47, - "sizeInBits": 1, - "offset": 0.0, - "factor": 1.0 - }, - { - "signalID": 16, - "isBigEndian": true, - "isSigned": false, - "firstBitPosition": 46, - "sizeInBits": 1, - "offset": 0.0, - "factor": 1.0 - }, - { - "signalID": 17, - "isBigEndian": true, - "isSigned": false, - "firstBitPosition": 12, - "sizeInBits": 1, - "offset": 0.0, - "factor": 1.0 - } - ] - } - ] -} diff --git a/src/datamanagement/datainspection/test/di-collection-policy-example.json b/src/datamanagement/datainspection/test/di-collection-policy-example.json deleted file mode 100644 index c8b730a9..00000000 --- a/src/datamanagement/datainspection/test/di-collection-policy-example.json +++ /dev/null @@ -1,263 +0,0 @@ -{ - "version": "1.0", - "collectionSchemeID": "arn::testCollectionScheme", - "eventType": "heartbeat", - - "eventTriggers": [ - { - "triggerType": "timepoint", - "valuePredicate": { - "condition": "every", - "value": 10 - } - }, - { - "triggerType": "signalvalue", - "valuePredicate": { - "condition": "less", - "value": 200, - "signalID": 9, - "messageID": 548 - } - }, - { - "triggerType": "signalvalue", - "valuePredicate": { - "condition": "bigger", - "value": 2, - "signalID": 2, - "messageID": 548 - } - } - ], - "eventMessages": [ - { - "messageID": 548, - "sizeInBytes": 8, - "signals": [ - { - "signalID": 1, - "isBigEndian": true, - "isSigned": false, - "firstBitPosition": 44, - "sizeInBits": 4, - "offset": 0.0, - "factor": 1.0 - }, - { - "signalID": 2, - "isBigEndian": true, - "isSigned": false, - "firstBitPosition": 2, - "sizeInBits": 2, - "offset": 0.0, - "factor": 1.0 - }, - { - "signalID": 3, - "isBigEndian": true, - "isSigned": false, - "firstBitPosition": 48, - "sizeInBits": 4, - "offset": 0.0, - "factor": 1.0 - }, - { - "signalID": 4, - "isBigEndian": true, - "isSigned": false, - "firstBitPosition": 15, - "sizeInBits": 1, - "offset": 0.0, - "factor": 1.0 - }, - { - "signalID": 5, - "isBigEndian": true, - "isSigned": false, - "firstBitPosition": 4, - "sizeInBits": 2, - "offset": 0.0, - "factor": 1.0 - }, - { - "signalID": 6, - "isBigEndian": true, - "isSigned": false, - "firstBitPosition": 59, - "sizeInBits": 5, - "offset": 0.0, - "factor": 1.0 - }, - { - "signalID": 7, - "isBigEndian": true, - "isSigned": false, - "firstBitPosition": 16, - "sizeInBits": 12, - "offset": 0.0, - "factor": 0.1 - }, - { - "signalID": 8, - "isBigEndian": true, - "isSigned": false, - "firstBitPosition": 6, - "sizeInBits": 4, - "offset": 0.0, - "factor": 1.0 - }, - { - "signalID": 9, - "isBigEndian": true, - "isSigned": false, - "firstBitPosition": 29, - "sizeInBits": 12, - "offset": 0.0, - "factor": 0.1 - }, - { - "signalID": 10, - "isBigEndian": true, - "isSigned": false, - "firstBitPosition": 28, - "sizeInBits": 1, - "offset": 0.0, - "factor": 1.0 - }, - { - "signalID": 11, - "isBigEndian": true, - "isSigned": false, - "firstBitPosition": 56, - "sizeInBits": 3, - "offset": 0.0, - "factor": 1.0 - }, - { - "signalID": 12, - "isBigEndian": true, - "isSigned": false, - "firstBitPosition": 41, - "sizeInBits": 3, - "offset": 0.0, - "factor": 1.0 - }, - { - "signalID": 13, - "isBigEndian": true, - "isSigned": false, - "firstBitPosition": 0, - "sizeInBits": 2, - "offset": 0.0, - "factor": 1.0 - }, - { - "signalID": 14, - "isBigEndian": true, - "isSigned": false, - "firstBitPosition": 52, - "sizeInBits": 1, - "offset": 0.0, - "factor": 1.0 - }, - { - "signalID": 15, - "isBigEndian": true, - "isSigned": false, - "firstBitPosition": 10, - "sizeInBits": 5, - "offset": 0.0, - "factor": 1.0 - }, - { - "signalID": 16, - "isBigEndian": true, - "isSigned": false, - "firstBitPosition": 53, - "sizeInBits": 1, - "offset": 0.0, - "factor": 1.0 - }, - { - "signalID": 17, - "isBigEndian": true, - "isSigned": false, - "firstBitPosition": 54, - "sizeInBits": 2, - "offset": 0.0, - "factor": 1.0 - } - ] - }, - { - "messageID": 609, - "sizeInBytes": 8, - "signals": [ - { - "signalID": 11, - "isBigEndian": true, - "isSigned": true, - "firstBitPosition": 16, - "sizeInBits": 16, - "offset": 0.0, - "factor": 0.01 - }, - { - "signalID": 12, - "isBigEndian": true, - "isSigned": true, - "firstBitPosition": 32, - "sizeInBits": 14, - "offset": 0.0, - "factor": 0.005 - }, - { - "signalID": 13, - "isBigEndian": true, - "isSigned": true, - "firstBitPosition": 48, - "sizeInBits": 16, - "offset": 0.0, - "factor": 0.005 - }, - { - "signalID": 14, - "isBigEndian": true, - "isSigned": false, - "firstBitPosition": 0, - "sizeInBits": 12, - "offset": 0.0, - "factor": 0.00544368 - }, - { - "signalID": 15, - "isBigEndian": true, - "isSigned": false, - "firstBitPosition": 47, - "sizeInBits": 1, - "offset": 0.0, - "factor": 1.0 - }, - { - "signalID": 16, - "isBigEndian": true, - "isSigned": false, - "firstBitPosition": 46, - "sizeInBits": 1, - "offset": 0.0, - "factor": 1.0 - }, - { - "signalID": 17, - "isBigEndian": true, - "isSigned": false, - "firstBitPosition": 12, - "sizeInBits": 1, - "offset": 0.0, - "factor": 1.0 - } - ] - } - ] -} diff --git a/src/datamanagement/datainspection/test/di-collection-scheme-example-reduced.json b/src/datamanagement/datainspection/test/di-collection-scheme-example-reduced.json deleted file mode 100644 index 8048e730..00000000 --- a/src/datamanagement/datainspection/test/di-collection-scheme-example-reduced.json +++ /dev/null @@ -1,86 +0,0 @@ -{ - "version": "1.0", - "collectionSchemeID": "arn::testCollectionScheme", - "eventType": "heartbeat", - - "eventTriggers": [ - { - "triggerType": "timepoint", - "valuePredicate": { - "condition": "every", - "value": 10 - } - } - ], - "eventMessages": [ - { - "messageID": 609, - "sizeInBytes": 8, - "signals": [ - { - "signalID": 11, - "isBigEndian": true, - "isSigned": true, - "firstBitPosition": 16, - "sizeInBits": 16, - "offset": 0.0, - "factor": 0.01 - }, - { - "signalID": 12, - "isBigEndian": true, - "isSigned": true, - "firstBitPosition": 32, - "sizeInBits": 14, - "offset": 0.0, - "factor": 0.005 - }, - { - "signalID": 13, - "isBigEndian": true, - "isSigned": true, - "firstBitPosition": 48, - "sizeInBits": 16, - "offset": 0.0, - "factor": 0.005 - }, - { - "signalID": 14, - "isBigEndian": true, - "isSigned": false, - "firstBitPosition": 0, - "sizeInBits": 12, - "offset": 0.0, - "factor": 0.00544368 - }, - { - "signalID": 15, - "isBigEndian": true, - "isSigned": false, - "firstBitPosition": 47, - "sizeInBits": 1, - "offset": 0.0, - "factor": 1.0 - }, - { - "signalID": 16, - "isBigEndian": true, - "isSigned": false, - "firstBitPosition": 46, - "sizeInBits": 1, - "offset": 0.0, - "factor": 1.0 - }, - { - "signalID": 17, - "isBigEndian": true, - "isSigned": false, - "firstBitPosition": 12, - "sizeInBits": 1, - "offset": 0.0, - "factor": 1.0 - } - ] - } - ] -} diff --git a/src/datamanagement/datainspection/test/di-collection-scheme-example.json b/src/datamanagement/datainspection/test/di-collection-scheme-example.json deleted file mode 100644 index c8b730a9..00000000 --- a/src/datamanagement/datainspection/test/di-collection-scheme-example.json +++ /dev/null @@ -1,263 +0,0 @@ -{ - "version": "1.0", - "collectionSchemeID": "arn::testCollectionScheme", - "eventType": "heartbeat", - - "eventTriggers": [ - { - "triggerType": "timepoint", - "valuePredicate": { - "condition": "every", - "value": 10 - } - }, - { - "triggerType": "signalvalue", - "valuePredicate": { - "condition": "less", - "value": 200, - "signalID": 9, - "messageID": 548 - } - }, - { - "triggerType": "signalvalue", - "valuePredicate": { - "condition": "bigger", - "value": 2, - "signalID": 2, - "messageID": 548 - } - } - ], - "eventMessages": [ - { - "messageID": 548, - "sizeInBytes": 8, - "signals": [ - { - "signalID": 1, - "isBigEndian": true, - "isSigned": false, - "firstBitPosition": 44, - "sizeInBits": 4, - "offset": 0.0, - "factor": 1.0 - }, - { - "signalID": 2, - "isBigEndian": true, - "isSigned": false, - "firstBitPosition": 2, - "sizeInBits": 2, - "offset": 0.0, - "factor": 1.0 - }, - { - "signalID": 3, - "isBigEndian": true, - "isSigned": false, - "firstBitPosition": 48, - "sizeInBits": 4, - "offset": 0.0, - "factor": 1.0 - }, - { - "signalID": 4, - "isBigEndian": true, - "isSigned": false, - "firstBitPosition": 15, - "sizeInBits": 1, - "offset": 0.0, - "factor": 1.0 - }, - { - "signalID": 5, - "isBigEndian": true, - "isSigned": false, - "firstBitPosition": 4, - "sizeInBits": 2, - "offset": 0.0, - "factor": 1.0 - }, - { - "signalID": 6, - "isBigEndian": true, - "isSigned": false, - "firstBitPosition": 59, - "sizeInBits": 5, - "offset": 0.0, - "factor": 1.0 - }, - { - "signalID": 7, - "isBigEndian": true, - "isSigned": false, - "firstBitPosition": 16, - "sizeInBits": 12, - "offset": 0.0, - "factor": 0.1 - }, - { - "signalID": 8, - "isBigEndian": true, - "isSigned": false, - "firstBitPosition": 6, - "sizeInBits": 4, - "offset": 0.0, - "factor": 1.0 - }, - { - "signalID": 9, - "isBigEndian": true, - "isSigned": false, - "firstBitPosition": 29, - "sizeInBits": 12, - "offset": 0.0, - "factor": 0.1 - }, - { - "signalID": 10, - "isBigEndian": true, - "isSigned": false, - "firstBitPosition": 28, - "sizeInBits": 1, - "offset": 0.0, - "factor": 1.0 - }, - { - "signalID": 11, - "isBigEndian": true, - "isSigned": false, - "firstBitPosition": 56, - "sizeInBits": 3, - "offset": 0.0, - "factor": 1.0 - }, - { - "signalID": 12, - "isBigEndian": true, - "isSigned": false, - "firstBitPosition": 41, - "sizeInBits": 3, - "offset": 0.0, - "factor": 1.0 - }, - { - "signalID": 13, - "isBigEndian": true, - "isSigned": false, - "firstBitPosition": 0, - "sizeInBits": 2, - "offset": 0.0, - "factor": 1.0 - }, - { - "signalID": 14, - "isBigEndian": true, - "isSigned": false, - "firstBitPosition": 52, - "sizeInBits": 1, - "offset": 0.0, - "factor": 1.0 - }, - { - "signalID": 15, - "isBigEndian": true, - "isSigned": false, - "firstBitPosition": 10, - "sizeInBits": 5, - "offset": 0.0, - "factor": 1.0 - }, - { - "signalID": 16, - "isBigEndian": true, - "isSigned": false, - "firstBitPosition": 53, - "sizeInBits": 1, - "offset": 0.0, - "factor": 1.0 - }, - { - "signalID": 17, - "isBigEndian": true, - "isSigned": false, - "firstBitPosition": 54, - "sizeInBits": 2, - "offset": 0.0, - "factor": 1.0 - } - ] - }, - { - "messageID": 609, - "sizeInBytes": 8, - "signals": [ - { - "signalID": 11, - "isBigEndian": true, - "isSigned": true, - "firstBitPosition": 16, - "sizeInBits": 16, - "offset": 0.0, - "factor": 0.01 - }, - { - "signalID": 12, - "isBigEndian": true, - "isSigned": true, - "firstBitPosition": 32, - "sizeInBits": 14, - "offset": 0.0, - "factor": 0.005 - }, - { - "signalID": 13, - "isBigEndian": true, - "isSigned": true, - "firstBitPosition": 48, - "sizeInBits": 16, - "offset": 0.0, - "factor": 0.005 - }, - { - "signalID": 14, - "isBigEndian": true, - "isSigned": false, - "firstBitPosition": 0, - "sizeInBits": 12, - "offset": 0.0, - "factor": 0.00544368 - }, - { - "signalID": 15, - "isBigEndian": true, - "isSigned": false, - "firstBitPosition": 47, - "sizeInBits": 1, - "offset": 0.0, - "factor": 1.0 - }, - { - "signalID": 16, - "isBigEndian": true, - "isSigned": false, - "firstBitPosition": 46, - "sizeInBits": 1, - "offset": 0.0, - "factor": 1.0 - }, - { - "signalID": 17, - "isBigEndian": true, - "isSigned": false, - "firstBitPosition": 12, - "sizeInBits": 1, - "offset": 0.0, - "factor": 1.0 - } - ] - } - ] -} diff --git a/src/datamanagement/datainspection/test/valgrind.supp b/src/datamanagement/datainspection/test/valgrind.supp deleted file mode 100644 index fb93ef2c..00000000 --- a/src/datamanagement/datainspection/test/valgrind.supp +++ /dev/null @@ -1,41 +0,0 @@ -{ - boost::lockfree::do_push - Memcheck:Cond - ... - fun:_ZN5boost8lockfree5queue* - ... -} - -{ - - Memcheck:Param - write(buf) - ... - fun:sem_open - ... -} - -{ - fastrptps_bug_remove_persistence_guid - Memcheck:Addr2 - ... - fun:*remove_persistence_guid* - ... -} - -{ - fastrptps_bug_add_persistence_guid - Memcheck:Addr2 - ... - fun:*add_persistence_guid* - ... -} - -{ - __libc_csu_init - Memcheck:Leak - match-leak-kinds: reachable - ... - fun:__libc_csu_init - ... -} diff --git a/src/datamanagement/datamanager/CMakeLists.txt b/src/datamanagement/datamanager/CMakeLists.txt deleted file mode 100644 index edf12730..00000000 --- a/src/datamanagement/datamanager/CMakeLists.txt +++ /dev/null @@ -1,106 +0,0 @@ -# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. -set(libraryTargetName iotfleetwise.datamanager) - -# The alias name is what other targets will use as a dependency -set(libraryAliasName IoTFleetWise::DataManager) - -set(SRCS - src/CheckinAndPersistency.cpp - src/CollectionSchemeManager.cpp - src/DecoderDictionaryExtractor.cpp - src/InspectionMatrixExtractor.cpp - src/Schema.cpp -) - -add_library( - ${libraryTargetName} - # STATIC or SHARED left out to depend on BUILD_SHARED_LIBS - ${SRCS} -) - -target_include_directories(${libraryTargetName} PUBLIC include) - -target_link_libraries( - ${libraryTargetName} - IoTFleetWise::Platform::Linux - IoTFleetWise::Vehiclenetwork - IoTFleetWise::DataInspection - IoTFleetWise::DataCollection - IoTFleetWise::DataDecoding - IoTFleetWise::OffboardConnectivityAwsIot - IoTFleetWise::Platform::Utility -) - -add_library(${libraryAliasName} ALIAS ${libraryTargetName}) - -### Install ### - -install(TARGETS ${libraryTargetName} DESTINATION lib) - -install( - FILES - include/ICollectionSchemeManager.h - include/IActiveCollectionSchemesListener.h - include/CollectionSchemeManagementListener.h - include/CollectionSchemeManager.h - include/Schema.h - include/SchemaListener.h - DESTINATION include -) - - -### Tests ### -# This is a list of tests that will compiled. -# If adding a test, simply add the source file here - -if(${BUILD_TESTING}) - message(STATUS "Building tests for ${libraryTargetName}") - - find_library(GMOCK_LIB - NAMES - gmock) - - find_library(GMOCK_MAIN_LIBRARY - NAMES - gmock_main) - - - set( - testSources - test/CheckinAndPersistencyTest.cpp - test/CollectionSchemeManagerGtest.cpp - test/CollectionSchemeManagerTest.cpp - test/DecoderDictionaryExtractorTest.cpp - test/InspectionMatrixExtractorTest.cpp - test/SchemaTest.cpp - ) - # Add the executable targets - foreach(testSource ${testSources}) - # Need a name for each exec so use filename w/o extension - get_filename_component(testName ${testSource} NAME_WE) - - add_executable(${testName} ${testSource}) - - target_include_directories( - ${testName} - PRIVATE - include - test/include) - - # Link to the project library and testing library main - target_link_libraries( - ${testName} - PRIVATE - ${libraryTargetName} - IoTFleetWise::TestingSupport - ${GMOCK_LIB} - ) - - add_test(NAME ${testName} COMMAND ${testName} --gtest_output=xml:report-${testName}.xml) - add_valgrind_test(${testName}) - install(TARGETS ${testName} RUNTIME DESTINATION bin/tests) - - endforeach() -else() - message(STATUS "Testing not enabled for ${libraryTargetName}") -endif() diff --git a/src/datamanagement/datamanager/test/.clang-tidy b/src/datamanagement/datamanager/test/.clang-tidy deleted file mode 100644 index 48f16d51..00000000 --- a/src/datamanagement/datamanager/test/.clang-tidy +++ /dev/null @@ -1,2 +0,0 @@ -# Enable only one dummy check -Checks: "-*,llvm-twine-local" diff --git a/src/datamanagement/datamanager/test/valgrind.supp b/src/datamanagement/datamanager/test/valgrind.supp deleted file mode 100644 index fb93ef2c..00000000 --- a/src/datamanagement/datamanager/test/valgrind.supp +++ /dev/null @@ -1,41 +0,0 @@ -{ - boost::lockfree::do_push - Memcheck:Cond - ... - fun:_ZN5boost8lockfree5queue* - ... -} - -{ - - Memcheck:Param - write(buf) - ... - fun:sem_open - ... -} - -{ - fastrptps_bug_remove_persistence_guid - Memcheck:Addr2 - ... - fun:*remove_persistence_guid* - ... -} - -{ - fastrptps_bug_add_persistence_guid - Memcheck:Addr2 - ... - fun:*add_persistence_guid* - ... -} - -{ - __libc_csu_init - Memcheck:Leak - match-leak-kinds: reachable - ... - fun:__libc_csu_init - ... -} diff --git a/src/datamanagement/datasender/CMakeLists.txt b/src/datamanagement/datasender/CMakeLists.txt deleted file mode 100644 index 07b0cce6..00000000 --- a/src/datamanagement/datasender/CMakeLists.txt +++ /dev/null @@ -1,96 +0,0 @@ -# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. -set(libraryTargetName iotfleetwise.datasender) - -# The alias name is what other targets will use as a dependency -set(libraryAliasName IoTFleetWise::DataSender) - -set(SRCS - src/DataSenderManagerWorkerThread.cpp - src/DataSenderManager.cpp - src/DataSenderProtoWriter.cpp -) - -add_library( - ${libraryTargetName} - # STATIC or SHARED left out to depend on BUILD_SHARED_LIBS - ${SRCS} -) - -target_include_directories(${libraryTargetName} PUBLIC include) - -target_link_libraries( - ${libraryTargetName} - IoTFleetWise::DataManagementTypes - IoTFleetWise::Platform::Linux - IoTFleetWise::DataInspection - IoTFleetWise::DataManager - IoTFleetWise::OffboardConnectivityAwsIot -) - -add_library(${libraryAliasName} ALIAS ${libraryTargetName}) - -### Install ### - -install(TARGETS ${libraryTargetName} DESTINATION lib) - -install( - FILES - include/DataSenderManager.h - include/DataSenderManagerWorkerThread.h - include/DataSenderProtoWriter.h - DESTINATION include -) - -if(${BUILD_TESTING}) - message(STATUS "Building tests for ${libraryTargetName}") - - find_library(GMOCK_LIB - NAMES - gmock) - - find_library(GMOCK_MAIN_LIBRARY - NAMES - gmock_main) - - file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/test/dm-collection-scheme-example.json - DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) - - - set( - testSources - test/DataSenderProtoWriterTest.cpp - ) - - find_package(Boost 1.65.1 REQUIRED COMPONENTS filesystem) - - # Add the executable targets - foreach(testSource ${testSources}) - # Need a name for each exec so use filename w/o extension - get_filename_component(testName ${testSource} NAME_WE) - - add_executable(${testName} ${testSource}) - - # Link to the project library and testing library main - target_link_libraries( - ${testName} - PRIVATE - ${libraryTargetName} - Boost::filesystem - IoTFleetWise::TestingSupport - IoTFleetWise::OffboardConnectivityAwsIot - ${GMOCK_LIB} - ) - - target_include_directories( - ${testName} - PRIVATE - include - test/include) - - add_unit_test(${testName}) - add_valgrind_test(${testName}) - install(TARGETS ${testName} RUNTIME DESTINATION bin/tests) - - endforeach() - -endif() diff --git a/src/datamanagement/datasender/src/DataSenderManagerWorkerThread.cpp b/src/datamanagement/datasender/src/DataSenderManagerWorkerThread.cpp deleted file mode 100644 index f06246da..00000000 --- a/src/datamanagement/datasender/src/DataSenderManagerWorkerThread.cpp +++ /dev/null @@ -1,249 +0,0 @@ -// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. -// SPDX-License-Identifier: Apache-2.0 - -#include "DataSenderManagerWorkerThread.h" -#include "ICollectionScheme.h" -#include "LoggingModule.h" -#include "TraceModule.h" - -using namespace Aws::IoTFleetWise::DataSender; - -const uint32_t DataSenderManagerWorkerThread::MAX_NUMBER_OF_SIGNAL_TO_TRACE_LOG = 6; - -DataSenderManagerWorkerThread::DataSenderManagerWorkerThread( CANInterfaceIDTranslator &canIDTranslator, - std::shared_ptr connectivityModule, - std::shared_ptr mqttSender, - std::shared_ptr payloadManager, - unsigned maxMessageCount, - uint64_t persistencyUploadRetryInterval ) - : mDataSenderManager( std::move( mqttSender ), std::move( payloadManager ), canIDTranslator, maxMessageCount ) - , mConnectivityModule( std::move( connectivityModule ) ) -{ - mPersistencyUploadRetryIntervalMs = persistencyUploadRetryInterval; -} - -bool -DataSenderManagerWorkerThread::init( const std::shared_ptr &collectedDataQueue ) -{ - mCollectedDataQueue = collectedDataQueue; - return true; -} - -bool -DataSenderManagerWorkerThread::start() -{ - // Prevent concurrent stop/init - std::lock_guard lock( mThreadMutex ); - mShouldStop.store( false ); - if ( !mThread.create( doWork, this ) ) - { - FWE_LOG_TRACE( "Data Sender Manager Thread failed to start" ); - } - else - { - FWE_LOG_TRACE( "Data Sender Manager Thread started" ); - mThread.setThreadName( "fwDSDataSendMng" ); - } - - return mThread.isActive() && mThread.isValid(); -} - -bool -DataSenderManagerWorkerThread::stop() -{ - // It might take several seconds to finish all running S3 async PutObject requests - if ( ( !mThread.isValid() ) || ( !mThread.isActive() ) ) - { - return true; - } - std::lock_guard lock( mThreadMutex ); - mShouldStop.store( true, std::memory_order_relaxed ); - FWE_LOG_TRACE( "Request stop" ); - mWait.notify(); - mThread.release(); - FWE_LOG_TRACE( "Stop finished" ); - mShouldStop.store( false, std::memory_order_relaxed ); - return !mThread.isActive(); -} - -bool -DataSenderManagerWorkerThread::shouldStop() const -{ - return mShouldStop.load( std::memory_order_relaxed ); -} - -void -DataSenderManagerWorkerThread::doWork( void *data ) -{ - DataSenderManagerWorkerThread *sender = static_cast( data ); - - bool uploadedPersistedDataOnce = false; - - while ( !sender->shouldStop() ) - { - sender->mTimer.reset(); - uint64_t minTimeToWaitMs = UINT64_MAX; - - // Check if new collection scheme is available to update available senders - if ( sender->mUpdatedCollectionSchemeListAvailable ) - { - std::lock_guard lock( sender->mActiveCollectionSchemesMutex ); - sender->mUpdatedCollectionSchemeListAvailable = false; - } - if ( sender->mPersistencyUploadRetryIntervalMs > 0 ) - { - uint64_t timeToWaitMs = - sender->mPersistencyUploadRetryIntervalMs - - std::min( static_cast( sender->mRetrySendingPersistedDataTimer.getElapsedMs().count() ), - sender->mPersistencyUploadRetryIntervalMs ); - minTimeToWaitMs = std::min( minTimeToWaitMs, timeToWaitMs ); - } - - if ( minTimeToWaitMs < UINT64_MAX ) - { - FWE_LOG_TRACE( "Waiting for: " + std::to_string( minTimeToWaitMs ) + " ms. Persistency " + - std::to_string( sender->mPersistencyUploadRetryIntervalMs ) + " configured, " + - std::to_string( sender->mRetrySendingPersistedDataTimer.getElapsedMs().count() ) + - " timer." ); - sender->mWait.wait( static_cast( minTimeToWaitMs ) ); - } - else - { - sender->mWait.wait( Platform::Linux::Signal::WaitWithPredicate ); - auto elapsedTimeMs = sender->mTimer.getElapsedMs().count(); - FWE_LOG_TRACE( "Event arrived. Time elapsed waiting for the event: " + std::to_string( elapsedTimeMs ) + - " ms" ); - } - - // Dequeues the collected data queue and sends the data to cloud - auto consumedElements = sender->mCollectedDataQueue->consume_all( - [&]( const TriggeredCollectionSchemeDataPtr triggeredCollectionSchemeDataPtr ) { - // Only used for trace logging - std::string firstSignalValues = "["; - uint32_t signalPrintCounter = 0; - std::string firstSignalTimestamp; - for ( auto &s : triggeredCollectionSchemeDataPtr->signals ) - { - if ( firstSignalTimestamp.empty() ) - { - firstSignalTimestamp = " first signal timestamp: " + std::to_string( s.receiveTime ); - } - signalPrintCounter++; - if ( signalPrintCounter > MAX_NUMBER_OF_SIGNAL_TO_TRACE_LOG ) - { - firstSignalValues += " ..."; - break; - } - auto signalValue = s.getValue(); - firstSignalValues += std::to_string( s.signalID ) + ":"; - switch ( signalValue.getType() ) - { - case SignalType::UINT8: - firstSignalValues += std::to_string( signalValue.value.uint8Val ) + ","; - break; - case SignalType::INT8: - firstSignalValues += std::to_string( signalValue.value.int8Val ) + ","; - break; - case SignalType::UINT16: - firstSignalValues += std::to_string( signalValue.value.uint16Val ) + ","; - break; - case SignalType::INT16: - firstSignalValues += std::to_string( signalValue.value.int16Val ) + ","; - break; - case SignalType::UINT32: - firstSignalValues += std::to_string( signalValue.value.uint32Val ) + ","; - break; - case SignalType::INT32: - firstSignalValues += std::to_string( signalValue.value.int32Val ) + ","; - break; - case SignalType::UINT64: - firstSignalValues += std::to_string( signalValue.value.uint64Val ) + ","; - break; - case SignalType::INT64: - firstSignalValues += std::to_string( signalValue.value.int64Val ) + ","; - break; - case SignalType::FLOAT: - firstSignalValues += std::to_string( signalValue.value.floatVal ) + ","; - break; - case SignalType::DOUBLE: - firstSignalValues += std::to_string( signalValue.value.doubleVal ) + ","; - break; - case SignalType::BOOLEAN: - firstSignalValues += std::to_string( static_cast( signalValue.value.boolVal ) ) + ","; - break; - } - } - firstSignalValues += "]"; - // Avoid invoking Data Collection Sender if there is nothing to send. - if ( triggeredCollectionSchemeDataPtr->signals.empty() && - triggeredCollectionSchemeDataPtr->canFrames.empty() && - triggeredCollectionSchemeDataPtr->mDTCInfo.mDTCCodes.empty() && - ( !triggeredCollectionSchemeDataPtr->mGeohashInfo.hasItems() ) ) - { - FWE_LOG_INFO( - "The trigger for Campaign: " + triggeredCollectionSchemeDataPtr->metadata.collectionSchemeID + - " activated eventID: " + std::to_string( triggeredCollectionSchemeDataPtr->eventID ) + - " but no data is available to ingest" ); - } - else - { - FWE_LOG_INFO( - "FWE data ready to send with eventID " + - std::to_string( triggeredCollectionSchemeDataPtr->eventID ) + " from " + - triggeredCollectionSchemeDataPtr->metadata.collectionSchemeID + - " Signals:" + std::to_string( triggeredCollectionSchemeDataPtr->signals.size() ) + " " + - firstSignalValues + firstSignalTimestamp + - " trigger timestamp: " + std::to_string( triggeredCollectionSchemeDataPtr->triggerTime ) + - " raw CAN frames:" + std::to_string( triggeredCollectionSchemeDataPtr->canFrames.size() ) + - " DTCs:" + std::to_string( triggeredCollectionSchemeDataPtr->mDTCInfo.mDTCCodes.size() ) + - " Geohash:" + triggeredCollectionSchemeDataPtr->mGeohashInfo.mGeohashString ); - sender->mDataSenderManager.processCollectedData( triggeredCollectionSchemeDataPtr ); - } - } ); - TraceModule::get().setVariable( TraceVariable::QUEUE_INSPECTION_TO_SENDER, consumedElements ); - if ( ( !uploadedPersistedDataOnce ) || - ( ( sender->mPersistencyUploadRetryIntervalMs > 0 ) && - ( static_cast( sender->mRetrySendingPersistedDataTimer.getElapsedMs().count() ) >= - sender->mPersistencyUploadRetryIntervalMs ) ) ) - { - sender->mRetrySendingPersistedDataTimer.reset(); - if ( sender->mConnectivityModule->isAlive() ) - { - sender->mDataSenderManager.checkAndSendRetrievedData(); - uploadedPersistedDataOnce = true; - } - } - } -} - -bool -DataSenderManagerWorkerThread::isAlive() -{ - return mThread.isValid() && mThread.isActive(); -} - -void -DataSenderManagerWorkerThread::onDataReadyToPublish() -{ - mWait.notify(); -} - -void -DataSenderManagerWorkerThread::onChangeCollectionSchemeList( - const std::shared_ptr &activeCollectionSchemes ) -{ - std::lock_guard lock( mActiveCollectionSchemesMutex ); - mActiveCollectionSchemes = activeCollectionSchemes; - mUpdatedCollectionSchemeListAvailable = true; - FWE_LOG_TRACE( "New list of active collections schemes was handed over" ); - mWait.notify(); -} - -DataSenderManagerWorkerThread::~DataSenderManagerWorkerThread() -{ - // To make sure the thread stops during teardown of tests. - if ( isAlive() ) - { - stop(); - } -} diff --git a/src/datamanagement/datasender/test/.clang-tidy b/src/datamanagement/datasender/test/.clang-tidy deleted file mode 100644 index 48f16d51..00000000 --- a/src/datamanagement/datasender/test/.clang-tidy +++ /dev/null @@ -1,2 +0,0 @@ -# Enable only one dummy check -Checks: "-*,llvm-twine-local" diff --git a/src/datamanagement/datasender/test/dm-collection-scheme-example.json b/src/datamanagement/datasender/test/dm-collection-scheme-example.json deleted file mode 100644 index bd26a687..00000000 --- a/src/datamanagement/datasender/test/dm-collection-scheme-example.json +++ /dev/null @@ -1,130 +0,0 @@ -{ - "version": "1.0", - "collectionSchemeID": "arn::testCollectionScheme", - "eventType": "heartbeat", - - "eventTriggers": [ - { - "triggerType": "timepoint", - "valuePredicate": { - "condition": "every", - "value": 10 - } - }, - { - "triggerType": "signalvalue", - "valuePredicate": { - "condition": "less", - "value": 1, - "signalID": 10, - "messageID": 123 - } - }, - { - "triggerType": "signalvalue", - "valuePredicate": { - "condition": "bigger", - "value": 1, - "signalID": 30, - "messageID": 456 - } - } - ], - "eventMessages": [ - { - "messageID": 123, - "sizeInBytes": 8, - "signals": [ - { - "signalID": 10, - "isBigEndian": false, - "isSigned": true, - "firstBitPosition": 8, - "sizeInBits": 16, - "offset": 0.0, - "factor": 0.0078125 - }, - { - "signalID": 20, - "isBigEndian": true, - "isSigned": false, - "firstBitPosition": 24, - "sizeInBits": 16, - "offset": 0.0, - "factor": 0.00390625 - } - ] - }, - { - "messageID": 456, - "sizeInBytes": 4, - "signals": [ - { - "signalID": 30, - "isBigEndian": true, - "isSigned": true, - "firstBitPosition": 8, - "sizeInBits": 16, - "offset": 0.0, - "factor": 100 - }, - { - "signalID": 40, - "isBigEndian": true, - "isSigned": true, - "firstBitPosition": 24, - "sizeInBits": 16, - "offset": 0.0, - "factor": 200 - } - ] - }, - { - "messageID": 678, - "sizeInBytes": 4, - "isMultiplexed": true, - "signals": [ - { - "signalID": 30, - "isBigEndian": true, - "isSigned": false, - "firstBitPosition": 8, - "sizeInBits": 24, - "offset": 0.0, - "factor": 1.0, - "multiplexerValue": 30 - }, - { - "signalID": 40, - "isBigEndian": true, - "isSigned": false, - "firstBitPosition": 8, - "sizeInBits": 16, - "offset": 0.0, - "factor": 1.0, - "multiplexerValue": 40 - }, - { - "signalID": 50, - "isBigEndian": true, - "isSigned": false, - "firstBitPosition": 24, - "sizeInBits": 8, - "offset": 0.0, - "factor": 1.0, - "multiplexerValue": 40 - }, - { - "signalID": 60, - "isBigEndian": true, - "isSigned": false, - "firstBitPosition": 0, - "sizeInBits": 8, - "offset": 0.0, - "factor": 1.0, - "isMultiplexer": true - } - ] - } - ] -} diff --git a/src/datamanagement/datasender/test/valgrind.supp b/src/datamanagement/datasender/test/valgrind.supp deleted file mode 100644 index 17d9a8d5..00000000 --- a/src/datamanagement/datasender/test/valgrind.supp +++ /dev/null @@ -1,32 +0,0 @@ -{ - boost::lockfree::do_push - Memcheck:Cond - ... - fun:_ZN5boost8lockfree5queue* - ... -} - -{ - - Memcheck:Param - write(buf) - ... - fun:sem_open - ... -} - -{ - fastrptps_bug_remove_persistence_guid - Memcheck:Addr2 - ... - fun:*remove_persistence_guid* - ... -} - -{ - fastrptps_bug_add_persistence_guid - Memcheck:Addr2 - ... - fun:*add_persistence_guid* - ... -} diff --git a/src/datamanagement/types/CMakeLists.txt b/src/datamanagement/types/CMakeLists.txt deleted file mode 100644 index 6ea3d5ef..00000000 --- a/src/datamanagement/types/CMakeLists.txt +++ /dev/null @@ -1,74 +0,0 @@ -# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. -set(libraryTargetName iotfleetwise.datamanagement.types) - -# The alias name is what other targets will use as a dependency -set(libraryAliasName IoTFleetWise::DataManagementTypes) - -set(SRCS - src/Geohash.cpp -) - -add_library( - ${libraryTargetName} - # STATIC or SHARED left out to depend on BUILD_SHARED_LIBS - ${SRCS} -) - -target_include_directories(${libraryTargetName} PUBLIC include) - -target_link_libraries( - ${libraryTargetName} - IoTFleetWise::Platform::Linux - IoTFleetWise::Vehiclenetwork -) - -add_library(${libraryAliasName} ALIAS ${libraryTargetName}) - -### Install ### - -install(TARGETS ${libraryTargetName} DESTINATION lib) -install( - FILES - include/CollectionInspectionAPITypes.h - include/CANDataTypes.h - include/EventTypes.h - include/Geohash.h - include/GeohashInfo.h - include/MessageTypes.h - include/OBDDataTypes.h - include/SignalTypes.h - DESTINATION - include) - -### Tests ### -# This is a list of tests that will compiled. -# If adding a test, simply add the source file here -if(${BUILD_TESTING}) - message(STATUS "Building tests for ${libraryTargetName}") - - set( - testSources - test/GeohashTest.cpp - ) - - # Add the executable targets - foreach(testSource ${testSources}) - # Need a name for each exec so use filename w/o extension - get_filename_component(testName ${testSource} NAME_WE) - - add_executable(${testName} ${testSource}) - # Link to the project library and testing library main - target_link_libraries( - ${testName} - PRIVATE - ${libraryTargetName} - IoTFleetWise::TestingSupport - ) - add_test(NAME ${testName} COMMAND ${testName} --gtest_output=xml:report-${testName}.xml) - add_valgrind_test(${testName}) - install(TARGETS ${testName} RUNTIME DESTINATION bin/tests) - - endforeach() -else() - message(STATUS "Testing not enabled for ${libraryTargetName}") -endif() diff --git a/src/datamanagement/types/test/.clang-tidy b/src/datamanagement/types/test/.clang-tidy deleted file mode 100644 index 48f16d51..00000000 --- a/src/datamanagement/types/test/.clang-tidy +++ /dev/null @@ -1,2 +0,0 @@ -# Enable only one dummy check -Checks: "-*,llvm-twine-local" diff --git a/src/datamanagement/types/test/valgrind.supp b/src/datamanagement/types/test/valgrind.supp deleted file mode 100644 index 00c906ed..00000000 --- a/src/datamanagement/types/test/valgrind.supp +++ /dev/null @@ -1,8 +0,0 @@ -{ - __libc_csu_init - Memcheck:Leak - match-leak-kinds: reachable - ... - fun:__libc_csu_init - ... -} diff --git a/src/executionmanagement/CMakeLists.txt b/src/executionmanagement/CMakeLists.txt deleted file mode 100644 index 43d76d2a..00000000 --- a/src/executionmanagement/CMakeLists.txt +++ /dev/null @@ -1,129 +0,0 @@ -# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. - -set(libraryTargetName iotfleetwise.executionmanagement) - -# The alias name is what other targets will use as a dependency -set(libraryAliasName IoTFleetWise::Executionmanagement) - -add_library( - ${libraryTargetName} - # STATIC or SHARED left out to depend on BUILD_SHARED_LIBS - src/IoTFleetWiseConfig.cpp - src/IoTFleetWiseEngine.cpp - ${CMAKE_CURRENT_BINARY_DIR}/IoTFleetWiseVersion.cpp -) - -target_include_directories(${libraryTargetName} PUBLIC include) - -target_link_libraries( - ${libraryTargetName} - IoTFleetWise::Vehiclenetwork - IoTFleetWise::DataManager - IoTFleetWise::DataCollection - IoTFleetWise::DataInspection - IoTFleetWise::DataDecoding - IoTFleetWise::DataSender - IoTFleetWise::Platform::Linux - IoTFleetWise::OffboardConnectivityAwsIot - $<$:IoTFleetWise::CustomDataSource> -) - -add_library(${libraryAliasName} ALIAS ${libraryTargetName}) - -### FWE Executable ### - -if(FWE_BUILD_EXECUTABLE) - add_executable(aws-iot-fleetwise-edge src/main.cpp) - target_link_libraries( - aws-iot-fleetwise-edge - ${libraryTargetName} - IoTFleetWise::Platform::Linux - -Xlinker - -Map=aws-iot-fleetwise-edge.map - ) -endif() - -if(FWE_BUILD_ANDROID_SHARED_LIBRARY) - add_library(aws-iot-fleetwise-edge SHARED src/android_shared_library.cpp) - target_link_libraries( - aws-iot-fleetwise-edge - ${libraryTargetName} - IoTFleetWise::Platform::Linux - log - android - -Xlinker - -Map=aws-iot-fleetwise-edge.map - ) -endif() - -### Version ### - -execute_process(COMMAND git rev-parse HEAD - OUTPUT_VARIABLE VERSION_GIT_SHA - ERROR_QUIET) - -execute_process(COMMAND git describe --tags --abbrev=0 - OUTPUT_VARIABLE VERSION_GIT_TAG - ERROR_QUIET) - -string(STRIP "${VERSION_GIT_SHA}" VERSION_GIT_SHA) - -string(STRIP "${VERSION_GIT_TAG}" VERSION_GIT_TAG) - -string(TIMESTAMP VERSION_CURRENT_TIME "%Y-%m-%d %H:%M:%S" UTC) - -configure_file(src/IoTFleetWiseVersion.cpp.in ${CMAKE_CURRENT_BINARY_DIR}/IoTFleetWiseVersion.cpp) - -### Install ### - -install(TARGETS ${libraryTargetName} DESTINATION lib) - -install( - FILES - include/IoTFleetWiseConfig.h - include/IoTFleetWiseEngine.h - DESTINATION include -) - -### Tests ### - -if(${BUILD_TESTING}) - message(STATUS "Building tests for ${libraryTargetName}") - - - file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/test/em-example-config.json - DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) - - file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/test/em-example-config-corrupt.json - DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) - - file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/test/em-example-config-inline-creds.json - DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) - - set( - testSources - test/IoTFleetWiseConfigTest.cpp - test/IoTFleetWiseEngineTest.cpp - ) - # Add the executable targets - foreach(testSource ${testSources}) - # Need a name for each exec so use filename w/o extension - get_filename_component(testName ${testSource} NAME_WE) - - add_executable(${testName} ${testSource}) - - # Link to the project library and testing library main - target_link_libraries( - ${testName} - PRIVATE - ${libraryTargetName} - IoTFleetWise::TestingSupport - ) - - add_unit_test(${testName}) - add_valgrind_test(${testName}) - install(TARGETS ${testName} RUNTIME DESTINATION bin/tests) - - endforeach() - -endif() diff --git a/src/executionmanagement/test/.clang-tidy b/src/executionmanagement/test/.clang-tidy deleted file mode 100644 index 48f16d51..00000000 --- a/src/executionmanagement/test/.clang-tidy +++ /dev/null @@ -1,2 +0,0 @@ -# Enable only one dummy check -Checks: "-*,llvm-twine-local" diff --git a/src/executionmanagement/test/valgrind.supp b/src/executionmanagement/test/valgrind.supp deleted file mode 100644 index eb4305b4..00000000 --- a/src/executionmanagement/test/valgrind.supp +++ /dev/null @@ -1,42 +0,0 @@ -{ - aws_io_library_init - Memcheck:Leak - match-leak-kinds: definite,reachable - ... - fun:aws_io_library_init - ... -} -{ - aws_http_library_init - Memcheck:Leak - match-leak-kinds: definite,reachable - ... - fun:aws_http_library_init - ... -} -{ - sem_open glibc false positive - Memcheck:Param - write(buf) - ... - fun:sem_open - ... -} - -{ - aws_mqtt_library_init - Memcheck:Leak - match-leak-kinds: definite,reachable - ... - fun:aws_mqtt_library_init - ... -} - -{ - __libc_csu_init - Memcheck:Leak - match-leak-kinds: reachable - ... - fun:__libc_csu_init - ... -} diff --git a/src/executionmanagement/src/main.cpp b/src/main.cpp similarity index 89% rename from src/executionmanagement/src/main.cpp rename to src/main.cpp index 6eae0af7..8cbf650c 100644 --- a/src/executionmanagement/src/main.cpp +++ b/src/main.cpp @@ -1,7 +1,6 @@ // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 -// Includes #include "ConsoleLogger.h" #include "IoTFleetWiseConfig.h" #include "IoTFleetWiseEngine.h" @@ -9,9 +8,11 @@ #include "LogLevel.h" #include #include +#include #include - -using namespace Aws::IoTFleetWise::ExecutionManagement; +#include +#include +#include // coverity[autosar_cpp14_a2_11_1_violation] static volatile sig_atomic_t mSignal = 0; // volatile has to be used since it will be modified by a signal handler, @@ -40,11 +41,11 @@ printVersion() static void configureLogging( const Json::Value &config ) { - Aws::IoTFleetWise::Platform::Linux::LogLevel logLevel = Aws::IoTFleetWise::Platform::Linux::LogLevel::Trace; + auto logLevel = Aws::IoTFleetWise::LogLevel::Trace; stringToLogLevel( config["staticConfig"]["internalParameters"]["systemWideLogLevel"].asString(), logLevel ); - gSystemWideLogLevel = logLevel; + Aws::IoTFleetWise::gSystemWideLogLevel = logLevel; - auto logColorOption = Aws::IoTFleetWise::Platform::Linux::LogColorOption::Auto; + auto logColorOption = Aws::IoTFleetWise::LogColorOption::Auto; if ( config["staticConfig"]["internalParameters"].isMember( "logColor" ) ) { std::string logColorConfig = config["staticConfig"]["internalParameters"]["logColor"].asString(); @@ -53,7 +54,7 @@ configureLogging( const Json::Value &config ) std::cout << "Invalid logColor config: " << logColorConfig << std::endl; } } - gLogColorOption = logColorOption; + Aws::IoTFleetWise::gLogColorOption = logColorOption; } static int @@ -91,7 +92,7 @@ main( int argc, char *argv[] ) signal( SIGUSR1, signalHandler ); std::string configFilename = argv[1]; Json::Value config; - if ( !IoTFleetWiseConfig::read( configFilename, config ) ) + if ( !Aws::IoTFleetWise::IoTFleetWiseConfig::read( configFilename, config ) ) { std::cout << "Failed to read config file: " + configFilename << std::endl; return EXIT_FAILURE; @@ -99,7 +100,7 @@ main( int argc, char *argv[] ) // Set system wide log level configureLogging( config ); - IoTFleetWiseEngine engine; + Aws::IoTFleetWise::IoTFleetWiseEngine engine; // Connect the Engine if ( engine.connect( config ) && engine.start() ) { diff --git a/src/offboardconnectivity/CMakeLists.txt b/src/offboardconnectivity/CMakeLists.txt deleted file mode 100644 index ac9b73e1..00000000 --- a/src/offboardconnectivity/CMakeLists.txt +++ /dev/null @@ -1,2 +0,0 @@ -add_subdirectory(implementation/aws/) -add_subdirectory(api) diff --git a/src/offboardconnectivity/api/CMakeLists.txt b/src/offboardconnectivity/api/CMakeLists.txt deleted file mode 100644 index a1c2f734..00000000 --- a/src/offboardconnectivity/api/CMakeLists.txt +++ /dev/null @@ -1,13 +0,0 @@ -# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. - -set(libraryTargetName iotfleetwise.OffboardConnectivity) - -set(libraryAliasName IoTFleetWise::OffboardConnectivity) - -add_library(${libraryTargetName} INTERFACE) - -target_include_directories(${libraryTargetName} INTERFACE include) - -target_link_libraries(${libraryTargetName} INTERFACE IoTFleetWise::Platform::Linux) - -add_library(${libraryAliasName} ALIAS ${libraryTargetName}) diff --git a/src/offboardconnectivity/implementation/aws/CMakeLists.txt b/src/offboardconnectivity/implementation/aws/CMakeLists.txt deleted file mode 100644 index fac9b08f..00000000 --- a/src/offboardconnectivity/implementation/aws/CMakeLists.txt +++ /dev/null @@ -1,24 +0,0 @@ -# Extra libraries are required to statically link with the AWS SDK. These are not always found by CMake, hence: -# - When FWE_STATIC_LINK is ON and FWE_AWS_SDK_EXTRA_LIBS is ON, automatically find the standard libraries: libcurl, libssl, libcrypto, libz -# - When FWE_AWS_SDK_EXTRA_LIBS is a list of libs, use those -# - When FWE_AWS_SDK_EXTRA_LIBS is OFF, don't link any extra libs -if(FWE_AWS_SDK_EXTRA_LIBS STREQUAL "ON") - if(NOT FWE_STATIC_LINK) - set(FWE_AWS_SDK_EXTRA_LIBS "") - else() - set(OLD_CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_FIND_LIBRARY_SUFFIXES}) - set(CMAKE_FIND_LIBRARY_SUFFIXES ".a") - find_library(CURL_LIBRARY NAMES curl) - find_library(OPENSSL_SSL_LIBRARY NAMES ssl) - find_library(OPENSSL_CRYPTO_LIBRARY NAMES crypto) - find_package(ZLIB REQUIRED) - set(FWE_AWS_SDK_EXTRA_LIBS "${CURL_LIBRARY} ${OPENSSL_SSL_LIBRARY} ${OPENSSL_CRYPTO_LIBRARY} ZLIB::ZLIB") - set(CMAKE_FIND_LIBRARY_SUFFIXES ${OLD_CMAKE_FIND_LIBRARY_SUFFIXES}) - endif() -elseif(FWE_AWS_SDK_EXTRA_LIBS STREQUAL "OFF") - set(FWE_AWS_SDK_EXTRA_LIBS "") -endif() -separate_arguments(FWE_AWS_SDK_EXTRA_LIBS) - -add_subdirectory(bootstrap) -add_subdirectory(iotcpp) diff --git a/src/offboardconnectivity/implementation/aws/bootstrap/CMakeLists.txt b/src/offboardconnectivity/implementation/aws/bootstrap/CMakeLists.txt deleted file mode 100644 index 3e8452c1..00000000 --- a/src/offboardconnectivity/implementation/aws/bootstrap/CMakeLists.txt +++ /dev/null @@ -1,33 +0,0 @@ -# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. - -set(libraryTargetName iotfleetwise.offboardconnectivityawsbootstrap) - -# The alias name is what other targets will use as a dependency -set(libraryAliasName IoTFleetWise::OffboardConnectivityAwsBootstrap) - -set(librarySrc - src/AwsBootstrap.cpp - src/AwsSDKMemoryManager.cpp -) - -add_library( - ${libraryTargetName} - # STATIC or SHARED left out to depend on BUILD_SHARED_LIBS - ${librarySrc} -) - -set(OLD_BUILD_SHARED_LIBS ${BUILD_SHARED_LIBS}) -set(BUILD_SHARED_LIBS ${FWE_AWS_SDK_SHARED_LIBS}) -find_package(AWSSDK REQUIRED COMPONENTS core) -set(BUILD_SHARED_LIBS ${OLD_BUILD_SHARED_LIBS}) - -target_include_directories(${libraryTargetName} PUBLIC include) - -target_link_libraries( - ${libraryTargetName} - IoTFleetWise::Platform::Linux - ${AWSSDK_LINK_LIBRARIES} - ${FWE_AWS_SDK_EXTRA_LIBS} -) - -add_library(${libraryAliasName} ALIAS ${libraryTargetName}) diff --git a/src/offboardconnectivity/implementation/aws/iotcpp/CMakeLists.txt b/src/offboardconnectivity/implementation/aws/iotcpp/CMakeLists.txt deleted file mode 100644 index 5f873682..00000000 --- a/src/offboardconnectivity/implementation/aws/iotcpp/CMakeLists.txt +++ /dev/null @@ -1,135 +0,0 @@ -# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. - -set(libraryTargetName iotfleetwise.offboardconnectivityawsiot) - -# The alias name is what other targets will use as a dependency -set(libraryAliasName IoTFleetWise::OffboardConnectivityAwsIot) -if(FWE_FEATURE_GREENGRASSV2) - set(EXTRA_SOURCE_FILES - ${EXTRA_SOURCE_FILES} - src/AwsGGConnectivityModule.cpp - src/AwsGGChannel.cpp) - find_package(GreengrassIpc-cpp REQUIRED) - set(GG_IPC_LIB_NAME AWS::GreengrassIpc-cpp) -endif() - -set(librarySrc - src/AwsIotChannel.cpp - src/AwsIotConnectivityModule.cpp - ${EXTRA_SOURCE_FILES} - src/RetryThread.cpp - src/PayloadManager.cpp - src/RemoteProfiler.cpp) - -add_library( - ${libraryTargetName} - # STATIC or SHARED left out to depend on BUILD_SHARED_LIBS - ${librarySrc} -) - -find_path(JSONCPP_INCLUDE_DIR "json/json.h" PATH_SUFFIXES "jsoncpp") -find_library(JSONCPP_LIBRARY NAMES jsoncpp) -find_package(aws-crt-cpp REQUIRED) - - -set(OLD_BUILD_SHARED_LIBS ${BUILD_SHARED_LIBS}) -set(BUILD_SHARED_LIBS ${FWE_AWS_SDK_SHARED_LIBS}) -find_package(AWSSDK REQUIRED COMPONENTS iot) -set(BUILD_SHARED_LIBS ${OLD_BUILD_SHARED_LIBS}) - -message(STATUS "Connectivity json include ${JSONCPP_INCLUDE_DIR}") -target_include_directories(${libraryTargetName} PUBLIC include -${JSONCPP_INCLUDE_DIR}) - - -target_link_libraries( - ${libraryTargetName} - IoTFleetWise::OffboardConnectivityAwsBootstrap - IoTFleetWise::OffboardConnectivity - IoTFleetWise::Platform::Linux - AWS::aws-crt-cpp - ${GG_IPC_LIB_NAME} - ${AWSSDK_LINK_LIBRARIES} - ${SNAPPY_LIBRARIES} - ${JSONCPP_LIBRARY} - ${FWE_AWS_SDK_EXTRA_LIBS} -) - - -add_library(${libraryAliasName} ALIAS ${libraryTargetName}) - -### Tests ### - -if(${BUILD_TESTING}) - message(STATUS "Building tests for ${libraryTargetName}") - - find_library(GMOCK_LIB - NAMES - gmock) - - find_library(GMOCK_MAIN_LIBRARY - NAMES - gmock_main) - - set(testName OffboardConnectivityAwsIotTest) - add_executable(${testName} - test/src/AwsIotConnectivityModuleTest.cpp - test/src/AwsIotSdkMock.cpp - test/src/MqttClient.cpp - ${librarySrc}) - - add_unit_test(${testName}) - add_valgrind_test(${testName}) - - target_link_libraries( - ${testName} - PRIVATE - IoTFleetWise::OffboardConnectivityAwsBootstrap - IoTFleetWise::OffboardConnectivity - IoTFleetWise::TestingSupport - AWS::aws-crt-cpp - ${GG_IPC_LIB_NAME} - ${GMOCK_MAIN_LIBRARY} - ${GMOCK_LIB} - ${SNAPPY_LIBRARIES} - ${JSONCPP_LIBRARY} - ) - - target_include_directories(${testName} PRIVATE - include - test/include - test/include/aws-iot-cpp-sdk-mock - ${JSONCPP_INCLUDE_DIR}) - - install(TARGETS ${testName} RUNTIME DESTINATION bin/tests) - - set( - testSources - test/src/PayloadManagerTest.cpp - test/src/RemoteProfilerTest.cpp - ) - - # Add the executable targets - foreach(testSource ${testSources}) - # Need a name for each exec so use filename w/o extension - get_filename_component(testName ${testSource} NAME_WE) - add_executable(${testName} ${testSource}) - - add_unit_test(${testName}) - add_valgrind_test(${testName}) - - # Link to the project library and testing library main - target_link_libraries( - ${testName} - PRIVATE - ${libraryTargetName} - IoTFleetWise::TestingSupport - IoTFleetWise::Proto - ${SNAPPY_LIBRARIES} - ) - - install(TARGETS ${testName} RUNTIME DESTINATION bin/tests) - - endforeach() - -endif() diff --git a/src/offboardconnectivity/implementation/aws/iotcpp/test/include/AwsIotSdkMock.h b/src/offboardconnectivity/implementation/aws/iotcpp/test/include/AwsIotSdkMock.h deleted file mode 100644 index b607d8de..00000000 --- a/src/offboardconnectivity/implementation/aws/iotcpp/test/include/AwsIotSdkMock.h +++ /dev/null @@ -1,132 +0,0 @@ -#pragma once -#include "aws/crt/Types.h" -#include "aws/iot/MqttClient.h" -#include // Brings in gMock. -namespace Aws -{ -namespace IoTFleetWise -{ -namespace OffboardConnectivityAwsIot -{ -namespace Testing -{ - -class AwsIotSdkMock -{ -public: - MOCK_METHOD( (const char *), aws_error_debug_str, (int)); - MOCK_METHOD( (void), aws_byte_buf_clean_up, ( struct aws_byte_buf * buf ) ); - MOCK_METHOD( (const char *), ErrorDebugString, (int)); - MOCK_METHOD( (struct aws_allocator *), DefaultAllocator, () ); - MOCK_METHOD( ( struct aws_byte_buf ), - ByteBufNewCopy, - ( struct aws_allocator * alloc, const uint8_t *array, size_t len ) ); - MOCK_METHOD( ( struct aws_byte_cursor ), ByteCursorFromCString, ( const char *str ) ); - MOCK_METHOD( ( Aws::Crt::String ), UUIDToString, () ); -}; - -using Aws::Crt::Mqtt::MqttConnection; -class MqttConnectionMock : public Aws::Crt::Mqtt::MqttConnection -{ -public: - MOCK_METHOD( ( uint16_t ), - Publish, - ( const char *topic, - aws_mqtt_qos qos, - bool retain, - const struct aws_byte_buf &payload, - MqttConnection::OnOperationCompleteHandler &&onOpComplete ), - ( noexcept ) ); - MOCK_METHOD( ( uint16_t ), - Unsubscribe, - ( const char *topicFilter, MqttConnection::OnOperationCompleteHandler &&onOpComplete ), - ( noexcept, override ) ); - MOCK_METHOD( ( uint16_t ), - Subscribe, - ( const char *topicFilter, - aws_mqtt_qos qos, - MqttConnection::OnMessageReceivedHandler &&onMessage, - MqttConnection::OnSubAckHandler &&onSubAck ), - ( noexcept ) ); - MOCK_METHOD( (bool), Disconnect, (), ( noexcept ) ); - MOCK_METHOD( (bool), SetOnMessageHandler, ( MqttConnection::OnMessageReceivedHandler && onMessage ), ( noexcept ) ); - MOCK_METHOD( (int), LastError, (), ( const, noexcept ) ); - MOCK_METHOD( (bool), - Connect, - ( const char *clientId, bool cleanSession, uint16_t keepAliveTimeSecs, uint32_t pingTimeoutMs ), - ( noexcept ) ); -}; - -class MqttClientMock -{ -public: - MOCK_METHOD( (void), CONSTRUCTOR, ( Aws::Crt::Io::ClientBootstrap & bootstrap, Aws::Crt::Allocator *allocator ) ); - MOCK_METHOD( (std::shared_ptr), - NewConnection, - ( const Aws::Iot::MqttClientConnectionConfig &config ) ); - MOCK_METHOD( (bool), operatorBool, () ); - MOCK_METHOD( (int), LastError, () ); -}; - -class MqttClientConnectionConfigMock -{ -public: - MOCK_METHOD( (bool), operatorBool, () ); - MOCK_METHOD( (int), LastError, () ); -}; - -class MqttClientConnectionConfigBuilderMock -{ -public: - MOCK_METHOD( (void), WithEndpoint, ( const Aws::Crt::String &endpoint ) ); - MOCK_METHOD( (void), WithCertificateAuthority, ( const Crt::ByteCursor &rootCA ) ); - MOCK_METHOD( ( Aws::Iot::MqttClientConnectionConfig ), Build, () ); -}; - -class ClientBootstrapMock -{ -public: - MOCK_METHOD( (void), - CONSTRUCTOR, - ( Aws::Crt::Io::EventLoopGroup & elGroup, - Aws::Crt::Io::HostResolver &resolver, - Aws::Crt::Allocator *allocator ) ); - MOCK_METHOD( (bool), operatorBool, () ); - MOCK_METHOD( (int), LastError, () ); -}; - -class EventLoopGroupMock -{ -public: - MOCK_METHOD( (void), CONSTRUCTOR, ( uint16_t threadCount ) ); - MOCK_METHOD( (bool), operatorBool, () ); -}; - -// These objects are instantiated by the software under test (SUT) directly or copied (not by reference) -// So with link time injection only one mock exists and the linked test files in this test folder -// forwards to the single instance mocks. -AwsIotSdkMock *getSdkMock(); -void setSdkMock( AwsIotSdkMock *m ); - -MqttConnectionMock *getConMock(); -void setConMock( MqttConnectionMock *m ); - -MqttClientMock *getClientMock(); -void setClientMock( MqttClientMock *m ); - -MqttClientConnectionConfigMock *getConfMock(); -void setConfMock( MqttClientConnectionConfigMock *m ); - -MqttClientConnectionConfigBuilderMock *getConfBuilderMock(); -void setConfBuilderMock( MqttClientConnectionConfigBuilderMock *m ); - -ClientBootstrapMock *getClientBootstrapMock(); -void setClientBootstrapMock( ClientBootstrapMock *m ); - -EventLoopGroupMock *getEventLoopMock(); -void setEventLoopMock( EventLoopGroupMock *m ); - -} // namespace Testing -} // namespace OffboardConnectivityAwsIot -} // namespace IoTFleetWise -} // namespace Aws diff --git a/src/offboardconnectivity/implementation/aws/iotcpp/test/include/aws-iot-cpp-sdk-mock/aws/crt/Api.h b/src/offboardconnectivity/implementation/aws/iotcpp/test/include/aws-iot-cpp-sdk-mock/aws/crt/Api.h deleted file mode 100644 index 9e262b64..00000000 --- a/src/offboardconnectivity/implementation/aws/iotcpp/test/include/aws-iot-cpp-sdk-mock/aws/crt/Api.h +++ /dev/null @@ -1,137 +0,0 @@ -// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. -// SPDX-License-Identifier: Apache-2.0 - -#pragma once -#include "AwsIotSdkMock.h" -#include "Types.h" - -using namespace Aws::IoTFleetWise::OffboardConnectivityAwsIot::Testing; - -inline const char * -aws_error_debug_str( int err ) -{ - return getSdkMock()->aws_error_debug_str( err ); -} - -inline void -aws_byte_buf_clean_up( struct aws_byte_buf *buf ) -{ - getSdkMock()->aws_byte_buf_clean_up( buf ); -} - -namespace Aws -{ -namespace Crt -{ - -inline Allocator * -DefaultAllocator() noexcept -{ - return getSdkMock()->DefaultAllocator(); -} -inline ByteBuf -ByteBufNewCopy( Allocator *alloc, const uint8_t *array, size_t len ) -{ - return getSdkMock()->ByteBufNewCopy( alloc, array, len ); -} - -inline ByteCursor -ByteCursorFromCString( const char *str ) -{ - return getSdkMock()->ByteCursorFromCString( str ); -} -class ApiHandle -{ -public: - ApiHandle(){}; - ApiHandle( Allocator *allocator ) - { - mAllocator = allocator; - static_cast( allocator ); - }; - static Allocator * - getLatestAllocator() - { - return mAllocator; - } - -private: - static Allocator *mAllocator; -}; - -inline const char * -ErrorDebugString( int error ) noexcept -{ - return getSdkMock()->ErrorDebugString( error ); -} - -namespace Io -{ -class EventLoopGroup final -{ -public: - EventLoopGroup( uint16_t threadCount = 0 ) noexcept - { - getEventLoopMock()->CONSTRUCTOR( threadCount ); - } - ~EventLoopGroup(){}; - - operator bool() const - { - return getEventLoopMock()->operatorBool(); - } - int LastError() const; - -private: - int m_lastError{}; -}; -class HostResolver -{ -}; -class DefaultHostResolver final : public HostResolver -{ -public: - DefaultHostResolver( EventLoopGroup &, size_t, size_t, Allocator *a = nullptr ) noexcept - { - (void)a; - }; - ~DefaultHostResolver(){}; - DefaultHostResolver( const DefaultHostResolver & ) = delete; - DefaultHostResolver &operator=( const DefaultHostResolver & ) = delete; - DefaultHostResolver( DefaultHostResolver && ) = delete; - DefaultHostResolver &operator=( DefaultHostResolver && ) = delete; - operator bool() const noexcept - { - return false; - } - -private: -}; -class ClientBootstrap final -{ -public: - ClientBootstrap() = default; - ClientBootstrap( EventLoopGroup &elGroup, HostResolver &resolver, Allocator *allocator = NULL ) noexcept - { - getClientBootstrapMock()->CONSTRUCTOR( elGroup, resolver, allocator ); - } - ~ClientBootstrap(){}; - ClientBootstrap( const ClientBootstrap & ) = delete; - ClientBootstrap &operator=( const ClientBootstrap & ) = delete; - ClientBootstrap( ClientBootstrap && ) = delete; - ClientBootstrap &operator=( ClientBootstrap && ) = delete; - - operator bool() const noexcept - { - return getClientBootstrapMock()->operatorBool(); - } - - int - LastError() const noexcept - { - return getClientBootstrapMock()->LastError(); - } -}; -} // namespace Io -} // namespace Crt -} // namespace Aws diff --git a/src/offboardconnectivity/implementation/aws/iotcpp/test/include/aws-iot-cpp-sdk-mock/aws/crt/Types.h b/src/offboardconnectivity/implementation/aws/iotcpp/test/include/aws-iot-cpp-sdk-mock/aws/crt/Types.h deleted file mode 100644 index 26c1b072..00000000 --- a/src/offboardconnectivity/implementation/aws/iotcpp/test/include/aws-iot-cpp-sdk-mock/aws/crt/Types.h +++ /dev/null @@ -1,70 +0,0 @@ -// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. -// SPDX-License-Identifier: Apache-2.0 - -#include -#include -#include -#pragma once -struct aws_allocator -{ - void *( *mem_acquire )( struct aws_allocator *allocator, size_t size ); - void ( *mem_release )( struct aws_allocator *allocator, void *ptr ); - void *( *mem_realloc )( struct aws_allocator *allocator, void *oldptr, size_t oldsize, size_t newsize ); - void *( *mem_calloc )( struct aws_allocator *allocator, size_t num, size_t size ); - void *impl; -}; - -struct aws_byte_cursor -{ - /* do not reorder this, this struct lines up nicely with windows buffer structures--saving us allocations */ - size_t len; - uint8_t *ptr; -}; - -struct aws_byte_buf -{ - size_t len; - uint8_t *buffer; - size_t capacity; - struct aws_allocator *allocator; -}; - -enum class aws_mqtt_qos -{ - AWS_MQTT_QOS_AT_MOST_ONCE = 0x0, - AWS_MQTT_QOS_AT_LEAST_ONCE = 0x1, - AWS_MQTT_QOS_EXACTLY_ONCE = 0x2, - AWS_MQTT_QOS_FAILURE = 0x80, -}; -enum class aws_mqtt_connect_return_code -{ - AWS_MQTT_CONNECT_ACCEPTED, - AWS_MQTT_CONNECT_UNACCEPTABLE_PROTOCOL_VERSION, - AWS_MQTT_CONNECT_IDENTIFIER_REJECTED, - AWS_MQTT_CONNECT_SERVER_UNAVAILABLE, - AWS_MQTT_CONNECT_BAD_USERNAME_OR_PASSWORD, - AWS_MQTT_CONNECT_NOT_AUTHORIZED, -}; - -namespace Aws -{ -namespace Crt -{ - -using Allocator = struct aws_allocator; -using ByteBuf = struct aws_byte_buf; -using ByteCursor = struct aws_byte_cursor; -using String = std::string; -namespace Io -{ - -class ClientBootstrap; -class EventLoopGroup; -class HostResolver; -} // namespace Io -} // namespace Crt -namespace Iot -{ -class MqttClientConnectionConfig; -} -} // namespace Aws diff --git a/src/offboardconnectivity/implementation/aws/iotcpp/test/include/aws-iot-cpp-sdk-mock/aws/crt/UUID.h b/src/offboardconnectivity/implementation/aws/iotcpp/test/include/aws-iot-cpp-sdk-mock/aws/crt/UUID.h deleted file mode 100644 index 2f5403d7..00000000 --- a/src/offboardconnectivity/implementation/aws/iotcpp/test/include/aws-iot-cpp-sdk-mock/aws/crt/UUID.h +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. -// SPDX-License-Identifier: Apache-2.0 - -#pragma once - -#include "Api.h" -#include "AwsIotSdkMock.h" -#include -namespace Aws -{ -namespace Crt -{ - -class UUID final -{ -public: - inline UUID() noexcept {}; - - inline String - ToString() const - { - return getSdkMock()->UUIDToString(); - } -}; -} // namespace Crt -} // namespace Aws diff --git a/src/offboardconnectivity/implementation/aws/iotcpp/test/include/aws-iot-cpp-sdk-mock/aws/iot/MqttClient.h b/src/offboardconnectivity/implementation/aws/iotcpp/test/include/aws-iot-cpp-sdk-mock/aws/iot/MqttClient.h deleted file mode 100644 index 1269cbf7..00000000 --- a/src/offboardconnectivity/implementation/aws/iotcpp/test/include/aws-iot-cpp-sdk-mock/aws/iot/MqttClient.h +++ /dev/null @@ -1,119 +0,0 @@ -// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. -// SPDX-License-Identifier: Apache-2.0 - -#pragma once -#include "aws/crt/Types.h" -#include -#include -#include -namespace Aws -{ - -namespace Crt -{ - -namespace Mqtt -{ -using QOS = aws_mqtt_qos; -using String = std::string; -using ReturnCode = aws_mqtt_connect_return_code; -class MqttConnection; - -using OnConnectionInterruptedHandler = std::function; - -using OnConnectionResumedHandler = - std::function; - -using OnConnectionCompletedHandler = - std::function; - -using OnSubAckHandler = - std::function; - -using OnDisconnectHandler = std::function; - -class MqttConnection -{ -public: - using OnMessageReceivedHandler = std::function; - - using OnSubAckHandler = std::function; - - using OnOperationCompleteHandler = - std::function; - - virtual uint16_t Unsubscribe( const char *topicFilter, OnOperationCompleteHandler &&onOpComplete ) noexcept = 0; - - virtual uint16_t Subscribe( const char *topicFilter, - QOS qos, - OnMessageReceivedHandler &&onMessage, - OnSubAckHandler &&onSubAck ) noexcept = 0; - - virtual uint16_t Publish( const char *topic, - QOS qos, - bool retain, - const ByteBuf &payload, - OnOperationCompleteHandler &&onOpComplete ) noexcept = 0; - - virtual bool Connect( const char *clientId, - bool cleanSession, - uint16_t keepAliveTimeSecs = 0, - uint32_t pingTimeoutMs = 0 ) noexcept = 0; - - virtual bool Disconnect() noexcept = 0; - - virtual bool SetOnMessageHandler( OnMessageReceivedHandler &&onMessage ) noexcept = 0; - - OnConnectionInterruptedHandler OnConnectionInterrupted; - OnConnectionResumedHandler OnConnectionResumed; - OnConnectionCompletedHandler OnConnectionCompleted; - OnDisconnectHandler OnDisconnect; - - virtual int LastError() const noexcept = 0; -}; - -} // namespace Mqtt -} // namespace Crt - -namespace Iot -{ -class MqttClientConnectionConfig -{ -public: - virtual explicit operator bool() const noexcept; - virtual int LastError() const noexcept; -}; -class MqttClientConnectionConfigBuilder final -{ -public: - MqttClientConnectionConfigBuilder() - { - } - MqttClientConnectionConfigBuilder( const char *, const char *, Crt::Allocator *a = nullptr ) noexcept - { - (void)a; - } - MqttClientConnectionConfigBuilder( const Crt::ByteCursor &, - const Crt::ByteCursor &, - Crt::Allocator *a = nullptr ) noexcept - { - (void)a; - } - - MqttClientConnectionConfigBuilder &WithEndpoint( const Crt::String &endpoint ); - MqttClientConnectionConfigBuilder &WithCertificateAuthority( const Crt::ByteCursor &rootCA ); - MqttClientConnectionConfig Build() noexcept; -}; -class MqttClient -{ -public: - MqttClient( Aws::Crt::Io::ClientBootstrap &bootstrap, Crt::Allocator *allocator = NULL ) noexcept; - - std::shared_ptr NewConnection( const MqttClientConnectionConfig &config ) noexcept; - int LastError() const noexcept; - explicit operator bool() const noexcept; -}; -} // namespace Iot -} // namespace Aws diff --git a/src/offboardconnectivity/implementation/aws/iotcpp/test/src/.clang-tidy b/src/offboardconnectivity/implementation/aws/iotcpp/test/src/.clang-tidy deleted file mode 100644 index 48f16d51..00000000 --- a/src/offboardconnectivity/implementation/aws/iotcpp/test/src/.clang-tidy +++ /dev/null @@ -1,2 +0,0 @@ -# Enable only one dummy check -Checks: "-*,llvm-twine-local" diff --git a/src/offboardconnectivity/implementation/aws/iotcpp/test/src/AwsIotSdkMock.cpp b/src/offboardconnectivity/implementation/aws/iotcpp/test/src/AwsIotSdkMock.cpp deleted file mode 100644 index a33e1498..00000000 --- a/src/offboardconnectivity/implementation/aws/iotcpp/test/src/AwsIotSdkMock.cpp +++ /dev/null @@ -1,108 +0,0 @@ -// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. -// SPDX-License-Identifier: Apache-2.0 - -#include "AwsIotSdkMock.h" - -namespace Aws -{ -namespace IoTFleetWise -{ -namespace OffboardConnectivityAwsIot -{ -namespace Testing -{ - -static AwsIotSdkMock *sdkMock = nullptr; -static MqttConnectionMock *conMock = nullptr; -static MqttClientMock *clientMock = nullptr; -static MqttClientConnectionConfigMock *confMock = nullptr; -static MqttClientConnectionConfigBuilderMock *confBuilder = nullptr; -static ClientBootstrapMock *clientBootstrap = nullptr; -static EventLoopGroupMock *eventLoopMock = nullptr; - -AwsIotSdkMock * -getSdkMock() -{ - return sdkMock; -} - -void -setSdkMock( AwsIotSdkMock *m ) -{ - sdkMock = m; -} - -MqttConnectionMock * -getConMock() -{ - return conMock; -} - -void -setConMock( MqttConnectionMock *m ) -{ - conMock = m; -} - -MqttClientMock * -getClientMock() -{ - return clientMock; -} - -void -setClientMock( MqttClientMock *m ) -{ - clientMock = m; -} - -MqttClientConnectionConfigMock * -getConfMock() -{ - return confMock; -} - -void -setConfMock( MqttClientConnectionConfigMock *m ) -{ - confMock = m; -} - -MqttClientConnectionConfigBuilderMock * -getConfBuilderMock() -{ - return confBuilder; -} -void -setConfBuilderMock( MqttClientConnectionConfigBuilderMock *m ) -{ - confBuilder = m; -} - -ClientBootstrapMock * -getClientBootstrapMock() -{ - return clientBootstrap; -} -void -setClientBootstrapMock( ClientBootstrapMock *m ) -{ - clientBootstrap = m; -} - -EventLoopGroupMock * -getEventLoopMock() -{ - return eventLoopMock; -} - -void -setEventLoopMock( EventLoopGroupMock *m ) -{ - eventLoopMock = m; -} - -} // namespace Testing -} // namespace OffboardConnectivityAwsIot -} // namespace IoTFleetWise -} // namespace Aws diff --git a/src/offboardconnectivity/implementation/aws/iotcpp/test/src/MqttClient.cpp b/src/offboardconnectivity/implementation/aws/iotcpp/test/src/MqttClient.cpp deleted file mode 100644 index 3be1d471..00000000 --- a/src/offboardconnectivity/implementation/aws/iotcpp/test/src/MqttClient.cpp +++ /dev/null @@ -1,59 +0,0 @@ -// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. -// SPDX-License-Identifier: Apache-2.0 - -#include "aws/iot/MqttClient.h" -#include "AwsIotSdkMock.h" -using namespace Aws::IoTFleetWise::OffboardConnectivityAwsIot::Testing; - -Aws::Iot::MqttClient::MqttClient( Aws::Crt::Io::ClientBootstrap &bootstrap, Aws::Crt::Allocator *allocator ) noexcept -{ - getClientMock()->CONSTRUCTOR( bootstrap, allocator ); -} - -std::shared_ptr -Aws::Iot::MqttClient::NewConnection( const MqttClientConnectionConfig &config ) noexcept -{ - return getClientMock()->NewConnection( config ); -} - -Aws::Iot::MqttClient::operator bool() const noexcept -{ - return getClientMock()->operatorBool(); -} - -int -Aws::Iot::MqttClient::LastError() const noexcept -{ - return getClientMock()->LastError(); -} - -Aws::Iot::MqttClientConnectionConfig::operator bool() const noexcept -{ - return getConfMock()->operatorBool(); -} - -int -Aws::Iot::MqttClientConnectionConfig::LastError() const noexcept -{ - return getConfMock()->LastError(); -} - -Aws::Iot::MqttClientConnectionConfigBuilder & -Aws::Iot::MqttClientConnectionConfigBuilder::WithEndpoint( const Aws::Crt::String &endpoint ) -{ - getConfBuilderMock()->WithEndpoint( endpoint ); - return *this; -} - -Aws::Iot::MqttClientConnectionConfigBuilder & -Aws::Iot::MqttClientConnectionConfigBuilder::WithCertificateAuthority( const Crt::ByteCursor &rootCA ) -{ - getConfBuilderMock()->WithCertificateAuthority( rootCA ); - return *this; -} - -Aws::Iot::MqttClientConnectionConfig -Aws::Iot::MqttClientConnectionConfigBuilder::Build() noexcept -{ - return getConfBuilderMock()->Build(); -} diff --git a/src/offboardconnectivity/implementation/aws/iotcpp/test/src/RemoteProfilerTest.cpp b/src/offboardconnectivity/implementation/aws/iotcpp/test/src/RemoteProfilerTest.cpp deleted file mode 100644 index 17a5d918..00000000 --- a/src/offboardconnectivity/implementation/aws/iotcpp/test/src/RemoteProfilerTest.cpp +++ /dev/null @@ -1,89 +0,0 @@ -// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. -// SPDX-License-Identifier: Apache-2.0 - -#include "RemoteProfiler.h" -#include -#include -#include -#include -#include -#include - -using namespace Aws::IoTFleetWise::OffboardConnectivity; - -class MockSender : public ISender -{ -public: - // Create a callback that will allow the sender to inject a testing function - using Callback = std::function; - Callback mCallback; - - bool - isAlive() override - { - return true; - } - - size_t - getMaxSendSize() const override - { - return 12345; - } - - ConnectivityError - sendBuffer( const std::uint8_t *buf, - size_t size, - struct Aws::IoTFleetWise::OffboardConnectivity::CollectionSchemeParams collectionSchemeParams = - CollectionSchemeParams() ) override - { - static_cast( collectionSchemeParams ); // Currently not implemented, hence unused - std::cout << buf << std::endl; - if ( !mCallback ) - { - return ConnectivityError::NoConnection; - } - return mCallback( buf, size ); - } - - ConnectivityError - sendFile( const std::string &filePath, - size_t size, - struct CollectionSchemeParams collectionSchemeParams = CollectionSchemeParams() ) override - { - static_cast( filePath ); - static_cast( size ); - static_cast( collectionSchemeParams ); - return ConnectivityError::TypeNotSupported; - } -}; - -void -checkMetrics( const std::uint8_t *buf, size_t size ) -{ - Json::Reader reader; - Json::Value root; - ASSERT_TRUE( reader.parse( std::string( reinterpret_cast( buf ) ), root ) ); - ASSERT_GE( size, 6 ); - ASSERT_GE( root["metric1"]["name"].asString().length(), 1 ); -} - -std::atomic a( 0 ); -TEST( RemoteProfilerTest, MetricsUpload ) -{ - auto mockMetricsSender = std::make_shared(); - mockMetricsSender->mCallback = [&]( const std::uint8_t *buf, size_t size ) -> ConnectivityError { - checkMetrics( buf, size ); - return ConnectivityError::Success; - }; - auto mockLogSender = std::make_shared(); - RemoteProfiler profiler( mockMetricsSender, mockLogSender, 1000, 1000, LogLevel::Trace, "Test" ); - profiler.start(); - - // Generate some cpu load - for ( int i = 0; i < 200000000; i++ ) - { - a++; - } - - std::this_thread::sleep_for( std::chrono::milliseconds( 1500 ) ); -} diff --git a/src/offboardconnectivity/implementation/aws/iotcpp/test/valgrind.supp b/src/offboardconnectivity/implementation/aws/iotcpp/test/valgrind.supp deleted file mode 100644 index 0fdf9f6f..00000000 --- a/src/offboardconnectivity/implementation/aws/iotcpp/test/valgrind.supp +++ /dev/null @@ -1,17 +0,0 @@ -{ - aws_io_library_init - Memcheck:Leak - match-leak-kinds: definite,reachable - ... - fun:aws_io_library_init - ... -} - -{ - __libc_csu_init - Memcheck:Leak - match-leak-kinds: reachable - ... - fun:__libc_csu_init - ... -} diff --git a/src/platform/CMakeLists.txt b/src/platform/CMakeLists.txt deleted file mode 100644 index 8e1ae908..00000000 --- a/src/platform/CMakeLists.txt +++ /dev/null @@ -1,37 +0,0 @@ -# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. - -# AWS IoT FleetWise Platforms. This configuration file selects the Platform -# for the build based on the setting of the PLATFORM_TYPE option. - -# This is a list of available platforms -set( - platformTypes - # Supported Platforms: - Linux - # Yocto - # AwesomeCarHardware1 - # AwesomeCarHardware2 -) - -# Because CMake only supports boolean options, PLATFORM_TYPE is set as CACHE STRING -set( - PLATFORM_TYPE Linux - CACHE STRING - "The type of platform selected for the build. Currently only Linux is support." -) - -# Allowable values for PLATFORM_TYPE to be the ones listed in the platformTypes variable -set_property(CACHE PLATFORM_TYPE PROPERTY STRINGS ${platformTypes}) - -# Enforce a valid setting -if(NOT PLATFORM_TYPE IN_LIST platformTypes) - message(FATAL_ERROR "PLATFORM_TYPE must be one of ${platformTypes}") -endif() - -# Add the selected platform subdirectory -if(${PLATFORM_TYPE} STREQUAL Linux) - message(STATUS "Adding Linux platform") - add_subdirectory( linux ) -endif() - -add_subdirectory( utility ) diff --git a/src/platform/linux/CMakeLists.txt b/src/platform/linux/CMakeLists.txt deleted file mode 100644 index 46e4c1ed..00000000 --- a/src/platform/linux/CMakeLists.txt +++ /dev/null @@ -1,156 +0,0 @@ -# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. - -# Linux platform Implementation. This is configured to compile into one library with -# exposed header files. Very importantly, a general alias is exported, allowing -# applications to add a general platform as a dependency - -message(STATUS "Linux platform configuration started.") - -# The name used for this library target -set(libraryTargetName iotfleetwise.platform.linux) -# The alias name is what other targets will use as a dependency -set(libraryAliasName IoTFleetWise::Platform::Linux) - -add_library( - ${libraryTargetName} - # STATIC or SHARED left out to depend on BUILD_SHARED_LIBS - logmanagement/src/ConsoleLogger.cpp - logmanagement/src/LoggingModule.cpp - logmanagement/src/TraceModule.cpp - threadingmanagement/src/Thread.cpp - timemanagement/src/ClockHandler.cpp - resourcemanagement/src/MemoryUsageInfo.cpp - resourcemanagement/src/CPUUsageInfo.cpp - persistencymanagement/src/CacheAndPersist.cpp -) - -find_path(JSONCPP_INCLUDE_DIR "json/json.h" PATH_SUFFIXES "jsoncpp") -find_library(JSONCPP_LIBRARY NAMES jsoncpp) -find_package(Boost 1.65.1 REQUIRED COMPONENTS filesystem) - -# These are public includes so we can expose the headers to other consumers -target_include_directories( - ${libraryTargetName} - PUBLIC - logmanagement/include - threadingmanagement/include - timemanagement/include - resourcemanagement/include - persistencymanagement/include - ${JSONCPP_INCLUDE_DIR} -) - -target_link_libraries( - ${libraryTargetName} - # From the Platform, this is what is used: logmanagement timemanagement - IoTFleetWise::Platform::Utility - Boost::filesystem - ${JSONCPP_LIBRARY} -) - -# This allows the preprocessor to enable the code in the libraries -target_compile_definitions( - ${libraryTargetName} - PUBLIC -) - -# We create an alias to a general platform library so that consuming apps -# do not need to be coupled to a specific implementation of the platform -add_library(${libraryAliasName} ALIAS ${libraryTargetName}) - -### INSTALL ### - -install( - TARGETS ${libraryTargetName} - RUNTIME DESTINATION bin - LIBRARY DESTINATION lib - ARCHIVE DESTINATION lib -) - -# Currently not necessary, but if we want to install the headers, here's how -install( - FILES - threadingmanagement/include/Listener.h - threadingmanagement/include/Signal.h - threadingmanagement/include/Thread.h - timemanagement/include/ClockHandler.h - timemanagement/include/Timer.h - timemanagement/include/Clock.h - resourcemanagement/include/CPUUsageInfo.h - resourcemanagement/include/MemoryUsageInfo.h - logmanagement/include/LoggingModule.h - logmanagement/include/ConsoleLogger.h - logmanagement/include/LogLevel.h - persistencymanagement/include/CacheAndPersist.h - DESTINATION include -) - -### Tests ### - -# This is a list of tests that will compiled. -# If adding a test, simply add the source file here -set( - testSources - logmanagement/test/TraceModuleTest.cpp - threadingmanagement/test/ThreadTest.cpp - timemanagement/test/TimerTest.cpp - timemanagement/test/ClockHandlerTest.cpp - resourcemanagement/test/CPUUsageInfoTest.cpp - resourcemanagement/test/MemoryUsageInfoTest.cpp - persistencymanagement/test/CacheAndPersistTest.cpp -) - -set( - benchmarkSources - timemanagement/test/ClockHandlerBenchmarkTest.cpp -) - - -if(${BUILD_TESTING}) - message(STATUS "Building tests for ${libraryTargetName}") - - find_package(benchmark REQUIRED) - - # Add the executable targets - foreach(testSource ${testSources}) - # Need a name for each exec so use filename w/o extension - get_filename_component(testName ${testSource} NAME_WE) - - add_executable(${testName} ${testSource}) - - # Link to the project library and testing library main - target_link_libraries( - ${testName} - PRIVATE - ${libraryTargetName} - IoTFleetWise::TestingSupport - ) - - add_unit_test(${testName}) - add_valgrind_test(${testName}) - install(TARGETS ${testName} RUNTIME DESTINATION bin/tests) - - endforeach() - - # Add the executable benchmark targets - foreach(testSource ${benchmarkSources}) - # Need a name for each exec so use filename w/o extension - get_filename_component(testName ${testSource} NAME_WE) - - add_executable(${testName} ${testSource}) - - # Link to the project library and testing library main - target_link_libraries( - ${testName} - PRIVATE - ${libraryTargetName} - benchmark::benchmark - ) - - add_test(NAME ${testName} COMMAND ${testName} --benchmark_out=benchmark-report-${testName}.txt --benchmark_out_format=console) - install(TARGETS ${testName} RUNTIME DESTINATION bin/tests) - - endforeach() -else() - message(STATUS "Testing not enabled for ${libraryTargetName}") -endif() diff --git a/src/platform/linux/logmanagement/test/.clang-tidy b/src/platform/linux/logmanagement/test/.clang-tidy deleted file mode 100644 index 48f16d51..00000000 --- a/src/platform/linux/logmanagement/test/.clang-tidy +++ /dev/null @@ -1,2 +0,0 @@ -# Enable only one dummy check -Checks: "-*,llvm-twine-local" diff --git a/src/platform/linux/persistencymanagement/test/.clang-tidy b/src/platform/linux/persistencymanagement/test/.clang-tidy deleted file mode 100644 index 48f16d51..00000000 --- a/src/platform/linux/persistencymanagement/test/.clang-tidy +++ /dev/null @@ -1,2 +0,0 @@ -# Enable only one dummy check -Checks: "-*,llvm-twine-local" diff --git a/src/platform/linux/resourcemanagement/test/.clang-tidy b/src/platform/linux/resourcemanagement/test/.clang-tidy deleted file mode 100644 index 48f16d51..00000000 --- a/src/platform/linux/resourcemanagement/test/.clang-tidy +++ /dev/null @@ -1,2 +0,0 @@ -# Enable only one dummy check -Checks: "-*,llvm-twine-local" diff --git a/src/platform/linux/test/valgrind.supp b/src/platform/linux/test/valgrind.supp deleted file mode 100644 index 00c906ed..00000000 --- a/src/platform/linux/test/valgrind.supp +++ /dev/null @@ -1,8 +0,0 @@ -{ - __libc_csu_init - Memcheck:Leak - match-leak-kinds: reachable - ... - fun:__libc_csu_init - ... -} diff --git a/src/platform/linux/threadingmanagement/test/.clang-tidy b/src/platform/linux/threadingmanagement/test/.clang-tidy deleted file mode 100644 index 48f16d51..00000000 --- a/src/platform/linux/threadingmanagement/test/.clang-tidy +++ /dev/null @@ -1,2 +0,0 @@ -# Enable only one dummy check -Checks: "-*,llvm-twine-local" diff --git a/src/platform/linux/timemanagement/test/.clang-tidy b/src/platform/linux/timemanagement/test/.clang-tidy deleted file mode 100644 index 48f16d51..00000000 --- a/src/platform/linux/timemanagement/test/.clang-tidy +++ /dev/null @@ -1,2 +0,0 @@ -# Enable only one dummy check -Checks: "-*,llvm-twine-local" diff --git a/src/platform/utility/CMakeLists.txt b/src/platform/utility/CMakeLists.txt deleted file mode 100644 index 2085517e..00000000 --- a/src/platform/utility/CMakeLists.txt +++ /dev/null @@ -1,25 +0,0 @@ -# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. - -set(libraryTargetName iotfleetwise.platform.utility) - -# The alias name is what other targets will use as a dependency -set(libraryAliasName IoTFleetWise::Platform::Utility) - -add_library( - ${libraryTargetName} - INTERFACE -) - -target_include_directories(${libraryTargetName} INTERFACE include) - -add_library(${libraryAliasName} ALIAS ${libraryTargetName}) - -### Install ### - -# No Install targets necessary - -### Tests ### - -if(${BUILD_TESTING}) -# None so far -endif() diff --git a/src/testingsupport/CMakeLists.txt b/src/testingsupport/CMakeLists.txt deleted file mode 100644 index cba58a1d..00000000 --- a/src/testingsupport/CMakeLists.txt +++ /dev/null @@ -1,76 +0,0 @@ -# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. - -set(libraryTargetName iotfleetwise.testingsupport) - -# The alias name is what other targets will use as a dependency -set(libraryAliasName IoTFleetWise::TestingSupport) - -add_library( - ${libraryTargetName} - # STATIC or SHARED left out to depend on BUILD_SHARED_LIBS - src/main.cpp -) - -find_package(GTest REQUIRED) - -target_include_directories(${libraryTargetName} - PUBLIC - include -) - -target_link_libraries( - ${libraryTargetName} - IoTFleetWise::Platform::Linux - GTest::GTest -) - -add_library(${libraryAliasName} ALIAS ${libraryTargetName}) - -### Install ### - -install(TARGETS ${libraryTargetName} DESTINATION lib) - -install( - FILES - include/Faketime.h - include/Testing.h - include/WaitUntil.h - DESTINATION include -) - -### Tests ### - -if(${BUILD_TESTING}) - message(STATUS "Building tests for ${libraryTargetName}") - - if(FWE_TEST_FAKETIME) - set(EXTRA_TEST_FILES ${EXTRA_TEST_FILES} test/FakeSystemTimeTest.cpp) - endif() - set( - testSources - test/WaitUntilTest.cpp - ${EXTRA_TEST_FILES} - ) - # Add the executable targets - foreach(testSource ${testSources}) - # Need a name for each exec so use filename w/o extension - get_filename_component(testName ${testSource} NAME_WE) - - add_executable(${testName} ${testSource}) - - # Link to the project library and testing library main - target_link_libraries( - ${testName} - PRIVATE - ${libraryTargetName} - IoTFleetWise::TestingSupport - ) - - if(FWE_TEST_FAKETIME) - add_unit_test_with_faketime(${testName}) - endif() - install(TARGETS ${testName} RUNTIME DESTINATION bin/tests) - - endforeach() - -endif() diff --git a/src/testingsupport/src/main.cpp b/src/testingsupport/src/main.cpp deleted file mode 100644 index f3f9dafb..00000000 --- a/src/testingsupport/src/main.cpp +++ /dev/null @@ -1,20 +0,0 @@ -#include "ConsoleLogger.h" -#include "LogLevel.h" -#include - -using namespace Aws::IoTFleetWise::Platform::Linux; - -static void -configureLogging() -{ - gSystemWideLogLevel = LogLevel::Trace; - gLogColorOption = LogColorOption::Yes; -} - -int -main( int argc, char **argv ) -{ - ::testing::InitGoogleTest( &argc, argv ); - configureLogging(); - return RUN_ALL_TESTS(); -} diff --git a/src/testingsupport/test/.clang-tidy b/src/testingsupport/test/.clang-tidy deleted file mode 100644 index 48f16d51..00000000 --- a/src/testingsupport/test/.clang-tidy +++ /dev/null @@ -1,2 +0,0 @@ -# Enable only one dummy check -Checks: "-*,llvm-twine-local" diff --git a/src/testingsupport/test/valgrind.supp b/src/testingsupport/test/valgrind.supp deleted file mode 100644 index 00c906ed..00000000 --- a/src/testingsupport/test/valgrind.supp +++ /dev/null @@ -1,8 +0,0 @@ -{ - __libc_csu_init - Memcheck:Leak - match-leak-kinds: reachable - ... - fun:__libc_csu_init - ... -} diff --git a/src/vehiclenetwork/CMakeLists.txt b/src/vehiclenetwork/CMakeLists.txt deleted file mode 100644 index 92d1370c..00000000 --- a/src/vehiclenetwork/CMakeLists.txt +++ /dev/null @@ -1,95 +0,0 @@ -# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. - -set(libraryTargetName iotfleetwise.vehiclenetwork) -# The alias name is what other targets will use as a dependency -set(libraryAliasName IoTFleetWise::Vehiclenetwork) - - -set(SRCS - src/ISOTPOverCANReceiver.cpp - src/ISOTPOverCANSender.cpp - src/ISOTPOverCANSenderReceiver.cpp -) - -add_library( - ${libraryTargetName} - # Leave STATIC or SHARED blank to allow for BUILD_SHARED_LIBS option - ${SRCS} -) - - -# Adding the include directory which contains two subdirectories. Users of this -# library will have to use the subdirectory name to include headers from this -# library, for example: #include "businterfaces/VehicleDataSource.h" -target_include_directories(${libraryTargetName} PUBLIC include) - -find_package(Boost 1.71.0 REQUIRED COMPONENTS thread) - -set(LIBS - IoTFleetWise::Platform::Linux - IoTFleetWise::Platform::Utility - Boost::thread -) - -target_link_libraries( - ${libraryTargetName} - PUBLIC - ${LIBS} -) - - -add_library(${libraryAliasName} ALIAS ${libraryTargetName}) - -### Install ### - -install(TARGETS ${libraryTargetName} DESTINATION lib) - -install( - FILES - include/businterfaces/ISOTPOverCANReceiver.h - include/businterfaces/ISOTPOverCANSender.h - include/businterfaces/ISOTPOverCANSenderReceiver.h - DESTINATION - include -) - -install( - FILES - include/datatypes/VehicleDataSourceTypes.h - include/datatypes/ISOTPOverCANOptions.h - DESTINATION - include/datatypes -) - -### Tests ### -# This is a list of tests that will compiled. -# If adding a test, simply add the source file here -set( - testSources - test/ISOTPOverCANProtocolTest.cpp -) - -if(${BUILD_TESTING}) - message(STATUS "Building tests for ${libraryTargetName}") - - # Add the executable targets - foreach(testSource ${testSources}) - # Need a name for each exec so use filename w/o extension - get_filename_component(testName ${testSource} NAME_WE) - - add_executable(${testName} ${testSource}) - # Link to the project library and testing library main - target_link_libraries( - ${testName} - PRIVATE - ${libraryTargetName} - IoTFleetWise::TestingSupport - ) - add_unit_test(${testName}) - add_valgrind_test(${testName}) - install(TARGETS ${testName} RUNTIME DESTINATION bin/tests) - - endforeach() -else() - message(STATUS "Testing not enabled for ${libraryTargetName}") -endif() diff --git a/src/vehiclenetwork/test/.clang-tidy b/src/vehiclenetwork/test/.clang-tidy deleted file mode 100644 index 48f16d51..00000000 --- a/src/vehiclenetwork/test/.clang-tidy +++ /dev/null @@ -1,2 +0,0 @@ -# Enable only one dummy check -Checks: "-*,llvm-twine-local" diff --git a/src/vehiclenetwork/test/valgrind.supp b/src/vehiclenetwork/test/valgrind.supp deleted file mode 100644 index e794ed1c..00000000 --- a/src/vehiclenetwork/test/valgrind.supp +++ /dev/null @@ -1,17 +0,0 @@ -{ - - Memcheck:Param - write(buf) - ... - fun:sem_open - ... -} - -{ - __libc_csu_init - Memcheck:Leak - match-leak-kinds: reachable - ... - fun:__libc_csu_init - ... -} diff --git a/src/datamanagement/custom/example/aaosvhal/test/AaosVhalSourceTest.cpp b/test/unit/AaosVhalSourceTest.cpp similarity index 87% rename from src/datamanagement/custom/example/aaosvhal/test/AaosVhalSourceTest.cpp rename to test/unit/AaosVhalSourceTest.cpp index 62e9c0d4..ac50dfaa 100644 --- a/src/datamanagement/custom/example/aaosvhal/test/AaosVhalSourceTest.cpp +++ b/test/unit/AaosVhalSourceTest.cpp @@ -1,12 +1,25 @@ // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 + #include "AaosVhalSource.h" +#include "CollectionInspectionAPITypes.h" +#include "IDecoderDictionary.h" +#include "MessageTypes.h" +#include "SignalTypes.h" +#include "VehicleDataSourceTypes.h" #include "WaitUntil.h" +#include +#include +#include #include -#include +#include +#include +#include -using namespace Aws::IoTFleetWise::DataManagement; -using namespace Aws::IoTFleetWise::TestingSupport; +namespace Aws +{ +namespace IoTFleetWise +{ class AaosVhalSourceTest : public ::testing::Test { @@ -73,3 +86,6 @@ TEST_F( AaosVhalSourceTest, testDecoding ) // NOLINT ASSERT_TRUE( vhalSource.stop() ); } + +} // namespace IoTFleetWise +} // namespace Aws diff --git a/src/offboardconnectivity/implementation/aws/iotcpp/test/src/AwsIotConnectivityModuleTest.cpp b/test/unit/AwsIotConnectivityModuleTest.cpp similarity index 61% rename from src/offboardconnectivity/implementation/aws/iotcpp/test/src/AwsIotConnectivityModuleTest.cpp rename to test/unit/AwsIotConnectivityModuleTest.cpp index d716b350..a7b40672 100644 --- a/src/offboardconnectivity/implementation/aws/iotcpp/test/src/AwsIotConnectivityModuleTest.cpp +++ b/test/unit/AwsIotConnectivityModuleTest.cpp @@ -2,117 +2,146 @@ // SPDX-License-Identifier: Apache-2.0 #include "AwsIotConnectivityModule.h" +#include "AwsBootstrap.h" #include "AwsIotChannel.h" -#include "AwsIotSdkMock.h" #include "AwsSDKMemoryManager.h" +#include "CacheAndPersist.h" +#include "IConnectionTypes.h" +#include "ISender.h" +#include "MqttClientWrapper.h" +#include "MqttClientWrapperMock.h" +#include "MqttConnectionWrapper.h" +#include "MqttConnectionWrapperMock.h" +#include "PayloadManager.h" +#include #include +#include +#include +#include +#include +#include #include +#include +#include +#include +#include +#include #include -#include -#include #include -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include #include +#include #include -using namespace Aws::IoTFleetWise::OffboardConnectivityAwsIot; -using namespace Aws::IoTFleetWise::OffboardConnectivityAwsIot::Testing; -using namespace Aws::Crt::Mqtt; +namespace Aws +{ +namespace IoTFleetWise +{ + using ::testing::_; using ::testing::AnyNumber; using ::testing::AtLeast; -using ::testing::DoAll; using ::testing::Invoke; using ::testing::NiceMock; using ::testing::Return; -using ::testing::ReturnRef; -using ::testing::SaveArg; -using ::testing::SaveArgPointee; -class AwsIotConnectivityModuleTest : public ::testing::Test +void +makeCert( std::string &keyPem, std::string &certPem ) { -protected: - void - SetUp() override + std::unique_ptr bn( BN_new(), BN_free ); + if ( !BN_set_word( bn.get(), RSA_F4 ) ) { + throw std::runtime_error( "error initializing big num" ); + } + auto rsa = RSA_new(); // Ownership passed to pkey below + if ( !RSA_generate_key_ex( rsa, 512, bn.get(), NULL ) ) + { + RSA_free( rsa ); + throw std::runtime_error( "error generating key" ); + } + std::unique_ptr pkey( EVP_PKEY_new(), EVP_PKEY_free ); + if ( !EVP_PKEY_assign_RSA( pkey.get(), rsa ) ) + { + throw std::runtime_error( "error assigning key" ); + } - setSdkMock( &sdkMock ); - setConMock( &conMock ); - - setClientMock( &clientMock ); - - setConfMock( &confMock ); - - setConfBuilderMock( &confBuilder ); - - setClientBootstrapMock( &clientBootstrap ); - - setEventLoopMock( &eventLoopMock ); - - ON_CALL( sdkMock, ErrorDebugString( _ ) ).WillByDefault( Return( "ErrorDebugString Mock called" ) ); + std::unique_ptr cert( X509_new(), X509_free ); + X509_set_version( cert.get(), 2 ); + ASN1_INTEGER_set( X509_get_serialNumber( cert.get() ), 0 ); + X509_gmtime_adj( X509_get_notBefore( cert.get() ), 0 ); + X509_gmtime_adj( X509_get_notAfter( cert.get() ), 60 * 60 * 24 * 365 ); + X509_set_pubkey( cert.get(), pkey.get() ); - ON_CALL( sdkMock, ByteCursorFromCString( _ ) ).WillByDefault( Return( byteCursor ) ); + auto name = X509_get_subject_name( cert.get() ); + X509_NAME_add_entry_by_txt( name, "C", MBSTRING_ASC, (const unsigned char *)"US", -1, -1, 0 ); + X509_NAME_add_entry_by_txt( name, "CN", MBSTRING_ASC, (const unsigned char *)"Dummy", -1, -1, 0 ); + X509_set_issuer_name( cert.get(), name ); - ON_CALL( sdkMock, ByteBufNewCopy( _, _, _ ) ).WillByDefault( Return( byteBuffer ) ); + if ( !X509_sign( cert.get(), pkey.get(), EVP_md5() ) ) + { + throw std::runtime_error( "error signing certificate" ); + } - ON_CALL( sdkMock, aws_error_debug_str( _ ) ).WillByDefault( Return( "aws_error_debug_str Mock called" ) ); + std::unique_ptr bio( BIO_new( BIO_s_mem() ), BIO_free ); + PEM_write_bio_PrivateKey( bio.get(), pkey.get(), NULL, NULL, 0, NULL, NULL ); + keyPem.resize( BIO_pending( bio.get() ) ); + BIO_read( bio.get(), &keyPem[0], static_cast( keyPem.size() ) ); - bootstrap = new Aws::Crt::Io::ClientBootstrap(); - } + PEM_write_bio_X509( bio.get(), cert.get() ); + certPem.resize( BIO_pending( bio.get() ) ); + BIO_read( bio.get(), &certPem[0], static_cast( certPem.size() ) ); +} - std::shared_ptr> - setupValidConnection() +class AwsIotConnectivityModuleTest : public ::testing::Test +{ +protected: + void + SetUp() override { - ON_CALL( eventLoopMock, operatorBool() ).WillByDefault( Return( true ) ); - ON_CALL( clientBootstrap, operatorBool() ).WillByDefault( Return( true ) ); - - ON_CALL( confMock, operatorBool() ).WillByDefault( Return( true ) ); - ON_CALL( clientMock, operatorBool() ).WillByDefault( Return( true ) ); - - std::shared_ptr> con = std::make_shared>(); - ON_CALL( clientMock, NewConnection( _ ) ).WillByDefault( Return( con ) ); - ON_CALL( *con, SetOnMessageHandler( _ ) ).WillByDefault( Return( true ) ); - ON_CALL( *con, Connect( _, _, _, _ ) ) - .WillByDefault( Invoke( [&con]( const char *, bool, uint16_t, uint32_t ) noexcept -> bool { - con->OnConnectionCompleted( *con, 0, ReturnCode::AWS_MQTT_CONNECT_ACCEPTED, true ); + makeCert( mKey, mCert ); + // Needs to initialize the SDK before creating a ClientConfiguration + AwsBootstrap::getInstance().getClientBootStrap(); + mMqttConnectionMock = std::make_shared>(); + mMqttClientWrapperMock = std::make_shared>(); + ON_CALL( *mMqttClientWrapperMock, MockedOperatorBool() ).WillByDefault( Return( true ) ); + ON_CALL( *mMqttClientWrapperMock, NewConnection( _ ) ).WillByDefault( Return( mMqttConnectionMock ) ); + ON_CALL( *mMqttConnectionMock, SetOnMessageHandler( _ ) ).WillByDefault( Return( true ) ); + ON_CALL( *mMqttConnectionMock, Connect( _, _, _, _ ) ) + .WillByDefault( Invoke( [this]( const char *, bool, uint16_t, uint32_t ) noexcept -> bool { + mMqttConnectionMock->mOnConnectionCompleted( + *mMqttConnectionMock, 0, Aws::Crt::Mqtt::ReturnCode::AWS_MQTT_CONNECT_ACCEPTED, true ); return true; } ) ); + ON_CALL( *mMqttConnectionMock, Disconnect() ).WillByDefault( Return( true ) ); - ON_CALL( *con, Disconnect() ).WillByDefault( Return( true ) ); - - return con; - } - - void - TearDown() override - { - delete ( bootstrap ); + mCreateMqttClientWrapper = [this]() -> std::shared_ptr { + return mMqttClientWrapperMock; + }; } - NiceMock sdkMock; - NiceMock conMock; - NiceMock clientMock; - NiceMock confMock; - NiceMock confBuilder; - NiceMock clientBootstrap; - NiceMock eventLoopMock; - Aws::Crt::ByteBuf byteBuffer; - uint8_t byte; - Aws::Crt::ByteCursor byteCursor = { 1, &byte }; - Aws::Crt::Io::ClientBootstrap *bootstrap; + std::string mKey; + std::string mCert; + std::shared_ptr> mMqttConnectionMock; + std::shared_ptr> mMqttClientWrapperMock; + std::function()> mCreateMqttClientWrapper; }; /** @brief Test attempting to disconnect when connection has already failed */ TEST_F( AwsIotConnectivityModuleTest, disconnectAfterFailedConnect ) { std::shared_ptr m = - std::make_shared( "", "", "", "", "", bootstrap ); + std::make_shared( "", "", "", "", "", mCreateMqttClientWrapper ); ASSERT_FALSE( m->connect() ); // disconnect must only disconnect when connection is available so this should not seg fault m->disconnect(); @@ -121,93 +150,96 @@ TEST_F( AwsIotConnectivityModuleTest, disconnectAfterFailedConnect ) /** @brief Test successful connection */ TEST_F( AwsIotConnectivityModuleTest, connectSuccessfully ) { - std::string endpoint( "endpoint" ); - auto con = setupValidConnection(); + std::shared_ptr m = std::make_shared( + mKey, mCert, "", "https://abcd", "clientIdTest", mCreateMqttClientWrapper, true ); + + ASSERT_TRUE( m->connect() ); - std::string requestedEndpoint; - EXPECT_CALL( confBuilder, WithEndpoint( _ ) ).Times( 1 ).WillOnce( SaveArg<0>( &requestedEndpoint ) ); + mMqttConnectionMock->mOnDisconnect( *mMqttConnectionMock ); - std::shared_ptr m = - std::make_shared( "key", "cert", "rootca", endpoint, "clientIdTest", bootstrap ); + m->disconnect(); +} + +/** @brief Test successful connection with root CA */ +TEST_F( AwsIotConnectivityModuleTest, connectSuccessfullyWithRootCA ) +{ + std::shared_ptr m = std::make_shared( + mKey, mCert, mCert, "https://abcd", "clientIdTest", mCreateMqttClientWrapper, true ); ASSERT_TRUE( m->connect() ); - con->OnDisconnect( *con ); + mMqttConnectionMock->mOnDisconnect( *mMqttConnectionMock ); m->disconnect(); - - // no modification should be made to endpoint - ASSERT_EQ( endpoint, requestedEndpoint ); } -/** @brief Test trying to connect, where creation of the bootstrap fails */ -TEST_F( AwsIotConnectivityModuleTest, connectFailsOnClientBootstrapCreation ) +/** @brief Test trying to connect, where certificate is invalid */ +TEST_F( AwsIotConnectivityModuleTest, connectFailsBadCert ) { - auto con = setupValidConnection(); + std::shared_ptr m = std::make_shared( + mKey, "", "", "https://abcd", "clientIdTest", mCreateMqttClientWrapper, true ); - std::shared_ptr m = - std::make_shared( "key", "cert", "rootca", "endpoint", "clientIdTest", nullptr ); ASSERT_FALSE( m->connect() ); } /** @brief Test trying to connect, where creation of the client fails */ TEST_F( AwsIotConnectivityModuleTest, connectFailsOnClientCreation ) { - auto con = setupValidConnection(); - EXPECT_CALL( clientMock, operatorBool() ).Times( AtLeast( 1 ) ).WillRepeatedly( Return( false ) ); + EXPECT_CALL( *mMqttClientWrapperMock, MockedOperatorBool() ) + .Times( AtLeast( 1 ) ) + .WillRepeatedly( Return( false ) ); - std::shared_ptr m = - std::make_shared( "key", "cert", "rootca", "endpoint", "clientIdTest", bootstrap ); + std::shared_ptr m = std::make_shared( + mKey, mCert, "", "https://abcd", "clientIdTest", mCreateMqttClientWrapper, true ); ASSERT_FALSE( m->connect() ); } /** @brief Test opening a connection, then interrupting it and resuming it */ TEST_F( AwsIotConnectivityModuleTest, connectionInterrupted ) { - auto con = setupValidConnection(); - - std::shared_ptr m = - std::make_shared( "key", "cert", "rootca", "endpoint", "clientIdTest", bootstrap ); + std::shared_ptr m = std::make_shared( + mKey, mCert, "", "https://abcd", "clientIdTest", mCreateMqttClientWrapper ); ASSERT_TRUE( m->connect() ); - con->OnConnectionInterrupted( *con, 10 ); - con->OnConnectionResumed( *con, ReturnCode::AWS_MQTT_CONNECT_ACCEPTED, true ); + mMqttConnectionMock->mOnConnectionInterrupted( *mMqttConnectionMock, 10 ); + mMqttConnectionMock->mOnConnectionResumed( + *mMqttConnectionMock, Aws::Crt::Mqtt::ReturnCode::AWS_MQTT_CONNECT_ACCEPTED, true ); - con->OnDisconnect( *con ); + mMqttConnectionMock->mOnDisconnect( *mMqttConnectionMock ); } /** @brief Test connecting when it fails after a delay */ TEST_F( AwsIotConnectivityModuleTest, connectFailsServerUnavailableWithDelay ) { - auto con = setupValidConnection(); std::atomic killAllThread( false ); std::promise completed; - std::thread completeThread( [con, &killAllThread, &completed]() { - while ( con->OnConnectionCompleted == nullptr && !killAllThread ) + std::thread completeThread( [this, &killAllThread, &completed]() { + while ( mMqttConnectionMock->mOnConnectionCompleted == nullptr && !killAllThread ) { std::this_thread::sleep_for( std::chrono::milliseconds( 5 ) ); } std::this_thread::sleep_for( std::chrono::milliseconds( 5 ) ); - con->OnConnectionCompleted( *con, 0, ReturnCode::AWS_MQTT_CONNECT_SERVER_UNAVAILABLE, true ); + mMqttConnectionMock->mOnConnectionCompleted( + *mMqttConnectionMock, 0, Aws::Crt::Mqtt::ReturnCode::AWS_MQTT_CONNECT_SERVER_UNAVAILABLE, true ); completed.set_value(); } ); - std::thread disconnectThread( [con, &killAllThread, &completed]() { - while ( con->OnDisconnect == nullptr && !killAllThread ) + std::thread disconnectThread( [this, &killAllThread, &completed]() { + while ( mMqttConnectionMock->mOnDisconnect == nullptr && !killAllThread ) { std::this_thread::sleep_for( std::chrono::milliseconds( 5 ) ); } completed.get_future().wait(); std::this_thread::sleep_for( std::chrono::milliseconds( 5 ) ); - con->OnDisconnect( *con ); + mMqttConnectionMock->mOnDisconnect( *mMqttConnectionMock ); } ); - std::shared_ptr m = - std::make_shared( "key", "cert", "rootca", "endpoint", "clientIdTest", bootstrap ); + std::shared_ptr m = std::make_shared( + mKey, mCert, "", "https://abcd", "clientIdTest", mCreateMqttClientWrapper ); - EXPECT_CALL( *con, Connect( _, _, _, _ ) ).Times( 1 ).WillOnce( Return( true ) ); + EXPECT_CALL( *mMqttConnectionMock, Connect( _, _, _, _ ) ).Times( 1 ).WillOnce( Return( true ) ); // We want to see exactly one call to disconnect - EXPECT_CALL( *con, Disconnect() ).Times( 1 ).WillRepeatedly( Return( true ) ); + EXPECT_CALL( *mMqttConnectionMock, Disconnect() ).Times( 1 ).WillRepeatedly( Return( true ) ); ASSERT_FALSE( m->connect() ); std::this_thread::sleep_for( std::chrono::milliseconds( 20 ) ); @@ -240,42 +272,40 @@ TEST_F( AwsIotConnectivityModuleTest, subscribeWithoutBeingConnected ) /** @brief Test successful subscription */ TEST_F( AwsIotConnectivityModuleTest, subscribeSuccessfully ) { - auto con = setupValidConnection(); - - std::shared_ptr m = - std::make_shared( "key", "cert", "rootca", "endpoint", "clientIdTest", bootstrap ); + std::shared_ptr m = std::make_shared( + mKey, mCert, "", "https://abcd", "clientIdTest", mCreateMqttClientWrapper ); ASSERT_TRUE( m->connect() ); AwsIotChannel c( m.get(), nullptr, m->mConnection ); c.setTopic( "topic" ); - EXPECT_CALL( *con, Subscribe( _, _, _, _ ) ) + EXPECT_CALL( *mMqttConnectionMock, Subscribe( _, _, _, _ ) ) .Times( 1 ) - .WillRepeatedly( Invoke( [&con]( const char *, + .WillRepeatedly( Invoke( [this]( const char *, aws_mqtt_qos, - MqttConnection::OnMessageReceivedHandler &&, - MqttConnection::OnSubAckHandler &&onSubAck ) -> bool { - onSubAck( *con, 10, "topic", aws_mqtt_qos::AWS_MQTT_QOS_AT_MOST_ONCE, 0 ); + MqttConnectionWrapper::OnMessageReceivedHandler &&, + MqttConnectionWrapper::OnSubAckHandler &&onSubAck ) -> bool { + onSubAck( *mMqttConnectionMock, 10, "topic", aws_mqtt_qos::AWS_MQTT_QOS_AT_MOST_ONCE, 0 ); return true; } ) ); ASSERT_EQ( c.subscribe(), ConnectivityError::Success ); - EXPECT_CALL( *con, Unsubscribe( _, _ ) ) + EXPECT_CALL( *mMqttConnectionMock, Unsubscribe( _, _ ) ) .Times( AtLeast( 1 ) ) - .WillRepeatedly( Invoke( - [&con]( const char *, MqttConnection::OnOperationCompleteHandler &&onOpComplete ) noexcept -> uint16_t { - onOpComplete( *con, 0, 0 ); + .WillRepeatedly( + Invoke( [this]( const char *, + MqttConnectionWrapper::OnOperationCompleteHandler &&onOpComplete ) noexcept -> uint16_t { + onOpComplete( *mMqttConnectionMock, 0, 0 ); return 0; } ) ); c.unsubscribe(); - con->OnDisconnect( *con ); + mMqttConnectionMock->mOnDisconnect( *mMqttConnectionMock ); c.invalidateConnection(); } /** @brief Test without a configured topic, expect an error */ TEST_F( AwsIotConnectivityModuleTest, sendWithoutTopic ) { - auto con = setupValidConnection(); std::shared_ptr m = std::make_shared( "", "", "", "", "", nullptr ); AwsIotChannel c( m.get(), nullptr, m->mConnection ); @@ -299,23 +329,21 @@ TEST_F( AwsIotConnectivityModuleTest, sendWithoutConnection ) /** @brief Test passing a null pointer, expect an error */ TEST_F( AwsIotConnectivityModuleTest, sendWrongInput ) { - auto con = setupValidConnection(); - std::shared_ptr m = - std::make_shared( "key", "cert", "rootca", "endpoint", "clientIdTest", bootstrap ); + std::shared_ptr m = std::make_shared( + mKey, mCert, "", "https://abcd", "clientIdTest", mCreateMqttClientWrapper ); AwsIotChannel c( m.get(), nullptr, m->mConnection ); ASSERT_TRUE( m->connect() ); c.setTopic( "topic" ); ASSERT_EQ( c.sendBuffer( nullptr, 10 ), ConnectivityError::WrongInputData ); - con->OnDisconnect( *con ); + mMqttConnectionMock->mOnDisconnect( *mMqttConnectionMock ); c.invalidateConnection(); } /** @brief Test sending a message larger then the maximum send size, expect an error */ TEST_F( AwsIotConnectivityModuleTest, sendTooBig ) { - auto con = setupValidConnection(); - std::shared_ptr m = - std::make_shared( "key", "cert", "rootca", "endpoint", "clientIdTest", bootstrap ); + std::shared_ptr m = std::make_shared( + mKey, mCert, "", "https://abcd", "clientIdTest", mCreateMqttClientWrapper ); AwsIotChannel c( m.get(), nullptr, m->mConnection ); ASSERT_TRUE( m->connect() ); @@ -323,7 +351,7 @@ TEST_F( AwsIotConnectivityModuleTest, sendTooBig ) std::vector a; a.resize( c.getMaxSendSize() + 1U ); ASSERT_EQ( c.sendBuffer( a.data(), a.size() ), ConnectivityError::WrongInputData ); - con->OnDisconnect( *con ); + mMqttConnectionMock->mOnDisconnect( *mMqttConnectionMock ); c.invalidateConnection(); } @@ -332,23 +360,22 @@ TEST_F( AwsIotConnectivityModuleTest, sendTooBig ) * messages as failed to send to check that path. */ TEST_F( AwsIotConnectivityModuleTest, sendMultiple ) { - auto con = setupValidConnection(); - std::shared_ptr m = - std::make_shared( "key", "cert", "rootca", "endpoint", "clientIdTest", bootstrap ); + std::shared_ptr m = std::make_shared( + mKey, mCert, "", "https://abcd", "clientIdTest", mCreateMqttClientWrapper ); ASSERT_TRUE( m->connect() ); AwsIotChannel c( m.get(), nullptr, m->mConnection ); std::uint8_t input[] = { 0xca, 0xfe }; c.setTopic( "topic" ); - std::list completeHandlers; - EXPECT_CALL( *con, Publish( _, _, _, _, _ ) ) + std::list completeHandlers; + EXPECT_CALL( *mMqttConnectionMock, Publish( _, _, _, _, _ ) ) .Times( 3 ) - .WillRepeatedly( - Invoke( [&completeHandlers]( const char *, - aws_mqtt_qos, - bool, - const struct aws_byte_buf &, - MqttConnection::OnOperationCompleteHandler &&onOpComplete ) noexcept -> bool { + .WillRepeatedly( Invoke( + [&completeHandlers]( const char *, + aws_mqtt_qos, + bool, + const struct aws_byte_buf &, + MqttConnectionWrapper::OnOperationCompleteHandler &&onOpComplete ) noexcept -> bool { completeHandlers.push_back( std::move( onOpComplete ) ); return true; } ) ); @@ -358,32 +385,30 @@ TEST_F( AwsIotConnectivityModuleTest, sendMultiple ) ASSERT_EQ( c.sendBuffer( input, sizeof( input ) ), ConnectivityError::Success ); // Confirm 1st (success as packetId is 1---v): - completeHandlers.front().operator()( *con, 1, 0 ); + completeHandlers.front().operator()( *mMqttConnectionMock, 1, 0 ); completeHandlers.pop_front(); // Queue another: ASSERT_EQ( c.sendBuffer( input, sizeof( input ) ), ConnectivityError::Success ); // Confirm 2nd (success as packetId is 2---v): - completeHandlers.front().operator()( *con, 2, 0 ); + completeHandlers.front().operator()( *mMqttConnectionMock, 2, 0 ); completeHandlers.pop_front(); // Confirm 3rd (failure as packetId is 0---v) (Not a test case failure, but a stimulated failure for code coverage) - completeHandlers.front().operator()( *con, 0, 0 ); + completeHandlers.front().operator()( *mMqttConnectionMock, 0, 0 ); completeHandlers.pop_front(); ASSERT_EQ( c.getPayloadCountSent(), 2 ); - con->OnDisconnect( *con ); + mMqttConnectionMock->mOnDisconnect( *mMqttConnectionMock ); c.invalidateConnection(); } /** @brief Test SDK exceeds RAM and Channel stops sending */ TEST_F( AwsIotConnectivityModuleTest, sdkRAMExceeded ) { - auto con = setupValidConnection(); - - std::shared_ptr m = - std::make_shared( "key", "cert", "rootca", "endpoint", "clientIdTest", bootstrap ); + std::shared_ptr m = std::make_shared( + mKey, mCert, "", "https://abcd", "clientIdTest", mCreateMqttClientWrapper ); ASSERT_TRUE( m->connect() ); auto &memMgr = AwsSDKMemoryManager::getInstance(); @@ -424,15 +449,16 @@ TEST_F( AwsIotConnectivityModuleTest, sdkRAMExceeded ) AwsSDKMemoryManager::getInstance().getLimit() - ( ( 2 * offset ) + required ), alignof( std::size_t ) ); ASSERT_NE( alloc5, nullptr ); - std::list completeHandlers; - EXPECT_CALL( *con, Publish( _, _, _, _, _ ) ) + std::list completeHandlers; + EXPECT_CALL( *mMqttConnectionMock, Publish( _, _, _, _, _ ) ) .Times( AnyNumber() ) - .WillRepeatedly( Invoke( - [&completeHandlers]( const char *, - aws_mqtt_qos, - bool, - const struct aws_byte_buf &, - MqttConnection::OnOperationCompleteHandler &&onOpComplete ) noexcept -> bool { + .WillRepeatedly( + Invoke( [&completeHandlers]( + const char *, + aws_mqtt_qos, + bool, + const struct aws_byte_buf &, + MqttConnectionWrapper::OnOperationCompleteHandler &&onOpComplete ) noexcept -> bool { completeHandlers.push_back( std::move( onOpComplete ) ); return true; } ) ); @@ -441,11 +467,11 @@ TEST_F( AwsIotConnectivityModuleTest, sdkRAMExceeded ) memMgr.FreeMemory( alloc5 ); // // Confirm 1st (success as packetId is 1---v): - completeHandlers.front().operator()( *con, 1, 0 ); + completeHandlers.front().operator()( *mMqttConnectionMock, 1, 0 ); completeHandlers.pop_front(); } - con->OnDisconnect( *con ); + mMqttConnectionMock->mOnDisconnect( *mMqttConnectionMock ); c.invalidateConnection(); } @@ -517,9 +543,8 @@ TEST_F( AwsIotConnectivityModuleTest, sendFileOverMQTTNoFile ) char buffer[PATH_MAX]; if ( getcwd( buffer, sizeof( buffer ) ) != NULL ) { - auto con = setupValidConnection(); std::shared_ptr m = std::make_shared( - "key", "cert", "rootca", "endpoint", "clientIdTest", bootstrap ); + mKey, mCert, "", "https://abcd", "clientIdTest", mCreateMqttClientWrapper ); const std::shared_ptr persistencyPtr = std::make_shared( std::string( buffer ) + "/Persistency", 131072 ); @@ -534,7 +559,7 @@ TEST_F( AwsIotConnectivityModuleTest, sendFileOverMQTTNoFile ) std::string filename = "testFile.json"; ASSERT_EQ( c.sendFile( filename, 100 ), ConnectivityError::WrongInputData ); - con->OnDisconnect( *con ); + mMqttConnectionMock->mOnDisconnect( *mMqttConnectionMock ); c.invalidateConnection(); } } @@ -544,10 +569,8 @@ TEST_F( AwsIotConnectivityModuleTest, sendFileOverMQTTSdkRAMExceeded ) char buffer[PATH_MAX]; if ( getcwd( buffer, sizeof( buffer ) ) != NULL ) { - auto con = setupValidConnection(); - std::shared_ptr m = std::make_shared( - "key", "cert", "rootca", "endpoint", "clientIdTest", bootstrap ); + mKey, mCert, "", "https://abcd", "clientIdTest", mCreateMqttClientWrapper ); ASSERT_TRUE( m->connect() ); auto &memMgr = AwsSDKMemoryManager::getInstance(); @@ -593,7 +616,7 @@ TEST_F( AwsIotConnectivityModuleTest, sendFileOverMQTTSdkRAMExceeded ) memMgr.FreeMemory( alloc4 ); } - con->OnDisconnect( *con ); + mMqttConnectionMock->mOnDisconnect( *mMqttConnectionMock ); c.invalidateConnection(); } } @@ -603,12 +626,11 @@ TEST_F( AwsIotConnectivityModuleTest, sendFileOverMQTT ) char buffer[PATH_MAX]; if ( getcwd( buffer, sizeof( buffer ) ) != NULL ) { - int ret = std::system( "mkdir ./Persistency" ); + int ret = std::system( "rm -rf ./Persistency && mkdir ./Persistency" ); ASSERT_FALSE( WIFEXITED( ret ) == 0 ); - auto con = setupValidConnection(); std::shared_ptr m = std::make_shared( - "key", "cert", "rootca", "endpoint", "clientIdTest", bootstrap ); + mKey, mCert, "", "https://abcd", "clientIdTest", mCreateMqttClientWrapper ); const std::shared_ptr persistencyPtr = std::make_shared( std::string( buffer ) + "/Persistency", 131072 ); @@ -626,15 +648,16 @@ TEST_F( AwsIotConnectivityModuleTest, sendFileOverMQTT ) ASSERT_TRUE( m->connect() ); c.setTopic( "topic" ); - std::list completeHandlers; - EXPECT_CALL( *con, Publish( _, _, _, _, _ ) ) + std::list completeHandlers; + EXPECT_CALL( *mMqttConnectionMock, Publish( _, _, _, _, _ ) ) .Times( 2 ) - .WillRepeatedly( Invoke( - [&completeHandlers]( const char *, - aws_mqtt_qos, - bool, - const struct aws_byte_buf &, - MqttConnection::OnOperationCompleteHandler &&onOpComplete ) noexcept -> bool { + .WillRepeatedly( + Invoke( [&completeHandlers]( + const char *, + aws_mqtt_qos, + bool, + const struct aws_byte_buf &, + MqttConnectionWrapper::OnOperationCompleteHandler &&onOpComplete ) noexcept -> bool { completeHandlers.push_back( std::move( onOpComplete ) ); return true; } ) ); @@ -642,17 +665,17 @@ TEST_F( AwsIotConnectivityModuleTest, sendFileOverMQTT ) ASSERT_EQ( c.sendFile( filename, testData.size() ), ConnectivityError::Success ); // Confirm 1st (success as packetId is 1---v): - completeHandlers.front().operator()( *con, 1, 0 ); + completeHandlers.front().operator()( *mMqttConnectionMock, 1, 0 ); completeHandlers.pop_front(); // Test callback return false persistencyPtr->write( stringData, testData.size(), DataType::EDGE_TO_CLOUD_PAYLOAD, filename ); ASSERT_EQ( c.sendFile( filename, testData.size() ), ConnectivityError::Success ); - completeHandlers.front().operator()( *con, 0, 0 ); + completeHandlers.front().operator()( *mMqttConnectionMock, 0, 0 ); completeHandlers.pop_front(); - con->OnDisconnect( *con ); + mMqttConnectionMock->mOnDisconnect( *mMqttConnectionMock ); c.invalidateConnection(); } } @@ -684,33 +707,37 @@ TEST_F( AwsIotConnectivityModuleTest, sendFileOverMQTTNoConnection ) /** @brief Test the separate thread with exponential backoff that tries to connect until connection succeeds */ TEST_F( AwsIotConnectivityModuleTest, asyncConnect ) { - auto con = setupValidConnection(); - std::shared_ptr m = std::make_shared( - "key", "cert", "rootca", "endpoint", "clientIdTest", bootstrap, true ); + mKey, mCert, "", "https://abcd", "clientIdTest", mCreateMqttClientWrapper, true ); - EXPECT_CALL( *con, Connect( _, _, _, _ ) ).Times( 1 ).WillOnce( Return( true ) ); + EXPECT_CALL( *mMqttConnectionMock, Connect( _, _, _, _ ) ).Times( 1 ).WillOnce( Return( true ) ); ASSERT_TRUE( m->connect() ); std::this_thread::sleep_for( std::chrono::milliseconds( 100 ) ); // first attempt should come immediately - EXPECT_CALL( *con, Connect( _, _, _, _ ) ).Times( 1 ).WillOnce( Return( true ) ); - con->OnConnectionCompleted( *con, 0, ReturnCode::AWS_MQTT_CONNECT_SERVER_UNAVAILABLE, true ); + EXPECT_CALL( *mMqttConnectionMock, Connect( _, _, _, _ ) ).Times( 1 ).WillOnce( Return( true ) ); + mMqttConnectionMock->mOnConnectionCompleted( + *mMqttConnectionMock, 0, Aws::Crt::Mqtt::ReturnCode::AWS_MQTT_CONNECT_SERVER_UNAVAILABLE, true ); std::this_thread::sleep_for( std::chrono::milliseconds( 100 ) ); - con->OnDisconnect( *con ); + mMqttConnectionMock->mOnDisconnect( *mMqttConnectionMock ); std::this_thread::sleep_for( std::chrono::milliseconds( 1100 ) ); // minimum wait time 1 second - EXPECT_CALL( *con, Connect( _, _, _, _ ) ).Times( 1 ).WillOnce( Return( true ) ); - con->OnConnectionCompleted( *con, 0, ReturnCode::AWS_MQTT_CONNECT_SERVER_UNAVAILABLE, true ); + EXPECT_CALL( *mMqttConnectionMock, Connect( _, _, _, _ ) ).Times( 1 ).WillOnce( Return( true ) ); + mMqttConnectionMock->mOnConnectionCompleted( + *mMqttConnectionMock, 0, Aws::Crt::Mqtt::ReturnCode::AWS_MQTT_CONNECT_SERVER_UNAVAILABLE, true ); std::this_thread::sleep_for( std::chrono::milliseconds( 100 ) ); - con->OnDisconnect( *con ); + mMqttConnectionMock->mOnDisconnect( *mMqttConnectionMock ); std::this_thread::sleep_for( std::chrono::milliseconds( 2100 ) ); // exponential backoff now 2 seconds - EXPECT_CALL( *con, Connect( _, _, _, _ ) ).Times( 0 ); - con->OnConnectionCompleted( *con, 0, ReturnCode::AWS_MQTT_CONNECT_ACCEPTED, true ); + EXPECT_CALL( *mMqttConnectionMock, Connect( _, _, _, _ ) ).Times( 0 ); + mMqttConnectionMock->mOnConnectionCompleted( + *mMqttConnectionMock, 0, Aws::Crt::Mqtt::ReturnCode::AWS_MQTT_CONNECT_ACCEPTED, true ); std::this_thread::sleep_for( std::chrono::milliseconds( 100 ) ); - con->OnDisconnect( *con ); + mMqttConnectionMock->mOnDisconnect( *mMqttConnectionMock ); } + +} // namespace IoTFleetWise +} // namespace Aws diff --git a/src/datamanagement/datainspection/test/CANDataSourceTest.cpp b/test/unit/CANDataSourceTest.cpp similarity index 96% rename from src/datamanagement/datainspection/test/CANDataSourceTest.cpp rename to test/unit/CANDataSourceTest.cpp index eef91939..d42f30a7 100644 --- a/src/datamanagement/datainspection/test/CANDataSourceTest.cpp +++ b/test/unit/CANDataSourceTest.cpp @@ -3,21 +3,34 @@ // SPDX-License-Identifier: Apache-2.0 #include "CANDataSource.h" +#include "CANDataConsumer.h" +#include "CollectionInspectionAPITypes.h" +#include "IDecoderDictionary.h" +#include "MessageTypes.h" +#include "SignalTypes.h" +#include "VehicleDataSourceTypes.h" #include "WaitUntil.h" -#include +#include +#include +#include +#include #include #include #include +#include #include -#include -#include +#include #include #include -#include +#include +#include #include +#include -using namespace Aws::IoTFleetWise::TestingSupport; -using namespace Aws::IoTFleetWise::DataInspection; +namespace Aws +{ +namespace IoTFleetWise +{ static void cleanUp( int mSocketFD ) @@ -329,3 +342,6 @@ TEST_F( CANDataSourceTest, testStringToCanTimestampType ) ASSERT_EQ( timestampType, CanTimestampType::POLLING_TIME ); ASSERT_FALSE( stringToCanTimestampType( "abc", timestampType ) ); } + +} // namespace IoTFleetWise +} // namespace Aws diff --git a/src/datamanagement/datadecoding/test/CANDecoderTest.cpp b/test/unit/CANDecoderTest.cpp similarity index 98% rename from src/datamanagement/datadecoding/test/CANDecoderTest.cpp rename to test/unit/CANDecoderTest.cpp index 275862c1..0ead6456 100644 --- a/src/datamanagement/datadecoding/test/CANDecoderTest.cpp +++ b/test/unit/CANDecoderTest.cpp @@ -2,11 +2,20 @@ // SPDX-License-Identifier: Apache-2.0 #include "CANDecoder.h" +#include "CANDataTypes.h" +#include "MessageTypes.h" +#include "SignalTypes.h" +#include +#include #include #include -#include +#include +#include -using namespace Aws::IoTFleetWise::DataManagement; +namespace Aws +{ +namespace IoTFleetWise +{ TEST( CANDecoderTest, CANDecoderTestSimpleMessage ) { @@ -659,3 +668,6 @@ TEST( CANDecoderTest, CANDecoderTestSkippingOutOfBoundSignals2 ) decoder.decodeCANMessage( frameData.data(), frameSize, msgFormat, signalIDsToCollect, decodedSignals ) ); ASSERT_EQ( decodedSignals.size(), 1 ); } + +} // namespace IoTFleetWise +} // namespace Aws diff --git a/src/platform/linux/resourcemanagement/test/CPUUsageInfoTest.cpp b/test/unit/CPUUsageInfoTest.cpp similarity index 85% rename from src/platform/linux/resourcemanagement/test/CPUUsageInfoTest.cpp rename to test/unit/CPUUsageInfoTest.cpp index 011114c8..b02451b0 100644 --- a/src/platform/linux/resourcemanagement/test/CPUUsageInfoTest.cpp +++ b/test/unit/CPUUsageInfoTest.cpp @@ -3,12 +3,19 @@ // SPDX-License-Identifier: Apache-2.0 #include "CPUUsageInfo.h" - #include +#include +#include #include #include +#include +#include +#include -using namespace Aws::IoTFleetWise::Platform::Linux; +namespace Aws +{ +namespace IoTFleetWise +{ TEST( CPUUsageInfoTest, testCPUUsageInfo ) { @@ -17,10 +24,10 @@ TEST( CPUUsageInfoTest, testCPUUsageInfo ) ASSERT_TRUE( cpuUsage.reportCPUUsageInfo() ); ASSERT_GE( cpuUsage.getKernelSpaceTime(), 0 ); CPUUsageInfo::ThreadCPUUsageInfos infos; - Thread::SetCurrentThreadName( "MainCPURTest" ); + Thread::setCurrentThreadName( "MainCPURTest" ); std::thread busyThread( []() { - Thread::SetCurrentThreadName( "BusyThread" ); + Thread::setCurrentThreadName( "BusyThread" ); auto startTime = std::chrono::system_clock::now(); // busy loop for around one second for ( volatile uint64_t i = 0; i < 200000000000; i++ ) @@ -50,3 +57,6 @@ TEST( CPUUsageInfoTest, testCPUUsageInfo ) } busyThread.join(); } + +} // namespace IoTFleetWise +} // namespace Aws diff --git a/src/platform/linux/persistencymanagement/test/CacheAndPersistTest.cpp b/test/unit/CacheAndPersistTest.cpp similarity index 98% rename from src/platform/linux/persistencymanagement/test/CacheAndPersistTest.cpp rename to test/unit/CacheAndPersistTest.cpp index 598a8fc5..a072dbf6 100644 --- a/src/platform/linux/persistencymanagement/test/CacheAndPersistTest.cpp +++ b/test/unit/CacheAndPersistTest.cpp @@ -2,13 +2,20 @@ // SPDX-License-Identifier: Apache-2.0 #include "CacheAndPersist.h" -#include +#include +#include +#include #include -#include -#include +#include +#include +#include #include +#include -using namespace Aws::IoTFleetWise::Platform::Linux::PersistencyManagement; +namespace Aws +{ +namespace IoTFleetWise +{ // Unit Tests for the collectionScheme persistency TEST( CacheAndPersistTest, testCollectionSchemePersistency ) @@ -494,3 +501,6 @@ TEST( CacheAndPersistTest, testInitAfterCleanUpFunction ) ASSERT_FALSE( WIFEXITED( ret ) == 0 ); } } + +} // namespace IoTFleetWise +} // namespace Aws diff --git a/src/datamanagement/datamanager/test/CheckinAndPersistencyTest.cpp b/test/unit/CheckinAndPersistencyTest.cpp similarity index 96% rename from src/datamanagement/datamanager/test/CheckinAndPersistencyTest.cpp rename to test/unit/CheckinAndPersistencyTest.cpp index 7a79fd76..90302f52 100644 --- a/src/datamanagement/datamanager/test/CheckinAndPersistencyTest.cpp +++ b/test/unit/CheckinAndPersistencyTest.cpp @@ -1,9 +1,21 @@ // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 +#include "CANInterfaceIDTranslator.h" +#include "Clock.h" +#include "ClockHandler.h" #include "CollectionSchemeManagerMock.h" -#include "CollectionSchemeManagerTest.h" -#include +#include "CollectionSchemeManagerTest.h" // IWYU pragma: associated +#include +#include // IWYU pragma: keep +#include +#include +#include + +namespace Aws +{ +namespace IoTFleetWise +{ using ::testing::_; using ::testing::NiceMock; @@ -206,3 +218,6 @@ TEST( CollectionSchemeManagerTest2, StoreAndRetrieve ) ret = std::system( "rm -rf ./testPersist" ); ASSERT_FALSE( WIFEXITED( ret ) == 0 ); } + +} // namespace IoTFleetWise +} // namespace Aws diff --git a/src/platform/linux/timemanagement/test/ClockHandlerBenchmarkTest.cpp b/test/unit/ClockHandlerBenchmarkTest.cpp similarity index 61% rename from src/platform/linux/timemanagement/test/ClockHandlerBenchmarkTest.cpp rename to test/unit/ClockHandlerBenchmarkTest.cpp index c5866486..a4a1dfb9 100644 --- a/src/platform/linux/timemanagement/test/ClockHandlerBenchmarkTest.cpp +++ b/test/unit/ClockHandlerBenchmarkTest.cpp @@ -1,13 +1,15 @@ -#include +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 +#include "Clock.h" #include "ClockHandler.h" - -using namespace Aws::IoTFleetWise::Platform::Linux; +#include +#include static void BM_timestampToString( benchmark::State &state ) { - auto clock = ClockHandler::getClock(); + auto clock = Aws::IoTFleetWise::ClockHandler::getClock(); for ( auto _ : state ) { clock->currentTimeToIsoString(); @@ -18,7 +20,7 @@ BENCHMARK( BM_timestampToString ); static void BM_systemTimeSinceEpochMs( benchmark::State &state ) { - auto clock = ClockHandler::getClock(); + auto clock = Aws::IoTFleetWise::ClockHandler::getClock(); for ( auto _ : state ) clock->systemTimeSinceEpochMs(); } diff --git a/src/platform/linux/timemanagement/test/ClockHandlerTest.cpp b/test/unit/ClockHandlerTest.cpp similarity index 73% rename from src/platform/linux/timemanagement/test/ClockHandlerTest.cpp rename to test/unit/ClockHandlerTest.cpp index 8c054d4f..3c14e608 100644 --- a/src/platform/linux/timemanagement/test/ClockHandlerTest.cpp +++ b/test/unit/ClockHandlerTest.cpp @@ -1,12 +1,15 @@ - // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 #include "ClockHandler.h" - +#include "Clock.h" #include +#include -using namespace Aws::IoTFleetWise::Platform::Linux; +namespace Aws +{ +namespace IoTFleetWise +{ TEST( ClockHandlerTest, systemTimeSinceEpochMs ) { @@ -14,3 +17,6 @@ TEST( ClockHandlerTest, systemTimeSinceEpochMs ) ASSERT_NE( clock.get(), nullptr ); ASSERT_GT( clock->systemTimeSinceEpochMs(), 0ull ); } + +} // namespace IoTFleetWise +} // namespace Aws diff --git a/src/datamanagement/datainspection/test/CollectionInspectionEngineTest.cpp b/test/unit/CollectionInspectionEngineTest.cpp similarity index 99% rename from src/datamanagement/datainspection/test/CollectionInspectionEngineTest.cpp rename to test/unit/CollectionInspectionEngineTest.cpp index bf99a69a..dcb9cf85 100644 --- a/src/datamanagement/datainspection/test/CollectionInspectionEngineTest.cpp +++ b/test/unit/CollectionInspectionEngineTest.cpp @@ -2,14 +2,30 @@ // SPDX-License-Identifier: Apache-2.0 #include "CollectionInspectionEngine.h" +#include "CANDataTypes.h" +#include "CollectionInspectionAPITypes.h" +#include "GeohashInfo.h" +#include "ICollectionScheme.h" +#include "OBDDataTypes.h" +#include "SignalTypes.h" #include "Testing.h" +#include "TimeTypes.h" +#include +#include +#include #include #include +#include +#include +#include #include +#include +#include -using namespace Aws::IoTFleetWise::DataInspection; -using namespace Aws::IoTFleetWise::DataManagement; -using namespace Aws::IoTFleetWise::TestingSupport; +namespace Aws +{ +namespace IoTFleetWise +{ using signalTypes = ::testing::Types; @@ -1900,3 +1916,6 @@ TEST_F( CollectionInspectionEngineDoubleTest, NoCollectionSchemes ) engine.onChangeInspectionMatrix( consCollectionSchemes ); ASSERT_FALSE( engine.evaluateConditions( timestamp ) ); } + +} // namespace IoTFleetWise +} // namespace Aws diff --git a/src/datamanagement/datainspection/test/CollectionInspectionWorkerThreadTest.cpp b/test/unit/CollectionInspectionWorkerThreadTest.cpp similarity index 97% rename from src/datamanagement/datainspection/test/CollectionInspectionWorkerThreadTest.cpp rename to test/unit/CollectionInspectionWorkerThreadTest.cpp index 04313579..0c939efd 100644 --- a/src/datamanagement/datainspection/test/CollectionInspectionWorkerThreadTest.cpp +++ b/test/unit/CollectionInspectionWorkerThreadTest.cpp @@ -2,15 +2,30 @@ // SPDX-License-Identifier: Apache-2.0 #include "CollectionInspectionWorkerThread.h" +#include "CANDataTypes.h" +#include "Clock.h" +#include "ClockHandler.h" +#include "CollectionInspectionAPITypes.h" +#include "ICollectionScheme.h" +#include "OBDDataTypes.h" +#include "SignalTypes.h" +#include "TimeTypes.h" #include "WaitUntil.h" -#include +#include +#include +#include +#include +#include #include -#include +#include +#include #include +#include -using namespace Aws::IoTFleetWise::DataInspection; -using namespace Aws::IoTFleetWise::DataManagement; -using namespace Aws::IoTFleetWise::TestingSupport; +namespace Aws +{ +namespace IoTFleetWise +{ class CollectionInspectionWorkerThreadTest : public ::testing::Test { @@ -376,3 +391,6 @@ TEST_F( CollectionInspectionWorkerThreadTest, StartWithoutInit ) CollectionInspectionWorkerThread worker; worker.onChangeInspectionMatrix( consCollectionSchemes ); } + +} // namespace IoTFleetWise +} // namespace Aws diff --git a/src/datamanagement/datamanager/test/CollectionSchemeManagerGtest.cpp b/test/unit/CollectionSchemeManagerGtest.cpp similarity index 98% rename from src/datamanagement/datamanager/test/CollectionSchemeManagerGtest.cpp rename to test/unit/CollectionSchemeManagerGtest.cpp index d89fda4d..d9023c73 100644 --- a/src/datamanagement/datamanager/test/CollectionSchemeManagerGtest.cpp +++ b/test/unit/CollectionSchemeManagerGtest.cpp @@ -1,16 +1,25 @@ // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 +#include "CANInterfaceIDTranslator.h" +#include "Clock.h" +#include "ClockHandler.h" #include "CollectionSchemeManagerMock.h" -#include "CollectionSchemeManagerTest.h" +#include "CollectionSchemeManagerTest.h" // IWYU pragma: associated #include "Testing.h" -#include +#include +#include +#include + +namespace Aws +{ +namespace IoTFleetWise +{ using ::testing::_; using ::testing::NiceMock; using ::testing::Return; using ::testing::ReturnRef; -using namespace Aws::IoTFleetWise::TestingSupport; /** @brief * This test validates the life cycle of the Collection Schemes as they get @@ -577,3 +586,6 @@ TEST( CollectionSchemeManagerGtest, checkTimeLineTest_ENABLED_BRANCHES ) // branch out startTime > currTime ASSERT_FALSE( gmocktest.checkTimeLine( currTime + 400 ) ); } + +} // namespace IoTFleetWise +} // namespace Aws diff --git a/src/datamanagement/datamanager/test/CollectionSchemeManagerTest.cpp b/test/unit/CollectionSchemeManagerTest.cpp similarity index 97% rename from src/datamanagement/datamanager/test/CollectionSchemeManagerTest.cpp rename to test/unit/CollectionSchemeManagerTest.cpp index 930c78b0..c345f29c 100644 --- a/src/datamanagement/datamanager/test/CollectionSchemeManagerTest.cpp +++ b/test/unit/CollectionSchemeManagerTest.cpp @@ -2,9 +2,19 @@ // SPDX-License-Identifier: Apache-2.0 #include "CollectionSchemeManagerTest.h" +#include "CANInterfaceIDTranslator.h" +#include "Clock.h" +#include "ClockHandler.h" #include "WaitUntil.h" +#include +#include +#include +#include -using namespace Aws::IoTFleetWise::TestingSupport; +namespace Aws +{ +namespace IoTFleetWise +{ /**********************test body ***********************************************/ TEST( CollectionSchemeManagerTest, StopMainTest ) @@ -257,3 +267,6 @@ TEST( CollectionSchemeManagerTest, getCollectionSchemeArns ) /* stopping main thread servicing a collectionScheme ending in 25 seconds */ WAIT_ASSERT_TRUE( test.disconnect() ); } + +} // namespace IoTFleetWise +} // namespace Aws diff --git a/src/datamanagement/custom/generic/test/CustomDataSourceTest.cpp b/test/unit/CustomDataSourceTest.cpp similarity index 92% rename from src/datamanagement/custom/generic/test/CustomDataSourceTest.cpp rename to test/unit/CustomDataSourceTest.cpp index 14aa1502..954b9367 100644 --- a/src/datamanagement/custom/generic/test/CustomDataSourceTest.cpp +++ b/test/unit/CustomDataSourceTest.cpp @@ -2,9 +2,23 @@ // SPDX-License-Identifier: Apache-2.0 #include "CustomDataSource.h" +#include "IDecoderDictionary.h" +#include "MessageTypes.h" +#include "SignalTypes.h" +#include "VehicleDataSourceTypes.h" +#include +#include #include #include +#include #include +#include +#include + +namespace Aws +{ +namespace IoTFleetWise +{ using ::testing::_; using ::testing::AnyNumber; @@ -17,9 +31,6 @@ using ::testing::Return; using ::testing::ReturnRef; using ::testing::SaveArg; using ::testing::SaveArgPointee; -#include "CollectionInspectionAPITypes.h" - -using namespace Aws::IoTFleetWise::DataManagement; class CustomDataSourceTestImplementation : public CustomDataSource { @@ -106,3 +117,6 @@ TEST_F( CustomDataSourceTest, pollIntervalChanges ) EXPECT_CALL( implementationMock, pollData() ).Times( Between( 8, 12 ) ); std::this_thread::sleep_for( std::chrono::milliseconds( 500 ) ); } + +} // namespace IoTFleetWise +} // namespace Aws diff --git a/test/unit/DataSenderManagerTest.cpp b/test/unit/DataSenderManagerTest.cpp new file mode 100644 index 00000000..70f3411b --- /dev/null +++ b/test/unit/DataSenderManagerTest.cpp @@ -0,0 +1,561 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +#include "DataSenderManager.h" +#include "CANDataTypes.h" +#include "CANInterfaceIDTranslator.h" +#include "CacheAndPersist.h" +#include "CollectionInspectionAPITypes.h" +#include "GeohashInfo.h" +#include "IConnectionTypes.h" +#include "ISender.h" +#include "OBDDataTypes.h" +#include "PayloadManagerMock.h" +#include "SenderMock.h" +#include "SignalTypes.h" +#include "vehicle_data.pb.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace Aws +{ +namespace IoTFleetWise +{ + +using ::testing::_; +using ::testing::DoAll; +using ::testing::Gt; +using ::testing::Invoke; +using ::testing::Return; +using ::testing::SetArgReferee; +using ::testing::StrictMock; + +class DataSenderManagerTest : public ::testing::Test +{ +public: + void + SetUp() override + { + mTriggeredCollectionSchemeData = std::make_shared(); + mTriggeredCollectionSchemeData->metadata.decoderID = "TESTDECODERID"; + mTriggeredCollectionSchemeData->metadata.collectionSchemeID = "TESTCOLLECTIONSCHEME"; + mTriggeredCollectionSchemeData->triggerTime = 1000000; + mTriggeredCollectionSchemeData->eventID = 579; + + mCANIDTranslator.add( "can123" ); + + mMqttSender = std::make_shared>(); + mPayloadManager = std::make_shared>(); + mDataSenderManager = + std::make_unique( mMqttSender, mPayloadManager, mCANIDTranslator, mTransmitThreshold ); + } + + void + TearDown() override + { + } + +protected: + unsigned mTransmitThreshold{ 5 }; // max number of messages that can be sent to cloud at one time + unsigned mCanChannelID{ 0 }; + std::shared_ptr mTriggeredCollectionSchemeData; + std::shared_ptr> mMqttSender; + std::shared_ptr> mPayloadManager; + CANInterfaceIDTranslator mCANIDTranslator; + std::unique_ptr mDataSenderManager; +}; + +TEST_F( DataSenderManagerTest, ProcessEmptyData ) +{ + EXPECT_CALL( *mMqttSender, mockedSendBuffer( _, _, _ ) ).Times( 0 ); + + // It should just not crash + mDataSenderManager->processCollectedData( nullptr ); +} + +TEST_F( DataSenderManagerTest, ProcessSingleSignal ) +{ + auto signal1 = CollectedSignal( 1234, 789654, 40.5, SignalType::DOUBLE ); + mTriggeredCollectionSchemeData->signals.push_back( signal1 ); + + EXPECT_CALL( *mMqttSender, mockedSendBuffer( _, Gt( 0 ), _ ) ).WillOnce( Return( ConnectivityError::Success ) ); + + mDataSenderManager->processCollectedData( mTriggeredCollectionSchemeData ); + + ASSERT_EQ( mMqttSender->getSentBufferData().size(), 1 ); + auto sentBufferData = mMqttSender->getSentBufferData(); + + auto collectionSchemeParams = sentBufferData[0].collectionSchemeParams; + ASSERT_EQ( collectionSchemeParams.eventID, mTriggeredCollectionSchemeData->eventID ); + ASSERT_EQ( collectionSchemeParams.triggerTime, mTriggeredCollectionSchemeData->triggerTime ); + ASSERT_EQ( collectionSchemeParams.compression, mTriggeredCollectionSchemeData->metadata.compress ); + ASSERT_EQ( collectionSchemeParams.persist, mTriggeredCollectionSchemeData->metadata.persist ); + + Schemas::VehicleDataMsg::VehicleData vehicleData; + ASSERT_TRUE( vehicleData.ParseFromString( sentBufferData[0].data ) ); + + ASSERT_EQ( vehicleData.captured_signals_size(), 1 ); + ASSERT_EQ( vehicleData.can_frames_size(), 0 ); + ASSERT_FALSE( vehicleData.has_dtc_data() ); + ASSERT_FALSE( vehicleData.has_geohash() ); + + ASSERT_EQ( vehicleData.captured_signals()[0].signal_id(), signal1.signalID ); + ASSERT_EQ( vehicleData.captured_signals()[0].double_value(), signal1.value.value.doubleVal ); +} + +TEST_F( DataSenderManagerTest, ProcessMultipleSignals ) +{ + auto signal1 = CollectedSignal( 1234, 789654, 40.5, SignalType::DOUBLE ); + auto signal2 = CollectedSignal( 1234, 789700, 42.5, SignalType::DOUBLE ); + auto signal3 = CollectedSignal( 5678, 789980, 22.5, SignalType::DOUBLE ); + mTriggeredCollectionSchemeData->signals.push_back( signal1 ); + mTriggeredCollectionSchemeData->signals.push_back( signal2 ); + mTriggeredCollectionSchemeData->signals.push_back( signal3 ); + + EXPECT_CALL( *mMqttSender, mockedSendBuffer( _, Gt( 0 ), _ ) ).WillOnce( Return( ConnectivityError::Success ) ); + + mDataSenderManager->processCollectedData( mTriggeredCollectionSchemeData ); + + ASSERT_EQ( mMqttSender->getSentBufferData().size(), 1 ); + auto sentBufferData = mMqttSender->getSentBufferData(); + + auto collectionSchemeParams = sentBufferData[0].collectionSchemeParams; + ASSERT_EQ( collectionSchemeParams.eventID, mTriggeredCollectionSchemeData->eventID ); + ASSERT_EQ( collectionSchemeParams.triggerTime, mTriggeredCollectionSchemeData->triggerTime ); + ASSERT_EQ( collectionSchemeParams.compression, mTriggeredCollectionSchemeData->metadata.compress ); + ASSERT_EQ( collectionSchemeParams.persist, mTriggeredCollectionSchemeData->metadata.persist ); + + Schemas::VehicleDataMsg::VehicleData vehicleData; + ASSERT_TRUE( vehicleData.ParseFromString( sentBufferData[0].data ) ); + + ASSERT_EQ( vehicleData.captured_signals_size(), 3 ); + ASSERT_EQ( vehicleData.can_frames_size(), 0 ); + ASSERT_FALSE( vehicleData.has_dtc_data() ); + ASSERT_FALSE( vehicleData.has_geohash() ); + + ASSERT_EQ( vehicleData.captured_signals()[0].signal_id(), signal1.signalID ); + ASSERT_EQ( vehicleData.captured_signals()[0].double_value(), signal1.value.value.doubleVal ); + ASSERT_EQ( vehicleData.captured_signals()[1].signal_id(), signal2.signalID ); + ASSERT_EQ( vehicleData.captured_signals()[1].double_value(), signal2.value.value.doubleVal ); + ASSERT_EQ( vehicleData.captured_signals()[2].signal_id(), signal3.signalID ); + ASSERT_EQ( vehicleData.captured_signals()[2].double_value(), signal3.value.value.doubleVal ); +} + +TEST_F( DataSenderManagerTest, ProcessMultipleSignalsBeyondTransmitThreshold ) +{ + std::vector signals = { CollectedSignal( 1234, 789654, 40.5, SignalType::DOUBLE ), + CollectedSignal( 1234, 789654, 40.5, SignalType::DOUBLE ), + CollectedSignal( 1234, 789654, 40.5, SignalType::DOUBLE ), + CollectedSignal( 1234, 789654, 40.5, SignalType::DOUBLE ), + CollectedSignal( 1234, 789654, 40.5, SignalType::DOUBLE ), + CollectedSignal( 1234, 789654, 40.5, SignalType::DOUBLE ), + CollectedSignal( 1234, 789654, 40.5, SignalType::DOUBLE ), + CollectedSignal( 1234, 789654, 40.5, SignalType::DOUBLE ), + CollectedSignal( 1234, 789654, 40.5, SignalType::DOUBLE ) }; + mTriggeredCollectionSchemeData->signals = signals; + + EXPECT_CALL( *mMqttSender, mockedSendBuffer( _, Gt( 0 ), _ ) ) + .Times( 2 ) + .WillRepeatedly( Return( ConnectivityError::Success ) ); + + mDataSenderManager->processCollectedData( mTriggeredCollectionSchemeData ); + + ASSERT_EQ( mMqttSender->getSentBufferData().size(), 2 ); + auto sentBufferData = mMqttSender->getSentBufferData(); + + auto collectionSchemeParams = sentBufferData[0].collectionSchemeParams; + ASSERT_EQ( collectionSchemeParams.eventID, mTriggeredCollectionSchemeData->eventID ); + ASSERT_EQ( collectionSchemeParams.triggerTime, mTriggeredCollectionSchemeData->triggerTime ); + ASSERT_EQ( collectionSchemeParams.compression, mTriggeredCollectionSchemeData->metadata.compress ); + ASSERT_EQ( collectionSchemeParams.persist, mTriggeredCollectionSchemeData->metadata.persist ); + + collectionSchemeParams = sentBufferData[1].collectionSchemeParams; + ASSERT_EQ( collectionSchemeParams.eventID, mTriggeredCollectionSchemeData->eventID ); + ASSERT_EQ( collectionSchemeParams.triggerTime, mTriggeredCollectionSchemeData->triggerTime ); + ASSERT_EQ( collectionSchemeParams.compression, mTriggeredCollectionSchemeData->metadata.compress ); + ASSERT_EQ( collectionSchemeParams.persist, mTriggeredCollectionSchemeData->metadata.persist ); + + Schemas::VehicleDataMsg::VehicleData vehicleData; + ASSERT_TRUE( vehicleData.ParseFromString( sentBufferData[0].data ) ); + + ASSERT_EQ( vehicleData.captured_signals_size(), 5 ); + ASSERT_EQ( vehicleData.can_frames_size(), 0 ); + ASSERT_FALSE( vehicleData.has_dtc_data() ); + ASSERT_FALSE( vehicleData.has_geohash() ); + + ASSERT_TRUE( vehicleData.ParseFromString( sentBufferData[1].data ) ); + + ASSERT_EQ( vehicleData.captured_signals_size(), 4 ); + ASSERT_EQ( vehicleData.can_frames_size(), 0 ); + ASSERT_FALSE( vehicleData.has_dtc_data() ); + ASSERT_FALSE( vehicleData.has_geohash() ); +} + +TEST_F( DataSenderManagerTest, ProcessSingleCanFrame ) +{ + std::array canBuf1 = { 0xDE, 0xAD, 0xBE, 0xEF, 0x0, 0x0, 0x0, 0x0 }; + auto canFrame1 = CollectedCanRawFrame( 0x380, mCanChannelID, 789654, canBuf1, sizeof( canBuf1 ) ); + mTriggeredCollectionSchemeData->canFrames.push_back( canFrame1 ); + + EXPECT_CALL( *mMqttSender, mockedSendBuffer( _, Gt( 0 ), _ ) ).WillOnce( Return( ConnectivityError::Success ) ); + + mDataSenderManager->processCollectedData( mTriggeredCollectionSchemeData ); + + ASSERT_EQ( mMqttSender->getSentBufferData().size(), 1 ); + auto sentBufferData = mMqttSender->getSentBufferData(); + + auto collectionSchemeParams = sentBufferData[0].collectionSchemeParams; + ASSERT_EQ( collectionSchemeParams.eventID, mTriggeredCollectionSchemeData->eventID ); + ASSERT_EQ( collectionSchemeParams.triggerTime, mTriggeredCollectionSchemeData->triggerTime ); + ASSERT_EQ( collectionSchemeParams.compression, mTriggeredCollectionSchemeData->metadata.compress ); + ASSERT_EQ( collectionSchemeParams.persist, mTriggeredCollectionSchemeData->metadata.persist ); + + Schemas::VehicleDataMsg::VehicleData vehicleData; + ASSERT_TRUE( vehicleData.ParseFromString( sentBufferData[0].data ) ); + + ASSERT_EQ( vehicleData.captured_signals_size(), 0 ); + ASSERT_EQ( vehicleData.can_frames_size(), 1 ); + ASSERT_FALSE( vehicleData.has_dtc_data() ); + ASSERT_FALSE( vehicleData.has_geohash() ); + + ASSERT_EQ( vehicleData.can_frames()[0].message_id(), canFrame1.frameID ); + ASSERT_EQ( vehicleData.can_frames()[0].interface_id(), "can123" ); + ASSERT_EQ( vehicleData.can_frames()[0].byte_values(), std::string( canBuf1.begin(), canBuf1.end() ) ); +} + +TEST_F( DataSenderManagerTest, ProcessMultipleCanFrames ) +{ + std::array canBuf1 = { 0xDE, 0xAD, 0xBE, 0xEF, 0x0, 0x0, 0x0, 0x0 }; + auto canFrame1 = CollectedCanRawFrame( 0x380, mCanChannelID, 789654, canBuf1, sizeof( canBuf1 ) ); + std::array canBuf2 = { 0xBA, 0xAD, 0xAF, 0xFE, 0x0, 0x0, 0x0, 0x0 }; + auto canFrame2 = CollectedCanRawFrame( 0x380, mCanChannelID, 789654, canBuf2, sizeof( canBuf2 ) ); + std::array canBuf3 = { 0xCA, 0xFE, 0xF0, 0x0D, 0x0, 0x0, 0x0, 0x0 }; + auto canFrame3 = CollectedCanRawFrame( 0x380, mCanChannelID, 789654, canBuf3, sizeof( canBuf3 ) ); + + mTriggeredCollectionSchemeData->canFrames.push_back( canFrame1 ); + mTriggeredCollectionSchemeData->canFrames.push_back( canFrame2 ); + mTriggeredCollectionSchemeData->canFrames.push_back( canFrame3 ); + + EXPECT_CALL( *mMqttSender, mockedSendBuffer( _, Gt( 0 ), _ ) ).WillOnce( Return( ConnectivityError::Success ) ); + + mDataSenderManager->processCollectedData( mTriggeredCollectionSchemeData ); + + ASSERT_EQ( mMqttSender->getSentBufferData().size(), 1 ); + auto sentBufferData = mMqttSender->getSentBufferData(); + + auto collectionSchemeParams = sentBufferData[0].collectionSchemeParams; + ASSERT_EQ( collectionSchemeParams.eventID, mTriggeredCollectionSchemeData->eventID ); + ASSERT_EQ( collectionSchemeParams.triggerTime, mTriggeredCollectionSchemeData->triggerTime ); + ASSERT_EQ( collectionSchemeParams.compression, mTriggeredCollectionSchemeData->metadata.compress ); + ASSERT_EQ( collectionSchemeParams.persist, mTriggeredCollectionSchemeData->metadata.persist ); + + Schemas::VehicleDataMsg::VehicleData vehicleData; + ASSERT_TRUE( vehicleData.ParseFromString( sentBufferData[0].data ) ); + + ASSERT_EQ( vehicleData.captured_signals_size(), 0 ); + ASSERT_EQ( vehicleData.can_frames_size(), 3 ); + ASSERT_FALSE( vehicleData.has_dtc_data() ); + ASSERT_FALSE( vehicleData.has_geohash() ); + + ASSERT_EQ( vehicleData.can_frames()[0].message_id(), canFrame1.frameID ); + ASSERT_EQ( vehicleData.can_frames()[0].interface_id(), "can123" ); + ASSERT_EQ( vehicleData.can_frames()[0].byte_values(), std::string( canBuf1.begin(), canBuf1.end() ) ); + ASSERT_EQ( vehicleData.can_frames()[1].message_id(), canFrame2.frameID ); + ASSERT_EQ( vehicleData.can_frames()[1].interface_id(), "can123" ); + ASSERT_EQ( vehicleData.can_frames()[1].byte_values(), std::string( canBuf2.begin(), canBuf2.end() ) ); + ASSERT_EQ( vehicleData.can_frames()[2].message_id(), canFrame3.frameID ); + ASSERT_EQ( vehicleData.can_frames()[2].interface_id(), "can123" ); + ASSERT_EQ( vehicleData.can_frames()[2].byte_values(), std::string( canBuf3.begin(), canBuf3.end() ) ); +} + +TEST_F( DataSenderManagerTest, ProcessMultipleCanFramesBeyondTransmitThreshold ) +{ + std::array canBuf1 = { 0xDE, 0xAD, 0xBE, 0xEF, 0x0, 0x0, 0x0, 0x0 }; + std::vector canFrames = { + CollectedCanRawFrame( 0x380, mCanChannelID, 789654, canBuf1, sizeof( canBuf1 ) ), + CollectedCanRawFrame( 0x380, mCanChannelID, 789654, canBuf1, sizeof( canBuf1 ) ), + CollectedCanRawFrame( 0x380, mCanChannelID, 789654, canBuf1, sizeof( canBuf1 ) ), + CollectedCanRawFrame( 0x380, mCanChannelID, 789654, canBuf1, sizeof( canBuf1 ) ), + CollectedCanRawFrame( 0x380, mCanChannelID, 789654, canBuf1, sizeof( canBuf1 ) ), + CollectedCanRawFrame( 0x380, mCanChannelID, 789654, canBuf1, sizeof( canBuf1 ) ), + CollectedCanRawFrame( 0x380, mCanChannelID, 789654, canBuf1, sizeof( canBuf1 ) ), + CollectedCanRawFrame( 0x380, mCanChannelID, 789654, canBuf1, sizeof( canBuf1 ) ), + CollectedCanRawFrame( 0x380, mCanChannelID, 789654, canBuf1, sizeof( canBuf1 ) ) }; + mTriggeredCollectionSchemeData->canFrames = canFrames; + + EXPECT_CALL( *mMqttSender, mockedSendBuffer( _, Gt( 0 ), _ ) ) + .Times( 2 ) + .WillRepeatedly( Return( ConnectivityError::Success ) ); + + mDataSenderManager->processCollectedData( mTriggeredCollectionSchemeData ); + + ASSERT_EQ( mMqttSender->getSentBufferData().size(), 2 ); + auto sentBufferData = mMqttSender->getSentBufferData(); + + auto collectionSchemeParams = sentBufferData[0].collectionSchemeParams; + ASSERT_EQ( collectionSchemeParams.eventID, mTriggeredCollectionSchemeData->eventID ); + ASSERT_EQ( collectionSchemeParams.triggerTime, mTriggeredCollectionSchemeData->triggerTime ); + ASSERT_EQ( collectionSchemeParams.compression, mTriggeredCollectionSchemeData->metadata.compress ); + ASSERT_EQ( collectionSchemeParams.persist, mTriggeredCollectionSchemeData->metadata.persist ); + + collectionSchemeParams = sentBufferData[1].collectionSchemeParams; + ASSERT_EQ( collectionSchemeParams.eventID, mTriggeredCollectionSchemeData->eventID ); + ASSERT_EQ( collectionSchemeParams.triggerTime, mTriggeredCollectionSchemeData->triggerTime ); + ASSERT_EQ( collectionSchemeParams.compression, mTriggeredCollectionSchemeData->metadata.compress ); + ASSERT_EQ( collectionSchemeParams.persist, mTriggeredCollectionSchemeData->metadata.persist ); + + Schemas::VehicleDataMsg::VehicleData vehicleData; + ASSERT_TRUE( vehicleData.ParseFromString( sentBufferData[0].data ) ); + + ASSERT_EQ( vehicleData.captured_signals_size(), 0 ); + ASSERT_EQ( vehicleData.can_frames_size(), 5 ); + ASSERT_FALSE( vehicleData.has_dtc_data() ); + ASSERT_FALSE( vehicleData.has_geohash() ); + + ASSERT_TRUE( vehicleData.ParseFromString( sentBufferData[1].data ) ); + + ASSERT_EQ( vehicleData.captured_signals_size(), 0 ); + ASSERT_EQ( vehicleData.can_frames_size(), 4 ); + ASSERT_FALSE( vehicleData.has_dtc_data() ); + ASSERT_FALSE( vehicleData.has_geohash() ); +} + +TEST_F( DataSenderManagerTest, ProcessSingleDtcCode ) +{ + DTCInfo dtcInfo; + dtcInfo.mSID = SID::STORED_DTC; + dtcInfo.receiveTime = 789654; + dtcInfo.mDTCCodes.emplace_back( "P0143" ); + mTriggeredCollectionSchemeData->mDTCInfo = dtcInfo; + + EXPECT_CALL( *mMqttSender, mockedSendBuffer( _, Gt( 0 ), _ ) ).WillOnce( Return( ConnectivityError::Success ) ); + + mDataSenderManager->processCollectedData( mTriggeredCollectionSchemeData ); + + ASSERT_EQ( mMqttSender->getSentBufferData().size(), 1 ); + auto sentBufferData = mMqttSender->getSentBufferData(); + + auto collectionSchemeParams = sentBufferData[0].collectionSchemeParams; + ASSERT_EQ( collectionSchemeParams.eventID, mTriggeredCollectionSchemeData->eventID ); + ASSERT_EQ( collectionSchemeParams.triggerTime, mTriggeredCollectionSchemeData->triggerTime ); + ASSERT_EQ( collectionSchemeParams.compression, mTriggeredCollectionSchemeData->metadata.compress ); + ASSERT_EQ( collectionSchemeParams.persist, mTriggeredCollectionSchemeData->metadata.persist ); + + Schemas::VehicleDataMsg::VehicleData vehicleData; + ASSERT_TRUE( vehicleData.ParseFromString( sentBufferData[0].data ) ); + + ASSERT_EQ( vehicleData.captured_signals_size(), 0 ); + ASSERT_EQ( vehicleData.can_frames_size(), 0 ); + ASSERT_TRUE( vehicleData.has_dtc_data() ); + ASSERT_FALSE( vehicleData.has_geohash() ); + + ASSERT_EQ( vehicleData.dtc_data().active_dtc_codes_size(), 1 ); + ASSERT_EQ( vehicleData.dtc_data().active_dtc_codes()[0], "P0143" ); +} + +TEST_F( DataSenderManagerTest, ProcessMultipleDtcCodes ) +{ + DTCInfo dtcInfo; + dtcInfo.mSID = SID::STORED_DTC; + dtcInfo.receiveTime = 789654; + dtcInfo.mDTCCodes.emplace_back( "P0143" ); + dtcInfo.mDTCCodes.emplace_back( "C0196" ); + mTriggeredCollectionSchemeData->mDTCInfo = dtcInfo; + + EXPECT_CALL( *mMqttSender, mockedSendBuffer( _, Gt( 0 ), _ ) ).WillOnce( Return( ConnectivityError::Success ) ); + + mDataSenderManager->processCollectedData( mTriggeredCollectionSchemeData ); + + ASSERT_EQ( mMqttSender->getSentBufferData().size(), 1 ); + auto sentBufferData = mMqttSender->getSentBufferData(); + + auto collectionSchemeParams = sentBufferData[0].collectionSchemeParams; + ASSERT_EQ( collectionSchemeParams.eventID, mTriggeredCollectionSchemeData->eventID ); + ASSERT_EQ( collectionSchemeParams.triggerTime, mTriggeredCollectionSchemeData->triggerTime ); + ASSERT_EQ( collectionSchemeParams.compression, mTriggeredCollectionSchemeData->metadata.compress ); + ASSERT_EQ( collectionSchemeParams.persist, mTriggeredCollectionSchemeData->metadata.persist ); + + Schemas::VehicleDataMsg::VehicleData vehicleData; + ASSERT_TRUE( vehicleData.ParseFromString( sentBufferData[0].data ) ); + + ASSERT_EQ( vehicleData.captured_signals_size(), 0 ); + ASSERT_EQ( vehicleData.can_frames_size(), 0 ); + ASSERT_TRUE( vehicleData.has_dtc_data() ); + ASSERT_FALSE( vehicleData.has_geohash() ); + + ASSERT_EQ( vehicleData.dtc_data().active_dtc_codes_size(), 2 ); + ASSERT_EQ( vehicleData.dtc_data().active_dtc_codes()[0], "P0143" ); + ASSERT_EQ( vehicleData.dtc_data().active_dtc_codes()[1], "C0196" ); +} + +TEST_F( DataSenderManagerTest, ProcessMultipleDtcCodesBeyondTransmitThreshold ) +{ + std::vector dtcCodes = { + "P0143", "C0196", "U0148", "B0148", "C0148", "C0149", "C0150", "C0151", "C0152" }; + + DTCInfo dtcInfo; + dtcInfo.mSID = SID::STORED_DTC; + dtcInfo.receiveTime = 789654; + dtcInfo.mDTCCodes = dtcCodes; + mTriggeredCollectionSchemeData->mDTCInfo = dtcInfo; + + EXPECT_CALL( *mMqttSender, mockedSendBuffer( _, Gt( 0 ), _ ) ) + .Times( 2 ) + .WillRepeatedly( Return( ConnectivityError::Success ) ); + + mDataSenderManager->processCollectedData( mTriggeredCollectionSchemeData ); + + ASSERT_EQ( mMqttSender->getSentBufferData().size(), 2 ); + auto sentBufferData = mMqttSender->getSentBufferData(); + + auto collectionSchemeParams = sentBufferData[0].collectionSchemeParams; + ASSERT_EQ( collectionSchemeParams.eventID, mTriggeredCollectionSchemeData->eventID ); + ASSERT_EQ( collectionSchemeParams.triggerTime, mTriggeredCollectionSchemeData->triggerTime ); + ASSERT_EQ( collectionSchemeParams.compression, mTriggeredCollectionSchemeData->metadata.compress ); + ASSERT_EQ( collectionSchemeParams.persist, mTriggeredCollectionSchemeData->metadata.persist ); + + Schemas::VehicleDataMsg::VehicleData vehicleData; + ASSERT_TRUE( vehicleData.ParseFromString( sentBufferData[0].data ) ); + + ASSERT_EQ( vehicleData.captured_signals_size(), 0 ); + ASSERT_EQ( vehicleData.can_frames_size(), 0 ); + ASSERT_TRUE( vehicleData.has_dtc_data() ); + ASSERT_FALSE( vehicleData.has_geohash() ); + ASSERT_EQ( vehicleData.dtc_data().active_dtc_codes_size(), 5 ); + + ASSERT_TRUE( vehicleData.ParseFromString( sentBufferData[1].data ) ); + + ASSERT_EQ( vehicleData.captured_signals_size(), 0 ); + ASSERT_EQ( vehicleData.can_frames_size(), 0 ); + ASSERT_TRUE( vehicleData.has_dtc_data() ); + ASSERT_FALSE( vehicleData.has_geohash() ); + ASSERT_EQ( vehicleData.dtc_data().active_dtc_codes_size(), 4 ); +} + +TEST_F( DataSenderManagerTest, ProcessGeohash ) +{ + GeohashInfo geohashInfo; + geohashInfo.mGeohashString = "9q9hwg28j"; + mTriggeredCollectionSchemeData->mGeohashInfo = geohashInfo; + + // TODO: verify data and collectionSchemeParams (3rd parameter) + EXPECT_CALL( *mMqttSender, mockedSendBuffer( _, Gt( 0 ), _ ) ).WillOnce( Return( ConnectivityError::Success ) ); + + mDataSenderManager->processCollectedData( mTriggeredCollectionSchemeData ); + + ASSERT_EQ( mMqttSender->getSentBufferData().size(), 1 ); + auto sentBufferData = mMqttSender->getSentBufferData(); + + auto collectionSchemeParams = sentBufferData[0].collectionSchemeParams; + ASSERT_EQ( collectionSchemeParams.eventID, mTriggeredCollectionSchemeData->eventID ); + ASSERT_EQ( collectionSchemeParams.triggerTime, mTriggeredCollectionSchemeData->triggerTime ); + ASSERT_EQ( collectionSchemeParams.compression, mTriggeredCollectionSchemeData->metadata.compress ); + ASSERT_EQ( collectionSchemeParams.persist, mTriggeredCollectionSchemeData->metadata.persist ); + + Schemas::VehicleDataMsg::VehicleData vehicleData; + ASSERT_TRUE( vehicleData.ParseFromString( sentBufferData[0].data ) ); + + ASSERT_EQ( vehicleData.captured_signals_size(), 0 ); + ASSERT_EQ( vehicleData.can_frames_size(), 0 ); + ASSERT_FALSE( vehicleData.has_dtc_data() ); + ASSERT_TRUE( vehicleData.has_geohash() ); + + ASSERT_EQ( vehicleData.geohash().geohash_string(), "9q9hwg28j" ); +} + +TEST_F( DataSenderManagerTest, PersistencyNoFiles ) +{ + Json::Value files( Json::arrayValue ); + + EXPECT_CALL( *mPayloadManager, retrievePayloadMetadata( _ ) ) + .WillOnce( DoAll( SetArgReferee<0>( files ), Return( ErrorCode::SUCCESS ) ) ); + + EXPECT_CALL( *mMqttSender, sendFile( _, _, _ ) ).Times( 0 ); + + mDataSenderManager->checkAndSendRetrievedData(); +} + +TEST_F( DataSenderManagerTest, ProcessSingleSignalWithCompression ) +{ + auto signal1 = CollectedSignal( 1234, 789654, 40.5, SignalType::DOUBLE ); + mTriggeredCollectionSchemeData->signals.push_back( signal1 ); + mTriggeredCollectionSchemeData->metadata.compress = true; + + EXPECT_CALL( *mMqttSender, mockedSendBuffer( _, Gt( 0 ), _ ) ).WillOnce( Return( ConnectivityError::Success ) ); + + mDataSenderManager->processCollectedData( mTriggeredCollectionSchemeData ); + + ASSERT_EQ( mMqttSender->getSentBufferData().size(), 1 ); + auto sentBufferData = mMqttSender->getSentBufferData(); + + auto collectionSchemeParams = sentBufferData[0].collectionSchemeParams; + ASSERT_EQ( collectionSchemeParams.eventID, mTriggeredCollectionSchemeData->eventID ); + ASSERT_EQ( collectionSchemeParams.triggerTime, mTriggeredCollectionSchemeData->triggerTime ); + ASSERT_EQ( collectionSchemeParams.compression, mTriggeredCollectionSchemeData->metadata.compress ); + ASSERT_EQ( collectionSchemeParams.persist, mTriggeredCollectionSchemeData->metadata.persist ); + + Schemas::VehicleDataMsg::VehicleData vehicleData; + std::string uncompressedData; + snappy::Uncompress( sentBufferData[0].data.c_str(), sentBufferData[0].data.size(), &uncompressedData ); + ASSERT_TRUE( vehicleData.ParseFromString( uncompressedData ) ); + + ASSERT_EQ( vehicleData.captured_signals_size(), 1 ); + ASSERT_EQ( vehicleData.can_frames_size(), 0 ); + ASSERT_FALSE( vehicleData.has_dtc_data() ); + ASSERT_FALSE( vehicleData.has_geohash() ); + + ASSERT_EQ( vehicleData.captured_signals()[0].signal_id(), signal1.signalID ); + ASSERT_EQ( vehicleData.captured_signals()[0].double_value(), signal1.value.value.doubleVal ); +} + +TEST_F( DataSenderManagerTest, PersistencySingleFile ) +{ + Json::Value files( Json::arrayValue ); + + files.append( Json::objectValue ); + files[0]["filename"] = "filename1"; + files[0]["compressionRequired"] = false; + files[0]["payloadSize"] = 1000; + + EXPECT_CALL( *mPayloadManager, retrievePayloadMetadata( _ ) ) + .WillOnce( DoAll( SetArgReferee<0>( files ), Return( ErrorCode::SUCCESS ) ) ); + + EXPECT_CALL( *mMqttSender, sendFile( "filename1", 1000, _ ) ).WillOnce( Return( ConnectivityError::Success ) ); + + mDataSenderManager->checkAndSendRetrievedData(); +} + +TEST_F( DataSenderManagerTest, PersistencyMultipleFiles ) +{ + Json::Value files( Json::arrayValue ); + + files.append( Json::objectValue ); + files[0]["filename"] = "filename1"; + files[0]["compressionRequired"] = false; + files[0]["payloadSize"] = 1000; + + files.append( Json::objectValue ); + files[1]["filename"] = "filename2"; + files[1]["compressionRequired"] = false; + files[1]["payloadSize"] = 3000; + + EXPECT_CALL( *mPayloadManager, retrievePayloadMetadata( _ ) ) + .WillOnce( DoAll( SetArgReferee<0>( files ), Return( ErrorCode::SUCCESS ) ) ); + + EXPECT_CALL( *mMqttSender, sendFile( "filename1", 1000, _ ) ) + .WillOnce( Return( ConnectivityError::WrongInputData ) ); + EXPECT_CALL( *mMqttSender, sendFile( "filename2", 3000, _ ) ).WillOnce( Return( ConnectivityError::Success ) ); + + mDataSenderManager->checkAndSendRetrievedData(); +} + +} // namespace IoTFleetWise +} // namespace Aws diff --git a/test/unit/DataSenderManagerWorkerThreadTest.cpp b/test/unit/DataSenderManagerWorkerThreadTest.cpp new file mode 100644 index 00000000..dffceb5b --- /dev/null +++ b/test/unit/DataSenderManagerWorkerThreadTest.cpp @@ -0,0 +1,150 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +#include "DataSenderManagerWorkerThread.h" +#include "CANInterfaceIDTranslator.h" +#include "Clock.h" +#include "ClockHandler.h" +#include "CollectionInspectionAPITypes.h" +#include "ConnectivityModuleMock.h" +#include "DataSenderManagerMock.h" +#include "SignalTypes.h" +#include "Testing.h" +#include "TimeTypes.h" +#include "WaitUntil.h" +#include +#include +#include +#include +#include + +namespace Aws +{ +namespace IoTFleetWise +{ + +using ::testing::_; +using ::testing::Return; +using ::testing::StrictMock; + +class DataSenderManagerWorkerThreadTest : public ::testing::Test +{ +public: + void + SetUp() override + { + mTriggerTime = ClockHandler::getClock()->systemTimeSinceEpochMs(); + + mTriggeredCollectionSchemeData = std::make_shared(); + mTriggeredCollectionSchemeData->metadata.decoderID = "TESTDECODERID"; + mTriggeredCollectionSchemeData->metadata.collectionSchemeID = "TESTCOLLECTIONSCHEME"; + mTriggeredCollectionSchemeData->triggerTime = mTriggerTime; + mTriggeredCollectionSchemeData->eventID = 579; + + mConnectivityModule = std::make_shared>(); + mDataSenderManager = std::make_shared>( canIDTranslator ); + mCollectedDataQueue = std::make_shared( 10000 ); + mDataSenderManagerWorkerThread = std::make_unique( + mConnectivityModule, mDataSenderManager, 100, mCollectedDataQueue ); + + EXPECT_CALL( *mConnectivityModule, isAlive() ).WillRepeatedly( Return( true ) ); + } + + void + TearDown() override + { + mDataSenderManagerWorkerThread->stop(); + } + +protected: + uint64_t mPersistencyUploadRetryIntervalMs{ 1000 }; + Timestamp mTriggerTime; + std::shared_ptr mTriggeredCollectionSchemeData; + + std::shared_ptr> mConnectivityModule; + CANInterfaceIDTranslator canIDTranslator; + std::shared_ptr> mDataSenderManager; + std::shared_ptr mCollectedDataQueue; + std::unique_ptr mDataSenderManagerWorkerThread; +}; + +class DataSenderManagerWorkerThreadTestWithAllSignalTypes : public DataSenderManagerWorkerThreadTest, + public testing::WithParamInterface +{ +}; + +INSTANTIATE_TEST_SUITE_P( MultipleSignals, + DataSenderManagerWorkerThreadTestWithAllSignalTypes, + allSignalTypes, + signalTypeToString ); + +TEST_F( DataSenderManagerWorkerThreadTest, ProcessNoData ) +{ + EXPECT_CALL( *mDataSenderManager, mockedProcessCollectedData( _ ) ).Times( 0 ); + mDataSenderManagerWorkerThread->start(); + + mCollectedDataQueue->push( mTriggeredCollectionSchemeData ); + + WAIT_ASSERT_GT( mDataSenderManager->mCheckAndSendRetrievedDataCalls, 0U ); +} + +TEST_P( DataSenderManagerWorkerThreadTestWithAllSignalTypes, ProcessSingleTrigger ) +{ + SignalType signalType = GetParam(); + EXPECT_CALL( *mDataSenderManager, mockedProcessCollectedData( _ ) ).Times( 1 ); + mDataSenderManagerWorkerThread->start(); + + auto signal1 = CollectedSignal( 1234, mTriggerTime - 10, 40.5, signalType ); + mTriggeredCollectionSchemeData->signals.push_back( signal1 ); + + mCollectedDataQueue->push( mTriggeredCollectionSchemeData ); + + WAIT_ASSERT_EQ( mDataSenderManager->getProcessedData().size(), 1U ); + ASSERT_TRUE( mDataSenderManagerWorkerThread->stop() ); + ASSERT_EQ( mDataSenderManager->getProcessedData()[0]->signals.size(), 1 ); + + auto processedSignal = mDataSenderManager->getProcessedData()[0]->signals[0]; + ASSERT_EQ( processedSignal.signalID, 1234 ); + ASSERT_EQ( processedSignal.receiveTime, mTriggerTime - 10 ); + ASSERT_NO_FATAL_FAILURE( assertSignalValue( processedSignal.value, 40.5, signalType ) ); +} + +TEST_F( DataSenderManagerWorkerThreadTest, ProcessMultipleTriggers ) +{ + auto triggeredCollectionSchemeData2 = std::make_shared(); + triggeredCollectionSchemeData2->metadata.decoderID = "TESTDECODERID2"; + triggeredCollectionSchemeData2->metadata.collectionSchemeID = "TESTCOLLECTIONSCHEME2"; + triggeredCollectionSchemeData2->triggerTime = mTriggerTime; + triggeredCollectionSchemeData2->eventID = 590; + + EXPECT_CALL( *mDataSenderManager, mockedProcessCollectedData( _ ) ).Times( 2 ); + + mDataSenderManagerWorkerThread->start(); + + auto signal1 = CollectedSignal( 1234, mTriggerTime - 10, 40.5, SignalType::DOUBLE ); + mTriggeredCollectionSchemeData->signals.push_back( signal1 ); + + auto signal2 = CollectedSignal( 5678, mTriggerTime, 99.5, SignalType::DOUBLE ); + triggeredCollectionSchemeData2->signals.push_back( signal2 ); + + mCollectedDataQueue->push( mTriggeredCollectionSchemeData ); + mCollectedDataQueue->push( triggeredCollectionSchemeData2 ); + + WAIT_ASSERT_EQ( mDataSenderManager->getProcessedData().size(), 2U ); + ASSERT_TRUE( mDataSenderManagerWorkerThread->stop() ); + + ASSERT_EQ( mDataSenderManager->getProcessedData()[0]->signals.size(), 1 ); + auto processedSignal = mDataSenderManager->getProcessedData()[0]->signals[0]; + ASSERT_EQ( processedSignal.signalID, 1234 ); + ASSERT_EQ( processedSignal.receiveTime, mTriggerTime - 10 ); + ASSERT_EQ( processedSignal.value.value.doubleVal, 40.5 ); + + ASSERT_EQ( mDataSenderManager->getProcessedData()[1]->signals.size(), 1 ); + processedSignal = mDataSenderManager->getProcessedData()[1]->signals[0]; + ASSERT_EQ( processedSignal.signalID, 5678 ); + ASSERT_EQ( processedSignal.receiveTime, mTriggerTime ); + ASSERT_EQ( processedSignal.value.value.doubleVal, 99.5 ); +} + +} // namespace IoTFleetWise +} // namespace Aws diff --git a/src/datamanagement/datasender/test/DataSenderProtoWriterTest.cpp b/test/unit/DataSenderProtoWriterTest.cpp similarity index 91% rename from src/datamanagement/datasender/test/DataSenderProtoWriterTest.cpp rename to test/unit/DataSenderProtoWriterTest.cpp index 96dc0ca2..a166597b 100644 --- a/src/datamanagement/datasender/test/DataSenderProtoWriterTest.cpp +++ b/test/unit/DataSenderProtoWriterTest.cpp @@ -2,14 +2,29 @@ // SPDX-License-Identifier: Apache-2.0 #include "DataSenderProtoWriter.h" +#include "CANDataTypes.h" +#include "CANInterfaceIDTranslator.h" +#include "Clock.h" #include "ClockHandler.h" -#include "Testing.h" +#include "CollectionInspectionAPITypes.h" +#include "GeohashInfo.h" +#include "OBDDataTypes.h" +#include "SignalTypes.h" +#include "TimeTypes.h" +#include "vehicle_data.pb.h" +#include +#include +#include +#include #include -#include +#include +#include +#include -using namespace Aws::IoTFleetWise::TestingSupport; -using namespace Aws::IoTFleetWise::DataSender; -using namespace Aws::IoTFleetWise::Platform::Linux; +namespace Aws +{ +namespace IoTFleetWise +{ class DataSenderProtoWriterTest : public ::testing::Test { @@ -60,7 +75,7 @@ TEST_F( DataSenderProtoWriterTest, TestVehicleData ) std::string out; EXPECT_TRUE( protoWriter.serializeVehicleData( &out ) ); - VehicleDataMsg::VehicleData vehicleDataTest{}; + Schemas::VehicleDataMsg::VehicleData vehicleDataTest{}; const std::string testProto = out; if ( !vehicleDataTest.ParseFromString( testProto ) ) @@ -112,7 +127,7 @@ TEST_F( DataSenderProtoWriterTest, TestDTCData ) std::string out; EXPECT_TRUE( protoWriter.serializeVehicleData( &out ) ); - VehicleDataMsg::VehicleData vehicleDataTest{}; + Schemas::VehicleDataMsg::VehicleData vehicleDataTest{}; const std::string testProto = out; if ( !vehicleDataTest.ParseFromString( testProto ) ) @@ -163,7 +178,7 @@ TEST_F( DataSenderProtoWriterTest, TestGeohash ) std::string out; EXPECT_TRUE( protoWriter.serializeVehicleData( &out ) ); - VehicleDataMsg::VehicleData vehicleDataTest{}; + Schemas::VehicleDataMsg::VehicleData vehicleDataTest{}; const std::string testProto = out; ASSERT_TRUE( vehicleDataTest.ParseFromString( testProto ) ); @@ -178,3 +193,6 @@ TEST_F( DataSenderProtoWriterTest, TestGeohash ) ASSERT_EQ( "9q9hwg28j", geohash->geohash_string() ); ASSERT_EQ( "9q9hwg281", geohash->prev_reported_geohash_string() ); } + +} // namespace IoTFleetWise +} // namespace Aws diff --git a/src/datamanagement/datamanager/test/DecoderDictionaryExtractorTest.cpp b/test/unit/DecoderDictionaryExtractorTest.cpp similarity index 99% rename from src/datamanagement/datamanager/test/DecoderDictionaryExtractorTest.cpp rename to test/unit/DecoderDictionaryExtractorTest.cpp index 58acd6f8..baec9242 100644 --- a/src/datamanagement/datamanager/test/DecoderDictionaryExtractorTest.cpp +++ b/test/unit/DecoderDictionaryExtractorTest.cpp @@ -1,10 +1,19 @@ // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 -#include "CollectionSchemeManagerTest.h" +#include "CANInterfaceIDTranslator.h" +#include "Clock.h" +#include "ClockHandler.h" +#include "CollectionSchemeManagerTest.h" // IWYU pragma: associated +#include "OBDDataTypes.h" #include "Testing.h" +#include +#include -using namespace Aws::IoTFleetWise::TestingSupport; +namespace Aws +{ +namespace IoTFleetWise +{ /** @brief * This test aims to test CollectionScheme Manager's Decoder Dictionary Extractor functionality @@ -595,3 +604,6 @@ TEST( CollectionSchemeManagerTest, DecoderDictionaryExtractorFirstRawFrameThenSi ASSERT_EQ( decoderMethod->second.find( 0x100 )->second.collectType, CANMessageCollectType::RAW_AND_DECODE ); ASSERT_EQ( decoderMethod->second.find( 0x100 )->second.format.mSignals[0].mOffset, 17 ); } + +} // namespace IoTFleetWise +} // namespace Aws diff --git a/src/datamanagement/datainspection/test/ExternalCANDataSourceTest.cpp b/test/unit/ExternalCANDataSourceTest.cpp similarity index 94% rename from src/datamanagement/datainspection/test/ExternalCANDataSourceTest.cpp rename to test/unit/ExternalCANDataSourceTest.cpp index 0dc509f4..6f4c1c4a 100644 --- a/src/datamanagement/datainspection/test/ExternalCANDataSourceTest.cpp +++ b/test/unit/ExternalCANDataSourceTest.cpp @@ -2,10 +2,27 @@ // SPDX-License-Identifier: Apache-2.0 #include "ExternalCANDataSource.h" +#include "CANDataConsumer.h" +#include "CollectionInspectionAPITypes.h" +#include "IDecoderDictionary.h" +#include "MessageTypes.h" +#include "SignalTypes.h" +#include "TimeTypes.h" +#include "VehicleDataSourceTypes.h" +#include +#include +#include #include #include +#include +#include +#include +#include -using namespace Aws::IoTFleetWise::DataInspection; +namespace Aws +{ +namespace IoTFleetWise +{ static void sendTestMessage( ExternalCANDataSource &dataSource, @@ -214,3 +231,6 @@ TEST_F( ExternalCANDataSourceTest, testExtractExtendedID ) } ASSERT_FALSE( signalBufferPtr->pop( signal ) ); } + +} // namespace IoTFleetWise +} // namespace Aws diff --git a/src/datamanagement/custom/example/externalgps/test/ExternalGpsSourceTest.cpp b/test/unit/ExternalGpsSourceTest.cpp similarity index 90% rename from src/datamanagement/custom/example/externalgps/test/ExternalGpsSourceTest.cpp rename to test/unit/ExternalGpsSourceTest.cpp index 83562b35..aa04ba2c 100644 --- a/src/datamanagement/custom/example/externalgps/test/ExternalGpsSourceTest.cpp +++ b/test/unit/ExternalGpsSourceTest.cpp @@ -1,12 +1,23 @@ // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 + #include "ExternalGpsSource.h" +#include "CollectionInspectionAPITypes.h" +#include "IDecoderDictionary.h" +#include "MessageTypes.h" +#include "SignalTypes.h" +#include "VehicleDataSourceTypes.h" #include "WaitUntil.h" +#include #include -#include +#include +#include +#include -using namespace Aws::IoTFleetWise::DataManagement; -using namespace Aws::IoTFleetWise::TestingSupport; +namespace Aws +{ +namespace IoTFleetWise +{ class ExternalGpsSourceTest : public ::testing::Test { @@ -92,3 +103,6 @@ TEST_F( ExternalGpsSourceTest, testWestNegativeLongitude ) // NOLINT ASSERT_TRUE( gpsSource.stop() ); } + +} // namespace IoTFleetWise +} // namespace Aws diff --git a/src/testingsupport/test/FakeSystemTimeTest.cpp b/test/unit/FakeSystemTimeTest.cpp similarity index 94% rename from src/testingsupport/test/FakeSystemTimeTest.cpp rename to test/unit/FakeSystemTimeTest.cpp index 7ffaf49b..fe0719b0 100644 --- a/src/testingsupport/test/FakeSystemTimeTest.cpp +++ b/test/unit/FakeSystemTimeTest.cpp @@ -6,13 +6,17 @@ #include "Signal.h" #include "Timer.h" #include -#include +#include #include +#include #include -using namespace Aws::IoTFleetWise::Platform::Linux; -using namespace Aws::IoTFleetWise::TestingSupport; -using namespace std::chrono_literals; +namespace Aws +{ +namespace IoTFleetWise +{ + +using std::chrono_literals::operator""h; TEST( TimerTest, timerTickCountChangingSystemTimeBackward ) { @@ -70,3 +74,6 @@ TEST( SignalTest, waitWithTimeoutChangingSystemTimeBackward ) // Sanity check to ensure faketime is working. If this fails, it means faketime is not properly set up. ASSERT_LT( std::chrono::system_clock::now().time_since_epoch().count(), systemTimeBeforeChange ); } + +} // namespace IoTFleetWise +} // namespace Aws diff --git a/src/datamanagement/datainspection/test/GeohashFunctionNodeTest.cpp b/test/unit/GeohashFunctionNodeTest.cpp similarity index 98% rename from src/datamanagement/datainspection/test/GeohashFunctionNodeTest.cpp rename to test/unit/GeohashFunctionNodeTest.cpp index e95e9dac..99b4161d 100644 --- a/src/datamanagement/datainspection/test/GeohashFunctionNodeTest.cpp +++ b/test/unit/GeohashFunctionNodeTest.cpp @@ -2,9 +2,15 @@ // SPDX-License-Identifier: Apache-2.0 #include "GeohashFunctionNode.h" +#include "Geohash.h" +#include "GeohashInfo.h" +#include "ICollectionScheme.h" #include -using namespace Aws::IoTFleetWise::DataInspection; +namespace Aws +{ +namespace IoTFleetWise +{ // This is a utility function to convert GPS signal from Decimal Degree to input unit type static double @@ -245,3 +251,6 @@ TEST( GeohashFunctionNodeTest, EvaluatePreviousGeohashChange ) // Expect No Geohash update ASSERT_FALSE( geohashFunctionNode.hasNewGeohash() ); } + +} // namespace IoTFleetWise +} // namespace Aws diff --git a/src/datamanagement/types/test/GeohashTest.cpp b/test/unit/GeohashTest.cpp similarity index 95% rename from src/datamanagement/types/test/GeohashTest.cpp rename to test/unit/GeohashTest.cpp index 58c7c1c8..5e0c9fad 100644 --- a/src/datamanagement/types/test/GeohashTest.cpp +++ b/test/unit/GeohashTest.cpp @@ -2,9 +2,14 @@ // SPDX-License-Identifier: Apache-2.0 #include "Geohash.h" +#include #include +#include -using namespace Aws::IoTFleetWise::DataInspection; +namespace Aws +{ +namespace IoTFleetWise +{ /** @brief test aims to check Geohash Encoding function to handle invalid * input such as invalid lat/lon and precision. @@ -75,3 +80,6 @@ TEST( GeohashTest, GeohashEncodeWithValidInput ) ASSERT_TRUE( Geohash::encode( 90, 180, 8, hashBits ) ); ASSERT_EQ( hashBits, 1099511627775 ); } + +} // namespace IoTFleetWise +} // namespace Aws diff --git a/src/vehiclenetwork/test/ISOTPOverCANProtocolTest.cpp b/test/unit/ISOTPOverCANProtocolTest.cpp similarity index 96% rename from src/vehiclenetwork/test/ISOTPOverCANProtocolTest.cpp rename to test/unit/ISOTPOverCANProtocolTest.cpp index e148c502..847fb476 100644 --- a/src/vehiclenetwork/test/ISOTPOverCANProtocolTest.cpp +++ b/test/unit/ISOTPOverCANProtocolTest.cpp @@ -2,17 +2,18 @@ // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 -#include "businterfaces/ISOTPOverCANReceiver.h" -#include "businterfaces/ISOTPOverCANSender.h" -#include "businterfaces/ISOTPOverCANSenderReceiver.h" +#include "ISOTPOverCANOptions.h" +#include "ISOTPOverCANReceiver.h" +#include "ISOTPOverCANSender.h" +#include "ISOTPOverCANSenderReceiver.h" +#include +#include #include -#include -#include -#include - #include -#include #include +#include +#include +#include /** * @brief This is an integration test of the ISO-TP Kernel Module @@ -24,8 +25,9 @@ * pre-installed. */ -using namespace Aws::IoTFleetWise::VehicleNetwork; -namespace +namespace Aws +{ +namespace IoTFleetWise { bool @@ -64,8 +66,6 @@ receivePDU( ISOTPOverCANReceiver &receiver, std::vector &pdu ) ASSERT_TRUE( receiver.receivePDU( pdu ) ); } -} // namespace - class ISOTPOverCANProtocolTest : public ::testing::Test { protected: @@ -245,3 +245,6 @@ TEST_F( ISOTPOverCANProtocolTest, isotpSendAndReceiveSameSocket ) ASSERT_TRUE( receiver.disconnect() ); ASSERT_TRUE( sender.disconnect() ); } + +} // namespace IoTFleetWise +} // namespace Aws diff --git a/src/datamanagement/custom/example/iwavegps/test/IWaveGpsSourceTest.cpp b/test/unit/IWaveGpsSourceTest.cpp similarity index 92% rename from src/datamanagement/custom/example/iwavegps/test/IWaveGpsSourceTest.cpp rename to test/unit/IWaveGpsSourceTest.cpp index 094667c9..615729e4 100644 --- a/src/datamanagement/custom/example/iwavegps/test/IWaveGpsSourceTest.cpp +++ b/test/unit/IWaveGpsSourceTest.cpp @@ -1,19 +1,28 @@ // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 + #include "IWaveGpsSource.h" +#include "CollectionInspectionAPITypes.h" +#include "IDecoderDictionary.h" +#include "MessageTypes.h" +#include "SignalTypes.h" +#include "VehicleDataSourceTypes.h" #include "WaitUntil.h" +#include #include -#include #include -#include #include #include +#include #include -#include #include +#include +#include -using namespace Aws::IoTFleetWise::DataManagement; -using namespace Aws::IoTFleetWise::TestingSupport; +namespace Aws +{ +namespace IoTFleetWise +{ class IWaveGpsSourceTest : public ::testing::Test { @@ -116,3 +125,6 @@ TEST_F( IWaveGpsSourceTest, testWestNegativeLongitude ) ASSERT_TRUE( gpsSource.stop() ); ASSERT_TRUE( gpsSource.disconnect() ); } + +} // namespace IoTFleetWise +} // namespace Aws diff --git a/src/datamanagement/datamanager/test/InspectionMatrixExtractorTest.cpp b/test/unit/InspectionMatrixExtractorTest.cpp similarity index 95% rename from src/datamanagement/datamanager/test/InspectionMatrixExtractorTest.cpp rename to test/unit/InspectionMatrixExtractorTest.cpp index bbfafdf2..f0b53fef 100644 --- a/src/datamanagement/datamanager/test/InspectionMatrixExtractorTest.cpp +++ b/test/unit/InspectionMatrixExtractorTest.cpp @@ -1,7 +1,15 @@ // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 -#include "CollectionSchemeManagerTest.h" +#include "CANInterfaceIDTranslator.h" +#include "CollectionSchemeManagerTest.h" // IWYU pragma: associated +#include +#include + +namespace Aws +{ +namespace IoTFleetWise +{ /** @brief * This test aims to test PM's functionality to invoke Inspection Engine on Inspection Matrix Update @@ -50,7 +58,7 @@ buildTree( int startVal, int count ) currNode = nodeQ.front(); nodeQ.pop(); startVal++; - currNode->left = new struct ExpressionNode(); + currNode->left = new ExpressionNode(); currNode->left->floatingValue = startVal; nodeQ.push( currNode->left ); startVal++; @@ -59,7 +67,7 @@ buildTree( int startVal, int count ) { break; } - currNode->right = new struct ExpressionNode(); + currNode->right = new ExpressionNode(); currNode->right->floatingValue = startVal; nodeQ.push( currNode->right ); count--; @@ -128,7 +136,7 @@ TEST( CollectionSchemeManager, InpsectionMatrixExtractorTreeTest ) { /* construct trees */ - struct ExpressionNode *tree1, *tree2, *tree3; + ExpressionNode *tree1, *tree2, *tree3; tree1 = buildTree( 1, 20 ); tree2 = buildTree( 11, 20 ); tree3 = buildTree( 21, 20 ); @@ -223,3 +231,6 @@ TEST( CollectionSchemeManager, InpsectionMatrixExtractorConditionDataTest ) ASSERT_EQ( conditionData.metadata.collectionSchemeID, collectionScheme->getCollectionSchemeID() ); } } + +} // namespace IoTFleetWise +} // namespace Aws diff --git a/src/executionmanagement/test/IoTFleetWiseConfigTest.cpp b/test/unit/IoTFleetWiseConfigTest.cpp similarity index 78% rename from src/executionmanagement/test/IoTFleetWiseConfigTest.cpp rename to test/unit/IoTFleetWiseConfigTest.cpp index d4da9613..729792b0 100644 --- a/src/executionmanagement/test/IoTFleetWiseConfigTest.cpp +++ b/test/unit/IoTFleetWiseConfigTest.cpp @@ -4,8 +4,12 @@ #include "IoTFleetWiseConfig.h" #include +#include -using namespace Aws::IoTFleetWise::ExecutionManagement; +namespace Aws +{ +namespace IoTFleetWise +{ TEST( IoTFleetWiseConfigTest, BadFileName ) { @@ -16,8 +20,11 @@ TEST( IoTFleetWiseConfigTest, BadFileName ) TEST( IoTFleetWiseConfigTest, ReadOk ) { Json::Value config; - ASSERT_TRUE( IoTFleetWiseConfig::read( "em-example-config.json", config ) ); + ASSERT_TRUE( IoTFleetWiseConfig::read( "static-config-ok.json", config ) ); ASSERT_EQ( 10000, config["staticConfig"]["bufferSizes"]["decodedSignalsBufferSize"].asInt() ); ASSERT_EQ( 10000, config["staticConfig"]["bufferSizes"]["rawCANFrameBufferSize"].asInt() ); ASSERT_EQ( "Trace", config["staticConfig"]["internalParameters"]["systemWideLogLevel"].asString() ); } + +} // namespace IoTFleetWise +} // namespace Aws diff --git a/src/executionmanagement/test/IoTFleetWiseEngineTest.cpp b/test/unit/IoTFleetWiseEngineTest.cpp similarity index 85% rename from src/executionmanagement/test/IoTFleetWiseEngineTest.cpp rename to test/unit/IoTFleetWiseEngineTest.cpp index e633ca87..94afb80a 100644 --- a/src/executionmanagement/test/IoTFleetWiseEngineTest.cpp +++ b/test/unit/IoTFleetWiseEngineTest.cpp @@ -3,21 +3,27 @@ // SPDX-License-Identifier: Apache-2.0 #include "IoTFleetWiseEngine.h" +#include "CANDataTypes.h" +#include "CollectionInspectionAPITypes.h" #include "IoTFleetWiseConfig.h" -#include "LogLevel.h" #include "WaitUntil.h" -#include +#include +#include #include +#include #include -#include +#include #include #include +#include -using namespace Aws::IoTFleetWise::TestingSupport; -using namespace Aws::IoTFleetWise::ExecutionManagement; -using namespace Aws::IoTFleetWise::DataManagement; +#ifdef FWE_FEATURE_IWAVE_GPS +#include +#endif -namespace +namespace Aws +{ +namespace IoTFleetWise { bool @@ -31,7 +37,6 @@ socketAvailable() close( sock ); return true; } -} // namespace class IoTFleetWiseEngineTest : public ::testing::Test { @@ -54,7 +59,7 @@ class IoTFleetWiseEngineTest : public ::testing::Test TEST_F( IoTFleetWiseEngineTest, InitAndStartEngine ) { Json::Value config; - ASSERT_TRUE( IoTFleetWiseConfig::read( "em-example-config.json", config ) ); + ASSERT_TRUE( IoTFleetWiseConfig::read( "static-config-ok.json", config ) ); IoTFleetWiseEngine engine; ASSERT_TRUE( engine.connect( config ) ); @@ -68,7 +73,7 @@ TEST_F( IoTFleetWiseEngineTest, InitAndStartEngine ) TEST_F( IoTFleetWiseEngineTest, InitAndStartEngineInlineCreds ) { Json::Value config; - ASSERT_TRUE( IoTFleetWiseConfig::read( "em-example-config-inline-creds.json", config ) ); + ASSERT_TRUE( IoTFleetWiseConfig::read( "static-config-inline-creds.json", config ) ); IoTFleetWiseEngine engine; ASSERT_TRUE( engine.connect( config ) ); @@ -82,7 +87,7 @@ TEST_F( IoTFleetWiseEngineTest, InitAndStartEngineInlineCreds ) TEST_F( IoTFleetWiseEngineTest, CheckPublishDataQueue ) { Json::Value config; - ASSERT_TRUE( IoTFleetWiseConfig::read( "em-example-config.json", config ) ); + ASSERT_TRUE( IoTFleetWiseConfig::read( "static-config-ok.json", config ) ); IoTFleetWiseEngine engine; ASSERT_TRUE( engine.connect( config ) ); @@ -123,8 +128,11 @@ TEST_F( IoTFleetWiseEngineTest, InitAndFailToStartCorruptConfig ) { Json::Value config; // Read should succeed - ASSERT_TRUE( IoTFleetWiseConfig::read( "em-example-config-corrupt.json", config ) ); + ASSERT_TRUE( IoTFleetWiseConfig::read( "static-config-corrupt.json", config ) ); IoTFleetWiseEngine engine; // Connect should fail as the Config file has a non complete Bus definition ASSERT_FALSE( engine.connect( config ) ); } + +} // namespace IoTFleetWise +} // namespace Aws diff --git a/test/unit/LoggingModuleTest.cpp b/test/unit/LoggingModuleTest.cpp new file mode 100644 index 00000000..c57f0f62 --- /dev/null +++ b/test/unit/LoggingModuleTest.cpp @@ -0,0 +1,23 @@ + +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +#include "LoggingModule.h" +#include +#include + +namespace Aws +{ +namespace IoTFleetWise +{ + +TEST( LoggingModuleTest, GetErrnoString ) +{ + // Try to open a non existing file + FILE *fp = fopen( "/tmp/fwe_strerror_test/2f1d6e5e5ab1", "rb" ); + (void)fp; + ASSERT_NE( getErrnoString(), "" ); +} + +} // namespace IoTFleetWise +} // namespace Aws diff --git a/src/platform/linux/resourcemanagement/test/MemoryUsageInfoTest.cpp b/test/unit/MemoryUsageInfoTest.cpp similarity index 83% rename from src/platform/linux/resourcemanagement/test/MemoryUsageInfoTest.cpp rename to test/unit/MemoryUsageInfoTest.cpp index e3af256f..d925db9d 100644 --- a/src/platform/linux/resourcemanagement/test/MemoryUsageInfoTest.cpp +++ b/test/unit/MemoryUsageInfoTest.cpp @@ -6,7 +6,10 @@ #include -using namespace Aws::IoTFleetWise::Platform::Linux; +namespace Aws +{ +namespace IoTFleetWise +{ TEST( MemoryUsageInfoTest, testMemoryUsageInfo ) { @@ -17,3 +20,6 @@ TEST( MemoryUsageInfoTest, testMemoryUsageInfo ) ASSERT_GE( usage.getResidentMemorySize(), 0 ); ASSERT_GE( usage.getVirtualMemorySize(), 0 ); } + +} // namespace IoTFleetWise +} // namespace Aws diff --git a/src/datamanagement/datadecoding/test/OBDDataDecoderTest.cpp b/test/unit/OBDDataDecoderTest.cpp similarity index 99% rename from src/datamanagement/datadecoding/test/OBDDataDecoderTest.cpp rename to test/unit/OBDDataDecoderTest.cpp index b0630957..1a5a93b0 100644 --- a/src/datamanagement/datadecoding/test/OBDDataDecoderTest.cpp +++ b/test/unit/OBDDataDecoderTest.cpp @@ -4,17 +4,29 @@ #include "OBDDataDecoder.h" #include "EnumUtility.h" +#include "MessageTypes.h" +#include "OBDDataTypes.h" +#include "OBDDataTypesUnitTestOnly.h" +#include "SignalTypes.h" #include "Testing.h" -#include "datatypes/OBDDataTypesUnitTestOnly.h" +#include +#include +#include #include -#include - -using namespace Aws::IoTFleetWise::DataManagement; -using namespace Aws::IoTFleetWise::TestingSupport; +#include +#include +#include +#include +#include // For testing purpose, Signal ID is defined as PID | (signal_order << PID_SIGNAL_BITS_LEFT_SHIFT) #define PID_SIGNAL_BITS_LEFT_SHIFT 8 +namespace Aws +{ +namespace IoTFleetWise +{ + class OBDDataDecoderTest : public ::testing::Test { protected: @@ -1123,3 +1135,6 @@ TEST_F( OBDDataDecoderTest, OBDDataDecoderDecodedEngineLoadCorruptDecoderDiction ASSERT_FALSE( decoder.decodeEmissionPIDs( SID::CURRENT_STATS, { pid }, txPDUData, info ) ); } + +} // namespace IoTFleetWise +} // namespace Aws diff --git a/src/datamanagement/datainspection/test/OBDOverCANModuleTest.cpp b/test/unit/OBDOverCANModuleTest.cpp similarity index 91% rename from src/datamanagement/datainspection/test/OBDOverCANModuleTest.cpp rename to test/unit/OBDOverCANModuleTest.cpp index 7fac2500..211aceee 100644 --- a/src/datamanagement/datainspection/test/OBDOverCANModuleTest.cpp +++ b/test/unit/OBDOverCANModuleTest.cpp @@ -2,25 +2,42 @@ // SPDX-License-Identifier: Apache-2.0 #include "OBDOverCANModule.h" +#include "CollectionInspectionAPITypes.h" +#include "EnumUtility.h" +#include "ICollectionScheme.h" +#include "IDecoderDictionary.h" +#include "ISOTPOverCANOptions.h" +#include "ISOTPOverCANReceiver.h" +#include "ISOTPOverCANSenderReceiver.h" +#include "MessageTypes.h" #include "OBDDataTypes.h" +#include "OBDDataTypesUnitTestOnly.h" +#include "SignalTypes.h" #include "Testing.h" +#include "Thread.h" +#include "VehicleDataSourceTypes.h" #include "WaitUntil.h" -#include "businterfaces/ISOTPOverCANReceiver.h" -#include "datatypes/OBDDataTypesUnitTestOnly.h" +#include +#include +#include +#include +#include #include #include -#include +#include +#include #include -#include -#include #include -#include +#include +#include +#include +#include -using namespace Aws::IoTFleetWise::DataInspection; -using namespace Aws::IoTFleetWise::TestingSupport; - -namespace +namespace Aws +{ +namespace IoTFleetWise { + using SignalDoubleValue = double; // ECU ID mocked for unit test @@ -116,8 +133,6 @@ initDecoderDictionary( SignalType signalType = SignalType::DOUBLE ) return decoderDictPtr; } -} // namespace - struct ECUMock { void @@ -126,7 +141,7 @@ struct ECUMock ISOTPOverCANReceiverOptions broadcastOptions; // Broadcast broadcastOptions.mSocketCanIFName = "vcan0"; - broadcastOptions.mSourceCANId = (unsigned)ECU_ID_MOCK::ENGINE_ECU_RX_EXTENDED; + broadcastOptions.mSourceCANId = (unsigned)physicalTxId; broadcastOptions.mIsExtendedId = (unsigned)broadcastRxId > CAN_SFF_MASK; broadcastOptions.mDestinationCANId = (unsigned)broadcastRxId; broadcastOptions.mP2TimeoutMs = P2_TIMEOUT_DEFAULT_MS; @@ -246,51 +261,6 @@ class OBDOverCANModuleTest : public ::testing::Test std::shared_ptr signalBufferPtr; std::shared_ptr activeDTCBufferPtr; std::vector ecus; - - void - assertSignalValue( const SignalValueWrapper &signalValueWrapper, - double expectedSignalValue, - SignalType expectedSignalType ) - { - switch ( expectedSignalType ) - { - case SignalType::UINT8: - ASSERT_EQ( signalValueWrapper.value.uint8Val, static_cast( expectedSignalValue ) ); - break; - case SignalType::INT8: - ASSERT_EQ( signalValueWrapper.value.int8Val, static_cast( expectedSignalValue ) ); - break; - case SignalType::UINT16: - ASSERT_EQ( signalValueWrapper.value.uint16Val, static_cast( expectedSignalValue ) ); - break; - case SignalType::INT16: - ASSERT_EQ( signalValueWrapper.value.int16Val, static_cast( expectedSignalValue ) ); - break; - case SignalType::UINT32: - ASSERT_EQ( signalValueWrapper.value.uint32Val, static_cast( expectedSignalValue ) ); - break; - case SignalType::INT32: - ASSERT_EQ( signalValueWrapper.value.int32Val, static_cast( expectedSignalValue ) ); - break; - case SignalType::UINT64: - ASSERT_EQ( signalValueWrapper.value.uint64Val, static_cast( expectedSignalValue ) ); - break; - case SignalType::INT64: - ASSERT_EQ( signalValueWrapper.value.int64Val, static_cast( expectedSignalValue ) ); - break; - case SignalType::FLOAT: - ASSERT_FLOAT_EQ( signalValueWrapper.value.floatVal, static_cast( expectedSignalValue ) ); - break; - case SignalType::DOUBLE: - ASSERT_DOUBLE_EQ( signalValueWrapper.value.doubleVal, static_cast( expectedSignalValue ) ); - break; - case SignalType::BOOLEAN: - ASSERT_EQ( signalValueWrapper.value.boolVal, static_cast( expectedSignalValue ) ); - break; - default: - FAIL() << "Unsupported signal type"; - } - } }; TEST_F( OBDOverCANModuleTest, OBDOverCANModuleInitFailure ) @@ -353,7 +323,8 @@ TEST_P( OBDOverCANModuleTestWithAllSignalTypes, RequestPIDFromNotExtendedIDECUTe // Setup ECU Mock ecus = std::vector( 2 ); - ecus[0].init( ECUID::BROADCAST_ID, ECU_ID_MOCK::ENGINE_ECU_TX, ECU_ID_MOCK::ENGINE_ECU_RX ); + ASSERT_NO_FATAL_FAILURE( + ecus[0].init( ECUID::BROADCAST_ID, ECU_ID_MOCK::ENGINE_ECU_TX, ECU_ID_MOCK::ENGINE_ECU_RX ) ); ecus[0].mSupportedPIDResponse1 = { 0x41, 0x00, 0x18, 0x00, 0x00, 0x00 }; ecus[0].mSupportedPIDResponse2 = { 0x41, 0xC0, 0x00, 0x00, 0x00, 0x00 }; ecus[0].mRequestPID1 = { 0x01, 0x04, 0x05 }; @@ -361,7 +332,8 @@ TEST_P( OBDOverCANModuleTestWithAllSignalTypes, RequestPIDFromNotExtendedIDECUTe ecus[0].mDTCResponse = { 0x43, 0x02, 0x01, 0x43, 0x41, 0x96 }; ecus[0].mThread.create( ecuResponse, &ecus[0] ); - ecus[1].init( ECUID::BROADCAST_ID, ECU_ID_MOCK::TRANSMISSION_ECU_TX, ECU_ID_MOCK::TRANSMISSION_ECU_RX ); + ASSERT_NO_FATAL_FAILURE( + ecus[1].init( ECUID::BROADCAST_ID, ECU_ID_MOCK::TRANSMISSION_ECU_TX, ECU_ID_MOCK::TRANSMISSION_ECU_RX ) ); ecus[1].mSupportedPIDResponse1 = { 0x41, 0x00, 0x00, 0x08, 0x00, 0x00 }; ecus[1].mSupportedPIDResponse2 = { 0x41, 0xC0, 0x00, 0x00, 0x00, 0x00 }; ecus[1].mRequestPID1 = { 0x01, 0x0D }; @@ -388,11 +360,11 @@ TEST_P( OBDOverCANModuleTestWithAllSignalTypes, RequestPIDFromNotExtendedIDECUTe // Verify all PID Signals are correctly decoded CollectedSignal signal; WAIT_ASSERT_TRUE( obdModule.getSignalBufferPtr()->pop( signal ) ); - assertSignalValue( signal.value, expectedPIDSignalValue[signal.signalID], signalType ); + ASSERT_NO_FATAL_FAILURE( assertSignalValue( signal.value, expectedPIDSignalValue[signal.signalID], signalType ) ); WAIT_ASSERT_TRUE( obdModule.getSignalBufferPtr()->pop( signal ) ); - assertSignalValue( signal.value, expectedPIDSignalValue[signal.signalID], signalType ); + ASSERT_NO_FATAL_FAILURE( assertSignalValue( signal.value, expectedPIDSignalValue[signal.signalID], signalType ) ); WAIT_ASSERT_TRUE( obdModule.getSignalBufferPtr()->pop( signal ) ); - assertSignalValue( signal.value, expectedPIDSignalValue[signal.signalID], signalType ); + ASSERT_NO_FATAL_FAILURE( assertSignalValue( signal.value, expectedPIDSignalValue[signal.signalID], signalType ) ); } // This test is to validate that OBDOverCANModule will only request PID that are specified in Decoder Dictionary @@ -413,7 +385,8 @@ TEST_F( OBDOverCANModuleTest, RequestPartialPIDFromNotExtendedIDECUTest ) ecus[0].mDTCResponse = { 0x43, 0x02, 0x01, 0x43, 0x41, 0x96 }; ecus[0].mThread.create( ecuResponse, &ecus[0] ); - ecus[1].init( ECUID::BROADCAST_ID, ECU_ID_MOCK::TRANSMISSION_ECU_TX, ECU_ID_MOCK::TRANSMISSION_ECU_RX ); + ASSERT_NO_FATAL_FAILURE( + ecus[1].init( ECUID::BROADCAST_ID, ECU_ID_MOCK::TRANSMISSION_ECU_TX, ECU_ID_MOCK::TRANSMISSION_ECU_RX ) ); ecus[1].mSupportedPIDResponse1 = { 0x41, 0x00, 0x00, 0x08, 0x00, 0x00 }; ecus[1].mSupportedPIDResponse2 = { 0x41, 0xC0, 0x80, 0x10, 0x00, 0x00 }; ecus[1].mRequestPID1 = { 0x01, 0x0D, 0xC1 }; @@ -626,7 +599,8 @@ TEST_F( OBDOverCANModuleTest, RequestPIDAndDTCFromNonExtendedIDECUTest ) // Setup ECU Mock ecus = std::vector( 2 ); - ecus[0].init( ECUID::BROADCAST_ID, ECU_ID_MOCK::ENGINE_ECU_TX, ECU_ID_MOCK::ENGINE_ECU_RX ); + ASSERT_NO_FATAL_FAILURE( + ecus[0].init( ECUID::BROADCAST_ID, ECU_ID_MOCK::ENGINE_ECU_TX, ECU_ID_MOCK::ENGINE_ECU_RX ) ); ecus[0].mSupportedPIDResponse1 = { 0x41, 0x00, 0x18, 0x00, 0x00, 0x00 }; ecus[0].mSupportedPIDResponse2 = { 0x41, 0xC0, 0x00, 0x00, 0x00, 0x00 }; ecus[0].mRequestPID1 = { 0x01, 0x04, 0x05 }; @@ -634,7 +608,8 @@ TEST_F( OBDOverCANModuleTest, RequestPIDAndDTCFromNonExtendedIDECUTest ) ecus[0].mDTCResponse = { 0x43, 0x04, 0x01, 0x43, 0x41, 0x96, 0x81, 0x48, 0xC1, 0x48 }; ecus[0].mThread.create( ecuResponse, &ecus[0] ); - ecus[1].init( ECUID::BROADCAST_ID, ECU_ID_MOCK::TRANSMISSION_ECU_TX, ECU_ID_MOCK::TRANSMISSION_ECU_RX ); + ASSERT_NO_FATAL_FAILURE( + ecus[1].init( ECUID::BROADCAST_ID, ECU_ID_MOCK::TRANSMISSION_ECU_TX, ECU_ID_MOCK::TRANSMISSION_ECU_RX ) ); ecus[1].mSupportedPIDResponse1 = { 0x41, 0x00, 0x00, 0x08, 0x00, 0x00 }; ecus[1].mSupportedPIDResponse2 = { 0x41, 0xC0, 0x80, 0x00, 0x00, 0x00 }; ecus[1].mRequestPID1 = { 0x01, 0x0D, 0xC1 }; @@ -687,7 +662,8 @@ TEST_F( OBDOverCANModuleTest, BroadcastRequestsStandardIDs ) // Setup ECU Mock ecus = std::vector( 2 ); - ecus[0].init( ECUID::BROADCAST_ID, ECU_ID_MOCK::ENGINE_ECU_TX, ECU_ID_MOCK::ENGINE_ECU_RX ); + ASSERT_NO_FATAL_FAILURE( + ecus[0].init( ECUID::BROADCAST_ID, ECU_ID_MOCK::ENGINE_ECU_TX, ECU_ID_MOCK::ENGINE_ECU_RX ) ); ecus[0].mSupportedPIDResponse1 = { 0x41, 0x00, 0x18, 0x00, 0x00, 0x00 }; ecus[0].mSupportedPIDResponse2 = { 0x41, 0xC0, 0x00, 0x00, 0x00, 0x00 }; ecus[0].mRequestPID1 = { 0x01, 0x04, 0x05 }; @@ -695,7 +671,8 @@ TEST_F( OBDOverCANModuleTest, BroadcastRequestsStandardIDs ) ecus[0].mDTCResponse = { 0x43, 0x02, 0x01, 0x43, 0x41, 0x96 }; ecus[0].mThread.create( ecuResponse, &ecus[0] ); - ecus[1].init( ECUID::BROADCAST_ID, ECU_ID_MOCK::TRANSMISSION_ECU_TX, ECU_ID_MOCK::TRANSMISSION_ECU_RX ); + ASSERT_NO_FATAL_FAILURE( + ecus[1].init( ECUID::BROADCAST_ID, ECU_ID_MOCK::TRANSMISSION_ECU_TX, ECU_ID_MOCK::TRANSMISSION_ECU_RX ) ); ecus[1].mSupportedPIDResponse1 = { 0x41, 0x00, 0x00, 0x08, 0x00, 0x00 }; ecus[1].mSupportedPIDResponse2 = { 0x41, 0xC0, 0x00, 0x00, 0x00, 0x00 }; ecus[1].mRequestPID1 = { 0x01, 0x0D }; @@ -855,3 +832,6 @@ TEST_F( OBDOverCANModuleTest, setExternalPIDResponse ) ASSERT_TRUE( obdModule.getSignalBufferPtr()->pop( signal ) ); ASSERT_DOUBLE_EQ( signal.value.value.doubleVal, expectedPIDSignalValue[signal.signalID] ); } + +} // namespace IoTFleetWise +} // namespace Aws diff --git a/src/offboardconnectivity/implementation/aws/iotcpp/test/src/PayloadManagerTest.cpp b/test/unit/PayloadManagerTest.cpp similarity index 94% rename from src/offboardconnectivity/implementation/aws/iotcpp/test/src/PayloadManagerTest.cpp rename to test/unit/PayloadManagerTest.cpp index 2b4dcdcb..e49e1bc8 100644 --- a/src/offboardconnectivity/implementation/aws/iotcpp/test/src/PayloadManagerTest.cpp +++ b/test/unit/PayloadManagerTest.cpp @@ -2,17 +2,23 @@ // SPDX-License-Identifier: Apache-2.0 #include "PayloadManager.h" -#include "AwsIotChannel.h" -#include "AwsIotConnectivityModule.h" -#include -#include +#include "CacheAndPersist.h" +#include "ISender.h" +#include +#include +#include +#include #include -#include +#include +#include +#include +#include +#include -using namespace Aws::IoTFleetWise::Platform::Linux::PersistencyManagement; -using namespace Aws::IoTFleetWise::OffboardConnectivity; -using namespace Aws::IoTFleetWise::OffboardConnectivityAwsIot; -using Aws::IoTFleetWise::OffboardConnectivity::CollectionSchemeParams; +namespace Aws +{ +namespace IoTFleetWise +{ TEST( PayloadManagerTest, TestNoConnectionDataPersistency ) { @@ -158,3 +164,6 @@ TEST( PayloadManagerTest, TestFailToAddMetadata ) ASSERT_FALSE( WIFEXITED( ret ) == 0 ); } } + +} // namespace IoTFleetWise +} // namespace Aws diff --git a/test/unit/RemoteProfilerTest.cpp b/test/unit/RemoteProfilerTest.cpp new file mode 100644 index 00000000..3ed61b17 --- /dev/null +++ b/test/unit/RemoteProfilerTest.cpp @@ -0,0 +1,64 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +#include "RemoteProfiler.h" +#include "IConnectionTypes.h" +#include "ISender.h" +#include "LogLevel.h" +#include "SenderMock.h" +#include "WaitUntil.h" +#include +#include +#include +#include +#include +#include +#include + +namespace Aws +{ +namespace IoTFleetWise +{ + +using ::testing::_; +using ::testing::Gt; +using ::testing::Return; +using ::testing::Sequence; +using ::testing::StrictMock; + +void +checkMetrics( const std::string &data ) +{ + Json::Reader reader; + Json::Value root; + ASSERT_TRUE( reader.parse( data, root ) ); + ASSERT_GE( data.size(), 6 ); + ASSERT_GE( root["metric1"]["name"].asString().length(), 1 ); +} + +std::atomic a( 0 ); +TEST( RemoteProfilerTest, MetricsUpload ) +{ + auto senderMock = std::make_shared>(); + EXPECT_CALL( *senderMock, mockedSendBuffer( _, Gt( 0 ), _ ) ) + .WillRepeatedly( Return( ConnectivityError::Success ) ); + + auto mockLogSender = std::make_shared(); + RemoteProfiler profiler( senderMock, mockLogSender, 1000, 1000, LogLevel::Trace, "Test" ); + profiler.start(); + + // Generate some cpu load + for ( int i = 0; i < 200000000; i++ ) + { + a++; + } + + WAIT_ASSERT_GT( senderMock->getSentBufferData().size(), 5U ); + for ( auto sentData : senderMock->getSentBufferData() ) + { + ASSERT_NO_FATAL_FAILURE( checkMetrics( sentData.data ) ); + } +} + +} // namespace IoTFleetWise +} // namespace Aws diff --git a/src/datamanagement/datamanager/test/SchemaTest.cpp b/test/unit/SchemaTest.cpp similarity index 81% rename from src/datamanagement/datamanager/test/SchemaTest.cpp rename to test/unit/SchemaTest.cpp index 6fc25fe5..72878a77 100644 --- a/src/datamanagement/datamanager/test/SchemaTest.cpp +++ b/test/unit/SchemaTest.cpp @@ -4,72 +4,44 @@ #include "Schema.h" #include "AwsIotChannel.h" #include "AwsIotConnectivityModule.h" - +#include "Clock.h" #include "ClockHandler.h" #include "CollectionSchemeIngestion.h" #include "CollectionSchemeIngestionList.h" #include "DecoderManifestIngestion.h" +#include "EnumUtility.h" #include "ICollectionScheme.h" -#include +#include "IConnectionTypes.h" +#include "IDecoderManifest.h" +#include "ISender.h" +#include "MessageTypes.h" +#include "SenderMock.h" +#include "SignalTypes.h" +#include "TimeTypes.h" +#include "VehicleDataSourceTypes.h" +#include "checkin.pb.h" +#include "collection_schemes.pb.h" +#include "decoder_manifest.pb.h" +#include +#include #include -#include +#include +#include #include #include +#include +#include -using namespace Aws::IoTFleetWise::Platform::Linux; -using namespace Aws::IoTFleetWise::DataManagement; -using namespace Aws::IoTFleetWise::OffboardConnectivity; -using namespace Aws::IoTFleetWise::OffboardConnectivityAwsIot; -using namespace Aws::IoTFleetWise::Schemas; - -/** - * @brief Create a mock ISender to be used by the Checkin test - */ -class MockSender : public ISender +namespace Aws +{ +namespace IoTFleetWise { -public: - // Create a callback that will allow the sender to inject a testing function - using Callback = std::function; - Callback mCallback; - - bool - isAlive() override - { - return true; - } - - size_t - getMaxSendSize() const override - { - return 12345; - } - - ConnectivityError - sendBuffer( const std::uint8_t *buf, - size_t size, - struct Aws::IoTFleetWise::OffboardConnectivity::CollectionSchemeParams collectionSchemeParams = - CollectionSchemeParams() ) override - { - static_cast( collectionSchemeParams ); // Currently not implemented, hence unused - if ( !mCallback ) - { - return ConnectivityError::NoConnection; - } - return mCallback( buf, size ); - } - - ConnectivityError - sendFile( const std::string &filePath, - size_t size, - struct CollectionSchemeParams collectionSchemeParams = CollectionSchemeParams() ) override - { - static_cast( filePath ); - static_cast( size ); - static_cast( collectionSchemeParams ); - return ConnectivityError::TypeNotSupported; - } -}; +using ::testing::_; +using ::testing::Gt; +using ::testing::Return; +using ::testing::Sequence; +using ::testing::StrictMock; TEST( CollectionSchemeIngestionTest, CollectionSchemeIngestionClass ) { @@ -99,10 +71,7 @@ class CheckinTest : public ::testing::Test { public: static void - checkinTest( const std::uint8_t *buf, - size_t size, - const std::vector &sampleDocList, - Timestamp timeBeforeCheckin ) + checkinTest( const std::string &data, const std::vector &sampleDocList, Timestamp timeBeforeCheckin ) { std::shared_ptr clock = ClockHandler::getClock(); @@ -110,8 +79,8 @@ class CheckinTest : public ::testing::Test std::multiset documentSet( sampleDocList.begin(), sampleDocList.end() ); // Deserialize the protobuf - CheckinMsg::Checkin sentCheckin; - ASSERT_TRUE( sentCheckin.ParseFromArray( buf, (int)size ) ); + Schemas::CheckinMsg::Checkin sentCheckin; + ASSERT_TRUE( sentCheckin.ParseFromString( data ) ); // Make sure the size of the documents is the same ASSERT_EQ( sentCheckin.document_sync_ids_size(), sampleDocList.size() ); @@ -140,12 +109,12 @@ TEST( CollectionSchemeIngestionTest, Checkins ) auto awsIotModule = std::make_shared( "", "", "", "", "", nullptr ); // Create a mock Sender - auto mockSender = std::make_shared(); + auto senderMock = std::make_shared>(); Schema collectionSchemeIngestion( std::make_shared( awsIotModule.get(), nullptr, awsIotModule.get()->mConnection ), std::make_shared( awsIotModule.get(), nullptr, awsIotModule.get()->mConnection ), - mockSender ); + senderMock ); std::shared_ptr clock = ClockHandler::getClock(); Timestamp timeBeforeCheckin = clock->systemTimeSinceEpochMs(); @@ -153,14 +122,20 @@ TEST( CollectionSchemeIngestionTest, Checkins ) // Create list of Arns std::vector sampleDocList; - // Create a lambda to inject in the mockSender that will handle the bulk of the testing - mockSender->mCallback = [&]( const std::uint8_t *buf, size_t size ) -> ConnectivityError { - CheckinTest::checkinTest( buf, size, sampleDocList, timeBeforeCheckin ); - return ConnectivityError::Success; - }; + Sequence seq; + EXPECT_CALL( *senderMock, mockedSendBuffer( _, Gt( 0 ), _ ) ) + .Times( 3 ) + .InSequence( seq ) + .WillOnce( Return( ConnectivityError::Success ) ); + EXPECT_CALL( *senderMock, mockedSendBuffer( _, Gt( 0 ), _ ) ) + .InSequence( seq ) + .WillOnce( Return( ConnectivityError::NoConnection ) ); // Test an empty checkin ASSERT_TRUE( collectionSchemeIngestion.sendCheckin( sampleDocList ) ); + ASSERT_EQ( senderMock->getSentBufferData().size(), 1 ); + ASSERT_NO_FATAL_FAILURE( + CheckinTest::checkinTest( senderMock->getSentBufferData()[0].data, sampleDocList, timeBeforeCheckin ) ); // Add some doc arns sampleDocList.emplace_back( "DocArn1" ); @@ -174,12 +149,12 @@ TEST( CollectionSchemeIngestionTest, Checkins ) // Test with duplicates - this shouldn't occur but make sure it works anyways sampleDocList.emplace_back( "DocArn4" ); ASSERT_TRUE( collectionSchemeIngestion.sendCheckin( sampleDocList ) ); - // Simulate a offboardconnectivity issue, the checkin message should fail to send. - mockSender->mCallback = [&]( const std::uint8_t *buf, size_t size ) -> ConnectivityError { - CheckinTest::checkinTest( buf, size, sampleDocList, timeBeforeCheckin ); - return ConnectivityError::NoConnection; - }; + + // Second call should simulate a offboardconnectivity issue, the checkin message should fail to send. ASSERT_FALSE( collectionSchemeIngestion.sendCheckin( sampleDocList ) ); + ASSERT_EQ( senderMock->getSentBufferData().size(), 4 ); + ASSERT_NO_FATAL_FAILURE( + CheckinTest::checkinTest( senderMock->getSentBufferData()[3].data, sampleDocList, timeBeforeCheckin ) ); } /** @@ -194,12 +169,12 @@ TEST( SchemaTest, DecoderManifestIngestion ) #define CAN_SOURCE_FOR_NODE_B 1 // Create a Decoder manifest protocol buffer and pack it with the data - DecoderManifestMsg::DecoderManifest protoDM; + Schemas::DecoderManifestMsg::DecoderManifest protoDM; protoDM.set_sync_id( "arn:aws:iam::123456789012:user/Development/product_1234/*" ); // Create a Proto CANSignal - DecoderManifestMsg::CANSignal *protoCANSignalA = protoDM.add_can_signals(); + Schemas::DecoderManifestMsg::CANSignal *protoCANSignalA = protoDM.add_can_signals(); protoCANSignalA->set_signal_id( 3908 ); protoCANSignalA->set_interface_id( "123" ); @@ -211,7 +186,7 @@ TEST( SchemaTest, DecoderManifestIngestion ) protoCANSignalA->set_factor( 10 ); protoCANSignalA->set_length( 8 ); - DecoderManifestMsg::CANSignal *protoCANSignalB = protoDM.add_can_signals(); + Schemas::DecoderManifestMsg::CANSignal *protoCANSignalB = protoDM.add_can_signals(); protoCANSignalB->set_signal_id( 2987 ); protoCANSignalB->set_interface_id( "123" ); @@ -223,7 +198,7 @@ TEST( SchemaTest, DecoderManifestIngestion ) protoCANSignalB->set_factor( 10 ); protoCANSignalB->set_length( 8 ); - DecoderManifestMsg::CANSignal *protoCANSignalC = protoDM.add_can_signals(); + Schemas::DecoderManifestMsg::CANSignal *protoCANSignalC = protoDM.add_can_signals(); protoCANSignalC->set_signal_id( 50000 ); protoCANSignalC->set_interface_id( "4892" ); @@ -235,7 +210,7 @@ TEST( SchemaTest, DecoderManifestIngestion ) protoCANSignalC->set_factor( 10 ); protoCANSignalC->set_length( 8 ); - DecoderManifestMsg::OBDPIDSignal *protoOBDPIDSignalA = protoDM.add_obd_pid_signals(); + Schemas::DecoderManifestMsg::OBDPIDSignal *protoOBDPIDSignalA = protoDM.add_obd_pid_signals(); protoOBDPIDSignalA->set_signal_id( 123 ); protoOBDPIDSignalA->set_pid_response_length( 10 ); protoOBDPIDSignalA->set_service_mode( 1 ); @@ -247,7 +222,7 @@ TEST( SchemaTest, DecoderManifestIngestion ) protoOBDPIDSignalA->set_bit_right_shift( 2 ); protoOBDPIDSignalA->set_bit_mask_length( 2 ); - DecoderManifestMsg::OBDPIDSignal *protoOBDPIDSignalB = protoDM.add_obd_pid_signals(); + Schemas::DecoderManifestMsg::OBDPIDSignal *protoOBDPIDSignalB = protoDM.add_obd_pid_signals(); protoOBDPIDSignalB->set_signal_id( 567 ); protoOBDPIDSignalB->set_pid_response_length( 4 ); protoOBDPIDSignalB->set_service_mode( 1 ); @@ -359,7 +334,7 @@ TEST( SchemaTest, DecoderManifestIngestion ) TEST( SchemaTest, SchemaInvalidDecoderManifestTest ) { // Create a Decoder manifest protocol buffer and pack it with the data - DecoderManifestMsg::DecoderManifest protoDM; + Schemas::DecoderManifestMsg::DecoderManifest protoDM; protoDM.set_sync_id( "arn:aws:iam::123456789012:user/Development/product_1234/*" ); @@ -409,7 +384,7 @@ TEST( SchemaTest, CollectionSchemeIngestionList ) ASSERT_FALSE( testPIPL.build() ); // Now lets try some real data :) - CollectionSchemesMsg::CollectionSchemes protoCollectionSchemesMsg; + Schemas::CollectionSchemesMsg::CollectionSchemes protoCollectionSchemesMsg; auto p1 = protoCollectionSchemesMsg.add_collection_schemes(); auto p2 = protoCollectionSchemesMsg.add_collection_schemes(); @@ -447,14 +422,14 @@ TEST( SchemaTest, CollectionSchemeIngestionList ) TEST( SchemaTest, CollectionSchemeIngestionHeartBeat ) { // Create a collection scheme Proto Message - CollectionSchemesMsg::CollectionScheme collectionSchemeTestMessage; + Schemas::CollectionSchemesMsg::CollectionScheme collectionSchemeTestMessage; collectionSchemeTestMessage.set_campaign_sync_id( "arn:aws:iam::2.23606797749:user/Development/product_1234/*" ); collectionSchemeTestMessage.set_decoder_manifest_sync_id( "model_manifest_12" ); collectionSchemeTestMessage.set_start_time_ms_epoch( 1621448160000 ); collectionSchemeTestMessage.set_expiry_time_ms_epoch( 2621448160000 ); // Create a Time_based_collection_scheme - CollectionSchemesMsg::TimeBasedCollectionScheme *message1 = + Schemas::CollectionSchemesMsg::TimeBasedCollectionScheme *message1 = collectionSchemeTestMessage.mutable_time_based_collection_scheme(); message1->set_time_based_collection_scheme_period_ms( 5000 ); @@ -465,21 +440,21 @@ TEST( SchemaTest, CollectionSchemeIngestionHeartBeat ) collectionSchemeTestMessage.set_priority( 9 ); // Add 3 Signals - CollectionSchemesMsg::SignalInformation *signal1 = collectionSchemeTestMessage.add_signal_information(); + Schemas::CollectionSchemesMsg::SignalInformation *signal1 = collectionSchemeTestMessage.add_signal_information(); signal1->set_signal_id( 0 ); signal1->set_sample_buffer_size( 10000 ); signal1->set_minimum_sample_period_ms( 1000 ); signal1->set_fixed_window_period_ms( 1000 ); signal1->set_condition_only_signal( false ); - CollectionSchemesMsg::SignalInformation *signal2 = collectionSchemeTestMessage.add_signal_information(); + Schemas::CollectionSchemesMsg::SignalInformation *signal2 = collectionSchemeTestMessage.add_signal_information(); signal2->set_signal_id( 1 ); signal2->set_sample_buffer_size( 10000 ); signal2->set_minimum_sample_period_ms( 1000 ); signal2->set_fixed_window_period_ms( 1000 ); signal2->set_condition_only_signal( false ); - CollectionSchemesMsg::SignalInformation *signal3 = collectionSchemeTestMessage.add_signal_information(); + Schemas::CollectionSchemesMsg::SignalInformation *signal3 = collectionSchemeTestMessage.add_signal_information(); signal3->set_signal_id( 2 ); signal3->set_sample_buffer_size( 1000 ); signal3->set_minimum_sample_period_ms( 100 ); @@ -487,13 +462,13 @@ TEST( SchemaTest, CollectionSchemeIngestionHeartBeat ) signal3->set_condition_only_signal( true ); // Add 2 RAW CAN Messages - CollectionSchemesMsg::RawCanFrame *can1 = collectionSchemeTestMessage.add_raw_can_frames_to_collect(); + Schemas::CollectionSchemesMsg::RawCanFrame *can1 = collectionSchemeTestMessage.add_raw_can_frames_to_collect(); can1->set_can_interface_id( "123" ); can1->set_can_message_id( 0x350 ); can1->set_sample_buffer_size( 100 ); can1->set_minimum_sample_period_ms( 10000 ); - CollectionSchemesMsg::RawCanFrame *can2 = collectionSchemeTestMessage.add_raw_can_frames_to_collect(); + Schemas::CollectionSchemesMsg::RawCanFrame *can2 = collectionSchemeTestMessage.add_raw_can_frames_to_collect(); can2->set_can_interface_id( "124" ); can2->set_can_message_id( 0x351 ); can2->set_sample_buffer_size( 10 ); @@ -530,7 +505,7 @@ TEST( SchemaTest, CollectionSchemeIngestionHeartBeat ) // Test for Copy and Build the message ASSERT_TRUE( collectionSchemeTest.copyData( - std::make_shared( collectionSchemeTestMessage ) ) ); + std::make_shared( collectionSchemeTestMessage ) ) ); ASSERT_TRUE( collectionSchemeTest.build() ); // isReady should now evaluate to True @@ -591,158 +566,164 @@ TEST( SchemaTest, CollectionSchemeIngestionHeartBeat ) TEST( SchemaTest, SchemaCollectionEventBased ) { // Create a collection scheme Proto Message - CollectionSchemesMsg::CollectionScheme collectionSchemeTestMessage; + Schemas::CollectionSchemesMsg::CollectionScheme collectionSchemeTestMessage; collectionSchemeTestMessage.set_campaign_sync_id( "arn:aws:iam::2.23606797749:user/Development/product_1235/*" ); collectionSchemeTestMessage.set_decoder_manifest_sync_id( "model_manifest_13" ); collectionSchemeTestMessage.set_start_time_ms_epoch( 162144816000 ); collectionSchemeTestMessage.set_expiry_time_ms_epoch( 262144816000 ); // Create an Event/Condition Based CollectionScheme - CollectionSchemesMsg::ConditionBasedCollectionScheme *message = + Schemas::CollectionSchemesMsg::ConditionBasedCollectionScheme *message = collectionSchemeTestMessage.mutable_condition_based_collection_scheme(); message->set_condition_minimum_interval_ms( 650 ); message->set_condition_language_version( 20 ); message->set_condition_trigger_mode( - CollectionSchemesMsg::ConditionBasedCollectionScheme_ConditionTriggerMode_TRIGGER_ALWAYS ); + Schemas::CollectionSchemesMsg::ConditionBasedCollectionScheme_ConditionTriggerMode_TRIGGER_ALWAYS ); // Build the AST Tree: //---------- - auto *root = new CollectionSchemesMsg::ConditionNode(); + auto *root = new Schemas::CollectionSchemesMsg::ConditionNode(); message->set_allocated_condition_tree( root ); - auto *rootOp = new CollectionSchemesMsg::ConditionNode_NodeOperator(); + auto *rootOp = new Schemas::CollectionSchemesMsg::ConditionNode_NodeOperator(); root->set_allocated_node_operator( rootOp ); - rootOp->set_operator_( CollectionSchemesMsg::ConditionNode_NodeOperator_Operator_LOGICAL_AND ); + rootOp->set_operator_( Schemas::CollectionSchemesMsg::ConditionNode_NodeOperator_Operator_LOGICAL_AND ); //---------- - auto *left = new CollectionSchemesMsg::ConditionNode(); + auto *left = new Schemas::CollectionSchemesMsg::ConditionNode(); rootOp->set_allocated_left_child( left ); - auto *leftOp = new CollectionSchemesMsg::ConditionNode_NodeOperator(); + auto *leftOp = new Schemas::CollectionSchemesMsg::ConditionNode_NodeOperator(); left->set_allocated_node_operator( leftOp ); - leftOp->set_operator_( CollectionSchemesMsg::ConditionNode_NodeOperator_Operator_LOGICAL_OR ); + leftOp->set_operator_( Schemas::CollectionSchemesMsg::ConditionNode_NodeOperator_Operator_LOGICAL_OR ); - auto *right = new CollectionSchemesMsg::ConditionNode(); + auto *right = new Schemas::CollectionSchemesMsg::ConditionNode(); rootOp->set_allocated_right_child( right ); - auto *rightOp = new CollectionSchemesMsg::ConditionNode_NodeOperator(); + auto *rightOp = new Schemas::CollectionSchemesMsg::ConditionNode_NodeOperator(); right->set_allocated_node_operator( rightOp ); - rightOp->set_operator_( CollectionSchemesMsg::ConditionNode_NodeOperator_Operator_COMPARE_SMALLER ); + rightOp->set_operator_( Schemas::CollectionSchemesMsg::ConditionNode_NodeOperator_Operator_COMPARE_SMALLER ); //---------- - auto *left_left = new CollectionSchemesMsg::ConditionNode(); + auto *left_left = new Schemas::CollectionSchemesMsg::ConditionNode(); leftOp->set_allocated_left_child( left_left ); - auto *left_leftOp = new CollectionSchemesMsg::ConditionNode_NodeOperator(); + auto *left_leftOp = new Schemas::CollectionSchemesMsg::ConditionNode_NodeOperator(); left_left->set_allocated_node_operator( left_leftOp ); - left_leftOp->set_operator_( CollectionSchemesMsg::ConditionNode_NodeOperator_Operator_COMPARE_BIGGER ); + left_leftOp->set_operator_( Schemas::CollectionSchemesMsg::ConditionNode_NodeOperator_Operator_COMPARE_BIGGER ); - auto *left_right = new CollectionSchemesMsg::ConditionNode(); + auto *left_right = new Schemas::CollectionSchemesMsg::ConditionNode(); leftOp->set_allocated_right_child( left_right ); - auto *left_rightOp = new CollectionSchemesMsg::ConditionNode_NodeOperator(); + auto *left_rightOp = new Schemas::CollectionSchemesMsg::ConditionNode_NodeOperator(); left_right->set_allocated_node_operator( left_rightOp ); - left_rightOp->set_operator_( CollectionSchemesMsg::ConditionNode_NodeOperator_Operator_COMPARE_NOT_EQUAL ); + left_rightOp->set_operator_( Schemas::CollectionSchemesMsg::ConditionNode_NodeOperator_Operator_COMPARE_NOT_EQUAL ); - auto *right_left = new CollectionSchemesMsg::ConditionNode(); + auto *right_left = new Schemas::CollectionSchemesMsg::ConditionNode(); rightOp->set_allocated_left_child( right_left ); - auto *right_leftOp = new CollectionSchemesMsg::ConditionNode_NodeOperator(); + auto *right_leftOp = new Schemas::CollectionSchemesMsg::ConditionNode_NodeOperator(); right_left->set_allocated_node_operator( right_leftOp ); - right_leftOp->set_operator_( CollectionSchemesMsg::ConditionNode_NodeOperator_Operator_COMPARE_SMALLER_EQUAL ); + right_leftOp->set_operator_( + Schemas::CollectionSchemesMsg::ConditionNode_NodeOperator_Operator_COMPARE_SMALLER_EQUAL ); - auto *right_right = new CollectionSchemesMsg::ConditionNode(); + auto *right_right = new Schemas::CollectionSchemesMsg::ConditionNode(); rightOp->set_allocated_right_child( right_right ); - auto *right_rightOp = new CollectionSchemesMsg::ConditionNode_NodeOperator(); + auto *right_rightOp = new Schemas::CollectionSchemesMsg::ConditionNode_NodeOperator(); right_right->set_allocated_node_operator( right_rightOp ); - right_rightOp->set_operator_( CollectionSchemesMsg::ConditionNode_NodeOperator_Operator_COMPARE_SMALLER ); + right_rightOp->set_operator_( Schemas::CollectionSchemesMsg::ConditionNode_NodeOperator_Operator_COMPARE_SMALLER ); //---------- - auto *left_left_left = new CollectionSchemesMsg::ConditionNode(); + auto *left_left_left = new Schemas::CollectionSchemesMsg::ConditionNode(); left_leftOp->set_allocated_left_child( left_left_left ); left_left_left->set_node_signal_id( 19 ); - auto *left_left_right = new CollectionSchemesMsg::ConditionNode(); + auto *left_left_right = new Schemas::CollectionSchemesMsg::ConditionNode(); left_leftOp->set_allocated_right_child( left_left_right ); left_left_right->set_node_double_value( 1 ); - auto *left_right_left = new CollectionSchemesMsg::ConditionNode(); + auto *left_right_left = new Schemas::CollectionSchemesMsg::ConditionNode(); left_rightOp->set_allocated_left_child( left_right_left ); - auto *left_right_leftOp = new CollectionSchemesMsg::ConditionNode_NodeOperator(); + auto *left_right_leftOp = new Schemas::CollectionSchemesMsg::ConditionNode_NodeOperator(); left_right_left->set_allocated_node_operator( left_right_leftOp ); - left_right_leftOp->set_operator_( CollectionSchemesMsg::ConditionNode_NodeOperator_Operator_ARITHMETIC_MULTIPLY ); + left_right_leftOp->set_operator_( + Schemas::CollectionSchemesMsg::ConditionNode_NodeOperator_Operator_ARITHMETIC_MULTIPLY ); - auto *left_right_right = new CollectionSchemesMsg::ConditionNode(); + auto *left_right_right = new Schemas::CollectionSchemesMsg::ConditionNode(); left_rightOp->set_allocated_right_child( left_right_right ); - auto *left_right_rightOp = new CollectionSchemesMsg::ConditionNode_NodeOperator(); + auto *left_right_rightOp = new Schemas::CollectionSchemesMsg::ConditionNode_NodeOperator(); left_right_right->set_allocated_node_operator( left_right_rightOp ); - left_right_rightOp->set_operator_( CollectionSchemesMsg::ConditionNode_NodeOperator_Operator_ARITHMETIC_DIVIDE ); + left_right_rightOp->set_operator_( + Schemas::CollectionSchemesMsg::ConditionNode_NodeOperator_Operator_ARITHMETIC_DIVIDE ); - auto *right_left_left = new CollectionSchemesMsg::ConditionNode(); + auto *right_left_left = new Schemas::CollectionSchemesMsg::ConditionNode(); right_leftOp->set_allocated_left_child( right_left_left ); - auto *right_left_leftOp = new CollectionSchemesMsg::ConditionNode_NodeOperator(); + auto *right_left_leftOp = new Schemas::CollectionSchemesMsg::ConditionNode_NodeOperator(); right_left_left->set_allocated_node_operator( right_left_leftOp ); - right_left_leftOp->set_operator_( CollectionSchemesMsg::ConditionNode_NodeOperator_Operator_LOGICAL_NOT ); + right_left_leftOp->set_operator_( Schemas::CollectionSchemesMsg::ConditionNode_NodeOperator_Operator_LOGICAL_NOT ); - auto *right_left_right = new CollectionSchemesMsg::ConditionNode(); + auto *right_left_right = new Schemas::CollectionSchemesMsg::ConditionNode(); right_leftOp->set_allocated_right_child( right_left_right ); - auto *right_left_rightOp = new CollectionSchemesMsg::ConditionNode_NodeOperator(); + auto *right_left_rightOp = new Schemas::CollectionSchemesMsg::ConditionNode_NodeOperator(); right_left_right->set_allocated_node_operator( right_left_rightOp ); - right_left_rightOp->set_operator_( CollectionSchemesMsg::ConditionNode_NodeOperator_Operator_ARITHMETIC_PLUS ); + right_left_rightOp->set_operator_( + Schemas::CollectionSchemesMsg::ConditionNode_NodeOperator_Operator_ARITHMETIC_PLUS ); - auto *right_right_left = new CollectionSchemesMsg::ConditionNode(); + auto *right_right_left = new Schemas::CollectionSchemesMsg::ConditionNode(); right_rightOp->set_allocated_left_child( right_right_left ); - auto *right_right_leftOp = new CollectionSchemesMsg::ConditionNode_NodeOperator(); + auto *right_right_leftOp = new Schemas::CollectionSchemesMsg::ConditionNode_NodeOperator(); right_right_left->set_allocated_node_operator( right_right_leftOp ); - right_right_leftOp->set_operator_( CollectionSchemesMsg::ConditionNode_NodeOperator_Operator_ARITHMETIC_MINUS ); + right_right_leftOp->set_operator_( + Schemas::CollectionSchemesMsg::ConditionNode_NodeOperator_Operator_ARITHMETIC_MINUS ); - auto *right_right_right = new CollectionSchemesMsg::ConditionNode(); + auto *right_right_right = new Schemas::CollectionSchemesMsg::ConditionNode(); right_rightOp->set_allocated_right_child( right_right_right ); - auto *right_right_rightOp = new CollectionSchemesMsg::ConditionNode_NodeOperator(); + auto *right_right_rightOp = new Schemas::CollectionSchemesMsg::ConditionNode_NodeOperator(); right_right_right->set_allocated_node_operator( right_right_rightOp ); - right_right_rightOp->set_operator_( CollectionSchemesMsg::ConditionNode_NodeOperator_Operator_ARITHMETIC_MINUS ); + right_right_rightOp->set_operator_( + Schemas::CollectionSchemesMsg::ConditionNode_NodeOperator_Operator_ARITHMETIC_MINUS ); //---------- - auto *left_right_left_left = new CollectionSchemesMsg::ConditionNode(); + auto *left_right_left_left = new Schemas::CollectionSchemesMsg::ConditionNode(); left_right_leftOp->set_allocated_left_child( left_right_left_left ); left_right_left_left->set_node_signal_id( 19 ); - auto *left_right_left_right = new CollectionSchemesMsg::ConditionNode(); + auto *left_right_left_right = new Schemas::CollectionSchemesMsg::ConditionNode(); left_right_leftOp->set_allocated_right_child( left_right_left_right ); left_right_left_right->set_node_double_value( 1 ); - auto *left_right_right_left = new CollectionSchemesMsg::ConditionNode(); + auto *left_right_right_left = new Schemas::CollectionSchemesMsg::ConditionNode(); left_right_rightOp->set_allocated_left_child( left_right_right_left ); left_right_right_left->set_node_signal_id( 19 ); - auto *left_right_right_right = new CollectionSchemesMsg::ConditionNode(); + auto *left_right_right_right = new Schemas::CollectionSchemesMsg::ConditionNode(); left_right_rightOp->set_allocated_right_child( left_right_right_right ); left_right_right_right->set_node_double_value( 1 ); - auto *right_left_left_left = new CollectionSchemesMsg::ConditionNode(); + auto *right_left_left_left = new Schemas::CollectionSchemesMsg::ConditionNode(); right_left_leftOp->set_allocated_left_child( right_left_left_left ); right_left_left_left->set_node_signal_id( 19 ); - auto *right_left_right_left = new CollectionSchemesMsg::ConditionNode(); + auto *right_left_right_left = new Schemas::CollectionSchemesMsg::ConditionNode(); right_left_rightOp->set_allocated_left_child( right_left_right_left ); right_left_right_left->set_node_signal_id( 19 ); - auto *right_left_right_right = new CollectionSchemesMsg::ConditionNode(); + auto *right_left_right_right = new Schemas::CollectionSchemesMsg::ConditionNode(); right_left_rightOp->set_allocated_right_child( right_left_right_right ); right_left_right_right->set_node_double_value( 1 ); - auto *right_right_left_left = new CollectionSchemesMsg::ConditionNode(); + auto *right_right_left_left = new Schemas::CollectionSchemesMsg::ConditionNode(); right_right_leftOp->set_allocated_left_child( right_right_left_left ); right_right_left_left->set_node_signal_id( 19 ); - auto *right_right_left_right = new CollectionSchemesMsg::ConditionNode(); + auto *right_right_left_right = new Schemas::CollectionSchemesMsg::ConditionNode(); right_right_leftOp->set_allocated_right_child( right_right_left_right ); right_right_left_right->set_node_double_value( 1 ); - auto *right_right_right_left = new CollectionSchemesMsg::ConditionNode(); + auto *right_right_right_left = new Schemas::CollectionSchemesMsg::ConditionNode(); right_right_rightOp->set_allocated_left_child( right_right_right_left ); right_right_right_left->set_node_signal_id( 19 ); - auto *right_right_right_right = new CollectionSchemesMsg::ConditionNode(); + auto *right_right_right_right = new Schemas::CollectionSchemesMsg::ConditionNode(); right_right_rightOp->set_allocated_right_child( right_right_right_right ); right_right_right_right->set_node_double_value( 1 ); @@ -755,21 +736,21 @@ TEST( SchemaTest, SchemaCollectionEventBased ) collectionSchemeTestMessage.set_priority( 5 ); // Add 3 Signals - CollectionSchemesMsg::SignalInformation *signal1 = collectionSchemeTestMessage.add_signal_information(); + Schemas::CollectionSchemesMsg::SignalInformation *signal1 = collectionSchemeTestMessage.add_signal_information(); signal1->set_signal_id( 19 ); signal1->set_sample_buffer_size( 5 ); signal1->set_minimum_sample_period_ms( 500 ); signal1->set_fixed_window_period_ms( 600 ); signal1->set_condition_only_signal( true ); - CollectionSchemesMsg::SignalInformation *signal2 = collectionSchemeTestMessage.add_signal_information(); + Schemas::CollectionSchemesMsg::SignalInformation *signal2 = collectionSchemeTestMessage.add_signal_information(); signal2->set_signal_id( 17 ); signal2->set_sample_buffer_size( 10000 ); signal2->set_minimum_sample_period_ms( 1000 ); signal2->set_fixed_window_period_ms( 1000 ); signal2->set_condition_only_signal( false ); - CollectionSchemesMsg::SignalInformation *signal3 = collectionSchemeTestMessage.add_signal_information(); + Schemas::CollectionSchemesMsg::SignalInformation *signal3 = collectionSchemeTestMessage.add_signal_information(); signal3->set_signal_id( 3 ); signal3->set_sample_buffer_size( 1000 ); signal3->set_minimum_sample_period_ms( 100 ); @@ -777,7 +758,7 @@ TEST( SchemaTest, SchemaCollectionEventBased ) signal3->set_condition_only_signal( true ); // Add 1 RAW CAN Messages - CollectionSchemesMsg::RawCanFrame *can1 = collectionSchemeTestMessage.add_raw_can_frames_to_collect(); + Schemas::CollectionSchemesMsg::RawCanFrame *can1 = collectionSchemeTestMessage.add_raw_can_frames_to_collect(); can1->set_can_interface_id( "1230" ); can1->set_can_message_id( 0x1FF ); can1->set_sample_buffer_size( 200 ); @@ -814,7 +795,7 @@ TEST( SchemaTest, SchemaCollectionEventBased ) // Test for Copy and Build the message ASSERT_TRUE( collectionSchemeTest.copyData( - std::make_shared( collectionSchemeTestMessage ) ) ); + std::make_shared( collectionSchemeTestMessage ) ) ); ASSERT_TRUE( collectionSchemeTest.build() ); // isReady should now evaluate to True @@ -942,38 +923,38 @@ TEST( SchemaTest, SchemaCollectionEventBased ) TEST( SchemaTest, SchemaGeohashFunctionNode ) { // Create a collection scheme Proto Message - CollectionSchemesMsg::CollectionScheme collectionSchemeTestMessage; + Schemas::CollectionSchemesMsg::CollectionScheme collectionSchemeTestMessage; collectionSchemeTestMessage.set_campaign_sync_id( "arn:aws:iam::2.23606797749:user/Development/product_1235/*" ); collectionSchemeTestMessage.set_decoder_manifest_sync_id( "model_manifest_13" ); collectionSchemeTestMessage.set_start_time_ms_epoch( 162144816000 ); collectionSchemeTestMessage.set_expiry_time_ms_epoch( 262144816000 ); // Create an Event/Condition Based CollectionScheme - CollectionSchemesMsg::ConditionBasedCollectionScheme *message = + Schemas::CollectionSchemesMsg::ConditionBasedCollectionScheme *message = collectionSchemeTestMessage.mutable_condition_based_collection_scheme(); message->set_condition_minimum_interval_ms( 650 ); message->set_condition_language_version( 20 ); message->set_condition_trigger_mode( - CollectionSchemesMsg::ConditionBasedCollectionScheme_ConditionTriggerMode_TRIGGER_ALWAYS ); + Schemas::CollectionSchemesMsg::ConditionBasedCollectionScheme_ConditionTriggerMode_TRIGGER_ALWAYS ); // Build a simple AST Tree. // Root: Equal // Left Child: GeohashFunction // Right Child: 1.0 - auto *root = new CollectionSchemesMsg::ConditionNode(); - auto *rootOp = new CollectionSchemesMsg::ConditionNode_NodeOperator(); - rootOp->set_operator_( CollectionSchemesMsg::ConditionNode_NodeOperator_Operator_COMPARE_EQUAL ); + auto *root = new Schemas::CollectionSchemesMsg::ConditionNode(); + auto *rootOp = new Schemas::CollectionSchemesMsg::ConditionNode_NodeOperator(); + rootOp->set_operator_( Schemas::CollectionSchemesMsg::ConditionNode_NodeOperator_Operator_COMPARE_EQUAL ); - auto *leftChild = new CollectionSchemesMsg::ConditionNode(); - auto *leftChildFunction = new CollectionSchemesMsg::ConditionNode_NodeFunction(); - auto *leftChildGeohashFunction = new CollectionSchemesMsg::ConditionNode_NodeFunction_GeohashFunction(); + auto *leftChild = new Schemas::CollectionSchemesMsg::ConditionNode(); + auto *leftChildFunction = new Schemas::CollectionSchemesMsg::ConditionNode_NodeFunction(); + auto *leftChildGeohashFunction = new Schemas::CollectionSchemesMsg::ConditionNode_NodeFunction_GeohashFunction(); leftChildGeohashFunction->set_latitude_signal_id( 0x1 ); leftChildGeohashFunction->set_longitude_signal_id( 0x2 ); leftChildGeohashFunction->set_geohash_precision( 6 ); leftChildGeohashFunction->set_gps_unit( - CollectionSchemesMsg::ConditionNode_NodeFunction_GeohashFunction_GPSUnitType_MILLIARCSECOND ); + Schemas::CollectionSchemesMsg::ConditionNode_NodeFunction_GeohashFunction_GPSUnitType_MILLIARCSECOND ); - auto *rightChild = new CollectionSchemesMsg::ConditionNode(); + auto *rightChild = new Schemas::CollectionSchemesMsg::ConditionNode(); rightChild->set_node_double_value( 1.0 ); leftChildFunction->set_allocated_geohash_function( leftChildGeohashFunction ); @@ -998,7 +979,7 @@ TEST( SchemaTest, SchemaGeohashFunctionNode ) // Test for Copy and Build the message ASSERT_TRUE( collectionSchemeTest.copyData( - std::make_shared( collectionSchemeTestMessage ) ) ); + std::make_shared( collectionSchemeTestMessage ) ) ); ASSERT_TRUE( collectionSchemeTest.build() ); // isReady should now evaluate to True @@ -1022,3 +1003,6 @@ TEST( SchemaTest, SchemaGeohashFunctionNode ) ASSERT_EQ( collectionSchemeTest.getAllExpressionNodes().at( 0 ).right->nodeType, ExpressionNodeType::FLOAT ); ASSERT_EQ( collectionSchemeTest.getAllExpressionNodes().at( 0 ).right->floatingValue, 1.0 ); } + +} // namespace IoTFleetWise +} // namespace Aws diff --git a/src/platform/linux/threadingmanagement/test/ThreadTest.cpp b/test/unit/ThreadTest.cpp similarity index 83% rename from src/platform/linux/threadingmanagement/test/ThreadTest.cpp rename to test/unit/ThreadTest.cpp index c0fe3654..8f792a12 100644 --- a/src/platform/linux/threadingmanagement/test/ThreadTest.cpp +++ b/test/unit/ThreadTest.cpp @@ -1,12 +1,16 @@ - // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 #include "Thread.h" - #include +#include +#include + +namespace Aws +{ +namespace IoTFleetWise +{ -using namespace Aws::IoTFleetWise::Platform::Linux; void workerFunction( void *data ) { @@ -26,3 +30,6 @@ TEST( ThreadTest, ThreadCPUUsageInfo ) ASSERT_TRUE( !thread.isValid() ); ASSERT_TRUE( !thread.isActive() ); } + +} // namespace IoTFleetWise +} // namespace Aws diff --git a/src/platform/linux/timemanagement/test/TimerTest.cpp b/test/unit/TimerTest.cpp similarity index 87% rename from src/platform/linux/timemanagement/test/TimerTest.cpp rename to test/unit/TimerTest.cpp index 7984ef49..bb6f3522 100644 --- a/src/platform/linux/timemanagement/test/TimerTest.cpp +++ b/test/unit/TimerTest.cpp @@ -1,12 +1,13 @@ - // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 #include "Timer.h" - #include -using namespace Aws::IoTFleetWise::Platform::Linux; +namespace Aws +{ +namespace IoTFleetWise +{ TEST( TimerTest, timerState ) { @@ -27,3 +28,6 @@ TEST( TimerTest, timerTickCount ) ASSERT_GE( timer.getElapsedMs().count(), 0LU ); ASSERT_GE( timer.getElapsedSeconds(), 0 ); } + +} // namespace IoTFleetWise +} // namespace Aws diff --git a/src/platform/linux/logmanagement/test/TraceModuleTest.cpp b/test/unit/TraceModuleTest.cpp similarity index 93% rename from src/platform/linux/logmanagement/test/TraceModuleTest.cpp rename to test/unit/TraceModuleTest.cpp index a6b40525..49b3f9e8 100644 --- a/src/platform/linux/logmanagement/test/TraceModuleTest.cpp +++ b/test/unit/TraceModuleTest.cpp @@ -3,11 +3,14 @@ // SPDX-License-Identifier: Apache-2.0 #include "TraceModule.h" - +#include #include #include -using namespace Aws::IoTFleetWise::Platform::Linux; +namespace Aws +{ +namespace IoTFleetWise +{ TEST( TraceModuleTest, TraceModulePrint ) { @@ -37,3 +40,6 @@ TEST( TraceModuleTest, TraceModulePrint ) TraceModule::get().print(); TraceModule::get().startNewObservationWindow(); } + +} // namespace IoTFleetWise +} // namespace Aws diff --git a/src/testingsupport/test/WaitUntilTest.cpp b/test/unit/WaitUntilTest.cpp similarity index 93% rename from src/testingsupport/test/WaitUntilTest.cpp rename to test/unit/WaitUntilTest.cpp index bc892637..d13b65f3 100644 --- a/src/testingsupport/test/WaitUntilTest.cpp +++ b/test/unit/WaitUntilTest.cpp @@ -2,12 +2,15 @@ // SPDX-License-Identifier: Apache-2.0 #include "WaitUntil.h" -#include +#include #include -#include #include -using namespace Aws::IoTFleetWise::TestingSupport; -using namespace std; +#include + +namespace Aws +{ +namespace IoTFleetWise +{ TEST( TimerTest, waitUntilTest ) { @@ -81,3 +84,6 @@ TEST( TimerTest, delayAssertFalse ) }; DELAY_ASSERT_FALSE( countdown() ); } + +} // namespace IoTFleetWise +} // namespace Aws diff --git a/src/datamanagement/datamanager/test/include/CollectionSchemeManagerMock.h b/test/unit/support/CollectionSchemeManagerMock.h similarity index 96% rename from src/datamanagement/datamanager/test/include/CollectionSchemeManagerMock.h rename to test/unit/support/CollectionSchemeManagerMock.h index a532b71f..4ee39584 100644 --- a/src/datamanagement/datamanager/test/include/CollectionSchemeManagerMock.h +++ b/test/unit/support/CollectionSchemeManagerMock.h @@ -20,11 +20,13 @@ #include #include -using namespace Aws::IoTFleetWise::Platform::Linux::PersistencyManagement; -using namespace Aws::IoTFleetWise::DataManagement; -using Aws::IoTFleetWise::Platform::Linux::ThreadListeners; - #define SECOND_TO_MILLISECOND( x ) ( 1000 ) * ( x ) + +namespace Aws +{ +namespace IoTFleetWise +{ + using uint8Ptr = std::uint8_t *; using vectorUint8 = std::vector; using vectorICollectionSchemePtr = std::vector; @@ -185,3 +187,6 @@ class mockCacheAndPersist : public CacheAndPersist // ErrorCode read( uint8_t *const readBufPtr, size_t size, DataType dataType, const std::string &filename ); MOCK_METHOD( ErrorCode, read, (uint8_t *const, size_t, DataType, const std::string &)); }; + +} // namespace IoTFleetWise +} // namespace Aws diff --git a/src/datamanagement/datamanager/test/include/CollectionSchemeManagerTest.h b/test/unit/support/CollectionSchemeManagerTest.h similarity index 93% rename from src/datamanagement/datamanager/test/include/CollectionSchemeManagerTest.h rename to test/unit/support/CollectionSchemeManagerTest.h index 4fa1f929..3366f9cf 100644 --- a/src/datamanagement/datamanager/test/include/CollectionSchemeManagerTest.h +++ b/test/unit/support/CollectionSchemeManagerTest.h @@ -3,24 +3,34 @@ #pragma once #include "CacheAndPersist.h" -#include "ClockHandler.h" +#include "CollectionInspectionAPITypes.h" #include "CollectionInspectionEngine.h" #include "CollectionSchemeIngestion.h" #include "CollectionSchemeIngestionList.h" +#include "CollectionSchemeManagementListener.h" #include "CollectionSchemeManager.h" #include "DecoderManifestIngestion.h" +#include "ICollectionScheme.h" +#include "ICollectionSchemeList.h" +#include "IDecoderDictionary.h" +#include "IDecoderManifest.h" #include "Listener.h" +#include "MessageTypes.h" #include "OBDOverCANModule.h" -#include -#include -#include -#include -#include -#include -#include +#include "SignalTypes.h" +#include "TimeTypes.h" +#include "VehicleDataSourceTypes.h" +#include // IWYU pragma: keep +#include +#include +#include +#include #include -#include -#include +#include // IWYU pragma: keep +#include +#include +#include +#include // color background definition for printing additionally in gtest #define ANSI_TXT_GRN "\033[0;32m" @@ -31,11 +41,13 @@ // sample print // std::cout << COUT_GTEST_MGT << "random seed = " << random_seed << ANSI_TXT_DFT << std::endl; #define COUT_GTEST_MGT COUT_GTEST << ANSI_TXT_MGT +#define SECOND_TO_MILLISECOND( x ) ( 1000 ) * ( x ) -using namespace Aws::IoTFleetWise::DataManagement; -using Aws::IoTFleetWise::Platform::Linux::ThreadListeners; +namespace Aws +{ +namespace IoTFleetWise +{ -#define SECOND_TO_MILLISECOND( x ) ( 1000 ) * ( x ) class IDecoderManifestTest : public DecoderManifestIngestion { public: @@ -173,7 +185,7 @@ class ICollectionSchemeTest : public CollectionSchemeIngestion { return rawCanFrms; } - const struct ExpressionNode * + const ExpressionNode * getCondition() const { return root; @@ -217,8 +229,7 @@ class ICollectionSchemeListTest : public CollectionSchemeIngestionList }; /* mock producer class that sends update to PM mocking PI */ -class CollectionSchemeManagerTestProducer - : public Aws::IoTFleetWise::Platform::Linux::ThreadListeners +class CollectionSchemeManagerTestProducer : public ThreadListeners { public: CollectionSchemeManagerTestProducer() @@ -451,3 +462,6 @@ class CollectionSchemeManagerTest : public CollectionSchemeManager protected: }; + +} // namespace IoTFleetWise +} // namespace Aws diff --git a/test/unit/support/ConnectivityModuleMock.h b/test/unit/support/ConnectivityModuleMock.h new file mode 100644 index 00000000..3f9e7fd4 --- /dev/null +++ b/test/unit/support/ConnectivityModuleMock.h @@ -0,0 +1,34 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#include "IConnectivityModule.h" +#include +#include + +namespace Aws +{ +namespace IoTFleetWise +{ +namespace Testing +{ + +class ConnectivityModuleMock : public IConnectivityModule +{ +public: + MOCK_METHOD( bool, isAlive, (), ( const override ) ); + + MOCK_METHOD( std::shared_ptr, + createNewChannel, + ( const std::shared_ptr &payloadManager ), + ( override ) ); + + MOCK_METHOD( bool, disconnect, () ); + + MOCK_METHOD( bool, connect, () ); +}; + +} // namespace Testing +} // namespace IoTFleetWise +} // namespace Aws diff --git a/test/unit/support/DataSenderManagerMock.h b/test/unit/support/DataSenderManagerMock.h new file mode 100644 index 00000000..9ab4a2b9 --- /dev/null +++ b/test/unit/support/DataSenderManagerMock.h @@ -0,0 +1,62 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#include "DataSenderManager.h" +#include +#include +#include +#include + +namespace Aws +{ +namespace IoTFleetWise +{ +namespace Testing +{ + +class DataSenderManagerMock : public DataSenderManager +{ +public: + unsigned mCheckAndSendRetrievedDataCalls{ 0 }; + + DataSenderManagerMock( CANInterfaceIDTranslator &canIDTranslator ) + : DataSenderManager( nullptr, nullptr, canIDTranslator, 0 ) + { + } + + void + processCollectedData( const TriggeredCollectionSchemeDataPtr triggeredCollectionSchemeDataPtr ) override + { + std::lock_guard lock( mProcessedDataMutex ); + mProcessedData.push_back( triggeredCollectionSchemeDataPtr ); + mockedProcessCollectedData( triggeredCollectionSchemeDataPtr ); + } + + MOCK_METHOD( void, + mockedProcessCollectedData, + ( const TriggeredCollectionSchemeDataPtr triggeredCollectionSchemeDataPtr ) ); + + std::vector + getProcessedData() + { + std::lock_guard lock( mProcessedDataMutex ); + return mProcessedData; + } + + void + checkAndSendRetrievedData() override + { + mCheckAndSendRetrievedDataCalls++; + } + +private: + // Record the calls so that we can wait for asynchronous calls to happen. + std::vector mProcessedData; + std::mutex mProcessedDataMutex; +}; + +} // namespace Testing +} // namespace IoTFleetWise +} // namespace Aws diff --git a/src/testingsupport/include/Faketime.h b/test/unit/support/Faketime.h similarity index 98% rename from src/testingsupport/include/Faketime.h rename to test/unit/support/Faketime.h index c8949e3b..6a42b7cc 100644 --- a/src/testingsupport/include/Faketime.h +++ b/test/unit/support/Faketime.h @@ -3,7 +3,6 @@ #pragma once -// Includes #include #include #include @@ -12,8 +11,7 @@ namespace Aws { namespace IoTFleetWise { -namespace TestingSupport -{ + /** * Wrapper around the faketime library to make it easier to use from tests and provide automatic clean up * @@ -121,6 +119,5 @@ class Faketime } }; -} // namespace TestingSupport } // namespace IoTFleetWise } // namespace Aws diff --git a/test/unit/support/MqttClientWrapperMock.h b/test/unit/support/MqttClientWrapperMock.h new file mode 100644 index 00000000..ed376db5 --- /dev/null +++ b/test/unit/support/MqttClientWrapperMock.h @@ -0,0 +1,36 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#include "MqttClientWrapper.h" +#include + +namespace Aws +{ +namespace IoTFleetWise +{ + +class MqttClientWrapperMock : public MqttClientWrapper +{ +public: + MqttClientWrapperMock() + : MqttClientWrapper( nullptr ){}; + + MOCK_METHOD( std::shared_ptr, + NewConnection, + (const Aws::Iot::MqttClientConnectionConfig &), + ( noexcept ) ); + + MOCK_METHOD( int, LastError, (), ( const, noexcept ) ); + + MOCK_METHOD( bool, MockedOperatorBool, (), ( const, noexcept ) ); + + virtual explicit operator bool() const noexcept override + { + return MockedOperatorBool(); + } +}; + +} // namespace IoTFleetWise +} // namespace Aws diff --git a/test/unit/support/MqttConnectionWrapperMock.h b/test/unit/support/MqttConnectionWrapperMock.h new file mode 100644 index 00000000..336e75cc --- /dev/null +++ b/test/unit/support/MqttConnectionWrapperMock.h @@ -0,0 +1,69 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#include "MqttConnectionWrapper.h" +#include + +namespace Aws +{ +namespace IoTFleetWise +{ + +class MqttConnectionWrapperMock : public MqttConnectionWrapper +{ +public: + MqttConnectionWrapperMock() + : MqttConnectionWrapper( nullptr ){}; + + MOCK_METHOD( bool, MockedOperatorBool, (), ( const, noexcept ) ); + + virtual explicit operator bool() const noexcept override + { + return MockedOperatorBool(); + } + + MOCK_METHOD( int, LastError, (), ( const, noexcept ) ); + MOCK_METHOD( bool, Connect, ( const char *, bool, uint16_t, uint32_t ), ( noexcept ) ); + MOCK_METHOD( bool, Disconnect, (), ( noexcept ) ); + MOCK_METHOD( uint16_t, + Subscribe, + (const char *, Aws::Crt::Mqtt::QOS, OnMessageReceivedHandler &&, OnSubAckHandler &&), + ( noexcept ) ); + MOCK_METHOD( bool, SetOnMessageHandler, ( OnMessageReceivedHandler && ), ( noexcept ) ); + MOCK_METHOD( uint16_t, Unsubscribe, (const char *, OnOperationCompleteHandler &&), ( noexcept ) ); + MOCK_METHOD( uint16_t, + Publish, + (const char *, Aws::Crt::Mqtt::QOS, bool, const Aws::Crt::ByteBuf &, OnOperationCompleteHandler &&), + ( noexcept ) ); + + virtual void + SetOnConnectionInterrupted( OnConnectionInterruptedHandler onConnectionInterrupted ) + { + mOnConnectionInterrupted = std::move( onConnectionInterrupted ); + } + virtual void + SetOnConnectionResumed( OnConnectionResumedHandler onConnectionResumed ) + { + mOnConnectionResumed = std::move( onConnectionResumed ); + } + virtual void + SetOnConnectionCompleted( OnConnectionCompletedHandler onConnectionCompleted ) + { + mOnConnectionCompleted = std::move( onConnectionCompleted ); + } + virtual void + SetOnDisconnect( OnDisconnectHandler onDisconnect ) + { + mOnDisconnect = std::move( onDisconnect ); + } + + OnConnectionInterruptedHandler mOnConnectionInterrupted; + OnConnectionResumedHandler mOnConnectionResumed; + OnConnectionCompletedHandler mOnConnectionCompleted; + OnDisconnectHandler mOnDisconnect; +}; + +} // namespace IoTFleetWise +} // namespace Aws diff --git a/src/vehiclenetwork/include/datatypes/OBDDataTypesUnitTestOnly.h b/test/unit/support/OBDDataTypesUnitTestOnly.h similarity index 99% rename from src/vehiclenetwork/include/datatypes/OBDDataTypesUnitTestOnly.h rename to test/unit/support/OBDDataTypesUnitTestOnly.h index defbde69..1757f2a5 100644 --- a/src/vehiclenetwork/include/datatypes/OBDDataTypesUnitTestOnly.h +++ b/test/unit/support/OBDDataTypesUnitTestOnly.h @@ -10,11 +10,6 @@ namespace Aws { namespace IoTFleetWise { -namespace DataManagement -{ -using namespace Aws::IoTFleetWise::VehicleNetwork; -using namespace Aws::IoTFleetWise::Platform::Linux; -using namespace Aws::IoTFleetWise::Platform::Utility; // Struct represent PID information: id, return length and formula for each signal struct PIDInfo @@ -530,6 +525,5 @@ enum class EmissionPIDs }; // clang-format on -} // namespace DataManagement } // namespace IoTFleetWise } // namespace Aws diff --git a/test/unit/support/PayloadManagerMock.h b/test/unit/support/PayloadManagerMock.h new file mode 100644 index 00000000..fcb05344 --- /dev/null +++ b/test/unit/support/PayloadManagerMock.h @@ -0,0 +1,45 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#include "PayloadManager.h" +#include +#include +#include +#include + +namespace Aws +{ +namespace IoTFleetWise +{ +namespace Testing +{ + +class PayloadManagerMock : public PayloadManager +{ +public: + PayloadManagerMock() + : PayloadManager( nullptr ){}; + + MOCK_METHOD( bool, + storeData, + ( const std::uint8_t *buf, size_t size, const CollectionSchemeParams &collectionSchemeParams ), + ( override ) ); + + MOCK_METHOD( void, + storeMetadata, + ( const std::string filename, size_t size, const CollectionSchemeParams &collectionSchemeParams ), + ( override ) ); + + MOCK_METHOD( ErrorCode, retrievePayloadMetadata, ( Json::Value & files ), ( override ) ); + + MOCK_METHOD( ErrorCode, + retrievePayload, + ( uint8_t * buf, size_t size, const std::string &filename ), + ( override ) ); +}; + +} // namespace Testing +} // namespace IoTFleetWise +} // namespace Aws diff --git a/test/unit/support/SenderMock.h b/test/unit/support/SenderMock.h new file mode 100644 index 00000000..93c32b9b --- /dev/null +++ b/test/unit/support/SenderMock.h @@ -0,0 +1,66 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#include "ISender.h" +#include +#include +#include +#include +#include +#include + +namespace Aws +{ +namespace IoTFleetWise +{ +namespace Testing +{ + +class SenderMock : public ISender +{ +public: + struct SentBufferData + { + std::string data; + CollectionSchemeParams collectionSchemeParams; + }; + + MOCK_METHOD( bool, isAlive, (), ( override ) ); + + MOCK_METHOD( size_t, getMaxSendSize, (), ( const, override ) ); + + ConnectivityError + sendBuffer( const std::uint8_t *buf, size_t size, CollectionSchemeParams collectionSchemeParams ) override + { + std::lock_guard lock( mSentBufferDataMutex ); + mSentBufferData.push_back( SentBufferData{ std::string( buf, buf + size ), collectionSchemeParams } ); + return mockedSendBuffer( buf, size, collectionSchemeParams ); + } + + std::vector + getSentBufferData() + { + std::lock_guard lock( mSentBufferDataMutex ); + return mSentBufferData; + } + + MOCK_METHOD( ConnectivityError, + mockedSendBuffer, + ( const std::uint8_t *buf, size_t size, CollectionSchemeParams collectionSchemeParams ) ); + + MOCK_METHOD( ConnectivityError, + sendFile, + ( const std::string &filePath, size_t size, CollectionSchemeParams collectionSchemeParams ), + ( override ) ); + +private: + // Record the calls so that we can wait for asynchronous calls to happen. + std::vector mSentBufferData; + std::mutex mSentBufferDataMutex; +}; + +} // namespace Testing +} // namespace IoTFleetWise +} // namespace Aws diff --git a/src/testingsupport/include/Testing.h b/test/unit/support/Testing.h similarity index 69% rename from src/testingsupport/include/Testing.h rename to test/unit/support/Testing.h index 88ef1458..bb76c40d 100644 --- a/src/testingsupport/include/Testing.h +++ b/test/unit/support/Testing.h @@ -3,7 +3,7 @@ #pragma once -// Includes +#include "CollectionInspectionAPITypes.h" #include "SignalTypes.h" #include "TimeTypes.h" #include @@ -12,12 +12,6 @@ namespace Aws { namespace IoTFleetWise { -namespace TestingSupport -{ - -using TimePoint = Aws::IoTFleetWise::Platform::Linux::TimePoint; -using Timestamp = Aws::IoTFleetWise::Platform::Linux::Timestamp; -using SignalType = Aws::IoTFleetWise::DataManagement::SignalType; TimePoint operator+( const TimePoint &time, Timestamp increment ) @@ -144,6 +138,51 @@ const auto allSignalTypes = testing::Values( SignalType::UINT8, const auto signedSignalTypes = testing::Values( SignalType::INT8, SignalType::INT16, SignalType::INT32, SignalType::INT64, SignalType::FLOAT, SignalType::DOUBLE ); +void +assertSignalValue( const SignalValueWrapper &signalValueWrapper, + double expectedSignalValue, + SignalType expectedSignalType ) +{ + switch ( expectedSignalType ) + { + case SignalType::UINT8: + ASSERT_EQ( signalValueWrapper.value.uint8Val, static_cast( expectedSignalValue ) ); + break; + case SignalType::INT8: + ASSERT_EQ( signalValueWrapper.value.int8Val, static_cast( expectedSignalValue ) ); + break; + case SignalType::UINT16: + ASSERT_EQ( signalValueWrapper.value.uint16Val, static_cast( expectedSignalValue ) ); + break; + case SignalType::INT16: + ASSERT_EQ( signalValueWrapper.value.int16Val, static_cast( expectedSignalValue ) ); + break; + case SignalType::UINT32: + ASSERT_EQ( signalValueWrapper.value.uint32Val, static_cast( expectedSignalValue ) ); + break; + case SignalType::INT32: + ASSERT_EQ( signalValueWrapper.value.int32Val, static_cast( expectedSignalValue ) ); + break; + case SignalType::UINT64: + ASSERT_EQ( signalValueWrapper.value.uint64Val, static_cast( expectedSignalValue ) ); + break; + case SignalType::INT64: + ASSERT_EQ( signalValueWrapper.value.int64Val, static_cast( expectedSignalValue ) ); + break; + case SignalType::FLOAT: + ASSERT_FLOAT_EQ( signalValueWrapper.value.floatVal, static_cast( expectedSignalValue ) ); + break; + case SignalType::DOUBLE: + ASSERT_DOUBLE_EQ( signalValueWrapper.value.doubleVal, static_cast( expectedSignalValue ) ); + break; + case SignalType::BOOLEAN: + ASSERT_EQ( signalValueWrapper.value.boolVal, static_cast( expectedSignalValue ) ); + break; + default: + FAIL() << "Unsupported signal type"; + } +} + /** * @brief Converts SignalType to a string to be used in parametrized tests * @@ -202,6 +241,5 @@ std::size_t operator""_GiB( unsigned long long sizeBytes ) return static_cast( sizeBytes * 1024 * 1024 * 1024 ); } -} // namespace TestingSupport } // namespace IoTFleetWise } // namespace Aws diff --git a/src/testingsupport/include/WaitUntil.h b/test/unit/support/WaitUntil.h similarity index 99% rename from src/testingsupport/include/WaitUntil.h rename to test/unit/support/WaitUntil.h index 18def6a1..f475853b 100644 --- a/src/testingsupport/include/WaitUntil.h +++ b/test/unit/support/WaitUntil.h @@ -79,8 +79,6 @@ namespace Aws { namespace IoTFleetWise { -namespace TestingSupport -{ const auto WAIT_TIME_OUT = std::chrono::seconds( 5 ); @@ -128,6 +126,5 @@ waitDelay( std::function func ) } } -} // namespace TestingSupport } // namespace IoTFleetWise } // namespace Aws diff --git a/test/unit/support/main.cpp b/test/unit/support/main.cpp new file mode 100644 index 00000000..3e9c7f3d --- /dev/null +++ b/test/unit/support/main.cpp @@ -0,0 +1,21 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +#include "ConsoleLogger.h" +#include "LogLevel.h" +#include + +static void +configureLogging() +{ + Aws::IoTFleetWise::gSystemWideLogLevel = Aws::IoTFleetWise::LogLevel::Trace; + Aws::IoTFleetWise::gLogColorOption = Aws::IoTFleetWise::LogColorOption::Yes; +} + +int +main( int argc, char **argv ) +{ + ::testing::InitGoogleTest( &argc, argv ); + configureLogging(); + return RUN_ALL_TESTS(); +} diff --git a/src/executionmanagement/test/em-example-config-corrupt.json b/test/unit/support/static-config-corrupt.json similarity index 100% rename from src/executionmanagement/test/em-example-config-corrupt.json rename to test/unit/support/static-config-corrupt.json diff --git a/src/executionmanagement/test/em-example-config-inline-creds.json b/test/unit/support/static-config-inline-creds.json similarity index 100% rename from src/executionmanagement/test/em-example-config-inline-creds.json rename to test/unit/support/static-config-inline-creds.json diff --git a/src/executionmanagement/test/em-example-config.json b/test/unit/support/static-config-ok.json similarity index 100% rename from src/executionmanagement/test/em-example-config.json rename to test/unit/support/static-config-ok.json diff --git a/tools/android-app/README.md b/tools/android-app/README.md index 7f1f543c..3aa334fe 100644 --- a/tools/android-app/README.md +++ b/tools/android-app/README.md @@ -21,13 +21,18 @@ available [ELM327 Bluetooth OBD adapter](https://www.amazon.com/s?k=elm327+bluet 1. Open the AWS CloudShell: [Launch CloudShell](https://console.aws.amazon.com/cloudshell/home) +1. Run the following command to clone the FWE repo from GitHub: + + ```bash + git clone https://github.com/aws/aws-iot-fleetwise-edge.git ~/aws-iot-fleetwise-edge + ``` + 1. Run the following script to provision credentials for the app to connect to your AWS account. You will be asked to enter the name of an existing S3 bucket, in which the credentials will be saved. **Note:** It is important that the chosen S3 bucket is not public. ```bash - git clone https://github.com/aws/aws-iot-fleetwise-edge.git ~/aws-iot-fleetwise-edge \ - && cd ~/aws-iot-fleetwise-edge/tools/android-app/cloud \ + cd ~/aws-iot-fleetwise-edge/tools/android-app/cloud \ && pip3 install segno \ && ./provision.sh --s3-qr-code ``` @@ -198,9 +203,9 @@ An x86_64 Ubuntu 20.04 development machine with 200GB free disk space should be ```bash ./tools/build-fwe-cross-android.sh \ && ./tools/build-dist.sh \ - build/x86_64/src/executionmanagement/libaws-iot-fleetwise-edge.so:x86_64 \ - build/arm64-v8a/src/executionmanagement/libaws-iot-fleetwise-edge.so:arm64-v8a \ - build/armeabi-v7a/src/executionmanagement/libaws-iot-fleetwise-edge.so:armeabi-v7a + build/x86_64/libaws-iot-fleetwise-edge.so:x86_64 \ + build/arm64-v8a/libaws-iot-fleetwise-edge.so:arm64-v8a \ + build/armeabi-v7a/libaws-iot-fleetwise-edge.so:armeabi-v7a ``` 1. Build the app: diff --git a/tools/cansim/canigen.py b/tools/cansim/canigen.py index c92c9a7d..604d6408 100644 --- a/tools/cansim/canigen.py +++ b/tools/cansim/canigen.py @@ -157,7 +157,15 @@ def _sig_thread(self, msg_name, cycle_time): self._can_bus.send(frame) send_time += cycle_time / 1000 sleep_time = send_time - time.monotonic() - if sleep_time >= 0: + if cycle_time >= 5 and sleep_time < 2.0 / 1000.0: + # If multiple signal samples with millisecond time precision are + # put into Timestream with exact same timestamp Timstream dedupes them, which + # might break test scenarios as there will be only one row for multiple samples. + # To avoid sending multiple messages of the same id with a cyclic time + # above 5 milliseconds within the same milliseconds slow the catch-up down + # to have at least 2 milliseconds between messages. + time.sleep(2 / 1000) + elif sleep_time >= 0: time.sleep(sleep_time) def _get_supported_pids(self, num_range, ecu): diff --git a/tools/cfn-templates/fwdemo.yml b/tools/cfn-templates/fwdemo.yml index cd2ca1be..1bfd4e57 100644 --- a/tools/cfn-templates/fwdemo.yml +++ b/tools/cfn-templates/fwdemo.yml @@ -174,8 +174,8 @@ Resources: fi sudo -u ubuntu mkdir dist && cd dist sudo -u ubuntu tar -zxf ../aws-iot-fleetwise-edge.tar.gz - sudo -u ubuntu mkdir -p build/src/executionmanagement - sudo -u ubuntu mv aws-iot-fleetwise-edge build/src/executionmanagement + sudo -u ubuntu mkdir -p build + sudo -u ubuntu mv aws-iot-fleetwise-edge build # Install SocketCAN modules: ./tools/install-socketcan.sh --bus-count ${FleetSize} diff --git a/tools/cloud/.gitignore b/tools/cloud/.gitignore index e8c33ccc..6304450e 100644 --- a/tools/cloud/.gitignore +++ b/tools/cloud/.gitignore @@ -1,5 +1,3 @@ -*-timestream-result.json -*.html -part-* s3-bucket-policy.json demo.env +collected-data-* diff --git a/tools/cloud/clean-up.sh b/tools/cloud/clean-up.sh index 751174d8..7f47f055 100755 --- a/tools/cloud/clean-up.sh +++ b/tools/cloud/clean-up.sh @@ -9,12 +9,17 @@ ENDPOINT_URL_OPTION="" REGION="us-east-1" VEHICLE_NAME="" DISAMBIGUATOR="" +SIGNAL_CATALOG="" ACCOUNT_ID=`aws sts get-caller-identity --query "Account" --output text` SERVICE_ROLE="IoTFleetWiseServiceRole" SERVICE_ROLE_POLICY_ARN="arn:aws:iam::${ACCOUNT_ID}:policy/" FLEET_SIZE=1 BATCH_SIZE=$((`nproc`*4)) +if [ -f demo.env ]; then + source demo.env +fi + parse_args() { while [ "$#" -gt 0 ]; do case $1 in @@ -30,6 +35,10 @@ parse_args() { DISAMBIGUATOR=$2 shift ;; + --signal-catalog) + SIGNAL_CATALOG=$2 + shift + ;; --endpoint-url) ENDPOINT_URL=$2 shift @@ -45,6 +54,7 @@ parse_args() { echo " the instance number will be appended to each" echo " Vehicle name after a '-', e.g. fwdemo-42" echo " --disambiguator The unique string used by the demo.sh script to avoid resource name conflicts" + echo " --signal-catalog Optional: name of signal catalog to delete" echo " --endpoint-url The endpoint URL used for AWS CLI calls" echo " --region The region used for AWS CLI calls, default: ${REGION}" exit 0 @@ -161,8 +171,9 @@ aws iam detach-role-policy --role-name ${SERVICE_ROLE} --policy-arn ${SERVICE_RO aws iam delete-policy --policy-arn ${SERVICE_ROLE_POLICY_ARN} --region ${REGION} || true aws iam delete-role --role-name ${SERVICE_ROLE} --region ${REGION} || true -# Note: As the service currently only supports one signal catalog, do not delete it -# echo "Deleting signal catalog..." -# aws iotfleetwise delete-signal-catalog \ -# ${ENDPOINT_URL_OPTION} --region ${REGION} \ -# --name ${NAME}-signal-catalog 2> /dev/null || true +if [ "${SIGNAL_CATALOG}" != "" ]; then + echo "Deleting signal catalog..." + aws iotfleetwise delete-signal-catalog \ + ${ENDPOINT_URL_OPTION} --region ${REGION} \ + --name ${SIGNAL_CATALOG} 2> /dev/null || true +fi diff --git a/tools/cloud/demo.sh b/tools/cloud/demo.sh index 7147c3aa..74a71cf2 100755 --- a/tools/cloud/demo.sh +++ b/tools/cloud/demo.sh @@ -66,6 +66,9 @@ parse_args() { BUCKET_NAME=$2 shift ;; + --set-bucket-policy) + SKIP_S3_POLICY=false + ;; --service-principal) SERVICE_PRINCIPAL=$2 shift @@ -87,6 +90,7 @@ parse_args() { echo " --campaign-file Campaign JSON file, default: ${DEFAULT_CAMPAIGN_FILE}" echo " --dbc-file DBC file, default: ${DEFAULT_DBC_FILE}" echo " --bucket-name S3 bucket name, if not specified a new bucket will be created" + echo " --set-bucket-policy Sets the required bucket policy" echo " --clean-up Delete created resources" echo " --enable-s3-upload Create campaigns to upload data to S3" echo " --endpoint-url The endpoint URL used for AWS CLI calls" @@ -168,6 +172,12 @@ fi save_variables() { # Export some variables to a .env file so that they can be referenced by other scripts echo " +VEHICLE_NAME=${VEHICLE_NAME} +FLEET_SIZE=${FLEET_SIZE} +DISAMBIGUATOR=${DISAMBIGUATOR} +ENDPOINT_URL=${ENDPOINT_URL} +REGION=${REGION} +SIGNAL_CATALOG=${CREATED_SIGNAL_CATALOG_NAME} TIMESTREAM_DB_NAME=${TIMESTREAM_DB_NAME} TIMESTREAM_TABLE_NAME=${TIMESTREAM_TABLE_NAME} BUCKET_NAME=${BUCKET_NAME} @@ -177,16 +187,7 @@ BUCKET_NAME=${BUCKET_NAME} cleanup() { save_variables if [ ${CLEAN_UP} == true ]; then - ./clean-up.sh \ - --vehicle-name ${VEHICLE_NAME} \ - --fleet-size ${FLEET_SIZE} \ - --disambiguator ${DISAMBIGUATOR} \ - ${ENDPOINT_URL_OPTION} \ - --region ${REGION} - if [ ! -z "${CREATED_SIGNAL_CATALOG_NAME}" ]; then - echo "Deleting signal catalog: ${CREATED_SIGNAL_CATALOG_NAME}" - aws iotfleetwise delete-signal-catalog --name ${CREATED_SIGNAL_CATALOG_NAME} ${ENDPOINT_URL_OPTION} --region=${REGION} - fi + ./clean-up.sh fi } @@ -348,14 +349,14 @@ aws iam attach-role-policy \ for ((i=0; i<${FLEET_SIZE}; i+=${BATCH_SIZE})); do for ((j=0; j<${BATCH_SIZE} && i+j<${FLEET_SIZE}; j++)); do - vehicle=${VEHICLES[$((i+j))]} - echo "Deleting vehicle ${vehicle} if it already exists..." + VEHICLE=${VEHICLES[$((i+j))]} + echo "Deleting vehicle ${VEHICLE} if it already exists..." # This output group is run in a background process. Note that stderr is redirected to stream 3 and back, # to print stderr from the output group, but not info about the background process. { \ aws iotfleetwise delete-vehicle \ ${ENDPOINT_URL_OPTION} --region ${REGION} \ - --vehicle-name "${vehicle}" \ + --vehicle-name "${VEHICLE}" | jq -r .arn \ 2>&3 &} 3>&2 2>/dev/null done # Wait for all background processes to finish @@ -401,6 +402,22 @@ EOF else echo "Skipping S3 bucket policy. Since bucket already existed it needs to be manually configured." fi + echo "Getting S3 bucket region..." + BUCKET_REGION=`aws s3api get-bucket-location --bucket ${BUCKET_NAME} | jq -r .LocationConstraint` + if [ -z "${BUCKET_REGION}" ] || [ "${BUCKET_REGION}" == "null" ]; then + BUCKET_REGION="us-east-1" + fi + echo ${BUCKET_REGION} + if [ "${BUCKET_REGION}" != "${REGION}" ]; then + echo "Error: S3 bucket ${BUCKET_NAME} is not in region ${REGION}. Cross-region not yet supported." + exit -1 + fi + echo "Checking bucket ACLs are disabled..." + if ! OWNERSHIP_CONTROLS=`aws s3api get-bucket-ownership-controls --bucket ${BUCKET_NAME} 2> /dev/null` \ + || [ "`echo ${OWNERSHIP_CONTROLS} | jq -r '.OwnershipControls.Rules[0].ObjectOwnership'`" != "BucketOwnerEnforced" ]; then + echo "Error: ACLs are enabled for bucket ${BUCKET_NAME}. Disable them at https://s3.console.aws.amazon.com/s3/bucket/${BUCKET_NAME}/property/oo/edit" + exit -1 + fi fi VEHICLE_NODE=`cat vehicle-node.json` @@ -501,7 +518,7 @@ else ${ENDPOINT_URL_OPTION} --region ${REGION} \ --name ${SIGNAL_CATALOG_NAME} \ --description "DBC Attributes" \ - --nodes-to-add '[{ + --nodes-to-update '[{ "attribute": { "dataType": "STRING", "description": "Color", @@ -580,10 +597,22 @@ aws iotfleetwise update-decoder-manifest \ --name ${NAME}-decoder-manifest \ --status ACTIVE | jq -r .arn +echo "Waiting for decoder manifest to become active..." +while true; do + sleep 5 + DECODER_MANIFEST_STATUS=`aws iotfleetwise get-decoder-manifest \ + ${ENDPOINT_URL_OPTION} --region ${REGION} \ + --name ${NAME}-decoder-manifest` + echo ${DECODER_MANIFEST_STATUS} | jq -r .arn + if [ `echo ${DECODER_MANIFEST_STATUS} | jq -r .status` == "ACTIVE" ]; then + break + fi +done + for ((i=0; i<${FLEET_SIZE}; i+=${BATCH_SIZE})); do for ((j=0; j<${BATCH_SIZE} && i+j<${FLEET_SIZE}; j++)); do - echo "Creating vehicle ${vehicle}..." - vehicle=${VEHICLES[$((i+j))]} + VEHICLE=${VEHICLES[$((i+j))]} + echo "Creating vehicle ${VEHICLE}..." # This output group is run in a background process. Note that stderr is redirected to stream 3 and back, # to print stderr from the output group, but not info about the background process. { \ @@ -593,7 +622,7 @@ for ((i=0; i<${FLEET_SIZE}; i+=${BATCH_SIZE})); do --association-behavior ValidateIotThingExists \ --model-manifest-arn ${MODEL_MANIFEST_ARN} \ --attributes '{"Vehicle.Color":"Red"}' \ - --vehicle-name "${vehicle}" >/dev/null \ + --vehicle-name "${VEHICLE}" >/dev/null \ 2>&3 &} 3>&2 2>/dev/null done # Wait for all background processes to finish @@ -610,15 +639,15 @@ echo ${FLEET_ARN} for ((i=0; i<${FLEET_SIZE}; i+=${BATCH_SIZE})); do for ((j=0; j<${BATCH_SIZE} && i+j<${FLEET_SIZE}; j++)); do - vehicle=${VEHICLES[$((i+j))]} - echo "Associating vehicle ${vehicle}..." + VEHICLE=${VEHICLES[$((i+j))]} + echo "Associating vehicle ${VEHICLE}..." # This output group is run in a background process. Note that stderr is redirected to stream 3 and back, # to print stderr from the output group, but not info about the background process. { \ aws iotfleetwise associate-vehicle-fleet \ ${ENDPOINT_URL_OPTION} --region ${REGION} \ --fleet-id ${NAME}-fleet \ - --vehicle-name "${vehicle}" \ + --vehicle-name "${VEHICLE}" \ 2>&3 &} 3>&2 2>/dev/null done # Wait for all background processes to finish @@ -705,12 +734,12 @@ check_vehicle_healthy() { for ((i=0; i<${FLEET_SIZE}; i+=${BATCH_SIZE})); do for ((j=0; j<${BATCH_SIZE} && i+j<${FLEET_SIZE}; j++)); do - vehicle=${VEHICLES[$((i+j))]} - echo "Waiting until status of vehicle ${vehicle} is healthy..." + VEHICLE=${VEHICLES[$((i+j))]} + echo "Waiting until status of vehicle ${VEHICLE} is healthy..." # This output group is run in a background process. Note that stderr is redirected to stream 3 and back, # to print stderr from the output group, but not info about the background process. { \ - check_vehicle_healthy "${vehicle}" \ + check_vehicle_healthy "${VEHICLE}" \ 2>&3 &} 3>&2 2>/dev/null done # Wait for all background processes to finish @@ -724,48 +753,84 @@ sleep ${DELAY} echo "The DB Name is ${TIMESTREAM_DB_NAME}" echo "The DB Table is ${TIMESTREAM_TABLE_NAME}" -for vehicle in ${VEHICLES[@]}; do - echo "Querying Timestream for vehicle ${vehicle}..." +COLLECTED_DATA_DIR="collected-data-${DISAMBIGUATOR}/" +mkdir -p ${COLLECTED_DATA_DIR} + +for VEHICLE in ${VEHICLES[@]}; do + echo "Querying Timestream for vehicle ${VEHICLE}..." aws timestream-query query \ --region ${REGION} \ --query-string "SELECT * FROM \"${TIMESTREAM_DB_NAME}\".\"${TIMESTREAM_TABLE_NAME}\" \ - WHERE vehicleName = '${vehicle}' \ + WHERE vehicleName = '${VEHICLE}' \ AND time between ago(1m) and now() ORDER BY time ASC" \ - > ${vehicle}-timestream-result.json + > ${COLLECTED_DATA_DIR}${VEHICLE}-timestream-result.json done -if [ "${DBC_FILE}" == "" ]; then +if [ "${DBC_FILE}" != "" ]; then + echo "----------------------------------------------------------------------------------------" + echo "| Note: A custom DBC file was used. If an error occurs below due to no collected data, |" + echo "| you need to modify cansim.py or run FWE with a real vehicle. |" + echo "----------------------------------------------------------------------------------------" +fi + +OUTPUT_FILES=() +for VEHICLE in ${VEHICLES[@]}; do + echo "Converting to HTML..." + OUTPUT_FILE_HTML="${COLLECTED_DATA_DIR}${VEHICLE}.html" + OUTPUT_FILES+=(${OUTPUT_FILE_HTML}) + python3 timestream-to-html.py \ + ${COLLECTED_DATA_DIR}${VEHICLE}-timestream-result.json \ + ${OUTPUT_FILE_HTML} +done + +echo "You can now view the collected data." +echo "----------------------------------" +echo "| Collected data in HTML format: |" +echo "----------------------------------" +for FILE in ${OUTPUT_FILES[@]}; do + echo `realpath ${FILE}` +done + +if [ ${S3_UPLOAD} == true ]; then + DELAY=1200 + echo "Waiting 20 minutes for data to be collected and uploaded to S3..." + sleep ${DELAY} + + echo "Downloading files from S3..." + S3_URL="s3://${BUCKET_NAME}/${NAME}-campaign-s3-${S3_SUFFIX}/processed-data/" + if ! COLLECTED_FILES=`aws s3 ls --recursive ${S3_URL}`; then + echo "Error: no collected data was found at ${S3_URL}" + exit -1 + fi + echo "${COLLECTED_FILES}" | while read LINE; do + KEY=`echo ${LINE} | cut -d ' ' -f4` + aws s3 cp s3://${BUCKET_NAME}/${KEY} ${COLLECTED_DATA_DIR} + done + OUTPUT_FILES=() - for vehicle in ${VEHICLES[@]}; do - echo "Converting to HTML..." - OUTPUT_FILE_HTML="${vehicle}.html" + for VEHICLE in ${VEHICLES[@]}; do + echo "Converting from JSON to HTML..." + OUTPUT_FILE_HTML="${COLLECTED_DATA_DIR}${VEHICLE}-json.html" + OUTPUT_FILES+=(${OUTPUT_FILE_HTML}) + python3 firehose-to-html.py \ + --vehicle-name ${VEHICLE} \ + --files ${COLLECTED_DATA_DIR}part-*.json \ + --html-filename ${OUTPUT_FILE_HTML} + + echo "Converting from Parquet to HTML..." + OUTPUT_FILE_HTML="${COLLECTED_DATA_DIR}${VEHICLE}-parquet.html" OUTPUT_FILES+=(${OUTPUT_FILE_HTML}) - python3 timestream-to-html.py ${vehicle}-timestream-result.json ${OUTPUT_FILE_HTML} + python3 firehose-to-html.py \ + --vehicle-name ${VEHICLE} \ + --files ${COLLECTED_DATA_DIR}part-*.parquet \ + --html-filename ${OUTPUT_FILE_HTML} done echo "You can now view the collected data." echo "----------------------------------" echo "| Collected data in HTML format: |" echo "----------------------------------" - for file in ${OUTPUT_FILES[@]}; do - echo $(pwd)/${file} + for FILE in ${OUTPUT_FILES[@]}; do + echo `realpath ${FILE}` done fi - -if [ ${S3_UPLOAD} == true ]; then - DELAY=1200 - echo "Waiting 20 minutes for data to be collected and uploaded to S3..." - sleep ${DELAY} - - if [ "${DBC_FILE}" == "" ]; then - echo "Converting data from S3 to HTML..." - OUTPUT_FILE_HTML="${NAME}.html" - python3 s3-to-html.py --bucket ${BUCKET_NAME} --prefix ${NAME}-campaign-s3-${S3_SUFFIX} --json-output-filename ${NAME}-s3-json-result.html --parquet-output-filename ${NAME}-s3-parquet-result.html - - echo "You can now view the collected data." - echo "-------------------------------------" - echo "| Collected S3 data in HTML format: |" - echo "-------------------------------------" - echo `pwd`/${NAME}-s3-json-result.html "and" `pwd`/${NAME}-s3-parquet-result.html - fi -fi diff --git a/tools/cloud/firehose-to-html.py b/tools/cloud/firehose-to-html.py new file mode 100755 index 00000000..d57e8b18 --- /dev/null +++ b/tools/cloud/firehose-to-html.py @@ -0,0 +1,74 @@ +#!/usr/bin/python3 +# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 + +import argparse +import json + +import pandas as pd +import plotly.graph_objects as go + + +def process_row(vehicle_name, row, data): + expanded_data = {"time": row["time"]} + if "measure_name" not in row or "time" not in row or "vehicleName" not in row: + raise Exception("Unsupported format") + if row["vehicleName"] != vehicle_name: + return + if "measure_value_DOUBLE" in row: + expanded_data[row["measure_name"]] = row["measure_value_DOUBLE"] + else: + raise Exception("Unsupported format") + data.append(expanded_data) + + +if __name__ == "__main__": + parser = argparse.ArgumentParser(description="Creates plots for collected data from Firehose") + parser.add_argument( + "--vehicle-name", + required=True, + help="Vehicle name", + ) + parser.add_argument( + "--files", + type=argparse.FileType("r"), + nargs="+", + required=True, + help="List files to process", + ) + parser.add_argument( + "--html-filename", + metavar="FILE", + required=True, + help="HTML output filename", + ) + + args = parser.parse_args() + + data = [] + for file in args.files: + try: + if file.name.endswith(".json"): + with open(file.name) as fp: + for line in fp: + row = json.loads(line) + process_row(args.vehicle_name, row, data) + elif file.name.endswith(".parquet"): + df = pd.read_parquet(file.name) + for _, row in df.iterrows(): + process_row(args.vehicle_name, row, data) + else: + raise Exception("Unsupported format") + except Exception as e: + raise Exception(e.message + f" in {file.name}") + + if len(data) == 0: + raise Exception("No data found") + df = pd.DataFrame(data) + df["time"] = pd.to_datetime(df["time"], unit="ms") + fig = go.Figure() + for column in df: + if column != "time": + fig.add_trace(go.Scatter(x=df["time"], y=df[column], mode="markers", name=column)) + with open(args.html_filename, "w") as fp: + fp.write(fig.to_html()) diff --git a/tools/cloud/install-deps.sh b/tools/cloud/install-deps.sh index 77eb2dac..45255c6d 100755 --- a/tools/cloud/install-deps.sh +++ b/tools/cloud/install-deps.sh @@ -4,14 +4,16 @@ set -eo pipefail -# Install Python 3 and pip -apt update && apt install -y python3 python3-pip +# On Ubuntu install Python 3 and pip +if command -v apt &> /dev/null; then + apt update + apt install -y python3 python3-pip +fi # Install pip packages pip3 install \ wrapt==1.10.0 \ plotly==5.3.1 \ - pandas==1.5.0 \ + pandas==1.3.5 \ cantools==36.4.0 \ - boto3==1.18.60 \ - fastparquet==2023.4.0 + fastparquet==0.8.1 diff --git a/tools/cloud/s3-to-html.py b/tools/cloud/s3-to-html.py deleted file mode 100755 index 1db67895..00000000 --- a/tools/cloud/s3-to-html.py +++ /dev/null @@ -1,79 +0,0 @@ -#!/usr/bin/python3 -# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. -# SPDX-License-Identifier: Apache-2.0 - -import argparse -import json -import os - -import boto3 -import pandas as pd -import plotly.graph_objects as go - - -def plot_df(df, filename=None): - fig = go.Figure() - for measurement, group in df.groupby("measure_name"): - fig.add_trace( - go.Scatter( - x=group["time"], y=group["measure_value_DOUBLE"], name=measurement, mode="markers" - ) - ) - if filename is None: - fig.show() - else: - with open(filename, "w") as fp: - fp.write(fig.to_html()) - - -if __name__ == "__main__": - parser = argparse.ArgumentParser(description="Creates plots for collected data from S3") - parser.add_argument( - "--bucket", - required=True, - help="S3 bucket name where the data was uploaded", - ) - parser.add_argument( - "--prefix", - required=True, - help="S3 object prefix where the data was uploaded", - ) - parser.add_argument( - "--json-output-filename", - metavar="FILE", - help="Filename to plot results collected in the JSON format", - ) - parser.add_argument( - "--parquet-output-filename", - metavar="FILE", - help="Filename to plot results collected in the parquet format", - ) - - args = parser.parse_args() - - json_dfs = [] - parquet_df = pd.DataFrame() - - s3_client = boto3.client("s3") - files = s3_client.list_objects(Bucket=args.bucket, Prefix=args.prefix + "/processed-data/") - if "Contents" in files: - for file in files["Contents"]: - results_file = "./" + os.path.basename(file["Key"]) - s3_client.download_file(args.bucket, file["Key"], results_file) - - if results_file.endswith(".json"): - with open(results_file) as f: - lines = f.readlines() - for line in lines: - data = json.loads(line) - json_dfs.append(pd.DataFrame([data])) - else: - new_parquet = pd.read_parquet(results_file) - parquet_df = pd.concat([parquet_df, pd.read_parquet(results_file)]) - - json_df = pd.concat(json_dfs, ignore_index=True, sort=False) - json_df["time"] = pd.to_datetime(json_df["time"], unit="ms") - parquet_df["time"] = pd.to_datetime(parquet_df["time"], unit="ms") - - plot_df(json_df, args.json_output_filename) - plot_df(parquet_df, args.parquet_output_filename) diff --git a/tools/code_check/compile_db_remove_test.py b/tools/code_check/compile_db_remove_test.py index 0543e9b4..502763c3 100755 --- a/tools/code_check/compile_db_remove_test.py +++ b/tools/code_check/compile_db_remove_test.py @@ -3,7 +3,6 @@ # SPDX-License-Identifier: Apache-2.0 import json -import re import sys # argv[1] should hold the build dir path @@ -13,20 +12,16 @@ with open(cmake_build_dir + "/compile_commands.json") as f: compile_commands = json.load(f) -f.close() output_compile_commands = [] for block in compile_commands: if "command" in block: - if re.search(r".+iotcpp\/test\/include.+", block["command"]): - continue # If we keep -Werror, we will get compiler errors from clang that don't happen with GCC. # Since clang is currently not one of our supported compilers, we will ignore the warnings. block["command"] = block["command"].replace("-Werror", "") output_compile_commands.append(block) # re-write the db file for clang-tidy -f = open(cmake_build_dir + "/Testing/Temporary/compile_commands.json", "w") -f.writelines(json.dumps(output_compile_commands, indent=2)) -f.close() +with open(cmake_build_dir + "/Testing/Temporary/compile_commands.json", "w") as f: + f.writelines(json.dumps(output_compile_commands, indent=2)) diff --git a/tools/container/Dockerfile b/tools/container/Dockerfile index fe8404a5..6bc4b381 100644 --- a/tools/container/Dockerfile +++ b/tools/container/Dockerfile @@ -13,11 +13,11 @@ RUN apt-get update \ jq \ && rm -rf /var/lib/apt/lists/* -COPY ${TARGETPLATFORM}/src/executionmanagement/aws-iot-fleetwise-edge /usr/bin/ -COPY tools/container/start-fwe.sh /usr/bin -COPY tools/configure-fwe.sh /usr/bin/ -COPY LICENSE /usr/share/doc/aws-iot-fleetwise-edge/ -COPY THIRD-PARTY-LICENSES /usr/share/doc/aws-iot-fleetwise-edge/ -COPY configuration/static-config.json /usr/share/aws-iot-fleetwise/ +COPY ${TARGETPLATFORM}/aws-iot-fleetwise-edge /usr/bin/ +COPY tools/container/start-fwe.sh /usr/bin +COPY tools/configure-fwe.sh /usr/bin/ +COPY LICENSE /usr/share/doc/aws-iot-fleetwise-edge/ +COPY THIRD-PARTY-LICENSES /usr/share/doc/aws-iot-fleetwise-edge/ +COPY configuration/static-config.json /usr/share/aws-iot-fleetwise/ ENTRYPOINT ["/usr/bin/start-fwe.sh"] diff --git a/tools/greengrassV2/README.md b/tools/greengrassV2/README.md index 8707908a..45aaf3b6 100644 --- a/tools/greengrassV2/README.md +++ b/tools/greengrassV2/README.md @@ -1,22 +1,24 @@ -# FWE with AWS IoT Greengrass v2 IPC - -This project is an integration of the Reference Implementation for AWS IoT FleetWise ("FWE") with -the AWS IoT Greengrass v2 IPC client. It enables FWE to be deployed as a Greengrass v2 Component and -allows it to connect to AWS IoT Core via the Greengrass IPC mechanism. Authentication with IoT Core -is handled by Greengrass, simplifying the configuration of IoT FleetWise. - -## Compile the FWE with Greengrass feature - -enable the compile flag: -DFWE_FEATURE_GREENGRASSV2=On - -``` -mkdir build && cd build && cmake \ - -DCMAKE_BUILD_TYPE=Release \ - -DFWE_STATIC_LINK=On \ - -DBUILD_TESTING=Off \ - -DFWE_FEATURE_GREENGRASSV2=On \ - .. \ - && make install -j`nproc` && cd .. +# FWE with AWS IoT Greengrass V2 IPC + +The Reference Implementation for AWS IoT FleetWise ("FWE") provides an integration with the AWS IoT +Greengrass V2 IPC client. It enables FWE to be deployed as a Greengrass v2 Component and allows it +to connect to AWS IoT Core via the Greengrass IPC mechanism. Authentication with IoT Core is handled +by Greengrass, simplifying the configuration of IoT FleetWise. + +## Compile the FWE with Greengrass V2 feature + +Enable the compile flag `-DFWE_FEATURE_GREENGRASSV2=On`: + +```bash +mkdir build && cd build \ +&& cmake \ + -DCMAKE_BUILD_TYPE=Release \ + -DFWE_STATIC_LINK=On \ + -DBUILD_TESTING=Off \ + -DFWE_FEATURE_GREENGRASSV2=On \ + .. \ +&& make install -j`nproc` \ +&& cd .. ``` ## Install IoT Greengrass core in local machine @@ -24,12 +26,12 @@ mkdir build && cd build && cmake \ Install IoT Greengrass v2 core on the development machine, by following these instructions: https://docs.aws.amazon.com/greengrass/v2/developerguide/getting-started.html#install-greengrass-v2 -## Configure the FWE as the deployment of GG +## Configure the FWE as the deployment of Greengrass V2 -Run the following command to create the configuration file for IoT FleetWise. Replace -with the thing name that you used above to register the IoT Greengrass device: +Run the following command to create the configuration file for IoT FleetWise. Replace +`` with the thing name that you used above to register the IoT Greengrass device: -``` +```bash mkdir -p tools/greengrassV2/artifacts/com.amazon.aws.IoTFleetWise/1.0.0/ ./tools/configure-fwe.sh \ --input-config-file ./configuration/static-config.json \ @@ -48,14 +50,14 @@ Deploy FWE via Greengrass deployment console. By creating a component using the Create the persistency path for FWE: -``` -mkdir -p /var/aws-iot-fleetwise +```bash +sudo mkdir -p /var/aws-iot-fleetwise ``` Make a local deployment of IoT FleetWise as a Greengrass Component by running the following: -``` -cp build/lib/aws-iot-fleetwise-edge/src/executionmanagement/aws-iot-fleetwise-edge \ +```bash +cp build/aws-iot-fleetwise-edge \ tools/greengrassV2/artifacts/com.amazon.aws.IoTFleetWise/1.0.0/ sudo /greengrass/v2/bin/greengrass-cli deployment create \ --recipeDir tools/greengrassV2/recipes \ @@ -65,7 +67,7 @@ sudo /greengrass/v2/bin/greengrass-cli deployment create \ View the logs of running component as follows: -``` +```bash sudo tail -f /greengrass/v2/logs/com.amazon.aws.IoTFleetWise.log ``` diff --git a/tools/install-deps-cross-android.sh b/tools/install-deps-cross-android.sh index 4a3be38a..f77f1421 100755 --- a/tools/install-deps-cross-android.sh +++ b/tools/install-deps-cross-android.sh @@ -90,8 +90,8 @@ install_deps() { --layout=system \ --arch=${TARGET_ARCH} \ --target-version=${VERSION_ANDROID_API} > /dev/null - mv build/out/${TARGET_ARCH}/lib ${INSTALL_PREFIX} - mv build/out/${TARGET_ARCH}/include ${INSTALL_PREFIX} + cp -r build/out/${TARGET_ARCH}/lib ${INSTALL_PREFIX} + cp -r build/out/${TARGET_ARCH}/include ${INSTALL_PREFIX} cd .. # Snappy @@ -110,7 +110,7 @@ install_deps() { -DANDROID_TOOLCHAIN=clang \ -DCMAKE_INSTALL_PREFIX=${INSTALL_PREFIX} \ .. - make install -j`nproc` + make install -j`nproc` > /dev/null cd ../.. # Protobuf @@ -119,27 +119,31 @@ install_deps() { cd protobuf-${VERSION_PROTOBUF} if [ ! -f ${NATIVE_PREFIX}/bin/protoc ]; then mkdir build_native && cd build_native - ../configure --prefix=${NATIVE_PREFIX} + cmake \ + -DCMAKE_BUILD_TYPE=Release \ + -DBUILD_SHARED_LIBS=OFF \ + -DCMAKE_POSITION_INDEPENDENT_CODE=On \ + -Dprotobuf_BUILD_TESTS=Off \ + -DCMAKE_INSTALL_PREFIX=${NATIVE_PREFIX} \ + .. make install -j`nproc` cd .. fi mkdir build_target && cd build_target - NDK=${SDK_PREFIX}/ndk/${VERSION_ANDROID_NDK} \ - TOOLCHAIN=${NDK}/toolchains/llvm/prebuilt/linux-x86_64 \ - TARGET=${HOST_PLATFORM} \ - API=${VERSION_ANDROID_API} \ - AR=${TOOLCHAIN}/bin/llvm-ar \ - CC=${TOOLCHAIN}/bin/${TARGET}${API}-clang \ - AS=${CC} \ - CXX=${TOOLCHAIN}/bin/${TARGET}${API}-clang++ \ - LD=${TOOLCHAIN}/bin/ld \ - RANLIB=${TOOLCHAIN}/bin/llvm-ranlib \ - STRIP=${TOOLCHAIN}/bin/llvm-strip \ - ../configure \ - --host=${HOST_PLATFORM} \ - --prefix=${INSTALL_PREFIX} \ - "CFLAGS=-fPIC" "CXXFLAGS=-fPIC" - make install -j`nproc` + cmake \ + -DCMAKE_BUILD_TYPE=Release \ + -DBUILD_SHARED_LIBS=OFF \ + -DCMAKE_POSITION_INDEPENDENT_CODE=On \ + -Dprotobuf_BUILD_TESTS=Off \ + -Dprotobuf_BUILD_PROTOC_BINARIES=Off \ + -DANDROID_ABI=${TARGET_ARCH} \ + -DANDROID_PLATFORM=android-${VERSION_ANDROID_API} \ + -DCMAKE_ANDROID_NDK=${SDK_PREFIX}/ndk/${VERSION_ANDROID_NDK} \ + -DCMAKE_TOOLCHAIN_FILE=${SDK_PREFIX}/ndk/${VERSION_ANDROID_NDK}/build/cmake/android.toolchain.cmake \ + -DANDROID_TOOLCHAIN=clang \ + -DCMAKE_INSTALL_PREFIX=${INSTALL_PREFIX} \ + .. + make install -j`nproc` > /dev/null cd ../.. # JsonCpp @@ -158,7 +162,7 @@ install_deps() { -DANDROID_TOOLCHAIN=clang \ -DCMAKE_INSTALL_PREFIX=${INSTALL_PREFIX} \ .. - make install -j`nproc` + make install -j`nproc` > /dev/null cd ../.. # OpenSSL @@ -169,7 +173,7 @@ install_deps() { PATH=${ANDROID_NDK_HOME}/toolchains/llvm/prebuilt/linux-x86_64/bin:${PATH} \ INSTALL_PREFIX=${INSTALL_PREFIX} SSL_TARGET=${SSL_TARGET} VERSION_ANDROID_API=${VERSION_ANDROID_API} \ bash -c './Configure ${SSL_TARGET} -D__ANDROID_API__=${VERSION_ANDROID_API} --prefix=${INSTALL_PREFIX} no-shared \ - && make -j`nproc`' + && make -j`nproc`' > /dev/null make install > /dev/null cd .. @@ -200,7 +204,7 @@ install_deps() { --disable-rtsp \ --host=${HOST_PLATFORM} \ --prefix=${INSTALL_PREFIX} - make install -j`nproc` V=1 LDFLAGS="-static -L${INSTALL_PREFIX}/lib" + make install -j`nproc` V=1 LDFLAGS="-static -L${INSTALL_PREFIX}/lib" > /dev/null cd .. # AWS C++ SDK @@ -222,7 +226,7 @@ install_deps() { -DCMAKE_FIND_ROOT_PATH=${INSTALL_PREFIX} \ -DCMAKE_INSTALL_PREFIX=${INSTALL_PREFIX} \ .. - make install -j`nproc` + make install -j`nproc` > /dev/null cd ../.. # pthread is directly linked somewhere, so just create a dummy .a file ar -rc ${INSTALL_PREFIX}/lib/libpthread.a @@ -231,20 +235,24 @@ install_deps() { rm -rf deps-cross-android } -ARCH_NOT_INSTALLED="false" for ARCH in ${ARCHS}; do + TARGET_ARCH=`echo $ARCH | cut -d ':' -f1` HOST_PLATFORM=`echo $ARCH | cut -d ':' -f2` - if [ ! -d /usr/local/${HOST_PLATFORM} ]; then - ARCH_NOT_INSTALLED="true" - break + SSL_TARGET=`echo $ARCH | cut -d ':' -f3` + BUILD="false" + if ! ${USE_CACHE}; then + echo "--native-prefix defined, building..." + BUILD="true" + elif [ ! -d ${NATIVE_PREFIX} ]; then + echo "${NATIVE_PREFIX} does not exist, building..." + BUILD="true" + elif [ ! -d /usr/local/${HOST_PLATFORM} ]; then + echo "/usr/local/${HOST_PLATFORM} does not exist, building..." + BUILD="true" + else + echo "/usr/local/${HOST_PLATFORM} exists, not building." fi -done - -if ! ${USE_CACHE} || ${ARCH_NOT_INSTALLED} || [ ! -d ${NATIVE_PREFIX} ]; then - for ARCH in ${ARCHS}; do - TARGET_ARCH=`echo $ARCH | cut -d ':' -f1` - HOST_PLATFORM=`echo $ARCH | cut -d ':' -f2` - SSL_TARGET=`echo $ARCH | cut -d ':' -f3` + if ${BUILD}; then install_deps ${TARGET_ARCH} ${HOST_PLATFORM} ${SSL_TARGET} - done -fi + fi +done diff --git a/tools/install-deps-cross-arm64.sh b/tools/install-deps-cross-arm64.sh index 24e58f71..23b99d97 100755 --- a/tools/install-deps-cross-arm64.sh +++ b/tools/install-deps-cross-arm64.sh @@ -9,6 +9,7 @@ source ${SCRIPT_DIR}/install-deps-versions.sh USE_CACHE="true" WITH_GREENGRASSV2_SUPPORT="false" +SHARED_LIBS="OFF" parse_args() { while [ "$#" -gt 0 ]; do @@ -21,10 +22,14 @@ parse_args() { USE_CACHE="false" shift ;; + --shared-libs) + SHARED_LIBS="ON" + ;; --help) echo "Usage: $0 [OPTION]" echo " --with-greengrassv2-support Install dependencies for Greengrass V2" echo " --native-prefix Native install prefix" + echo " --shared-libs Build shared libs, rather than static libs" exit 0 ;; esac @@ -40,10 +45,29 @@ if [ "${ARCH}" == "arm64" ]; then exit -1 fi -sed -i "s/deb http/deb [arch=${ARCH}] http/g" /etc/apt/sources.list +print_file() { + echo ">>> $1: $2" + cat $2 + echo ">>>" +} + +print_file "Before patching" /etc/apt/sources.list +sed -i -E "s/deb (http|mirror\+file)/deb [arch=${ARCH}] \1/g" /etc/apt/sources.list cp /etc/apt/sources.list /etc/apt/sources.list.d/arm64.list -sed -i "s/deb \[arch=${ARCH}\] http/deb [arch=arm64] http/g" /etc/apt/sources.list.d/arm64.list -sed -i -E "s#(archive|security).ubuntu.com/ubuntu#ports.ubuntu.com/ubuntu-ports#g" /etc/apt/sources.list.d/arm64.list +sed -i -E "s/deb \[arch=${ARCH}\] (http|mirror\+file)/deb [arch=arm64] \1/g" /etc/apt/sources.list.d/arm64.list +# GitHub uses a separate mirrors file +if [ -f /etc/apt/apt-mirrors.txt ]; then + print_file "Before patching" /etc/apt/apt-mirrors.txt + cp /etc/apt/apt-mirrors.txt /etc/apt/apt-mirrors-arm64.txt + sed -i "s#/etc/apt/apt-mirrors.txt#/etc/apt/apt-mirrors-arm64.txt#g" /etc/apt/sources.list.d/arm64.list + PATCH_FILE="/etc/apt/apt-mirrors-arm64.txt" + print_file "After patching" /etc/apt/apt-mirrors-arm64.txt +else + PATCH_FILE="/etc/apt/sources.list.d/arm64.list" +fi +sed -i -E "s#(archive|security).ubuntu.com/ubuntu#ports.ubuntu.com/ubuntu-ports#g" ${PATCH_FILE} +print_file "After patching" /etc/apt/sources.list.d/arm64.list + dpkg --add-architecture arm64 apt update apt install -y \ @@ -85,7 +109,7 @@ if ! ${USE_CACHE} || [ ! -d /usr/local/aarch64-linux-gnu ] || [ ! -d ${NATIVE_PR mkdir build && cd build cmake \ -DCMAKE_BUILD_TYPE=Release \ - -DBUILD_SHARED_LIBS=OFF \ + -DBUILD_SHARED_LIBS=${SHARED_LIBS} \ -DCMAKE_POSITION_INDEPENDENT_CODE=On \ -DJSONCPP_WITH_TESTS=Off \ -DJSONCPP_WITH_POST_BUILD_UNITTEST=Off \ @@ -99,12 +123,25 @@ if ! ${USE_CACHE} || [ ! -d /usr/local/aarch64-linux-gnu ] || [ ! -d ${NATIVE_PR tar -zxf protobuf-cpp-${VERSION_PROTOBUF}.tar.gz cd protobuf-${VERSION_PROTOBUF} mkdir build && cd build - ../configure --prefix=${NATIVE_PREFIX} + cmake \ + -DCMAKE_BUILD_TYPE=Release \ + -DBUILD_SHARED_LIBS=${SHARED_LIBS} \ + -DCMAKE_POSITION_INDEPENDENT_CODE=On \ + -Dprotobuf_BUILD_TESTS=Off \ + -DCMAKE_INSTALL_PREFIX=${NATIVE_PREFIX} \ + .. make install -j`nproc` cd .. mkdir build_arm64 && cd build_arm64 - CC=aarch64-linux-gnu-gcc CXX=aarch64-linux-gnu-g++ \ - ../configure --host=aarch64-linux --prefix=/usr/local/aarch64-linux-gnu + cmake \ + -DCMAKE_BUILD_TYPE=Release \ + -DBUILD_SHARED_LIBS=${SHARED_LIBS} \ + -DCMAKE_POSITION_INDEPENDENT_CODE=On \ + -Dprotobuf_BUILD_TESTS=Off \ + -Dprotobuf_BUILD_PROTOC_BINARIES=Off \ + -DCMAKE_TOOLCHAIN_FILE=/usr/local/aarch64-linux-gnu/lib/cmake/arm64-toolchain.cmake \ + -DCMAKE_INSTALL_PREFIX=/usr/local/aarch64-linux-gnu \ + .. make install -j`nproc` cd ../.. @@ -112,35 +149,41 @@ if ! ${USE_CACHE} || [ ! -d /usr/local/aarch64-linux-gnu ] || [ ! -d ${NATIVE_PR tar -zxf curl-${VERSION_CURL}.tar.gz cd curl-${VERSION_CURL} mkdir build && cd build - LDFLAGS="-static" PKG_CONFIG="pkg-config --static" CC=aarch64-linux-gnu-gcc ../configure \ - --disable-shared --enable-static --disable-ldap --enable-ipv6 --with-ssl --disable-unix-sockets \ - --disable-rtsp --without-zstd --host=aarch64-linux --prefix=/usr/local/aarch64-linux-gnu - make install -j`nproc` V=1 LDFLAGS="-static" - cd ../.. - - git clone -b ${VERSION_AWS_SDK_CPP} --recursive https://github.com/aws/aws-sdk-cpp.git - cd aws-sdk-cpp - mkdir build && cd build - cmake \ - -DENABLE_TESTING=OFF \ - -DBUILD_SHARED_LIBS=OFF \ - -DCMAKE_BUILD_TYPE=Release \ - -DBUILD_ONLY='s3-crt;iot' \ - -DAWS_CUSTOM_MEMORY_MANAGEMENT=ON \ - -DZLIB_LIBRARY=/usr/lib/aarch64-linux-gnu/libz.a \ - -DCURL_LIBRARY=/usr/local/aarch64-linux-gnu/lib/libcurl.a \ - -DCMAKE_TOOLCHAIN_FILE=/usr/local/aarch64-linux-gnu/lib/cmake/arm64-toolchain.cmake \ - -DCMAKE_INSTALL_PREFIX=/usr/local/aarch64-linux-gnu \ - .. - make install -j`nproc` + CURL_OPTIONS=" + --disable-ldap + --enable-ipv6 + --with-ssl + --disable-unix-sockets + --disable-rtsp + --without-zstd + --host=aarch64-linux + --prefix=/usr/local/aarch64-linux-gnu" + if [ "${SHARED_LIBS}" == "OFF" ]; then + LDFLAGS="-static" PKG_CONFIG="pkg-config --static" CC=aarch64-linux-gnu-gcc \ + ../configure \ + --disable-shared \ + --enable-static \ + ${CURL_OPTIONS} + make install -j`nproc` V=1 LDFLAGS="-static" + else + CC=aarch64-linux-gnu-gcc \ + ../configure \ + --enable-shared \ + --disable-static \ + ${CURL_OPTIONS} + make install -j`nproc` V=1 + fi cd ../.. + # Build AWS IoT Device SDK before AWS SDK because they both include aws-crt-cpp as submodules. + # And although we make sure both versions match, we want the AWS SDK version to prevail so that + # we always use the same aws-crt-cpp regardless whether Greengrass is enabled. if ${WITH_GREENGRASSV2_SUPPORT}; then git clone -b ${VERSION_AWS_IOT_DEVICE_SDK_CPP_V2} --recursive https://github.com/aws/aws-iot-device-sdk-cpp-v2.git cd aws-iot-device-sdk-cpp-v2 mkdir build && cd build cmake \ - -DBUILD_SHARED_LIBS=OFF \ + -DBUILD_SHARED_LIBS=${SHARED_LIBS} \ -DBUILD_DEPS=ON \ -DBUILD_TESTING=OFF \ -DUSE_OPENSSL=ON \ @@ -152,6 +195,27 @@ if ! ${USE_CACHE} || [ ! -d /usr/local/aarch64-linux-gnu ] || [ ! -d ${NATIVE_PR cd ../.. fi + git clone -b ${VERSION_AWS_SDK_CPP} --recursive https://github.com/aws/aws-sdk-cpp.git + cd aws-sdk-cpp + mkdir build && cd build + if [ "${SHARED_LIBS}" == "OFF" ]; then + AWS_SDK_CPP_OPTIONS="-DZLIB_LIBRARY=/usr/lib/aarch64-linux-gnu/libz.a -DCURL_LIBRARY=/usr/local/aarch64-linux-gnu/lib/libcurl.a" + else + AWS_SDK_CPP_OPTIONS="" + fi + cmake \ + -DENABLE_TESTING=OFF \ + -DBUILD_SHARED_LIBS=${SHARED_LIBS} \ + -DCMAKE_BUILD_TYPE=Release \ + -DBUILD_ONLY='s3-crt;iot' \ + -DAWS_CUSTOM_MEMORY_MANAGEMENT=ON \ + ${AWS_SDK_CPP_OPTIONS} \ + -DCMAKE_TOOLCHAIN_FILE=/usr/local/aarch64-linux-gnu/lib/cmake/arm64-toolchain.cmake \ + -DCMAKE_INSTALL_PREFIX=/usr/local/aarch64-linux-gnu \ + .. + make install -j`nproc` + cd ../.. + cd .. rm -rf deps-cross-arm64 fi diff --git a/tools/install-deps-cross-armhf.sh b/tools/install-deps-cross-armhf.sh index af07b531..61b8112f 100755 --- a/tools/install-deps-cross-armhf.sh +++ b/tools/install-deps-cross-armhf.sh @@ -9,6 +9,7 @@ source ${SCRIPT_DIR}/install-deps-versions.sh USE_CACHE="true" WITH_GREENGRASSV2_SUPPORT="false" +SHARED_LIBS="OFF" parse_args() { while [ "$#" -gt 0 ]; do @@ -21,10 +22,14 @@ parse_args() { USE_CACHE="false" shift ;; + --shared-libs) + SHARED_LIBS="ON" + ;; --help) echo "Usage: $0 [OPTION]" echo " --with-greengrassv2-support Install dependencies for Greengrass V2" echo " --native-prefix Native install prefix" + echo " --shared-libs Build shared libs, rather than static libs" exit 0 ;; esac @@ -40,10 +45,29 @@ if [ "${ARCH}" == "armhf" ]; then exit -1 fi -sed -i "s/deb http/deb [arch=${ARCH}] http/g" /etc/apt/sources.list +print_file() { + echo ">>> $1: $2" + cat $2 + echo ">>>" +} + +print_file "Before patching" /etc/apt/sources.list +sed -i -E "s/deb (http|mirror\+file)/deb [arch=${ARCH}] \1/g" /etc/apt/sources.list cp /etc/apt/sources.list /etc/apt/sources.list.d/armhf.list -sed -i "s/deb \[arch=${ARCH}\] http/deb [arch=armhf] http/g" /etc/apt/sources.list.d/armhf.list -sed -i -E "s#(archive|security).ubuntu.com/ubuntu#ports.ubuntu.com/ubuntu-ports#g" /etc/apt/sources.list.d/armhf.list +sed -i -E "s/deb \[arch=${ARCH}\] (http|mirror\+file)/deb [arch=armhf] \1/g" /etc/apt/sources.list.d/armhf.list +# GitHub uses a separate mirrors file +if [ -f /etc/apt/apt-mirrors.txt ]; then + print_file "Before patching" /etc/apt/apt-mirrors.txt + cp /etc/apt/apt-mirrors.txt /etc/apt/apt-mirrors-armhf.txt + sed -i "s#/etc/apt/apt-mirrors.txt#/etc/apt/apt-mirrors-armhf.txt#g" /etc/apt/sources.list.d/armhf.list + PATCH_FILE="/etc/apt/apt-mirrors-armhf.txt" + print_file "After patching" /etc/apt/apt-mirrors-armhf.txt +else + PATCH_FILE="/etc/apt/sources.list.d/armhf.list" +fi +sed -i -E "s#(archive|security).ubuntu.com/ubuntu#ports.ubuntu.com/ubuntu-ports#g" ${PATCH_FILE} +print_file "After patching" /etc/apt/sources.list.d/armhf.list + dpkg --add-architecture armhf apt update apt install -y \ @@ -85,7 +109,7 @@ if ! ${USE_CACHE} || [ ! -d /usr/local/arm-linux-gnueabihf ] || [ ! -d ${NATIVE_ mkdir build && cd build cmake \ -DCMAKE_BUILD_TYPE=Release \ - -DBUILD_SHARED_LIBS=OFF \ + -DBUILD_SHARED_LIBS=${SHARED_LIBS} \ -DCMAKE_POSITION_INDEPENDENT_CODE=On \ -DJSONCPP_WITH_TESTS=Off \ -DJSONCPP_WITH_POST_BUILD_UNITTEST=Off \ @@ -99,12 +123,25 @@ if ! ${USE_CACHE} || [ ! -d /usr/local/arm-linux-gnueabihf ] || [ ! -d ${NATIVE_ tar -zxf protobuf-cpp-${VERSION_PROTOBUF}.tar.gz cd protobuf-${VERSION_PROTOBUF} mkdir build && cd build - ../configure --prefix=${NATIVE_PREFIX} + cmake \ + -DCMAKE_BUILD_TYPE=Release \ + -DBUILD_SHARED_LIBS=${SHARED_LIBS} \ + -DCMAKE_POSITION_INDEPENDENT_CODE=On \ + -Dprotobuf_BUILD_TESTS=Off \ + -DCMAKE_INSTALL_PREFIX=${NATIVE_PREFIX} \ + .. make install -j`nproc` cd .. mkdir build_armhf && cd build_armhf - CC=arm-linux-gnueabihf-gcc CXX=arm-linux-gnueabihf-g++ \ - ../configure --host=arm-linux --prefix=/usr/local/arm-linux-gnueabihf + cmake \ + -DCMAKE_BUILD_TYPE=Release \ + -DBUILD_SHARED_LIBS=${SHARED_LIBS} \ + -DCMAKE_POSITION_INDEPENDENT_CODE=On \ + -Dprotobuf_BUILD_TESTS=Off \ + -Dprotobuf_BUILD_PROTOC_BINARIES=Off \ + -DCMAKE_TOOLCHAIN_FILE=/usr/local/arm-linux-gnueabihf/lib/cmake/armhf-toolchain.cmake \ + -DCMAKE_INSTALL_PREFIX=/usr/local/arm-linux-gnueabihf \ + .. make install -j`nproc` cd ../.. @@ -112,35 +149,41 @@ if ! ${USE_CACHE} || [ ! -d /usr/local/arm-linux-gnueabihf ] || [ ! -d ${NATIVE_ tar -zxf curl-${VERSION_CURL}.tar.gz cd curl-${VERSION_CURL} mkdir build && cd build - LDFLAGS="-static" PKG_CONFIG="pkg-config --static" CC=arm-linux-gnueabihf-gcc ../configure \ - --disable-shared --enable-static --disable-ldap --enable-ipv6 --with-ssl --disable-unix-sockets \ - --disable-rtsp --without-zstd --host=arm-linux --prefix=/usr/local/arm-linux-gnueabihf - make install -j`nproc` V=1 LDFLAGS="-static" - cd ../.. - - git clone -b ${VERSION_AWS_SDK_CPP} --recursive https://github.com/aws/aws-sdk-cpp.git - cd aws-sdk-cpp - mkdir build && cd build - cmake \ - -DENABLE_TESTING=OFF \ - -DBUILD_SHARED_LIBS=OFF \ - -DCMAKE_BUILD_TYPE=Release \ - -DBUILD_ONLY='s3-crt;iot' \ - -DAWS_CUSTOM_MEMORY_MANAGEMENT=ON \ - -DZLIB_LIBRARY=/usr/lib/arm-linux-gnueabihf/libz.a \ - -DCURL_LIBRARY=/usr/local/arm-linux-gnueabihf/lib/libcurl.a \ - -DCMAKE_TOOLCHAIN_FILE=/usr/local/arm-linux-gnueabihf/lib/cmake/armhf-toolchain.cmake \ - -DCMAKE_INSTALL_PREFIX=/usr/local/arm-linux-gnueabihf \ - .. - make install -j`nproc` + CURL_OPTIONS=" + --disable-ldap + --enable-ipv6 + --with-ssl + --disable-unix-sockets + --disable-rtsp + --without-zstd + --host=arm-linux + --prefix=/usr/local/arm-linux-gnueabihf" + if [ "${SHARED_LIBS}" == "OFF" ]; then + LDFLAGS="-static" PKG_CONFIG="pkg-config --static" CC=arm-linux-gnueabihf-gcc \ + ../configure \ + --disable-shared \ + --enable-static \ + ${CURL_OPTIONS} + make install -j`nproc` V=1 LDFLAGS="-static" + else + CC=arm-linux-gnueabihf-gcc \ + ../configure \ + --enable-shared \ + --disable-static \ + ${CURL_OPTIONS} + make install -j`nproc` V=1 + fi cd ../.. + # Build AWS IoT Device SDK before AWS SDK because they both include aws-crt-cpp as submodules. + # And although we make sure both versions match, we want the AWS SDK version to prevail so that + # we always use the same aws-crt-cpp regardless whether Greengrass is enabled. if ${WITH_GREENGRASSV2_SUPPORT}; then git clone -b ${VERSION_AWS_IOT_DEVICE_SDK_CPP_V2} --recursive https://github.com/aws/aws-iot-device-sdk-cpp-v2.git cd aws-iot-device-sdk-cpp-v2 mkdir build && cd build cmake \ - -DBUILD_SHARED_LIBS=OFF \ + -DBUILD_SHARED_LIBS=${SHARED_LIBS} \ -DBUILD_DEPS=ON \ -DBUILD_TESTING=OFF \ -DUSE_OPENSSL=ON \ @@ -152,6 +195,27 @@ if ! ${USE_CACHE} || [ ! -d /usr/local/arm-linux-gnueabihf ] || [ ! -d ${NATIVE_ cd ../.. fi + git clone -b ${VERSION_AWS_SDK_CPP} --recursive https://github.com/aws/aws-sdk-cpp.git + cd aws-sdk-cpp + mkdir build && cd build + if [ "${SHARED_LIBS}" == "OFF" ]; then + AWS_SDK_CPP_OPTIONS="-DZLIB_LIBRARY=/usr/lib/arm-linux-gnueabihf/libz.a -DCURL_LIBRARY=/usr/local/arm-linux-gnueabihf/lib/libcurl.a" + else + AWS_SDK_CPP_OPTIONS="" + fi + cmake \ + -DENABLE_TESTING=OFF \ + -DBUILD_SHARED_LIBS=${SHARED_LIBS} \ + -DCMAKE_BUILD_TYPE=Release \ + -DBUILD_ONLY='s3-crt;iot' \ + -DAWS_CUSTOM_MEMORY_MANAGEMENT=ON \ + ${AWS_SDK_CPP_OPTIONS} \ + -DCMAKE_TOOLCHAIN_FILE=/usr/local/arm-linux-gnueabihf/lib/cmake/armhf-toolchain.cmake \ + -DCMAKE_INSTALL_PREFIX=/usr/local/arm-linux-gnueabihf \ + .. + make install -j`nproc` + cd ../.. + cd .. rm -rf deps-cross-armhf fi diff --git a/tools/install-deps-native.sh b/tools/install-deps-native.sh index 47fde284..d1f26dab 100755 --- a/tools/install-deps-native.sh +++ b/tools/install-deps-native.sh @@ -10,6 +10,7 @@ source ${SCRIPT_DIR}/install-deps-versions.sh USE_CACHE="true" INSTALL_BUILD_TIME_DEPS="true" WITH_GREENGRASSV2_SUPPORT="false" +SHARED_LIBS="OFF" parse_args() { while [ "$#" -gt 0 ]; do @@ -25,11 +26,15 @@ parse_args() { --runtime-only) INSTALL_BUILD_TIME_DEPS="false" ;; + --shared-libs) + SHARED_LIBS="ON" + ;; --help) echo "Usage: $0 [OPTION]" echo " --with-greengrassv2-support Install dependencies for Greengrass V2" echo " --runtime-only Install only runtime dependencies" echo " --prefix Install prefix" + echo " --shared-libs Build shared libs, rather than static libs" exit 0 ;; esac @@ -56,7 +61,7 @@ if ${INSTALL_BUILD_TIME_DEPS}; then libsnappy-dev \ libssl-dev \ unzip \ - wget \ + wget \ zlib1g-dev update-alternatives --install /usr/bin/clang-format clang-format /usr/bin/clang-format-10 1000 update-alternatives --install /usr/bin/clang-tidy clang-tidy /usr/bin/clang-tidy-10 1000 @@ -84,7 +89,7 @@ if ${INSTALL_BUILD_TIME_DEPS} && ( ! ${USE_CACHE} || [ ! -d ${PREFIX} ] ); then mkdir build && cd build cmake \ -DCMAKE_BUILD_TYPE=Release \ - -DBUILD_SHARED_LIBS=OFF \ + -DBUILD_SHARED_LIBS=${SHARED_LIBS} \ -DCMAKE_POSITION_INDEPENDENT_CODE=On \ -DJSONCPP_WITH_TESTS=Off \ -DJSONCPP_WITH_POST_BUILD_UNITTEST=Off \ @@ -97,7 +102,13 @@ if ${INSTALL_BUILD_TIME_DEPS} && ( ! ${USE_CACHE} || [ ! -d ${PREFIX} ] ); then tar -zxf protobuf-cpp-${VERSION_PROTOBUF}.tar.gz cd protobuf-${VERSION_PROTOBUF} mkdir build && cd build - ../configure --prefix=${PREFIX} + cmake \ + -DCMAKE_BUILD_TYPE=Release \ + -DBUILD_SHARED_LIBS=${SHARED_LIBS} \ + -DCMAKE_POSITION_INDEPENDENT_CODE=On \ + -Dprotobuf_BUILD_TESTS=Off \ + -DCMAKE_INSTALL_PREFIX=${PREFIX} \ + .. make install -j`nproc` cd ../.. @@ -105,33 +116,39 @@ if ${INSTALL_BUILD_TIME_DEPS} && ( ! ${USE_CACHE} || [ ! -d ${PREFIX} ] ); then tar -zxf curl-${VERSION_CURL}.tar.gz cd curl-${VERSION_CURL} mkdir build && cd build - LDFLAGS="-static" PKG_CONFIG="pkg-config --static" ../configure --disable-shared --enable-static \ - --disable-ldap --enable-ipv6 --with-ssl --disable-unix-sockets --disable-rtsp --without-zstd --prefix=${PREFIX} - make install -j`nproc` V=1 LDFLAGS="-static" - cd ../.. - - git clone -b ${VERSION_AWS_SDK_CPP} --recursive https://github.com/aws/aws-sdk-cpp.git - cd aws-sdk-cpp - mkdir build && cd build - cmake \ - -DENABLE_TESTING=OFF \ - -DBUILD_SHARED_LIBS=OFF \ - -DCMAKE_BUILD_TYPE=Release \ - -DBUILD_ONLY='s3-crt;iot' \ - -DAWS_CUSTOM_MEMORY_MANAGEMENT=ON \ - -DZLIB_LIBRARY=/usr/lib/$(gcc -dumpmachine)/libz.a \ - -DCURL_LIBRARY=${PREFIX}/lib/libcurl.a \ - -DCMAKE_INSTALL_PREFIX=${PREFIX} \ - .. - make install -j`nproc` + CURL_OPTIONS=" + --disable-ldap + --enable-ipv6 + --with-ssl + --disable-unix-sockets + --disable-rtsp + --without-zstd + --prefix=${PREFIX}" + if [ "${SHARED_LIBS}" == "OFF" ]; then + LDFLAGS="-static" PKG_CONFIG="pkg-config --static" \ + ../configure \ + --disable-shared \ + --enable-static \ + ${CURL_OPTIONS} + make install -j`nproc` V=1 LDFLAGS="-static" + else + ../configure \ + --enable-shared \ + --disable-static \ + ${CURL_OPTIONS} + make install -j`nproc` V=1 + fi cd ../.. + # Build AWS IoT Device SDK before AWS SDK because they both include aws-crt-cpp as submodules. + # And although we make sure both versions match, we want the AWS SDK version to prevail so that + # we always use the same aws-crt-cpp regardless whether Greengrass is enabled. if ${WITH_GREENGRASSV2_SUPPORT}; then git clone -b ${VERSION_AWS_IOT_DEVICE_SDK_CPP_V2} --recursive https://github.com/aws/aws-iot-device-sdk-cpp-v2.git cd aws-iot-device-sdk-cpp-v2 mkdir build && cd build cmake \ - -DBUILD_SHARED_LIBS=OFF \ + -DBUILD_SHARED_LIBS=${SHARED_LIBS} \ -DBUILD_DEPS=ON \ -DBUILD_TESTING=OFF \ -DUSE_OPENSSL=ON \ @@ -141,6 +158,26 @@ if ${INSTALL_BUILD_TIME_DEPS} && ( ! ${USE_CACHE} || [ ! -d ${PREFIX} ] ); then cd ../.. fi + git clone -b ${VERSION_AWS_SDK_CPP} --recursive https://github.com/aws/aws-sdk-cpp.git + cd aws-sdk-cpp + mkdir build && cd build + if [ "${SHARED_LIBS}" == "OFF" ]; then + AWS_SDK_CPP_OPTIONS="-DZLIB_LIBRARY=/usr/lib/$(gcc -dumpmachine)/libz.a -DCURL_LIBRARY=${PREFIX}/lib/libcurl.a" + else + AWS_SDK_CPP_OPTIONS="" + fi + cmake \ + -DENABLE_TESTING=OFF \ + -DBUILD_SHARED_LIBS=${SHARED_LIBS} \ + -DCMAKE_BUILD_TYPE=Release \ + -DBUILD_ONLY='s3-crt;iot' \ + -DAWS_CUSTOM_MEMORY_MANAGEMENT=ON \ + ${AWS_SDK_CPP_OPTIONS} \ + -DCMAKE_INSTALL_PREFIX=${PREFIX} \ + .. + make install -j`nproc` + cd ../.. + git clone -b ${VERSION_GOOGLE_TEST} https://github.com/google/googletest.git cd googletest mkdir build && cd build @@ -155,7 +192,7 @@ if ${INSTALL_BUILD_TIME_DEPS} && ( ! ${USE_CACHE} || [ ! -d ${PREFIX} ] ); then cd benchmark mkdir build && cd build cmake \ - -DBUILD_SHARED_LIBS=OFF \ + -DBUILD_SHARED_LIBS=${SHARED_LIBS} \ -DBENCHMARK_DOWNLOAD_DEPENDENCIES=on \ -DCMAKE_BUILD_TYPE=Release \ -DCMAKE_INSTALL_PREFIX=${PREFIX} \ @@ -165,4 +202,8 @@ if ${INSTALL_BUILD_TIME_DEPS} && ( ! ${USE_CACHE} || [ ! -d ${PREFIX} ] ); then cd .. rm -rf deps-native + + if [ "${SHARED_LIBS}" == "ON" ]; then + ldconfig + fi fi diff --git a/tools/install-deps-versions.sh b/tools/install-deps-versions.sh index 2bec9ce6..94a89a1e 100755 --- a/tools/install-deps-versions.sh +++ b/tools/install-deps-versions.sh @@ -4,9 +4,9 @@ export VERSION_PROTOBUF="3.21.12" export VERSION_PROTOBUF_RELEASE="v21.12" export VERSION_CURL="7.86.0" export VERSION_CURL_RELEASE="curl-7_86_0" -export VERSION_AWS_SDK_CPP="1.11.111" -# MAKE SURE THE CRT VERSON IN AWS_SDK_CPP IS THE SAME AS IN AWS_IOT_SDK_CPP -export VERSION_AWS_IOT_DEVICE_SDK_CPP_V2="v1.22.0" +export VERSION_AWS_SDK_CPP="1.11.148" +# MAKE SURE THE CRT VERSION IN AWS_SDK_CPP IS THE SAME AS IN AWS_IOT_SDK_CPP +export VERSION_AWS_IOT_DEVICE_SDK_CPP_V2="v1.29.0" export VERSION_GOOGLE_TEST="release-1.10.0" export VERSION_GOOGLE_BENCHMARK="v1.6.1" export VERSION_ANDROID_CMDLINE_TOOLS="9123335" diff --git a/tools/install-fwe.sh b/tools/install-fwe.sh index 47e3a312..dcac672b 100755 --- a/tools/install-fwe.sh +++ b/tools/install-fwe.sh @@ -8,8 +8,8 @@ set -e mkdir -p /var/aws-iot-fleetwise -cp build/src/executionmanagement/aws-iot-fleetwise-edge /usr/bin/ -cp tools/deploy/run-fwe.sh /usr/bin/ -cp tools/deploy/fwe@.service /lib/systemd/system/ +cp build/aws-iot-fleetwise-edge /usr/bin/ +cp tools/deploy/run-fwe.sh /usr/bin/ +cp tools/deploy/fwe@.service /lib/systemd/system/ ./tools/deploy/start-and-enable-fwe.sh diff --git a/tools/yocto/sources/meta-aws-iot-fleetwise/recipes-extended/setup-socketcan/setup-socketcan.bb b/tools/yocto/sources/meta-aws-iot-fleetwise/recipes-extended/setup-socketcan/setup-socketcan.bb index a7ebe53c..76e041e8 100644 --- a/tools/yocto/sources/meta-aws-iot-fleetwise/recipes-extended/setup-socketcan/setup-socketcan.bb +++ b/tools/yocto/sources/meta-aws-iot-fleetwise/recipes-extended/setup-socketcan/setup-socketcan.bb @@ -13,6 +13,6 @@ inherit systemd do_install() { install -d ${D}${systemd_system_unitdir} install -m 0755 ${S}/setup-socketcan.service ${D}${systemd_system_unitdir} - install -d ${D}${bindir} - install -m 0755 ${S}/setup-socketcan.sh ${D}${bindir} + install -d ${D}${bindir} + install -m 0755 ${S}/setup-socketcan.sh ${D}${bindir} }