Wie man das 5 Sekunden boot Delay beim Digispark / Digistump attiny85 entfernt

Neben den ESP8266 Microcontrollern hatte ich mir zum Herumspielen auch ein Dreierpack attiny85 Microcontroller von Digispark bestellt. Diese sind sehr klein, stromsparend und können für verschiedenste kleine Aufgaben herangezogen werden. Der entsprechend installierte Bootloader macht die Entwicklung dabei besonders einfach, weil man mit der Arduino IDE arbeiten kann und das Gerät einfach nur anstecken muss und nicht irgendwelche Programmer benötigt oder so.

Diese Einfachheit hat allerdings einen Nachteil: immer, wenn man den attiny85 mit dem Strom verbindet, wartet der Bootloader 5-6 Sekunden lang, ehe das installierte Programm startet. Und hier möchte ich euch nun zeigen, wie ihr den Bootloader so modifizieren könnt, dass er direkt das Programm startet und statt der 5s Wartezeit mittels Jumper in den Programmier-Modus gebracht wird.

Dazu benötigt ihr:

Neuer Bootloader:
https://github.com/micronucleus/micronucleus/blob/v1.11/upgrade/releases/micronucleus-1.11-entry-jumper-pb0-upgrade.hex

Upload Software:
https://github.com/digistump/DigistumpArduino/tree/master/tools

Ladet euch das für euer Betriebsystem passende tar.gz herunter und entpackt es. In den entpackten Ordner könnt ihr der Einfachheit halber direkt die Hex Datei packen.

Der Upload ist dann eigentlich ganz leicht:

chmod +x micronucleus <-- die Binary ist nicht ausführbar, muss man also einmalig erledigen...
./micronucleus micronucleus-1.11-entry-jumper-pb0-upgrade.hex

Ihr werdet nun aufgefordert, den attiny85 anzustecken. Sobald das erledigt ist, wird der neue Bootloader gebrannt. Anschließend müsst ihr ca. 30s warten, dann das Gerät vom USB abziehen und den Pin GND mit Pin P0 verbinden. Nun zurück zur Arduino IDE wechseln, erneut den Upload des Programmes starten und wenn ihr aufgefordert werdet steckt ihr den attiny85 mit der GND-P0 Verbindung an. Nachdem die Firmware geschrieben wurde, zieht ihr das Teil wieder ab und trennt die Verbindung zwischen GND und P0. Wenn er nun wieder mit dem Strom verbunden wird, sollte der attiny85 sofort und ohne Pause das Programm starten.

Beim Ausführungen von Java jnlp Anwendungen erscheint ein Access Denied Fehler

Beim Ausführen einer Java Anwendung mit einer jnlp Datei bekam ich komischerweise immer wieder Fehlermeldungen „java.io.FilePermission“ für die Datei „/usr/bin/xprop“. Die Datei war im System vorhanden und durfte auch von jedem ausgeführt werden, selbst mit Sudo kam der Fehler.

Die Lösung des Problems ist zwar relativ leicht, aber mal wieder sehr ärgerlich: es ist ein Fehler in der OpenJDK und in meinem Fall der icedtea-netx Implementierung. Und um diesen zu umgehen muss man leider die original Oracle JAVA JRE runterladen und installieren.

Wichtig hierbei: man muss wohl zwingend die tar.gz Variante und nicht die RPM Variante nehmen, da nur diese „javasw“ enthält.

Das Vorgehen für die Installation ist:

  • openjdk und co vom System schmeissen (es geht auch anders, aber man muss die Sache ja nicht unnötig verkomplizieren)
  • unter http://www.oracle.com/technetwork/java/javase/downloads/index.html den Download Button unter „JRE“ anklicken und auf der folgenden Seite die AGB akzeptieren und dann die entsprechende tar.gz für 64bit oder 32bit herunterladen
  • tar.gz entpacken und den Ordner nach /usr/java/[ORDNER_NAME] verschieben
  • anschließend (keine Ahnung ob das der richtige Weg ist, aber er funktioniert) unter /usr/bin per Link die java und javasw Binaries verlinken:
cd /usr/bin
ln -s /usr/java/[ORDNER_NAME]/bin/java
ln -s /usr/java/[ORDNER_NAME]/bin/javasw

Nun könnt ihr die jnlp Datei einfach per
javasw [DATEI].jnlp aufrufen.

[Quicktip] Befehl für den Reset / Restart eines ESP 12 / 32 Microcontrollers

Normalerweise kann man einen ESP8266 per Pin „Kurzschluss“ oder einfach über die entsprechende Taste auf dem Board Neustarten. Ich wollte das ganze aber per Code machen, und die Suche nach der Lösung hatte mich etwas verzweifeln lassen. Dabei ist es doch so einfach 🙂

esp_restart();

Python MySQL connector liefert in einer Endlossschleife immer das gleiche Query Ergebnis

Für ein Projekt habe ich einen Runner laufen, der in bestimmten Intervallen eine MySQL Datenbank abfragt, ob es neue Jobs für ihn zu tun gibt. Letztendlich handelt es sich einfach um eine Endlos-While-Schleife, in der immer wieder die Query ausgeführt wird.

Das Problem war aber nun: der Runner hat im aktuellen Lauf scheinbar immer nur das Ergebnis des ERSTEN Durchlaufs der Schleife aus dem Cache gelesen. Dabei handelt es sich wohl nicht um einen Fehler auf Python Seite, sondern in MySQL selbst. Die Lösung ist zwar technisch nicht gerade schön gelöst, aber sie funktioniert: man muss einfach nur die Autocommit-Funktion für die aktuelle Verbindung zum MySQL Server aktivieren. Und das geht so:

cnx = mysql.connector.connect(...)
cnx.autocommit = True

Durch dieses Setting wird dem MySQL Server ein “set autocommit=1;” übertragen, was dann dazu führt, dass der Query Cache komplett umgangen wird.

Wie kann ich einen unendlich lang gültigen Facebook Page Accesstoken erzeugen?

Facebook Access Tokens sind eine ziemlich fiese Sache, wenn man Server only Anwendungen bauen möchte – also keine wirkliche Chance hat, den User einen Token besorgen zu lassen. Zusätzlich haben die “normalen” Access Tokens bei Facebook das Problem, dass sie spätestens nach 60 Tagen ungültig sind. Es gibt aber derzeit noch eine Möglichkeit, an unendlich gültige Access Tokens zu kommen. Mit diesen Tokens könnt ihr beliebig auf euer Seite posten, Statistiken abfragen usw. – und an diesen Token kommt ihr so:

  1. Zunächst müsst ihr Admin der gewünschten Fan Page sein
  2. erstellt eine Facebook App – natürlich mit dem gleichen User, der auch Admin der Seite ist.
  3. kopiert in den Einstellungen der App die App-ID sowie das App Secret
  4. öffnet den Facebook Graph API Explorer
  5. oben rechts ist ein Dropdown, in dem ihr die eben erstellte App auswählt (anfänglich steht da “Graph API Explorer” drin)
  6. nun klickt ihr auf das “Get Token”-Dropdown und wählt da “Get User Access Token” – dabei ist es wichtig, dass ihr in der nun erscheinenden Übersicht das Häkchen bei “manage_pages” setzt
  7. kopiert nun den kurzfristigen Token aus dem Textfeld in der Mitte und ruft folgende URL auf:
    https://graph.facebook.com/oauth/access_token?client_id=[APP_ID]&client_secret=[APP_SECRET]&grant_type=fb_exchange_token&fb_exchange_token=[TOKEN]
  8. kopiert euch den nun angezeigten langfristigen Token (LONG_LIVING_TOKEN, 60 Tage gültig)
  9. ruft nun die folgende URL auf:

    https://graph.facebook.com/me/accounts?access_token=[LONG_LIVING_TOKEN]

  10. in dem nun erscheinenden JSON seht ihr alle von euch verwalteten Seiten sowie deren unendlich lang gültigen Tokens für die verwendete App

Zur Überprüfung ruft ihr einfach das Access Token Debug Tool auf: 

https://developers.facebook.com/tools/debug/accesstoken

Hier könnt ihr den Token eintragen und bekommt dann Informationen darüber – und eben auch die Gültigkeit.

Wie lade ich in Django 1.10 ein Bild von der Festplatte per Django Command hoch?

Für den Fall, dass man ein Bild in eine Django Applikation uploaden möchte, gibt es unzählige Tutorials – kniffelig wird es dann ein bisschen, wenn man ein Bild von der Festplatte des Servers, auf dem die Applikation läuft, mittels Django Command hochladen möchte. In meinem Beispiel importiere ich Bilder per Cronjob aus einem anderen Programm. Bisher ging der Upload auch ohne Probleme, aber seit Django 1.9 oder 1.10 wurde das Sicherheitskonzept geändert – man darf keine Dateien mehr ausserhalb des Media_Path Kontextes hochladen (Suspicious File Operation. Um das Problem zu umgehen, muss man das “normale” Fileobject, welches man normalerweise dann an das Model übergeben würde, in den Django File Wrapper packen. Dazu importiert ihr diesen Wrapper wie im Beispiel unten, übergebt den realen Pfad zum Bild und, und das ist nun wichtig, übergebt per “name” Parameter einen beliebigen Dateinamen, mit dem diese Datei dann im “Upload Prozess” von Django ankommt. Nun müsst ihr das “image” Objekt einfach nur an den Image Parameter eures Models hängen, und schon klappt das Einspielen der Datei wieder. Bei mir war es tatsächlich der fehlende “name” Parameter, der mich in die Verzweiflung getrieben hat 🙂

from django.core.files import File
image = File(open("[PATH_TO_REAL_FILE]", "rb"), name="[SOME_FILE_NAME]")

[Quicktip] Nginx Reverse Proxy mit Basic Auth

Nehmen wir an, ihr richtet einen Nginx als reverse Proxy ein und möchtet nun, dass bestimmte Subdomains, die von anderen Servern durchgeschliffen werden, per Basic Auth “geschützt” werden sollen. Dann werdet ihr wahrscheinlich auf das Problem stoßen, dass ihr immer wieder nach dem Basic Auth Login gefragt werdet und der Reverse Proxy nicht korrekt agiert. Die Lösung ist ganz einfach: ihr müsst verhindern, dass die Basic Auth Header weitergereicht werden. Und das geht so:

server {
    listen 80;
    server_name foo.bar.com;
    access_log            /var/log/nginx/foo.access.log;
    location / {
      proxy_set_header        Authorization "";    # <== das ist die wichtige Zeile, die verhindert, dass Basic Auth weiter gereicht wird!
      auth_basic              "Protected";
      auth_basic_user_file    /etc/nginx/basic_auth;
      proxy_set_header        X-Real-IP $remote_addr;
      proxy_set_header        X-Forwarded-For $proxy_add_x_forwarded_for;
      proxy_set_header        X-Forwarded-Proto $scheme;
      proxy_set_header        Host [YOUR_REMOTE_DOMAIN];
      proxy_set_header        Accept-Encoding "";
      proxy_pass              [YOUR_REMOTE_URL];
      proxy_read_timeout      90;
    }
}

[Quicktip] Wie kann ich alle installierten Python pip Packages upgraden?

Über einen kleinen Umweg kann man auf der Bash ganz einfach alle aktuell installierten pip Pakete updaten / upgraden:

pip freeze | sed -e 's/==.*//g' > upgrade.txt
pip install --upgrade -r upgrade.txt
rm upgrade.txt

Das Script lässt sich alle installierten Pakete ausgeben, entfernt das “==[Versionsnummer]” hinter dem Namen und packt diese Liste in die Datei upgrade.txt. Anschließend wird diese Datei bei einem “pip upgrade” als “requirements.txt” übergeben und mit dem upgrade Befehl ausgeführt.