package interdroid.swan.sensors; import interdroid.cuckoo.base.NoResourceAvailableException; import interdroid.cuckoo.client.Cuckoo; import interdroid.cuckoo.client.Cuckoo.Resource; import interdroid.cuckoo.client.Oracle; import interdroid.swan.cuckoo_sensors.CuckooPoller; import java.io.IOException; import java.util.HashMap; import java.util.List; import java.util.Map; import android.content.Context; import android.content.SharedPreferences; import android.os.Bundle; import android.util.Log; import com.google.android.gms.gcm.GoogleCloudMessaging; public abstract class AbstractCuckooSensor extends AbstractSwanSensor { private final static String TAG = "AbstractCuckooSensor"; private final static String REGISTRATION_ID = "registration_id"; private Map<String, MonitorThread> monitors = new HashMap<String, MonitorThread>(); private Resource remoteResource = null; private SharedPreferences prefs; private boolean mRegistering = false; @Override public final synchronized void onConnected() { // TODO improve picking of resource! List<Resource> resources = Oracle.getAllResources(this); Log.d(TAG, "got resources: " + resources.size()); prefs = getSharedPreferences(getClass().getSimpleName(), Context.MODE_PRIVATE); if (resources.size() > 0) { remoteResource = resources.get(0); if (prefs.getString(REGISTRATION_ID, null) == null) { registerBackground(); } else { Log.d(TAG, "regId: " + prefs.getString(REGISTRATION_ID, null)); } } } @Override public final void onDestroySensor() { remoteResource = null; } @Override public final synchronized void register(final String id, final String valuePath, Bundle configuration) throws IOException { final Map<String, Object> configAsMap = new HashMap<String, Object>(); for (String key : configuration.keySet()) { // TODO: maybe short circuit if a value is not serializable configAsMap.put(key, configuration.get(key)); } Log.d(TAG, "Trying to register expression"); new Thread() { public void run() { while (prefs.getString(REGISTRATION_ID, null) == null && mRegistering) { Log.d(TAG, "waiting for reg id"); try { sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } if (prefs.getString(REGISTRATION_ID, null) != null) { try { Cuckoo.register(AbstractCuckooSensor.this, remoteResource, prefs.getString(REGISTRATION_ID, null), getGCMApiKey(), getPoller(), id, valuePath, configAsMap); registerReceiver(); return; } catch (NoResourceAvailableException e) { // fall back to local impl remoteResource = null; } } // local Log.d(TAG, "Falling back to local implementation"); MonitorThread monitor = new MonitorThread( AbstractCuckooSensor.this, valuePath, configAsMap); monitors.put(id, monitor); monitor.start(); } }.start(); } @Override public final void unregister(String id) { if (remoteResource != null) { try { Cuckoo.unregister(this, remoteResource, id); return; } catch (NoResourceAvailableException e) { // TODO: we lost connection to this resource, retry later with // an alarm or so. // TODO Auto-generated catch block e.printStackTrace(); } } else { Log.d(TAG, "unregistering sensor, interrupting monitor!"); monitors.remove(id).shouldStop = true; } } public abstract CuckooPoller getPoller(); public abstract String getGCMSenderId(); public abstract String getGCMApiKey(); public abstract void registerReceiver(); private void registerBackground() { new Thread() { public void run() { mRegistering = true; try { Log.d(TAG, "getting a registration id for sender id: " + getGCMSenderId()); prefs.edit() .putString( REGISTRATION_ID, GoogleCloudMessaging.getInstance( AbstractCuckooSensor.this) .register(getGCMSenderId())) .commit(); Log.d(TAG, "We did get a registration ID: " + prefs.getString(REGISTRATION_ID, null)); } catch (IOException e) { // TODO: something useful. Log.w(TAG, "failed to get registration id", e); } mRegistering = false; } }.start(); } public static Object makeTyped(String string) { String[] components = string.split(":", 2); String type = components[0]; String value = components[1]; if (type.equals("java.lang.Long")) { return Long.parseLong(value); } else if (type.equals("java.lang.String")) { return value; } else if (type.equals("java.lang.Integer")) { return Integer.parseInt(value); } else if (type.equals("java.lang.Boolean")) { return Boolean.parseBoolean(value); } else if (type.equals("java.lang.Character")) { return value.charAt(0); } else if (type.equals("java.lang.Float")) { return Float.parseFloat(value); } else if (type.equals("java.lang.Double")) { return Double.parseDouble(value); } else { throw new RuntimeException("Please implement " + AbstractCuckooSensor.class + " makeTyped(String string) for type '" + type + "'"); } } }