Φτιάχνοντας ένα Έξυπνο Σπίτι, και έλεγχος από το Android (μέρος 5ο)

android smart home

Φτάνοντας στο 5ο μέρος της κατασκευής του "Έξυπνου Σπιτιού", θα κατασκευάσουμε την Android εφαρμογή που θα λαμβάνει δεδομένα από αισθητήρες. (1o, 2o, 3o, 4o)

Μέχρι τώρα έχουμε προβάλλει δεδομένα από αισθητήρες στον Web Browser των συσκευών μας (PC, Laptop, Tablet, κινητό), οπότε σήμερα θα δούμε πώς θα φτιάξουμε την σχετική Android εφαρμογή.

Η λογική του σχεδίου μας

Η λογική είναι η εξής, οι αισθητήρες παίρνουν δεδομένα τα οποία στέλνουν στο Arduino, το οποίο με την σειρά του τα ανεβάζει μέσω της Ethernet Shield σε έναν HTTP Server.

Στην συνέχεια η Android εφαρμογή διαβάζει τα δεδομένα αυτά από τον HTTP Server, και τα προβάλλει.

  • arduino-ethernet-schematic

Ανάπτυξη Android εφαρμογής

Αφού εγκαταστήσετε τα απαραίτητα προγράμματα στο PC σας, και δείτε λίγο τις λειτουργίες του IDE με το παράδειγμά μας για το Hello World, είστε έτοιμοι να αρχίσετε την ανάπτυξη της εφαρμογής.

Στο νέο project μας (στην πιο απλή μορφή του) αρκεί ένα WebView το οποίο θα διαβάζει το HTML που φτιάξαμε στον Server στο Arduino.

  • java-code

Ενδεικτικά ο κώδικας java που μπορείτε να χρησιμοποιήσετε:

package com.sql.greekapp;

import android.app.Activity;
import android.os.Build;
import android.os.Bundle;
import android.view.KeyEvent;
import android.view.Window;
import android.webkit.WebChromeClient;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;

import com.sql.greekapp.R;

public class GreekNewsActivity extends Activity {
	WebView webview;
    
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        this.getWindow().requestFeature(Window.FEATURE_PROGRESS);
        setContentView(R.layout.main);    
        getWindow().setFeatureInt(	Window.FEATURE_PROGRESS, Window.PROGRESS_VISIBILITY_ON); 
        
        webview = (WebView) findViewById(R.id.web_engine); 
        webview.setWebViewClient(new HelloWebViewClient());
        webview.getSettings().setJavaScriptEnabled(true); 
        webview.getSettings().setPluginsEnabled(true);  //depriciated
        if (Integer.parseInt(Build.VERSION.SDK) >= Build.VERSION_CODES.FROYO)
        	webview.getSettings().setPluginState(WebSettings.PluginState.ON); 
        webview.getSettings().setAllowFileAccess(true);        
        webview.getSettings().setBuiltInZoomControls(true); //multitouch an ipostirizetai        
        webview.setScrollBarStyle(WebView.SCROLLBARS_OUTSIDE_OVERLAY);
        webview.loadUrl("http://192.168.10.250"); //o server tou Arduino
        
        //webview.loadUrl("http://google.com"); //gia debug   
      
       final Activity MyActivity = this;
	   webview.setWebChromeClient(new WebChromeClient() {
       public void onProgressChanged(WebView view, int progress)   
       {
       	//Na svisw tin mpara afou fortwsei to url
       	MyActivity.setTitle("Φόρτωση...");
       	MyActivity.setProgress(progress * 100); //svisimo

       	// Kai na emfanisw to app name
           if(progress == 100)
           	MyActivity.setTitle(R.string.app_name);
         }
       });
   
    }

    //Na krataw ta clicks within the app
    private class HelloWebViewClient extends WebViewClient {
        @Override
        public boolean shouldOverrideUrlLoading(WebView view, String url) {        	 
                return false;            
        }    
    }
    
    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        if ((keyCode == KeyEvent.KEYCODE_BACK) && webview.canGoBack()) {
            webview.goBack();
            return true;
        }
        return super.onKeyDown(keyCode, event);
    }    
}

Καθώς και το layout/main.xml για το UI της Android εφαρμογής:

  • main-xml

Και το αποτέλεσμα:

  • android-app

Εναλλακτικές (σωστότερες) υλοποιήσεις (xml/json)

Αντί να "στήσουμε" μία ολόκληρη HTTP σελίδα στον WebServer στο Arduino, και απλά να Linkάρουμε σε αυτόν από την Android εφαρμογή μας, είναι προγραμματιστικά σωστότερο να "φτιάχνουμε" ένα xml στον server μας (ή json), το οποίο θα περιέχει τις μετρήσεις.

Στην συνέχεια θα κάνουμε "parse" το xml αυτό από την Android εφαρμογή.

  • arduino-xml

Κώδικας στο Arduino για να πάρουμε xml output:

#include <SPI.h>
#include <Ethernet.h>

byte mac[] = { 
  0xDE, 0xDE, 0xDE, 0xDE, 0xDE, 0xDE }; //orizoume emeis ti mac theloume, heh!
IPAddress ip(192,168,10,250); //i ip tis siskevis sto diktio, profanws rithmiste analogws

EthernetServer server(80);

void setup() {
  pinMode(4, OUTPUT); // buzzer, exodos
  Serial.begin(9600);
   while (!Serial) {
    ; // serial debug
  }


  Ethernet.begin(mac, ip);
  server.begin();
  Serial.print("server is at ");
  Serial.println(Ethernet.localIP());
}


void loop() {
  // listen for incoming clients
  EthernetClient client = server.available();
  if (client) {
    Serial.println("new client");
    // an http request ends with a blank line
    boolean currentLineIsBlank = true;
    while (client.connected()) {
      if (client.available()) {
        char c = client.read();
        Serial.write(c);
        if (c == '\n' && currentLineIsBlank) {          
          client.println("HTTP/1.1 200 OK"); // standard http response header
          client.println("Content-Type: text/xml"); //text/xml otan theloume na vgaloume xml output
          client.println("Connection: close");
          client.println();
          client.println(""); //UTF8 giati tha xoume kai ellhnika
          client.println("");
          client.print("");
          //thermokrasia         
          int sensorReading = analogRead(0);
          float temp;
          temp = (sensorReading * 0.488);
          client.print(temp);          
          client.println("");
          client.println("");
            if (temp>30){
                buzz(4, 2000, 4000); // energopoihsh toy buzzer sto pin 4 sta 2000Hz gia 2 sec
                delay(1000); // diakopi gia 1 second
            }

          break;
        }
        if (c == '\n') {
          // you're starting a new line
          currentLineIsBlank = true;
        } 
        else if (c != '\r') {
          // you've gotten a character on the current line
          currentLineIsBlank = false;
        }
      }
    }
    // give the web browser time to receive the data
    delay(1);
    // close the connection:
    client.stop();
    Serial.println("client disonnected");
  }
}

void buzz(int targetPin, long frequency, long length) {
  long delayValue = 1000000/frequency/2;
  long numCycles = frequency * length/ 1000;
 for (long i=0; i < numCycles; i++){
    digitalWrite(targetPin,HIGH);
    delayMicroseconds(delayValue);
    digitalWrite(targetPin,LOW);
    delayMicroseconds(delayValue);
  }
}

Κάντε Like το GreeceAndroid.gr στο Facebook!

Γίνετε μέλος της Ελληνική Κοινότητας του Android στο G+

aByte