{"id":251,"date":"2018-05-22T19:40:55","date_gmt":"2018-05-22T19:40:55","guid":{"rendered":"https:\/\/www.wpvs.de\/iot-2018\/?p=251"},"modified":"2021-05-14T10:07:06","modified_gmt":"2021-05-14T08:07:06","slug":"raspberrybuy-2-ci-setup-und-aktueller-stand","status":"publish","type":"post","link":"https:\/\/www.iot-embedded.de\/iot-2018\/projekt-raspberrybuy\/raspberrybuy-2-ci-setup-und-aktueller-stand\/","title":{"rendered":"RaspberryBuy (2): CI-Setup und aktueller Stand"},"content":{"rendered":"<h1>Aufbau der Entwicklungslandschaft<\/h1>\n<p>F\u00fcr ein agiles Entwicklungsumfeld ist Continous Integration (CI) von zentraler Bedeutung. Jeder neue Code wird zeitnah an ein zentrales Code-Repository gesendet und in die bestehende Code-Basis integriert. Dabei muss neben den neuen Funktionalit\u00e4ten auch getestet werden, ob die bereits bestehenden Funktionalit\u00e4ten durch den neuen Code nicht gest\u00f6rt wurden. Da der Aufwand f\u00fcr ein manuelles Testen nach jeder Code\u00e4nderung zu hoch ist, sollten automatisiert Tests durchgef\u00fchrt werden. Ein solches CI-Setup wurde f\u00fcr das Projekt aufgesetzt. Es besteht aus den folgenden Komponenten:<\/p>\n<ul>\n<li>Github: F\u00fcr das Projekt wurden drei Repositories angelegt (Server, Pi Client, Web Client). Die master-Branch ist dabei gesch\u00fctzt, das hei\u00dft auf sie darf nicht direkt gepusht werden. Stattdessen muss f\u00fcr jedes neue Feature eine Feature-Branch erstellt werden. Sobald die Entwicklung abgeschlossen ist, muss ein Pull Request (PR) erstellt werden, um die neuen \u00c4nderungen in die master-Branch mergen zu k\u00f6nnen. Davor muss jedoch eine weitere Person die \u00c4nderungen akzeptiert haben (4-Augen Prinzip) und die automatisierten Tests m\u00fcssen erfolgreich sein.<\/li>\n<li>Style Checker: Um trotz unterschiedlicher Entwickler einen einheitlichen Code Style zu haben, werden die Style Checker eslint (f\u00fcr JS) bzw. tslint (f\u00fcr TS) verwendet. Diese Checks sind in die Tests integriert, sodass bei falschem Style nicht gemergt werden kann.<\/li>\n<li><a href=\"https:\/\/www.npmjs.com\/package\/mocha\">Mocha<\/a> und <a href=\"https:\/\/www.npmjs.com\/package\/chai\">Chai<\/a>: Diese beiden NPM Module werden f\u00fcr die automatisierten Unit Tests des Servers verwendet. In der Abbildung unten ist ein Ergebnis-Report eines Test-Durchlaufs zu sehen. Eventuell wird in einem sp\u00e4teren Blogbeitrag n\u00e4her darauf eingegangen.<\/li>\n<li><a href=\"https:\/\/travis-ci.com\/\">Travis CI<\/a>: Dieses CI-Tool wird f\u00fcr die Ausf\u00fchrung der automatisierten Tests verwendet. Es meldet die Ergebnisse direkt an Github zur\u00fcck.<\/li>\n<\/ul>\n<p>Die Konfiguration des Travis CI Jobs sieht wie folgt aus:<\/p>\n<blockquote>\n<pre>env:\n global:\n   - APP_MODE=test\n\nsudo: required\n\ncache:\n  directories:\n    - \"node_modules\"\n\nlanguage: node_js\nnode_js:\n  - \"lts\/*\"\n\nservices:\n  - mongodb                     \/\/ MongoDB starten\n\naddons:\n  apt:\n    sources:\n    - ubuntu-toolchain-r-test\n    packages:\n    - g++-5\n  hosts:\n    - raspberrybuy.dynv6.net   \/\/ wird zu 127.0.0.1 resolvt\n\nbefore_install:\n  - npm install -g node-gyp\n\nbefore_script:\n  - npm install\n\nscript:\n  - node .\/dist\/index.js &amp;    \/\/ Server starten\n  - npm test                  \/\/ Tests starten<\/pre>\n<\/blockquote>\n<p>Ergebnis-Report des mocha Frameworks:<\/p>\n<p><img decoding=\"async\" loading=\"lazy\" class=\"alignnone size-full wp-image-253\" src=\"http:\/\/www.iot-embedded.de\/iot-2018\/wp-content\/uploads\/sites\/3\/2018\/05\/mocha_report.png\" alt=\"\" width=\"261\" height=\"252\" \/><\/p>\n<h1>Aktueller Stand<\/h1>\n<p><em>Woran haben wir diese Woche noch gearbeitet?\u00a0<\/em><\/p>\n<p>Diese Woche gab es unterschiedliche Schwerpunkte, welche bearbeitet wurden.<\/p>\n<p>Zum einen wurde der Server\u00a0weiterentwickelt. Zur Persistierung der Daten wird eine MongoDB verwendet. Wie beispielsweise durch die Verbreitung des MEAN-Stacks deutlich wird, wird im Zusammenhang mit NodeJS oftmals eine MongoDB verwendet. Der Dokumenten-basierte Ansatz ist f\u00fcr manche Datenmodellierungen sinnvoller. So kann beispielsweise denormalisiert werden.<\/p>\n<p>Ein weiterer Schwerpunkt lag auf dem Session Handling. Mithilfe der express Middleware\u00a0<a href=\"https:\/\/www.npmjs.com\/package\/express-session\">express-session<\/a>\u00a0wurde dies f\u00fcr den NodeJS-basierten Server implementiert. Diese ist f\u00fcr das Erstellen und Versenden von Cookies und deren Zuordnung zu einer Session zust\u00e4ndig. Die entsprechenden Session-Daten werden wie alle anderen Daten in der MongoDB gespeichert. Die Passw\u00f6rter eines Users werden nicht im Klartext abgespeichert. Stattdessen werden sie mithilfe der <a href=\"https:\/\/www.npmjs.com\/package\/bcrypt\">BCrypt-Bibliothek<\/a> gehasht. Bei einem Login-Request wird der Hash-Wert mit dem eingegebenen Passwort verglichen. Im Erfolgsfall wird eine neue Session, die die User-ID beinhaltet, angelegt. Bei allen weiteren Requests, die ein g\u00fcltiges Session-Cookie mitsenden, wird die hinterlegte User-ID automatisch aus der DB geladen.<\/p>\n<p>Die Oberfl\u00e4che f\u00fcr den Raspberry konnte ebenfalls in Teilen erstellt werden. Wie auf der unten dargestellten Abbildung ersichtlich, wurde die grundlegende Men\u00fcf\u00fchrung zur Auswahl eines Profils mithilfe von JavaScript erstellt. Hierf\u00fcr wurde eine JSON-Datei erstellt, welche einige Testnutzer beinhaltet. Im Produktiv-Modus werden die Daten vom Server gesendet. Der Aufbau wird sich jedoch noch weiter wandeln. Jeder Nutzer enth\u00e4lt eine ID, einen Namen und ein Profilbild zur Darstellung der Icons. Hierf\u00fcr wurden die dargestellten Test-Icons mittels Paint.Net erstellt. Weitere Inhalte werden noch folgen.<\/p>\n<p><img decoding=\"async\" loading=\"lazy\" class=\"alignnone size-medium wp-image-255\" src=\"http:\/\/www.iot-embedded.de\/iot-2018\/wp-content\/uploads\/sites\/3\/2018\/05\/Umsetzung-Mockups-300x174.png\" alt=\"\" width=\"300\" height=\"174\" srcset=\"https:\/\/www.iot-embedded.de\/iot-2018\/wp-content\/uploads\/sites\/3\/2018\/05\/Umsetzung-Mockups-300x174.png 300w, https:\/\/www.iot-embedded.de\/iot-2018\/wp-content\/uploads\/sites\/3\/2018\/05\/Umsetzung-Mockups-1024x595.png 1024w, https:\/\/www.iot-embedded.de\/iot-2018\/wp-content\/uploads\/sites\/3\/2018\/05\/Umsetzung-Mockups-768x446.png 768w, https:\/\/www.iot-embedded.de\/iot-2018\/wp-content\/uploads\/sites\/3\/2018\/05\/Umsetzung-Mockups.png 1278w\" sizes=\"(max-width: 300px) 100vw, 300px\" \/><\/p>\n<p>&nbsp;<\/p>\n<p><em>Welche Probleme mussten wir l\u00f6sen oder haben derzeit noch?\u00a0<\/em><\/p>\n<ol>\n<li>F\u00fcr die verschiedenen Profile eines User (entsprechen den Mitbewohnern einer WG) soll es die M\u00f6glichkeit geben, ein Profilbild hochzuladen. Dazu musste gekl\u00e4rt werden, in welcher Form das Bild versendet und persistiert wird. Aufgrund der geringen Gr\u00f6\u00dfe und der einfacheren Rechteverwaltung haben wir uns dazu entschieden, das Bild als Base64 kodierten Bin\u00e4r-String in der MongoDB abzulegen. <a href=\"https:\/\/docs.mongodb.com\/manual\/core\/gridfs\/\">GridFS<\/a>, das Framework zum Speichern von gro\u00dfen Dateien in der MongoDB, wird dabei nicht ben\u00f6tigt, da die Bilder eine geringe Gr\u00f6\u00dfe haben. Der Browser erh\u00e4lt das Bild als Teil eines JSON-Dokumentes und muss es f\u00fcr die Darstellung dekodieren.<\/li>\n<li>Bei der Erstellung des Firmware Images f\u00fcr den Pi sind noch Probleme zu l\u00f6sen. Zum einen funktioniert die grafische Ausgabe noch nicht, weshalb der aktivierte (und in der inittab gestartete) Browser qt-webkit-kiosk nicht ge\u00f6ffnet werden kann (siehe auch <a href=\"https:\/\/www.wpvs.de\/iot-2018\/forum\/topic\/qt-webkit-kiosk-browser-could-not-find-drm-device\/\">Forum<\/a>). Au\u00dferdem wurde versucht, die Anbindung der Kamera zu erm\u00f6glichen. Dazu soll das Standardprogramm von Raspian, raspistill, verwendet werden, welches auf <a href=\"https:\/\/github.com\/raspberrypi\/firmware\/tree\/master\/opt\/vc\/bin\">Github<\/a> verf\u00fcgbar ist. Die Datei ist allerdings f\u00fcr 32-bit Systeme kompiliert, w\u00e4hrend Buildroot ein 64-bit System erstellt. Somit ist das Programm in der vorliegenden Form nicht nutzbar. Es muss eine L\u00f6sung gefunden werden, wie die Kamera angesprochen werden kann. (<span class=\"atwho-inserted\">@dennis<\/span>\u00a0haben Sie eine Idee f\u00fcr uns?)<\/li>\n<li>Die Umsetzung einer dynamischen Oberfl\u00e4che gestaltet sich zum jetzigem Zeitpunkt schwieriger als zun\u00e4chst angenommen. Dies betrifft beispielsweise die Anordnung und Aufteilung der einzelnen DIV-Elemente. Eine optimale Umsetzung erfolgt in naher Zukunft.<\/li>\n<\/ol>\n<p>&nbsp;<\/p>\n<p><em>Wie weit ist unser Projekt insgesamt? Was fehlt noch?\u00a0<\/em><\/p>\n<p>F\u00fcr die n\u00e4chsten Schritte ist es erforderlich, die Anbindung zum Server und den damit verbundenen Austausch der Daten zu den Web-Clients zu modellieren. Dies soll auf den REST-Prinzipien basieren. Wie im <a href=\"https:\/\/www.wpvs.de\/iot-2018\/projekt-raspberrybuy\/raspberrybuy-1-idee-und-architektur\/\">letztem Blogeintrag<\/a> dargestellt, muss zudem noch das Problem mit der Kamera vollends beseitigt werden.\u00a0Auch ist\u00a0es\u00a0in den kommenden Wochen\u00a0erforderlich die einzelnen Masken zur Bedienung der Anwendung weiter zu entwickeln.<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Aufbau der Entwicklungslandschaft F\u00fcr ein agiles Entwicklungsumfeld ist Continous Integration (CI) von zentraler Bedeutung. Jeder neue Code wird zeitnah an ein zentrales Code-Repository gesendet und in die bestehende Code-Basis integriert. Dabei muss neben den neuen Funktionalit\u00e4ten auch getestet werden, ob<\/p>\n","protected":false},"author":3,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":[],"categories":[4],"tags":[],"_links":{"self":[{"href":"https:\/\/www.iot-embedded.de\/iot-2018\/wp-json\/wp\/v2\/posts\/251"}],"collection":[{"href":"https:\/\/www.iot-embedded.de\/iot-2018\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.iot-embedded.de\/iot-2018\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.iot-embedded.de\/iot-2018\/wp-json\/wp\/v2\/users\/3"}],"replies":[{"embeddable":true,"href":"https:\/\/www.iot-embedded.de\/iot-2018\/wp-json\/wp\/v2\/comments?post=251"}],"version-history":[{"count":1,"href":"https:\/\/www.iot-embedded.de\/iot-2018\/wp-json\/wp\/v2\/posts\/251\/revisions"}],"predecessor-version":[{"id":650,"href":"https:\/\/www.iot-embedded.de\/iot-2018\/wp-json\/wp\/v2\/posts\/251\/revisions\/650"}],"wp:attachment":[{"href":"https:\/\/www.iot-embedded.de\/iot-2018\/wp-json\/wp\/v2\/media?parent=251"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.iot-embedded.de\/iot-2018\/wp-json\/wp\/v2\/categories?post=251"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.iot-embedded.de\/iot-2018\/wp-json\/wp\/v2\/tags?post=251"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}