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!

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

Give feedback

Comments

Similar projects you might like

Solar Smart Greenhouse using Vertical Aquaponic Towers
Intermediate
  • 1,293
  • 22

Work in progress

Feed your family with 22 sqm greenhousing by combining permaculture, aquaponic vertical towers and IOT.

Vehicle Artificial Perception-Building Experimental Systems
Intermediate
  • 1,538
  • 15

Work in progress

Exploring Vehicle Artificial Perception in Self-driving technology with DragonBoard 410c and Raspberry Pi 3

IOT Aquarium controller
Intermediate
  • 333
  • 3

Full instructions

An opensource 3D printed aquarium controller with IOT capabilities.

4 Wheel Drive, DC Motor Control for Raspberry Pi
Intermediate
  • 1,297
  • 10

Full instructions

Base project for implementing DC motor control using the Raspberry Pi's I2C interface and an Adafruit 16-Channel Servo Shield.

Overkill GENIE garage door opener
Intermediate
  • 1,082
  • 11

Work in progress

Web app garage door opener with up/down direction detection, https password protection, lots of error detection and activity/error logging.

Arduino - Motor PID Speed Control
Intermediate
  • 817
  • 4

Full instructions

Make a program for the Arduino Pro Mini in Visual Studio to control motor speed with PID which can archive it exactly.

Add projectSign up / Login
Respect project