Hardware components | ||||||
| × | 1 | ||||
| × | 1 | ||||
| × | 1 | ||||
| × | 2 | ||||
| × | 1 | ||||
Software apps and online services | ||||||
| ||||||
| ||||||
| ||||||
| ||||||
| ||||||
| ||||||
Hand tools and fabrication machines | ||||||
|
Internet of Toiletries is a project that makes all of our toiletries smart, it focuses on problems of refilling toiletries such as toothpaste, contact lens solution, lotions, and many other items. Users can track their usage over the phone, and Amazon RDS helps to reorder once it reaches 1/4 of the item weight. The current proof of concept design can hold 2 different items, which we will use to demonstrate the ordering system for Tooth Paste and Contact Lens solution.
I've always find myself out of contact lens solutions and toothpastes, ordering on Amazon generally takes 2 days to ship and running to super market can be a hassle when it's cold outside. These are also items I don't usually buy extra for storage, mainly due to the fact they have expiration date on them. For the proof of concept we are doing 2 items because that's only 2 items I've personally find always missing on my own life. But we can easily expand this to 3 to 4 item units depending on the situation.
The Toiletries uses weight sensor to sense the product weight and sending it to the cloud, this allows user can check their items in real time. When the toiletries reach threshold of 1/4 of the weight it would automatically use Amazon RDS for reordering, allows users to seamlessly getting their toiletries. The trigger would be 4am in the morning for the order checked once a day, this allows users not to have to worry about taking items out of the Unit.
Design of the unitWe've been taking a lot of consideration for the design of the unit including the aesthetic appeal as well as the simplicity for the use, the top unit is high enough to hold items like toothpaste, contact lens solutions as well as many other items. The scale sits in the middle, the hole under the scale plate is used to do the wiring to the bottom portion which holds the battery and PLCs.
The bottom portion is used to hold the chip, the sensor wiring and the battery, the POC was made a little larger on purpose to accommodate different sizes of chips as well as battery, the next version is likely much smaller.
There are 3 components that making Internet of Toiletries work, the code for the chip, the node.js server, and consumer facing Android app.
Arduino 101The IoT chip senses the weight data, then sending it to the cloud every 5 seconds (on POC), this way it allows users to monitor them at the real time. The code is being open sourced and attached below, Arduino 101 is using Wifi Shield, 2x Hx711 Weight Weighing Load Cell Conversion Module Sensors
Alternatively, we were also able to get this working using LinkIt™ Smart 7688 Duo because the MediaTek LinkIt™ Smart 7688 Duo contains the wifi without the shield. The Media kit uses A0, A1 for the first scale, and A2, A3 for the second scale. The mechanism works as MediaTek will upload the sensor data every 5 minutes. The code for MediaTek LinkIt™ using Arduino IDE is being open sourced and attached below.
Node.js server and mysql
The server uses mysql for data storage, which includes updating the weight value as well as getting the data.
Amazon Dash Replenishment
Following the walkthrough of Amazon Dash Replenishment, I was able to setup LWA, SNS and ADR Device. Creating 2 slots on the unit.
Android
The Android app does 3 things. First is allowing user to login with Amazon through LWA, creating an environment allowing user to make purchases.
Second is retrieving and displaying data of the current unit. In the Proof of Concept prototype we've already connected with the device as it is the only device available. Login through RDS and setup the slot items, then loading the weight to see how much does it have left.
Third is where when item is below threshold, android would automatically make a purchase. Amazon Dash Replenishment Service will automatically place the order at 4am in the morning if it is below threshold of 25%.
In the following demo we are showing how the functionalities work with Amazon Dash Replenishment. The reordering system happens at 4am, we just comment a line for the trigger on the demo for the automatic ordering.
Next StepCurrent proof of concept is fully functional and being tested by myself, the very near future I will be improving the design of the casing and sensors and see if there is a market for this item.
Unit Scale
Bottom portion
Arduino Code For LinkIt Smart 7688 Duo and and Arduino 101
ArduinoServer code and Android code will be posted separately on github
#include "HX711.h"
#include <SPI.h>
#include <WiFi.h>
WiFiClient client;
char clientServer[] = "shrouded-citadel-97257.herokuapp.com";
IPAddress ip(192,168,2,3);
char ssid[] = ""; // your network SSID (name)
char pass[] = ""; // your network password
int status = WL_IDLE_STATUS;
HX711 scale1;//(A1,A0);
HX711 scale2;//(A3,A2);
void setup() {
Serial.begin(9600);
if (WiFi.status() == WL_NO_SHIELD) {
Serial.println("WiFi shield not present");
// don't continue:
while(true);
}
// attempt to connect to Wifi network:
while ( status != WL_CONNECTED) {
Serial.print("Attempting to connect to SSID: ");
Serial.println(ssid);
// Connect to WPA/WPA2 network. Change this line if using open or WEP network:
status = WiFi.begin(ssid, pass);
// status = WiFi.begin(ssid);
// wait 10 seconds for connection:
delay(20000);
}
printWifiStatus();
// parameter "gain" is ommited; the default value 128 is used by the library
// HX711.DOUT - pin #A1
// HX711.PD_SCK - pin #A0
scale1.begin(A1, A0);
scale2.begin(A3, A2);
scale1.set_scale(2280.f); // this value is obtained by calibrating the scale with known weights; see the README for details
scale2.tare(); // reset the scale to 0
scale1.set_scale(2280.f); // this value is obtained by calibrating the scale with known weights; see the README for details
scale2.tare();
}
void loop() {
Serial.print("one reading:\t");
Serial.print(scale1.get_units(10), 1);
Serial.print("two reading:\t");
Serial.println(scale2.get_units(10), 1);
String PostData = "{\"product1weight\":" + String(scale1.get_units(10), 1) + ",\"product2weight\":" + String(scale2.get_units(10), 1) + " }";
Serial.println(PostData);
if (client.connect(clientServer, 80)) {
Serial.println("connected");
Serial.println("POST /updatevalue HTTP/1.1");
client.println("POST /updatevalue HTTP/1.1");
client.println("Host: shrouded-citadel-97257.herokuapp.com");
client.println("User-Agent: Internet of Toiltries");
client.println("Content-Type: application/json");
client.print("Content-Length: ");
client.println(PostData.length());
client.println();
client.println(PostData);
client.println();
client.println("Connection: close");
while(client.connected() && !client.available()) delay(1); //waits for data
while (client.connected() && client.available()) { //connected or data available
char c = client.read(); //gets byte from ethernet buffer
Serial.print(c); //prints byte to serial monitor
}
Serial.println();
Serial.println("disconnecting.");
Serial.println("==================");
Serial.println();
client.stop(); //stop client
}
scale1.power_down(); // put the ADC in sleep mode
scale2.power_down(); // put the ADC in sleep mode
delay(5000);
scale1.power_up();
scale2.power_up();
}
void printWifiStatus() {
// print the SSID of the network you're attached to:
Serial.print("SSID: ");
Serial.println(WiFi.SSID());
// print your WiFi shield's IP address:
ip = WiFi.localIP();
Serial.print("IP Address: ");
Serial.println(ip);
// print the received signal strength:
long rssi = WiFi.RSSI();
Serial.print("signal strength (RSSI):");
Serial.print(rssi);
Serial.println(" dBm");
// check firmware version
Serial.print("Firmware version: ");
Serial.println(WiFi.firmwareVersion());
}
package hack.internetoftoiletries;
import android.app.Activity;
import android.content.Context;
import android.content.SharedPreferences;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.support.v7.app.AppCompatActivity;
import android.util.Base64;
import android.util.Log;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;
import com.amazon.identity.auth.device.AuthError;
import com.amazon.identity.auth.device.api.Listener;
import com.amazon.identity.auth.device.api.authorization.AuthCancellation;
import com.amazon.identity.auth.device.api.authorization.AuthorizationManager;
import com.amazon.identity.auth.device.api.authorization.AuthorizeListener;
import com.amazon.identity.auth.device.api.authorization.AuthorizeRequest;
import com.amazon.identity.auth.device.api.authorization.AuthorizeResult;
import com.amazon.identity.auth.device.api.authorization.ProfileScope;
import com.amazon.identity.auth.device.api.authorization.Scope;
import com.amazon.identity.auth.device.api.authorization.User;
import com.amazon.identity.auth.device.api.workflow.RequestContext;
import com.amazon.identity.auth.device.AuthError;
import com.amazon.identity.auth.device.authorization.api.AmazonAuthorizationManager;
import com.amazon.identity.auth.device.authorization.api.AuthorizationListener;
import com.amazon.identity.auth.device.authorization.api.AuthzConstants;
import org.codeandmagic.android.gauge.GaugeView;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLEncoder;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import okhttp3.FormBody;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
public class MainActivity extends AppCompatActivity {
private static final String TAG = MainActivity.class.getName();
public static final MediaType JSON
= MediaType.parse("application/json; charset=utf-8");
public static final MediaType STRING
= MediaType.parse("application/x-www-form-urlencoded");
public String DRS_URL = "https://dash-replenishment-service-na.amazon.com/replenish/";
private TextView mProfileText;
private TextView mProfileText2;
private TextView mLogoutTextView;
private ProgressBar mLogInProgress;
private RequestContext requestContext;
private boolean mIsLoggedIn;
private View mLoginButton;
private ViewGroup mWrapperProfile;
private GaugeView mGaugeView1;
private GaugeView mGaugeView2;
private TextView product1;
private TextView product2;
private ScheduledFuture<?> future;
private ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
OkHttpClient client = new OkHttpClient();
private String slot1 = "f76a78ff-d73b-4c64-967f-d28f54645c9d";
private String slot2 = "59a29d6d-39f3-4adb-8b88-96fc5e2261cc";
private AmazonAuthorizationManager mAuthManager;
private boolean started = false;
private Handler handler = new Handler();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mAuthManager = new AmazonAuthorizationManager(this, Bundle.EMPTY);
requestContext = RequestContext.create(this);
/*
requestContext.registerListener(new AuthorizeListener() {
@Override
public void onSuccess(AuthorizeResult authorizeResult) {
runOnUiThread(new Runnable() {
@Override
public void run() {
// At this point we know the authorization completed, so remove the ability to return to the app to sign-in again
setLoggingInState(true);
}
});
fetchUserProfile();
}
@Override
public void onError(AuthError authError) {
Log.e(TAG, "AuthError during authorization", authError);
runOnUiThread(new Runnable() {
@Override
public void run() {
showAuthToast("Error during authorization. Please try again.");
resetProfileView();
setLoggingInState(false);
}
});
}
@Override
public void onCancel(AuthCancellation authCancellation) {
Log.e(TAG, "User cancelled authorization");
runOnUiThread(new Runnable() {
@Override
public void run() {
showAuthToast("Authorization cancelled");
resetProfileView();
}
});
}
});*/
setContentView(R.layout.activity_main);
initializeUI();
//new HttpGetRequestRefill().execute("");
start();
//Schedule for every 24 hours, this is just for demo, will be used in the future
Runnable runnable = new Runnable() {
@Override
public void run() {
SharedPreferences sharedPref = MainActivity.this.getPreferences(Context.MODE_PRIVATE);
if(sharedPref.contains("access_token") && sharedPref.contains("refresh_token"))
{
new HttpGetRequestRefill().execute("");
}
}
};
//schedule this once every day
future = scheduler.scheduleAtFixedRate(runnable, 0, 1, TimeUnit.DAYS);
}
private Runnable runnable = new Runnable() {
@Override
public void run() {
new HttpGetRequest().execute("");
start();
}
};
public void start() {
started = true;
handler.postDelayed(runnable, 2000);
}
@Override
protected void onResume() {
super.onResume();
requestContext.onResume();
}
@Override
protected void onStart() {
super.onStart();
SharedPreferences sharedPref = MainActivity.this.getPreferences(Context.MODE_PRIVATE);
if(sharedPref.contains("refresh_token") && sharedPref.contains("access_token"))
{
mLoginButton.setVisibility(View.GONE);
mWrapperProfile.setVisibility(View.VISIBLE);
}
else
{
mLoginButton.setVisibility(View.VISIBLE);
mWrapperProfile.setVisibility(View.GONE);
}
/*
Scope[] scopes = {ProfileScope.profile(), ProfileScope.postalCode()};
AuthorizationManager.getToken(this, scopes, new Listener<AuthorizeResult, AuthError>() {
@Override
public void onSuccess(AuthorizeResult result) {
if (result.getAccessToken() != null) {
fetchUserProfile();
mAccessToken = result.getAccessToken();
} else {
}
}
@Override
public void onError(AuthError ae) {
}
});*/
}
private void fetchUserProfile() {
User.fetch(this, new Listener<User, AuthError>() {
/* fetch completed successfully. */
@Override
public void onSuccess(User user) {
final String name = user.getUserName();
final String email = user.getUserEmail();
final String account = user.getUserId();
final String zipCode = user.getUserPostalCode();
runOnUiThread(new Runnable() {
@Override
public void run() {
updateProfileData(name, email, account, zipCode);
}
});
}
/* There was an error during the attempt to get the profile. */
@Override
public void onError(AuthError ae) {
runOnUiThread(new Runnable() {
@Override
public void run() {
setLoggedOutState();
String errorMessage = "Error retrieving profile information.\nPlease log in again";
Toast errorToast = Toast.makeText(getApplicationContext(), errorMessage, Toast.LENGTH_LONG);
errorToast.setGravity(Gravity.CENTER, 0, 0);
errorToast.show();
}
});
}
});
}
private void updateProfileData(String name, String email, String account, String zipCode) {
StringBuilder profileBuilder = new StringBuilder();
profileBuilder.append(String.format("Welcome, %s!\n", name));
profileBuilder.append(String.format("Your email is %s\n", email));
profileBuilder.append(String.format("Your zipCode is %s\n", zipCode));
final String profile = profileBuilder.toString();
Log.d(TAG, "Profile Response: " + profile);
runOnUiThread(new Runnable() {
@Override
public void run() {
updateProfileView(profile);
setLoggedInState();
}
});
}
/**
* Initializes all of the UI elements in the activity
*/
private void initializeUI() {
mWrapperProfile = (ViewGroup)findViewById(R.id.wrapperProfile);
mLoginButton = findViewById(R.id.login_with_amazon);
mLoginButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Bundle options = new Bundle();
// device_model is generated by the wizard when you create a device - replace "modelX"; serial is something you provide and should be visible to the customer - replace "serialY".
String scope_data = "{\"dash:replenish\":{\"device_model\":\"Internet_of_Toiletries\", \"serial\":\"0\", \"is_test_device \":\"true\"} }";
options.putString(AuthzConstants.BUNDLE_KEY.SCOPE_DATA.val, scope_data);
// Request the authorization code instead of an access token
options.putBoolean(AuthzConstants.BUNDLE_KEY.GET_AUTH_CODE.val, true);
// Plain = code verifier; S256 uses a Base64url encoding of the code verifier's hash
options.putString(AuthzConstants.BUNDLE_KEY.CODE_CHALLENGE.val, "e9598da04c204deaf2dff8892efdd9cb0e180b44f406c31ee916175a99511231");
// Set code challenge method - "plain" or "S256"
options.putString(AuthzConstants.BUNDLE_KEY.CODE_CHALLENGE_METHOD.val, "plain");
mAuthManager.authorize(new String []{"dash:replenish"}, options, new AuthorizeListener());
/*
AuthorizationManager.authorize(
new AuthorizeRequest.Builder(requestContext)
.addScopes(ProfileScope.profile(), ProfileScope.postalCode())
.build()
);*/
}
});
mGaugeView1 = (GaugeView)findViewById(R.id.gauge_view1);
mGaugeView1.setTargetValue(0);
mGaugeView1.initDrawingRects();
mGaugeView2 = (GaugeView)findViewById(R.id.gauge_view2);
mGaugeView2.setTargetValue(0);
mGaugeView2.initDrawingRects();
product1 = (TextView)findViewById(R.id.product1);
product2 = (TextView)findViewById(R.id.product2);
// Find the button with the logout ID and set up a click handler
View logoutButton = findViewById(R.id.logout);
logoutButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
AuthorizationManager.signOut(getApplicationContext(), new Listener<Void, AuthError>() {
@Override
public void onSuccess(Void response) {
runOnUiThread(new Runnable() {
@Override
public void run() {
setLoggedOutState();
}
});
}
@Override
public void onError(AuthError authError) {
Log.e(TAG, "Error clearing authorization state.", authError);
}
});
}
});
String logoutText = getString(R.string.logout);
mProfileText = (TextView) findViewById(R.id.profile_info);
mProfileText2 = (TextView) findViewById(R.id.profile_info_2);
mLogoutTextView = (TextView) logoutButton;
mLogoutTextView.setText(logoutText);
mLogInProgress = (ProgressBar) findViewById(R.id.log_in_progress);
}
/**
* Sets the text in the mProfileText {@link TextView} to the value of the provided String.
*
* @param profileInfo the String with which to update the {@link TextView}.
*/
private void updateProfileView(String profileInfo) {
Log.d(TAG, "Updating profile view");
mProfileText.setText(profileInfo);
mProfileText2.setText(profileInfo);
}
/**
* Sets the text in the mProfileText {@link TextView} to the prompt it originally displayed.
*/
private void resetProfileView() {
setLoggingInState(false);
mProfileText.setText(getString(R.string.default_message));
}
/**
* Sets the state of the application to reflect that the user is currently authorized.
*/
private void setLoggedInState() {
mLoginButton.setVisibility(Button.GONE);
setLoggedInButtonsVisibility(Button.VISIBLE);
mIsLoggedIn = true;
setLoggingInState(false);
}
/**
* Sets the state of the application to reflect that the user is not currently authorized.
*/
private void setLoggedOutState() {
mLoginButton.setVisibility(Button.VISIBLE);
setLoggedInButtonsVisibility(Button.GONE);
mIsLoggedIn = false;
resetProfileView();
}
/**
* Changes the visibility for both of the buttons that are available during the logged in state
*
* @param visibility the visibility to which the buttons should be set
*/
private void setLoggedInButtonsVisibility(int visibility) {
mLogoutTextView.setVisibility(visibility);
}
/**
* Turns on/off display elements which indicate that the user is currently in the process of logging in
*
* @param loggingIn whether or not the user is currently in the process of logging in
*/
private void setLoggingInState(final boolean loggingIn) {
if (loggingIn) {
mLoginButton.setVisibility(Button.GONE);
setLoggedInButtonsVisibility(Button.GONE);
mLogInProgress.setVisibility(ProgressBar.VISIBLE);
mProfileText.setVisibility(TextView.GONE);
mWrapperProfile.setVisibility(View.GONE);
} else {
if (mIsLoggedIn) {
setLoggedInButtonsVisibility(Button.VISIBLE);
mProfileText.setVisibility(TextView.VISIBLE);
mWrapperProfile.setVisibility(View.VISIBLE);
} else {
mLoginButton.setVisibility(Button.VISIBLE);
mProfileText.setVisibility(TextView.GONE);
mWrapperProfile.setVisibility(View.GONE);
}
mLogInProgress.setVisibility(ProgressBar.GONE);
}
}
private void showAuthToast(String authToastMessage) {
Toast authToast = Toast.makeText(getApplicationContext(), authToastMessage, Toast.LENGTH_LONG);
authToast.setGravity(Gravity.CENTER, 0, 0);
authToast.show();
}
public class DashAuthorize extends AsyncTask<String, Void, String> {
@Override
protected String doInBackground(String... params){
String result = null;
try {
if(params.length == 0 || params[0] == null)
{
return null;
}
RequestBody body = RequestBody.create(STRING, params[0]);
Request AMZNrequest = new Request.Builder()
.url("https://api.amazon.com/auth/O2/token")
.post(body)
.build();
Response AMZNresponse = client.newCall(AMZNrequest).execute();
String responseBody = AMZNresponse.body().string();
Log.e("responseBody", responseBody);
JSONObject authData = new JSONObject(responseBody);
SharedPreferences sharedPref = MainActivity.this.getPreferences(Context.MODE_PRIVATE);
SharedPreferences.Editor editor = sharedPref.edit();
if(authData.has("access_token"))
{
editor.putString("access_token", authData.getString("access_token"));
editor.commit();
}
if(authData.has("refresh_token"))
{
editor.putString("refresh_token", authData.getString("refresh_token"));
editor.commit();
}
return responseBody;
}
catch(IOException e){
e.printStackTrace();
result = null;
} catch (JSONException e) {
e.printStackTrace();
}
return result;
}
protected void onPostExecute(String result){
super.onPostExecute(result);
if(result != null)
{
try {
JSONObject authData = new JSONObject(result);
if(authData.has("refresh_token")) {
mLoginButton.setVisibility(View.GONE);
}
} catch (JSONException e) {
e.printStackTrace();
}
Log.e("stuff", result);
}
}
}
public class DashRefresh extends AsyncTask<String, Void, String> {
@Override
protected String doInBackground(String... params){
String result = null;
try {
SharedPreferences sharedPref = MainActivity.this.getPreferences(Context.MODE_PRIVATE);
if(!sharedPref.contains("access_token") || !sharedPref.contains("refresh_token") || !sharedPref.contains("client_id"))
{
return null;
}
String bodyraw = "grant_type=refresh_token&refresh_token=" + sharedPref.getString("sharedPref", "")
+ "&client_id=" + sharedPref.getString("client_id", "");
RequestBody body = RequestBody.create(STRING, bodyraw);
Request AMZNrequest = new Request.Builder()
.url("https://api.amazon.com/auth/O2/token")
.post(body)
.build();
Response AMZNresponse = client.newCall(AMZNrequest).execute();
String responseBody = AMZNresponse.body().string();
Log.e("responseBody", responseBody);
JSONObject authData = new JSONObject(responseBody);
SharedPreferences.Editor editor = sharedPref.edit();
if(authData.has("access_token"))
{
editor.putString("access_token", authData.getString("access_token"));
editor.commit();
}
if(authData.has("refresh_token"))
{
editor.putString("refresh_token", authData.getString("refresh_token"));
editor.commit();
}
return responseBody;
}
catch(IOException e){
e.printStackTrace();
result = null;
} catch (JSONException e) {
e.printStackTrace();
}
return result;
}
protected void onPostExecute(String result){
super.onPostExecute(result);
super.onPostExecute(result);
if(result != null)
{
try {
JSONObject authData = new JSONObject(result);
if(authData.has("refresh_token")) {
mLoginButton.setVisibility(View.GONE);
}
} catch (JSONException e) {
e.printStackTrace();
}
Log.e("stuff", result);
new HttpGetRequestRefill().execute("");
}
}
}
public class HttpGetRequest extends AsyncTask<String, Void, String> {
@Override
protected String doInBackground(String... params){
String result;
String inputLine;
try {
Request request = new Request.Builder()
.url("https://shrouded-citadel-97257.herokuapp.com/getproduct")
.build();
Response response = client.newCall(request).execute();
if (!response.isSuccessful()) {
return null;
}
return response.body().string();
}
catch(IOException e){
e.printStackTrace();
result = null;
}
return result;
}
protected void onPostExecute(String result){
super.onPostExecute(result);
if(result != null)
{
try {
JSONArray data = new JSONArray(result);
if(data.length() > 0)
{
JSONObject item = data.getJSONObject(0);
String product1_desc = item.optString("Product1Name", "");
String product2_desc = item.optString("Product2Name", "");
float product_ratio1 = (float) (item.getDouble("Product1weight") / item.getDouble("Product1Max"));
float product_ratio2 = (float) (item.getDouble("Product2weight") / item.getDouble("Product2Max"));
product1.setText(product1_desc);
product2.setText(product2_desc);
mGaugeView1.setTargetValue(product_ratio1 * 100.0f);
mGaugeView2.setTargetValue(product_ratio2 * 100.0f);
}
} catch (JSONException e) {
e.printStackTrace();
}
}
}
}
//Amazon Dash
public class HttpGetRequestRefill extends AsyncTask<String, Void, String> {
@Override
protected String doInBackground(String... params){
String result = null;
try {
Request request = new Request.Builder()
.url("https://shrouded-citadel-97257.herokuapp.com/getproduct")
.build();
Response response = client.newCall(request).execute();
if (!response.isSuccessful())
{
return null;
}
String jsonresult = response.body().string();
Log.e("result", jsonresult);
JSONArray data = new JSONArray(jsonresult);
if(data.length() > 0)
{
JSONObject item = data.getJSONObject(0);
float product_ratio1 = (float) (item.getDouble("Product1weight") / item.getDouble("Product1Max"));
float product_ratio2 = (float) (item.getDouble("Product2weight") / item.getDouble("Product2Max"));
String url = "";
//If first product is smaller than 25%
//if(product_ratio1 * 100.0f < 25.0f)
//{
url = DRS_URL + slot1;
//}
//If second product is smaller than 25%
if(product_ratio2 * 100.0f < 25.0f)
{
url = DRS_URL + slot2;
}
SharedPreferences sharedPref = MainActivity.this.getPreferences(Context.MODE_PRIVATE);
RequestBody body = RequestBody.create(JSON, "");
Request AMZNrequest = new Request.Builder()
.addHeader("Authorization", "Bearer " + sharedPref.getString("access_token", ""))
.addHeader("x-amzn-accept-type", "com.amazon.dash.replenishment.DrsReplenishResult@1.0")
.addHeader("x-amzn-type-version", "com.amazon.dash.replenishment.DrsReplenishInput@1.0")
.url(url)
.post(body)
.build();
Response AMZNresponse = client.newCall(AMZNrequest).execute();
String responseBody = AMZNresponse.body().string();
return responseBody;
}
}
catch(IOException e){
e.printStackTrace();
result = null;
}
catch (JSONException e) {
e.printStackTrace();
result = null;
}
return result;
}
protected void onPostExecute(String result){
super.onPostExecute(result);
if(result != null)
{
JSONObject order = null;
try {
order = new JSONObject(result);
if(!order.has("eventInstanceId"))
{
new DashRefresh().execute("");
}
} catch (JSONException e) {
e.printStackTrace();
}
Log.e("result", result);
}
}
}
public class AuthorizeListener implements AuthorizationListener {
/* Authorization was completed successfully. */
@Override
public void onSuccess(Bundle response) {
try {
String authorizationCode = response.getString(AuthzConstants.BUNDLE_KEY.AUTHORIZATION_CODE.val);
String clientId = mAuthManager.getClientId();
String redirectUri = mAuthManager.getRedirectUri();
SharedPreferences sharedPref = MainActivity.this.getPreferences(Context.MODE_PRIVATE);
SharedPreferences.Editor editor = sharedPref.edit();
editor.putString("client_id", clientId);
editor.commit();
/*
RequestBody body = new FormBody.Builder()
.add("grant_type", "authorization_code")
.add("code", authorizationCode)
.add("redirect_uri", redirectUri)
.add("client_id", clientId)
.add("code_verifier", "e9598da04c204deaf2dff8892efdd9cb0e180b44f406c31ee916175a99511231")
.build();*/
String body = "grant_type=authorization_code&code=" + authorizationCode + "&redirect_uri=" + redirectUri
+ "&client_id=" + clientId + "&code_verifier=e9598da04c204deaf2dff8892efdd9cb0e180b44f406c31ee916175a99511231";
Log.e("doh", body);
//Getting authorized
new DashAuthorize().execute(body);
} catch (AuthError authError) {
authError.printStackTrace();
}
}
/* There was an error during the attempt to authorize the application. */
@Override
public void onError(AuthError ae) {
String errorResponse = ae.getMessage();
if(errorResponse != null)
{
Log.e("doh", errorResponse);
}
}
/* Authorization was cancelled before it could be completed. */
@Override
public void onCancel(Bundle cause) {
}
}
}
var express = require('express');
var mysql = require('mysql');
var app = express();
var bodyParser = require('body-parser');
var jsonParser = bodyParser.json();
require('dotenv').config()
var connection = mysql.createConnection({
host : process.env.RDS_HOSTNAME,
user : process.env.RDS_USERNAME,
password : process.env.RDS_PASSWORD,
port : process.env.RDS_PORT,
database : process.env.RDS_DB
});
app.set('port', (process.env.PORT || 5000));
app.use(express.static(__dirname + '/public'));
// views is directory for all template files
app.set('views', __dirname + '/views');
app.set('view engine', 'ejs');
app.get('/', function(request, response) {
console.log(process.env.RDS_HOSTNAME);
response.render('pages/index');
});
connection.connect(function(err) {
if (err) {
console.error('error connecting: ' + err.stack);
return;
}
console.log('connected as id ' + connection.threadId);
});
app.get('/getproduct', function(request, response) {
connection.query('Select * from products where id = 0', function(err, results) {
if(err) throw err;
console.log(results);
response.send(results);
});
});
//just updating demo unit for now, in the future we will update it by id
//this portion requires the service to allow me to change items on the slots
app.post('/updateproduct', jsonParser, function(request, response) {
if (!request.body) return response.sendStatus(400);
connection.query('UPDATE products SET Product1 = ?, Product2 = ?, Product1Max= ?, Product2Max = ?, Product1Name = ?, Product2Name =? WHERE id = 0',
[request.body.product1, request.body.product2, request.body.product1max, request.body.product2max, request.body.product1name, request.body.product2name], function(err, results) {
if(err) throw err;
console.log("success");
});
response.sendStatus(200);
});
//just updating demo unit for now, in the future we will update it by id
app.post('/updatevalue', jsonParser, function(request, response) {
if (!request.body) return response.sendStatus(400);
connection.query('UPDATE products SET Product1weight = ?, Product2weight = ? WHERE id = 0',
[request.body.product1weight, request.body.product2weight], function(err, results) {
if(err) throw err;
console.log("success");
});
response.sendStatus(200);
});
app.listen(app.get('port'), function() {
console.log('Node app is running on port', app.get('port'));
});
Comments