package st.alr.mqttitude.support; import java.text.SimpleDateFormat; import java.util.Date; import java.util.EnumSet; import java.util.Set; import de.greenrobot.event.EventBus; import st.alr.mqttitude.App; import st.alr.mqttitude.R; import st.alr.mqttitude.services.ServiceMqtt; import st.alr.mqttitude.support.Defaults.State; import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; import android.content.SharedPreferences.OnSharedPreferenceChangeListener; import android.location.Location; import android.preference.PreferenceManager; import android.util.Log; public abstract class Locator implements MqttPublish { protected Context context; protected SharedPreferences sharedPreferences; private OnSharedPreferenceChangeListener preferencesChangedListener; protected Date lastPublish; private java.text.DateFormat lastPublishDateFormat; private Set<Defaults.State> state; protected final String TAG = this.toString(); Locator(Context context) { this.context = context; this.sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context); this.state = EnumSet.of(Defaults.State.Idle); preferencesChangedListener = new SharedPreferences.OnSharedPreferenceChangeListener() { @Override public void onSharedPreferenceChanged(SharedPreferences sharedPreference, String key) { handlePreferences(); } }; sharedPreferences.registerOnSharedPreferenceChangeListener(preferencesChangedListener); } abstract public Location getLastKnownLocation(); abstract protected void handlePreferences(); abstract public void start(); abstract public void enableForegroundMode(); abstract public void enableBackgroundMode(); public void publishLastKnownLocation() { Log.v(TAG, "publishLastKnownLocation"); lastPublish = new Date(); Intent service = new Intent(context, ServiceMqtt.class); StringBuilder payload = new StringBuilder(); Date d = new Date(); Location l = getLastKnownLocation(); String topic = sharedPreferences.getString(Defaults.SETTINGS_KEY_TOPIC, Defaults.VALUE_TOPIC); ServiceMqtt s = ServiceMqtt.getInstance(); if(s == null) { return; } if (topic == null) { addState(State.NOTOPIC); return; } if (l == null) { this.addState(State.LocatingFail); return; } context.startService(service); payload.append("{"); payload.append("\"type_\": ").append("\"").append("location").append("\""); payload.append(", \"lat\": ").append("\"").append(l.getLatitude()).append("\""); payload.append(", \"lon\": ").append("\"").append(l.getLongitude()).append("\""); payload.append(", \"tst\": ").append("\"").append((int)(d.getTime()/1000)).append("\""); payload.append(", \"acc\": ").append("\"").append(Math.round(l.getAccuracy() * 100) / 100.0d).append("m").append("\""); payload.append(", \"alt\": ").append("\"").append(l.getAltitude()).append("\""); payload.append("}"); ServiceMqtt.getInstance().publish( topic, payload.toString(), sharedPreferences.getBoolean(Defaults.SETTINGS_KEY_RETAIN, Defaults.VALUE_RETAIN), Integer.parseInt(sharedPreferences.getString(Defaults.SETTINGS_KEY_QOS, Defaults.VALUE_QOS)) , 20, this); } public void publishSuccessfull() { Log.v(TAG, "publishSuccessfull"); EventBus.getDefault().post(new Events.PublishSuccessfull()); // This is a bit hacked as we append an empty space on every second // ticker update. Otherwise consecutive tickers with the same text would // not be shown if(isTickerOnPublishEnabled()) App.getInstance().updateTicker(App.getInstance().getString(R.string.statePublished)); this.resetState(); } public Set<State> getState() { return this.state; } public String getStateAsText() { if (this.state.contains(State.NOTOPIC)) { return App.getInstance().getString(R.string.stateNotopic); } if (this.state.contains(State.PublishConnectionTimeout)) { return App.getInstance().getString(R.string.statePublishTimeout); } if (this.state.contains(State.LocatingFail)) { return App.getInstance().getString(R.string.stateLocatingFail); } if (this.state.contains(State.Publishing)) { return App.getInstance().getString(R.string.statePublishing); } if (this.state.contains(State.PublishConnectionWaiting)) { return App.getInstance().getString(R.string.stateWaiting); } return App.getInstance().getString(R.string.stateIdle); } public void publishFailed() { Log.e(TAG, "publishTimeout"); this.addState(State.PublishConnectionTimeout); } public void publishing() { Log.v(TAG, "publishing"); this.addState(State.Publishing); } public void publishWaiting() { Log.v(TAG, "waiting for broker connection"); this.addState(State.PublishConnectionWaiting); } protected void setStateTo(State s) { this.state.clear(); this.state.add(s); } protected void addState(State s) { this.state.add(s); if (isTickerState(s) && isTickerOnPublishEnabled()) { App.getInstance().updateTicker(getStateAsText()); } App.getInstance().updateNotification(); EventBus.getDefault().post(new Events.StateChanged()); } private boolean isTickerState(State s) { return s == Defaults.State.LocatingFail || s == Defaults.State.NOTOPIC || s == Defaults.State.PublishConnectionTimeout || s == Defaults.State.PublishConnectionWaiting || s == Defaults.State.Publishing; } protected void removeState(State s) { this.state.remove(s); EventBus.getDefault().post(new Events.StateChanged()); } public void resetState() { this.setStateTo(State.Idle); EventBus.getDefault().post(new Events.StateChanged()); App.getInstance().updateNotification(); } public Date getLastPublishDate() { return lastPublish; } public boolean areBackgroundUpdatesEnabled() { return sharedPreferences.getBoolean(Defaults.SETTINGS_KEY_BACKGROUND_UPDATES, Defaults.VALUE_BACKGROUND_UPDATES); } public boolean isTickerOnPublishEnabled(){ return sharedPreferences.getBoolean(Defaults.SETTINGS_KEY_TICKER_ON_PUBLISH, Defaults.VALUE_TICKER_ON_PUBLISH); } public int getUpdateIntervall() { return Integer.parseInt(sharedPreferences.getString(Defaults.SETTINGS_KEY_BACKGROUND_UPDATES_INTERVAL, Defaults.VALUE_BACKGROUND_UPDATES_INTERVAL)); } public int getUpdateIntervallInMiliseconds() { return getUpdateIntervall() * 60 * 1000; } }