Hardware components | ||||||
| × | 1 | ||||
| × | 1 | ||||
| × | 1 | ||||
| × | 1 | ||||
| × | 1 | ||||
| × | 1 | ||||
| × | 2 | ||||
Software apps and online services | ||||||
|
During transportation of goods there are several factors that contributes to damage of goods. It can be a deliberate act or accidental. But receiving party might not notice this unless opened while receiving the goods.
This project intends to provide an effective monitoring unit which can be used to monitor the container's health in terms of temperature, humidity, tilt and when and for how long the container was opened.
This system consists of various sensors attached to a single MCU with WiFi capabilities. Ideally, connectivity using 3G/4G module is suited for this kind of application. Since I have no 3G/4G module, for my prototype, I chose WiFi connectivity. Below are the components used in this project,
- Redbear's CC3200 WiFi Micro: This is the main entity responsible for collecting sensor data and posting it on to cloud.
- DHT22: This module is used to fetch real-time temperature and humidity inside container. This is connected to D2 pin of CC3200.
- MQ135: This gas/smoke used to monitor air condition inside the container. Analog out from MQ135 is connected to A1 pin of CC3200. ADC channel is 1.5v tolerant, so voltage divider is required as shown in schematics.
- MPU6050: This used to detect container tilt along x-axis. This module communicates over I2C.
- IR transceiver: This is placed near door so that whenever door is opened the IR will not be reflected back, hence detecting opening of door. This module
- EM-411: This is GPS module which is connected to CC3200's RX0 pin.
Idea is to build a configurable system which can be modified by user at any given moment within lifetime of the container delivery. To achieve this an android application is developed which has following features,
- Fetching and displaying real-time data which includes temperature, humidity, air quality within container, tilt and GPS coordinates.
- Using GPS coordinates, locating container on Google Maps.
- Configuring alert parameters which play role is alerting user by sending emails whenever certain limits are exceeded.
For this project, a new device type is created, LHMS_parameters. This device type is now public. Manifest of LHMS_parameters looks as shown below. The convention followed here is, suffix "rt" is for real-time data, suffix "alert_mail" is used by Artik cloud rules engine to send alert emails, suffix "value" and "threshold" for compare parameters used by Artik rules engine.
Below are few screenshots of android app. Welcome screen would look like below image,
When clicked on "Get Real-time data" would update screen as shown below.
Below is "Configure parameters" view.
Below is the screenshot of radiobuttons for enabling/disabling email alerts.
Below is the screenshot of real-time data viewed on Artik cloud charts.
Rules engine is configured to send mails of violations only if "alert_mail" parameter is set to "true". For door opening event there is no "alert_mail" parameter, this alert is sent whenever door is opened because this is event can be very harmful and dangerous.
Below is the video demonstrating the rich GUI which is simple to use and allows reconfigurability of parameters without much fuzz. Reception of "door open" alert can be seen in this video.
Necessary files building android app is attached. It has 4 "activity",
- MainActivity: Handles login and web view.
- WelcomActivity: Welcome screen, gives two options, "Configure parameters" and "Get real-time data"
- MessageActivity: Handles configuring parameters and updating Artik cloud appropriately.
- RTActivity: Fetches latest data from cloud and displays it. Also provides an interface to view container location on Google Maps.
This is just a showcase of what can be achieved using Artik cloud and its powerful rules engine. This project can improve on certain aspects such as logging data locally whenever the system fails to connect with the cloud due to bad network and push stored data whenever the connection with cloud is established.
#include <ArduinoJson.h>
#include <WiFi.h>
#include "DHT.h"
#include <Wire.h>
#include <TinyGPS.h>
#define DHTPIN 2
#define MQ135PIN A1
#define DOORPIN 3
#define DHTTYPE DHT22
#define MPU_ADDR 0x68
#define ACC_XOUT_H 0x3B
#define LED RED_LED
DHT dht(DHTPIN, DHTTYPE);
TinyGPS gps;
// Web REST API params
char server[] = "api.artik.cloud";
int port = 443; //(port 443 is default for HTTPS)
String AuthorizationData = "Authorization: Bearer <DEVICE_TOKEN>";
char buf[200];
int ledState = 0;
int MPU_zero_value = 0;
WiFiClient client;
char ssid[] = ""; // your network SSID (name)
char pass[] = "";
int status = WL_IDLE_STATUS;
int read_MPU_X(void)
{
Wire.beginTransmission(MPU_ADDR);
Wire.write(ACC_XOUT_H);
Wire.endTransmission(false);
Wire.requestFrom(MPU_ADDR, 2, true); // request a total of 14 registers
return (Wire.read() << 8 | Wire.read());
}
int filter_MPU_X(void)
{
int i;
long res = 0;
for (i = 0; i < 8; i++)
{
res += read_MPU_X();
}
res = res / 8;
return (res - MPU_zero_value);
}
void calibrate_MPU(void)
{
int i;
long res = 0;
/* Wake up MPU6050 */
Wire.beginTransmission(MPU_ADDR);
Wire.write(0x6B);
Wire.write(0);
Wire.endTransmission(true);
for (i = 0; i < 8; i++)
{
res += filter_MPU_X();
}
MPU_zero_value = res / 8;
}
void setup() {
pinMode(LED,OUTPUT);
Serial.begin(4800);
dht.begin();
Wire.begin();
calibrate_MPU();
pinMode(DOORPIN, INPUT_PULLUP);
while (status != WL_CONNECTED){
Serial.println("Connecting");
status = WiFi.begin(ssid,pass);
}
Serial.println("Connected!!!");
}
void loop() {
float flat, flon;
unsigned long age;
ledToggle();
client.sslConnect(server, port);
smartdelay(1000);
if (client.connected()) {
float temp = dht.readTemperature();
float humd = dht.readHumidity();
int smoke = analogRead(MQ135PIN);
int tilt = filter_MPU_X();
bool door = digitalRead(DOORPIN);
gps.f_get_position(&flat, &flon, &age);
client.println("POST /v1.1/messages HTTP/1.1");
client.println("Host: api.artik.cloud");
client.println("Accept: */*");
client.println("Content-Type: application/json");
client.println("Connection: close");
client.println(AuthorizationData);
// Automated POST data section
client.print("Content-Length: ");
client.println(loadBuffer(temp , humd, tilt, smoke, door, flat, flon)); // loads buf, returns length
client.println();
client.println(buf);
client.stop();
Serial.println("Data Posted");
smartdelay(2000);
}
}
/* Using Json support, precision of GPS coordinates are lost.
Json dataPair supports only 2-digit fractional
load_gps fills buf retaining full precision.
*/
int load_gps(float flat, float flon)
{
char temp[64];
int i = strlen(buf);
buf[i - 2] = ',';
buf[i - 1] = '\0';
int n = flat;
float f = abs(flat - n);
int f_n = f * 1000000;
sprintf(temp, "\"GPS_lat_rt\":%d.%06d,", n, f_n);
strcat(buf, temp);
n = flon;
f = abs(flat - n);
f_n = f * 1000000;
sprintf(temp, "\"GPS_lon_rt\":%d.%06d", n, f_n);
strcat(buf, temp);
i = strlen(buf);
buf[i++] = '}';
buf[i++] = '}';
buf[i] = '\0';
Serial.println(buf);
return i;
}
int loadBuffer(int insTemp, int insHumid, int insTilt, int insGas, bool insDoor, float insGlat, float insGlon ) {
StaticJsonBuffer<200> jsonBuffer; // reserve spot in memory
JsonObject& root = jsonBuffer.createObject(); // create root objects
root["sdid"] = "<DEVICE_ID>"; // FIX
root["type"] = "message";
JsonObject& dataPair = root.createNestedObject("data"); // create nested objects
dataPair["temp_rt"] = insTemp;
dataPair["humid_rt"] = insHumid;
dataPair["tilt_rt"] = insTilt;
dataPair["gas_rt"] = insGas;
dataPair["door_open_rt"] = insDoor;
root.printTo(buf, sizeof(buf)); // JSON-print to buffer
return load_gps(insGlat, insGlon);
}
void ledToggle(){
if (ledState == 0){
digitalWrite(LED,LOW);
ledState = 1;
} else {
digitalWrite(LED,HIGH);
ledState = 0;
}
}
static void smartdelay(unsigned long ms)
{
unsigned long start = millis();
do
{
while (Serial.available())
gps.encode(Serial.read());
} while (millis() - start < ms);
}
package cloud.artik.example.hellocloud;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.Button;
public class MainActivity extends Activity {
static final String TAG = "MainActivity";
private static final String ARTIK_CLOUD_AUTH_BASE_URL = "https://accounts.artik.cloud";
private static final String CLIENT_ID = "CLIENT_ID";// AKA application id
//private static final String REDIRECT_URL = "http://localhost:8000/acdemo/index.php";
private static final String REDIRECT_URL = "android-app://redirect";
private View mLoginView;
private WebView mWebView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mWebView = (WebView)findViewById(R.id.webview);
mWebView.setVisibility(View.GONE);
mLoginView = findViewById(R.id.ask_for_login);
mLoginView.setVisibility(View.VISIBLE);
Button button = (Button)findViewById(R.id.btn);
Log.v(TAG, "::onCreate");
button.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
try {
Log.v(TAG, ": button is clicked.");
loadWebView();
} catch (Exception e) {
Log.v(TAG, "Run into Exception");
e.printStackTrace();
}
}
});
}
@SuppressLint("SetJavaScriptEnabled")
private void loadWebView() {
Log.v(TAG, "::loadWebView");
mLoginView.setVisibility(View.GONE);
mWebView.setVisibility(View.VISIBLE);
mWebView.getSettings().setJavaScriptEnabled(true);
mWebView.setWebViewClient(new WebViewClient() {
@Override
public boolean shouldOverrideUrlLoading(WebView view, String uri) {
if ( uri.startsWith(REDIRECT_URL) ) {
// Redirect URL has format http://localhost:8000/acdemo/index.php#expires_in=1209600&token_type=bearer&access_token=xxxx
// Extract OAuth2 access_token in URL
String[] sArray = uri.split("&");
for (String paramVal : sArray) {
if (paramVal.indexOf("access_token=") != -1) {
String[] paramValArray = paramVal.split("access_token=");
String accessToken = paramValArray[1];
startWelcomeActivity(accessToken);
break;
}
}
return true;
}
// Load the web page from URL (login and grant access)
return super.shouldOverrideUrlLoading(view, uri);
}
});
String url = getAuthorizationRequestUri();
Log.v(TAG, "webview loading url: " + url);
mWebView.loadUrl(url);
}
public String getAuthorizationRequestUri() {
//https://accounts.artik.cloud/authorize?client=mobile&client_id=xxxx&response_type=token&redirect_uri=http://localhost:8000/acdemo/index.php
return ARTIK_CLOUD_AUTH_BASE_URL + "/authorize?client=mobile&response_type=token&" +
"client_id=" + CLIENT_ID + "&redirect_uri=" + REDIRECT_URL;
}
private void startWelcomeActivity(String accessToken) {
Intent welcomeActivityIntent = new Intent(this, WelcomeActivity.class);
welcomeActivityIntent.putExtra(WelcomeActivity.KEY_ACCESS_TOKEN, accessToken);
startActivity(welcomeActivityIntent);
}
}
package cloud.artik.example.hellocloud;
import android.app.Activity;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.RadioButton;
import android.widget.TextView;
import android.widget.Toast;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import cloud.artik.api.MessagesApi;
import cloud.artik.api.UsersApi;
import cloud.artik.client.ApiCallback;
import cloud.artik.client.ApiClient;
import cloud.artik.client.ApiException;
import cloud.artik.model.MessageAction;
import cloud.artik.model.MessageIDEnvelope;
import cloud.artik.model.NormalizedMessagesEnvelope;
import cloud.artik.model.UserEnvelope;
public class MessageActivity extends Activity {
private static final String TAG = "MessageActivity";
private static final String DEVICE_ID = "DEVICE_ID";
public static final String KEY_ACCESS_TOKEN = "Access_Token";
private UsersApi mUsersApi = null;
private MessagesApi mMessagesApi = null;
private String mAccessToken;
private EditText temph;
private EditText templ;
private EditText humid;
private EditText tilth;
private EditText tiltl;
private EditText smoke;
private EditText gpslat;
private EditText gpslon;
private RadioButton temp_alert;
private RadioButton humid_alert;
private RadioButton tilt_alert;
private RadioButton smoke_alert;
private Boolean temp_alert_flag = false;
private Boolean humid_alert_flag = false;
private Boolean tilt_alert_flag = false;
private Boolean smoke_alert_flag = false;
private TextView mSendResponse;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_message);
mAccessToken = getIntent().getStringExtra(KEY_ACCESS_TOKEN);
Log.v(TAG, "::onCreate get access token = " + mAccessToken);
Button updateparams = (Button)findViewById(R.id.updateparams_btn);
Button getparams = (Button)findViewById(R.id.getparams_btn);
temph = (EditText) findViewById(R.id.tempheditText);
templ = (EditText) findViewById(R.id.templeditText);
humid = (EditText) findViewById(R.id.humeditText);
tilth = (EditText) findViewById(R.id.tiltheditText);
tiltl = (EditText) findViewById(R.id.tiltleditText);
smoke = (EditText) findViewById(R.id.gaseditText);
gpslat = (EditText) findViewById(R.id.gpslateditText);
gpslon = (EditText) findViewById(R.id.gpsloneditText);
temp_alert = (RadioButton) findViewById(R.id.tempradioButton);
humid_alert = (RadioButton) findViewById(R.id.humradioButton);
tilt_alert = (RadioButton) findViewById(R.id.tiltradioButton);
smoke_alert = (RadioButton) findViewById(R.id.smokeradioButton);
mSendResponse = (TextView) findViewById(R.id.resptextView);
setupArtikCloudApi();
getUserInfo();
updateparams.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
Log.v(TAG, ": send button is clicked.");
postMsg();
}
});
getparams.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
Log.v(TAG, ": get latest message button is clicked.");
// Now get the message
getParameters();
}
});
}
public void onRadioButtonClicked(View view) {
boolean checked = ((RadioButton) view).isChecked();
switch(view.getId()) {
case R.id.tempradioButton:
temp_alert_flag = !temp_alert_flag;
temp_alert.setChecked(temp_alert_flag);
break;
case R.id.humradioButton:
humid_alert_flag = !humid_alert_flag;
humid_alert.setChecked(humid_alert_flag);
break;
case R.id.tiltradioButton:
tilt_alert_flag = !tilt_alert_flag;
tilt_alert.setChecked(tilt_alert_flag);
break;
case R.id.smokeradioButton:
smoke_alert_flag = !smoke_alert_flag;
smoke_alert.setChecked(smoke_alert_flag);
break;
}
}
private void setupArtikCloudApi() {
ApiClient mApiClient = new ApiClient();
mApiClient.setAccessToken(mAccessToken);
mApiClient.setDebugging(true);
mUsersApi = new UsersApi(mApiClient);
mMessagesApi = new MessagesApi(mApiClient);
}
private void getUserInfo()
{
final String tag = TAG + " getSelfAsync";
try {
mUsersApi.getSelfAsync(new ApiCallback<UserEnvelope>() {
@Override
public void onFailure(ApiException exc, int statusCode, Map<String, List<String>> map) {
processFailure(tag, exc);
}
@Override
public void onSuccess(UserEnvelope result, int statusCode, Map<String, List<String>> map) {
Log.v(TAG, "getSelfAsync::setupArtikCloudApi self name = " + result.getData().getFullName());
//updateWelcomeViewOnUIThread("Welcome " + result.getData().getFullName());
}
@Override
public void onUploadProgress(long bytes, long contentLen, boolean done) {
}
@Override
public void onDownloadProgress(long bytes, long contentLen, boolean done) {
}
});
} catch (ApiException exc) {
processFailure(tag, exc);
}
}
private void getParameters() {
final String tag = TAG + " getLastNormalizedMessagesAsync";
try {
int messageCount = 1;
mMessagesApi.getLastNormalizedMessagesAsync(messageCount, DEVICE_ID, null,
new ApiCallback<NormalizedMessagesEnvelope>() {
@Override
public void onFailure(ApiException exc, int i, Map<String, List<String>> stringListMap) {
processFailure(tag, exc);
}
@Override
public void onSuccess(NormalizedMessagesEnvelope result, int i, Map<String, List<String>> stringListMap) {
Log.v(tag, " onSuccess latestMessage = " + result.getData().toString());
updateGetResponseOnUIThread(result.getData().get(0).getMid(), result.getData().get(0).getData().toString());
}
@Override
public void onUploadProgress(long bytes, long contentLen, boolean done) {
}
@Override
public void onDownloadProgress(long bytes, long contentLen, boolean done) {
}
});
} catch (ApiException exc) {
processFailure(tag, exc);
}
}
private void postMsg() {
final String tag = TAG + " sendMessageActionAsync";
HashMap<String, Object> data = new HashMap<String, Object>();
data.put("temp_limit_h", Float.valueOf(temph.getText().toString()));
data.put("temp_limit_l", Float.valueOf(templ.getText().toString()));
data.put("humidity_threshold", Float.valueOf(humid.getText().toString()));
data.put("tilt_limit_h", Float.valueOf(tilth.getText().toString()));
data.put("tilt_limit_l", Float.valueOf(tiltl.getText().toString()));
data.put("GPS_lon_value", Float.valueOf(gpslon.getText().toString()));
data.put("GPS_lat_value", Float.valueOf(gpslat.getText().toString()));
data.put("gas_threshold", Float.valueOf(smoke.getText().toString()));
data.put("temp_alert_mail", temp_alert_flag = temp_alert.isChecked());
data.put("humid_alert_mail", humid_alert_flag = humid_alert.isChecked());
data.put("tilt_alert_mail", tilt_alert_flag = tilt_alert.isChecked());
data.put("gas_alert_mail", smoke_alert_flag = smoke_alert.isChecked());
MessageAction msg = new MessageAction();
msg.setSdid(DEVICE_ID);
msg.setData(data);
try {
mMessagesApi.sendMessageActionAsync(msg, new ApiCallback<MessageIDEnvelope>() {
@Override
public void onFailure(ApiException exc, int i, Map<String, List<String>> stringListMap) {
processFailure(tag, exc);
}
@Override
public void onSuccess(MessageIDEnvelope result, int i, Map<String, List<String>> stringListMap) {
Log.v(tag, " onSuccess response to sending message = " + result.getData().toString());
updateSendResponseOnUIThread(result.getData().toString());
}
@Override
public void onUploadProgress(long bytes, long contentLen, boolean done) {
}
@Override
public void onDownloadProgress(long bytes, long contentLen, boolean done) {
}
});
} catch (ApiException exc) {
processFailure(tag, exc);
}
}
static void showErrorOnUIThread(final String text, final Activity activity) {
activity.runOnUiThread(new Runnable() {
@Override
public void run() {
int duration = Toast.LENGTH_LONG;
Toast toast = Toast.makeText(activity.getApplicationContext(), text, duration);
toast.show();
}
});
}
private void updateGetResponseOnUIThread(final String mid, final String msgData) {
this.runOnUiThread(new Runnable() {
@Override
public void run() {
try {
JSONObject reader = new JSONObject(msgData);
temph.setText(reader.getString("temp_limit_h"));
templ.setText(reader.getString("temp_limit_l"));
humid.setText(reader.getString("humidity_threshold"));
tilth.setText(reader.getString("tilt_limit_h"));
tiltl.setText(reader.getString("tilt_limit_l"));
gpslon.setText(reader.getString("GPS_lon_value"));
gpslat.setText(reader.getString("GPS_lat_value"));
smoke.setText(reader.getString("gas_threshold"));
if (reader.getString("temp_alert_mail") == "true") {
temp_alert.setChecked(true);
} else {
temp_alert.setChecked(false);
}
if (reader.getString("humid_alert_mail") == "true") {
humid_alert.setChecked(true);
} else {
humid_alert.setChecked(false);
}
if (reader.getString("tilt_alert_mail") == "true") {
tilt_alert.setChecked(true);
} else {
tilt_alert.setChecked(false);
}
if (reader.getString("gas_alert_mail") == "true") {
smoke_alert.setChecked(true);
} else {
smoke_alert.setChecked(false);
}
mSendResponse.setText("Satus: Success");
} catch (JSONException e) {e.printStackTrace();}
}
});
}
private void updateSendResponseOnUIThread(final String response) {
this.runOnUiThread(new Runnable() {
@Override
public void run() {
mSendResponse.setText("Satus: Success");
}
});
}
private void processFailure(final String context, ApiException exc) {
String errorDetail = " onFailure with exception" + exc;
Log.w(context, errorDetail);
exc.printStackTrace();
showErrorOnUIThread(context+errorDetail, MessageActivity.this);
}
} //MessageActivity
package cloud.artik.example.hellocloud;
import android.app.Activity;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
import org.json.JSONException;
import org.json.JSONObject;
import java.util.List;
import java.util.Map;
import cloud.artik.api.MessagesApi;
import cloud.artik.api.UsersApi;
import cloud.artik.client.ApiCallback;
import cloud.artik.client.ApiClient;
import cloud.artik.client.ApiException;
import cloud.artik.model.NormalizedMessagesEnvelope;
public class RTActivity extends Activity{
private static final String TAG = "RTActivity";
private static final String DEVICE_ID = "DEVICE_ID";
public static final String KEY_ACCESS_TOKEN = "Access_Token";
private UsersApi mUsersApi = null;
private MessagesApi mMessagesApi = null;
private String mAccessToken;
private TextView rt_data;
private Button showOnGmaps;
private String latitude;
private String longitude;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_rt);
mAccessToken = getIntent().getStringExtra(KEY_ACCESS_TOKEN);
Log.v(TAG, "::onCreate get access token = " + mAccessToken);
Button getlatest = (Button)findViewById(R.id.get_latest_btn);
showOnGmaps = (Button)findViewById(R.id.gps_map_btn);
rt_data = (TextView)findViewById(R.id.rt_textView);
showOnGmaps.setEnabled(false);
setupArtikCloudApi();
getParameters();
showOnGmaps.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
Log.v(TAG, ": showOnGmaps button is clicked.");
startGMaps();
}
});
getlatest.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
Log.v(TAG, ": getlatest button is clicked.");
getParameters();
}
});
}
private void setupArtikCloudApi() {
ApiClient mApiClient = new ApiClient();
mApiClient.setAccessToken(mAccessToken);
mApiClient.setDebugging(true);
mUsersApi = new UsersApi(mApiClient);
mMessagesApi = new MessagesApi(mApiClient);
}
private void getParameters() {
final String tag = TAG + " getLastNormalizedMessagesAsync";
try {
int messageCount = 1;
mMessagesApi.getLastNormalizedMessagesAsync(messageCount, DEVICE_ID, null,
new ApiCallback<NormalizedMessagesEnvelope>() {
@Override
public void onFailure(ApiException exc, int i, Map<String, List<String>> stringListMap) {
processFailure(tag, exc);
}
@Override
public void onSuccess(NormalizedMessagesEnvelope result, int i, Map<String, List<String>> stringListMap) {
Log.v(tag, " onSuccess latestMessage = " + result.getData().toString());
updateGetResponseOnUIThread(result.getData().get(0).getMid(), result.getData().get(0).getData().toString());
}
@Override
public void onUploadProgress(long bytes, long contentLen, boolean done) {
}
@Override
public void onDownloadProgress(long bytes, long contentLen, boolean done) {
}
});
} catch (ApiException exc) {
processFailure(tag, exc);
}
}
private void startGMaps() {
Uri gmmIntentUri = Uri.parse("geo:" + latitude + "," + longitude + "?q=" + latitude + "," + longitude);
Intent mapIntent = new Intent(Intent.ACTION_VIEW, gmmIntentUri);
mapIntent.setPackage("com.google.android.apps.maps");
if (mapIntent.resolveActivity(getPackageManager()) != null) {
startActivity(mapIntent);
}
}
static void showErrorOnUIThread(final String text, final Activity activity) {
activity.runOnUiThread(new Runnable() {
@Override
public void run() {
int duration = Toast.LENGTH_LONG;
Toast toast = Toast.makeText(activity.getApplicationContext(), text, duration);
toast.show();
}
});
}
private void updateGetResponseOnUIThread(final String mid, final String msgData) {
this.runOnUiThread(new Runnable() {
@Override
public void run() {
try {
JSONObject reader = new JSONObject(msgData);
rt_data.setText("Temperature: " + reader.getString("temp_rt") +
"\r\nHumidity: " + reader.getString("humid_rt") +
"\r\nTilt: " + reader.getString("tilt_rt") +
"\r\nGas/Smoke: " + reader.getString("gas_rt") +
"\r\nDoor Opened: " + reader.getString("door_open_rt") +
"\r\nGPS latitude: " + reader.getString("GPS_lat_rt") +
"\r\nGPS longitude: " + reader.getString("GPS_lon_rt"));
latitude = reader.getString("GPS_lat_rt");
longitude = reader.getString("GPS_lon_rt");
showOnGmaps.setEnabled(true);
} catch (JSONException e) {
rt_data.setText("Data Not available");
showOnGmaps.setEnabled(false);
}
}
});
}
private void processFailure(final String context, ApiException exc) {
String errorDetail = " onFailure with exception" + exc;
Log.w(context, errorDetail);
exc.printStackTrace();
showErrorOnUIThread(context+errorDetail, RTActivity.this);
}
}
package cloud.artik.example.hellocloud;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
public class WelcomeActivity extends Activity {
private static final String TAG = "WelcomeActivity";
public static final String KEY_ACCESS_TOKEN = "Access_Token";
private String mAccessToken;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_welcome);
mAccessToken = getIntent().getStringExtra(KEY_ACCESS_TOKEN);
Log.v(TAG, "::onCreate get access token = " + mAccessToken);
Button confparams = (Button)findViewById(R.id.confparams_btn);
Button getrt = (Button)findViewById(R.id.getrt_btn);
confparams.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
Log.v(TAG, ": confparams button is clicked.");
startMessageActivity(mAccessToken);
}
});
getrt.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
Log.v(TAG, ": getrt button is clicked.");
startRTActivity(mAccessToken);
}
});
}
private void startMessageActivity(String accessToken) {
Intent msgActivityIntent = new Intent(this, MessageActivity.class);
msgActivityIntent.putExtra(MessageActivity.KEY_ACCESS_TOKEN, accessToken);
startActivity(msgActivityIntent);
}
private void startRTActivity(String accessToken) {
Intent rtActivityIntent = new Intent(this, RTActivity.class);
rtActivityIntent.putExtra(RTActivity.KEY_ACCESS_TOKEN, accessToken);
startActivity(rtActivityIntent);
}
}
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="cloud.artik.example.hellocloud"
android:versionCode="1"
android:versionName="1.0" >
<uses-permission android:name="android.permission.INTERNET" />
<uses-sdk
android:minSdkVersion="14"
android:targetSdkVersion="21" />
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name="cloud.artik.example.hellocloud.MainActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name="cloud.artik.example.hellocloud.WelcomeActivity"
android:label="@string/play_with_messages" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
<activity
android:name="cloud.artik.example.hellocloud.MessageActivity"
android:label="@string/play_with_messages" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
<activity
android:name="cloud.artik.example.hellocloud.RTActivity"
android:label="@string/play_with_messages" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
</application>
</manifest>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.example.myfirstapp.MainActivity" >
<RelativeLayout
android:id="@+id/ask_for_login"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<TextView
android:id="@+id/hello_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/hello_world" />
<Button
android:id="@+id/btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/hello_text"
android:text="@string/click" />
</RelativeLayout>
<WebView
android:id="@+id/webview"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
/>
</RelativeLayout>
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="10dp"
android:fillViewport="false">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:orientation="vertical"
android:weightSum="1">
<Button
android:id="@+id/getparams_btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Get Parameters"
android:layout_gravity="center_horizontal" />
<TextView
android:layout_width="match_parent"
android:layout_height="28dp"
android:text="Temp high limit"
android:id="@+id/temphtextView" />
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/tempheditText"
android:layout_gravity="right"
android:inputType="text" />
<TextView
android:layout_width="match_parent"
android:layout_height="28dp"
android:text="Temp low limit"
android:id="@+id/templtextView" />
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/templeditText"
android:layout_gravity="right"
android:inputType="text" />
<TextView
android:layout_width="match_parent"
android:layout_height="28dp"
android:text="Humidity threshold"
android:id="@+id/humtextView" />
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/humeditText"
android:layout_gravity="right"
android:inputType="text" />
<TextView
android:layout_width="match_parent"
android:layout_height="28dp"
android:text="Tilt high limit"
android:id="@+id/tilthtextView" />
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/tiltheditText"
android:layout_gravity="right"
android:inputType="text" />
<TextView
android:layout_width="match_parent"
android:layout_height="28dp"
android:text="Tilt low limit"
android:id="@+id/tiltltextView" />
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/tiltleditText"
android:layout_gravity="right"
android:inputType="text" />
<TextView
android:layout_width="match_parent"
android:layout_height="28dp"
android:text="Gas/smoke threshold"
android:id="@+id/gastextView" />
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/gaseditText"
android:layout_gravity="right"
android:inputType="text" />
<TextView
android:layout_width="match_parent"
android:layout_height="28dp"
android:text="GPS Latitude"
android:id="@+id/gpslattextView" />
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/gpslateditText"
android:layout_gravity="right"
android:inputType="text" />
<TextView
android:layout_width="match_parent"
android:layout_height="28dp"
android:text="GPS Longitude"
android:id="@+id/gpslontextView" />
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/gpsloneditText"
android:layout_gravity="right"
android:inputType="text" />
<RadioButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Send mail for temp alert"
android:id="@+id/tempradioButton"
android:onClick="onRadioButtonClicked" />
<RadioButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Send mail for humidity alert"
android:id="@+id/humradioButton"
android:onClick="onRadioButtonClicked" />
<RadioButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Send mail for tilt alert"
android:id="@+id/tiltradioButton"
android:onClick="onRadioButtonClicked" />
<RadioButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Send mail for gas/smoke alert"
android:id="@+id/smokeradioButton"
android:onClick="onRadioButtonClicked" />
<Button
android:id="@+id/updateparams_btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Update Parameters"
android:layout_gravity="center_horizontal" />
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text=""
android:id="@+id/resptextView" />
</LinearLayout>
</ScrollView>
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/rt_textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="" />
<Button
android:id="@+id/get_latest_btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:text="Get latest data" />
<Button
android:id="@+id/gps_map_btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:text="Show on GMaps" />
</LinearLayout>
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">
<Button
android:layout_width="243dp"
android:layout_height="wrap_content"
android:text="Configure Parameters"
android:id="@+id/confparams_btn"
android:layout_gravity="center_horizontal" />
<Button
android:layout_width="243dp"
android:layout_height="wrap_content"
android:text="Get Real-Time data"
android:id="@+id/getrt_btn"
android:layout_gravity="center_horizontal" />
</LinearLayout>
Comments