{"id":235,"date":"2017-06-07T19:18:42","date_gmt":"2017-06-07T17:18:42","guid":{"rendered":"https:\/\/www.pingu-mobil.de\/iot\/?p=235"},"modified":"2021-05-14T10:07:52","modified_gmt":"2021-05-14T08:07:52","slug":"dingdong-2-blogeintrag-automatische-netzwerkverbindung","status":"publish","type":"post","link":"https:\/\/www.iot-embedded.de\/iot-2017\/tuersteuerung\/dingdong-2-blogeintrag-automatische-netzwerkverbindung\/","title":{"rendered":"DingDong 2. Blogeintrag: Automatische Netzwerkverbindung"},"content":{"rendered":"<p>In unserem Projekt wird ein Raspberry zur Steuerung einer T\u00fcr verwendet. Das Konfigurieren der Netzwerkverbindung ist meine Aufgabe im Projekt. Der Raspberry soll\u00a0vom Kunden \u00fcber eine App bzw. \u00fcber einen Browser konfiguriert werden. Es stehen keine anderen Konfigurationsm\u00f6glichkeiten (wie z. B. Bildschirm und Tastatur) zur Verf\u00fcgung. Da der Raspberry nahe der Gegensprechanlage installiert werden muss, soll sich dieser per WLAN mit dem Heimnetzwerk\/Internet verbinden. Diese Verbindung (WLAN, Passwort und eventuell statische IP) muss jedoch zun\u00e4chst konfiguriert werden. Um den Raspberry konfigurieren zu k\u00f6nnen, soll dieser sein eigenes WLAN (Access Point) starten. Mit diesem kann sich der Kunde verbinden und die Konfiguration vornehmen. Die Umsetzung dieser Anforderungen wird nachfolgend beschrieben.<\/p>\n<p>Es werden drei Services verwendet: hostapd,\u00a0dnsmasq und\u00a0wpa_supplicant.<\/p>\n<ul>\n<li>hostapd erstellt einen Access Point (AP).<\/li>\n<li>dnsmasq ist ein DNS- und DHCP-Server. Dieser ist notwendig, um eine IP an ein mit dem AP verbundenes Ger\u00e4t zu vergeben.<\/li>\n<li>wpa_supplicant ist ein WLAN &#8222;Bittsteller&#8220; der u. a. WPA und WPA2 unterst\u00fctzt.<\/li>\n<\/ul>\n<p>Diese Services m\u00fcssen \u00fcber Scripte automatisch konfiguriert und gestartet werden. Ich habe mich aus Gr\u00fcnden der Einfachheit gegen eine direkte Umsetzung in Buildroot entschieden und stattdessen in Raspbian gescriptet und getestet. Auch bei dieser &#8222;einfacheren&#8220; Umsetzung entstanden viele Probleme, die in den Scripts ber\u00fccksichtigt werden mussten. Haupts\u00e4chlich entstehen diese durch die gemeinsame Nutzung von Ressourcen durch hostapd , dnsmasq und wpa_supplicant.<\/p>\n<p>Zun\u00e4chst m\u00fcssen hostapd und dnsmasq installiert werden. (wpa_supplicant ist bereits installiert)<\/p>\n<blockquote><p>apt-get install hostapd dnsmasq -y<\/p><\/blockquote>\n<p>Damit hostapd als Service gestartet werden kann, muss in der Konfigurationsdatei \/etc\/default\/hostapd die Zeile<\/p>\n<blockquote><p>DAEMON_CONF=&#8220;\/etc\/hostapd\/hostapd.conf&#8220;<\/p><\/blockquote>\n<p>hinzugef\u00fcgt werden. Um einen Start der Services beim Booten zur verhindern, m\u00fcssen diese deaktiviert werden:<\/p>\n<blockquote><p>systemctl disable hostapd.service<br \/>\nsystemctl disable dnsmasq.service<br \/>\nsystemctl disable wpa_supplicant.service<\/p><\/blockquote>\n<p>Anschlie\u00dfend sollte das System neu gestartet werden.<\/p>\n<p>Die Services werden \u00fcber 5 Dateien Konfiguriert:<\/p>\n<ul>\n<li><strong>\/etc\/dnsmasq.conf<\/strong> enth\u00e4lt die Konfiguration zur Vergabe von IP-Adressen im AP-Modus.<\/li>\n<li><strong>\/etc\/hostapd\/hostapd.conf<\/strong> enth\u00e4lt die Konfiguration des\u00a0APs.<\/li>\n<li><strong>\/etc\/network\/interfaces<\/strong> enth\u00e4lt die Konfiguration der Netzwerkinterfaces.<\/li>\n<li><strong>\/etc\/dhcpcd.conf<\/strong> enth\u00e4lt die Konfiguration des DHCP Clients.<\/li>\n<li><strong>\/etc\/wpa_supplicant\/wpa_supplicant.conf\u00a0<\/strong>enth\u00e4lt die Konfiguration des WLAN.<\/li>\n<\/ul>\n<p>Das Starten der Services und das Konfigurieren der Dateien wird durch 4 Scripte erledigt.<\/p>\n<ul>\n<li><strong>startup.sh<\/strong> startet nach dem Booten das WLAN (ruft hierf\u00fcr<strong> wlan-setup.sh<\/strong> auf) und ruft anschlie\u00dfend <strong>switch.sh<\/strong> auf.<\/li>\n<li><strong>switch.sh<\/strong> \u00fcberpr\u00fcft, ob eine WLAN-Verbindung erfolgreich aufgebaut werden konnte. Ist dies der Fall, wird nichts unternommen. Konnte keine WLAN-Verbindung aufgebaut werden, wird nach verf\u00fcgbaren WLANs gesucht. Diese werden in einer Datei gespeichert, die sp\u00e4ter dem Kunden in der WLAN-Konfiguration angezeigt werden soll. Anschlie\u00dfend wird <strong>ap-setup.sh<\/strong> aufgerufen.<\/li>\n<li><strong>wlan-setup.sh<\/strong> versucht eine Verbindung mit dem hinterlegten WLAN aufzubauen.<\/li>\n<li><strong>ap-setup.sh <\/strong>erstellt einen &#8222;offenen&#8220; AP.<\/li>\n<\/ul>\n<p>Beispielhaft sind unten die Scripte<strong> switch.sh<\/strong> und <strong>ap-setup.sh<\/strong> angeh\u00e4ngt.<\/p>\n<p>&nbsp;<\/p>\n<p><strong>&#8211;&gt; Aktueller Status: Raspberry konfiguriert sein Netzwerk selbst\u00e4ndigt und ohne Reboot<\/strong><\/p>\n<ul>\n<li>Raspberry verbindet sich (wenn m\u00f6glich) mit dem konfigurierten WLAN.<\/li>\n<li>Ist dies nicht m\u00f6glich, scannt dieser die verf\u00fcgbaren WLANs und startet in den AP-Modus.<\/li>\n<li>Verbindet sich ein Ger\u00e4t im AP-Modus, bekommt dieses eine IP-Adresse zugewiesen.<\/li>\n<\/ul>\n<p><strong>&#8211;&gt; TO DO<\/strong><\/p>\n<ul>\n<li>Umsetzung in Buildroot<\/li>\n<li>Bug: Manchmal werden WLAN-Prozesse nicht richtig beendet<\/li>\n<li>Bug: Der AP-Modus funktioniert nur, wenn ein bestimmter WLAN-Kanal gew\u00e4hlt wird. Das automatische w\u00e4hlen des Kanals\u00a0funktioniert nicht.<\/li>\n<li>Die Ausnahmebehandlung in den Scripts muss verbessert werden. So k\u00f6nnen auch auf viele Sleep-Funktionen verzichtet und der Prozess beschleunigt werden.<\/li>\n<li>Noch sind die WLAN-Informationen fest im Script hinterlegt. Diese sollen in eine Konfigurationsdatei ausgelagert werden.<\/li>\n<li>Die IP im WLAN-Modus wird momentan \u00fcber DHCP bezogen -&gt; M\u00f6glichkeit der Konfiguration einer statischen IP soll gegeben sein.<\/li>\n<li>Nice to have:\n<ul>\n<li>Bei einem Rest des Raspberry (Hardwareschalter?) soll die WLAN-Konfiguration gel\u00f6scht werden.<\/li>\n<li>Bei einem Verbindungsabbruch des WLANs, soll automatisch die\u00a0Verbindung wiederhergestellt werden.<\/li>\n<li>LEDs am Raspberry zeigen an, ob er im WLAN-Modus oder AP-Modus ist.<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<p><strong>Scripte:<\/strong><\/p>\n<p><strong>switch.sh<\/strong><\/p>\n<blockquote><p>#!\/bin\/bash<br \/>\n#<br \/>\n#\u00fcberpr\u00fcfe ob Rootrechte vorhanden sind<br \/>\nif [ &#8222;$EUID&#8220; -ne 0 ]<br \/>\nthen echo &#8222;Must be root&#8220;<br \/>\nexit<br \/>\nfi<\/p>\n<p>#\u00fcberpr\u00fcfen ob mit WLAN verbunden<br \/>\nstatus=$(wpa_cli status | grep wpa_state | tr -d wpa_state=)<br \/>\nif [ &#8222;$status&#8220; == &#8222;COMPLETED&#8220; ]<br \/>\nthen<br \/>\n#wenn Raspberry mit WLAN verbunden ist, wird nichts unternommen<br \/>\necho &#8222;&#8212;&gt; WLAN Status: Verbunden&#8220;<br \/>\necho &#8222;Debug: Es wurden keine \u00c4nderungen durchgef\u00fchrt&#8220;<\/p>\n<p>else<br \/>\n#wenn Raspberry nicht mit WLAN verbunden ist, soll Access Point (AP) gestartet werden<br \/>\necho &#8222;&#8212;&gt; WLAN Status: Nicht verbunden&#8220;<br \/>\necho &#8222;&#8212;&gt; Pr\u00fcfe ob AP-Modus bereits gestartet ist&#8220;<br \/>\n#\u00fcberpr\u00fcfe den AP Status<br \/>\napstatus=$(sudo service hostapd status | grep &#8218;Active:&#8216;)<br \/>\nif [[ $apstatus == *&#8220;running&#8220;* ]]<br \/>\nthen<br \/>\n#wenn der AP l\u00e4uft<br \/>\necho &#8222;&#8212;&gt; AP l\u00e4uft bereits: Es werden keine \u00c4nderungen durchgef\u00fchrt&#8220;<br \/>\nelse<br \/>\n#wenn der AP nicht l\u00e4uft<br \/>\necho &#8222;&#8212;&gt; AP l\u00e4uft nicht&#8220;<br \/>\necho &#8222;&#8212;&gt; Suche Nach WLANs&#8220;<br \/>\n#f\u00fchre wlan konfiguration durch<br \/>\nsource \/bin\/wlan-setup.sh<br \/>\n#warten bis wlanadapter verf\u00fcgbar ist<br \/>\nsleep 15<br \/>\n#suche nach verf\u00fcgbaren WLANs und schreibe diese in eine Datei<br \/>\niwlist wlan0 scan | grep &#8218;ESSID\\|Encryption key&#8216; &gt; \/bin\/wifis<br \/>\n#der erste Scanversuch schl\u00e4gt meistens fehl<br \/>\niwlist wlan0 scan | grep &#8218;ESSID\\|Encryption key&#8216; &gt; \/bin\/wifis<br \/>\n#Leerzeichen am Anfang jeder Zeile in der WLAN Datei l\u00f6schen<br \/>\nsed -i &#8217;s\/^ *\/\/&#8216; \/bin\/wifis<br \/>\necho &#8222;&#8212;&gt; Folgende WLANs wurden gefunden&#8220;<br \/>\n#gefundene WLANs anzeigen<br \/>\ncat \/bin\/wifis<br \/>\n#AP Modus starten<br \/>\necho &#8222;&#8212;&gt; Starte AP-Modus&#8220;<br \/>\nsleep 5<br \/>\nsource \/bin\/ap-setup.sh<br \/>\nfi<br \/>\nfi<\/p><\/blockquote>\n<p>&nbsp;<\/p>\n<p><strong>ap-setup.sh<\/strong><\/p>\n<blockquote><p>#!\/bin\/bash<br \/>\n#<br \/>\n#\u00fcberpr\u00fcfe ob Rootrechte vorhanden sind<br \/>\nif [ &#8222;$EUID&#8220; -ne 0 ]<br \/>\nthen echo &#8222;Must be root&#8220;<br \/>\nexit<br \/>\nfi<\/p>\n<p>#eventuell gestartete Services und Prozesse m\u00fcssen beendet werden, die die selben Ressourcen nutzen<br \/>\necho &#8222;Debug: Services stoppen&#8220;<br \/>\nwpa_cli -i wlan0 terminate<br \/>\n#Services stoppen<br \/>\nsystemctl stop hostapd.service<br \/>\nsystemctl stop dnsmasq.service<br \/>\nsystemctl stop wpa_supplicant.service<br \/>\n#warte bis Services gestoppt sind<br \/>\nsleep 5<br \/>\n#es kann vorkommen, dass nicht alle Prozesse beendet wurden<br \/>\nkillall -v wpa_supplicant<\/p>\n<p>#pr\u00fcfen ob wpa_supplicant wirklich beendet wurde<br \/>\nprozessstatus=$(ps -e | grep wpa_supplicant)<br \/>\nif [[ $prozessstatus == *&#8220;wpa_supplicant&#8220;* ]]<br \/>\nthen<br \/>\necho &#8222;&#8212;&gt; ERROR: Prozess wpa_supplicant l\u00e4uft noch&#8220;<br \/>\nfi<\/p>\n<p>echo &#8222;Debug: DHCP konfigurieren&#8220;<br \/>\n#dnsmasq.conf wird konfiguriert<br \/>\ncat &gt; \/etc\/dnsmasq.conf &lt;&lt;EOF<br \/>\ninterface=wlan0<br \/>\ndhcp-range=10.0.0.2,10.0.0.5,255.255.255.0,12h<br \/>\nEOF<\/p>\n<p>#hostapd wird konfiguriert<br \/>\ncat &gt; \/etc\/hostapd\/hostapd.conf &lt;&lt;EOF<br \/>\n#AP Konfiguration<br \/>\ninterface=wlan0<br \/>\nhw_mode=g<br \/>\nchannel=6<br \/>\nssid=DingDong<br \/>\nEOF<\/p>\n<p>#Netzwerkinterfaces werden konfiguriert<br \/>\ncat &gt; \/etc\/network\/interfaces &lt;&lt;EOF<br \/>\n#AP Konfiguration<br \/>\niface eth0 inet manual<\/p>\n<p>wpa-conf \/etc\/wpa_supplicant\/wpa_supplicant.conf<\/p>\n<p>allow-hotplug wlan0<br \/>\niface wlan0 inet static<br \/>\naddress 10.0.0.1<br \/>\nnetmask 255.255.255.0<br \/>\nnetwork 10.0.0.0<br \/>\nbroadcast 10.0.0.255<br \/>\nEOF<\/p>\n<p>#dhcp client wird konfiguriert<br \/>\necho &#8222;denyinterfaces wlan0&#8220; &gt;&gt; \/etc\/dhcpcd.conf<\/p>\n<p>#starte Services<br \/>\necho &#8222;Debug: Starte hostapd&#8220;<br \/>\nsystemctl start hostapd.service<br \/>\necho &#8222;Debug: Starte dhcp&#8220;<br \/>\nsystemctl start dnsmasq.service<br \/>\necho &#8222;\u00dcberpr\u00fcfe ob hostapd gestartet ist&#8220;<br \/>\n#warte bis Services gestartet sind<br \/>\nsleep 5<br \/>\n#\u00fcberpr\u00fcfe ob hostapd gestartet wurde<br \/>\napstatus=$(service hostapd status | grep &#8218;Active:&#8216;)<br \/>\nif [[ $apstatus == *&#8220;running&#8220;* ]]<br \/>\nthen<br \/>\necho &#8222;&#8212;&gt; AP erfolgreich gestartet&#8220;<br \/>\nelse<br \/>\necho &#8222;&#8212;&gt; ERROR: AP nicht gestartet&#8220;<br \/>\nfi<\/p><\/blockquote>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>In unserem Projekt wird ein Raspberry zur Steuerung einer T\u00fcr verwendet. Das Konfigurieren der Netzwerkverbindung ist meine Aufgabe im Projekt. Der Raspberry soll\u00a0vom Kunden \u00fcber eine App bzw. \u00fcber einen Browser konfiguriert werden. Es stehen keine anderen Konfigurationsm\u00f6glichkeiten (wie z.<\/p>\n","protected":false},"author":3,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":[],"categories":[5],"tags":[],"_links":{"self":[{"href":"https:\/\/www.iot-embedded.de\/iot-2017\/wp-json\/wp\/v2\/posts\/235"}],"collection":[{"href":"https:\/\/www.iot-embedded.de\/iot-2017\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.iot-embedded.de\/iot-2017\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.iot-embedded.de\/iot-2017\/wp-json\/wp\/v2\/users\/3"}],"replies":[{"embeddable":true,"href":"https:\/\/www.iot-embedded.de\/iot-2017\/wp-json\/wp\/v2\/comments?post=235"}],"version-history":[{"count":1,"href":"https:\/\/www.iot-embedded.de\/iot-2017\/wp-json\/wp\/v2\/posts\/235\/revisions"}],"predecessor-version":[{"id":580,"href":"https:\/\/www.iot-embedded.de\/iot-2017\/wp-json\/wp\/v2\/posts\/235\/revisions\/580"}],"wp:attachment":[{"href":"https:\/\/www.iot-embedded.de\/iot-2017\/wp-json\/wp\/v2\/media?parent=235"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.iot-embedded.de\/iot-2017\/wp-json\/wp\/v2\/categories?post=235"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.iot-embedded.de\/iot-2017\/wp-json\/wp\/v2\/tags?post=235"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}