In diesem Beitrag möchte ich dir zeigen, wie du deinen Raspberry Pi Pico W mit einem OLED Display in ein Creator Display verwandeln kannst und dort deine Social-Media Attribute anzeigen lässt.
Natürlich kannst du dieses Beispiel auch recht einfach adaptieren und dort andere Daten von APIs anderer Dienste anzeigen, wie zbsp. vom Deutschen Wetterdienst, Umrechnungskurse, Aktienkurse etc.
Da wir das spätere Programm in MicroPython schreiben, können wir auch einen anderen Mikrocontroller als den Raspberry Pi Pico W verwenden. Jedoch ist dieser derzeit meine erste Wahl und wird für dieses kleine Projekt eingesetzt.
Was soll das Creator Display anzeigen?
Ziel soll es sein, auf einem Display die Aufrufe und Abos anzeigen zu lassen.
Da mein YoutTube Kanal Draeger-IT noch recht klein ist, habe ich noch nicht so viele Abos und auch nicht die Masse an Aufrufe, aber trotzdem möchte ich die YouTube API ansprechen, um die Daten zu empfangen und auszuwerten.
Hier eine kleine Auflistung der APIs zu welchen man recht einfach Zugriff bekommt:
In diesem Beitrag möchte ich mich zunächst auf die YouTube API beschränken. Die anderen Social-Media-Plattformen werden ggf. in separaten Beiträgen behandelt.
Benötigte Ressourcen für dieses Projekt
Damit du Zugriff auf die YouTube API bekommst, benötigst du einen Google Account und einen API Key. Den API Key kannst du dir nur mit einem Google Developer Account anlegen und unter https://console.cloud.google.com/apis/ anlegen.
Um einen API Key zu generieren, klicken wir zunächst im Navigationsmenü auf der linken Seite auf “Anmeldedaten” (1) und können dann auf “+ CREATE CREDENTIALS” (2) klicken.
Im neu geöffneten Untermenü kannst du den ersten Eintrag “API-Schlüssel” (3) wählen und ein allgemeingültiger API-Schlüssel wird erzeugt.
Nach einer kurzen Wartezeit wird dir der API Key in einem Dialog angezeigt, welchen du dir in die Zwischenablage kopieren kannst.
Achtung: Mit dem API Key kannst du auf einfache Weise auf deinen Account zugreifen und Daten hinzufügen und auch ändern. Den hier dargestellten API Key habe ich gegen Missbrauch unkenntlich gemacht und auch nach der Erstellung von diesem Beitrag wieder gelöscht.
Aufruf der YouTube API per HTTP Request
Am Einfachsten kannst du über einen simplen HTTP Request auf die YouTube API zugreifen, du benötigst also keine zusätzlichen Module, welche du importieren musst.
Du kannst mit deinem zuvor generierten API Key somit recht einfach eine URL zusammensetzen und wie hier die aktuelle Kanalstatistik als JSON abrufen.
https://www.googleapis.com/youtube/v3/channels?id=UCUoqALbWy__4Blgfztg4sKg&key=AIzaSyD*********F3AJHs&part=statistics
{ "kind": "youtube#channelListResponse", "etag": "MozCK4S3NxXniTguDkimSgach7g", "pageInfo": { "totalResults": 1, "resultsPerPage": 5 }, "items": [ { "kind": "youtube#channel", "etag": "0CqNqtSh7-lTmkTeLoIK66YKh30", "id": "UCUoqALbWy__4Blgfztg4sKg", "statistics": { "viewCount": "121900", "subscriberCount": "333", "hiddenSubscriberCount": false, "videoCount": "300" } } ] }
Im letzten Beitrag Raspberry Pi Pico W – Zeit aus dem Internet lesen und auf einem Display anzeigen habe ich dir bereits gezeigt, wie du eine Zeit von einem Server als JSON Response anfordern und auswerten kannst. Jedoch müssen wir auf die API per SSL zugreifen und daher müssen wir etwas umschreiben.
Aufbau einer SSL Verbindung mit dem Modul ussl
Das nachfolgende Beispiel habe ich von der Seite Python ussl.wrap_socket() Examples entnommen und dieses hat auf Anhieb quasi ohne Änderungen funktioniert.
Der Vorteil ist an der erweiterten Funktion, dass diese mit HTTP & HTTPS arbeiten kann. Damit wir die SSL Verbindung aufbauen können, müssen wir zunächst das Modul ussl in die Thonny IDE einbinden.
Über das Hauptmenü “Extras” > “Verwalte Pakete…” erreichst du den Dialog zum Installieren neuer Module.
In diesem Dialog suchst du zunächst nach “ussl” (1), mit der Schaltfläche “Suche auf PyPi” (2) aus den Suchergebnissen wählst du den Eintrag “pycopy-cpython-ussl” (3) aus. Nach dem Selektieren des Eintrages aus den Suchergebnissen kannst du dann die Schaltfläche “Installieren” (4) betätigen und das Modul wird hinzugefügt.
Im Ordner “lib” des Mikrocontrollers findest du nun die Datei “ussl.py”.
Hier die angesprochene Funktion zum Absenden eines HTTP / HTTPS Request und liefern des Response.
import ussl # Funktion zum absenden eines HTTP / HTTPS Request und # Rückgabe des Response # Quelle: https://www.programcreek.com/python/example/96165/ussl.wrap_socket def http_get(url): print("Fetching:", url) proto, _, host, path = url.split('/', 3) if proto == "http:": port = 80 elif proto == "https:": port = 443 addr = socket.getaddrinfo(host, port)[0][-1] s = socket.socket() s.connect(addr) if proto == "https:": s = ussl.wrap_socket(s, server_hostname=host) s.write(bytes('GET /%s HTTP/1.0\r\nHost: %s\r\n\r\n' % (path, host), 'utf8')) result = '' while True: data = s.read(100) if data: result = result + str(data, 'utf8') else: break s.close() return result
Die Rückgabe ist nicht nur ein einfacher HTTP/HTTPS Response, sondern auch die gesamten Header Daten.
Waiting to connect:
('192.168.178.70', '255.255.255.0', '192.168.178.1', '192.168.178.1')
Fetching: https://www.googleapis.com/youtube/v3/channels?id=UCUoqALbWy__4Blgfztg4sKg&key=AI******3AJHs&part=statistics
HTTP/1.0 200 OK
Content-Type: application/json; charset=UTF-8
Vary: X-Origin
Vary: Referer
Date: Sun, 31 Jul 2022 09:25:38 GMT
Server: scaffolding on HTTPServer2
Cache-Control: private
X-XSS-Protection: 0
X-Frame-Options: SAMEORIGIN
X-Content-Type-Options: nosniff
Accept-Ranges: none
Vary: Origin,Accept-Encoding
Alt-Svc: h3=":443"; ma=2592000,h3-29=":443"; ma=2592000,h3-Q050=":443"; ma=2592000,h3-Q046=":443"; ma=2592000,h3-Q043=":443"; ma=2592000,quic=":443"; ma=2592000; v="46,43"
{
"kind": "youtube#channelListResponse",
"etag": "nJfSIGqHLEeyYpfTt3arnG3kax0",
"pageInfo": {
"totalResults": 1,
"resultsPerPage": 5
},
"items": [
{
"kind": "youtube#channel",
"etag": "fkog7EYCmW7T2e-HdOuTSsKST_Q",
"id": "UCUoqALbWy__4Blgfztg4sKg",
"statistics": {
"viewCount": "122093",
"subscriberCount": "342",
"hiddenSubscriberCount": false,
"videoCount": "301"
}
}
]
}
Funktion zum Extrahieren des JSON Response
Wie du erkennen kannst, liefert die Funktion noch zusätzliche Daten, welche wir in diesem Fall nicht benötigen. Mit einfachen nachfolgenden Funktion können wir den JSON Response extrahieren.
# Ermitteln des JSONs aus dem HTTP Response def findJson(response): return response[response.find('{')-2:]
Als Parameter übergeben wir das Result der Funktion “http_get(url)” und erhalten unser JSON.
{
"kind": "youtube#channelListResponse",
"etag": "nJfSIGqHLEeyYpfTt3arnG3kax0",
"pageInfo": {
"totalResults": 1,
"resultsPerPage": 5
},
"items": [
{
"kind": "youtube#channel",
"etag": "fkog7EYCmW7T2e-HdOuTSsKST_Q",
"id": "UCUoqALbWy__4Blgfztg4sKg",
"statistics": {
"viewCount": "122093",
"subscriberCount": "342",
"hiddenSubscriberCount": false,
"videoCount": "301"
}
}
]
}
Auswerten des JSON Response
Wenn du die Adresse im Browser ausgeführt / abgesendet wird, erhält man wie erwähnt eine Antwort mit einem JSON aus welchem man die nachfolgenden Werte entnehmen kann:
- viewCount – Anzahl der gesamten Klicks auf Videos
- subscriberCount – Anzahl der Abos
- videoCount – Anzahl der Videos
Zunächst wandeln wir das JSON Objekt in ein Dictionary um, denn so können wir ganz einfach auf die Werte zugreifen.
import json aDict = json.loads(jsonData)
{'pageInfo': {'resultsPerPage': 5, 'totalResults': 1}, 'kind': 'youtube#channelListResponse', 'etag': 'nJfSIGqHLEeyYpfTt3arnG3kax0', 'items': [{'id': 'UCUoqALbWy__4Blgfztg4sKg', 'kind': 'youtube#channel', 'etag': 'fkog7EYCmW7T2e-HdOuTSsKST_Q', 'statistics': {'subscriberCount': '342', 'videoCount': '301', 'hiddenSubscriberCount': False, 'viewCount': '122093'}}]}
Dun kann man mit dem Key “statistics” auf die oben aufgeführten Werte zugreifen.
aDict = json.loads(jsonData) statistics = aDict['items'][0]['statistics'] subscriberCount = statistics['subscriberCount'] videoCount = statistics['videoCount'] viewCount = statistics['viewCount'] print('subscriberCount', subscriberCount, sep=" ") print('videoCount', videoCount, sep=" ") print('viewCount', viewCount, sep=" ")
subscriberCount 342
videoCount 301
viewCount 122093
Programmieren des Raspberry Pico W Creator Display
Nachdem wir die Daten ermittelt haben, wollen wir diese jetzt auf einem OLED Display anzeigen lassen.
Für den Arduino, ESPx sowie natürlich für den Raspberry Pi / Pico / Pico W bekommst du diverse OLED Displays in verschiedene Auflösungen und auch Farben.
Im nachfolgenden Beispiel verwende ich das 0,96″ OLED Display mit einer Auflösung von 128 x 64 Pixel.
Anschließen eines OLED Displays per I²C an den Pi Pico / Pico W
Zunächst schließen wir unser OLED Display per I²C an den Pi Pico W an. Hier verwende ich die folgende Pinbelegung:
- GND – Pin 38, GND
- VCC – Pin 40, VBUS
- SCL – Pin 1, GP1
- SDA – Pin 0, GP0
Installieren des Modules für das OLED Display mit SSD1306 Chip
Auf dem OLED Display ist ein Chip vom Typ SSD1306 verbaut, für die Programmierung benötigen wir das Modul “micropython-ssd1306” welches wir ebenfalls wie zuvor das “ussl” Modul über “Extras” > “Verwalte Pakete…” installieren.
Wir suchen somit nach “ssd1306” (1) mit der Schaltfläche “Suche auf PyPi” (2) oder betätigen einfach die Return taste. In den Suchergebnissen wählen wir den ersten Eintrag “micropyhton-ssd1306” aus und wählen im nächsten Dialog die Schaltfläche “Installieren”, wenn der vorgang
Ausgabe der Zeile “Hello World!” auf dem OLED Display
In der offiziellen Dokumentation zum Modul “micropython-ssd130” unter Using a SSD1306 OLED display findest du weitere Informationen, wie man ein OLED Display in MicroPython programmiert.
Hier nun ein kleines Beispiel, wie man die Textzeile “Hello World!” ausgibt.
from machine import Pin, I2C import ssd1306 import time i2c = I2C(0, sda=Pin(0), scl=Pin(1)) time.sleep(3) display = ssd1306.SSD1306_I2C(128, 64, i2c, addr=0x3c) display.fill(0) display.text('Hello World!', 0, 0, 1) display.show()
Das Display kann maximal 6 Zeilen mit jeweils 16 Zeichen vernünftig anzeigen.
Fertiges Skript “Raspberry Pi Pico W Creator Display”
Hier nun das fertige Skript zum Laden der YouTube Statistik zu einem Kanal mithilfe der API und einem generierten API_KEY.
import network import socket import time import json import ssl import ussl from machine import Pin, I2C import ssd1306 i2c = I2C(0, sda=Pin(0), scl=Pin(1)) time.sleep(3) display = ssd1306.SSD1306_I2C(128, 64, i2c, addr=0x3c) #Zugangsdaten zum WLAN Netzwerk ssid = '*****' password = '******' #Adresse welche uns das JSON mit den Zeitdaten liefert CHANNEL_NAME = 'Draeger-IT' CHANNEL_ID = 'UCUoqALbWy__4Blgfztg4sKg' API_KEY = 'AIz****AJHs' url = "https://www.googleapis.com/youtube/v3/channels?id={}&key={}&part=statistics".format(CHANNEL_ID, API_KEY) # Aufbau einer WiFi Verbindung def wifiConnect(): wlan = network.WLAN(network.STA_IF) wlan.active(True) wlan.connect(ssid, password) print("Waiting to connect:") while not wlan.isconnected() and wlan.status() >= 0: print(".", end="") time.sleep(1) print("") print(wlan.ifconfig()) # Funktion zum absenden eines HTTP / HTTPS Request und # Rückgabe des Response # Quelle: https://www.programcreek.com/python/example/96165/ussl.wrap_socket def http_get(url): print("Fetching:", url) proto, _, host, path = url.split('/', 3) if proto == "http:": port = 80 elif proto == "https:": port = 443 addr = socket.getaddrinfo(host, port)[0][-1] s = socket.socket() s.connect(addr) if proto == "https:": s = ussl.wrap_socket(s, server_hostname=host) s.write(bytes('GET /%s HTTP/1.0\r\nHost: %s\r\n\r\n' % (path, host), 'utf8')) result = '' while True: data = s.read(100) if data: result = result + str(data, 'utf8') else: break s.close() return result # Ermitteln des JSONs aus dem HTTP Response def findJson(response): txt = '{' return response[response.find(txt)-2:] def displayYouTubeStatistics(text, value): display.fill(0) display.text('YouTube channel', 0, 0, 1) display.text(CHANNEL_NAME, 0, 15, 1) display.text(text, 0, 30, 1) display.text(str(value), 0, 45, 1) display.show() # Main Funktion def main(): # Aufbau der Wifi-Verbindung wifiConnect() # Auslesen des HTTP Response response = http_get(url) #print(response) # ermitteln des JSONs jsonData = findJson(response) # umwandeln des JSONs in ein Dictionary aDict = json.loads(jsonData) statistics = aDict['items'][0]['statistics'] subscriberCount = statistics['subscriberCount'] videoCount = statistics['videoCount'] viewCount = statistics['viewCount'] print('subscriberCount', subscriberCount, sep=" " ) print('videoCount', videoCount, sep=" " ) print('viewCount', viewCount, sep=" " ) pause = 2.5 displayYouTubeStatistics('subscriberCount', subscriberCount) time.sleep(pause) displayYouTubeStatistics('videoCount', videoCount) time.sleep(pause) displayYouTubeStatistics('viewCount', viewCount) time.sleep(pause) # Aufrufen der Funktion main() while True: main() # eine Pause von 5 Minuten einlegen # Der Server leht die Verbindung ab wenn der Intervall # des Zugriffs zu klein ist. time.sleep(300)