/** AirCasting - Share your Air! Copyright (C) 2011-2012 HabitatMap, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. You can contact the authors by email at <info@habitatmap.org> */ package pl.llp.aircasting.helper; import pl.llp.aircasting.event.sensor.ThresholdSetEvent; import pl.llp.aircasting.model.Sensor; import pl.llp.aircasting.model.internal.MeasurementLevel; import pl.llp.aircasting.sensor.ExternalSensorDescriptor; import android.content.SharedPreferences; import com.google.common.base.Strings; import com.google.common.eventbus.EventBus; import com.google.common.eventbus.Subscribe; import com.google.gson.Gson; import com.google.gson.JsonSyntaxException; import com.google.gson.reflect.TypeToken; import com.google.inject.Inject; import com.google.inject.Singleton; import java.lang.reflect.Type; import java.util.Iterator; import java.util.List; import static com.google.common.collect.Lists.newArrayList; @Singleton public class SettingsHelper { public static final String AUTH_TOKEN = "auth_token"; public static final String USER_LOGIN = "user_login"; public static final String KEEP_SCREEN_ON = "keep_screen_on"; public static final String OFFSET_60_DB = "offset_60_db"; public static final String SOUND_LEVEL_MEASUREMENTLESS = "sound_level_measurementless"; public static final String CALIBRATION = "calibration"; public static final String SATELLITE = "satellite"; public static final String BACKEND = "backend"; public static final String BACKEND_PORT = "backend_port"; public static final String HEAT_MAP_DENSITY = "heat_map_density"; public static final String FIRST_LAUNCH = "first_launch"; public static final String DISABLE_MAPS = "disable_maps"; public static final String FIXED_SESSIONS_STREAMING = "fixed_sessions_streaming"; public static final String CONTRIBUTE_TO_CROWDMAP = "contribute_to_crowdmap"; public static final int DEFAULT_CALIBRATION = 100; public static final boolean DEFAULT_SATELLITE = false; public static final String DEFAULT_BACKEND = "aircasting.org"; public static final int DEFAULT_BACKEND_PORT = 80; public static final int DEFAULT_HEAT_MAP_DENSITY = 10; public static final boolean DEFAULT_KEEP_SCREEN_ON = false; public static final int DEFAULT_OFFSET_60_DB = 0; public static final int MIN_OFFSET_60_DB = -5; public static final int MAX_OFFSET_60_DB = 5; public static final boolean DEFAULT_SOUND_LEVEL_MEASUREMENTLESS = false; public static final String SAMPLE_INTERVAL = "sample_interval"; public static final String AVERAGING_TIME = "averaging_time"; private static final int MIN_AVERAGING_TIME = 1; private static final int MAX_AVERAGING_TIME = 3600; public static final String SYNC_ONLY_WIFI = "sync_only_wifi"; public static final String SHOW_ROUTE = "show_route"; public static final String SENSORS = "external_sensors_json"; public static final boolean DEFAULT_FIXED_SESSIONS_STREAMING = false; public static final boolean DEFAULT_CONTRIBUTE_TO_CROWDMAP = false; public static final String SHOW_GRAPH_METADATA = "show_graph_metadata"; @Inject SharedPreferences preferences; @Inject Gson gson; @Inject EventBus eventBus; @Inject public void init() { eventBus.register(this); } @Subscribe public void onEvent(ThresholdSetEvent event) { setThreshold(event.getSensor(), event.getLevel(), event.getValue()); } public int getCalibration() { return getInt(CALIBRATION, DEFAULT_CALIBRATION); } private int getInt(String key, int defaultValue) { String value = preferences.getString(key, Integer.toString(defaultValue)); try { return Integer.parseInt(value); } catch (NumberFormatException e) { remove(key); return defaultValue; } } public boolean isSatelliteView() { return preferences.getBoolean(SATELLITE, DEFAULT_SATELLITE); } public String getBackendURL() { return preferences.getString(BACKEND, DEFAULT_BACKEND); } public int getBackendPort() { return getInt(BACKEND_PORT, DEFAULT_BACKEND_PORT); } public int getHeatMapDensity() { return getInt(HEAT_MAP_DENSITY, DEFAULT_HEAT_MAP_DENSITY); } public int getThreshold(Sensor sensor, MeasurementLevel measurementLevel) { int defValue = sensor.getThreshold(measurementLevel); String key = thresholdKey(sensor, measurementLevel); return preferences.getInt(key, defValue); } public void setThreshold(Sensor sensor, MeasurementLevel measurementLevel, int value) { SharedPreferences.Editor editor = preferences.edit(); String key = thresholdKey(sensor, measurementLevel); editor.putInt(key, value); editor.commit(); } private String thresholdKey(Sensor sensor, MeasurementLevel level) { return sensor.getSensorName() + ";" + level; } public void setAuthToken(String token) { writeString(AUTH_TOKEN, token); } public String getAuthToken() { return preferences.getString(AUTH_TOKEN, ""); } public void resetThresholds(Sensor sensor) { SharedPreferences.Editor editor = preferences.edit(); for (MeasurementLevel level : MeasurementLevel.values()) { String key = thresholdKey(sensor, level); editor.remove(key); } editor.commit(); } public void setUserLogin(String email) { writeString(USER_LOGIN, email); } public String getUserLogin() { return preferences.getString(USER_LOGIN, null); } public void removeCredentials() { SharedPreferences.Editor editor = preferences.edit(); editor.remove(AUTH_TOKEN); editor.remove(USER_LOGIN); editor.commit(); } public boolean hasCredentials() { return preferences.contains(AUTH_TOKEN); } public boolean hasNoCredentials() { return !hasCredentials(); } public boolean isKeepScreenOn() { return preferences.getBoolean(KEEP_SCREEN_ON, DEFAULT_KEEP_SCREEN_ON); } public boolean isSoundLevelMeasurementsDisabled() { return preferences.getBoolean(SOUND_LEVEL_MEASUREMENTLESS, DEFAULT_SOUND_LEVEL_MEASUREMENTLESS); } public int getOffset60DB() { return getInt(OFFSET_60_DB, DEFAULT_OFFSET_60_DB); } public boolean validateOffset60DB(int newValue) { return validateRange(newValue, MIN_OFFSET_60_DB, MAX_OFFSET_60_DB); } private boolean validateRange(String key, int value, int min, int max) { if (value < min) { writeString(key, Integer.toString(min)); return false; } if (value > max) { writeString(key, Integer.toString(max)); return false; } return true; } private boolean validateRange(int value, int max, int min) { return value >= min && value <= max; } public boolean validateAveragingTime() { return validateRange(AVERAGING_TIME, getAveragingTime(), MIN_AVERAGING_TIME, MAX_AVERAGING_TIME); } public boolean isFirstLaunch() { return preferences.getBoolean(FIRST_LAUNCH, true); } public void setFirstLaunch(boolean value) { writeBoolean(FIRST_LAUNCH, value); } private boolean writeBoolean(String key, boolean value) { return preferences.edit().putBoolean(key, value).commit(); } private void writeString(String key, String value) { preferences.edit().putString(key, value).commit(); } public boolean validateFormat(String key) { if (isNumericPreference(key)) { try { Integer.parseInt(preferences.getString(key, "0")); return true; } catch (NumberFormatException e) { remove(key); return false; } } return true; } private void remove(String key) { preferences.edit().remove(key).commit(); } private boolean isNumericPreference(String key) { return key.equals(CALIBRATION) || key.equals(OFFSET_60_DB) || key.equals(HEAT_MAP_DENSITY) || key.equals(BACKEND_PORT) || key.equals(SAMPLE_INTERVAL); } public int getAveragingTime() { return 1; } public boolean isAveraging() { return false; } public boolean isSyncOnlyWifi() { return preferences.getBoolean(SYNC_ONLY_WIFI, false); } public boolean isShowRoute() { return preferences.getBoolean(SHOW_ROUTE, true); } public void setBackendAddress(String backendAddress) { writeString(BACKEND, backendAddress); } public void setBackendPort(String backendAddress) { writeString(BACKEND_PORT, backendAddress); } public List<ExternalSensorDescriptor> knownSensors() { String json = getConnectedSensorsAsJSON(); if (Strings.isNullOrEmpty(json)) { return newArrayList(); } Type type = new TypeToken<List<ExternalSensorDescriptor>>() {}.getType(); try { return gson.fromJson(json, type); } catch (JsonSyntaxException e) { writeString(SENSORS, ""); } return newArrayList(); } public void knownSensorsWithout(String addres) { List<ExternalSensorDescriptor> descriptors = knownSensors(); for (Iterator<ExternalSensorDescriptor> iterator = descriptors.iterator(); iterator.hasNext(); ) { ExternalSensorDescriptor aDescriptor = iterator.next(); if(addres.equals(aDescriptor.getAddress())) { iterator.remove(); } } setExternalSensors(descriptors); } public String getConnectedSensorsAsJSON() { return preferences.getString(SENSORS, null); } public void setExternalSensors(List<ExternalSensorDescriptor> sensors) { String sensorsAsJson = gson.toJson(sensors); writeString(SENSORS, sensorsAsJson); } public boolean showGraphMetadata() { return preferences.getBoolean(SHOW_GRAPH_METADATA, false); } public void setDisableMaps(boolean checked) { writeBoolean(DISABLE_MAPS, checked); } public boolean areMapsDisabled() { return preferences.getBoolean(DISABLE_MAPS, false); } public boolean isContributingToCrowdMap() { return preferences.getBoolean(CONTRIBUTE_TO_CROWDMAP, DEFAULT_CONTRIBUTE_TO_CROWDMAP); } public boolean isFixedSessionStreamingEnabled() { return preferences.getBoolean(FIXED_SESSIONS_STREAMING, DEFAULT_FIXED_SESSIONS_STREAMING); } }