Sensorki – aplikacja „pogodowa” – #0

This entry is part 1 of 10 in the series Sensorki

Dawno temu Mąż porozstawiał po domu sensorki [specyfikacja sensorków] zbierające dane na temat m. in. temperatury i wilgotności w pomieszczeniach mieszkania i z balkonu. Do tej pory jedynym dostępem do danych jest strona internetowa. Nie może tak być – trzeba zrobić aplikację na Androida 😉

O to jak będzie wyglądać aplikacja nie musiałam się martwić. Zamierzałam wzorować się na tym co na stronie:

wersja web

Na początku trzeba było wyciągnać dane – nie było to trudne skoro dostałam endpoint, który zwraca mi plik .json z danymi, które muszę tylko wyświetlić. 

{
"sensors": {
"1": { "label": "Balkon", "data": ["hum_temp", "hum_hum", "bar_pres_rel", "lux", "vbat", "vreg"] },
"2": { "label": "Salon", "data": ["hum_temp", "hum_hum", "lux", "vbat", "vreg"] }
},
"readings": {
"1": {
"id": 253985, "stamp": 1533903958, "sensor_id": 1, "seq": 62790, "status": 0, "flags": 23,
"bar_temp": 24.58, "bar_pres_abs": 1007.44, "bar_pres_rel": 1023.47, "lux": 5200.64,
"hum_temp": 24.23, "hum_hum": 99.7, "vbat": 3.71, "vreg": 2.83
},
"2": {
"id": 253986, "stamp": 1533903959, "sensor_id": 2, "seq": 49675, "status": 0, "flags": 6,
"bar_temp": null, "bar_pres_abs": null, "bar_pres_rel": null, "lux": 163.458,
"hum_temp": 27.74, "hum_hum": 57.2, "vbat": 3.59, "vreg": 2.72
}
}
}
view raw data.json hosted with ❤ by GitHub
przykładowy plik

Na kursie Udacity Nanodegree z Androida, którego nie ukończyłam, zdążyłam poznać bibliotekę Retrofit, którą postanowiłam użyć do pobrania pliku z serwera. Najpierw trzeba było utworzyć interfejs serwisu z obiektem typu Retrofit z adresem serwera, do którego będę się łączyć:

public interface WeatherService {
@GET("data.json")
Call<JsonObject> loadData();
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(BuildConfig.WEATHER_ADDRESS)
.addConverterFactory(GsonConverterFactory.create())
.build();
}
WeatherService.java

Poza tym serwis zawiera tylko jedną deklarację metody – loadData(), która zwraca Call<JSONObject>. Do deklaracji przypięłam adnotację, która wskazuje na endpoint, doklejaną do baseUrl z obiektu Retrofit.

Serwis tworzę i wywołuję w MainActivity. Wywołanie metody loadData wyląduje w kolejce. Tworzę Callback by wywołała się asynchronicznie. W Callbacku nadpisuję metody onResponse, jeśli wszystko będzie ok i onFailure, która wykona się jeśli coś się wykrzaczy. W pomyślnym przebiegu to co przyjdzie z serwera zamieniam na obiekty typu Sensor i dam znać do adaptera żeby zaktualizował widok.

private void sendQueryForData() {
final Context mContext = this;
WeatherService weatherService = WeatherService.retrofit.create(WeatherService.class);
final Call<JsonObject> call = weatherService.loadData();
call.enqueue(new Callback<JsonObject>() {
@Override
public void onResponse(@NonNull Call<JsonObject> call, @NonNull Response<JsonObject> response) {
JsonObject body = response.body();
if (body != null) {
List<Sensor> sensors = createSensorsFromJsonObject(body);
adapter.updateResults(sensors);
}
}
@Override
public void onFailure(@NonNull Call<JsonObject> call, @NonNull Throwable t) {
Log.e("LOAD_DATA", t.getLocalizedMessage());
Toast.makeText(mContext, R.string.connection_error, Toast.LENGTH_LONG).show();
}
});
}
MainActivity.java

Na ten moment klasa Sensor wygląda tak:

public class Sensor {
private long id;
private String label;
private double temperature;
private long timestamp;
private int humidity;
private double lux;
private Double barPressure;
private double vbat, vreg;
Sensor(Map.Entry<String, JsonElement> entry, String label) {
this.id = Long.valueOf(entry.getKey());
this.label = label;
JsonObject measurement = entry.getValue().getAsJsonObject();
this.temperature = measurement.get("hum_temp").getAsDouble();
this.timestamp = measurement.get("stamp").getAsLong();
this.humidity = measurement.get("hum_hum").getAsInt();
this.lux = measurement.get("lux").getAsDouble();
this.barPressure = measurement.get("bar_pres_rel").isJsonNull() ? null : measurement.get("bar_pres_rel").getAsDouble();
this.vbat = measurement.get("vbat").getAsDouble();
this.vreg = measurement.get("vreg").getAsDouble();
}
}
view raw Sensor.java hosted with ❤ by GitHub
Sensor.java na dzień 10.08.18 😉

ale czemu by nie skorzystać z biblioteki Moshi – trzeba tylko zmapować odpowiednie struktury 😉 Ale to stanie się gdzieś na etapie refaktoryzacji. W kolejnym wpisie – warstwa widoku. A kod można podejrzeć na githubie. Od razu uprzedzam, że nie działa, podany jest fake’owy adres – nie chcę DDoS na biedny, domowy serwerek 😉 Aplikacja jest podpięta do demo serwera na Heroku generującego losowe dane 😉

Series NavigationSensorki – widok i adapter – #1 >>

2 thoughts on “Sensorki – aplikacja „pogodowa” – #0

Dodaj komentarz

Twój adres e-mail nie zostanie opublikowany. Wymagane pola są oznaczone *

This site uses Akismet to reduce spam. Learn how your comment data is processed.