aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWei-Ning Huang <w@dexon.org>2019-01-22 01:52:28 +0800
committerWei-Ning Huang <w@dexon.org>2019-01-22 11:31:04 +0800
commit712ac399081339fbbe6cd652950e8e07a6ad0e9b (patch)
tree265be6f6d87d8bb48655ea0af9b8e92623b94268
parent5dce4114bf8750e9e15696600f1711830877ba96 (diff)
downloaddexon-iot-firmware-pio-712ac399081339fbbe6cd652950e8e07a6ad0e9b.tar
dexon-iot-firmware-pio-712ac399081339fbbe6cd652950e8e07a6ad0e9b.tar.gz
dexon-iot-firmware-pio-712ac399081339fbbe6cd652950e8e07a6ad0e9b.tar.bz2
dexon-iot-firmware-pio-712ac399081339fbbe6cd652950e8e07a6ad0e9b.tar.lz
dexon-iot-firmware-pio-712ac399081339fbbe6cd652950e8e07a6ad0e9b.tar.xz
dexon-iot-firmware-pio-712ac399081339fbbe6cd652950e8e07a6ad0e9b.tar.zst
dexon-iot-firmware-pio-712ac399081339fbbe6cd652950e8e07a6ad0e9b.zip
BLE wifi and contract deployment working
-rw-r--r--.gitignore6
-rw-r--r--.travis.yml67
-rw-r--r--.vscode/extensions.json7
-rw-r--r--.vscode/tasks.json14
-rw-r--r--partitions_singleapp.csv5
-rw-r--r--platformio.ini8
-rw-r--r--src/main.cpp275
7 files changed, 339 insertions, 43 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..2de98ab
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,6 @@
+.pio
+.pioenvs
+.piolibdeps
+.vscode/.browse.c_cpp.db*
+.vscode/c_cpp_properties.json
+.vscode/launch.json
diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 0000000..7c486f1
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,67 @@
+# Continuous Integration (CI) is the practice, in software
+# engineering, of merging all developer working copies with a shared mainline
+# several times a day < https://docs.platformio.org/page/ci/index.html >
+#
+# Documentation:
+#
+# * Travis CI Embedded Builds with PlatformIO
+# < https://docs.travis-ci.com/user/integration/platformio/ >
+#
+# * PlatformIO integration with Travis CI
+# < https://docs.platformio.org/page/ci/travis.html >
+#
+# * User Guide for `platformio ci` command
+# < https://docs.platformio.org/page/userguide/cmd_ci.html >
+#
+#
+# Please choose one of the following templates (proposed below) and uncomment
+# it (remove "# " before each line) or use own configuration according to the
+# Travis CI documentation (see above).
+#
+
+
+#
+# Template #1: General project. Test it using existing `platformio.ini`.
+#
+
+# language: python
+# python:
+# - "2.7"
+#
+# sudo: false
+# cache:
+# directories:
+# - "~/.platformio"
+#
+# install:
+# - pip install -U platformio
+# - platformio update
+#
+# script:
+# - platformio run
+
+
+#
+# Template #2: The project is intended to be used as a library with examples.
+#
+
+# language: python
+# python:
+# - "2.7"
+#
+# sudo: false
+# cache:
+# directories:
+# - "~/.platformio"
+#
+# env:
+# - PLATFORMIO_CI_SRC=path/to/test/file.c
+# - PLATFORMIO_CI_SRC=examples/file.ino
+# - PLATFORMIO_CI_SRC=path/to/test/directory
+#
+# install:
+# - pip install -U platformio
+# - platformio update
+#
+# script:
+# - platformio ci --lib="." --board=ID_1 --board=ID_2 --board=ID_N
diff --git a/.vscode/extensions.json b/.vscode/extensions.json
new file mode 100644
index 0000000..8281e64
--- /dev/null
+++ b/.vscode/extensions.json
@@ -0,0 +1,7 @@
+{
+ // See http://go.microsoft.com/fwlink/?LinkId=827846
+ // for the documentation about the extensions.json format
+ "recommendations": [
+ "platformio.platformio-ide"
+ ]
+} \ No newline at end of file
diff --git a/.vscode/tasks.json b/.vscode/tasks.json
new file mode 100644
index 0000000..c4f0974
--- /dev/null
+++ b/.vscode/tasks.json
@@ -0,0 +1,14 @@
+{
+ // See https://go.microsoft.com/fwlink/?LinkId=733558
+ // for the documentation about the tasks.json format
+ "version": "2.0.0",
+ "tasks": [
+ {
+ "type": "PlatformIO",
+ "task": "Upload and Monitor",
+ "problemMatcher": [
+ "$platformio"
+ ]
+ }
+ ]
+} \ No newline at end of file
diff --git a/partitions_singleapp.csv b/partitions_singleapp.csv
new file mode 100644
index 0000000..e31cbb8
--- /dev/null
+++ b/partitions_singleapp.csv
@@ -0,0 +1,5 @@
+# Name, Type, SubType, Offset, Size, Flags
+# Note: if you change the phy_init or app partition offset, make sure to change the offset in Kconfig.projbuild
+nvs, data, nvs, , 0x6000,
+phy_init, data, phy, , 0x1000,
+factory, app, factory, , 2M,
diff --git a/platformio.ini b/platformio.ini
index 2b8a820..c3de9d3 100644
--- a/platformio.ini
+++ b/platformio.ini
@@ -15,7 +15,11 @@ framework = arduino
upload_port=/dev/cu.SLAB_USBtoUART
monitor_port=/dev/cu.SLAB_USBtoUART
monitor_speed = 115200
+board_build.partitions = partitions_singleapp.csv
+
+build_flags =
+ -DCORE_DEBUG_LEVEL=3
lib_deps =
- DEXON-Web3E \
- WebSockets \ No newline at end of file
+ WebSockets
+ #DEXON-Web3E \ No newline at end of file
diff --git a/src/main.cpp b/src/main.cpp
index 449f940..381c12b 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -2,54 +2,171 @@
#include <Web3.h>
#include <Util.h>
#include <Contract.h>
+#include <WebSocketsClient.h>
+#include <BLEDevice.h>
+#include <BLEUtils.h>
+#include <BLEServer.h>
+#include "cJSON/cJSON.h"
-const char *ssid = "COBINHOOD_Guest";
-const char *password = "COB0921592018";
#define MY_ADDRESS "0xBF8C48A620bacc46907f9B89732D25E47A2D7Cf7"
#define RPC_HOST "api-testnet.dexscan.app"
#define RPC_PATH "/v1/network/rpc"
-#define CONTRACT_ADDRESS "0x109dc2e0964e114f03e9ce3348912b3e925b42f2"
#define DEXSCAN_TX "https://testnet.dexscan.app/transaction/"
-#define LED_PIN 5
+#define CONTRACT_BYTECODE "608060405234801561001057600080fd5b506040516020806102c18339810180604052602081101561003057600080fd5b8101908080519060200190929190505050806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050610230806100916000396000f3fe608060405260043610610051576000357c01000000000000000000000000000000000000000000000000000000009004806329c15b71146100565780638da5cb5b14610093578063b70c5e75146100ea575b600080fd5b34801561006257600080fd5b506100916004803603602081101561007957600080fd5b81019080803515159060200190929190505050610119565b005b34801561009f57600080fd5b506100a86101cc565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b3480156100f657600080fd5b506100ff6101f1565b604051808215151515815260200191505060405180910390f35b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614151561017457600080fd5b80600060146101000a81548160ff0219169083151502179055507fb87f936dd029fdc50266e531c100fb6f7e2b1f385e524eb8a736753539fc25e881604051808215151515815260200191505060405180910390a150565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600060149054906101000a900460ff168156fea165627a7a72305820dbabb9ae82b801b172e87e23029ddd8e141dae86ef80989dc133d77da6bb987c0029"
+
+// BLE
+#define SERVICE_UUID "4fafc201-1fb5-459e-8fcc-c5c9c331914b"
+#define WIFI_CHARACTERISTIC_UUID "beb5483e-36e1-4688-b7f5-ea07361b26a8"
+#define OWNER_CHARACTERISTIC_UUID "f925981a-7be4-45af-9b61-23979364a0e2"
+#define CONTRACT_ADDRESSS_CHARACTERISTIC_UUID "25f656a8-89db-4d94-a5d3-1da16c10fa3e"
-// Copy/paste the private key from MetaMask in here
-const char *PRIVATE_KEY = "FA30B47A7A3D5AB6935D873FFAEB8CA5B9782D102C4094BE6DA6B7F2FC04B5BD"; //32 Byte Private key
+#define PRIVATE_KEY "FA30B47A7A3D5AB6935D873FFAEB8CA5B9782D102C4094BE6DA6B7F2FC04B5BD" //32 Byte Private key
+
+#define LED_PIN 5
int wificounter = 0;
+
+WebSocketsClient webSocket;
Web3 web3(RPC_HOST, RPC_PATH);
-void setup_wifi();
-void PushERC20Transaction();
-void sendEthToAddress(double eth, const char *destination);
-void queryERC875Balance(const char *userAddress);
-double queryAccountBalance(const char *address);
+enum State {
+ STATE_INIT = 0,
+ STATE_WIFI_CONNECTED,
+ STATE_CONTRACT_DEPLOYED,
+ STATE_WS_CONNECTED,
+ STATE_LOGS_SUBSCRIBED,
+};
-void setup() {
- Serial.begin(115200);
+State state;
+
+std::string contractAddress;
+std::string ownerAddress;
- setup_wifi();
+BLECharacteristic *pContractAddressCharacteristic;
+
+void on_websocket_event(WStype_t type, uint8_t * payload, size_t length) {
+ switch (type) {
+ case WStype_CONNECTED:
+ {
+ Serial.println("Websocket connected.");
+
+ string req = std::string("{\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"eth_subscribe\",\"params\":[\"logs\",{\"address\":\"") +
+ contractAddress +
+ std::string("\",\"topics\":[\"0xb87f936dd029fdc50266e531c100fb6f7e2b1f385e524eb8a736753539fc25e8\"]}]}");
+
+ webSocket.sendTXT(req.c_str());
+ break;
+ }
+ case WStype_DISCONNECTED:
+ Serial.println("Websocket disconnected.");
+ break;
+ case WStype_TEXT:
+ {
+ int status;
+ if (state < STATE_LOGS_SUBSCRIBED) {
+ Serial.println((const char*) payload);
+ state = STATE_LOGS_SUBSCRIBED;
+ break;
+ }
+ Serial.println((const char*)payload);
+ cJSON *root = NULL, *params = NULL, *result = NULL, *data = NULL;
+ root = cJSON_Parse((const char*)payload);
+ if (root == NULL) {
+ goto cleanup;
+ }
+ params = cJSON_GetObjectItem(root, "params");
+ if (params == NULL) {
+ Serial.println("get params error");
+ goto cleanup;
+ }
+ result = cJSON_GetObjectItem(params, "result");
+ if (result == NULL) {
+ Serial.println("get data error");
+ goto cleanup;
+ }
+ data = cJSON_GetObjectItem(result, "data");
+ if (data == NULL) {
+ Serial.println("get data error");
+ goto cleanup;
+ }
+ status = strtol(data->valuestring, nullptr, 16);
+ Serial.printf("Status: %d\n", status);
+ digitalWrite(LED_PIN, status);
+cleanup:
+ if (root != NULL)
+ cJSON_free(root);
+ if (params != NULL)
+ cJSON_free(params);
+ if (result != NULL)
+ cJSON_free(result);
+ if (data != NULL)
+ cJSON_free(data);
+ break;
+ }
+ default:
+ Serial.printf("unhandled event: %d\n", type);
+ }
}
+std::string deploy_contract(std::string owner) {
+ Contract contract(&web3, "");
+ contract.SetPrivateKey(PRIVATE_KEY);
-void loop() {
- Contract contract(&web3, CONTRACT_ADDRESS);
+ std::string address = MY_ADDRESS;
+ uint32_t nonceVal = (uint32_t)web3.EthGetTransactionCount(&address);
+ unsigned long long gasPriceVal = 20000000000ULL;
+ uint32_t gasLimitVal = 5000000;
+ std::string value;
+ std::string emptyString;
+
+ value = Util::ConvertEthToWei(1);
+ std::string result = contract.SendTransaction(nonceVal, gasPriceVal, gasLimitVal, &ownerAddress, &value, &emptyString);
+ Serial.println(result.c_str());
+
+ std::string data = string(CONTRACT_BYTECODE) + "000000000000000000000000" + owner.substr(2);
+ value = "0";
+ result = contract.SendTransaction(nonceVal + 1, gasPriceVal, gasLimitVal, &emptyString, &value, &data);
+ Serial.println(result.c_str());
+ string transactionHash = web3.getString(&result);
+ Serial.printf("TxHash: %s\n", transactionHash.c_str());
+
+ for (int i = 0; i < 7; i++) {
+ string contractAddress = web3.EthGetDeployedContractAddress(&transactionHash);
+ if (contractAddress.length() != 0)
+ return contractAddress;
+ delay(1000);
+ }
+ return "";
+}
+
+void post_wifi_connect() {
+ Serial.printf("Deploying contract, setting owner to %s\n", ownerAddress.c_str());
+ contractAddress = deploy_contract(ownerAddress);
+ if (contractAddress.length() == 0) {
+ Serial.println("Contract deployment failed.");
+ return;
+ }
+ Serial.printf("Contract deployed: %s\n", contractAddress.c_str());
+
+ pContractAddressCharacteristic->setValue(contractAddress.c_str());
+ state = STATE_CONTRACT_DEPLOYED;
+ Serial.printf("done");
+}
+
+void post_contract_deployment() {
+ Contract contract(&web3, contractAddress.c_str());
string param = contract.SetupContractData("powered()");
string result = contract.ViewCall(&param);
- int status = web3.getInt(&result);
- Serial.printf("Status: %d\n", status);
- pinMode(LED_PIN, OUTPUT);
- digitalWrite(LED_PIN, status);
-}
+ digitalWrite(LED_PIN, web3.getInt(&result));
+ webSocket.begin("testnet.dexon.org", 8546);
+ webSocket.onEvent(on_websocket_event);
+ state = STATE_WS_CONNECTED;
+}
-/* This routine is specifically geared for ESP32 perculiarities */
-/* You may need to change the code as required */
-/* It should work on 8266 as well */
-void setup_wifi()
-{
- if (WiFi.status() == WL_CONNECTED)
- {
+void setup_wifi(const char* ssid, const char* password) {
+ if (WiFi.status() == WL_CONNECTED) {
return;
}
@@ -57,8 +174,7 @@ void setup_wifi()
Serial.print("Connecting to ");
Serial.println(ssid);
- if (WiFi.status() != WL_CONNECTED)
- {
+ if (WiFi.status() != WL_CONNECTED) {
WiFi.persistent(false);
WiFi.mode(WIFI_OFF);
WiFi.mode(WIFI_STA);
@@ -67,20 +183,15 @@ void setup_wifi()
}
wificounter = 0;
- while (WiFi.status() != WL_CONNECTED && wificounter < 10)
- {
- for (int i = 0; i < 500; i++)
- {
- delay(1);
- }
+ while (WiFi.status() != WL_CONNECTED && wificounter < 10) {
+ delay(500);
Serial.print(".");
wificounter++;
}
- if (wificounter >= 10)
- {
- Serial.println("Restarting ...");
- ESP.restart(); //targetting 8266 & Esp32 - you may need to replace this
+ if (wificounter >= 10) {
+ Serial.println("Can not connect");
+ return;
}
delay(10);
@@ -89,4 +200,86 @@ void setup_wifi()
Serial.println("WiFi connected.");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
-} \ No newline at end of file
+
+ state = STATE_WIFI_CONNECTED;
+}
+
+
+class WiFiCharacteristicCallback : public BLECharacteristicCallbacks {
+ virtual void onWrite(BLECharacteristic* pCharacteristic) {
+ std::string wifiSettings = pCharacteristic->getValue();
+ int pos = wifiSettings.find_first_of(" ");
+ if (pos == std::string::npos) {
+ return;
+ }
+ std::string ssid = wifiSettings.substr(0, pos);
+ std::string password = wifiSettings.substr(pos + 1);
+ Serial.println(ssid.c_str());
+ Serial.println(password.c_str());
+ setup_wifi(ssid.c_str(), password.c_str());
+ }
+};
+
+class OwnerCharacteristicCallback : public BLECharacteristicCallbacks {
+ virtual void onWrite(BLECharacteristic* pCharacteristic) {
+ ownerAddress = pCharacteristic->getValue();
+ }
+};
+
+void setup_bluetooth() {
+ BLEDevice::init("DEXON IoT Core");
+
+ BLEServer *pServer = BLEDevice::createServer();
+ BLEService *pService = pServer->createService(SERVICE_UUID);
+ BLECharacteristic *c = pService->createCharacteristic(
+ WIFI_CHARACTERISTIC_UUID,
+ BLECharacteristic::PROPERTY_READ |
+ BLECharacteristic::PROPERTY_WRITE);
+ c->setCallbacks(new WiFiCharacteristicCallback());
+
+ c = pService->createCharacteristic(
+ OWNER_CHARACTERISTIC_UUID,
+ BLECharacteristic::PROPERTY_READ |
+ BLECharacteristic::PROPERTY_WRITE);
+ c->setCallbacks(new OwnerCharacteristicCallback());
+
+ pContractAddressCharacteristic = pService->createCharacteristic(
+ CONTRACT_ADDRESSS_CHARACTERISTIC_UUID,
+ BLECharacteristic::PROPERTY_READ);
+
+ pService->start();
+ BLEAdvertising *pAdvertising = BLEDevice::getAdvertising();
+ pAdvertising->addServiceUUID(SERVICE_UUID);
+ pAdvertising->setScanResponse(true);
+ pAdvertising->setMinPreferred(0x06); // functions that help with iPhone connections issue
+ pAdvertising->setMinPreferred(0x12);
+ BLEDevice::startAdvertising();
+ Serial.println("BLE advertisement started.");
+}
+
+void setup() {
+ Serial.begin(115200);
+
+ pinMode(LED_PIN, OUTPUT);
+
+ //setup_wifi("COBINHOOD_Guest", "COB0921592018");
+ setup_bluetooth();
+ //ownerAddress = "0x32528352352B73fAE48AbB05945EA457797D8bDC";
+}
+
+void loop() {
+ switch (state) {
+ case STATE_INIT:
+ return;
+ case STATE_WIFI_CONNECTED:
+ post_wifi_connect();
+ return;
+ case STATE_CONTRACT_DEPLOYED:
+ post_contract_deployment();
+ return;
+ case STATE_WS_CONNECTED:
+ case STATE_LOGS_SUBSCRIBED:
+ default:
+ webSocket.loop();
+ }
+}