In my last blog IoT 3.0, I demonstrated the difference between sending IoT data to a central database versus to a distributed ledger. To do so, I leveraged Duino IoT that is a feature of Duino-Coin, a hybrid crypto currency.

In this blog, I will look under the covers how this works and deploy IoT data via Apache Kafka to my own local blockchain as follows:

  1. Install Microsoft Visual Studio Code.
  2. Install Microsoft Windows Subsystem for Linux.
  3. Install Node.js.
  4. Install Hardhat.
  5. Deploy smart contract.
  6. Send IoT data to local blockchain.
  7. Read IoT Data from local blockchain.

Install Visual Studio Code.

Microsoft Visual Studio Code could not be easier to install and comes in editions for macOS, Windows x64 and Linux x64. It supports many programming languages, among these, for this blog, Solidity and TypeScript.

Install the Microsoft Windows Subsystem for Linux.

I work on Microsoft Windows, but if you work on macOS or Linux, you can omit this step.

wsl –install

Install Node.js

Since I need Node.js as my TypeScript runtime, I install it with the Node Version Manager.

curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.3/install.sh | bash
nvm install node

Install Hardhat.

Hardhat is a development environment for Ethereum software that I leverage for this blog.

npm install --save-dev hardhat
mkdir raspi
cd raspi
yarn hardhat init

Deploy smart contract.

My smart contract is very simple with a read and set function.

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;

contract Raspi {
    int public pressure;

    function read() public view returns (int) {
        return pressure;
    }

    function set(int _pressure) public {
        pressure = _pressure;
    }
}

After compiling, it is ready for deployment.

yarn hardhat compile

In preparation for deployment, I start a local HTTP and WebSocket JSON-RPC server.

yarn hardhat node
yarn run v1.22.19
$ /home/architectSAP/raspi/node_modules/.bin/hardhat node
Started HTTP and WebSocket JSON-RPC server at http://127.0.0.1:8545/

And add it to hardhat.config.ts.

import { HardhatUserConfig } from "hardhat/config";
import "@nomicfoundation/hardhat-toolbox";

const config: HardhatUserConfig = {
  solidity: "0.8.17",
  networks: {
    localhost: {
      url: "http://127.0.0.1:8545/",
      chainId: 31337,
    },
  },
};

export default config;

Deployment is via TypeScript and provides me with its address.

import { ethers } from "hardhat";

async function main() {
  const Lock = await ethers.getContractFactory("Raspi");
  const lock = await Lock.deploy();

  await lock.deployed();

  console.log(`${lock.address}`);
}

main().catch((error) => {
  console.error(error);
  process.exitCode = 1;
});
yarn hardhat run scripts/raspi.ts --network localhost
yarn run v1.22.19
$ /home/architectSAP/raspi/node_modules/.bin/hardhat run scripts/raspi.ts --network localhost
0x5FbDB2315678afecb367f032d93F642f64180aa3

I also see that Contract deployment: Raspi is the first block in my local blockchain and how much Gas it used.

  Contract deployment: Raspi
  Contract address:    0x5fbdb2315678afecb367f032d93f642f64180aa3
  Transaction:         0xbd67c6963243a392ecce06e8c3baefd469295f6adb1212fd09907f26756404bc
  From:                0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266
  Value:               0 ETH
  Gas used:            135811 of 135811
  Block #1:            0x5a30a5ae9cbf37838660c4ee41b3df457f7d840b1f6181cdcd1ee4f238e25d93

Send IoT data to local blockchain.

Given my smart contract address, I sent my IoT data to it via Apache Kafka.

import { Kafka } from "kafkajs"
import { ethers } from "hardhat"

const kafka = new Kafka({
    brokers: ["your.kafka.server:9092"],
    clientId: "goerli",
})

const consumer = kafka.consumer({ groupId: "raspi" })

const contractAddress = "0x5fbdb2315678afecb367f032d93f642f64180aa3"

const raspi = async () => {
    const raspi = await ethers.getContractAt("Raspi", contractAddress)
    await consumer.connect()
    await consumer.subscribe({ topic: "bme680", fromBeginning: true })
    await consumer.run({
        eachMessage: async ({ topic, partition, message }) => {
            const obj = JSON.parse(message.value as unknown as string)[0]
            console.log({ pressure: obj.pressure, millis: obj.millis })
            await raspi.set((obj.pressure * 100).toFixed(0))
        },
    })
}

raspi().catch((e) => console.error(e))
yarn hardhat run scripts/set.ts --network localhost
yarn run v1.22.19
$ /home/architectSAP/raspi/node_modules/.bin/hardhat run scripts/set.ts --network localhost
{"level":"INFO","timestamp":"2023-02-11T00:49:53.156Z","logger":"kafkajs","message":"[Consumer] Starting","groupId":"raspi"}
{"level":"INFO","timestamp":"2023-02-11T00:49:57.886Z","logger":"kafkajs","message":"[ConsumerGroup] Consumer has joined the group","groupId":"raspi","memberId":"goerli-d802a384-618e-4d3a-a241-2105df0d1cf1","leaderId":"goerli-d802a384-618e-4d3a-a241-2105df0d1cf1","isLeader":true,"memberAssignment":{"bme680":[0]},"groupProtocol":"RoundRobinAssigner","duration":4727}
{ pressure: 1030.84, millis: '2023-02-12 19:35:01.900606' }

I also see that Contract call: Raspi#set is the second block in my blockchain and how much Gas it used:

  Contract call:       Raspi#set
  Transaction:         0x559c316e94ee8682ac003aabe7cdc0b870e9ed106383937c81f10187ceeb2b16
  From:                0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266
  To:                  0x5fbdb2315678afecb367f032d93f642f64180aa3
  Value:               0 ETH
  Gas used:            43770 of 43770
  Block #2:            0xed8e665c4d0616b6590377370f5b3e655a6032869c17c637fab752f603e64dcc

Read IoT Data from local blockchain.

And read it respectively.

import { ethers } from "hardhat"

let pressure: any

async function main() {
    const contractAddress = "0x5fbdb2315678afecb367f032d93f642f64180aa3"
    const raspi = await ethers.getContractAt("Raspi", contractAddress)
    pressure = await raspi.read()
    console.log({ pressure: pressure / 100 })
}

main().catch((error) => {
    console.error(error)
    process.exitCode = 1
})
yarn hardhat run scripts/read.ts --network localhost
yarn run v1.22.19
$ /home/frank/hh-fcc/raspi/node_modules/.bin/hardhat run scripts/read.ts --network localhost
{ pressure: 1030.84 }

I also see that Contract call: Raspi#read did not alter my blockchain and therefore does not use any Gas.

  Contract call:       Raspi#read
  From:                0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266
  To:                  0x5fbdb2315678afecb367f032d93f642f64180aa3

Conclusion

This blog has been executed on a local blockchain, but the exact same code could be applied to any blockchain.

Sara Sampaio

Sara Sampaio

Author Since: March 10, 2022

0 0 votes
Article Rating
Subscribe
Notify of
0 Comments
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x