A decentralized energy grid management system that connects IoT devices (Tapo P110 smart plugs) to blockchain smart contracts, enabling automatic participation in grid events and token-based rewards.
PowerGrid Network enables:
- Real-time Energy Monitoring - Tapo P110 smart plugs track power consumption
- Automatic Grid Participation - Oracle service automatically participates in grid events
- Token Rewards - Earn PWGD tokens for energy contributions
- On-Chain Verification - All device data and participation recorded on blockchain
- Decentralized Governance - Community-driven network management
Tapo P110 → Oracle Service → Blockchain Contracts → Token Rewards
(IoT) (Python) (ink! Smart Contracts) (PWGD)
Milestone 2 MVP: 100% Complete
- ✅ Real smart plug sending actual data (Tapo P110)
- ✅ Backend service processing and submitting on-chain
- ✅ Smart contracts receiving and storing data
- ✅ Complete flow from device → oracle → contracts → rewards
- ✅ Documented and reproducible
- Prerequisites
- Quick Start
- Local Setup
- Docker Setup (Multi-Architecture)
- Testing
- Complete Demo Flow
- API Documentation
- Troubleshooting
- Project Structure
- Tapo P110 Smart Plug (or compatible Tapo device)
- WiFi Network (device must be connected)
- Computer (Mac/Linux/Windows with Python 3.10+)
- Rust 1.86.0+ with
wasm32-unknown-unknowntarget - cargo-contract v5.0.1+
- substrate-contracts-node v0.42.0+
- Python 3.10+ with virtual environment
- Git
- Docker 20.10+
- Docker Compose 2.0+
- Supports:
linux/amd64(x86_64) andlinux/arm64(Apple Silicon)
1. Start Local Node
~/.local/bin/substrate-contracts-node --dev --tmp --rpc-external --rpc-cors all2. Deploy Contracts → Get Addresses
./scripts/deploy-local.shOutput:
✅ PowerGrid Token deployed
Contract: 5FY8e8RtXKDWdeAhnYcBv7TjojDt6NxJNmX7T1TRrZZSZMyk
✅ Resource Registry deployed
Contract: 5D12ZE2pVZTb3v7RnSMMnf4LPHCAEbcwQWE1TAF9qQiYbFDh
✅ Grid Service deployed
Contract: 5DW1GhTM696DH4vS5n2zj7L6kFG6t4MVipaEnPKygj48TUtX
✅ Governance deployed
Contract: 5HdqtBYTtX8KppCxe4ofkFRFR5XTD8uaVCQkXxYhpxGkrTi5
3. Configure Oracle with Addresses
Edit backend/.env and add the contract addresses:
TOKEN_CONTRACT_ADDRESS=5FY8e8RtXKDWdeAhnYcBv7TjojDt6NxJNmX7T1TRrZZSZMyk
REGISTRY_CONTRACT_ADDRESS=5D12ZE2pVZTb3v7RnSMMnf4LPHCAEbcwQWE1TAF9qQiYbFDh
GRID_SERVICE_CONTRACT_ADDRESS=5DW1GhTM696DH4vS5n2zj7L6kFG6t4MVipaEnPKygj48TUtX
GOVERNANCE_CONTRACT_ADDRESS=5HdqtBYTtX8KppCxe4ofkFRFR5XTD8uaVCQkXxYhpxGkrTi5
# Tapo Device
[email protected]
TAPO_PASSWORD=your-password
TAPO_DEVICE_IP=192.168.1.33 # Your device IP4. Connect Real Tapo P110 Device
Test connection:
cd backend
source venv/bin/activate
python src/tapo_monitor.pyExpected Output:
✅ Connected to P110 (MAC: 8C-86-DD-C7-6D-7C)
⚡ Current Power: 0.00 W
📈 Today's Energy: 0.000 kWh
5. Run Oracle Service
cd backend
source venv/bin/activate
python src/oracle_service.pyExpected Output:
🚀 PowerGrid Oracle Service Starting...
✅ Configuration validated
✅ Tapo device connected
✅ Blockchain connected
✅ Device already registered
📊 Monitoring Iteration #1
⚡ Current Power: 0.00 W
📈 Today's Energy: 0.000 kWh
💰 PWGD Balance: 1000.0000 tokens
# 1. Clone repository
git clone https://github.com/kunal-drall/powergrid_network.git
cd powergrid_network
# 2. Build Docker image (15-30 minutes first time)
docker-compose build
# 3. Start substrate node
docker-compose up -d node
# 4. Run complete E2E test
docker-compose run --rm tester ./scripts/run-e2e-test.sh# Install Rust
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
rustup default 1.86.0
# Add WebAssembly target
rustup target add wasm32-unknown-unknown
# Add rust-src component
rustup component add rust-srccargo install --force --locked cargo-contractmacOS (Apple Silicon):
# Download pre-built binary
cd /tmp
curl -L https://github.com/paritytech/substrate-contracts-node/releases/download/v0.42.0/substrate-contracts-node-mac-universal.tar.gz -o substrate-contracts-node.tar.gz
tar -xzf substrate-contracts-node.tar.gz
cp substrate-contracts-node-mac/substrate-contracts-node ~/.local/bin/
chmod +x ~/.local/bin/substrate-contracts-nodeLinux:
cargo install contracts-node --git https://github.com/paritytech/substrate-contracts-node.git --tag v0.42.0Verify installation:
substrate-contracts-node --version./scripts/build-all.shThis builds all 4 contracts:
powergrid_token- PWGD token contractresource_registry- Device registrationgrid_service- Grid event managementgovernance- DAO governance
cd backend
python3 -m venv venv
source venv/bin/activate # On Windows: venv\Scripts\activate
pip install -r requirements.txtEdit backend/.env:
# Tapo Device Credentials
[email protected]
TAPO_PASSWORD=your-password
TAPO_DEVICE_IP=192.168.1.44 # Your device IP
# Blockchain Configuration
SUBSTRATE_RPC_URL=ws://127.0.0.1:9944
DEVICE_OWNER_SEED=//Alice # Or your custom seed
# Contract Addresses (set after deployment)
TOKEN_CONTRACT_ADDRESS=
REGISTRY_CONTRACT_ADDRESS=
GRID_SERVICE_CONTRACT_ADDRESS=
GOVERNANCE_CONTRACT_ADDRESS=
# Service Configuration
MONITORING_INTERVAL_SECONDS=30
STAKE_AMOUNT=2000000000000000000- linux/amd64 (x86_64) - Intel/AMD processors
- linux/arm64 (ARM64) - Apple Silicon (M1/M2/M3), ARM servers
# Build for ARM64 (Apple Silicon)
docker build --platform linux/arm64 -t powergrid-network:arm64 .
# Build for AMD64 (Intel/AMD)
docker build --platform linux/amd64 -t powergrid-network:amd64 .
# Build for current platform (auto-detect)
docker build -t powergrid-network .The docker-compose.yml is configured for multi-architecture support:
# Build (first time: 15-30 minutes)
docker-compose build
# Start substrate node
docker-compose up -d node
# Run tests in container
docker-compose run --rm tester ./scripts/test-all.sh
# Deploy contracts
docker-compose run --rm tester ./scripts/deploy-local.sh
# Interactive shell
docker-compose run --rm tester bash- node: Substrate contracts node (ws://localhost:9944)
- tester: Interactive container for running tests and scripts
Apple Silicon (M1/M2/M3):
- Docker automatically uses ARM64
- First build compiles substrate from source (~30 minutes)
- Subsequent builds are faster with cache
Intel/AMD:
- Uses x86_64 architecture
- Faster builds with pre-compiled binaries
# Local
./scripts/test-all.sh
# Docker
docker-compose run --rm tester cargo test --workspace# Local (requires running node)
./scripts/test-integration.sh
# Docker
docker-compose run --rm tester ./scripts/test-integration.sh# Complete system test
./scripts/run-e2e-test.sh
# This tests:
# - Node connectivity
# - Contract deployment
# - Device registration
# - Tapo connection
# - Event creation
# - Oracle servicecd backend
source venv/bin/activate
python src/tapo_monitor.pycd backend
source venv/bin/activate
python src/blockchain_client.pyLocal:
~/.local/bin/substrate-contracts-node --dev --tmp --rpc-external --rpc-cors allDocker:
docker-compose up -d node./scripts/deploy-local.shImportant: Copy contract addresses from output and update backend/.env.
cd backend
source venv/bin/activate
python scripts/setup_authorization.pyThis authorizes:
- Oracle service on Grid Service contract
- Grid Service as minter on Token contract
cd backend
source venv/bin/activate
python src/oracle_service.pyThe oracle will:
- ✅ Connect to Tapo device
- ✅ Connect to blockchain
- ✅ Register device (first run)
- ✅ Start monitoring every 30 seconds
cd backend
source venv/bin/activate
python scripts/create_test_event.pyOr use bash script:
./scripts/create-grid-event.sh DemandResponse 60 750000000000000000 100# View live logs
tail -f backend/logs/oracle.logWhen device consumes energy:
📊 Monitoring Iteration #5
⚡ Current Power: 150.50 W
📈 Today's Energy: 0.125 kWh
📢 Found 1 active event(s)
🎯 Event 1: DemandResponse
✅ Participated with 125 Wh
💰 PWGD Balance: 1000.0938 tokens
cd backend
source venv/bin/activate
python scripts/check-rewards.pyRun everything at once:
./scripts/demo-full-flow.shLocation: backend/src/tapo_monitor.py
Methods:
async connect()- Connect to Tapo deviceasync get_current_power()- Get current power consumption (W)async get_energy_usage()- Get energy usage (kWh)async get_device_info()- Get device informationasync get_complete_snapshot()- Get all device data
Example:
from tapo_monitor import TapoMonitor
monitor = TapoMonitor(email, password, device_ip)
await monitor.connect()
snapshot = await monitor.get_complete_snapshot()
print(f"Current Power: {snapshot['current_power']['power_watts']} W")Location: backend/src/blockchain_client.py
Methods:
connect()- Connect to Substrate nodeload_contracts()- Load all contract instancesis_device_registered()- Check device registrationregister_device()- Register device on blockchainget_active_events()- Get active grid eventsparticipate_in_event()- Participate in grid eventget_token_balance()- Get PWGD token balanceget_device_reputation()- Get device reputation
Example:
from blockchain_client import BlockchainClient
client = BlockchainClient(rpc_url, seed_phrase)
client.connect()
client.load_contracts(token_addr, registry_addr, grid_addr, gov_addr)
is_reg = client.is_device_registered()
events = client.get_active_events()Location: backend/src/oracle_service.py
Main Service:
- Automatic device registration
- Real-time energy monitoring
- Automatic event participation
- Token reward tracking
Run:
python src/oracle_service.pyContract: contracts/token/
Key Methods:
balance_of(owner)- Get token balancetransfer(to, value)- Transfer tokensmint(account, amount)- Mint tokens (minter only)add_minter(account)- Grant minter role (admin only)
Contract: contracts/resource_registry/
Key Methods:
register_device(metadata, stake)- Register deviceis_device_registered(account)- Check registrationget_device_reputation(account)- Get reputation score
Contract: contracts/grid_service/
Key Methods:
create_grid_event(type, duration, rate, target)- Create eventparticipate_in_event(event_id, energy)- Participateget_active_events()- Get active eventsadd_authorized_caller(caller)- Authorize caller (owner only)
Contract: contracts/governance/
Key Methods:
create_proposal(type, description)- Create proposalvote(proposal_id, support)- Vote on proposalexecute_proposal(proposal_id)- Execute proposal
Symptoms:
❌ Failed to connect to Tapo device: Connection refused
Solutions:
- Check device IP in
backend/.env - Verify device is powered on and connected to WiFi
- Test connection:
python src/tapo_monitor.py - Update IP if device changed networks
- Check Tapo app to confirm device is online
Symptoms:
❌ Failed to connect to blockchain
Solutions:
- Verify node is running:
curl http://localhost:9944 - Check
SUBSTRATE_RPC_URLinbackend/.env - Restart node if needed
- For Docker: Ensure
docker-compose up nodeis running
Symptoms:
❌ Failed to load contracts
Solutions:
- Verify contracts are deployed:
./scripts/deploy-local.sh - Check contract addresses in
backend/.env - Ensure node is running and synced
- Rebuild contracts:
./scripts/build-all.sh
Symptoms:
⚠️ No energy contribution to report yet
Solutions:
- Plug something into Tapo device (must consume power)
- Wait for next monitoring cycle (30 seconds)
- Check that grid event is active
- Verify device is registered
- Check logs:
tail -f backend/logs/oracle.log
Symptoms:
❌ Unauthorized caller
Solutions:
- Run authorization setup:
python scripts/setup_authorization.py - Verify owner account has permissions
- Check contract owner is correct
- Note: Owner account can always create events
Symptoms:
error: could not compile rococo-runtime
Solutions:
- Ensure Docker has enough resources (4GB+ RAM)
- Build for correct platform:
--platform linux/arm64or--platform linux/amd64 - Clear Docker cache:
docker system prune -a - Check Dockerfile for correct Rust version (1.86.0)
Apple Silicon:
- Use
--platform linux/arm64explicitly - First build takes 30+ minutes (compiles from source)
- Ensure Docker Desktop is updated
Intel/AMD:
- Use
--platform linux/amd64explicitly - Faster builds with pre-compiled binaries
powergrid_network/
├── backend/ # Python oracle service
│ ├── src/
│ │ ├── oracle_service.py # Main oracle service
│ │ ├── blockchain_client.py # Blockchain integration
│ │ └── tapo_monitor.py # Tapo device integration
│ ├── config/
│ │ ├── config.py # Configuration management
│ │ └── abis/ # Contract ABIs
│ ├── scripts/
│ │ ├── create_test_event.py # Create grid events
│ │ ├── check-rewards.py # Check token balance
│ │ └── setup_authorization.py # Setup permissions
│ └── requirements.txt # Python dependencies
├── contracts/ # ink! smart contracts
│ ├── token/ # PWGD token contract
│ ├── resource_registry/ # Device registration
│ ├── grid_service/ # Grid event management
│ └── governance/ # DAO governance
├── scripts/ # Build and deployment scripts
│ ├── setup.sh # Initial setup
│ ├── build-all.sh # Build all contracts
│ ├── deploy-local.sh # Deploy contracts
│ ├── test-all.sh # Run unit tests
│ ├── run-e2e-test.sh # End-to-end test
│ └── demo-full-flow.sh # Complete demo
├── Dockerfile # Multi-architecture Docker image
├── docker-compose.yml # Docker Compose configuration
└── README.md # This file
./scripts/setup.sh- Install all dependencies./scripts/build-all.sh- Build all contracts./scripts/test-all.sh- Run unit tests./scripts/test-integration.sh- Run integration tests
./scripts/deploy-local.sh- Deploy all contracts locally./scripts/start-node-and-deploy.sh- Start node and deploy
./scripts/demo-full-flow.sh- Complete system check./scripts/create-grid-event.sh- Create grid event (bash)./scripts/run-e2e-test.sh- End-to-end integration test
backend/scripts/create_test_event.py- Create grid event (Python)backend/scripts/check-rewards.py- Check token balancebackend/scripts/setup_authorization.py- Setup contract permissions
Backend (backend/.env):
TAPO_EMAIL- Tapo account emailTAPO_PASSWORD- Tapo account passwordTAPO_DEVICE_IP- Device IP addressSUBSTRATE_RPC_URL- Blockchain RPC endpointDEVICE_OWNER_SEED- Account seed phraseTOKEN_CONTRACT_ADDRESS- Token contract addressREGISTRY_CONTRACT_ADDRESS- Registry contract addressGRID_SERVICE_CONTRACT_ADDRESS- Grid Service contract addressGOVERNANCE_CONTRACT_ADDRESS- Governance contract addressMONITORING_INTERVAL_SECONDS- Oracle monitoring interval (default: 30)STAKE_AMOUNT- Device registration stake (default: 2 tokens)
Contracts are configured via constructor arguments during deployment. See scripts/deploy-local.sh for details.
- Create contract in
contracts/your_contract/ - Add to workspace
Cargo.toml - Build:
cd contracts/your_contract && cargo contract build --release - Deploy: Add to
scripts/deploy-local.sh - Add ABI to
backend/config/abis/ - Load in
blockchain_client.py
- Update contract code in
contracts/ - Rebuild contracts:
./scripts/build-all.sh - Update backend if needed:
backend/src/ - Test:
./scripts/test-all.sh - Deploy:
./scripts/deploy-local.sh
- Fork the repository
- Create a feature branch
- Make your changes
- Run tests:
./scripts/test-all.sh - Submit a pull request
See LICENSE file for details.
For issues or questions:
- Check Troubleshooting section
- Review logs:
backend/logs/oracle.log - Check contract events on blockchain explorer
Device Connection:
INFO:__main__:✅ Connected to P110 (MAC: 8C-86-DD-C7-6D-7C)
INFO:__main__:⚡ Current Power: 45.20 W
INFO:__main__:📈 Today's Energy: 0.125 kWh
✅ Device connecting - Real Tapo P110 sending actual data
Blockchain Transactions:
✅ Test event created successfully!
Transaction: 0x735dd73e97f71384d75c457cea18f3de67797d5ed7a9ae3f40e0fbec52cfd8db
Block: 0xfe119dd155d9f12bc29508c96ae4b5ec74ac3bb054dfc25aebb43b4c24584a6e
✅ Blockchain transactions - All operations recorded on-chain
Participation Recorded:
INFO:__main__:📢 Found 1 active event(s)
INFO:__main__:🎯 Event 1: DemandResponse
INFO:__main__:✅ Participated with 125 Wh
✅ Participation recorded - Oracle automatically participates
Rewards Distributed:
INFO:__main__:💰 PWGD Balance: 1000.0938 tokens
✅ Rewards distributed - Token balance increases after participation
Cycle 1:
📊 Monitoring Iteration #1
⚡ Current Power: 0.00 W
📈 Today's Energy: 0.000 kWh
💰 PWGD Balance: 1000.0000 tokens
Cycle 2 (With Energy):
📊 Monitoring Iteration #3
⚡ Current Power: 45.20 W
📈 Today's Energy: 0.125 kWh
✅ Participated with 125 Wh
💰 PWGD Balance: 1000.0938 tokens
Device Registration:
- Before:
Device registered: False - After:
Device registered: True✅
Token Balance:
- Before:
1000.0000 tokens - After:
1000.0938 tokens(+0.0938 tokens) ✅
Active Events:
- Created:
Event ID: 1, Type: DemandResponse✅ - Detected:
Found 1 active event(s)✅
See docs/TEST_RESULTS.md for complete evidence and test results.
✅ Milestone 2 MVP: 100% Complete and Verified
- ✅ Real hardware integration (Tapo P110) - Verified with actual device
- ✅ Complete data pipeline - Tested with real power readings
- ✅ Blockchain integration - All transactions verified on-chain
- ✅ Automatic event participation - Confirmed with multiple cycles
- ✅ Token reward system - Rewards distributed and tracked
- ✅ Multi-architecture support - ARM64 and x86_64 tested
- ✅ Comprehensive documentation - Complete setup and testing guides
Ready for production deployment and scaling!