Amazon Pricing Notifier
Made by Kami Chin, Ryan Stinebaugh and Samuel Lee
Made by Kami Chin, Ryan Stinebaugh and Samuel Lee
This project is an ambient device which will open a chest when an item on the user's personal wishlist goes under a target price
Created: February 15th, 2018
This project is designed to display personal data in a public way. We chose to create a device that shows when something on the user's Amazon wish list goes on sale. The device uses the Amazon API to get data about the user's personal wish list and what is currently on sale at Amazon. This information is shown to the user by opening an old amazon box automatically through the use of servo motors.
1. Modified the code found on http://diotlabs.daraghbyrne.me/6-controlling-outputs/servo/ to control 2 Servo motors. Code is listed below.
2. Created the code to access the Amazon API. Our code can be found below.
2. Used the Amazon API to alert our Particle when a target item on Amazon is on sale.
3. Attached two Servo motors to the insides of a box using string and duct tape to automatically open the box when triggered by the Particle.
We considered different methods of opening a box. As illustrated below, we thought about opening the box via a "sliding door" method, drawing a curtain, or using a front flap. Ultimately, we chose to open the box using the two top flaps of the box because it was simple, easy to implement with two Servo motors, and the most noticeable state change.
We started making the self opening box by poking two holes for the servo motor. We then threaded the wires through for the motor making sure to leave enough slack in the line to re position the motors. We first tried mounting the servos inside on the bottom surface of the box and ran thin wire outside of the box to "pull" the box open. Our hope was that we could hide the motors with a false bottom, so it would look like a more finished produce. After struggling to get this working, we changed the design by moving the motors higher.
The new design placed the motors centered directly below the "hinge" of the box flaps. The motors were held in place by duct tape and string, but this can be replaced by a stronger form of joining such as glue or screws. Since the included servo fin was not long enough to open the box entirely, we used two alligator clip heads to extend the length of the lever arm. The alligator clips sometimes fell out of place so we added duct tape to the connection point as well.
The code below is made to go on to the particle device, and does not need to be updated if the user wants to change the item they are tracking. The purpose of this code is to check for an update in the particle cloud for a push from the Amazon API code and to tell the two servo motors to open and disengage after a set amount of time.
// Code for particle servo control
/*
* Project Ambient
* Description: Detects amazon price changes and opens a treasure box
* Author: Samuel Lee, Ryan Stinebaugh, Kami Chin
* Date:
*/
int servo_pin_1 = D0;
int servo_pin_2 = D1 ;
int device_on = HIGH ;
int box_open = 0 ; //should be closed in natural state
Servo myServo1 ;
Servo myServo2 ;
//function will be exposed to cloud. args not used
//called when wave is to be performed
int servoWave(String args) {
//perform wave
if(device_on == LOW) {
return 0 ;
}
const int leftAngle = 0 ;
const int rightAngle = 100 ;
const int delayPeriod = 500 ;
int numWaves = 4 ;
for(int w =0; w < numWaves ; w++) {
if(w%2) {
//odd iteration
myServo1.write(leftAngle) ;
}
else {
myServo1.write(rightAngle) ;
}
delay(delayPeriod) ;
}
//reset position
myServo1.write(leftAngle) ;
delay(delayPeriod) ;
return 1;
}
//called asynchronously
int servoOpenBox(String args) {
if(device_on == LOW || box_open) {
return 0 ;
}
const int closedAngle = 0 ;
const int openAngle = 100 ;
const int delayPeriod = 3000 ;
//assumes closed
myServo1.write(openAngle) ;
myServo2.write(openAngle) ;
box_open = 1 ; //signal box is open
delay(delayPeriod) ;
//reset position
myServo1.write(closedAngle) ;
myServo2.write(closedAngle) ;
box_open = 0 ; //closed box
return 1;
}
// setup() runs once, when the device is first turned on.
void setup() {
// Put initialization like pinMode and begin functions here.
myServo1.attach(servo_pin_1);
myServo2.attach(servo_pin_2);
//ensure it's at 0 position
myServo1.write(0) ;
myServo2.write(0) ;
//test servo
myServo1.write(100) ;
myServo2.write(100) ;
delay(500) ;
myServo1.write(0) ;
myServo2.write(0) ;
Particle.function("servoWave", servoWave) ;
Particle.function("servoOpenBox", servoOpenBox) ;
}
//main logic controlled by external server
void loop() {
//TODO add logic to change device_on based on digital input
}
Click to Expand
This code works with the Amazon API to track a desired item on their website. A target price is set by the user to determine when they would like to be notified, and once that threshold is passed, a notification is sent through the particle cloud to tell the designated particle device to run the function to open the motors
from amazon.api import AmazonAPI
import time, threading
import requests
access_key = "YOUR AMAZON PRODUCT ADVERTISING ACCESS KEY"
secret_key = "YOUR AMAZON PRODUCT ADVERTISING SECRET KEY"
associate_id = "YOUR AMAZON PRODUCT ADVERTISING ASSOCIATE ID"
amazon = AmazonAPI(access_key, secret_key, associate_id, region="US")
device_id = "YOUR PARTICLE DEVICE ID"
particle_access_token = "YOUR PARTICLE ACCESS TOKEN"
check_freq = 60 # in seconds
item_id = 'AMAZON PRODUCT ID FOR DESIRED PRODUCT TO PURCHASE'
item_price = 59.99 # set this to the current market price for the item
target_price = 47.99 # set this to desired purchase price
def servoOpenBox():
global device_id, particle_access_token
url = "https://api.particle.io/v1/devices/{}/{}".format(device_id, "servoOpenBox")
res = requests.post(url, data={"arg":"", "access_token":particle_access_token})
if res.status_code != requests.codes.ok:
print "Bad POST request. Error {}".format(res.status_code)
else:
# print "Good Request"
print ""
def alertPriceDrop():
if item_price <= target_price:
# servoWave()
print "Price Dropped Target = {} Current = {}".format(target_price, item_price)
servoOpenBox()
def update_price():
global check_freq, item_price, item_id, amazon
print time.ctime()
item = amazon.lookup(ItemId=item_id)
item_price = float(item.price_and_currency[0])
alertPriceDrop()
# for simulation purposes
def simulate_update_price():
global item_price, target_price
# simulate_check_freq = 10 #in seconds
high_price = 59.99
low_price = target_price
if item_price <= low_price:
item_price = high_price
else:
item_price = low_price
alertPriceDrop()
# threading.Timer(simulate_check_freq, simulate_update_price).start()
class UpdateThread(threading.Thread):
def __init__(self, update_func, period):
threading.Thread.__init__(self)
self.update = update_func
self.period = period
self.event = threading.Event()
def stop(self):
self.event.set()
def run(self):
while not self.event.wait(self.period):
self.update()
def setup():
global amazon, item_id
item = amazon.lookup(ItemId=item_id)
# print "{}".format("abc")
print "Name = {}, price = {}".format(item.title, item.price_and_currency)
item_price = float(item.price_and_currency[0])
print item_price
def run():
setup()
updateThread = UpdateThread(update_price, check_freq)
updateThread.start()
while 1:
cmd = raw_input()
if cmd == "stop":
print "stopping..."
updateThread.stop()
break
return
if __name__ == "__main__":
run()
Click to Expand
If we were to make this concept into a product fit for market, we would need to add a way for the user know which item on their list was on sale. This could be done through a inside of the box, so the user would have to look inside to get the information. Currently our prototype follows one product, which is defined by putting the amazon item number in the code that accesses the Amazon API. We would also need to simplify this experience for the user, and one way this could be done is through a mobile application or even creating an IFTTT widget for what we produced through our code. I think we also would want to redesign the box so that the motors are hidden. This could be done through adding an inner box where the motor could sit in between the layers. This would also protect the motor from being broken when the user is reaching inside the box.
A hands-on introductory course exploring the Internet of Things and connected product experiences.
This project is an ambient device which will open a chest when an item on the user's personal wishlist goes under a target price