Home » Λογισμικό » Απλή εφαρμογή Android για φωτοβολταϊκές εγκαταστάσεις

Απλή εφαρμογή Android για φωτοβολταϊκές εγκαταστάσεις


Η εφαρμογή (βλ. παρακάτω σχετικό κώδικα android) σχεδιάστηκε πρόχειρα για φωτοβολταϊκή εγκατάσταση σε σπίτι αλλά μπορεί να χρησιμοποιηθεί σε οποιαδήποτε εγκατάσταση εφόσον υπάρχουν τα ακόλουθα:

1. η εγκατάσταση διαθέτει δρομολογητή δικτύου (π.χ. το webbox της SMA Sunny) που είναι ενήμερος με όλα τα λειτουργικά στοιχεία της εγκατάστασης

2. ο δρομολογητής δύναται να συνδεθεί σε τοπικό δίκτυο ethernet και αποκρίνεται σε εντολές HTTP, οι οποίες προφανώς θα είναι ήδη γνωστές στον προγραμματιστή από την κατασκευάστρια εταιρεία

3. υπάρχει συσκευή android που μπορεί να συνδεθεί με το τοπικό δίκτυο

4. είναι γνωστή η τοπική διεύθυνση IP του φωτοβολταϊκού δρομολογητή

Στην δική μου περίπτωση υπάρχει οικιακός ρούτερ με τοπική διεύθυνση 192.168.123.1 και δυνατότητα εκπομπής wifi, ο φωτοβολταϊκός δρομολογητής είναι συνδεμένος με τον οικιακό ρούτερ με καλώδιο ethernet και λαμβάνει σταθερή IP 192.168.123.168. Η συσκευή android που χρησιμοποιήθηκε είναι ένα κινητό τηλέφωνο LG με λειτουργικό android v2.3.6 και δέκτη wifi που συνδέει το τηλέφωνο σε αυτό το τοπικό οικιακό δίκτυο.

Η λογική του κώδικα είναι να εμφανίζονται στην οθόνη του κινητού κάποιες επιλεχθείσες παράμετροι από την εγκατάσταση. Για να επιτευχθεί αυτό πρέπει να τοποθετηθεί πάνω στην οθόνη ένα ή περισσότερα αντικείμενα κειμένου, στην φάση του προγραμματισμού, τα οποία θα ανανεώνονται κάθε 6 ή γενικώς T δευτερόλεπτα. Η ανανέωση επιτυγχάνεται με συναρτήσεις ασύγχρονες (νήματα ή threads) που λειτουργούν κυκλικά. Π.χ. η συνάρτηση _wbxthread αναλαμβάνει να κάνει αυτόματο login στο webbox με μία εντολή HTTP, να ζητήσει αναφορά εγκατάστασης από το webbox με μία εντολή HTTP, να εξάγει τις παραμέτρους που θέλει από την αναφορά, να τις απεικονίσει στην οθόνη του κινητού και τέλος να κάνει logout από το webbox. Στην συνέχεια προκαλείται σκόπιμα μία καθυστέρηση T δευτερολέπτων στην εκτέλεση του κώδικα και η διαδικασία επαναλαμβάνεται από την αρχή.

Η εφαρμογή είναι πρόχειρα προγραμματισμένη σχεδόν χωρίς αποσφαλμάτωση. Η σκοπιμότητά της έγκειται στην καταγραφή των παραμέτρων σε αρχείο ανά τακτά διαστήματα ώστε να είναι δυνατή η επεξεργασία και παρουσίαση των δεδομένων από άλλες εφαρμογές π.χ. excel, access κλπ. Ακόμα περισσότερο, αναζητείται τρόπος το αρχείο αυτό να μεταφέρεται σε μία γνωστή ιστοσελίδα, σε τακτά διαστήματα, ώστε να είναι δυνατή η απομακρυσμένη μέσω διαδικτύου πρόσβαση στα τελευταία δεδομένα της εγκατάστασης.

Χριστ. Χατζ.

Χημ. Μηχ.

Κώδικας οθόνης android

<?xml version=”1.0″ encoding=”utf-8″?>
<LinearLayout xmlns:android=”http://schemas.android.com/apk/res/android&#8221;
android:layout_width=”match_parent”
android:layout_height=”match_parent”
android:orientation=”vertical” >

<DigitalClock
android:id=”@+id/digitalClock1″
android:layout_width=”wrap_content”
android:layout_height=”wrap_content”
android:inputType=”date”
android:text=”DigitalClock” />

<TextView
android:id=”@+id/LAN”
android:layout_width=”match_parent”
android:layout_height=”wrap_content”
android:scrollbars=”vertical”
android:text=”#”
android:textSize=”20dip” />

<TextView
android:id=”@+id/WAN”
android:layout_width=”wrap_content”
android:layout_height=”wrap_content”
android:text=”#”
android:textSize=”20dip” />

<TextView
android:id=”@+id/WBX”
android:layout_width=”wrap_content”
android:layout_height=”wrap_content”
android:scrollbarAlwaysDrawVerticalTrack=”true”
android:scrollbars=”vertical”
android:text=”wbx”
android:textSize=”20dip” />

<LinearLayout
android:id=”@+id/linearLayout1″
android:layout_width=”match_parent”
android:layout_height=”wrap_content”
android:layout_marginTop=”40dip”
android:orientation=”horizontal” >
</LinearLayout>

</LinearLayout>

Κώδικας android

package com.example.de.vogella.android.locationapi.simple;
//http://www.ipcas.com/blog/2011/06/threads-in-android-part-2-updating-the-ui/
//http://www.codeproject.com/Articles/19071/Quick-tool-A-minimalistic-Telnet-library?msg=4551801#xx4551801xx
//http://www.codeproject.com/Questions/262521/How-to-login-automatically-to-my-router
//http://stackoverflow.com/questions/3625837/android-what-is-wrong-with-openfileoutput
//http://www.flattermann.net/2011/02/android-howto-find-the-hardware-mac-address-of-a-remote-host/
//http://stackoverflow.com/questions/8277464/java-find-host-by-mac-address
//http://stackoverflow.com/questions/5462805/small-ip-scanner-code-in-java
//http://learn-it-stuff.blogspot.gr/2012/03/simple-android-telnet-application.html
//http://www.androidhive.info/2011/11/android-xml-parsing-tutorial/
//http://developer.android.com/training/basics/network-ops/xml.html

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.text.SimpleDateFormat;
import java.util.Date;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.util.EntityUtils;

import android.util.Log;
import android.view.Menu;
import android.app.Activity;
import android.net.DhcpInfo;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.widget.TextView;

public class ShowLocationActivity extends Activity {

protected static final String TAG = null;
private TextView lan;
private TextView wan;
private TextView wbx;
public String strg;
public String routerip1=”xxx.xxx.xxx.xxx”, routerip2=”xxx.xxx.xxx.xxx”;
public String androidip1=”xxx.xxx.xxx.xxx”, androidip2=”xxx.xxx.xxx.xxx”;
public String internetip1=”xxx.xxx.xxx.xxx”, internetip2=”xxx.xxx.xxx.xxx”;
public WifiManager wifiManager = null;
public WifiInfo wifiInfo = null;
public DhcpInfo dhcpInfo = null;
public Handler uilanh = new uilanh();
public Handler uiwanh = new uiwanh();
public Handler uiwbxh = new uiwbxh();
public long readings =0;
public long readinterv =5;

class uilanh extends Handler {
@Override
public void handleMessage(Message msg) {
// a message is received; update UI text view
lan.setText(msg.obj.toString());
super.handleMessage(msg);
}
}

class uiwanh extends Handler {
@Override
public void handleMessage(Message msg) {
// a message is received; update UI text view
wan.setText(msg.obj.toString());
super.handleMessage(msg);
}
}

class uiwbxh extends Handler {
@Override
public void handleMessage(Message msg) {
// a message is received; update UI text view
wbx.setText(msg.obj.toString());
super.handleMessage(msg);
}
}

@Override
protected void onCreate(Bundle savedInstanceState ) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_show_location);
lan = (TextView) findViewById(R.id.LAN);
wan = (TextView) findViewById(R.id.WAN);
wbx = (TextView) findViewById(R.id.WBX);
// _lanthread();
// _wanthread();
_wbxthread();
//DHCP IP Pool Summary
//Host Name IP Address MAC Address Expire Time
//android_d229e93b527c7fad 192.168.123.2 00-AA-70-97-68-BF 2days, 23:39:2
// 192.168.123.3 00-04-A3-4D-90-67 2days, 12:58:15
//android_566f64559f1fe268 192.168.123.4 1C-1D-67-54-75-58 2days, 17:8:49
//win8-mez5 192.168.123.5 78-E3-B5-99-69-C0 2days, 19:11:15
// 192.168.123.6 E8-5B-5B-0E-85-6A 2days, 17:12:10
}

/*public void _tc() {
//create a new telnet connection to hostname “gobelijn” on port “23”
TelnetConnection tc = new TelnetConnection(“gobelijn”, 23);

//login with user “root”,password “rootpassword”, using a timeout of 100ms,
//and show server output
string s = tc.Login(“root”, “rootpassword”,100);
Console.Write(s);

// server output should end with “$” or “>”, otherwise the connection failed
string prompt = s.TrimEnd();
prompt = s.Substring(prompt.Length -1,1);
if (prompt != “$” && prompt != “>” )
throw new Exception(“Connection failed”);

prompt = “”;

// while connected
while (tc.IsConnected && prompt.Trim() != “exit” )
{
// display server output
Console.Write(tc.Read());

// send client input to server
prompt = Console.ReadLine();
tc.WriteLine(prompt);

// display server output
Console.Write(tc.Read());
}

Console.WriteLine(“***DISCONNECTED”);
Console.ReadLine();
}*/

public void _wbxthread() {
Thread wbxthread = new Thread() {
public void run() {
try {
String str=””;
String str3=””;
FileOutputStream fOut=null;
do {
readings=readings+1;
str=gethttp(“http://192.168.123.168/culture/login?Userlevels=Installer&password=0000&#8221;);
//str=gethttp(“http://192.168.123.168/culture/DeviceOverview.dml?__selected=hp.processDataOverview_&__newTab=hp.PlantOverview&__deviceKey=138:2130033989:i&#8221;);
str=gethttp(“http://192.168.123.168/culture/DeviceOverview.dml?__newTab=hp.PlantOverview&__selected=hp.PlantOverview_&__deviceKey=109:155002835:p&#8221;);
try {
fOut = openFileOutput(“res.xml”,MODE_WORLD_WRITEABLE+MODE_WORLD_READABLE);
} catch (FileNotFoundException e) {
e.printStackTrace(); }
try {
OutputStreamWriter osw = new OutputStreamWriter(fOut);
osw.write(str);osw.flush();osw.close();
} catch (IOException e) {
e.printStackTrace(); }
Message msg = Message.obtain(uiwbxh);
str3=”Readings=”+String.valueOf(readings)+” at intervs of “+String.valueOf(readinterv)+” sec\n”;
str3 = str3+”Day Yield=”+findxmlvalue(str,”Day yield”)+”\n”;
str3 = str3+”Fault =”+findxmlvalue(str,”Fault” )+”\n”;
str3 = str3+”Off =”+findxmlvalue(str,”Off” )+”\n”;
str3 = str3+”Ok =”+findxmlvalue(str,”name=\”Ok\””)+”\n”;
str3 = str3+”Warning =”+findxmlvalue(str,”Warning” )+”\n”;
str3 = str3+”Minimum =”+findxmlvalue(str,”Minimum” )+”\n”;
str3 = str3+”Maximum =”+findxmlvalue(str,”Maximum” )+”\n”;
str3 = str3+”Sum =”+findxmlvalue(str,”Sum” )+”\n”;
str3 = str3+”Average =”+findxmlvalue(str,”Average” )+”\n”;
str3 = str3+”NumOfDev =”+findxmlvalue(str,”NumOfDev” )+”\n”;
str3 = str3+”Tot Yield=”+findxmlvalue(str,”Total yield”)+”\n”;
str=gethttp(“http://192.168.123.168/culture/logout&#8221;);
msg.obj = str3;
uiwbxh.sendMessage(msg);
Thread.sleep(readinterv*1000);
}
while (1==1);
}
catch (InterruptedException e) { Log.e(TAG, “run in thread”, e); }
}
};
wbxthread.start();
}

public String findxmlvalue(String source, String dest) {
/*
01. Day Yield
02. Fault
03. off
04. ok
05. Warning
06. Minimum
07. Maximum
08. Sum
09. Average
10. Number of devices
11. Total yield
12. Fault
13. Off
14. ok
15. Warning
*/
String src=””;
String res=””;
int start, start2, start3;
int indx=0;
res=””;
src=source;
start=src.indexOf(dest);
if (start>0) {
src=src.substring(start+1);
start2=src.indexOf(“<Items /><Value>”);
if (start2>0) {
src=src.substring(start2+1);
start3=src.indexOf(“</Value>”);
if (start3>0) {
res=src.substring(15, start3);
}
}
}
return res;
}

public String gethttp(String url){
try {
HttpClient httpclient = new DefaultHttpClient();
HttpGet httpget = new HttpGet(url);
HttpResponse response;
response = httpclient.execute(httpget);
HttpEntity entity = response.getEntity();
if (entity != null) {
long len = entity.getContentLength();
if (len != -1 && len < 100024) {
return EntityUtils.toString(entity);
} else {
return “Response too long or error.”;
}
} else {
return “Null:”+response.getStatusLine().toString(); }
}
catch (Exception e)
{ return e.getMessage(); }
}

public void _lanthread() {
Thread lanthread = new Thread() {
public void run() {
try {
do {
wifiManager = (WifiManager) getSystemService(WIFI_SERVICE);
wifiInfo = wifiManager.getConnectionInfo();
dhcpInfo = wifiManager.getDhcpInfo();
routerip1=String.format(“%03d.%03d.%03d.%03d”,(dhcpInfo.gateway & 0xff),(dhcpInfo.gateway >> 8 & 0xff),(dhcpInfo.gateway >> 16 & 0xff),(dhcpInfo.gateway >> 24 & 0xff));
androidip1=String.format(“%03d.%03d.%03d.%03d”,(wifiInfo.getIpAddress() & 0xff),(wifiInfo.getIpAddress() >> 8 & 0xff),(wifiInfo.getIpAddress() >> 16 & 0xff),(wifiInfo.getIpAddress() >> 24 & 0xff));
if ((routerip1.compareTo(routerip2)!=0) || (androidip1.compareTo(androidip2)!=0)) {
//strg=routerip1+”\t”+androidip1+”\n”;
strg=routerip1+”\t”+routerip2+”\t”+androidip1+”\t”+androidip2+”\n”;
routerip2=routerip1;
androidip2=androidip1;
writeips(strg);
}
Message msg = Message.obtain(uilanh);
msg.obj = strg;
uilanh.sendMessage(msg);
Thread.sleep(10*1000);
}
while (1==1);
}
catch (InterruptedException e) { Log.e(TAG, “run in thread”, e); }
}
};
lanthread.start();
}

public void _wanthread() {
Thread wanthread = new Thread() {
public void run() {
try {
do {
internetip1=getwanip();
if (internetip1.compareTo(“Error”)!=0) {
if ((internetip1.compareTo(internetip2)!=0)) {
// strg=internetip1+”\n”;
strg=internetip1+”\t”+internetip2+”\n”;
internetip2=internetip1;
writeips(strg);
}
}
Message msg = Message.obtain(uiwanh);
msg.obj = strg;
uiwanh.sendMessage(msg);
Thread.sleep(10*1000);
}
while (1==1);
}
catch (InterruptedException e) { Log.e(TAG, “run in thread”, e); }
}
};
wanthread.start();
}

public void writeips(String strg){
SimpleDateFormat sdf = new SimpleDateFormat(“yyyyMMdd_HHmmss”);
String now = sdf.format(new Date());
strg=now+”\t”+strg;
FileOutputStream fOut=null;
try {
fOut = openFileOutput(“samplefile.txt”,MODE_WORLD_WRITEABLE+MODE_WORLD_READABLE+MODE_APPEND);
} catch (FileNotFoundException e) {
e.printStackTrace(); }
try {
OutputStreamWriter osw = new OutputStreamWriter(fOut);
osw.write(strg);osw.flush();osw.close();
} catch (IOException e) {
e.printStackTrace(); }
}

public String getwanip(){
try {
HttpClient httpclient = new DefaultHttpClient();
HttpGet httpget = new HttpGet(“http://api.externalip.net/ip/&#8221;);
//HttpGet httpget = new HttpGet(“http://checkip.dyndns.org/&#8221;);
//HttpGet httpget = new HttpGet(“http://api.exip.org/?call=ip&#8221;);
HttpResponse response;
response = httpclient.execute(httpget);
HttpEntity entity = response.getEntity();
if (entity != null) {
long len = entity.getContentLength();
if (len != -1 && len < 1024) {
String str=EntityUtils.toString(entity);
return str;
} else {
return “Response too long or error.”;
}
} else {
return “Null:”+response.getStatusLine().toString(); }
}
catch (Exception e)
{ return “Error”; }

}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.show_location, menu);
return true;
}

@Override
protected void onResume() {
super.onResume();
}

@Override
protected void onPause() {
super.onPause();
}

}


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: