Microservices
Microservices are a set of functions that can be called by mutliple other components to perform some task such as filtering sensor data, writing and reading data to and from the database and the Smart Contract, and calling cloud services such as AWS Image Rekognition. In this solution these microservices will be called by two other components:
-
The Application Programming Interfaces (APIs): which will be used by the microcontrollers to call the AWS Image Rekognition service and by the web app to write and read data to and from the database and the Smart Contract.
-
The AWS IoT Platform: which is where microcontrollers will post the sensor data.
This topic covers the microservices used in this solution, their purpose, which component calls them and which other function they call.
In this solution we have used the AWS architecture and services (known as Lambda functions) to deploy microservices. While the approach and code is largely reusable, you will have to adapt to your platform or tech stack if you choose a try a different one.
Lambda Functions
The following Lamda functions will be implemented:
1. receiveAndFilterMicrocontrollerData
This function will receive the data sent by the microcontrollers via the MQTT Broker or any other path. The primary purpose of this function is to filter out the data noise (such as data from invalid microcontrollers or sensors and data that is totally out of range and hence likely an error) before sending it to the Smart Contract.
The data to the database should be sent without filtering (as received) so it can be used for subsequent audit and analysis, while the data to the Smart Contract must be filtered since it is expensive to store and manage data on a Blockhain.
The function will invoke other functions to save the data to the database and to send the data to the Smart Contract.
The checks for valid data include the following:
- For the sake of simplicity, we are assuming there is only one order actively under processing (in the Open state) so the order id is not received as a parameter.
- To validate the microcontroller id, check the Participants table to see which participant it is mapped to and then confirm that the participant is mapped to the order being processed.
- In the case of the Transporter check if the microcontroller id is mapped to the assigned vehicle.
- Get the id type from the Microcontrollers table and validate that the type is relevant to the participant it is mapped to.
- Get the sensor ids and sensor types attached to the microcontroller.
- From the SensorTypes table get the parameters expected from the sensor and the range of value for each parameter.
- Validate that the data received from the microcontroller passes all these checks.
- The Smart Contract must be sent data at the pre-defined frequency it expects. If any of the values are not as expected, pass a value of -1 so the Smart Contract can factor it in for penalty calculations.
This function will not have an API endpoint but will be called by the AWS IoT platform rule when microcontrollers publish data on a topic.
2. receiveAndProcessANPRImage
This function will receive the binary image data sent by the camera modules on microcontrollers and process it using the AWS Rekognition service. This function will have an API endpoint and is the one case where the microcontrollers will directly call the API endpoint over WiFi instead of pushing data to the MQTT broker (which is the generally preferred method for IoT data transfer).
This function will invoke the AWS Rekognition services and get the text version of the registration number from the image of the number plate received. It will then create the required data structure and pass it on for further processing and to write to the database and send to the Smart Contract.
3. writeToDDB
This function will write the data to the AWS DynamoDB.
4. sendANPRData
This function will send the text data for the vehicle registration number (extracted from the image by the ANPR service) to the Smart Contract.
5. sendScheduleData
This function sends the departure and arrival time data to the Smart Contract.
6. sendQuantityData
This function sends the loaded and unloaded quantity data to the Smart Contract.
7. sendTransportConditionsData
Sends the transport conditions data to the Smart Contract.
Coding and Deploying Lambda Functions
All functions that interact with the Smart Contract to write or read data are implemented in Node.js. This is necessary since they need the web3.js library which is not available in the AWS environment.
When a Lambda function needs custom libraries or other supporting files, the main file, named index.js, and all required libraries and supporting files need to be uploaded as a zip file when creating the Lambda function as its source code. Note that you should zip only the files required and not the folder containing the files.
The following files are required for any function that sends or reads data to and from a Smart Contract:
File | Purpose |
---|---|
index.js | The main function code file. This needs the web3 service provider endpoint for the private devnet or a public testnet. This may need to be mapped to the participant address, since each participant will have their own node endpoint. This will also need the private key of the participant that will execute this function. Ideally this should not be saved in a publicly visible artifact. A small Lambda function to get it from the Smart Contract could be developed which could be invoked by the functions that write to the Smart Contract. |
package.json | The list of packages the main function code requires. |
package-lock.json | Similar to package.json. |
node_modules | The folder that has all required packages listed in package.json installed with npm. Note that this can get quite large in size. |
smart_contract_specs.json | This file has two pieces of data that are required to identify the contract the function is going to iteract with: -The smart contract ABI (generated in Remix after compiling). -The smart contract address (generated in Remix after deploying). Due to this requirement the Smart Contract will have to be compiled and deployed before the function code is uploaded. This file can be reused across all functions. |
Functions that do not interact with the Smart Contract are implemented using the Python language.
Lambda functions are mapped to an API endpoint, which means they are the function executed when a client invokes an API.
Separation of Duties (SOD) is an application architecture best practice so each Lambda function must perform a single logical task or a set of logically grouped tasks. Lambda functions may be chained, such that one Lambda function may call another, each performing some action.
The code for the Lamda functions and the steps to deploy them will be shared with subscribers.