ChainMetric: IoT
Overview
Chainmetric IoT being an embedded sensors-equipped device firmware, designed to be compatible with a permissioned blockchain network based on Hyperledger Fabric stack.
By leveraging highly concurrent engine driver such implementation is ideal for harvesting environmental surrounding conditions and further publishing them onto the distributed, immutable ledger, where such data can be validated by on-chain Smart Contacts against previously assigned requirements.
Both hardware specification and firmware architecture designed to modular and extendable to support vast variety of use cases, deployment environments, and business needs.
The device itself is intended for deployment in the areas where assets requiring monitoring are stored or being delivered on. Thus, providing a general-purpose supply-chain monitoring solution.
Chainmetric edge IoT device (development stage beta build)
Supported IO
Digital sensors
Digital sensors natively supports hotswap, so that it is possible to add, replace, or remove such sensors on fly,
without device restart or reconfiguration. This is possible due to combination of the address assigned for each I²C
chip
and CHIP_ID
register, which together should be unique. The exception is of course sensors based on 1-Wire
communication
interface, they must instead be registered as static sensors.
Analog sensors
Hotswap capabilities is also supported for analog sensors, and although these do not have any unique identifier
to be detectable by, the ADC chip does. So, the solution here is to attach ADC chip to each analog sensor
and setup different address for each used sensor. There is a limitation in this method, since ADC available addresses is finite.
For ADS1115 used this project we are bounded to 4 addresses (0x48, 0x49, 0x4A, 0x4B).
Power
Displays
Bluetooth
Protocol |
Service |
UUID |
Description |
Driver |
BLE |
Location service |
F8AE4978-5AAB-46C3-A8CB-127F347EAA01 |
Enables location tethering with mobile application |
Library go-ble |
Firmware architecture
The design decisions firmware development was mostly based on the idea of enabling wide range of use cases for IoT device.
With that in mind the architecture itself is based on the concept of modularity, thus allowing feature set to be
easily extendable and adaptable for new hardware, areas of application, and deployment environments.
Drivers
On the lower level we got drivers, which of course implementing direct communication and control of the hardware:
Network
Since being a firmware oriented on IoT device in the Blockchain infrastructure,
it is of course cannot come without network layer:
network/blockchain
- the Hyperledger Fabric related clients as well as Smart Contract RPCs.
network/localnet
- package proving interface for low range radius communication with other devices
Controllers
Lastly, on the higher level we got business logic driven controllers, which by taking favor of the previous layers
define required feature set of the IoT device.
Besides controllers/gui
and controllers/storage
,
which by definition do exactly what their names stand for, this layer holds controllers/device
,
which is the controller for device itself where the most of the domain logic are.
This is the place where the mentioned above modularity really starts to shine.
Logical modules
While the Device
type holds the current state of the device, along with cached operational data,
up-to-date sensors registry and the main context, it actually does not hold any feature-related functionality.
Instead, it delegates that to the logical modules, each containing its own atomic portion of the business logic, responsibilities,
and is capable of mutating state of the Device
.
Module |
Description |
Implementation |
LIFECYCLE_MANAGER |
Manages device initialization, registration on network, updates device state on startup and shutdown |
modules/lifecycle_manager |
ENGINE_OPERATOR |
Operates SensorsReader engine, handles readings requests and posts results on chain |
modules/engine_operator |
EVENTS_OBSERVER |
Listens to changes in assets, requirements or device state on the Blockchain, handles them accordingly |
modules/events_observer |
CACHE_MANAGER |
Caches operational data on device startup, updates or flushes cache when needed |
modules/cache_manager |
FAILOVER_HANDLER |
Handles network issues which lead to inability of posting readings by storing them in the persistent storage (embedded LevelDB) |
modules/failover_handler |
HOTSWAP_DETECTOR |
Monitors and detects changes in device's periphery, updates available sensors pool |
modules/hotswap_detector |
REMOTE_CONTROLLER |
Listens to remote commands directed to the current device, performs command execution against the device |
modules/remote_controller |
POWER_MANAGER |
Monitors device power consumption and battery level, updates device state on chain |
modules/power_manager |
LOCATION_MANAGER |
Manages device physical location, updates device state on chain |
modules/location_manager |
GUI_RENDERER |
Displays device specs, requests throughput, and other useful data on the display if such is available |
modules/gui_renderer |
Logical modules can be registered on the device instance conditionally, e.g. depending on the device hardware specs or deployment environment.
device := device.New(
modules.WithLifecycleManager(),
modules.WithEngineOperator(),
modules.WithCacheManager(),
modules.WithEventsObserver(),
modules.WithHotswapDetector(),
modules.WithRemoteController(),
modules.WithLocationManager(),
modules.WithPowerManager(),
modules.WithFailoverHandler(),
modules.WithGUIRenderer(),
)
Logical modules are implemented in such a way, so they cannot directly communicate with each other
and foremost not being aware of other modules' existence. Yet, some functionality requires exactly that,
e.g. requires intermediate input or must be triggered by some occurred event.
For such purposes modules can utilize shared state of the device or more often local operational events.
Such idea is borrowed from the Event Driven Architecture (EDA) and is achieved with help of timoth-y/go-eventdriver
package.
Although such approach definitely can increase complexity of the codebase it on the other hand provides some major benefits,
which have been considered to be worth-taking trade off. Some of them are stronger abstraction, low logic blocks coupling,
higher extensibility with lower risc of broking something, and more.
Sensors reading engine
One other essential component of the device functionality is the controllers/engine
package,
whose responsibility includes proving interface to receive sensor reading requests, subscribe handlers for outcome results,
control, initialize and deallocate physical sensor modules if such are on stand-by for certain amount of time.
Engine leverages the convenience of the Go concurrency model, allowing to harvest data from multiply sensors
and for multiply subscribers at the same time, while not blocking other components and modules execution.
Requirements
Deployment
The Makefile in the root directory contains rule sync
for syncing local project codebase with a remote device via IP address, which can be set as environmental variables:
DOMAIN=chainmetric.network
ORG=chipa-inu
USER_ID=edge-device1
REMOTE_IP=192.168.50.61
CRYPTO_DIR=../network/.crypto-config.chainmetric.network
For initial setup rule setup-device
can be used, which performs build
, sends cryptographic materials,
generates connection.yaml
with fabnctl
utility based on previously setup env vars,
and finally executes sync
rule:
$ make setup-device
While development to build rule build
is available which will perform build for GOARCH=ARM
$ make build
To build and send binaries to device rule update-device
can be used:
$ make update-device
The firmware configuration can be changed directly in config.yaml
file:
...
device:
hotswap_detect_interval: 500ms
battery_check_interval: 2m
gui_update_interval: 10s
engine:
sensor_sleep_standby_timeout: 3m
...
Or via exporting env variables (use _
where yaml has .
):
$ export ENGINE_HOTSWAP_DETECT_INTERVAL 500ms
After the device has been set up and contains binaries with configuration, the firmware is ready to be run
:
$ make run
For force stop of the firmware use kill
rule:
$ make kill
Usage
- The device should be deployed in the same area with controlled assets (warehouse, delivery truck, etc)
- In case the device is being used for the first time it must be registered via dedicated mobile application via QR code which will be automatically displayed on the embedded screen (currently ST7789 is the only supported driver). The generated QR code will contain the device's specification: network info, supported metrics, etc.
- It is allowed to use any
I²C
bus (or USB port) for any sensor modules, the device will perform a scan to detect the location of sensors on startup.
- As soon as the device will be registered on the network it will detect surrounding assets and requirements assigned to them and will start posting sensor reading to the blockchain
- Further device management and issuing remote commands can be performed from dedicated mobile application
- The registered device will automatically post its status on the startup and shutdown
Roadmap
- Failover caching on network connection absence (#3)
- Sensor modules hot-swap support (#1)
- Analog sensors (Hall-effect sensor, microphone) support via
MCP3008 ADS1115 (#4)
- E-Ink display support (#5)
- GUI for displaying statistics data and emergency warnings (#9)
- Location tracking via bluetooth pairing with mobile app (#10)
- A device as a blockchain node
- Load distribution across nearby devices
- Video-camera driver
Wrap up
Chainmetric device is designed for providing a real-time continuous stream of sensor-sourced environmental metrics readings
to the distributed secure ledger for further validation by on-chain Smart Contracts.
Such a core-concept in combination with a dedicated cross-platform mobile application makes
Chainmetric project an ambitious general-purpose requirements control solution for supply-chains.
License
Licensed under the Apache 2.0.