Things used in this project

Hardware components:
Abx00004 iso both
Arduino MKR1000 & Genuino MKR1000
×1
51gzz5eu9pl. sx425
HC-SR04
×1
Adafruit 3.7V LiPo Battery
×1
Software apps and online services:
Vs2015logo
Microsoft Visual Studio 2015
Ide web
Arduino IDE

Schematics

DashLid Schematic
Dashlid schematic eoy6akpqfl

Code

Visual Studio DashLid Client SolutionC#
This code is run to setup the DashLid Device.
No preview (download only).
Visual Studio DashLid Client CodeC#
Used to set up the Dash Lid
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Net;
using RestSharp;
using System.IO.Ports;

//Watin problems?
//Add reference to Interop.SHDocVw
//Set CopyLocal to true, or copy the dll into the Release/Debug folders

namespace DRS
{
    public partial class SetupForm : Form
    {
        SerialPort serialPort;
        string returnURL;
        string code;
        Tokens tokens;
        string wifiPassword;
        string wifiSsid;

        //Enter your client info here.
        //Go to https://developer.amazon.com/iba-sp/overview.html -> APPS & SERVICES -> Security Profile (in sub-header) and choose your security profile.
        const string client_id = "";
        const string client_secret = "";
        const string slot_id = ""; //APPS & SERVICES -> Dash Replenishment Service  (sub-header)

        DeviceData deviceData;
        DeviceSpecifications deviceSpecifications;
        string URL;
        byte replenishHour;

        public SetupForm()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            //Save the settings from the form
            replenishHour = (Byte) cbRefreshHour.SelectedIndex;
            wifiSsid = tbSSID.Text;
            wifiPassword = tbPassword.Text;

            GetDRSDeviceInfo();
            BuildURL();
            UseWatinBrowser();
            ExtractCodeFromReturnURL();
            ObtainDRSTokens();
            SendDeviceInfo();
            ReadDeviceDebuggingInfo();
        }

        private void GetDRSDeviceInfo()
        {
            while (SerialPort.GetPortNames().Count() == 0); //Wait for a COM port to appear - when MKR1000 is connected
            string[] ports = SerialPort.GetPortNames();
            string port = ports[0];
            
            Console.WriteLine("Opening port " + port);

            serialPort = new SerialPort(port, 9600, Parity.None, 8, StopBits.One);
            serialPort.Open();
            string deviceInfo = serialPort.ReadLine();
            System.Diagnostics.Debug.WriteLine(deviceInfo);
            deviceSpecifications = Json.JsonParser.Deserialize<DeviceSpecifications>(deviceInfo);
        }

        private void BuildURL()
        {
            string scopeData = "{\"dash:replenish\":{\"device_model\":\"" + deviceSpecifications.model + "\",\"serial\":\"" + deviceSpecifications.serial + "\",\"is_test_device\":\"true\"}}";
            string urlEncodedScopeData = WebUtility.UrlEncode(scopeData); 
            URL = "https://www.amazon.com/ap/oa?client_id=" + client_id + "&scope=dash%3Areplenish&scope_data=" + urlEncodedScopeData + "&response_type=code&redirect_uri=https%3A%2F%2Fwww.getpostman.com%2Foauth2%2Fcallback";   
        }

        private void UseWatinBrowser()
        {
            //Check url until the code is returned
            WatiN.Core.IE ie = new WatiN.Core.IE(URL);
            bool OkToContinue = true;
            while (OkToContinue)
            {
                string currentURL = ie.Url;
                System.Diagnostics.Debug.WriteLine(currentURL);
                if (currentURL.Contains("code="))
                {
                    returnURL = currentURL;
                    OkToContinue = false;
                    ie.ForceClose();
                }
                else
                    System.Threading.Thread.Sleep(1000);
            }
        }

        private void ExtractCodeFromReturnURL()
        {
            //returnURL example: "https://app.getpostman.com/oauth2/callback?code=cccccccooooooooodddddddeeeeee&scope=dash%3Areplenish";
            int startString = returnURL.IndexOf("?code") + 6;
            int endString = returnURL.IndexOf("&scope");
            code = returnURL.Substring(startString, endString - startString);
            //System.Diagnostics.Debug.WriteLine(code);
        }

        private void ObtainDRSTokens()
        {
            var client = new RestClient("https://api.amazon.com/auth/o2/token");
            var request = new RestRequest(Method.POST);
            request.AddHeader("cache-control", "no-cache");
            request.AddHeader("content-type", "application/x-www-form-urlencoded");
            request.AddParameter("application/x-www-form-urlencoded", "grant_type=authorization_code&code=" + code + "&client_id=" + client_id + "&client_secret=" + client_secret + "&redirect_uri=https%3A%2F%2Fwww.getpostman.com%2Foauth2%2Fcallback", ParameterType.RequestBody);
            IRestResponse response = client.Execute(request);

            //System.Diagnostics.Debug.WriteLine(response.Content);
            tokens = Json.JsonParser.Deserialize<Tokens>(response.Content);
        }

        private void SendDeviceInfo()
        {
            deviceData = new DeviceData();
            deviceData.AccessToken = tokens.access_token;
            deviceData.RefreshToken = tokens.refresh_token;
            deviceData.WifiPassword = wifiPassword;
            deviceData.WifiSsid = wifiSsid;
            deviceData.ClientId = client_id;
            deviceData.ClientSecret = client_secret;
            deviceData.SlotId = slot_id;
            deviceData.ReplenishHour = replenishHour;

            DateTime dateTime = System.DateTime.Now;
            deviceData.Year = (byte)(dateTime.Year - 2000);
            deviceData.Month = (byte)dateTime.Month;
            deviceData.Day = (byte)dateTime.Day;
            deviceData.Hour = (byte)dateTime.Hour;
            deviceData.Minute = (byte)dateTime.Minute;
            deviceData.Second = (byte)dateTime.Second;
            string json = Json.JsonParser.Serialize<DeviceData>(deviceData);
            System.Diagnostics.Debug.WriteLine(json);
            serialPort.WriteLine(json);
        }


        private void ReadDeviceDebuggingInfo()
        {
            while (true)
            {
                if (serialPort.BytesToRead > 0)
                {
                    System.Diagnostics.Debug.WriteLine(serialPort.ReadLine());
                }
            }
        }


        // FIN
























        private void TestSendingDeviceInfo()
        {
            //SerialPort testPort = new SerialPort("COM5", 9600, Parity.None, 8, StopBits.One);
            //testPort.Open();
            //string line = testPort.ReadLine();
            //System.Diagnostics.Debug.WriteLine(line);

            deviceData = new DeviceData();
            deviceData.AccessToken = "Atza|testAccessToken";
            deviceData.RefreshToken = "Atzr|testRefreshToken";
            deviceData.WifiPassword = wifiPassword;
            deviceData.WifiSsid = wifiSsid;
            deviceData.ClientId = client_id;
            deviceData.ClientSecret = client_secret;
            deviceData.SlotId = slot_id;
            deviceData.ReplenishHour = 3;

            DateTime dateTime = System.DateTime.Now;
            deviceData.Year = (byte)(dateTime.Year - 2000);
            deviceData.Month = (byte)dateTime.Month;
            deviceData.Day = (byte)dateTime.Day;
            deviceData.Hour = (byte)dateTime.Hour;
            deviceData.Minute = (byte)dateTime.Minute;
            deviceData.Second = (byte)dateTime.Second;
            string json = Json.JsonParser.Serialize<DeviceData>(deviceData);
            //testPort.WriteLine(json);
        }




        private void ParseTokensTest()
        {
            string tokens = "{\"access_token\":\"Atza|testAccessToken\",\"refresh_token\":\"Atzr|testRefreshToken\",\"token_type\":\"bearer\",\"expires_in\":3585}";
            System.Diagnostics.Debug.WriteLine(tokens);
            Tokens t = Json.JsonParser.Deserialize<Tokens>(tokens);
        }

        private void flowLayoutPanel1_Paint(object sender, PaintEventArgs e)
        {

        }

        private void label3_Click(object sender, EventArgs e)
        {

        }
    }
}
Arduino Code FilesArduino
MKR1000 Code
No preview (download only).
Arduino Code for DashLidArduino
DashLid Code
#include <ArduinoJson.h>
#include <RTCZero.h>
#include "AmazonDRS.h"

//JSON Parsing -------------------------------------------------------------------------------
StaticJsonBuffer<2000> jsonBuffer;
String readString;
//--------------------------------------------------------------------------------------------

//DRS ----------------------------------------------------
//WiFi creds ----------------------------------------------------------------------------------
//char ssid[] = ""; //  your network SSID (name)
//char pass[] = ""; // your network password (use for WPA, or use as key for WEP)
//------------------------------------------------------------------------------------------------------

#define slotNumber 1 //This will vary for multi slot devices - dash buttons typically only serve one product/slot

const int dashButton = 5;     //DIO number of the pushbutton pin
static long buttonHigh = 0;    //millis of last button push for switch debouncing
static String slotStatus = ""; //boolean which depicts if slot is available for replenishment
static String slotId = "";     //unique slot id ex: 0a5038b7-7609-4b81-b87e-3e291f386324 
//Enter your device Info
  char jsonDeviceInfo[] ="{\"model\":\"Dry_Goods_Retro_Container\",\"serial\":\"dgrc01\"}";
  
AmazonDRS DRS = AmazonDRS();
  
//RTC ----------------------------------------------------
RTCZero rtc; //rtc RTCZero instance
bool awake = false; //true = running, false = sleep mode
//Values to set the current initial date and time 
byte seconds;
byte minutes;
byte hours;
byte day;
byte month;
byte year;
byte replenishhour;

//Ultrasonic ---------------------------------------------
#define echoPin 7 // Echo Pin
#define trigPin 8 // Trigger Pin
#define LEDPin 6 // Onboard LED

int maximumRange = 200; // Maximum range needed
int minimumRange = 5; // Minimum range needed
int replenishRange = 20; //20 cm. or greater => Replenish
long duration, distance; // Duration used to calculate distance

//Setup ---------------------------------------------------
void setup() {
 Serial.begin (9600);

 delay(10000); //delay to measure current draw. Also needed to be able to re-program MKR1000 when using sleep mode

//Exchange Data with Client ----------------------------------------------------------------
Serial.println(jsonDeviceInfo);

  while (!Serial.available()) {} //Wait for the serial port
  while (Serial.available()) {
    delay(3);  //delay to allow buffer to fill
    if (Serial.available() >0) {
      char c = Serial.read();  //gets one byte from serial buffer
      readString += c; //append to readString
    }
  }

  //if (readString.length() >0) Serial.println(readString); //see what was received

  JsonObject& root = jsonBuffer.parseObject(readString);

  // Test if parsing failed
  if (!root.success()) {
    Serial.println("parseObject() failed");
    return; //We have a problem
  }

  
  String ssidString = root["wifissid"];
  char ssid[ssidString.length()]; 
  ssidString.toCharArray(ssid, ssidString.length()+1); 

  String passString = root["wifipassword"];
  char pass[passString.length()]; 
  passString.toCharArray(pass, passString.length()+1);

  String refreshToken = root["refreshtoken"];
  DRS.setRefreshToken(refreshToken);

  String accessToken = root["accesstoken"];
  DRS.setAccessToken(accessToken);

  

  Serial.print("==========> Refresh Token: ");
  Serial.println(refresh_token);

  Serial.print("==========> Access Token: ");
  Serial.println(access_token);

  


  seconds = root["second"];
  minutes = root["minute"];
  hours = root["hour"];
  year = root["year"];
  month = root["month"];
  day = root["day"];
  replenishhour = root["replenishhour"];

  Serial.print("SSID: ");
  Serial.println(ssid);
  //Serial.print("PASS: ");
  //Serial.println(pass);
      
//------------------------------------------------------------------------------------------


  DRS.begin(ssid,pass); //Startup DRS
  
  pinMode(LEDPin, OUTPUT); //set LED pin to output
  digitalWrite(LEDPin, LOW); //turn LED off

  rtc.begin(); //Start RTC, this is where the clock source is initialized

  rtc.setTime(hours, minutes, seconds); //set time
  rtc.setDate(day, month, year); //set date
  rtc.setAlarmTime(replenishhour, 0, 0); 

  Serial.print("================> Replenish Hour: ");
  Serial.println(replenishhour);
  Serial.print("RTC Date/Time: ");
  PrintDateTime();

  
  //rtc.enableAlarm(rtc.MATCH_SS);//set alarm time to go off on matching seconds
  rtc.enableAlarm(rtc.MATCH_HHMMSS); //set alarm to go off at a specific time
  rtc.attachInterrupt(ISR); //creates an interrupt that wakes the SAMD21 which is triggered by a FTC alarm

  
  //Replenish(); //Replenish immediately for testing
  rtc.standbyMode(); //Puts the SAMD chip in standby (low power) mode. USB Serial port will not work (disconnects from USB). Comment out for testing.
}

//Loop -----------------------------------------------
void loop() {
 if (awake)
 { 
  Serial.println("awake in loop");
  ping();
  awake = false;
 }
}

void ISR()
{
  //Serial.println("awake in ISR");
  awake = true;
  PrintDateTime();
}

void ping()
{
  Serial.println("awake in ping");
 //Setup Ultrasonic Sensor
 pinMode(trigPin, OUTPUT);
 pinMode(echoPin, INPUT);

 //Ping Ultrasonic Sensor and show distance
 /* The following trigPin/echoPin cycle is used to determine the distance of the nearest object by bouncing soundwaves off of it. */ 
 //digitalWrite(trigPin, LOW); 
 delayMicroseconds(2); 

 digitalWrite(trigPin, HIGH);
 delayMicroseconds(10); 
 
 digitalWrite(trigPin, LOW);
 duration = pulseIn(echoPin, HIGH);
 
 //Calculate the distance (in cm) based on the speed of sound.
 float distance = duration/58.2;
 
 if (distance >= maximumRange || distance <= minimumRange)
 {
  //Ignore
  //Serial.println("out of range");
 }
 else {
  //We have a valid distance reading, see if we need to replenish
   digitalWrite(LEDPin, HIGH);
   delay(1000);
   digitalWrite(LEDPin, LOW);
   delay(1000);
  if (distance >= replenishRange)
    Replenish();
    
 /* Send the distance to the computer using Serial protocol, and turn LED OFF to indicate successful reading. */
 Serial.print("Distance: ");
 Serial.print(distance,3);
 Serial.print(" cm Duration: ");
 Serial.println(duration);
 }
}

void Replenish()
{
  Serial.println("Requesting replenishment");
    DRS.retrieveSubscriptionInfo();  //check slot statuses

  slotStatus = DRS.getSlotStatus(slotNumber);
  slotId = DRS.getSlotId(slotNumber);

        //Replenish          
        if(slotStatus == "true")   //if the product in slot are available 
        {
            //we have a match! replenish the products associated with that slot!    
            Serial.println("Trying to replenish!!!");        
            DRS.requestReplenishmentForSlot(slotId);
        }
        else
        {
          Serial.print("Sorry, slot ");
          Serial.print(slotId);
          Serial.println(" is not available at this time");
        }
}

void print2digits(int number) 
{
  if (number < 10) {
    Serial.print("0"); // print a 0 before if the number is < than 10
  }
  Serial.print(number);
}

void PrintDateTime()
{
    // Print date...
  print2digits(rtc.getMonth());
  Serial.print("/");
  print2digits(rtc.getDay());
  Serial.print("/");
  print2digits(rtc.getYear());
  Serial.print(" ");

  // ...and time
  print2digits(rtc.getHours());
  Serial.print(":");
  print2digits(rtc.getMinutes());
  Serial.print(":");
  print2digits(rtc.getSeconds());

  Serial.println();
}
An Arduino library for WiFi101 connected devices implementing the Amazon Dash Replenishment API

Credits

Replications

Did you replicate this project? Share it!

I made one

Love this project? Think it could be improved? Tell us what you think!

Give feedback

Comments

Similar projects you might like

PHPoc Blue to Control Door Knob by MQTT Protocol and Cortana
Intermediate
  • 122
  • 7

Programming a PHPoc Blue board to control a servo motor to rotate the knob of a door using MQTT Protocol through voice command.

Cat Door with Pet Recognition
Intermediate
  • 4,732
  • 22

Full instructions

Use object detection to let your cat in and out of the house with a motion-activated pet door.

Adding RC Transmitter/Receiver to Control Mecanum Bot
Intermediate
  • 584
  • 6

Full instructions

We previously showed our Mecanum Bot being controlled by a wireless Xbox controller, now we added RC transmitter/receiver.

ConnectTheDots with Particle Azure IoT Hub Integration
Intermediate
  • 582
  • 7

Protip

This project will allow you to connect your Particle device into an Azure IoT Hub for viewing data in real-time through an ASP.NET web app!

Lego Mindstorms  Elevator
Intermediate
  • 158
  • 2

A 3-story elevator with a mechanical door made from Lego Mindstorms and programmed on RoboCore. It moves up and down and reacts to buttons.

Lego Mindstorms Elevator

Team ElevatorRoboCore

I'm Fine for the Workplace
Intermediate
  • 622
  • 5

Full instructions

A system to let someone ask for help at school or in the workplace without having to do it publicly.

I'm Fine for the Workplace

Team National Star and EDF Energy Hackathon

Add projectSign up / Login