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)
📷 | Sensor | Interface | Metrics | Driver |
---|---|---|---|---|
MAX44009 | I²C |
Custom implementation | ||
SI1145 | I²C |
Custom implementation | ||
HDC1080 | I²C |
Custom implementation | ||
DHT11/22 | 1-Wire |
Library d2r2/go-dht with custom wrapper | ||
CCS811 | I²C |
Custom implementation | ||
BMP280 | I²C |
Library google/periph with custom wrapper | ||
ADXL345 | I²C |
Custom implementation | ||
LSM303C | I²C |
Fork bskari/go-lsm303 with custom wrapper | ||
MAX30102 | I²C |
Library cgxeiji/max3010x with custom wrapper |
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.
📷 | Sensor | Interface | Metrics | Driver | ADC Driver |
---|---|---|---|---|---|
Hall Effect | Analog with I²C ADC |
Custom implementation | Library MichaelS11/go-ads | ||
Microphone | Analog with I²C ADC |
Custom implementation | Library MichaelS11/go-ads | ||
Piezoelectric film | Analog with I²C ADC |
Custom implementation | Library MichaelS11/go-ads | ||
Gas (MQ-9) | Analog with I²C ADC |
Custom implementation | Library MichaelS11/go-ads | ||
Flame detector | Analog with I²C ADC |
Custom implementation | Library MichaelS11/go-ads |
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).
📷 | Chip | Interface | Hardware options | Driver |
---|---|---|---|---|
MAX17040 | I²C |
UPS-Lite | Custom implementation |
📷 | Chip | Interface | Hardware options | Driver |
---|---|---|---|---|
e-Ink (EPD) | SPI |
2.13' e-Paper HAT | Custom implementation | |
ST7789 | SPI |
2' IPS LCD | Custom implementation |
Protocol | Service | UUID | Description | Driver |
---|---|---|---|---|
BLE | Location service | F8AE4978-5AAB-46C3-A8CB-127F347EAA01 |
Enables location tethering with mobile application | Library go-ble |
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.
On the lower level we got drivers, which of course implementing direct communication and control of the hardware:
drivers/periphery
- communication protocols implementation and wrappers (I²C
, SPI
, GPIO
)drivers/sensors
- each sensor custom drivers or library wrappers reduced to a single interface structuredrivers/display
- possible visual output drivers drivers/power
- UPS's and power management driversSince 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 devicesLastly, 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.
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.
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.
GPIO
, I²C
, and SPI
available, as well as Internet connection capabilities, preferably with Wi-Fi module. Based on considerations of portability and relative cheapness this project intends to use RPi Zero Wconnection.yaml
file in the root directoryThe 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
I²C
bus (or USB port) for any sensor modules, the device will perform a scan to detect the location of sensors on startup.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.
Licensed under the Apache 2.0.