IOT Push Button (Like Amazon Dash)

Amazon Dash button is an incredible piece of hardware and another example of “applied engineering” in Amazon, just like Kindle.

The inspiration for this project isn’t directly derived from amazon dash, I wasn’t aware of it until I started digging the internet but at end, I had to set the performance goal to Amazon dash, because no other piece of hardware was up to mark. A detailed teardown of dash button can be found here.

So, Since “decades” I wanted to build some piece of hardware which I could dynamically program for any functionality like playing next youtube video, unlocking door, rebooting a machine, minimizing all open tabs or whatever with a push of a button. The button should be portable and independent of device for operation.

To meet my requirements I had to remove BLE or any other radio-based technology which needed a receiver or additional unit to operate. ESP-12F is power intensive and somewhat large if compared to esp-01.  The end prototype looked like this and worked as expected.

| MAD Blog

Below is list of components I used.

  • 1x LiPo Battery – 150mAh
  • 1x ESP8266-01
  • 1x 1k Register
  • 1x Tactile Switch Button

You might require a soldering iron with fine tip, basic desoldering skills, access to 3d printer, FTDI board or similar setup.

The schematics of setup would look like below:

| MAD Blog

The functioning would be like – We turn on ESP using push button, but it would take time to log in to wifi, authenticate – so we need to keep it on for pretty long time – which could be done by using programming output pins, As soon as ESP turn on GPIO2 can be set to HIGH, Once operation is finished it can be set to low. Few challenges which I found on way (with fixes):

  • Power is very limited – So we need to remove LED’s from the esp, this would save a lot of power and would increase battery life by almost a fold!
  • You should use diode and transistor to limit current, since I am not an electronic nerd I would not comment on it.
  • You should set a timeout period, in case you are writing custom logic else battery will drain and you will never come to know why!

After soldering – You have to upload following code which need to be tweaked according to need, but it has basic logic code –

The code can set in hotspot mode if couldn’t connect to wifi and if could connect it would make a connection to mqtt server and make an announcement then shutdown.

#define DEVICE_ID         "YOUR_USERNAME"
#define DEVICE_NAME       "iot-" DEVICE_ID
#define WIFI_SSID         "mad-" DEVICE_ID
#define WIFI_PASSWORD     DEVICE_ID
#define MQTT_SERVER       "YOUR_SERVER"
#define MQTT_USERNAME     DEVICE_ID
#define MQTT_PASSWORD     "YOUR_PASSWORD"
#define MQTT_SEND_CHANNEL "pushbutton"
#define MQTT_RECV_CHANNEL DEVICE_NAME




#define BUTTON_MODE 1
#define USE_SSL 1
#define GPIO2 2
#define BUTTON_TIMEOUT 30000


#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <ESP8266WebServer.h>
#include <ESP8266mDNS.h>
#include <PubSubClient.h>
#include <DNSServer.h>
#include <WiFiManager.h>
#include <ArduinoJson.h>
#include <stdarg.h>


#if USE_SSL
#   include <WiFiClientSecure.h>
//    WiFiClientSecure client;
#   define PORT 443
#else
// WiFiClient client;
#   define PORT 80
#endif


void reconnect();
void sendMessage(String action, String data, char* num = "", ...);
char* stringToChar(String str);

WiFiClient espClient;
PubSubClient client(espClient);
WiFiManager wifiManager;


long lastMsg = 0;
char msg[50];
int value = 0;
String DEVICE_FEATURES = "";

void setup() {

  DEVICE_FEATURES += "pushbutton;";
  pinMode(GPIO2, OUTPUT);
  digitalWrite(GPIO2, HIGH);


  //Serial.begin(9600);

  //  wifiManager.resetSettings();
  if (!wifiManager.autoConnect(WIFI_SSID, WIFI_PASSWORD)) {
    //Serial.println("failed to connect, we should reset as see if it connects");
    delay(1000);
    ESP.reset();
    delay(1000);
  }
  client.setServer(MQTT_SERVER, 1883);

}
void loop() {

  //if button mode, & time since start is greater than TIMEOUT close the time.
  if (millis() > BUTTON_TIMEOUT)
    digitalWrite(GPIO2, LOW);
  //if MQTT Client not connect connect it back.
  if (!client.connected())
    reconnect();
  client.loop();

}



/**
   Send message to server
   example: sendMessage("hello", DEVICE_NAME,"ksks","mac",getMacAddress(),"localIP",WiFi.localIP().toString());
   k for key
   d : double, f : float, s : string, l : long,
   No char type
*/
void sendMessage(String action, String data, char *types, ...) {
  StaticJsonBuffer<200> jsonBuffer;
  JsonObject& root = jsonBuffer.createObject();
  root["action"] = action;
  root["data"] = data;

  //find length
  int count = 0;
  while (types[count++] != '\0');
  --count;

  //if not even args
  if (count % 2 != 0)
    return;

  //for argument parsing.
  va_list arguments;
  va_start ( arguments, types );

  String key;

  //even length validated already
  for (int i = 0; types[i] != '\0'; i += 2) {
    //this is intentionally done, default key as type k can be used, but developer might mistake, causing lot of debugging
    if (types[i] != 'k')
      continue;
    key =  va_arg ( arguments, char *  );

    switch (types[i + 1])
    {
      case 'd': root[key] = (va_arg(arguments, int));
        break;
      case 'l': root[key] = (va_arg(arguments, long));
        break;
      case 'f': root[key] = (va_arg(arguments, double));
        break;
      case 's': root[key] = (va_arg(arguments, char *));
        break;
      default:  ;
    };
  }

  va_end ( arguments );                  // Cleans up the list

  char tmp[root.measureLength() + 2];
  root.printTo(tmp, sizeof(tmp));
  client.publish(MQTT_SEND_CHANNEL, tmp);
}



void reconnect() {
  // Loop until we're reconnected
  while (!client.connected()) {
    //Serial.print("Attempting MQTT connection...");
    // Attempt to connect
    if (client.connect(DEVICE_NAME, MQTT_USERNAME, MQTT_PASSWORD)) {
      //Serial.println("connected");
      // Once connected, publish an announcement...
      sendMessage("hello", DEVICE_NAME, "ksks", "features", (DEVICE_FEATURES).c_str() , "localIP", (WiFi.localIP().toString().c_str()));
      digitalWrite(GPIO2, LOW);
    } else {
      //Serial.print("failed, rc=");
      //Serial.print(client.state());
      //Serial.println(" try again in 5 seconds");
      // Wait 5 seconds before retrying
      delay(2000);
    }
  }
}

I hope you enjoyed the article, it wasn’t a detailed writeup and I dropped many details – but if you have any questions you can comment or drop mail – I will surely help.

4 comments

Skip to comment form

    • karan singh on May 24, 2019 at 9:53 am
    • Reply

    please continue to make posts.

    i saw your github/rdroid please continue it.

    as number of android smartphones are increasing there is high demand of android penetration testing.

    so, please rewrite your rdroid code, if possible make video and also teach how you write that code with brief explanation.

    1. Hi Karan,

      I am sorry for late response. Thank you for your feedback

      It has been years since I worked on that project, if you can be specific – I can help.

    • milad on May 28, 2019 at 12:13 pm
    • Reply

    Error compiling program.
    Error description: Unknown member: createcontactentry2
    Error occurred on line: 429
    m.createContactEntry2(Name,Null,phones,mails,Note,Website,”Home”,ahome,awork)
    Word: createcontactentry2

    https://user-images.githubusercontent.com/22496001/58452897-58cfc180-812e-11e9-8edd-375cf534d4e7.PNG

    Please list all the Basic 4 Android libraries for downlaod ???

    1. Hi Milad,

      I am sorry for late response, been busy lately.

      Were you able to solve the issue ?

Leave a Reply

Your email address will not be published.