-
1Step 1
The first step is to install an Ethereum client and configure a local blockchain on the Raspberry Pi 3.
We chose Parity as a Ethereum client because of the features offered and its interface facilitating its use.Parity installation
An image is available with Parity and Geth (another Ethereum client) :
➡ http://ethraspbian.com/downloads/image_2017-04-19-EthRaspbian-parity-1.6.6-lite.zip
(see GitHub repository: diglos/pi-gen for more informations).
This image is compatible with Raspberry Pi 2 and 3 and runs Parity Ethereum client as a boot service (full Ethereum node).After turning on the Raspberry Pi, disable the Parity service for now:
$ sudo systemctl stop parity $ sudo systemctl disable parity Removed symlink /etc/systemd/system/multi-user.target.wants/parity.service.
And update/upgrade Raspbian:$ sudo aptitude update && sudo aptitude upgrade
Parity configuration
Parity can be easily configure through a configuration file:
➡ https://github.com/paritytech/parity/wiki/Configuring-Parity#config-fileFor testing purposes and due to ressources limitations, a private/local blockchain will be set up with Proof-of-Authority consensus engine, for this version of DAISEE prototype :
[Proof-of-Authority] does not depend on nodes solving arbitrarily difficult mathematical problems, but instead uses a hard-configured set of "authorities" - nodes that are explicitly allowed to create new blocks and secure the blockchain. This makes it easier to maintain a private chain and keep the block issuers accountable.
All steps for setting up a local blockchain with Proof-of-Authority are described here:
➡ Demo PoA tutorialAfter following the tutorial, here are the differents files used for one node of the prototype:
- blockchain specifications (demo-spec.json):
{ "name": "DemoPoA", "engine": { "authorityRound": { "params": { "gasLimitBoundDivisor": "0x400", "stepDuration": "5", "validators" : { "list": [ "0x00Bd138aBD70e2F00903268F3Db08f2D25677C9e", "0x00Aa39d30F0D20FF03a22cCfc30B7EfbFca597C2", "0x002e28950558fbede1a9675cb113f0bd20912019" ] } } } }, "params": { "maximumExtraDataSize": "0x20", "minGasLimit": "0x1388", "networkID" : "0x2323" }, "genesis": { "seal": { "authorityRound": { "step": "0x0", "signature": "0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" } }, "difficulty": "0x20000", "gasLimit": "0x5B8D80" }, "accounts": { "0x0000000000000000000000000000000000000001": { "balance": "1", "builtin": { "name": "ecrecover", "pricing": { "linear": { "base": 3000, "word": 0 } } } }, "0x0000000000000000000000000000000000000002": { "balance": "1", "builtin": { "name": "sha256", "pricing": { "linear": { "base": 60, "word": 12 } } } }, "0x0000000000000000000000000000000000000003": { "balance": "1", "builtin": { "name": "ripemd160", "pricing": { "linear": { "base": 600, "word": 120 } } } }, "0x0000000000000000000000000000000000000004": { "balance": "1", "builtin": { "name": "identity", "pricing": { "linear": { "base": 15, "word": 3 } } } }, "0x004ec07d2329997267Ec62b4166639513386F32E": { "balance": "10000000000000000000000" } } }
3 validators are defined
- config.toml
[parity] chain = "/home/pi/demo-spec.json" base_path = "/home/pi/parity/" [network] port = 30300 bootnodes = ["enode://ff14ae0a273e08ffbbe20b4b398460eb471e23f1b4301ce46b92a86ad420f67b9b470d097f1939fa7b9b2aae7d24e72cf7c63fe67217bdf3fd6cb60bbb7ecc59@192.168.0.47:30300"] discovery = false [rpc] disable = false interface = "192.168.0.15" port = 8545 cors = "*" apis = ["web3", "eth", "net", "personal", "parity", "parity_set", "traces", "rpc", "parity_accounts"] [ui] force = false disable = false port = 8180 interface = "192.168.0.15" path = "/home/pi/parity/signer/" [dapps] port = 8088 [account] password = ["node.pwds"] [mining] engine_signer = "0x002e28950558fbede1a9675cb113f0bd20912019" reseal_on_txs = "none"
exemple of a config file for one node
- Running Parity
$ parity
- Adding a node
Since the blockchain is private/locale, adding a node can be done with the configuration file in Network part.
[network] bootnodes = ["enode://ff14ae0a273e08ffbbe20b4b398460eb471e23f1b4301ce46b92a86ad420f67b9b470d097f1939fa7b9b2aae7d24e72cf7c63fe67217bdf3fd6cb60bbb7ecc59@192.168.0.47:30300"] discovery = false
The Public node Node is displayed on Parity Client launch. It can also be found on Parity UI, in Status tab:- In the case where a new validator node is added, after modifying lists of validators, the following message may appear during blocks import:
Error: Engine(NotProposer(Mismatch { expected: 00aa39d30f0d20ff03a22ccfc30b7efbfca597c2, found: 00bd138abd70e2f00903268f3db08f2d25677c9e }))
The workaround is to modify the chain specifications to revert to the precedent version, until a new error message.
Exemple:Only 3 blocks are imported with the last version of chain-specs.json (3 validators). In order to import the next blocks, the last validator is removed from chain specs, and blocks are imported until block #55. After this message, using the last version of chain specs (with the 3 validators) allows to import the full blockchain.
The best solution would be to add the new validator account only after importing the full blockchain on the node. -
2Step 2
Smart-contracts
The energy data and exchanges are stored on the blockchain thanks to 2 smart-contracts (in Solidity):
-
token.sol
This is the smart-contract described in the tutorial "Create your own crypto-currency".
It allows to create a token, according to the ERC20 Token Standard. -
daisee.sol
The current version allows to :- store energy data on blockchain (consumption and production),
- make transactions between peers, using tokens.
For now, the rules that trigger transactions are not implemented in a smart contract. Note: the smart contract is still under development, the code may change (see Issues).
To deploy the smart contracts, connect to the Parity UI.
In Contracts Tab, after clicking on "DEVELOP" button, paste the token smart contract code for the token and compile:With Parity UI, the smart contract can be easily deployed ("DEPLOY" button):
Deploy the Daisee smart-contract:
The two smart-contract now appear in Contracts tab:Note: the current version of DAISEE smart contract allows to update consumption and production directly (without connexion to a sensor):
-
token.sol
-
3Step 3
Interface
To view data, a Web interface communicates with the local node, through Web3 JavaScript API, using web3.js.Tutorial source:
➡ A simple smart contract Web UI using web3.jsThe microframework Flask allows to display the interface from a Raspberry Pi node.
The current version displays Ethereum transactions and realtime data from the energy monitoring application
- install the requirements
$ sudo aptitude install git $ sudo pip3 install flask pyyaml
- clone the repository
$ git clone https://github.com/DAISEE/DApp-v2.git
- create the configuration file (config.yml) from the example and complete it:
Type Field Description contracts
daisee Daisee.sol address on the blockchain
token DaiseeCoin smart-contract address on the blockchain user
login login for UI
pwd hashed password for the UI*
coinbase user address
type type of node ('C' for consumer, 'P' for producer). Not Used
url url of energy monitoring application**
sensorId url of energy monitoring application
sensorLogin login for energy monitoring application
sensorPassword password for energy monitoring application
sensorSource energy monitoring application : 'CW'
for citizenWatt (only app supported for now)
sensorPort if necessary, port of energy monitoring application, example : ':8080'
still under development, it may change
* to obtain the hashed password, use 'url/hash/<password>' after running the server
- run the server
$ cd dapp $ export FLASK_APP=server.py $ python3 -m flask run --host=0.0.0.0
-
4Step 4
CitizenWatt Application
CitizenWatt is an open source and open hardware sensor. It is associated with a Python application, that runs on a Raspberry Pi 1. Data are stored locally and exposed through an API.
The original sources are here:
➡ Sensor : https://github.com/CitoyensCapteurs/CitizenWatt-sensor
➡ Application : https://github.com/CitoyensCapteurs/CitizenWatt-BaseCitizenWatt application has been modified to run on a Rapsberry Pi 3 and to work with other types of sensors:
➡ https://github.com/DAISEE/CitizenWatt-Base-RPI3For now, several branches are available:
‣ master (works with CitizenWatt sensor, through NRF24, not used for this prototype),
‣ smartplug (works with AWOX Smartplug, through bluetooth, not used for this prototype),
‣ ina291 (works with INA219 sensor, directly connected to Raspberry Pi),
‣ acs712 (works with an ACS 712-based sensor connected to an Arduino).Prerequisites to connections to the sensors
INA219- Activate I²C in Interfacing Options
$ sudo raspi-config
- Connections:
Source:
➡ http://www.rototron.info/raspberry-pi-ina219-tutorial/AS712-based sensor
- Arduino:
Upload the following code on an Arduino: sensor_acs712.ino - Connections between sensor and Arduino:
Source:
➡ [FR] http://wiki.mchobby.be/index.php?title=SENSEUR-COURANT-ACS712#BrancherAplication installation
- Python3 and packages installation
$ git clone https://github.com/DAISEE/CitizenWatt-Base-RPI3.git $ sudo mv CitizenWatt-Base-RPI3/ /opt/citizenwatt/ $ cd /opt/citizenwatt/ $ sudo bash system/install_req.sh
- citizenwatt-visu compilation
$ dpkg-deb --build citizenwatt-visu $ sudo dpkg -i citizenwatt-visu.deb
- Database creation
$ sudo -u postgres psql [sudo] password for debian: psql (9.4.9) Type "help" for help. postgres-# CREATE DATABASE citizenwatt; postgres-# CREATE USER citizenwatt PASSWORD 'citizenwatt'; postgres-# GRANT ALL ON DATABASE citizenwatt TO citizenwatt; postgres-# exit postgres-#
- Firewall configuration
$ sudo iptables -t nat -A PREROUTING -p tcp --dport 80 -j DNAT --to-destination :8080 $ sudo netfilter-persistent save
- (Additional steps) for INA219 sensor
$ sudo pip3 install pi-ina219 pyserial
Application
For testing, all programs are launched manually.
$ python3 receive.py $ python3 process.py $ python3 visu.py
To launch these programs automatically, use the supervisor:
$ cd /opt/citizenwatt/system $ mv supervisor_citizenwatt.conf /etc/supervisor/conf.d/supervisor_citizenwatt.conf
After launching the server, the application will be available locally (see hostname or ip).
Complete the configuration:
If a sensor is connected and configured, data will be displayed in the "CONSO" tab:
Data are available through an API.
Example:
- /api/<sensor:int>/get/<watt_euros:watts|kwatthours|euros>/by_time/<time1:float>/<time2:float>
Returns measures between timestamps <time1> and <time2> from sensor <sensor> in watts or euros.
-
5Step 5
Energy transactions
For this version of this version of the prototype, we have:
- a Raspberry Pi connected to a battery (= "Node 1" = "consumer")
- a Raspberry Pi connected to a solar panel and a battery (= "Node 2" = "producer")
- a Raspberry Pi controlling a relay, allowing to switch the energy source
On each node (consumer and producer), the CitizenWatt application, an Ethereum client and the Daisee App are running. In order to allow for energy exchanges, additional python scripts are required:
➡ https://github.com/DAISEE/ScriptsInstallation
Clone the repository on each Raspberry Pi:
$ git clone https://github.com/DAISEE/Scripts.git
Relay
- After connecting the relay to the Raspberry Pi (see the tutorial on Sunfounder Wiki), connect the node 1 energy source to the first channel (= channel 0) and the node 2 energy source to the second channel (= channel 1).
- Install RPI.GPIO library:
$ pip3 install RPi.GPIO pyyaml
- Run the following script:
$ python3 scripts/server_relay.py
The others nodes can interact with the relay through sockets (port: 15555).
Producer and consumer nodes
- To interact with the Ethereum blockchain, the web3.py library, a python implementation of web3.js, is used.
$ pip3 install web3
- create the parameter file (
parameters.yml
) from the example and complete it:
Type Field Description contracts
daisee Daisee.sol address on the blockchain
token DaiseeCoin smart-contract address on the blockchain
node url of Ethereum client node
address Ethereum account
accountpswd Ethereum account password
url url of the monitoring application (should be the same as Ethereum client)
id id of the sensor (on the monitoring app)
type type of node ('C' for consumer, 'P' for producer).
login login for energy monitoring application
password password for energy monitoring application
limit threshold from which the exchange is triggered
delta quantity of energy to buy
channel relay channel
fuelgauge if the battery state of charge is monitored (Boolean) sellers
sellern part to duplicate, with the Ethereum account and channel of the seller (where n is the seller number) relay
host Ip of the rapsberry pi controlling the relay
port socket port (15555) exemple:
contract: address: '0xc33179A7f73fCcCe0DED8e613Fcf2688bA385558' token: '0xdFf8C10F1E64B592cF902e82C948E2ddF9f49aaF' node: '192.168.0.10' node: address: '0x004ec07d2329997267ec62b4166639513386f32e' accountpswd: 'password1' url: 'http://192.168.0.10:8080' sensorId: 1 typ: 'C' login: 'user' password: 'password2' limit: 20 delta: 200 channel: 0 fuelgauge: False sellers: seller1: account: '0x00625a1a269ac76c7c7b98939b5e60916fd41070' channel: 1 relay: host: '192.168.0.50' port: 15555
Running scripts
The script
client_interaction.py
allows to update energy data on the Blockchain from data exposed by CitizenWatt API and triggers energy exchanges.Producer node
Just run the script:
$ python3 scripts/client_interaction.py
The transactions are displayed on the DAISEE App:
Consumer node
- To allow energy exchange, the consumer must have some tokens.
If not, transfer some tokens via the Parity UI (functionTransfer
of the Token contract): - Moreover, it is necessary that the Daisee contract can transfer these tokens to the energy Producer at the time of the purchase.
- Function
Approve
of the Token contract: - After validation of the transaction, the allowance is updated:
- Function
Note: to avoid to update the allowance before buying energy, the token contract offers the function
approveAndCall
. This function is not yet used in this version of the prototype.- Data displayed on the DAISEE App
- Run the script
$ python3 scripts/client_interaction.py
- Data displayed on the DAISEE App after running the script:
As long as the battery charge is greater than the threshold, Node 1 consumes the energy of its own battery (blocks 728 to 731).
Once the battery charge has fallen below the threshold, Node 1 buys energy (block 732) and consumes power from Node 2 battery (blocks 733 to 735).
The table "Purchased energy" shows the energy consumed compared to the energy purchased.
Discussions
Become a Hackaday.io Member
Create an account to leave a comment. Already have an account? Log In.