IoT + Azure automation: At the click of a (motivational IoT) button

Sometimes you need and extra motivational boost. What better way to do this than clicking a button and seeing a dog?


In this build, i made an ESP8266 (01) IoT button and used it to trigger a script in Azure Automation through a HTTPS WebHook.

The goals for this build was small size and low cost, with off-the-shelf hardware. Buying these parts off ebay would set you back about 6$ (~ 50 nok)
I use Azure automation here, but you could do this for any IOT / WebHook enabled service.

Circuit

The circuit here is quite simple; its an ESP8266 01 with a pushbutton wired between ground and its reset pin: When the button is pressed, the pin is pulled low and the chip is reset, triggering the code to run.

If you are familiar with the ESP8266 chip, you`ll know that GPIO0 needs to be pulled high for normal operation: the 10 K resistor acts as a pullup here. Other than that, make the necessary connections of VCC and CH_PD to + and GND to GND.

The choice of using an 826601 instead of one of the newer models is purely for cost. the 01 chip can be bought as low as 2$ a piece, Althought these chips are known to be a bit tricky to get code onto. I might do a post on flashing them later as this is something i had a tough time doing when i first started out.

Parts list:
ESP 8266 01
Pushbutton
10k resistor
Battery holder

Code

Now to the code:
There are 2 elements of code in this build: the code flashed to the ESP8266, and the Azure Automation job we are triggering.

First things first; the code for the ESP.

You will need three things before running it: Wifi SSID and PW to the network you`ll be using, the Webhook URL you`ll trigger and (because we are triggering a Webhook that uses HTTPS) the Certificate Thumbrint used for the connection.

If you are triggering Azure Automation, you’ll get the WebHook URL from there. The Certificate Thumbrint can be found by going to the URL and viewing the certificate details from there, but its a wildcard cert for *.Azure-automation.net so i`m leaving the one i used in the code. All code is run in the setup block, as its a one time thing every time the button is pressed. At the end of the block, notice that the ESP is being put to sleep. You’ll usually pass the allotted time the chip is able to sleep between each run so its basically turning of.

Code for the ESP:

#include <ESP8266WiFi.h>
//#include <ESP8266HTTPClient.h>
#include <WiFiClientSecure.h>

const char* WIFISSID = "YourWifiName";
const char* WIFIPW = "YourWifiPW";

const char* URL = "s2events.azure-automation.net";
const char* WebHook = "/webhooks?token=YourWebHookTokenEtc";
const int HTTPSPort = 443;

//SHA1 fingerprint
const char* fingerprint = "D3 C8 87 84 06 33 68 5C C8 E4 19 02 5A 59 A1 D7 83 87 62 92";

void setup() {

  Serial.begin(115200);
  Serial.println();
  Serial.print("connecting to ");
  Serial.println(WIFISSID);
  WiFi.mode(WIFI_STA);
  
  WiFi.begin(WIFISSID, WIFIPW);
    while (WiFi.status() != WL_CONNECTED) {
      delay(500);
      Serial.print(".");
    }
  
  Serial.println("");
  Serial.println("WiFi connected");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());
 
 Serial.println("Starting up!"); 
 
 if(WiFi.status()== WL_CONNECTED){   //Check WiFi connection status

  WiFiClientSecure client;
  Serial.print("Posting to  ");
  Serial.println(URL);
  
  if (!client.connect(URL, HTTPSPort)) {
    Serial.println("connection failed");
    return;
  }
    if (client.connect(URL, HTTPSPort)) {
    Serial.print("Connected to");
    Serial.println(URL);
  }

      if (client.verify(fingerprint, URL)) {
        Serial.println("certificate matches");
      } 
      
      else {
        Serial.println("certificate doesn't match");
      }
      
  client.print(String("POST ") + WebHook + " HTTP/1.1\r\n" +
               "Host: " + URL + "\r\n" +
               "Content-Type: application/x-www-form-urlencoded\r\n" +
               "Content-Length: 0\r\n" +
               "Connection: close\r\n\r\n");

  Serial.println("request sent");
  
  while (client.connected()) {
    String line = client.readStringUntil('\n');
    if (line == "\r") {
      Serial.println("headers received");
      break;
    }
  }
  
  String line = client.readStringUntil('\n');
  Serial.println("reply was:");
  Serial.println("==========");
  Serial.println(line);
  Serial.println("==========");
  Serial.println("closing connection");


  //Enter DeepSleep and never wake up. This makes it hibernate until reset it triggered.
  Serial.println("Going to sleep"); 
  ESP.deepSleep(0);
 
  }
}

void loop() {}

The code in azure automation;
The button triggers a job that gets a random image from TheDogApi (dog.ceo), and sends it to you by email. Perfect for those times when you need an extra motivational boost!

param (
        
    [object]$WebhookData   
    )

    # If runbook was called from Webhook, WebhookData will not be null.
    if ($WebhookData) {
            Write-output $WebHookData

        #First We`ll download an image from the Dog API

        $ApiRoot = "https://dog.ceo/api/"
        $ApiOne = "breeds/image/random"

        $File = "NewestDogPic.jpg"

        $CallURIOne = $ApiRoot + $ApiOne

        $ResponseObject = Invoke-RestMethod -Uri $CallURIOne -Method Get

        $Img = ($ResponseObject).Message
        $ImgTitle = $Img -split "/" | select -Last 1

        $Item = New-Item -ItemType File -Name $ImgTitle
        Write-Output "$Img"

        (New-Object System.Net.WebClient).DownloadFile($Img, $Item)

        Write-output $Image

        #Now we`ll generate the message that we will be sending

        $Subject = "The motivational button has been pressed" 
        $Recipients = "You@email.com"
        $BccRecipients = "YourOtherEmail@Email.com
        $Attachment = $Item

        #This part is used for sending the email 

        $AzureOrgIdCredential = "O365 enabled mailbox"
        $Cred = Get-AutomationPSCredential -Name $AzureOrgIdCredential

        $email = @{

            From = "Admin@bitbrb.com"
            To = $Recipients
            Bcc = $BccRecipients
            Subject = $Subject
            SMTPServer = "smtp.office365.com"
            Port = 587
            UseSSL = $True
            Credential = $Cred
            BodyAsHTML = $True
            Body = 'Hang in there! <br /><img src="{0}" />' -f ($Attachment.Name)
            Attachments = $Attachment.FullName

        }
        write-output "ready to send email:"
        Write-output $Email
        Send-MailMessage @email

    }

That’s all there is to it! Hope you enjoyed the read, be a good boy.

Leave a Reply

Your email address will not be published. Required fields are marked *