/*
* HostDetailActivity.java
* Open Mobile Hub
*
* Created by Gareth Johnson
* Copyright (c) 2014 Beckersweet. All rights reserved.
*/
package com.beckersweet.opmub;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.ContentResolver;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentSender;
import android.location.Location;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.os.Bundle;
import android.provider.Settings.Secure;
import android.text.format.Formatter;
import android.util.Log;
import android.view.View;
import android.widget.EditText;
import android.widget.ScrollView;
import android.widget.TextView;
import android.widget.Toast;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.GooglePlayServicesClient;
import com.google.android.gms.common.GooglePlayServicesUtil;
import com.google.android.gms.location.LocationClient;
import com.google.android.gms.location.LocationListener;
import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStreamWriter;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
@SuppressWarnings("deprecation")
public class MainActivity extends Activity implements LocationListener,
GooglePlayServicesClient.ConnectionCallbacks,
GooglePlayServicesClient.OnConnectionFailedListener {
private static final boolean DEBUG = true;
private static final String DEBUG_TAG = "BeckersweetMqttClient";
private static final int DEFAULT_PORT = 9998;
private static int CONNECTION_FAILURE_RESOLUTION_REQUEST = 1; // arbitrary #
private static String MARKERS = "com.beckersweet.mqttclient.MARKERS";
private String brokerUrl;
private int port;
private String deviceId;
private String ipAddress;
private String macAddress;
private double latitude;
private double longitude;
private LocationClient locationClient; // for getting GPS coordinates
private MqttHelper mqtt; // controls MQTT client for subscribing/publishing
private JSONArray hosts; // array of host info returned from broker
private ScrollView logWindow; // contains debug log
private TextView log; // for debug messages
private UserMessageHelper messenger; // controls debug messages and alerts
private WifiManager wifiManager; // for getting IP address and MAC address
private WifiInfo wifiInfo; // for getting IP address and MAC address
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Initialize user message stuff.
log = (TextView) findViewById(R.id.log_text);
logWindow = (ScrollView) findViewById(R.id.log_window);
messenger = new UserMessageHelper(this, log, logWindow, DEBUG,
DEBUG_TAG);
// Initialize MQTT client.
File cacheDirectory = getCacheDir(); // for MQTT logs
mqtt = new MqttHelper(messenger, cacheDirectory);
// Check for Google Play services (needed for map).
int result = GooglePlayServicesUtil.isGooglePlayServicesAvailable(this);
if (result != ConnectionResult.SUCCESS) {
Dialog errorDialog = GooglePlayServicesUtil.getErrorDialog(result,
this, CONNECTION_FAILURE_RESOLUTION_REQUEST);
errorDialog.show();
}
// Initialize location stuff.
locationClient = new LocationClient(this, this, this);
latitude = 0;
longitude = 0;
hosts = new JSONArray();
// Get device ID from Android device.
ContentResolver contentResolver = this.getContentResolver();
String contentName = Secure.ANDROID_ID;
deviceId = Secure.getString(contentResolver, contentName);
messenger.printDebugMessage("Device ID: " + deviceId);
}
@Override
protected void onStart() {
super.onStart();
locationClient.connect();
}
@Override
protected void onStop() {
locationClient.disconnect();
super.onStop();
}
@Override
public void onConnected(Bundle dataBundle) {
// Display the connection status
Toast.makeText(this, "Connected to Google Play Services",
Toast.LENGTH_SHORT).show();
}
@Override
public void onDisconnected() {
// Display the connection status
Toast.makeText(this, "Disconnected from Google Play Services." +
"Please re-connect.", Toast.LENGTH_SHORT).show();
}
@Override
public void onConnectionFailed(ConnectionResult connectionResult) {
if (connectionResult.hasResolution()) {
try {
connectionResult.startResolutionForResult(this,
CONNECTION_FAILURE_RESOLUTION_REQUEST);
} catch (IntentSender.SendIntentException e) {
e.printStackTrace();
}
} else {
int errorCode = connectionResult.getErrorCode();
messenger.showAlert(Integer.toString(errorCode));
}
}
@Override
public void onLocationChanged(Location location) {
latitude = location.getLatitude();
longitude = location.getLongitude();
}
public int prepareConnection() {
// Get broker URL.
brokerUrl = getBrokerUrl();
if (brokerUrl == null)
return 1;
// Attach port and protocol to broker URL.
EditText portText = (EditText) findViewById(R.id.port);
String portString = portText.getText().toString();
if (portString.isEmpty())
port = DEFAULT_PORT;
else
port = Integer.parseInt(portText.getText().toString());
brokerUrl = "tcp://" + brokerUrl + ":" + Integer.toString(port);
messenger.printDebugMessage("Broker URL: " + brokerUrl);
return 0;
}
private String getBrokerUrl() {
// Verify broker URL.
try {
EditText brokerUrlText = (EditText) findViewById(R.id.broker_url);
String url = brokerUrlText.getText().toString();
if (url.isEmpty()) throw new Exception("Field is empty.");
return url;
} catch (Exception e) {
messenger.showAlert("Invalid broker ID: " + e.getMessage());
e.printStackTrace();
return null;
}
}
public void addHost(View view) {
if (prepareConnection() == 0) {
if (mqtt.isConnected())
mqtt.disconnect();
int connectionResult = mqtt.connect(brokerUrl, deviceId);
if (connectionResult == 0) {
messenger.printDebugMessage("Determining IP and MAC addresses" +
"...");
wifiManager = (WifiManager) getSystemService(WIFI_SERVICE);
wifiInfo = wifiManager.getConnectionInfo();
int intIpAddress = wifiInfo.getIpAddress();
ipAddress = Formatter.formatIpAddress(intIpAddress);
macAddress = wifiInfo.getMacAddress();
messenger.printDebugMessage("Getting current location...");
Location location = locationClient.getLastLocation();
latitude = location.getLatitude();
longitude = location.getLongitude();
messenger.printDebugMessage("Creating message...");
JSONObject jsonMessage = new JSONObject();
try {
jsonMessage.put("from", deviceId);
jsonMessage.put("command", "addRealHost");
jsonMessage.put("name", deviceId);
jsonMessage.put("ip", ipAddress);
jsonMessage.put("mac", macAddress);
jsonMessage.put("latitude", latitude);
jsonMessage.put("longitude", longitude);
jsonMessage.put("available", true);
} catch (JSONException e) {
messenger.showAlert("JSON problem: " + e.getMessage());
e.printStackTrace();
}
String jsonMessageString = jsonMessage.toString();
messenger.printDebugMessage("Message: " + jsonMessageString);
mqtt.sendMessage(jsonMessageString);
mqtt.disconnect();
}
}
}
public void getHosts(View view) {
if (prepareConnection() == 0) {
if (mqtt.isConnected())
mqtt.disconnect();
int result = mqtt.connect(brokerUrl, deviceId);
if (result == 0) {
mqtt.subscribe(deviceId);
messenger.printDebugMessage("Creating message...");
JSONObject jsonMessage = new JSONObject();
try {
jsonMessage.put("from", deviceId);
jsonMessage.put("command", "getRealHosts");
} catch (JSONException e) {
messenger.showAlert("JSON problem: " + e.getMessage());
e.printStackTrace();
}
String jsonMessageString = jsonMessage.toString();
messenger.printDebugMessage("Message: " + jsonMessageString);
mqtt.sendMessage(jsonMessageString);
while (mqtt.isWaiting) {
// Wait for response
}
hosts = mqtt.getHosts();
mqtt.disconnect();
}
}
}
public void startWorker(View view) {
// Write broadcast address to a file.
String fileName;
FileOutputStream stream;
OutputStreamWriter writer;
EditText broadcastAddressText;
String broadcastAddress;
try {
broadcastAddress = getBrokerUrl();
if (broadcastAddress == null)
return;
fileName = "broadcast_address.txt";
stream = this.openFileOutput(fileName, Context.MODE_PRIVATE);
writer = new OutputStreamWriter(stream);
writer.write(broadcastAddress);
writer.close();
stream.close();
} catch (Exception e) {
messenger.showAlert("Error writing file: " + e.getMessage());
e.printStackTrace();
return;
}
// Start Parallel Python activity.
Intent intent = new Intent(this, ScriptActivity.class);
startActivity(intent);
}
public void openMap(View view) {
if (hosts.length() == 0) {
messenger.showAlert("There are no hosts to show. Try pressing " +
"'Add Host' and 'Get Hosts' first.");
return;
}
HostMarker[] markers = new HostMarker[hosts.length()];
for (int i = 0; i < hosts.length(); i++) {
JSONObject host;
String name, ip, mac;
boolean available;
double latitude, longitude;
try {
host = hosts.getJSONObject(i);
name = host.getString("name");
ip = host.getString("ip");
mac = host.getString("mac");
latitude = host.getDouble("latitude");
longitude = host.getDouble("longitude");
available = host.getBoolean("available");
} catch (Exception e) {
messenger.showAlert("Invalid host data: " + e.getMessage());
return;
}
HostMarker marker;
marker = new HostMarker(name, ip, mac, latitude, longitude,
available);
markers[i] = marker;
}
Intent intent = new Intent(this, MapActivity.class);
intent.putExtra(MARKERS, markers);
try {
startActivity(intent);
} catch (Exception e) {
Log.e(DEBUG_TAG, e.getMessage());
}
}
public void showAlert(String message) {
AlertDialog alert = new AlertDialog.Builder(this).create();
alert.setCancelable(false);
alert.setMessage(message);
alert.setButton("OK", new DialogInterface.OnClickListener() {
@Override
public void onClick(final DialogInterface dialog, final int which) {
dialog.dismiss();
}
});
alert.show();
}
}