|
| 1 | +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. |
| 2 | +// SPDX-License-Identifier: Apache-2.0 |
| 3 | + |
| 4 | +#include "MyBlobDataSource.h" |
| 5 | +#include "LoggingModule.h" |
| 6 | +#include <chrono> |
| 7 | +#include <utility> |
| 8 | +#include <vector> |
| 9 | + |
| 10 | +namespace Aws |
| 11 | +{ |
| 12 | +namespace IoTFleetWise |
| 13 | +{ |
| 14 | + |
| 15 | +MyBlobDataSource::MyBlobDataSource( SignalBufferPtr signalBufferPtr, |
| 16 | + std::shared_ptr<RawData::BufferManager> rawDataBufferManager ) |
| 17 | + : mSignalBufferPtr( std::move( signalBufferPtr ) ) |
| 18 | + , mRawBufferManager( std::move( rawDataBufferManager ) ) |
| 19 | +{ |
| 20 | + mThread = std::thread( [this]() { |
| 21 | + // Example code that pushes a message every 500ms: |
| 22 | + while ( !mStop ) |
| 23 | + { |
| 24 | + pushData(); |
| 25 | + std::this_thread::sleep_for( std::chrono::milliseconds( 500 ) ); |
| 26 | + } |
| 27 | + } ); |
| 28 | +} |
| 29 | + |
| 30 | +MyBlobDataSource::~MyBlobDataSource() |
| 31 | +{ |
| 32 | + mStop = true; |
| 33 | + mThread.join(); |
| 34 | +} |
| 35 | + |
| 36 | +void |
| 37 | +MyBlobDataSource::pushData() |
| 38 | +{ |
| 39 | + std::lock_guard<std::mutex> lock( mDecoderDictionaryMutex ); |
| 40 | + if ( mBlobSourceSignalId == INVALID_SIGNAL_ID ) |
| 41 | + { |
| 42 | + FWE_LOG_TRACE( "No decoding info yet" ); |
| 43 | + return; |
| 44 | + } |
| 45 | + |
| 46 | + FWE_LOG_TRACE( "Pushing blob" ); |
| 47 | + // Example blob data: |
| 48 | + std::vector<uint8_t> blob{ 'H', 'e', 'l', 'l', 'o', ' ', 'w', 'o', 'r', 'l', 'd', '!' }; |
| 49 | + |
| 50 | + // Serialize in the CDR format defined in blob-nodes.json and blob-decoders.json which is just a |
| 51 | + // message containing a single byte array of unstructured (blob) data: |
| 52 | + // Add CDR header: |
| 53 | + std::vector<uint8_t> cdr{ |
| 54 | + 0, // UINT8 Dummy byte |
| 55 | + 1, // UINT8 Encapsulation |
| 56 | + 0, // UINT16-LSB Options |
| 57 | + 0, // UINT16-MSB Options |
| 58 | + }; |
| 59 | + // Add the UINT32 blob size: |
| 60 | + cdr.push_back( blob.size() & 0xFF ); |
| 61 | + cdr.push_back( ( blob.size() >> 8 ) & 0xFF ); |
| 62 | + cdr.push_back( ( blob.size() >> 16 ) & 0xFF ); |
| 63 | + cdr.push_back( ( blob.size() >> 24 ) & 0xFF ); |
| 64 | + // Add blob data: |
| 65 | + cdr.insert( cdr.end(), blob.begin(), blob.end() ); |
| 66 | + |
| 67 | + // Ingest the message: |
| 68 | + auto timestamp = mClock->systemTimeSinceEpochMs(); |
| 69 | + auto bufferHandle = mRawBufferManager->push( cdr.data(), cdr.size(), timestamp, mBlobSourceSignalId ); |
| 70 | + if ( bufferHandle == RawData::INVALID_BUFFER_HANDLE ) |
| 71 | + { |
| 72 | + FWE_LOG_WARN( "Raw message was rejected by RawBufferManager" ); |
| 73 | + return; |
| 74 | + } |
| 75 | + // immediately set usage hint so buffer handle does not get directly deleted again |
| 76 | + mRawBufferManager->increaseHandleUsageHint( |
| 77 | + mBlobSourceSignalId, bufferHandle, RawData::BufferHandleUsageStage::COLLECTED_NOT_IN_HISTORY_BUFFER ); |
| 78 | + auto collectedSignal = |
| 79 | + CollectedSignal( mBlobSourceSignalId, timestamp, bufferHandle, SignalType::RAW_DATA_BUFFER_HANDLE ); |
| 80 | + CollectedSignalsGroup collectedSignalsGroup; |
| 81 | + collectedSignalsGroup.push_back( collectedSignal ); |
| 82 | + if ( !mSignalBufferPtr->push( CollectedDataFrame( collectedSignalsGroup ) ) ) |
| 83 | + { |
| 84 | + FWE_LOG_WARN( "Signal buffer full" ); |
| 85 | + } |
| 86 | +} |
| 87 | + |
| 88 | +void |
| 89 | +MyBlobDataSource::onChangeOfActiveDictionary( ConstDecoderDictionaryConstPtr &dictionary, |
| 90 | + VehicleDataSourceProtocol networkProtocol ) |
| 91 | +{ |
| 92 | + if ( networkProtocol != VehicleDataSourceProtocol::COMPLEX_DATA ) |
| 93 | + { |
| 94 | + return; |
| 95 | + } |
| 96 | + std::lock_guard<std::mutex> lock( mDecoderDictionaryMutex ); |
| 97 | + mBlobSourceSignalId = INVALID_SIGNAL_ID; |
| 98 | + auto decoderDictionaryPtr = std::dynamic_pointer_cast<const ComplexDataDecoderDictionary>( dictionary ); |
| 99 | + auto decoders = decoderDictionaryPtr->complexMessageDecoderMethod.find( BLOB_NETWORK_INTERFACE_ID ); |
| 100 | + if ( decoders == decoderDictionaryPtr->complexMessageDecoderMethod.end() ) |
| 101 | + { |
| 102 | + FWE_LOG_INFO( std::string( "No decoders found for interface ID " ) + BLOB_NETWORK_INTERFACE_ID ); |
| 103 | + return; |
| 104 | + } |
| 105 | + auto decoder = decoders->second.find( BLOB_MESSAGE_ID ); |
| 106 | + if ( decoder == decoders->second.end() ) |
| 107 | + { |
| 108 | + FWE_LOG_INFO( std::string( "No decoder found for message ID " ) + BLOB_MESSAGE_ID ); |
| 109 | + return; |
| 110 | + } |
| 111 | + mBlobSourceSignalId = decoder->second.mSignalId; |
| 112 | + FWE_LOG_INFO( "Signal ID for blob is " + std::to_string( mBlobSourceSignalId ) ); |
| 113 | + |
| 114 | + // Note that there's no sanity check of the message format here, so if it doesn't match the |
| 115 | + // format pushed in pushData(), then cloud won't understand it. |
| 116 | +} |
| 117 | + |
| 118 | +} // namespace IoTFleetWise |
| 119 | +} // namespace Aws |
0 commit comments