Funksteckdosen per Arduino und Android Steuern

Funksteckdosen per Arduino und Android Steuern

Bereits vor einiger Zeit habe ich ein kleineres Projekt gestartet, um per Android App und einem Raspberry Pi meine Funksteckdosen zu steuern. In diesem Projekt habe ich eben eine Android App erstellt, die mittels Heimnetzwerk auf unseren Raspberry Pi Befehle schickt, welche der Pi dann seinerseits in das Schalten von Funksteckdosen umgesetzt hat.

Meines Erachtens nach ein nettes Projekt, viel Spielerei und vor allem am Ende dann Komfort.
Wie dem auch sei.

Wer direkt zur Anleitung möchte, der kann direkt auf Seite 2 wechseln.

Ein bisschen Seemannsgarn zur Vorgeschichte dieses Artikels.
Letzte Woche lag ich Abends schon im Bett und wollte meine kleine Pikachu Lampe über dieses Projekt einschalten. Ich klicke und nichts geschieht. (Wo wir bei Pokemon waren: Kapador setzt Platscher ein – Nichts geschieht.) Ich klicke ein weiteres mal … nichts geschieht. Erst dachte ich daran, dass das Funksignal nicht ausreicht und schlichtweg nicht an der Funksteckdose ankommt. Diese Probleme hatte ich nämlich schon häufiger. Also bin ich müde, wie ich war aufgestanden und habe den Pi Richtung Funksteckdose hoch gehalten. Meistens funktioniert das nämlich. Dieses mal nicht.

Ich bin jemand, den so eine Fehlfunktion echt extremst nervt.
Also wollte ich meinen PC einschalten und über SSH einmal nach dem Rechten auf dem Pi schauen. Tja, Pustekuchen. Der PC hängt auch an einer Funksteckdose. Na super, da habe ich mir ja echt alle Wege verbaut.

Also bin ich schlichtweg mit meinem Handy und einer SSH App auf die glorreiche Idee gekommen mal darüber nach dem Rechten zu schauen.
Die Verbindungen schlugen jedes mal fehl. Nach langem Suchen und Tüfteln bin ich zu der Erkenntnis gelangt: Der Pi oder besser gesagt die SD Karte hat den Geist aufgegeben. Somit habe ich mich dazu entschlossen einen Arduino für das Schalten der Steckdosen zu verwenden.

Für mein Projekt habe ich einen Arduino Nano (der Aufbau sollte ja so klein, wie möglich sein), ein USB-Ladekabel, ein altes Handy Ladegerät, ein Lan-Kabel, einen Netzwerkadapter, 3 Jumper Kabel (Female-Female) und ein 433Mhz Sender verwendet.

Die Kosten für dieses Projekt würden sich bei einer Lieferung aus China auf etwa 10€ belaufen (voraugesetzt ihr habt noch ein altes Lan-Kabel und ein altes Handy-Ladegerät). Bei einer Bestellung über Amazon und selben Voraussetzungen würden wir bei ca. 30€ landen. Ich habe mich für die Lieferung über Amazon entschieden, da ich meine nötigen Teile so nach 2 Tagen in der DHL Packstation vorgefunden habe.

Hier noch einmal meine Einkaufsliste:

Sind dann alle nötigen Teile da, könnt ihr direkt beginnen. Einen Lötkolben benötigt ihr nicht. Dafür aber höchstens eine Heißklebepistole oder aber etwas dickere beidseitige Klebestreifen und das auch nur, wenn ihr das 433Mhz Sendermodul an den Arduino kleben wollt.

Als erstes installiert ihr die Arduino IDE, welche unter Windows 10 auch im Microsoft Store erhältlich ist.
Alternativ könnt ihr diese auch hier herunterladen: Arduino IDE

Steckt den Arduino auf das Lan-Modul und zwar so, dass der USB-Anschluss dem Lan-Anschluss gegenüber liegt. Die beide Anschlüsse dürfen nicht in die selbe Richtung zeigen.

Steckt den linken Pin des 433Mhz Senders über die Jumper an GND des Arduinos. Den rechten Pin steckt ihr an 5v und den mittleren an den Pin 10 (Beschriftung ist hier “D10”). Falls benötigt könnt ihr noch eine Antenne an das 433Mhz Modul löten. Hier bitte das Loch ganz unten links auf dem Bild verwenden. Das ist aber absolut optional und verbessert lediglich die Sendeleistung.

Sender 433mhz

Sender 433mhz

Arduino Nano mit Lan und 433Mhz Modul zur Schaltung von Steckdosen

Arduino Nano mit Lan und 433Mhz Modul zur Schaltung von Steckdosen

Zur späteren besseren Übersicht öffnet nun bitte die Arduino IDE und geht über den Menüpunkt “Werkzeuge” mit der Maus auf “Port”. Merkt euch, welche Ports dort aufgelistet sind.

Nun können wir den Code, nach Erstellung eines neuen Projektes (Sketch) einfügen:

#include <ethercard.h>
#include <rcswitch.h>
 
static byte mymac[] = { 0x74, 0x69, 0x59, 0x2A, 0x31, 0x31 };
static byte myip[] = { 192, 168, 0, 200 };

RCSwitch sender = RCSwitch();
byte Ethernet::buffer[500];
BufferFiller bfill;
 
const char HttpNotFound[] PROGMEM =
 "HTTP/1.0 404 Unauthorized\r\n"
 "Content-Type: text/html\r\n\r\n"
 "

404 Page Not Found

"
; void setup () { Serial.begin(9600); sender.enableTransmit(10); // Der Sender wird an Pin 10 angeschlossen if (ether.begin(sizeof Ethernet::buffer, mymac) == 0) { Serial.println("Failed to access Ethernet"); }else{ Serial.println("Successfully started Server."); } ether.staticSetup(myip); } static word HomePage(unsigned long code) { bfill = ether.tcpOffset(); bfill.emit_p(PSTR( "HTTP/1.0 200 OK\r\n" "Content-Type: application/json\r\n" "Pragma: no-cache\r\n" "\r\n" "Sending Code: $L"), code); return bfill.position(); } unsigned long code = 0L; void loop () { word len = ether.packetReceive(); word pos = ether.packetLoop(len); if (pos) // check if valid tcp data is received { bfill = ether.tcpOffset(); char* data = (char*) Ethernet::buffer + pos; if (strncmp("GET /", data, 5) != 0) { bfill.emit_p(HttpNotFound); } else { data += 5; sscanf(data, "?code=%lx", &amp;code); Serial.println("Code: "); Serial.println(code); HomePage(code); sender.send(code, 24); } ether.httpServerReply(bfill.position()); // send http response } }


In Zeile 5 definieren wir die IP-Adresse unseres Arduinos. Wer also eine andere IP-Adresse angeben möchte, der kann hier gerne Änderungen vornehmen.

Um unseren Code nun auf den Arduino zu bringen müssen wir diesen über das mitgelieferte USB-Kabel an den PC anschließen. Schaut anschließend wieder über den Menüpunkt “Werkzeuge” und “Port” nach den angezeigten Ports. Wählt hier dann den neu hinzugekommenen Port aus. Zusätzlich wählen wir bei den beiden darüber liegenden Menüpunkten aus:

  • Board: Arduino Nano
  • Prozessor: ATmega328P

Schlussendlich müssen wir nur noch auf den nach rechts zeigenden Pfeil in der grünen Leiste klicken und unser Code wird auf den Arduino geschoben.

Arduino IDE - Code auf den Arduino schieben

Arduino IDE – Code auf den Arduino schieben

Da jetzt nun hoffentlich alles geklappt hat können wir uns der entsprechenden Android App widmen.
Der Clue an dem Arduino ist, dass wir keine SSH Verbindung benötigen. Ein einfacher Aufruf einer URL reicht aus, denn der Arduino reagiert auf einen simplen Aufruf, wie im Browser.

Wir müssen ledigt unter Android einen Aufruf der Form “192.168.0.200/?code=32423” generieren. Unter der Prämisse, dass der Code in hexadezimal Schreibweise notiert ist. Wollen wir also den Code 15 per 433Mhz Modul senden, dann verwenden wir den Aufruf “192.168.0.200/?code=F”.

Für die einfache Umrechnung könnt ihre folgendes Tool verwenden: http://binaer-dezimal-hexadezimal-umrechner.miniwebapps.de/
Tragt dort einfach euren gefundenen Code in die “Dezimal”spalte ein und verwendet dann den Code im “Hexadezimal”feld.

Für einen ersten Test könnt ihr die URL auch einfach in den Browser eingeben. Der Arduino wird euch dann anzeigen, welcher Code gerade gesendet wird.

Die Android App:

Aber genug der Zusatzinformationen. Fangen wir an die App zu programmieren.
Ich dachte mir, dass es einfacher wäre eine leicht zu editierende App zu programmieren, damit ihr schnell und einfach beliebig viele Steckdosen hinzufügen und wieder entfernen könnt.

Damit unsere App später einmal sehr leichter erweitert werden kann erstellen wir eine neue Klasse.
Wir nennen diese einfach einmal “Steckdose” und füllen sie mit folgendem Inhalt:


package de.staticfloat.arduinosteckdosen;

public class Steckdose {

 String name = "Unbekannte Steckdose";
 String codeOn = "";
 String codeOff = "";

 public Steckdose(String name, String codeOn, String codeOff){
 this.name = name;
 this.codeOn = codeOn;
 this.codeOff = codeOff;
 }
}

Super!

Wir haben eine neue Klasse erstellt, die es uns ermöglicht eine Steckdose zu registrieren.
Da wir später noch eine Anfrage an unseren Arduino senden senden wollen müssen wir unserer App die Berechtigung erteilen sich ins Netz zu verbinden.
Tragt dazu in die Datei “AndroidManifest.xml” diese Zeile zwischen “manifest” und “application” ein:

<uses-permission android:name="android.permission.INTERNET"></uses-permission>

Bevor wir unsere App dann mit der richtigen Programmierung fertigstellen müssen wir noch das Layout anpassen. Öffnet hierzu die Datei “activity_main.xml” und ersetzt den Inhalt mit:

<!--?xml version="1.0" encoding="utf-8"?-->
<linearlayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/steckdosenListe" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" tools:context="de.staticfloat.arduinosteckdosen.MainActivity">

</linearlayout>


Das wars auch schon an “Vorarbeit”.

Auf der nächsten Seite gibt es den vollständigen Code, zur Schaltung der Steckdosen.

Ich habe versucht den Code so klein und übersichtlich wie möglich zu gestalten.
In Zeile 20-22 sind 3 Steckdosen vorbereitet. Jede Zeile beschreibt eine neue Steckdose. Der erste Parameter ist dabei der Name der Steckdose. Der zweite besteht aus dem Code zum einschalten dieser Steckdose und der dritte Parameter wiederum zum ausschalten.

Zeile 18 sollte dabei die von euch gewählte IP-Adresse beinhalten.


package de.staticfloat.arduinosteckdosen;

import android.os.AsyncTask;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.LinearLayout;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.URL;


public class MainActivity extends AppCompatActivity {

 private static String arduinoUrl = "http://192.168.0.200/?code=";
 private Steckdose[] steckdosen = new Steckdose[]{
 new Steckdose("Steckdose 1", "11111", "11112"),
 new Steckdose("Steckdose 2", "22221", "22222"),
 new Steckdose("Steckdose 3", "33331", "33332")
 };

 @Override
 protected void onCreate(Bundle savedInstanceState) {
 super.onCreate(savedInstanceState);
 setContentView(R.layout.activity_main);

 for(Steckdose steckdose : steckdosen){
 erstelleButtonFuerSteckdose(steckdose);
 }
 }

 private void erstelleButtonFuerSteckdose(final Steckdose steckdose){
 Button buttonOn = new Button(this);
 buttonOn.setText(steckdose.name + " - Ein");
 buttonOn.setOnClickListener(new View.OnClickListener() {
 @Override
 public void onClick(View view) {
 new RequestTask().execute(arduinoUrl + steckdose.codeOn);
 }
 });

 Button buttonOff = new Button(this);
 buttonOff.setText(steckdose.name + " - Aus");
 buttonOff.setOnClickListener(new View.OnClickListener() {
 @Override
 public void onClick(View view) {
 new RequestTask().execute(arduinoUrl + steckdose.codeOff);
 }
 });

 LinearLayout ll = (LinearLayout) findViewById(R.id.steckdosenListe);
 ll.addView(buttonOn);
 ll.addView(buttonOff);
 }
}

class RequestTask extends AsyncTask {

 @Override
 protected String doInBackground(String... uri) {
 String responseString = "";
 try {
 String line = null;
 URL urls = new URL(uri[0]);
 InputStreamReader isr = new InputStreamReader(urls.openStream(), "UTF-8");
 BufferedReader reader = new BufferedReader(isr);
 while ((line = reader.readLine()) != null) {
 responseString += line;
 Log.d("Ausgabe", line);
 }

 } catch (Exception e) {
 e.printStackTrace();
 }
 return responseString;
 }

 @Override
 protected void onPostExecute(String result) {
 super.onPostExecute(result);
 }
}

Ich wünsche viel Spaß beim basteln/tüfteln/schalten.

Marvin

Ich bin ein Mensch, der sich neben der Programmierung noch für tausend andere Dinge interessiert, die mal mehr und mal weniger verrückt sind. Vor allem aber bin ich Feuer und Flamme mit der Programmierung von eigenen kleinen Apps und Programmen, die mein Leben bereichern.

Hat dir dieser Artikel gefallen?

Kommentar hinzufügen

*Pflichtfeld

  1. Tobias

    Hallo Melvin, danke für deine Beschreibung. Echt super! Könntest du eine Anleitung auch hierzu schreiben, wie ich folgendes Einrichten kann im Detail: "Wenn ihr auch von Unterwegs Steckdosen steuern möchtet, dann solltet ihr versuchen an euren Raspberry Pi eine statische lokale IP-Adresse zu vergeben, im Router eine Port-Weiterleitung einrichten und einen Dienst, wie DynDNS, in eurem Router aktivieren." Bin in der Hinsicht blutiger Anfänger.... Gruß und Danke! Toby

  2. Melvin

    Hallo Tobias, das Duplikat deines Kommentars habe ich mal mal weg gelassen. Ich kann gerne einen weiteren Artikel dazu schreiben, möchte aber so ehrlich sein und dir von diesem Weg abraten. Zumindest was das Schalten der Steckdosen über SSH und einen öffentlichen Port angeht. Angesichts der Tatsache, dass du dich als Anfänger siehst könnte es zu Sicherheitsproblemen kommen. Ich werde die Tage den Artikel schreiben und dann hier in den Kommentaren verlinken. Spätestens zu Wochenende kannst du dann alles nachlesen. Wenn du allerdings noch ein wenig mehr Zeit hast, dann kann ich ja mal aus dem Nähkästchen plaudern und verraten, dass ich gerade noch in der Closed Alpha eine Android App programmiere, die ohne SSH auskommt. Vielleicht könnte ich dich in die closed Alpha im PlayStore hinzufügen, wenn du mir deine Gmail Adresse einmal per Mail an mail(at)staticfloat.de zuschickst. Gruß, Marvin