6.2. Grundlagen

6.2.1. I2C-Kommunikation

I2C (Inter-Integrated Circuit) ist ein weit verbreiteter Kommunikationsstandard, der für den Zweck entwickelt wurde, die digitale Signalübertragung zwischen verschiedenen Mikrocontrollern innerhalb eines elektronischen Geräts zu ermöglichen. Der I2C-Bus ermöglicht die serielle Datenübertragung über nur zwei Drähte: einen für die Daten (SDA) und einen für den Takt (SCL), was ihn zu einer effizienten Lösung für Systeme mit begrenztem Platzangebot macht. Entwickelt von Philips Semiconductors in den 1980er Jahren, wird I2C heute in einer Vielzahl von Anwendungen genutzt, von einfachen Haushaltsgeräten bis hin zu komplexen Rechensystemen. Der Standard unterstützt eine Vielzahl von Geräten und erlaubt die einfache Erweiterung von Kommunikationsnetzwerken, indem neue Geräte ohne umfangreiche Konfigurationen hinzugefügt werden können. I2C ist besonders nützlich für Anwendungen, die eine zuverlässige Datenübertragung in Echtzeit benötigen.

6.2.2. Golang (Go)

Golang (Go) ist eine moderne Programmiersprache, die von Google entwickelt wurde und sich durch ihre einfache Syntax, effiziente Kompilierung und starke Typisierung auszeichnet. Go wurde entwickelt, um die Produktivität von Entwicklern zu steigern und die Erstellung von performanten und zuverlässigen Anwendungen zu erleichtern. Die Sprache verfügt über Features wie automatische Speicherbereinigung, einfache Parallelisierung über sog. Channels und eine umfangreiche Standardbibliothek.

Go wird von einer wachsenden Anzahl von Entwicklern und Organisationen auf der ganzen Welt eingesetzt und hat sich als eine der beliebtesten Programmiersprachen für die Entwicklung von Cloud-basierten Anwendungen und Systemdiensten etabliert.

Mit seiner einfachen Syntax und seiner effizienten Kompilierung ist Go eine ideale Wahl für die Entwicklung von Anwendungen, die eine hohe Leistung und Zuverlässigkeit erfordern.

6.2.3. Go Routines und Channels

Golang (Go) bietet mit Go Routines und Channels eine einfache Möglichkeit, nebenläufige Programme zu schreiben. Go Routines sind leichtgewichtige Threads, die von der Go-Runtime verwaltet werden und es ermöglichen, mehrere Aufgaben gleichzeitig auszuführen. Channels sind eine Art von Datenstruktur, die es ermöglicht, Daten zwischen Go-Routinen zu übertragen und synchronisieren. Channels sind eine effektive Möglichkeit, um Daten zwischen Go-Routinen zu übertragen und die Kommunikation zwischen verschiedenen Teilen eines Programms zu erleichtern. Go Routines und Channels sind ein leistungsstarkes Werkzeug, um nebenläufige Programme zu schreiben, die effizient und zuverlässig sind.

Ein Beispiel für die Verwendung von Go Routines und Channels in Go, um die Berechnung von Primzahlen zu parallelisieren und die Ergebnisse auszugeben:

package main

import (
    "fmt"
)

func isPrime(n int) bool {
    if n <= 1 {
        return false
    }
    for i := 2; i*i <= n; i++ {
        if n%i == 0 {
            return false
        }
    }
    return true
}

func primeWorker(in <-chan int, out chan<- int) {
    for n := range in {
        if isPrime(n) {
            out <- n
        }
    }
}

func main() {
    in := make(chan int)
    out := make(chan int)

    go primeWorker(in, out)

    go func() {
        for i := 2; i < 100; i++ {
            in <- i
        }
        close(in)
    }()

    for prime := range out {
        fmt.Println(prime)
    }
}

CLIs in Go

Golang ist in der Entwickler-Community beliebt für die Entwicklung von Command-Line-Interfaces (CLIs) aufgrund der Vielfalt an Bibliotheken und Tools, die es für die Erstellung von CLIs bietet.

Wir haben uns aufgrund der Einfachheit für die Bibliothek CLI von urfave (https://github.com/urfave/cli) entschieden, um eine CLI für die AALBox zu entwickeln.

Der Code um eine CLI zu erstellen ist sehr einfach und kann in wenigen Zeilen geschrieben werden, wie das folgende Example aus der offiziellen Dokumentation zeigt:

package main

import (
    "fmt"
    "log"
    "os"

    "github.com/urfave/cli/v2"
)

func main() {
    app := &cli.App{
        Name:  "boom",
        Usage: "make an explosive entrance",
        Action: func(*cli.Context) error {
            fmt.Println("boom! I say!")
            return nil
        },
    }

    if err := app.Run(os.Args); err != nil {
        log.Fatal(err)
    }
}

Quellen:

C-Bindings in Go

C-Bindings in Go, oder cgo, ermöglichen es, C-Code innerhalb von Go-Programmen zu integrieren. Diese Technik ist dafür entwickelt worden, die Integration und Interoperabilität zwischen Go und bestehenden C-Bibliotheken zu erleichtern. Durch cgo können Go-Programme direkt Funktionen aufrufen, die in C geschrieben sind, Datenstrukturen teilen und komplizierte Anwendungsfälle handhaben, die in reinem Go schwierig zu implementieren wären. Diese Fähigkeit macht cgo besonders wertvoll für Projekte, die auf Systemnähe angewiesen sind, wie zum Beispiel Hardware-Schnittstellenprogrammierung oder performanzkritische Systemdienste. Ursprünglich entwickelt von Google, ist cgo heute ein unverzichtbares Werkzeug in vielen hochleistungsfähigen Go-Anwendungen, die eine nahtlose Zusammenarbeit mit bestehenden C-Libraries benötigen, ohne die Notwendigkeit umfassender Neuimplementierungen in Go.

Libnfc in Go

Libnfc ist eine Open-Source-Bibliothek, die es ermöglicht, NFC-Geräte über eine Vielzahl von Schnittstellen zu steuern. Die Bibliothek unterstützt eine Vielzahl von NFC-Chips und -Lesegeräten und bietet eine einfache API für die Kommunikation mit diesen Geräten. Libnfc ist in C geschrieben und bietet eine Reihe von Funktionen für die Initialisierung, Konfiguration und Kommunikation mit NFC-Geräten.

Um Libnfc in Go zu verwenden, können wir die C-Bindings von Go verwenden, um die Funktionen der Bibliothek direkt in Go aufzurufen. Es ist bereits ein Wrapper für Libnfc in Go auf GitHub verfügbar, den wir benutzen können. Wir verwenden die LGPL-Lizenzierte Bibliothek https://github.com/clausecker/nfc.

GPIO in Go

GPIO (General Purpose Input/Output) ist eine weit verbreitete Schnittstelle, die es ermöglicht, digitale Signale zwischen einem Mikrocontroller und externen Geräten zu übertragen. GPIO-Pins können als Ein- oder Ausgänge konfiguriert werden und bieten eine einfache Möglichkeit, Sensoren, Aktoren und andere Geräte mit einem Mikrocontroller zu verbinden.

Um GPIO in Go zu verwenden, verwenden wir die Bibliothek https://github.com/warthog618/go-gpiocdev, die MIT-Lizensiert ist.

Datenbank für die Speicherung der Songs

Für die Speicherung der Songs verwenden wir eine PostgreSQL-Datenbank, die wir über den MIT-Lizensierten Driver https://github.com/lib/pq in Go ansprechen. Für eine universellere Umsetzung hätte auf einen OR-Mapper wie GORM zurückgegriffen werden können, jedoch haben wir uns für die Erprobung vorerst für die simplere Variante entschieden.