Sumit Kumar
Published © GPL3+

Infinity Charge ∞ Infinity Exit

Pay IOTA tokens to wirelessly charge your vehicle also get out of traffic fast with our services.

BeginnerFull instructions provided7 hours1,168
Infinity Charge ∞ Infinity Exit

Things used in this project

Story

Read more

Schematics

Get everything here

Code

Particle Code

C/C++
// This #include statement was automatically added by the Particle IDE.
#include <MFRC522.h>
#include <SparkJson.h>

#define SS_PIN      SS
#define RST_PIN     D2
#define relay D5

MFRC522 mfrc522(SS_PIN, RST_PIN);	// Create MFRC522 instance.

bool chargeFlag = false;
int chargeTime = 0;
int prevTime = 0;
String status ;

// this runs only once for declarations and static initialisations
void setup() 
{
 // Subscribing to webhooks makes them ready for publish methods 
  Particle.subscribe("hook-response/SEND_ID", myHandler, MY_DEVICES);
  Particle.subscribe("hook-response/READ_ID", dataRead, MY_DEVICES);
  Serial.begin(9600);
  pinMode(relay,OUTPUT);
  digitalWrite(relay,LOW);
}

// You will not need this
void myHandler(const char *event, const char *data)  
{
  // Handle the integration response
}

// this runs forever to make your device independent
void loop()
{
    readId();
    /**  if payment is done and shows success on firebase then the chargeFlag would become false showing that the user is already charging,
    this would prevent me from making infinite requests from webhooks**/
    if(chargeFlag==true)  
    {
      Particle.publish("READ_ID","",PRIVATE);  // keep on checking values from firebase for transaction success to start charging 
    }
   charge();
}

// charge for committed time
void charge()
{
    /** after charging has been done this method would be useless because we have reset the charge time to 0,
    but it would become active if a new car and transaction is found**/
    
    if(millis()-prevTime>(chargeTime*60*1000)) // check after converting charge time in milliseconds because the user had sent time from app in minutes
    {
        Serial.println("Charging OFF, bye");
        chargeTime = 0; 
        digitalWrite(relay,LOW); 
    }
    else return;
}

// reading RFID using predefined functions 
void readId()
{
  // Look for new cards
  if ( ! mfrc522.PICC_IsNewCardPresent()) 
  {
    return;
  }
  // Select one of the cards
  if ( ! mfrc522.PICC_ReadCardSerial()) 
  {
    return;
  }
 // if found read the tag
  String content= "";
  byte letter;
  for (byte i = 0; i < mfrc522.uid.size; i++) 
  {
     Serial.print(mfrc522.uid.uidByte[i] < 0x10 ? " 0" : " ");
     Serial.print(mfrc522.uid.uidByte[i], HEX);
     content.concat(String(mfrc522.uid.uidByte[i] < 0x10 ? " 0" : " "));
     content.concat(String(mfrc522.uid.uidByte[i], HEX));
  }
  content.toUpperCase();
  String IDfound = content.substring(1) ;
  // send the ID read to Firebase webhook and verify the correct user device to charge with
  chargeFlag = true;
  Serial.println("Valid ID found, you can start charging.");
  sendId(IDfound);
} 

// Sending ID to firebase so that the car app can check whether the user is registered or not
void sendId(String IDfound)
{
    char buf[256];
	snprintf(buf, sizeof(buf), "{\"id\":\"%s\"}", IDfound);
	Serial.printlnf("publishing %s", buf);
	Particle.publish("SEND_ID", buf, PRIVATE);
	delay(3000);
}

// we need to reset data for new users
void resetData()
{
    char reset[256];
	snprintf(reset, sizeof(reset), "{\"tm\":\%d\, \"status\":\"%s\"}", 0," "); // keep note of the JSON strings,( 0,"") are the null values for resetting data
	Serial.printlnf("resetting %s", reset);
	Particle.publish("SEND_ID", reset, PRIVATE);
	delay(3000);
}

/**reading data from firebase and storing it in global variables for further use**/
void dataRead(const char *event, const char *data) 
{
    StaticJsonBuffer<255> jsonBuffer;
    char *mutableCopy = strdup(data);
    JsonObject& root = jsonBuffer.parseObject(mutableCopy);
    free(mutableCopy);
    chargeTime = atoi(root["tm"]);
    status = root["status"];
    if(strcmp(status,"Success")&&chargeTime>0&&chargeFlag==true)
    {
        resetData();
        chargeFlag = false;
        prevTime = millis();
        digitalWrite(relay,HIGH);
        Serial.println("Charging ON");
    }
}

Arduino UNO Serial(slave)

Arduino
// Arduino code for serial Read
#include <AFMotor.h>
// Connect a stepper motor with 48 steps per revolution (7.5 degree)
// to motor port #2 (M3 and M4)
AF_Stepper motor(48, 2);
void setup()
{
 Serial.begin(115200);
 Serial.println("Listening to ESP32 requests");
 motor.setSpeed(10);  // 10 rpm
while (!Serial) 
{
    ; // wait for serial port to connect. Needed for native USB port only
}
 
}
void loop()
{
  if (Serial.available()>0)
  {
    char c=Serial.read();
    if(c=='D') 
    {
      Serial.write("Yes there's a request");
      // There's a request from user for infinity exit, the car is standing on base so time to bring it down     
      // you can use ultrasonic sensor instead for more better performance   
      motor.step(100, BACKWARD, SINGLE);
      // bring up after 5 minutes
      delay(1000*60*5);
      motor.step(100, FORWARD, SINGLE);
    }
    else
    {
    Serial.write("no");

    }
   
  }
}

ESP32_IOTA code

Arduino
// this version is supported only on esp32 boards
#include <WiFiClientSecure.h>
WiFiClientSecure client;
#include <ArduinoJson.h>
#include <string.h>

// Let's Encrypt root cert
const char* le_root_ca= \
     "-----BEGIN CERTIFICATE-----\n" \
     "MIIEkjCCA3qgAwIBAgIQCgFBQgAAAVOFc2oLheynCDANBgkqhkiG9w0BAQsFADA/\n" \
     "MSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMT\n" \
     "DkRTVCBSb290IENBIFgzMB4XDTE2MDMxNzE2NDA0NloXDTIxMDMxNzE2NDA0Nlow\n" \
     "SjELMAkGA1UEBhMCVVMxFjAUBgNVBAoTDUxldCdzIEVuY3J5cHQxIzAhBgNVBAMT\n" \
     "GkxldCdzIEVuY3J5cHQgQXV0aG9yaXR5IFgzMIIBIjANBgkqhkiG9w0BAQEFAAOC\n" \
     "AQ8AMIIBCgKCAQEAnNMM8FrlLke3cl03g7NoYzDq1zUmGSXhvb418XCSL7e4S0EF\n" \
     "q6meNQhY7LEqxGiHC6PjdeTm86dicbp5gWAf15Gan/PQeGdxyGkOlZHP/uaZ6WA8\n" \
     "SMx+yk13EiSdRxta67nsHjcAHJyse6cF6s5K671B5TaYucv9bTyWaN8jKkKQDIZ0\n" \
     "Z8h/pZq4UmEUEz9l6YKHy9v6Dlb2honzhT+Xhq+w3Brvaw2VFn3EK6BlspkENnWA\n" \
     "a6xK8xuQSXgvopZPKiAlKQTGdMDQMc2PMTiVFrqoM7hD8bEfwzB/onkxEz0tNvjj\n" \
     "/PIzark5McWvxI0NHWQWM6r6hCm21AvA2H3DkwIDAQABo4IBfTCCAXkwEgYDVR0T\n" \
     "AQH/BAgwBgEB/wIBADAOBgNVHQ8BAf8EBAMCAYYwfwYIKwYBBQUHAQEEczBxMDIG\n" \
     "CCsGAQUFBzABhiZodHRwOi8vaXNyZy50cnVzdGlkLm9jc3AuaWRlbnRydXN0LmNv\n" \
     "bTA7BggrBgEFBQcwAoYvaHR0cDovL2FwcHMuaWRlbnRydXN0LmNvbS9yb290cy9k\n" \
     "c3Ryb290Y2F4My5wN2MwHwYDVR0jBBgwFoAUxKexpHsscfrb4UuQdf/EFWCFiRAw\n" \
     "VAYDVR0gBE0wSzAIBgZngQwBAgEwPwYLKwYBBAGC3xMBAQEwMDAuBggrBgEFBQcC\n" \
     "ARYiaHR0cDovL2Nwcy5yb290LXgxLmxldHNlbmNyeXB0Lm9yZzA8BgNVHR8ENTAz\n" \
     "MDGgL6AthitodHRwOi8vY3JsLmlkZW50cnVzdC5jb20vRFNUUk9PVENBWDNDUkwu\n" \
     "Y3JsMB0GA1UdDgQWBBSoSmpjBH3duubRObemRWXv86jsoTANBgkqhkiG9w0BAQsF\n" \
     "AAOCAQEA3TPXEfNjWDjdGBX7CVW+dla5cEilaUcne8IkCJLxWh9KEik3JHRRHGJo\n" \
     "uM2VcGfl96S8TihRzZvoroed6ti6WqEBmtzw3Wodatg+VyOeph4EYpr/1wXKtx8/\n" \
     "wApIvJSwtmVi4MFU5aMqrSDE6ea73Mj2tcMyo5jMd6jmeWUHK8so/joWUoHOUgwu\n" \
     "X4Po1QYz+3dszkDqMp4fklxBwXRsW10KXzPMTZ+sOPAveyxindmjkW8lGy+QsRlG\n" \
     "PfZ+G6Z6h7mjem0Y+iWlkYcV4PIWL1iwBi8saCbGS5jN2p8M+X+Q7UNKEkROb3N6\n" \
     "KOqkqm57TH2H3eDJAkSnh6/DNFu0Qg==\n" \
     "-----END CERTIFICATE-----\n";

// WiFi Credentials - MODIFY MEEEE
const char* ssid = "vivo1718";
const char* password =  "c412ac1492ed";
const char* server = "nodes.devnet.thetangle.org";  // Server URL
const char* address = "LNE9SZAJANDOCBWLHDKJFITWARIUDPXUISLEXHUESDFXJBTCEXT9XOSVK9XCHKVZFABYGJSYI9XUUGNVX";
const char* addressChecksum = "OUEVSOUGKSTMEFUMVLIXNUTKNNRHGAD9CXVBNJEBGFZYJYOHSELJDNWFYLUJNKZRHZMJLECNGIPFQ9CYCDFTNUZN9A";
int paymentsAtAddress = 0;
int iterator = 0;

void setup() 
{
  /// Start Serial
  Serial.begin(115200);
  Serial.println();
  
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(1000);
    Serial.print(".");
  }
  // Set Cert
  client.setCACert(le_root_ca);
  Serial.println("Setup done");

}

void loop() 
{
    // Intialise loop by re/setting counters
    fetchTransactions();
    iterator = paymentsAtAddress;    
    
    // Check for payment
    while (paymentsAtAddress == iterator) {
        // Wait 5 seconds before checking
       delay(5000);
       fetchTransactions();
    }

  // Dispense coffee
  takeCarDown();
}

void fetchTransactions()
{
    // Make a HTTP request:
  char* data1="{\"command\":\"findTransactions\",\"addresses\":[\"";
  char* data2="\"]}";
  char payload[129] = "";
  strcat(payload, data1);
  strcat(payload, address);
  strcat(payload, data2);
  
  Serial.println("\nFetching Transactions...");
  if (!client.connect(server, 443))
    Serial.println("Connection failed!");
  else {
    client.println("POST / HTTP/1.1");
    client.println("Host: nodes.devnet.thetangle.org");
    client.println("X-IOTA-API-Version: 1");
    client.println("Content-Type: application/json");
    client.println("Content-Length: 129");
    client.println();
    client.println(payload);
    client.println("Connection: close");
    client.println();

    while (client.connected()) {
      String line = client.readStringUntil('\n');
      if (line == "\r") {
        // Headers Received
        break;
      }
    }
    // if there are incoming bytes available
    // from the server, read them and print them:
    while (client.available()) {
      // Parse JSON object
      DynamicJsonDocument doc(1024);
      DeserializationError error = deserializeJson(doc, client);
      if (error) {
        Serial.print(F("deserializeJson() failed: "));
        Serial.println(error.c_str());
        return;
      }
      paymentsAtAddress = doc["hashes"].size();

      String output = "";
      serializeJson(doc, output);
      Serial.println(output);
      client.stop();
    }
  }
}


void takeCarDown()
{
  Serial.println("Payment Received.");
  delay(1000);
  Serial.println('D'); 
}

IOTA Script transactions

JavaScript
const iotaLibrary = require('@iota/core')
var firebase = require("firebase-admin")

var database = firebase.database();
var firebaseConfig = {
    apiKey: "AIzaSyBhsEDxDPwzjmcoEyjLH0g3_oSIRV_TILo",
    authDomain: "smartroad-48be2.firebaseapp.com",
    databaseURL: "https://smartroad-48be2.firebaseio.com",
    projectId: "smartroad-48be2",
    storageBucket: "ID-READ.appspot.com",
};

firebase.initializeApp(firebaseConfig);
var ref = database.ref("/ID-READ");
var usersRef = ref.child("Payment_Status");**/

const iota = iotaLibrary.composeAPI({
    provider: 'https://nodes.devnet.thetangle.org:443'
})

var lastBalance = 3000;
var iotaPaid = 0;

const address = 'OUEVSOUGKSTMEFUMVLIXNUTKNNRHGAD9CXVBNJEBGFZYJYOHSELJDNWFYLUJNKZRHZMJLECNGIPFQ9CYCDFTNUZN9A'
setInterval(checkBalance, 3000)

function checkBalance() {
    iota.getBalances([address], 100).then(({ balances }) => {
            //console.log(balances)
            if (lastBalance < balances) {
                iotaPaid = balances - lastBalance
                lastBalance = balances
                console.log("iota Paid =" + iotaPaid)
                usersRef.set('Success');
            }
        })
        .catch(err => {
            console.error(err)
        })
}

Get everything here

Credits

Sumit Kumar

Sumit Kumar

32 projects • 97 followers
19 y/o. My daily routine involves dealing with electronics, code, distributed storage and cloud APIs.

Comments