Arduino Yun - solpanel övervakningssystem (7 / 8 steg)
Steg 7: SOLPANEL övervaka – ANDROID APP (2)
WIDGETEN APP
App widgets är små fönster som kan placeras på Android startskärmen. De kan användas för att visa information eller uppgifter i ansökan på startskärmen utan att programmet körs. Jag använder detta här att ha tre huvudsakliga värden (förbrukade makt, exporterade / importerade makt och producerade power) alltid synlig när jag använder min telefon eller tablett.
Widgeten app använder sin egen timer
/ ** Uppsåt för broadcast-meddelande att uppdatera widgets * /
Uppsåt startIntent = ny Intent(SPwidget.SP_WIDGET_UPDATE);
/ ** Avvaktan uppsåt för broadcast-meddelande att uppdatera widgets * /
PendingIntent pendingIntent = PendingIntent.getBroadcast ()
sammanhang, 2701, startIntent, PendingIntent.FLAG_CANCEL_CURRENT).
/ ** Larm manager för schemalagda widget uppdateringar * /
AlarmManager alarmManager = (AlarmManager) context.getSystemService
(Context.ALARM_SERVICE);
alarmManager.setInexactRepeating (AlarmManager.RTC_WAKEUP,
System.currentTimeMillis(),
alarmTime, pendingIntent);
att uppdatera data varje 1 minut. Utvilad data dras från Arduino styrelsen
/ ** Sträng listan med delar av URL * /
String [] ipValues = deviceIP.split("/");
/ ** Sträng med Webbadressen för att få data * /
String urlString = "http://" + ipValues [2] + "/ data/få"; URL till kalla
/ ** Svar spMonitor enheten eller fel meddelandet * /
String resultToDisplay = "";
/ ** En HTTP klienten att komma åt spMonitor enheten * /
OkHttpClient klient = nya OkHttpClient();
/ ** Solenergi från spMonitor enhet som minut genomsnitt * /
Flyta solarPowerMin = 0.0f;
/ ** Konsumtion från spMonitor enhet som minut genomsnitt * /
Flyta consPowerMin = 0.0f;
/ ** Begära till spMonitor enhet * /
Begäran begäran = nya Request.Builder()
.URL(urlString)
.Build();
om (begäran! = null) {
/ ** Svar från spMonitor-enhet * /
Svar svar = client.newCall(request).execute();
om (svar! = null) {
resultToDisplay = response.body().string();
}
}
avkoda JSON
om (Utilities.isJSONValid(resultToDisplay)) {
/ ** JSON objekt som innehåller resultatet från server * /
JSONObject jsonResult = ny JSONObject(resultToDisplay);
/ ** JSON objekt som innehåller värdena * /
JSONObject jsonValues = jsonResult.getJSONObject("value");
solarPowerMin = Float.parseFloat(jsonValues.getString("S"));
consPowerMin = Float.parseFloat(jsonValues.getString("C"));
/ ** Dubbel för resultatet av solar ström och konsumtion används på 1min uppdateringar * /
Double resultPowerMin = solarPowerMin + consPowerMin;
views.setTextViewText (R.id.tv_widgetRow1Value,
String.format ("%.0f", resultPowerMin) + "W");
views.setTextViewText (R.id.tv_widgetRow2Value,
String.format ("%.0f", Math.abs(consPowerMin)) + "W");
views.setTextViewText (R.id.tv_widgetRow3Value,
String.format ("%.0f", solarPowerMin) + "W");
om (consPowerMin > 0,0 d) {
views.setTextColor (R.id.tv_widgetRow2Value,
context.getResources()
.getColor (android. R.Color.holo_red_light));
} annat {
views.setTextColor (R.id.tv_widgetRow2Value,
context.getResources()
.getColor (android. R.Color.holo_green_light));
}
}
med hjälp av okhttp biblioteket som har lätt att använda funktioner för att kommunicera över ett nätverk.
DATABASFUNKTIONERNA
Jag använder en förlängning av SQLiteOpenHelper för att få enkel tillgång till en lokal databas på Android.
klassen DataBaseHelper utökar SQLiteOpenHelper
Databasen skapas automatiskt när programmet öppnar det första gången
public void onCreate (SQLiteDatabase db) {
db.execSQL ("CREATE TABLE" + TABLE_NAME + "(" +
"år heltal, månad heltal, dag heltal, timme heltal, minut heltal," +
"Solar dubbel, cons dubbel, ljus lång," +
"id heltal primär nyckel AUTOINCREMENT);");
}
Alla nödvändiga funktioner för att komma åt databasen genomförs i Hjälpklass för databasen.
klassen DataBaseHelper utökar SQLiteOpenHelper
/**
* Lägg till en post i databasen
*
* db
* pekare till databasen
* recordLine
* Sträng med rekord
* format: åå, dd-mm, tt: mm, ljus, sol, konsumtion
* exempel: "15,08,13, 13:54, 35000, 613.456,-120.22"
*/
offentliga statisk void addDay (SQLiteDatabase db, sträng recordLine)
/**
* Läsa data av dagen "dayNumber" och returnerar data som en markör
*
* db
* pekare till databasen
* dayNumber
* den dag vi vill läsa (1-31)
* monthSelected
* den månad vi vill läsa från
* yearSelected
* året vi vill läsa från
* Markören dayStamp
* Markören med alla databasposter matchar med dayNumber
* Posten per minut är
* markören [0] = år stämpel
* markören [1] = månad stämpel
* markören [2] = dag stämpel
* markören [3] = timme stämpel
* markören [4] = minut stämpel
* markören [5] = sensor effekt
* markören [6] = Förbrukad effekt
* markören [7] = ljus värde
*/
offentliga statisk markör getDay (SQLiteDatabase db, int dayNumber, int monthSelected, int yearSelected)
/**
* Få särskild radvärden från databasen,
* t. ex. alla år lagras i databasen eller
* alla månader av ett år som lagras i databasen eller
* alla dagar i en månad för ett år i databasen
*
* db
* pekare till databasen
* requestField
* önskade raden från db
* "år" returnerar alla värdena för år hittade
* "månad" returnerar alla månad värdena i år requestLimiterYear
* "dag" returnerar alla dag värdena i månaden requestLimiterMonth
* och år requestLimiterYear
* requestLimiterMonth
* limiter för begäran
* oanvända om requestField är "år"
* oanvända om requestField är "månad"
* månad om requestField är "dagen"
* requestLimiterYear
* limiter för begäran
* oanvända om requestField är "år"
* året om requestField är "månad"
* året om requestField är "dagen"
*
* ArrayList
* array lista med alla poster hittades
*/
offentliga statisk ArrayList getEntries (SQLiteDatabase db.
Sträng requestField, int requestLimiterMonth, int requestLimiterYear)
/**
* Läsa data av dagen "dayNumber" och returnerar data som en markör
*
* db
* pekare till databasen
* Markören dayStamp
* Markören med data från den sista raden
* Posten är
* markören [0] = år stämpel
* markören [1] = månad stämpel
* markören [2] = dag stämpel
* markören [3] = timme stämpel
* markören [4] = minut stämpel
* markören [5] = sensor effekt
* markören [6] = Förbrukad effekt
* markören [7] = ljus värde
*/
offentliga statisk markör getLastRow (SQLiteDatabase db)
SYNKRONISERINGSTJÄNSTEN
Arduinoen lägger varje minut en uppsättning data i databasen. Om Android ansökan börjar, kan mängden data som ska synkroniseras vara ganska stora och ta lång tid att synkronisera. Att förkorta detta skapade jag en bakgrundstjänst som kallas en gång om dagen för att synkronisera databaser av Arduino och en Android enhet. Skriptet query.php på Arduino kallas för synkronisering.
/ ** En HTTP klienten att komma åt spMonitor enheten * /
OkHttpClient klient = nya OkHttpClient();
/ ** Sträng listan med delar av URL * /
String [] ipValues = deviceIP.split("/");
/ ** URL att kallas * /
String urlString = "http://"+ipValues[2]+"/sd/spMonitor/query.php"; URL till kalla
När på sista posten i den lokala databasen
/ ** Instans av DataBaseHelper * /
DataBaseHelper dbHelper = ny DataBaseHelper(intentContext);
/ ** Instans av data bas * /
SQLiteDatabase databas = dbHelper.getReadableDatabase();
/ ** Markören med data från databasen * /
Markören dbCursor = DataBaseHelper.getLastRow(dataBase);
om (dbCursor.getCount()! = 0) {/ / lokala databasen inte tom, behöver synkronisera endast saknas
dbCursor.moveToFirst();
int lastMinute = dbCursor.getInt(4);
int lastHour = dbCursor.getInt(3);
int lastDay = dbCursor.getInt(2);
urlString += "? datum =" + dbCursor.getString(0); Lägg till år
urlString += "-" + ("00" +
dbCursor.getString(1)).substring(dbCursor.getString(1).length()); Lägg till månad
urlString += "-" + ("00" +
String.valueOf(lastDay))
.substring(String.valueOf(lastDay).length()); Lägg dag
urlString += "-" + ("00" +
String.valueOf(lastHour))
.substring(String.valueOf(lastHour).length()); Lägg till timme
urlString += ":" + ("00" +
String.valueOf(lastMinute))
.substring(String.valueOf(lastMinute).length()); Lägg till minut
urlString += "& få = alla";
} / / annat {} lokal databas är tom, behöver synkronisera alla data
dbCursor.close();
dataBase.close();
dbHelper.close();
Göra kalla endast om giltig url ges
om (! urlString.startsWith("No")) {
/ ** Begära till spMonitor enhet * /
Begäran begäran = nya Request.Builder()
.URL(urlString)
.Build();
om (begäran! = null) {
/ ** Svar från spMonitor-enhet * /
Svar svar = client.newCall(request).execute();
om (svar! = null) {
resultData = response.body().string();
om (Utilities.isJSONValid(resultData)) {
/ ** JSON array med uppgifterna från spMonitor enhet * /
JSONArray jsonFromDevice = ny JSONArray(resultData);
/ ** Instans av DataBaseHelper * /
dbHelper = ny DataBaseHelper(intentContext);
/ ** Instans av data bas * /
Databas = dbHelper.getWritableDatabase();
Få mottagna data i lokal databas
hoppa över första post från enhet, det är redan i databasen
för (int jag = 1; jag < jsonFromDevice.length();i++) {
JSONObject med en enskild post
JSONObject jsonRecord = jsonFromDevice.getJSONObject(i);
Sträng rekord = jsonRecord.getString("d");
posten = record.replace("-",",");
spela in += "," + jsonRecord.getString("l");
spela in += "," + jsonRecord.getString("s");
spela in += "," + jsonRecord.getString("c");
DataBaseHelper.addDay (databas, rekord);
}
dataBase.close();
dbHelper.close();
}
}
}
}
Okhttp biblioteket används igen för åtkomst Arduino styrelsen.
STARTA OM TJÄNSTEN
Det är nödvändigt att starta timers för app widget uppdateringar och dagliga synkronisering igen efter Android enheten är påslagen eller var rebootet. Detta görs i AutoStart klass, som kallas av Android OS varje gång enheten startar eller var rebootet.
public void onReceive (kontext sammanhang, avsikt intent) {
om (intent.getAction().equals("android.intent.action.BOOT_COMPLETED")) {
/ ** Tillgång till delade inställningar av app widget * /
SharedPreferences wPrefs = context.getSharedPreferences("spMonitor",0);
om (BuildConfig.DEBUG) Log.d ("spMonitor Autostart", "Widget nummer =" + wPrefs.getInt("wNums",0));
om (wPrefs.getInt("wNums",0)! = 0) {
om (BuildConfig.DEBUG) Log.d ("spMonitor Autostart", "Aktivera widget timer");
/ ** Uppdateringsintervall i ms * /
int alarmTime = 60000;
/ ** Uppsåt för broadcast-meddelande att uppdatera widgets * /
Uppsåt widgetIntent = ny Intent(SPwidget.SP_WIDGET_UPDATE);
/ ** Avvaktan uppsåt för broadcast-meddelande att uppdatera widgets * /
PendingIntent pendingWidgetIntent = PendingIntent.getBroadcast ()
sammanhang, 2701, widgetIntent, PendingIntent.FLAG_CANCEL_CURRENT).
/ ** Larm manager för schemalagda widget uppdateringar * /
AlarmManager alarmManager = (AlarmManager) context.getSystemService
(Context.ALARM_SERVICE);
alarmManager.setInexactRepeating (AlarmManager.RTC_WAKEUP,
System.currentTimeMillis() + 10000,
alarmTime, pendingWidgetIntent);
Starta tjänsten för att registrera ScreenReceiverService
context.startService (ny avsiktsförklaring (sammanhang, ScreenReceiverService.class));
}
/ ** Kalender instans till setup dagliga sync * /
Kalender kalender = Calendar.getInstance();
calendar.set (Calendar.HOUR_OF_DAY, 5); utlösa kl 1
calendar.set (Calendar.MINUTE, 0);
calendar.set (Calendar.SECOND, 0);
/ ** Avvaktan uppsåt för dagliga sync * /
PendingIntent pi = PendingIntent.getService (sammanhang, 2702,
nya uppsåt (sammanhang, SyncService.class),PendingIntent.FLAG_UPDATE_CURRENT);
/ ** Larm manager för dagliga sync * /
AlarmManager är = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
am.setRepeating (AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(),
AlarmManager.INTERVAL_DAY, pi).
}
}
Klassen AutoStart kontrollerar om det finns någon app widgets aktiva och börjar uppdatera timern om det behövs. Timern för den dagliga synkroniseringen startas varje gång.
Det är det för Android ansökan. Jag gick inte in på detaljer här, eftersom källkoden är ganska stor. Men om du är intresserad kan du kolla in hela källkoden från min Github databasen.
Chef över till sista inlägget i denna serie. Kan du hitta där en lista av hårdvarukomponenter jag använt, utveckling IDE för Arduino och Android programvaruutveckling och nödvändiga biblioteken i ansökningarna.