Samstag, 2. Januar 2021

Müllkalender in die Owncloud importieren

Mein Entsorger bietet eine praktische Funktion an, in der er die Abholungstermine als iCal (.ics) Datei bereitstellt. 
Leider kann die .ics Datei so nicht ohne weiteres in die Owncloud importiert werden. Zur Umwandlung der Datei verwende ich folgendes Linux Kommando:

sed 's/\r//' Downloads/muellkalender.ics | sed '/DTSTART.*/s/$/T060000Z/' | sed '/DTEND.*/s/$/T060000Z/' > owncloud-cal.ics

Die Datei owncloud-cal.ics, kann jetzt einfach importiert werden.

*** UPDATE ***

Seit letztem Jahr wurden die Einträge immer für zwei aufeinanderfolgende Tage angezeigt. Das habe ich gefixt, allerdings braucht man dazu ein kleines Python Skript.

Dazu den folgenden Inhalt die Date bdg4owc,py kopieren und anschließend:

python bdg4owc.py <Pfad zur BDG Datei.ics>  aufrufen. Der konvertierte Kalender befindet sich dann in /tmp/bdg4owncloud.ics.

Python: 

#!/bin/python
import sys

in_cal = open(sys.argv[1], "r")
out_cal = open('/tmp/bdg4owncloud.ics', 'w')

content = in_cal.readlines()
dt_start=""
for line in content:
if line.startswith('DTSTART'):
parts = line.split(':')
if parts[1].find('T') == -1:
out_cal.write(line.strip() + 'T060000Z\n')
dt_start = parts[1].strip()+'T060000Z'
elif line.startswith('DTEND'):
parts = line.split(':')
if len(dt_start) == 0:
out_cal.write(line.strip() + 'T060000Z\n')
else:
out_cal.write(parts[0]+":"+dt_start+'\n')
else:
out_cal.write(line)



Freitag, 24. April 2020

Adafruit Feather 32u4 mit MacOS Catalina

Wenn man versucht das Feather 32u4 von Adafruit mit seiner Arduino IDE (1.8.12) zu verwenden, läuft man auf diesen Fehler auf:

 Bad CPU type in executable

Das liegt daran, das seit MacOS 10.15 nur noch 64Bit executables ausgeführt werden können. Unglücklicherweise liefert das Boardpackage (1.4.13) von Adafruit noch 32 Bit Executables für die Ansteuerung des Boards aus.  Glücklicherweise liefert die IDE alle Tools, die man benötigt in 64 Bit mit.

En möglichst wenig invasiver Eingriff, und as Problem zu fixen sieht so aus:

  1. cd ~/Library/Arduino15/packages/arduino/tools/avr-gcc
    An dieser Stelle liegen die 32 Bit Executables.
  2. mv 4.9.2-atmel3.5.4-arduino2/ 4.9.2-atmel3.5.4-arduino2-orig
    Damit werden die 32Bit Executables verschoben.
  3. ln -s /Applications/Arduino.app/Contents/Java/hardware/tools/avr/ 4.9.2-atmel3.5.4-arduino2
    Mit diesem Kommando stellen wir die Verbindung zum den neuen 64Bit executables her, die mit der IDE geliefert werden.
Damit wurde der Compiler angepasst und man kann den Sketch übersetzen. Als nächstes muss die Kommunikation mit dem Board hergestellt werden. Dies wird mit dem Programm avrdude bewerkstelligt, was in der Auslieferung des Adafruit Packages ebenfalls nur in 32Bit verfügbar ist. Um den avrdude gegen die neue version zu tauschen kann man wie folgt vorgehen:
  1. cd ~/Library/Arduino15/packages/arduino/tools/avrdude/6.3.0-arduino9/bin
    An dieser Stelle liegen der 32 Bit avrdude.
  2. mv avrdude avrdude-orig
    Das 32Bit Executable wird verschoben.
  3. ln -s /Applications/Arduino.app/Contents/Java//hardware/tools/avr/bin/avrdude avrdude
    Mit diesem Kommando stellen wir die Verbindung zum den neuen 64Bit avrdude her.
Jetzt sollte alles wie gewohnt in der Arduino IDE funktionieren. 

Sonntag, 6. Oktober 2019

Neue SAT over IP Sender in Apple TV einrichten

Mit einer M3U Liste kann man eine alternative Senderlisten in die SAT>IP App des Apple TV einspielen. Das Format dieser Liste ist recht schlecht dokumentiert weswegen ich es hier aufschreibe.

Die M3U Liste ist eine Textdatei. Eine einfache Beschreibung findet man hier. In einer SAT>IP Liste wird folgendes Format erwartet:

#EXTINF:0,1. Das Erste HD
rtsp://sat.ip/?src=1&freq=11494&pol=h&ro=0.35&msys=dvbs2&mtype=8psk&plts=on&sr=22000&fec=23&pids=0,17,18,5100,5101,5102,5104

Die erste Zeile ist der Titel des Senders und die Programmnummer in diesem Fall 1.
Die zweite Zeile enthält den URL wo dieses Programm vom Apple TV abgerufen werden kann. Dieser URL enthält eine Reihe von Parametern, die die Programmauswahl im Tuner des SAT>IP Servers steuern.

Die Parameter:

  • src: Unbekannt ist aber in den M3U Dateien die ich  finden konnte immer 1.
  • freq: Die Frequenz des Senders.
  • pol: Die Polarisation hier sind die Werte v = vertikal und h = horizontal möglich.
  • ro: DVB Roll ist in den von mir gefundenen Dateien immer 0.35.
  • msys: Kann die Werte dvbs für SD Programme oder dvbs2 für HD Programme annehmen.
  • mtype: Modulationstyp kann die Werte 8psk oder qpsk annehmen
  • plts: Unbekannt, kann den Wert on oder off annehmen. Bei meinen Playlisten war der Wert bei mtype=8psk immer on und bei mtype=qpsk immer off.
  • sr: Symbolrate
  • fec: Unbekannt
  • pids: Eine Liste von pids (Programm Identitäten). Diese Liste beginnt mit: 0,17,18 dann kommt die PMT PID anschließend die VideoPID, danach die AudioPID und die PID für den Videotext.
Die notwendigen Daten für einen Sender kann man hier nachschlagen.

TLC ist im Moment nicht in der offiziellen Liste enthalten. Ein entsprechender Eintrag würde also so aussehen:


#EXTINF:0,23. TLC
rtsp://sat.ip/?src=1&freq=12460&pol=h&ro=0.35&msys=dvbs&mtype=qpsk&plts=off&sr=27500&fec=34&pids=0,17,18,103,1535,1536,37

Wenn dieser Eintrag einer aktuellen List hinzugefügt wird (die gibt es hier) und diese Date auf einem Webserver abgelegt wird, kann der URL in die SAT>IP Apple TV App eingetragen werden.

Das Programm 23 hat zwar kein Icon, aber TLC kann ausgewählt und angesehen werden.

Donnerstag, 22. September 2016

Mac OS Sierra und SSH

Mit dem Sierra Update von Mac OS unterstützt SSH  keine DSA Schlüssel mehr. Das hat zur Folge, dass die Authentifizierung mit diesen Schlüsseln nicht mehr funktioniert und man nach dem Passwort gefragt wird, oder die Authentifizierung scheitert, wenn der Server keine Passworte akzeptiert.

Auf jeden Fall sollten alle DSA Schlüssel durch RSA Schlüssel ersetzt und die neuen PubKeys dann auf dem Server installiert werden.

Um eine Verbindung mit den nun nicht mehr unterstützen Schlüsseln aufbauen zu können, reicht es in der Kommandozeile den Algorithmus zu erlauben.

ssh -o PubkeyAcceptedKeyTypes=+ssh-dss usern@example.com

So kann eine SSH Sitzung mit den alten Schlüsseln aufgebaut werden. Diese Sitzung kann man verwenden, um die neuen Schlüssel in die authorized_keys einzutragen.

Sonntag, 3. Januar 2016

Owncloud Kalender und Kontakte migrieren

Die Migration von Kalendereinträgen und Kontakten zwischen einem alten und einem neuen Owncloud Server oder zwischen inkompatiblen Versionen in meinem Fall von 7.0 nach 8.2.2 ist einfacher, als es sich nach einer einfachen Googlesuche darstellt. 
In meinem Fall versagte das occ Upgrade Utility und ich konnte den Server nicht upgraden.
Hier eine kurze Beschreibung, wie der Transfer von wenigen Personen einfach und schnell durchgeführt werden kann.
Die folgenden Schritte haben bei mir funktioniert:

  1. Export
    Sowohl an den Kalender CalDAV Link (verborgen hinter dem Kettensymbol), als auch bei dem CardDAV Link der Kontakte kann ?export angehängt werden. Den CardDAV Link findet man im Settingsmenü der Kontakte (Zahnradsymbol unten in der ersten Spalte) ebenfalls hinter dem Kettensymbol.
  2. Jeweils einen der Links in die Adresszeile des Browsers kopieren und ?export ohne Leerzeichen hinter den kopierten Link schreiben und die Seite aufrufen.
  3. Es wird jeweils eine Datei heruntergeladen. In der .ics Datei befinden sich alle Kalendereinträge in der .vcf Datei alle Kontakte.
  4. Für die Kontakte verwendet man die Importfunktion, die sich ebenfalls hinter dem Zahnradsymbol im Settingsmenü der Kontakte befindet. Nach dem Hochladen der .vcf Datei dauert es eine ganze Weile bis der Fortschrittsbalken etwas anzeigt, also Geduld.
  5. Bei den Kalenderdaten ist die Import Funktion nicht so offensichtlich. Die .ics Datei in den Dateibereich des Owncloud Servers hochladen. Der Server zeigt dann für die Datei ein Kalendersymbol. Wählt man jetzt die Datei aus beginnt der Importprozess. Auch dieser erscheint eine Weile regungslos, so dass man Bedenken hat, der Prozess sei abgestürzt, auch hier braucht man Geduld.
Das wars auch schon. Das Verfahren hat bei meinen 10 Benutzern gut funktioniert.

Freitag, 6. März 2015

RS-232 mit Java und Mac OS Yosemite

Auch wenn die serielle Kommunikation über RS-232 aus der Mode ist, gibt es immer noch eine Reihe von Geräten, die sich darüber einfach steuern lassen. Um eine serielle Kommunikation über Java zu ermöglichen wird seit Jahren die RXTX Library verwendet. 
Die Mac OS Binaries die auf der Homepage angeboten werden sind leider i386 Binaries, also etwas aus der Mode. Für alle Besitzer eines 64Bit System bleibt nur der Weg die Bibliothek selbst zu kompilieren und Java zur Verfügung zu stellen.

Da dies mit einigen Hürden verbunden hoffe ich, dass die folgenden Schritten anderen Fans der seriellen Kommunikation mit Java ein paar Minuten sparen.

Die folgenden Schritte sind notwendig:
  1. Xcode installieren.
  2. Aktuelles JDK installieren. Ich verwende JDK 1.8_40.
  3. Einen Shell Export für JAVA_HOME erstellen mit: export JAVA_HOME=/Library/Java/JavaVirtualMachines/jdk1.8.0_40.jdk/Contents/Home
  4. Macports installieren.
  5. Mit dem Kommando sudo /opt/local/bin/port install libtool glibtool installieren.
  6. RXTX Source Package herunterladen und entpacken.
  7. Im Ordner in dem das RXTX ZIP entpackt worden ist  das Kommando ./configure ausführen.
  8. Im Makefile müssen ein paar Anpassungen durchgeführt werden:
    die Zeile:
    LIBTOOLC = $(GLIBTOOL) --mode=compile $(CC) $(INCLUDES) $(CPPFLAGS) $(CFLAGS) $(VERBOSE_IOEXCEPTIONS) -c
    muss durch die Zeile:
    LIBTOOLC = $(GLIBTOOL) --tag=CC --mode=compile $(CC) $(INCLUDES) $(CPPFLAGS) $(CFLAGS) $(VERBOSE_IOEXCEPTIONS) -c
    ersetzt werden.
    Die Zeile:
    JAVAINCLUDEDIR = /Library/Java/JavaVirtualMachines/jdk1.8.0_40.jdk/Contents/Home/../../../Headers
    muss durch die Zeile:
    JAVAINCLUDEDIR = /Library/Java/JavaVirtualMachines/jdk1.8.0_40.jdk/Contents/Home/include
    ersetzt werden.
    Jetzt muss noch die Zeile:
    JAVANATINC = -I$(JAVAINCLUDEDIR)/
    durch:
    JAVANATINC = -I$(JAVAINCLUDEDIR)/darwin
    ersetzt werden.
  9. mit dem Kommando make wird der Buildprozess gestartet an dessen Ende zwei relevante Dateien erzeugt worden sind.
  10. In dem Ordner in dem das make Kommando ausgeführt worden ist befindet sich die Datei RXTXcomm.jar.  Im Unterordner i686-apple-darwin14.1.0 befindet sich die Datei librxtxSerial.jnilib
  11. Beide Dateien müssen in den Ordner /Library/Java/Extensions kopiert werden und das Setup ist komplett.
Ich hoffe das es euch hilft.

Dienstag, 6. Januar 2015

Grails 2.x Debugging in Netbeans

Wenn man eine Grails Applikation in Netbeans 8 erstellt und diese mit dem Debugger bearbeiten möchte stellt man fest, dass das nicht geht.
Der Debugger startet zwar und die Oberfläche stellt sich so dar als ob man die Applikation debuggen könnte, allerdings spricht keiner der gesetzten Breakpoints an.

Wenn man in die BuildConfig.groovy schaut stellt man fest, das in allen Forkkonfigurationen debugging disabled ist.

grails.project.fork = [
    // configure settings for compilation JVM, note ...      

    //  compile: [maxMemory: 256, minMemory: 64, de ...

    // configure settings for the test-app JVM, ...
    test: [maxMemory: 768, minMemory: 64,
debug: false, maxPerm: 256, daemon:true],
    // configure settings for the run-app JVM
    run: [maxMemory: 768, minMemory: 64,
debug: false, maxPerm: 256, forkReserve:false],   
    // configure settings for the run-war JVM
    war: [maxMemory: 768, minMemory: 64,
debug: false, maxPerm: 256, forkReserve:false],
    // configure settings for the Console UI JVM
    console: [maxMemory: 768, minMemory: 64,
debug: false, maxPerm: 256]
]



Die naheliegendste Änderung wäre es, true statt false in die BuildConfig.groovy einzutragen. Leider ist das nicht wirklich gut umgesetzt. Der Debugger startet zwar, verbindet sich aber nicht automatisch mit der geforkten JVM.
Der Debugger kann nachträglich attached (localhost:5005) werden und arbeitet dann korrekt. Dieses Vorgehen benötigt aber immer den Schritt des nachträglichen Verbindens mit der JVM.


Die komfortabelste Methode ist es den Fork zu deaktivieren. Dann erhält Netbeans die Kontrolle und die Gralsapplikation verhält sich wie jede andere Applikation in Netbeans.

Zum Deaktivieren des Forks die Zeile:

run: [maxMemory: 768, minMemory: 64, debug: false, maxPerm: 256, forkReserve:false],   

durch:

run: false,   

ersetzen.

Danach kann einfach über das Kontextmenü eine Debugsession gestartet werden.

Samstag, 28. Juni 2014

pyotherside für Jolla

Für alle die kein C++ können, aber trotzdem mehr wollen als sich mit Javascript realisieren lässt, ist pyotherside eine gute Erweiterung der Möglichkeiten von QtQuick.

pyotherside ist ein QML Objekt, mit dem sich in direkt QML Python Code embedden und ausführen lässt. Da pyotherside vom Jolla Harbour akzeptiert wird können Apps in Python entwickelt und in den Harbour deployed werden.
Wenigstens äußert sich das MER Wiki dahingehend optimistisch.

Die Verwendung von pyotherside ist denkbar einfach. pyotherside gehört zwar nicht zum Standardumfang eines Jolla Telefons, is aber in den offiziellen Repositories enthalten.

Um bei der Installation der eigenen App sicherzustellen, das pyotherside auf dem Jolla mit installiert wird, muss das Paket in die Liste der von der Software benötigten Pakete eingetragen werden.

Durch diesen Eintrag wird sichergestellt, dass während der Installation des RPMs das pyotherside Package automatisch mit installiert wird,

In der Datei <projektname>.yaml im Abschnitt Requires muss der Eintrag:

... 
# Build dependencies without a pkgconfig setup can be listed here
# PkgBR:
#   - package-needed-to-build

# Runtime dependencies which are not automatically detected
Requires:
  - sailfishsilica-qt5 >= 0.10.9

  - pyotherside-qml-plugin-python3-qt5 >= 1.2.0

# All installed files
Files:
  - '%{_bindir}'

...


eingefügt werden.

In der QML Datei reicht das Hinzufügen einer import Anweisung, um Python in QML verfügbar zu machen:

    import io.thp.pyotherside 1.2

Der Python Code selbst wird mit einer nach dem Import verfügbaren Python Componenten in das QML embedded.

Ein einfaches Kochbuch mit den notwendigsten Anweisungen zur Erstellung von Apps mit Python findet man hier.

Sonntag, 29. Dezember 2013

Jolla - SailfishOS einfacher Konfigurationsspeicher für QtQuick/QML Apps

Die meisten Apps müssen Konfigurationsdaten wie Servernamen oder Benutzerpräferenzen speichern. Diese Daten sollten von jeder Stelle der App zugreifbar sein, um sich die Übergabe von langen Parameterlisten sparen zu können. Natürlich muss die Speicherung persistent erfolgen, so dass die Konfiguration nicht nach dem Beenden der Applikation verloren geht.

Mein Ansatz besteht aus einem kleinen Javascript, das in alle QML Dateien importiert werden kann und die Daten in einer Datenbank speichert.

Vor dem ersten Start muss der Platzhalter <your app name> durch den Namen der jeweiligen Applikation ersetzt werden.

Die Funktion intialize() muss beim start der App aufgerufen werden. Danach kann mit getSetting() und setSetting() ein Key/Value Pair in der DB gespeichert werden.

Javascript:

Qt.include("QtQuick.LocalStorage")

function getDatabase() {
     return LocalStorage.openDatabaseSync("<your app name>", "1.0",  

            "StorageDatabase", 100000);
}

function initialize() {
    var db = getDatabase();
    db.transaction(
        function(tx) {
            tx.executeSql('CREATE TABLE IF NOT EXISTS'+

                   ' settings(setting TEXT UNIQUE, value TEXT)');
      });
}


function setSetting(setting, value) {
   var db = getDatabase();
   var res = "";
   db.transaction(function(tx) {
        var rs = tx.executeSql('INSERT OR REPLACE INTO settings'+

                       ' VALUES (?,?);', [setting,value]);
        if (rs.rowsAffected > 0) {
            res = "OK";
        } else {
            res = "NOK";
        }
   });
   return res;
}

function getSetting(setting) {
   var db = getDatabase();
   var res="";
   db.transaction(function(tx) {
     var rs = tx.executeSql('SELECT value FROM settings WHERE'+

                        ' setting=?;', [setting]);
     if (rs.rows.length > 0) {
          res = rs.rows.item(0).value;
     } else {
         res = "";
     }
  });
  return res;
}


Ein dazu passender QML Preferences Dialog könnte dann so aussehen:
import QtQuick 2.0
import Sailfish.Silica 1.0
import QtQuick.LocalStorage 2.0
import "storage.js" as Storage


Dialog {
    id: preferencePage
    DialogHeader { title: "Save" }
    anchors.fill: parent

        TextField {
            y:200
            id:serverName
            width: parent.width
            label: "Server URL"
            placeholderText: "Enter Sever Name"
            focus: true
            horizontalAlignment: left
        }

        TextField {
            id:deviceId
            anchors.top:serverName.bottom
            width: parent.width
            label: "REMSY Device Name"
            placeholderText: "Enter Device Name"
            focus: true
            horizontalAlignment: left
        }


    Component.onCompleted: {
        Storage.initialize();
        serverName.text=Storage.getSetting("serverurl");
        deviceId.text=Storage.getSetting("deviceid");
    }
    onAccepted: {
        Storage.setSetting("serverurl", serverName.text)
        Storage.setSetting("deviceid", deviceId.text)
    }
}

 

Dienstag, 2. Juli 2013

ePass 2003 Token für OpenVPN Tunnel einrichten

Der französische Anbieter gooze bietet die kostengünstigen und Open Source kompatiblen Smartcard Systeme des chinesischen Herstellers Feitian an. Die Smartcards und Tokens sind vergleichsweise preiswert und enthalten nicht die üblichen Abos, NDAs und andere Hürden, die einem bei anderen Anbietern für einen einfachen Einsatz im Weg stehen.

Darüberhinaus ist die Lieferung relativ schnell, wenn die Smartcards nicht irritierenderweise beim Zoll festsitzen oder die Lieferung aus China sich verspätet.

Das Token ePass2003 ist ein USB-Stick mit integrierter Smartcard und  Kartenleser. Die Einrichtung des Tokens für die Verwendung mit opnevpn unter Mint 14 LMDE ist wird im Folgenden beschrieben.

Die aktuellen Debian Distributionen enthalten nicht die aktuellsten OpenSC Treiber. Auch wenn der Sicherheitsimpact abgewägt werden muss habe ich mich entscheiden das Repository von Gooze zu verwenden um passende und geprüfte OpenSC Pakete zu bekommen.

Um dies zu erreichen muss das Repository von Gooze der sources.list hinzugefügt werden. Da Mint 14 im Wesentlichen auf debian Wheezy basiert, wird das Wheezy Repo der sources.list hinzugefügt.

Als erstes müssen diese zwei Zeilen der Datei /etc/apt/sources.list hinzugefügt werden:

deb http://apt.gooze.eu/debian/ wheezy main
deb-src http://apt.gooze.eu/debian/ wheezy main 

Mit:

# wget -q "http://apt.gooze.eu/257FF7B2.asc" -O- | sudo apt-key add -

wird der Schlüssel für die Gooze Packages dem Keyring hinzugefügt.
Im Ordner /etc/apt/preferences.d/ die Datei gooze mit folgendem Inhalt anlegen:

Package: *
Pin: origin o=apt.gooze.eu
Pin-Priority: 1001 


Nach der Ausführung von apt-get update können alle notwendigen Pakete mit der Anweisung:

# apt-get install pcscd pcsc-tools libccid libpcsclite1 openvpn opensc/staging

installiert werden.

Das ePass2003 ist im Auslieferungszustand für die Feitian Windows-Treiber vorbereitet. Das verhindert die korrekte Erkennung unter Linux. Um das Token unter Linux "sichtbar" zu machen muss das Token neu initialisiert werden.

Während der Initialisierung werden die PIN und die PUK (SuperPIN) vereinbart, sowie ein Label, das verschiedene Programme bei der Nachfrage nach der PIN als Text verwenden.


$ pkcs15-init -E
$ pkcs15-init --create-pkcs15 --profile pkcs15+onepin \
    --use-default-transport-key --pin 123456 \
    --puk 7891011 --label "Peter Mustermann"


Ist die Initialisierung erfolgreich sollte die Anweisung:

$ pkcs15-tool --dump

ungefähr die folgende Ausgabe liefern.

PKCS#15 Card [Peter Mustermann]:
    Version        : 0
    Serial number  : 1234567890091101
    Manufacturer ID: EnterSafe
    Last update    : 20120630083313Z
    Flags          : EID compliant

PIN [User PIN]
    Object Flags   : [0x3], private, modifiable
    ID             : 01
    Flags          : [0x32], local, initialized, needs-padding
    Length         : min_len:4, max_len:16, stored_len:16
    Pad char       : 0x00
    Reference      : 1 (0x01)
    Type           : ascii-numeric
    Path           : 3f005015

...


Damit ist das Token betriebsbereit und kann mit Schlüsseln und Zertifikaten bespielt werden.

Wie man sich einen Schlüssel und ein Zertifikat für SSL erstellt ist erschöpfend im Netz beschrieben, weswegen ich diesen Punkt überspringe und davon ausgehe, das sich der Leser im Besitz einer gültigen PKCS#12 (.p12) Datei befindet.

Mit den Anweisungen:

$ openssl pkcs12 -in cert.p12 -clcerts -nokeys -out petercert.pem
$ openssl pkcs12 -in cert.p12 -cacerts -nokeys -out root.pem
$ openssl pkcs12 -in cert.p12 -nocerts -out peterkey.pem


werden die notwendigen Dateien aus der PKCS#12 Datei extrahiert.

Mit:

$ pkcs15-init --store-private-key peterkey.pem --auth-id 01 --pin 123456

wird der Schlüssel auf dem Token gespeichert. Während dieser Prozedur wird dem Schlüssel eine ID zugewiesen die ausgelesen werden muss, um das Zertifikat mit diesem Schlüssel zu assoziieren.

$ pkcs15-tool --list-keys

Listet alle Schlüssel des Tokens mit deren Ids:

Using reader with a card: Feitian ePass2003 00 00
Private RSA Key [Certificate]
    Object Flags   : [0x3], private, modifiable
    Usage          : [0x4], sign
    Access Flags   : [0xD], sensitive, alwaysSensitive, neverExtrac
    ModLength      : 2048
    Key ref        : 0 (0x0)
    Native         : yes
    Path           : 3f0050152900
    Auth ID        : 01
    ID             : 012347050ef750567872b7e7aa80539110b0e921
    GUID           : {0abc494d-2712-32dc-b64d-be218b23ce90}


Die ID muss beim Speichern des Zertifikates angegeben werde:

# pkcs15-init --store-certificate petercert.pem --auth-id 01 \
   --id  012347050ef750567872b7e7aa80539110b0e921 --format pem


Das Token ist jetzt vollständig eingerichtet.

Um das Token für openvpn nutzbar zu machen muss eine Client Konfiguration im Ordner /etc/openvpn angelegt werden. Openvpn erzeugt seine eigenen IDs mit denen es Schlüssel auf dem Token identifiziert. Diese ID wird mit:

# openvpn --show-pkcs11-ids /usr/lib/opensc-pkcs11.so

ausgelesen und sieht ungefähr so aus:

The following objects are available for use.
Each object shown below may be used as parameter to
--pkcs11-id option please remember to use single quote mark.

Certificate
       DN:             /C=DE/ST=Berlin/L=Berlin/O=Foobar GmbH/OU=FooSecurity/CN=Peter Mustermann
       Serial:         09
       Serialized id:  EnterSafe/PKCS\x2315/6257011116091101/Peter\x20Mustermann\x20\x28User\x20PIN\x29/0
012347050ef750567872b7e7aa80539110b0e9211


Der gelb markierte Hinweis ist unbedingt zu beachten, da ansonsten die \ Zeichen falsch interpretiert und das Zeritifkat nicht mehr zugeordnet werden kann.

Eine minimale /etc/openvpn/client.conf könnte dann so aussehen, wobei hierzu unbedingt die Dokumentation der OpenVPN Website konsultiert werden sollte.
Außerdem hängt der Inhalt der Datei von den Einstellungen ab, die auf der Serverseite durchgeführt worden sind. Für einen einfachen minimalen Test reicht das angegebene Beispiel in jedoch aus.

client
dev tun
proto udp
remote vpn.foobar.com
nobind
persist-key
persist-tun
ca /etc/openvpn/certs/foobar-ca.cert
pkcs11-providers /usr/lib/opensc-pkcs11.so
pkcs11-id '
EnterSafe/PKCS\x2315/6257011116091101/Peter\x20Mustermann\x20\x28User\x20PIN\x29/0012347050ef750567872b7e7aa80539110b0e9211'
comp-lzo


Mit der Anweisung:

# openvpn --config /etc/openvpn/vpn.sourcepark.biz --verb 2

beginnt der Aufbau der Tunnelverbindung. Sobald der Server kontaktiert wurde und der SSL Handshake begonnen hat wird die PIN abgefragt. Nach Eingabe der korrekten PIN wird die Tunnelverbindung etabliert und kann verwendet werden.

Das Erstellen der Zertifikate und die korrekte Verwendung verlangen etwas Übung. Sollte das Token nicht wie gewünscht arbeiten, kann man den Tunnel testweise nur mit den Zertifikaten aufbauen, und anschlie0end die geprüften Zertifkate auf das Token übertragen.

Eine OpenVPN Client Konfiguration, die mit der Zertifkats- und Schlüsseldatei arbeitet würde so aussehen:

client
dev tun
proto udp
remote vpn.foobar.com
nobind
persist-key
persist-tun
ca /etc/openvpn/certs/foobar-ca.cert
cert /etc/openvpn/certs/petercert.pem
key /etc/openvpn/private/peterkey.pem
comp-lzo

Kann mit dieser Konfiguration kein Tunnel etabliert werden liegt es an den Zertifikaten. Lässt sich mit der Angegebenen Konfiguration ein Tunnel aufbauen, arbeitet der Treiber oder das Token nicht korrekt.

Samstag, 27. April 2013

Sennheiser MM 450-X unter Mint 14 LMDE einbinden

Mit dem Bluetooth Headset unter Linux Musik hören ist leider immer noch ein wenig schwierig. Die meisten Headsets werden nach dem Pairing in der Ansicht der verfügbaren Audiohardware gelistet, aber das klappt leider nicht immer.
Für alle bei denen das nicht funktioniert hat, hier eine kurze Beschreibung wie ich mein Sennheiser MM 450-X Headset unter Mint 14 LMDE installiert habe.

Das Headset ließ sich nur mit dem Rechner verbinden, wenn man im Bluetoot Pairing Dialog den Typ auf "Alle Typen" stellt. Das Pairing ist problemlos und das Device erschient in der Liste der bekannten Geräte.

Als Wiedergabegerät lässt es sich jedoch noch nicht verwenden. Das Paket bluez-alsa muss installiert werden um Bluetooth Audio Geräte für Alsa verfügbar zu machen.

    apt-get install bluez-alsa

Damit das Headset auch unter einem bestimmten Namen als Gerät verwendet werden muss eine .asound Datei im Homeverzeichnis angelegt werden.

pcm.btheadset {
   type plug
   slave {
       pcm {
           type bluetooth
           device 00:16:94:0B:97:F6
           profile "auto"
       }  
   }  
   hint {
       show on
       description "Sennheiser MX-450"
   }  
}
ctl.btheadset {
  type bluetooth
}
 


Abmelden und wieder anmelden oder besser den Rechner neu starten.

Mit dem Kommando:

    mplayer -ao alsa:device=btheadset <Eine MP3 Datei>

kann geprüft werden, ob das Headset schon funktioniert.

Sollte kein Audio über das Headset wiedergegeben werden und die Ausgabe von mplayer ungefähr so aussehen:

Selected audio codec: [mpg123] afm: mpg123 (MPEG 1.0/2.0/2.5 layers I, II, III)
==========================================================================
bt_audio_service_open: connect() failed: Connection refused (111)
[AO_ALSA] Playback open error: Connection refused
Failed to initialize audio driver 'alsa:device=btheadset'
Could not open/initialize audio device -> no sound.
Audio: no sound
Video: no video


muss in die Datei /etc/bluetooth/audio.conf in der Sektion [General] die Zeile:

    Enable=Socket
 
hinzugefügt werden. Anschließend muss der Bluetooth Dienst mit /etc/init.d/bluetooth restart neu gestartet werden.

Ein erneuter Start des mplayers sollte jetzt die Tonwiedergabe über das Headset lenken.

Der letzte Schritt zu einer vollständigen Integration in den Desktop, ist die installation des pulseaudio bluetooth Moduls und von pavucontrol mit:

    apt-get install pulseaudio-module-bluetooth pavucontrol

Anschließend den pulsaudio Daemon mit  pulseaudio -k neu starten.
Unter Mint 14 LMDE hat das Bluetooth Tray Icon in meiner Installation einen Fehler. Wähle ich aus dem Pop-Up Menü des Try-Icons das Headset aus und wähle verbinden, wird keine Verbindung zum Headset hergestellt.
Wähle ich aus dem Pop-Up Menü den Menüpunkt Bluetooth Einstellungen und verbinde das Headset dort wird die Verbindung korrekt hergestellt.

Das Headset sollte jetzt als Audiohardware in pavucontrol angezeigt werden.


Sollte die Tonqualität an ein Handygespräch erinnern, muss im Konfigurations-Tab von pavucontrol das Profil A2DP ausgewählt werden.




Montag, 31. Dezember 2012

Raspberry Audio ohne Störungen

Der Rapberry PI ist mit 30-40 € sicher eines der günstigsten LINUX basierten Einplatinensysteme die im Augenblick auf dem Markt verfügbar sind.
Die Verwendung als Low-Cost Audiowiedergabestation drängt sich förmlich auf.
Leider haben die aktuellen Versionen einen Bug im Audiosystem, der dazu führt, dass am Ende der Wiedergabe einer MP3 Datei ein häßliches PLOP oder POP Geräusch zu hören ist.
Dieser Artikel beschreibt eine einfach Möglichkeit diese Störungen weitgehend zu unterdrücken.

Die Störung scheint zu entstehen, wenn der Raspberry das Audiodevice bzw. den entsprechenden Treiber öffnet oder schließt. Wird mit mplayer, vlc oder gst123 eine Playliste  wiedergegeben ertönt das Knacken nach und for jedem einzelnen MP3.

Ein Blick in die Suchmaschine ergab, dass das Problem bekannt, eine Behebung aber im Augenblick nicht verfügbar und unter Umständen nur durch einen Hardwareupgrade zu beheben ist.

Hier mein Vorschlag für einen Workaround:

mit  

     apt-get install pulseaudio

den pulseaudio Server installieren.
Nach erfolgreicher Installation in der Datei /etc/default/pulseaudio die Zeile:

    PULSEAUDIO_SYSTEM_START=0

in

    PULSEAUDIO_SYSTEM_START=1

ändern.

Diese Änderung sorgt dafür, dass der pulseaudio Server direkt beim Systemstart ausgeführt wird. Der pulseaudio Server öffnet das Audiodevice und das Störgeräusch wird einmal beim Booten wiedergegeben.

Damit alle Programme, die ALSA verwenden auf den pulseaudio Server umgelenkt werden muss die Datei /etc/asound.conf angepasst werden.
Die original asound.conf sichern. Anschließend die folgenden Zeilen in die Datei /etc/asound.conf eintragen:

    pcm.pulse {
         type pulse
    }
    ctl.pulse {
        type pulse
    }
    pcm.!default {
        type pulse
    }
    ctl.!default {
        type pulse
    }


Der pulseaudio Server schließt nicht verwendete Audiogeräte nach einer gewissen Zeit. Da dies ebenfalls das Störgeräusch erzeugt findet, man gelegentlich den Hinweis die folgende Änderung in der Datei /etc/pulse/system.pa durchzuführen. Änderung von:

    load-module module-suspend-on-idle

in

    #load-module module-suspend-on-idle

Mein Raspberry gibt nach dieser Änderung keinen Ton mehr von sich. Ich rate also davon ab diese Änderung durchzuführen.

Wer die Wiedergabelautstärke seines Raspberry remote steuern möchte kann die folgende Zeile an die Datei /etc/pulse/system.pa anhängen.

    load-module module-native-protocol-tcp auth-ip-acl=127.0.0.1;192.168.1.0/24 listen="0.0.0.0"

Bei dieser Änderung bitte die berechtigten Subnetze anpassen. Also für ein typisches fritzbox Netz wurde statt:  192.168.1.0/24 in 192.168.178.0/24 geändert werden.

Durch diese Änderung wird der pulseaudio Server über die Netzwerkschnittstelle erreichbar. Soll die Lautstärke von einem anderen Rechner aus geändert werden, muss die Umgebungsvariable PULSE_SERVER die IP Adresse des Raspberry enthalten. Nach dem Setzen der Variable kann man GUI Tools wie pavucontrol oder pacmd verwenden, um die Lautstärke zu ändern.
Bei pactl muss der Server direkt über die -s Option angegeben werden.


Beispiele:

    $ pactl -s <raspberry IP> set-sink-volume 0 50000
  $ PULSE_SERVER=<raspberrypi IP> pavucontrol 

Als letzter Schritt müssen alle Benutzer, die Audio wiedergeben möchten den Gruppen pulse und pulse-access zugefügt werden, andernfalls erscheint die folgende Fehlermeldung:

[AO_ALSA] alsa-lib: pulse.c:243:(pulse_connect) PulseAudio: Unable to connect: Access denied

Also für jeden Benutzer der Audio wiedergeben können soll, müssen die beiden Befehle als root oder mit sudo ausgeführt werden:
  
    # addgroup pi pulse
    # addgroup pi pulse-access

Sind alle Änderungen durchgeführt, den Raspberry neu starten. Das Problem mit dem Plop sollte jetzt nur noch beim Starten oder Stoppen auftreten, bzw. wenn der pulseaudio Server das Device öffnet oder schließt. Zwischen den MP3s sollte es zumindest deutlich leiser, wenn nicht ganz verschwunden sein.

EDIT: 
Eine weitere Quelle für verbrummtes oder anderweitig gestörtes Audio kann auch das Netzteil und das verwendete Kabel sein. Sitzt die Masse des Steckers locker im Netzteil kann das zu erheblichen Störungen führen. Auch preiswerte USB-Netzteil oder billige Kabel können zu Störungen bei der Audiowiedergabe führen.
Bei Problemen einfach mal Kabel und/Oder Netzteil tauschen.

Donnerstag, 11. Oktober 2012

Grails WAR mit Maven auf einen entfernten Tomcat deployen

Zum kompilieren einer Grails Applikation wird das Grails Plugin verwendet. Das produzierte Artefakt kann dann durch Verwendung des Cargo Maven Plugins auf einen entfernten Tomcat Server, in meinem Fall einem Tomcat 6, deployed werden.

Tomcat Einstellungen

Ich verwende Tomcat aus dem stable Repository von Debian Squeeze. Um später das Remote-Deployment durchführen zu können muss zusätzlich zum Package tomcat6 das Package tomcat6-admin installiert sein.

Mit root Berechtigung reicht die Ausführung des Kommandos:

    apt-get install tomcat6 tomcat6-admin

um  alles notwendige zu installieren.

Anschließend muss ein Tomcat-Benutzer  eingerichtet werden. Die Datei /var/lib/tomcat6/conf/tomcat-users.xml muss um die folgenden Einträge erweitert werden:

    <role rolename="manager-gui"/>
    <role rolename="manager-script"/>
    <role rolename="manager-jmx"/>
    <role rolename="manager-status"/>
    <user username="me" password="secret

          roles="manager-gui,manager-script,manager-jmx,manager-status"/>
Diese Erweiterung sorgt dafür, dass der Benutzer "me" mit dem Passwort "secret" Zugriff auf die Managementfunktionen des Tomcat bekommt.

Beim Deployment von Grails Applikationen kommt es häufig zu einem "out of PermGenSpace" Fehler. Um diesen zu vermeiden sollte die JAVA_OPTS Zeile in der Datei  /etc/default/tomcat6 um die Option -XX:MaxPermSize=256m erweitert werden. Dadurch wird der PermGenSpace auf 256 MByte vergrößert und reicht in den meisten Fällen aus.

Die JAVA_OPTS Zeile in /etc/default/tomcat6 sollte dann so aussehen:


    ...
    JAVA_OPTS="-Djava.awt.headless=true -Xmx128m -XX:+UseConcMarkSweepGC
             -XX:MaxPermSize=256m"
    ...

Damit sind alle für Tomcat notwendigen Einstellungen vorgenommen und Tomcat muss mit:

    /etc/init.d/tomcat6 restart

neu gestartet werden, damit alle durchgeführten Änderungen wirksam werden.

MAVEN Einstellungen

In der pom.xml der Grails-Applikation wird das Cargo Plugin hinzugefügt. In der Plugin Konfiguration werden alle relevanten Daten wie der Server auf dem Deployed werden soll, sowie die oben festgelegten Zugangsdaten konfiguriert.
Beispiel:

        <plugin>
        <groupId>org.codehaus.cargo</groupId>
        <artifactId>cargo-maven2-plugin</artifactId>
        <version>1.0.6</version>
        <configuration>
            <container>
            <containerId>tomcat6x</containerId>
            <type>remote</type>
            </container>
            <configuration>
            <type>runtime</type>
            <properties>
                <cargo.tomcat.manager.url>

                    http://myserver:8080/manager
                </cargo.tomcat.manager.url>
                <cargo.remote.username>me</cargo.remote.username>
                <cargo.remote.password>secret</cargo.remote.password>
            </properties>
            </configuration>
            <deployer>
            <type>remote</type>
            <deployables>
                <deployable>
                <location>target/${artifactId}-${version}.war</location>
                <groupId>${groupId}</groupId>
                <artifactId>${artifactId}</artifactId>
                <type>war</type>
                <properties>
                    <context>${artifactId}</context>
                </properties>
                </deployable>
            </deployables>
            </deployer>
        </configuration>
        </plugin>


Das <location> Tag sorgt dafür, dass das gerade erstellte Artefakt über das Filesystem und nicht aus dem Build selbst heraus deployed wird.
Da das Grails Plugin den Packaging-Type grails-app benötigt, das Cargo Plugin aber nur Standard Packaging Types wie war, ear usw. verarbeitet, würde es sonst zu folgendem Fehler kommen:

    [INFO] [cargo:redeploy {execution: default-cli}]
    [WARNING] The defined deployable has the same groupId and artifactId 

    as your project's main artifact but the type is different. You've 
    defined a [war] type whereas the project's packaging is 
    [grails-app]. This is possibly an error and as a consequence the 
    plugin will try to find this deployable in the project's 
    dependencies.
    [INFO] ----------------------------------------------------------------------
    [ERROR] BUILD ERROR


Wenn der POM angepasst wurde und alles korrekt konfiguriert worden ist, kann mit dem Kommando:

    mvn -Dmaven.test.skip=true clean install cargo:redeploy

das Artefakt gebaut und deployed werden.

Dienstag, 4. September 2012

Zotac Box mit HDMI Audio

HDMI Audio ist unter Linux und speziell unter Debian immer ein wenig kompliziert in Betrieb zu nehmen.
Ich beschreibe hier kurz wie ich meine Zotac Box, die mit einem NVIDIA Ion Chipset ausgerüstet ist eingerichtet habe. Auf der Box läuft ein Debian Squeeze (6.0.3) und MythTV 0.24.
Das alsa Package und das alsa-utils Package müssen installiert sein.
Mit aplay -l werden alle Audiodevices aufgelistet. Das sieht bei mir so aus:
root@twinpeaks:~# aplay -l
**** Liste der Hardware-Geräte (PLAYBACK) ****
Karte 0: Intel [HDA Intel], Gerät 0: ALC888 Analog [ALC888 Analog]
  Sub-Geräte: 1/1
  Sub-Gerät #0: subdevice #0
Karte 0: Intel [HDA Intel], Gerät 1: ALC888 Digital [ALC888 Digital]
  Sub-Geräte: 1/1
  Sub-Gerät #0: subdevice #0
Karte 1: NVidia [HDA NVidia], Gerät 3: HDMI 0 [HDMI 0]
  Sub-Geräte: 1/1
  Sub-Gerät #0: subdevice #0
Karte 1: NVidia [HDA NVidia], Gerät 7: HDMI 0 [HDMI 0]
  Sub-Geräte: 1/1
  Sub-Gerät #0: subdevice #0
Karte 1: NVidia [HDA NVidia], Gerät 8: HDMI 0 [HDMI 0]
  Sub-Geräte: 1/1
  Sub-Gerät #0: subdevice #0
Karte 1: NVidia [HDA NVidia], Gerät 9: HDMI 0 [HDMI 0]
  Sub-Geräte: 1/1
  Sub-Gerät #0: subdevice #0

Welches der vielen Audiodevices das Richtige ist habe ich durch probieren ermittelt. Hierzu eigenet sich das in den alsa-utils enthaltene speaker-test Programm.
HDMI Kabel an den Fernseher anschließen. Lautstärke des Fernsehers beachten, also nicht zu niedrig einstellen.
Anschließend für jedes der aufgelisteten Geräte das Kommando:
speaker-test -Dplughw:<Karte>,<Gerät>
ausführen. Wobei <Karte> durch die Nummer der Karte und <Gerät> durch die Nummer des Gerätes ersetzt werden müssen. Also das Kommando um das erste Gerät der Liste zu testen wäre dann:
speaker-test -Dplughw:0,0
Bei mir war es plughw:1,7. Hat man das Device identifiziert kann man es als Alsa Default Device vereinbaren, in dem man die Datei /etc/asound.conf wir folgt anlegt:

pcm.!default {
    type plug
    slave.pcm {
        type hw
        card 1
        device 7
    }
}

Ich würde das Alsa System jetzt neu starten. 
Für alle MythTV Anwender: In der Audiokonfiguration wird das Device mit ALSA:plughw:1,7, natürlich entsprechend eurer Karte/Gerät, angegeben.

Einfacher WMA nach MP3 Encoder

Da einige der Internetradiosender ihre Sendungen nur als  WMA-Stream ausstrahlen, mein N770 Webtablet aber nur MP3 wiedergeben lann habe ich, natürlich nur zu Bildungszwecken, das folgende kleine Skript geschrieben.
Es ist ein kleiner Webserver in Python der auf Port 8080 lauscht. Bei einem eingehenden Request, wobei es sich um einen beliebigen GET Request handeln muss, verbindet sich der Webserver mit der im run  Kommando angegebenen mms Adresse und lädt den WMA-Stream in einen Transcoder, der ihn dann in einen MP3 Stream umwandelt. Der aus dem Transcoder gewonnene Datenstrom wird mit dem notwendigen Contentheader versehen und als Antwort auf den GET Request zurücksendet.
Das Skript ist in Python 2.5 geschrieben und benötigt die libmimms bindings für Python.
Source radio.py:
from os import curdir, sep
from BaseHTTPServer import BaseHTTPRequestHandler, HTTPServer
from libmimms.core import run

__author__="barmeier"
__date__ ="$04.01.2010 16:48:20$"


class MmsTranscoder(BaseHTTPRequestHandler):

    def do_GET(self):
        try:
            self.send_response(200)
            self.send_header('Content-type', 'audio/mpeg')
            self.end_headers()
            run("mms://radiotstation/livestream.wma",self.wfile)
        except IOError:
            self.send_error(404,'File Not Found: %s' % self.path)

def main():
    try:
        server = HTTPServer(('', 8080), MmsTranscoder)
        print 'Welcome to the machine...'
        server.serve_forever()
    except KeyboardInterrupt:
        print '^C received, shutting down server'
        server.socket.close()

if __name__ == '__main__':
    main()
Damit die automatische MP3 Kodierung funktioniert habe ich die download Methode in der Datei libmms/core.py gepatched. Das kann man sicher viel eleganter machen, aber ich wollte endlich Radio hören.
download Methode für libmms/core.py:
def download(url, outStream):
    "Using the given options, download the stream to a file."
    stream = libmms.Stream(url, 1e6)
    bitrate= 128000
    dec= enc= mx= None
    #sys.stdout.flush()
    dm = muxer.Demuxer("wma")
    type="mp3"
    stopped = False
    for data in stream:
        #f.write(data)
        frames = dm.parse(data)
        if frames:
            for fr in frames:
                # Assume for now only audio streams
                if dec == None:
                    # Open decoder
                    dec = acodec.Decoder(dm.streams[fr[0]])
                    print 'Decoder params:', dm.streams[fr[0]]
                # Decode audio frame
                r = dec.decode(fr[1])
                try:
                    if r:
                        if bitrate == None:
                            bitrate = r.bitrate
                        # Open muxer and encoder
                        if enc == None:
                            params = {'id': acodec.getCodecID(type),
                                'bitrate': bitrate,
                                'sample_rate': r.sample_rate,
                                'channels': r.channels}
                            print 'Encoder params:', params
                            mx = muxer.Muxer(type)
                            stId = mx.addStream(muxer.CODEC_TYPE_AUDIO, params)
                            enc = acodec.Encoder(params)
                            ss = mx.start()
                            outStream.write(ss)
                            outStream.flush()
                        enc_frames = enc.encode(r.data)
                        if enc_frames:
                            for efr in enc_frames:
                                ss = mx.write(stId, efr)
                                if ss:
                                    outStream.write(ss)
                                    outStream.flush()
                except:
                    print "Client lost. Waiting for next ..."
                    stopped=True
                    break
        if stopped:
            break
    stream.close()

Auf der Kommandozeile startet man das Programm mit:
sbamamoto/home$ python raodio.py
Einfach im Browser http://<rechnername>:8080 aufrufen und dann sollte es funktionieren.