Industrielle Fertigung
Industrielles Internet der Dinge | Industrielle Materialien | Gerätewartung und Reparatur | Industrielle Programmierung |
home  MfgRobots >> Industrielle Fertigung >  >> Manufacturing Technology >> Herstellungsprozess

Alexa-fähiger USB-Netzschalter

Komponenten und Verbrauchsmaterialien

Arduino MKR1000
× 1
0.1uF 0805 Kondensator
× 8
LED (generisch)
× 4
Taste drücken (lang)
× 4
INA219 (soic 8)
× 1
LM3526M
× 2
USB-Buchse (vertikal)
× 4
1k 0805 Widerstand
× 4
0,1 Ohm Strommesswiderstand
× 1
1uF 0805 Kondensator
× 1

Notwendige Werkzeuge und Maschinen

3D-Drucker (generisch)
Lötkolben (generisch)

Apps und Onlinedienste

Amazon Alexa Alexa Skills Kit
Tinamous
Amazon Web Services AWS Lambda

Über dieses Projekt

Alexa, schalte den ThingyStick ein...

Hintergrund

Immer mehr Geräte werden über USB mit Strom versorgt, viele davon neigen dazu, "dumme" Geräte ohne Internetverbindung oder Hausautomatisierungsoptionen (z. B. LED-Leuchten) zu sein. Wie können wir sie automatisieren oder aus der Ferne steuern? Vielleicht eine USB-Versorgung an einem Netzschalter, das ist etwas übertrieben, besonders wenn wir 4 Geräte einzeln ansteuern wollen!

Mit diesem Projekt können Sie die Stromversorgung von USB-betriebenen Geräten über das Internet steuern und mit dem Tinamous SmartHome Skill für Alexa die Sprachsteuerung für Ihre dummen USB-Geräte aktivieren.

Derzeit gibt es nur sehr wenige Geräte auf dem Markt, um die USB-Stromversorgung aus der Ferne zu steuern. Als ich dieses Projekt startete, fand ich keine (in Großbritannien), aber ein paar sind kürzlich als Teil von Mehrfachsteckdosen erschienen (ja, die Idee) begann vor langer Zeit, in einer weit entfernten Galaxie), diese sind nicht von bekannten Hausautomationsherstellern, sondern von markenlosen Herstellern (zB ZLD-34UK). China und zurück, was passiert, wenn dieser Hersteller nicht mehr existiert, wie sicher ist er, wie verwendbar ist die Software, wird sie nächste Woche in der Recyclingbox sein und viele der anderen normalen Bedenken von Geräten mit Internetanschluss, ganz zu schweigen davon genauso hackbar wie ein Open-Source-Arduino-betriebenes Gerät sein kann.

Anwendungsfälle

Beispiele für USB-betriebene Geräte, die wir möglicherweise steuern möchten:

  • USB-betriebene Lampen
  • Kindle Fire / Chromecast-Sticks (besonders in Kinderzimmern, damit sie nicht fernsehen)
  • USB-Luftbefeuchter
  • Echo Dot (Alexa für die Nacht herunterfahren lassen? oder das Gerät einfach neu starten)
  • Entwicklungsboards. Müssen Sie dieses Projekt neu starten, weil Ihre Codes in eine Endlosschleife geraten sind?
  • Geräte, die schwer zugänglich sind, aber gelegentlich neu gestartet werden müssen (z. B. Sensoren auf dem Dachboden).
  • Geräte, die beim Kunden installiert sind, wo wir sicherstellen möchten, dass sie mit Strom versorgt werden (durch Messung des Stromverbrauchs und der Eingangsspannung)

Einfache Leistungssteuerung: Internetfähiges Stromschalten, entweder über die Alexa-Sprachsteuerung oder andere Befehle über Tinamous. Ein und Aus.

Intelligente Leistungssteuerung: Viele USB-Lampen haben Touch-Bedienelemente, um die Lampe einzuschalten, was bedeutet, dass wir das Licht aus der Ferne nicht einschalten können, aber wir können es ausschalten, und oft ist das alles, was wir wollen (versuchen zu schlafen, ließ eine Lampe an) ?Ausgehen, alle Lichter ausschalten?).

Sobald wir jedoch Alexa zum Ausschalten der USB-Lampe verwendet haben, müssen wir Alexa bitten, die Lampe einzuschalten, bevor wir sie einschalten können, das ist einfach albern. Wenn Smart Power aktiviert ist, schaltet der Aus-Befehl die Lampenleistung für einige Sekunden aus, bevor die Stromversorgung des Geräts wiederhergestellt wird. Genug, um die Lampe auszuschalten, aber auch danach den normalen Betrieb zu ermöglichen.

Timer-Automatisierung: Lassen Sie Ihre Geräte zu festgelegten Zeiten automatisch herunterfahren. Kinder, die Amazon TV auf dem Feuerstock zu spät schauen? Lassen Sie die USB-Versorgung um 20:00 Uhr automatisch abschalten.

Leistungsüberwachung: Wenn Sie USB-betriebene Hardware entwickeln, möchten Sie vielleicht wissen, wie viel Strom Ihr Gerät verbraucht, insbesondere wenn es zum ersten Mal eingeschaltet wird, oder Sie möchten ein Profil zum Laden des Akkus erstellen. Mit dem On-Board INA219 kann man die Stromaufnahme überwachen (ich habe mit wenig Aufwand ca. 1kHz Abtastung geschafft). Spannungsabfall an USB-Kabeln bei hohem Strom kann ebenfalls ein Problem sein. Der INA219 überwacht die Stromversorgung des Geräts, damit wir bei niedriger Spannung warnen können. Ein Klemmenblock ist ebenfalls vorhanden, um höhere Ströme und größere Kabel verwenden zu können.

Stromausfall: Durch die Verwendung der Batterieoption des MKR 1000 können wir die USB-Versorgungsspannung überwachen und Benachrichtigungen senden, wenn die Eingangsspannung ausgefallen ist. Dies kann für Remote-Lösungen (außerhalb des Standorts) nützlich sein, die USB-Strom verwenden, aber ein wenig zusätzliche Überwachung benötigen, oder einfach als einfache Erkennung von Stromausfall für Ihr Haus.

Hardware

Dieses Projekt ist ziemlich einfach, ein Arduino MKR1000 im Herzen, USB-Power-Switching mit zwei LM3526Ms für High-Side-Switching und Fehlererkennung (Niederspannung, Überstrom), zusammen mit Stromüberwachung (Spannung und Strom) mit einem INA219 und schließlich LEDs und Schalter für lokale Steuerungsoptionen.

Ich habe eine Platine bei DirtyPCBs.com herstellen lassen, Sie können die .brd-Datei auch an OSHPark.com senden, um auch einige zu machen. Die Arduino-Buchse hat auf beiden Seiten jedes Pins PCB-Pads, um Hacking zu ermöglichen. z.B. Sie können leicht einige Sensoren für Umgebungsbedingungen oder ein kleines OLED-Display hinzufügen, um Spannung und Strom anzuzeigen.

Im Github-Repository gibt es eine 2-Port- und 4-Port-Option. Seien Sie vorsichtig mit der 2-Port-Platine, denn Ich habe es vermasselt und habe das Layout für die USB-Buchse falsch gemacht (sie sind von hinten nach vorne - falsche Polarität !).

Sieg aus dem Rachen der Niederlage:

Wie sich herausstellte, ist die Montage des USB-Sockels auf der Rückseite des Boards eigentlich eine schöne Lösung und bedeutete, dass die Pinbelegung korrekt war (bei der 2-Port-Platine bedeutet dies jedoch auch, dass der Siebdruck auf der falschen Seite ist!). Der Arduino mit Headern in einer Buchse war etwas platzsparend mit der erforderlichen Höhe, um die USB-Buchsen aus dem Gehäuse zu bekommen, also hat es tatsächlich besser geklappt. Ich beschloss, die Platine mit Buchsen, Schaltern und LEDs auf der Rückseite neu zu machen Seite und um zwei zusätzliche Ports hinzuzufügen, daher wurde die 4-Port-Version erstellt (auch hatte ich die LEDs auf dem 2-Porter schrecklich ausgerichtet, so dass das auch behoben wurde!).

Ihre Erweiterung auf einen 6- oder 8-Port-Switcher ist kaum zu verhindern, obwohl die LEDs und Switches möglicherweise weggelassen oder verbessert werden müssen.

Der Schaltplan sieht viel komplexer aus, als er ist. Viele der Widerstände sind optional. Die Widerstände R23, 19, 27 und 26 sind alle Pull-Ups für die Schalter, ebenso R20-22, R14 &R15 sind Pull-Ups für die USB-Steuerung und Fehlererkennung. Dies kann alles über den INPUT_PULLUP-Pin-Modus im Arduino erfolgen. Wenn Sie jedoch das Arduino in den Energiesparmodus versetzen und Interrupts verwenden möchten, um es aufzuwecken, möchten Sie diese möglicherweise auffüllen, damit sie nicht schweben (und herumspringen). .

Ich habe auch optionale Widerstände um die USB D+/D- Leitungen hinzugefügt. Diese können angebracht werden, um dem Gerät mitzuteilen, wie viel Strom es verbrauchen kann, aber für viele dumme Geräte werden diese sowieso ignoriert. Darunter wird eigentlich nur R24 ​​für die LED-Strombegrenzung benötigt. R2-5 und R28 bleiben leer.

Auch die LEDs und Schalter sind komplett optional. Wenn Sie nur eine eigenständige Box wünschen, die USB aus der Ferne steuert, fügen Sie diese Teile nicht hinzu.

Leistungsaufnahme

Dieser Controller kann über drei Optionen mit Strom versorgt werden.

Die erste ist die Option "Intern" (JP6-Pins 1 und 2 verbunden), USB-Strom wird vom 5V-Pin des Arduino (und damit vom Arduino-USB-Anschluss) entnommen. Dies sollte jedoch nur für Lasten mit geringer Leistung verwendet werden.

Die anderen Optionen sind für die externe Stromversorgung (JP6-Pins 2 &3 verbunden), Sie können dann 5 V über J2 (den integrierten USB-Mikroanschluss) oder JP8 (eine Klemmleiste) anschließen. Sie sollten nicht beide Optionen gleichzeitig verwenden. Die externe Stromversorgung wird auch an den Arduino VIn-Pin geleitet, sodass keine eigene Stromversorgungsoption erforderlich ist.

Für Bonuspunkte bietet das Anbringen von 0R-Widerständen an R10 und R11 sowie J2 USB-Pass-Through für USB 3, damit wir ein über USB angeschlossenes Gerät neu starten können, sehr praktisch bei der Entwicklung von Hardware und Sie möchten Ihre USB-Buchsen nicht abnutzen der PC!

Gehäuse

Ein 3D-druckbares Gehäuse ist in diesem Projekt enthalten. Es verwendet M3-Heatfit-Einsätze für Leiterplatten- und Deckelverbindungen, obwohl die Toleranzen am Deckel für einen Reibschluss gut genug sind.

Der Deckel enthält einige Optionen.

  • Mit oder ohne Batteriefach.
  • Mit oder ohne Füße (auch bekannt als Befestigungslöcher, damit die Box an einer Oberfläche befestigt werden kann).

Ebenso kann die Basisbox (unter Verwendung von OpenSCAD) so konfiguriert werden, dass sie Öffnungen für jede der drei Stromquellen enthält.

Es hat ein paar Schritte gedauert, bis das Gehäuse richtig war. Wie versionieren Sie Ihre Drucke? Meine Proben vom Rigid.Ink-Fanclub waren sehr praktisch.

Verbindung zu Tinamous herstellen

Wir verwenden den Arduino MKR1000, um die Steckdosen zu steuern, also haben wir eine WiFi-Konnektivität. Wenn Sie neu bei diesem Board sind, müssen Sie die Board-Option zu Ihrer Arduino IDE hinzufügen.

Wir werden den Tinamous MQTT-Server verwenden, um eine Verbindung herzustellen, hauptsächlich weil er großartig ist, aber auch, vielleicht weil ich der Gründer/Entwickler/Teekocher bin! Wir abonnieren das Thema Statuspost für Nachrichten, die an das Gerät gesendet werden. (d. h. das Thema "Status.To").

Bevor wir mit der Codierung beginnen, müssen wir sicherstellen, dass das Arduino über die neueste Firmware sowie die erforderlichen SSL-Zertifikate verfügt, um eine sichere Verbindung zu Tinamous herzustellen. Wenn Sie es vorziehen, können Sie dies natürlich an Ihren eigenen lokalen MQTT-Server anpassen und sich nicht so viele Gedanken über die Sicherheit machen.

Schritt 1

Öffnen Sie die Arduino IDE und laden Sie den FirmwareUpdater Skizze aus dem WiFi101-Beispielmenü. Laden Sie dies auf Ihr Gerät hoch.

Schritt 2

Wählen Sie nach dem Hochladen WiFi101 Firmware Updater aus den Tools Menü.

Schritt 3

Testen Sie Ihre Verbindung und dann Firmware aktualisieren . Sobald dies erledigt ist, verwenden Sie Domain hinzufügen und fügen Sie tinamous.com . hinzu um sicherzustellen, dass das Arduino über die richtigen SSL-Zertifikate verfügt. Drücken Sie auf Zertifikate in das WLAN-Modul hochladen Schaltfläche zum Hochladen der Zertifikate.

Schritt 4

Jetzt können wir unsere eigene Firmware schreiben. Sie finden die an dieses Projekt angehängten Dateien und auch im GitHub-Repository (GitHub wird die neueste Version haben).

Wir verwenden den WiFi101 und den MQTT-Client für Ihre Arduino-Skizze.

Wählen Sie die Option MQTT von Joel Gaehwiler.

Die Datei secrets.h muss mit Ihren WLAN- und Tinamous-MQTT-Einstellungen gefüllt werden, ich habe meine Kopie aus offensichtlichen Gründen nicht hinzugefügt.

WLAN- und MQTT-Servereinstellungen:

#define SECRET_SSID "Ihre SSID"#define SECRET_PASS "Ihre SSIDs Passwort"/**************************** Tinamous MQTT Setup *********************************/#define MQTT_SERVER ".tinamous.com"#define MQTT_SERVERPORT 8883 #define MQTT_USERNAME "UsbSwitch."#define MQTT_PASSWORD "Ihr Passwort kommt hier rein."#define MQTT_CLIENT_ID "UsbSwitch"#define DEVICE_USERNAME "UsbSwitch" 

Wenn Sie sich noch nicht bei Tinamous registriert haben, können Sie hier Ihr eigenes kostenloses Konto erstellen. Wenn Sie sich registrieren, werden Sie nach einem Konto-/Organisationsnamen gefragt. Dies wird Ihr eigener privater Bereich von Tinamous, Sie können andere Mitglieder in diesen Bereich einladen (einschließlich Alexa) und Ihre Geräte mit Ihrer Gruppe teilen.

Unten nenne ich mein Konto "AlexaExample", das muss ich in das MQTT-Setup aufnehmen, und mein Tinamous-Konto befindet sich unter https://AlexaExample.Tinamous.com

Schritt 5

Als nächstes müssen wir unser Gerät hinzufügen. Klicken Sie auf der Seite Tinamous Devices auf die Schaltfläche Add.

Daher sehen die Tinamous MQTT-Einstellungen für mein Gerät ungefähr so ​​​​aus...

/************************ Tinamous MQTT-Setup ************* ******************/#define MQTT_SERVER "AlexaExample.tinamous.com"#define MQTT_SERVERPORT 8883 #define MQTT_USERNAME "UsbSwitch.AlexaExample"#define MQTT_PASSWORD "Mein supergeheimes Passwort, das ist absolut nicht Passw0rd...."#define MQTT_CLIENT_ID "UsbSwitch"#define DEVICE_USERNAME "UsbSwitch" 

Das ist unser Tinamous-Konto und das Gerät aktiviert. Sie können hier weitere Geräte hinzufügen, wenn Sie möchten, aktualisieren Sie einfach die MQTT-Einstellungen für DEVICE_USERNAME und MQTT_USERNAME (MQTT sendet keine Header-Informationen wie http, daher hat Tinamous keine Ahnung, welche Sub-Domain Sie verwenden, daher müssen wir dies angeben Konto im Benutzernamen).

Schritt 6

Laden Sie den angehängten Code auf Ihre Geräte hoch (mit Ihrer aktualisierten secrets.h-Datei). Nehmen Sie sich einen Moment Zeit, um sich die Datei TinamousMQTTClient.ino anzusehen. Diese verarbeitet unsere MQTT-Interaktionen und damit die Alexa-Befehle, die an unser Gerät gesendet werden.

Wir müssen den WiFiSSLClient für SSL verwenden. Wenn Sie einen lokalen MQTT-Server ohne SSL verwenden möchten, können Sie den regulären WiFi-Client verwenden und auf Port 1883 herunterfahren, aber für alles, was internetbasiert ist, verwenden Sie den SSL-Client.

Wir müssen auch etwas mehr als den Standardpuffer für den MQTT-Client reservieren, hier reservieren wir 4096 Byte.

WiFiSSLClient networkClient; MQTTClient mqttClient(4096);  

Wir verwenden mqttClient.begin, um den Client einzurichten und geben in onMessage einen Funktionshandler an, der aufgerufen wird, wenn eine Nachricht vom MQTT-Server empfangen wird.

 mqttClient.begin(MQTT_SERVER, MQTT_SERVERPORT, networkClient); // Behandelt empfangene Nachrichten. mqttClient.onMessage(messageReceived); 

Und dann können wir uns verbinden und die Themen abonnieren, die uns interessieren. Hier sehen Sie, dass wir "Tinamous/V1/Status.To/UsbSwitch" abonniert haben, wir erhalten Nachrichten von der Tinamous-Timeline an @UsbSwitch. So erhalten wir Nachrichten von Alexa.

if (!mqttClient.connect(MQTT_CLIENT_ID, MQTT_USERNAME, MQTT_PASSWORD)) { if (mqttClient.lastError() ==LWMQTT_CONNECTION_DENIED) { // Dieser Fehler liegt an einem falschen Benutzernamen oder Passwort } if (mqttClient. lastError() ==-6) { // Dieser Fehler ist höchstwahrscheinlich darauf zurückzuführen, dass Sie das SSL-Zertifikat nicht hinzugefügt haben. } // Erzwinge eine Verzögerung, bevor die Verbindungsverzögerung erneut versucht wird (10000); return false;} // Erfolgreiche Verbindung. Abonnieren Sie nun das Thema mqttClient.subscribe("/Tinamous/V1/Status.To/" DEVICE_USERNAME); 

Sie können sich die Tinamous-Timeline wie eine private Version von Twitter für Sie und Ihre Geräte vorstellen. Sie können MQTT oder die REST-API (oder einen der Bots) verwenden, um die an sie gesendeten Nachrichten zu sehen und darauf zu reagieren, sowie zu posten Nachrichten zurück.

Wir haben in Tinamous noch etwas zu tun, um die Alexa-Integration zu ermöglichen, aber im Moment können wir unser Gerät und unsere Firmware testen, indem wir die Timeline verwenden und Nachrichten senden.

Wenn Sie den Tinamous SmartHome Skill verwenden, ist dies die gesamte erforderliche Codierung.

Der Tinamous Smart Home Skill für Alexa

Für den Tinamous Smart Home Skill steht derzeit die Freigabe zur Veröffentlichung aus (zum Zeitpunkt des Schreibens, Daumen drücken, er ist jetzt im Laden...). Um Ihren eigenen USB-Umschalter zu erstellen, können Sie diesen Skill einfach verwenden, wenn er verfügbar ist.

Der Skill ist eigentlich sehr allgemein gehalten, er weiß nichts über die Geräte oder wie man mit ihm spricht. Wir weisen den Geräten in Tinamous Tags zu und der Skill erstellt ein entsprechendes Gerät im Alexa-Konto. Daher können Sie diesen Skill und Tinamous verwenden, um eines Ihrer eigenen Projekte mit nur wenigen Codezeilen auf dem Gerät zu aktivieren.

Sie können jedoch Dinge ändern oder Ihre eigenen Fähigkeiten schreiben, damit ich die Details meiner Entwicklung mit Ihnen teile.

Ich habe den Skill in C# für .Net Core 2.0 geschrieben, er wurde eigentlich für mein BOFF-Smart-Fan-Projekt entwickelt, aber für dieses Projekt habe ich ihn erweitert, um es einem Gerät zu ermöglichen, viele Ausgänge (Ports) zu haben und für jeden erstklassig zu sein Bürger in Alexa Smart Home-Geräten.

Der gesamte Code (einschließlich einiger Tests!) ist im Tinamous SmartHome-Repository, klonen, herunterladen oder einfach anzeigen, wie Sie möchten. Ich habe Visual Studio 2017 mit den installierten AWS-Tools verwendet, um den Skill auf Lambda zu übertragen.

Das Framework deserialisiert die eingehende Direktivennachricht von Alexa in Objekte, auf die wir über den Code zugreifen können, entsprechende Aktionen werden basierend auf dem Header-Namespace und Direktivennamen ausgeführt und dann wird eine entsprechende Antwort zurückgegeben.

Die wichtigsten Botschaften von Interesse sind:

  • Kontoverknüpfung
  • Entdeckung
  • Staatsbericht
  • Energiekontrolle

Kontoverknüpfung:

Dies wird von Alexa für uns abgewickelt. Nachdem wir den Skill zu unserem Konto hinzugefügt haben, fordert Alexa eine Authentifizierung an, wir werden zur Tinamous Authorize-Seite weitergeleitet, damit das Gerät auf unser Konto zugreifen kann. Hier müssen Sie Ihren Kontonamen (in diesem Fall AlexaExample), Ihren Benutzernamen (Steve) und Ihr Passwort (nein, das verrate ich nicht!) eingeben

Entdeckung:

Sobald Ihr Konto verknüpft ist, fordert Alexa auf, eine Erkennung durchzuführen, der Skill fragt Tinamous dann nach Geräten ab, die mit "Alexa.SmartDevice . markiert sind ". Geräte ohne diese werden einfach ignoriert.

Diese Tags werden angewendet, indem das Gerät auf der Seite Geräte in Tinamous bearbeitet wird.

Wenn das Gerät auch mit "MultiPort . gekennzeichnet ist " Jeder Port wird aufgezählt und für diese wird auch ein Gerät hinzugefügt. Wir wenden auch Tags basierend auf den Alexa-Direktiven an, die unser Gerät unterstützt, hier ist es nur "Alexa.PowerController " und auch ein Tag, um anzugeben, unter welcher Kategorie das Gerät in der App angezeigt werden soll, hier habe ich "SmartPlug . verwendet ".

Andere Schnittstellen sind vorhanden, wie zum Beispiel Alexa.BrightnessController, aber das ist hier nicht so nützlich. Weitere Informationen finden Sie in der Readme-Datei zum Repository.

Damit unser MultiPort-Gerät einzelne Ports für Alexa verfügbar macht, müssen wir die Zustandsvariablen auch auf der Seite zum Bearbeiten des Geräts einrichten.

PortCount gibt die Anzahl der Ports an, die das Gerät hat, dann "Port-1".."Port-n" gibt die Namen an, die Alexa für die Ports verwendet. Alle Ports ohne Namen werden ignoriert. Sie können hier ganz einfach den Namen des Ports ändern und die Erkennung erneut ausführen, um Alexa zu aktualisieren.

Während der Erkennung sucht der Skill auch nach einem Feld, das entsprechend mit "powerState" oder "powerState-port-n" gekennzeichnet, benannt oder beschriftet ist. Wenn dieses Feld gefunden wird, wird es dem Gerät als unterstützte Funktion zugewiesen (mehr dazu im Statusbericht).

Zustandsbericht

Während der Discovery-Phase haben wir Alexa mitgeteilt, welche Fähigkeiten unser Gerät hat. Der Skill teilt Alexa standardmäßig mit, dass diese angefordert werden können, daher sendet Alexa eine StateReport-Anfrage, um die Werte dafür abzurufen.

Wir haben einen letzten Satz von Tags, der angewendet werden muss, um dies zu unterstützen, diesmal auf die Gerätefelder. Sobald Ihr Gerät Daten sendet (das ist die Senml-Nachricht, die im Arduino-Code über MQTT übertragen wird), erstellt Tinamous Felder für das Gerät. Wir können dann die Option Erweitert aus der Feldliste verwenden, um dies zu bearbeiten. Die Verwendung der Tag-Option ist am vielseitigsten, da wir den Feldnamen nicht in der Firmware korrigieren oder feststecken müssen, wenn wir ihn umbenennen möchten.

Wenn die portspezifischen Felder nicht gefunden werden, wird Alexa auf das nicht portspezifische Feld (hier powerState genannt) zurückgreifen.

Leistungssteuerung

Ohne dies wird unser Gerät in Alexa keinen Nutzen haben! Alexa sendet zwei Anweisungen an unseren Skill "TurnOn" und "TurnOff". Der Hauptfunktionseinstiegspunkt für den Skill sucht zuerst nach dem Namespace (Alexa.PowerController) und übergibt dann den Job an die entsprechende Controller-Klasse (PowerController.cs).

Der Skill veröffentlicht dann einfach eine Statusmeldung auf der Tinamous-Timeline.

Zum Beispiel:

@UsbSwitch einschalten

oder

@UsbSwitch Port-1 einschalten

Die anderen unterstützten Schnittstellen werden nahezu identisch gehandhabt. Es liegt dann an unserem Gerät, auf diese Statusmeldung zu achten und eine Aktion auszuführen. Alexa kann dann den Status mithilfe eines StateReports zurücklesen.

So funktioniert die Fertigkeit. Jetzt müssen wir es nur noch an AWS Lambda senden und einen Skill-Eintrag auf der Alexa-Konsole erstellen, um Alexa tatsächlich Zugriff darauf zu gewähren.

Erstellen der AWS Lambda-Funktion:

Ich habe die AWS-Tools in Visual Studio verwendet, um den kompilierten Skill an Lambda zu übertragen. Aber zuerst müssen wir das Lambda erstellen.

Profi-Tipp: Erstellen Sie Lambda im entsprechenden AWS-Bereich für die von Ihnen unterstützte Sprache. Englisch (UK) muss auf eu-west (Irland) abzielen.

Erstellen Sie eine neue Lambda-Funktion von Grund auf. Die vorhandenen Blaupausen sind begrenzt und veraltet (unterstützen nur V2 der SmartHome-Schnittstelle, die sehr unterschiedlich und veraltet ist - wir verwenden V3).

Sie müssen eine neue Rolle erstellen, damit Lambda auf die benötigten Ressourcen zugreifen kann. Hier wählen wir Simple Microservices als Standard aus (es gibt tatsächlich mehr nach als wir brauchen). Wenn Sie feststellen, dass Sie keine Protokolle in Cloud Watch erhalten, müssen Sie möglicherweise auch die Rollenberechtigungen dafür über den IAM-Abschnitt erteilen.

Dann müssen wir die Binärdateien aus Visual Studio veröffentlichen. Klicken Sie bei installierten AWS-Tools mit der rechten Maustaste auf das Projekt und wählen Sie "In AWS Lambda veröffentlichen..."

Geben Sie dann die Details für den Lambda-Ausdruck ein und klicken Sie auf Hochladen...

Nach dem Hochladen können wir einige Tests auf dem Lambda durchführen, um sicherzustellen, dass er läuft. Dann müssen wir im Dropdown-Menü "Aktionen" "Neue Version veröffentlichen" auswählen.

Nach der Veröffentlichung müssen wir unserem Skill Berechtigungen erteilen, um darauf zuzugreifen,

Klicke auf den Auslöser "Alexa Smart Home" und gib die Skill-ID ein (das haben wir aber noch nicht...)

Erstellen des Skills in der Alexa-Konsole:

Da unser Lambda fast fertig ist, müssen wir zur Skill-Entwicklerkonsole gehen und tatsächlich einen Eintrag dafür erstellen. Öffne https://developer.amazon.com, wähle Alexa Skills Kit und füge einen neuen Skill hinzu.

Wählen Sie die Smart Home Skill API, die Sprache, die Sie ansprechen möchten (z. B. Englisch (UK) für uns in Großbritannien) und wählen Sie die Nutzlastversion V3 (bevorzugt).

Auf der Konfigurationsseite gehen wir auf die interessanteren Details ein. Geben Sie den Lambda-ARN von unserem versionierten Lambda (oben rechts auf dem Bildschirm) ein. Es sollte so enden wie :1 oder :2 oder :5246 (wenn Sie ein paar Versuche gemacht haben;-) ).

Während wir in Lambda auch die "Application ID" oder "Skill ID" oder "ID" oder wie auch immer es heute vom Skill heißt, einfügen können, sollte es in etwa wie amzn1.ask.skill.2_________50 aussehen.

Achten Sie darauf, auf Speichern zu klicken, nachdem Sie die Anwendungs-ID hinzugefügt haben. In der alten Konsole finden Sie die ID in der Kopfzeile unter dem Skill-Namen, in der neuen, ähm, öffnen Sie ein neues Fenster, gehen Sie zurück zur Konsolen-Skill-Liste und klicken Sie auf den entsprechenden Link. (Es ist, als ob sie die Konsole nie benutzt hätten, um tatsächlich eine Fertigkeit zu erstellen).

Um die Kontoverknüpfung zu ermöglichen, benötigen wir eine bei Tinamous erstellte OAuth-Anwendung, dies geschieht mit dem Alexa Bot. Gehen Sie auf die Bots-Seite Ihres Tinamous-Kontos und fügen Sie einen Alexa-Bot hinzu. Sobald Sie dieses erstellt haben, erhalten Sie im Dialogfeld alle Details, die Sie zum Konfigurieren der Kontoverknüpfung benötigen.

Hinweis:Wenn Sie den (bald...) veröffentlichten Tinamous SmartHome Skill verwenden, benötigen Sie keinen Alexa Bot.

Die vom Bot erstellte Anwendung ermöglicht es allen anderen Tinamous-Kontoinhabern, Ihren Skill zu verwenden und ihr Konto zu verknüpfen. Natürlich müssen Sie Ihren Skill nicht veröffentlichen und können ihn privat halten, und sie können nichts in Ihrem Tinamous-Konto sehen.

Ebenso, wenn Sie eine andere Geräte-Cloud verwenden (im Ernst, warum sollten Sie das tun;-) ), dann müssen Sie deren OAuth-Anwendungsdetails eingeben.

Stellen Sie auf der Testseite sicher, dass Ihr Skill bei „Diesen Skill in der Alexa App anzeigen“ auf „Ja“ eingestellt ist.

Speichern Sie und gehen Sie zu alexa.amazon.co.uk (oder die für Ihre Region geeignete) oder anscheinend auch eine App .....

Klicken Sie auf "Fähigkeiten", dann oben rechts auf "Ihre Fähigkeiten" und dann auf "ENTWICKLER-FÄHIGKEITEN", Sie sollten Ihre Fertigkeit mit einer grünen Markierung sehen, um anzuzeigen, dass es sich um eine Entwicklungsfertigkeit handelt.

"Alexa, schalte das USB-Licht aus" und zusätzliche Skill-Informationen, wenn Sie sie auswählen, werden auf der Seite "Veröffentlichungsinformationen" konfiguriert. Sie können die Informationen während der Entwicklung eingeben, ohne die Veröffentlichung vollständig durchführen zu müssen.

Wenn Sie den Skill-Code aktualisieren müssen, laden Sie die neue Lambda-Funktion hoch, erstellen Sie eine neue Version, fügen Sie den SmartHome-Trigger und die Skill-ID erneut hinzu und fügen Sie dann die versionierte Lambda-Funktion in die Skill-Konsole ein (möglicherweise können Sie versioned lambda, but it didn't work when I tried - although there were many other things I'd also got wrong at that time).

Success!

With our skill code is running in Lambda and the Skill installed in our Alexa account, we can run discovery, and then start controlling the devices.

You can click over to the CloudWatch logs to see the log information written by your skill.

Skill Debugging &Tips

Alexa provides next to no developer feedback when things go wrong, you can spend ages guessing why Alexa doesn't do as you hoped.

  • Avoid most things other than alpha-numerics in your endpointID's (I used * at one stage and everything broke, but not in an obvious way, however # was fine. Go figure!).
  • Log everything. Check for logs when you've invoked your skill. No log then it's probably authentication, or your skill isn't authorized for the Lambda expression.
  • Use matching AWS and Alexa email accounts.
  • Keep the Lambda in the same region as the skill (Ireland for UK skills).
  • If your skill is invoked but Alexa isn't responding to it (i.e. not listing devices), your response format is probably wrong.
  • If you don't want to use your day to day Alexa account you can use Amazon households to add a second adult account. Note however this appears to be limited to 2 adults, and you can't change it without an epic delay.
  • You can ask "Alexa, Switch Profiles" to switch between your developer and regular profiles.
  • I hope with the redesign of the Alexa Console some better debugging information will be available. However right now all I see is bigger boxes and a little better validation. Some logs are available but they are just success logs. aka management level feel good metrics, and delayed by 36 hours which isn't helpful for debugging!

One Skill, Any (IoT) Thing!

With the Tinamous SmartHome skill, as long as your (Internet of Things) thing can connect to the Tinamous MQTT server (or is connected via a supported bot) adding Alexa SmartHome control to your thing is simply a few lines of code to handle messages like "Turn On", "Turn Off", "Set brightness 20". Just add the tags in Tinamous, and....

"Alexa, Discover Smart Home Devices".

Code

  • AlexaUsbSwitcher.ino
  • TinamousMQTTClient.ino
  • UsbControl.ino
  • WiFiClient.ino
  • Secrets.h
AlexaUsbSwitcher.inoArduino
This is the main file.
#include #include #include #include // Provide your own Secrets.h with WiFi and Tinamous definitions in it.#include "Secrets.h"// ================================/*#define MAX_USB_PORTS 2// 2 Port board.int led_pin[MAX_USB_PORTS][2] ={{A5, A6},{0,1}};int switch_pin[] ={A0, A1};// Usb switch B channel -> pin 5 ==USB1int usb_enable_pin[] ={2, 5};int usb_fault_pin[] ={3, 4};bool usb_port_state[] ={false, false};bool usb_power_mode[] ={0, 0, 1, 1};*/// ---------------------------------// 4 Port board.#define MAX_USB_PORTS 4// The 2 port board has bi-color LEDs, 4 port doesn't so use same pin......// LEDs:TX, Rx, D7, D6 (1-4)int led_pin[MAX_USB_PORTS][2] ={{14, 14}, {13,13}, {7,7}, {6,6}};int switch_pin[] ={A0, A1, A2, A3};// USB Enable pins, D1, D3, D4, D5 (not in that order)int usb_enable_pin[] ={5, 4, 1, 3};// Single fault pin (D2)int usb_fault_pin[] ={2, 2, 2, 2};bool usb_port_state[] ={false, false, false, false};// Mode:0 - Switch off as requested.// Mode:1 - Switch off, then on after a delay (useful for LED lights that have touch controls).int usb_power_mode[] ={1, 0, 0, 0};// ================================// Automation options.// time (millis) that the USB port should be switched on/off at.// zero indicates ignore.unsigned long usb_power_switch_on_at[] ={0, 0, 0, 0};// Set> 0 to get processed on first loop.// Side effect is switching them off that those in smart power // mode will schedule to come back on again).unsigned long usb_power_switch_off_at[] ={1, 1, 1, 1};// Current monitor INA219Adafruit_INA219 ina219;// Flag to indicate if one or more USB ports has a fault.bool has_usb_fault =false;// Measured power .float shunt_voltage =0;float bus_voltage =0;float current_mA =0;float load_voltage =0;float power_mW =0;// Min/max float max_current_mA =0;float max_busvoltage =0;float min_busvoltage =20;// track power usage.unsigned long last_measurement_time =0;bool power_failed =false;bool over_current =false;// MQTT publishing.// Probably want it quicker when powering devices.// or slower when not!int update_interval_seconds =20;unsigned long next_message_send_at =0;// =================================================// Main setup entry point// =================================================void setup() { pinMode(LED_BUILTIN, OUTPUT); digitalWrite(LED_BUILTIN, HIGH); for (int channel=0; channel MAX_USB_PORTS) { return; } // Light up the LED (1..4) based on the setup progress. SetLeds(stage-1 , true, true);}// ===================================================// Main Loop// ===================================================void loop() { // 4 port device, Debug LED is port 4 LED. // if any port 4 is on, then don't switch off the LED. // with all 4 ports off, the debug LED can blink as it likes... if (!hasPoweredPorts()) { digitalWrite(LED_BUILTIN, LOW); } // Check for a fault. bool faulted =false; for (int channel =0; channel  max_current_mA) { max_current_mA =current_mA; } if (bus_voltage> max_busvoltage) { max_busvoltage =bus_voltage; } if (bus_voltage  4.5) { Serial.print("External power restored. Bus voltage:"); Serial.print(bus_voltage); Serial.println(" V"); publishTinamousStatus("External power has been restored."); power_failed =false; } if (bus_voltage <4.2 &&!power_failed) { Serial.print("External power failed! Bus voltage:"); Serial.print(bus_voltage); Serial.println(" V."); publishTinamousStatus("External power lost!"); power_failed =true; } if (over_current &¤t_mA <1500) { publishTinamousStatus("Current fault cleared!"); over_current =false; } if (current_mA> 2000 &&!over_current) { // Overload! publishTinamousStatus("Over Current!"); over_current =true; } }void printPowerWide() { Serial.print("Bus Voltage:\t"); Serial.print(bus_voltage); Serial.print(" V\t"); Serial.print("Current:\t"); Serial.print(current_mA); Serial.print(" mA\t"); Serial.print("Max Current:\t"); Serial.print(max_current_mA); Serial.print(" mA\t"); Serial.print("Min Voltage:\t"); Serial.print(min_busvoltage); Serial.print(" V\t"); Serial.print("Max Voltage:\t"); Serial.print(max_busvoltage); Serial.print(" V\t"); Serial.println();}void printPowerSkinny() { Serial.print(bus_voltage); Serial.print("\t"); Serial.print(current_mA); Serial.print("\t\t"); Serial.print(max_current_mA); Serial.print("\t\t"); Serial.print(min_busvoltage); Serial.print("\t"); Serial.print(max_busvoltage); Serial.print("\t"); Serial.print("["); for (int channel=0; channel next_message_send_at) { Serial.println("------------------------"); Serial.println("MQTT publish measurements"); if (power_failed) { // reduce how often we send when the power // has failed to preserve battery power. sentNextPublishAt(update_interval_seconds * 10); } else { sentNextPublishAt(update_interval_seconds); } // And do one as senml... String senml ="{'e':["; // Voltage senml =senml + "{'n':'busVoltage'"; senml =senml + ", 'v':"; senml =senml + String(bus_voltage); senml =senml + ", 'u':'V'}"; // Max voltage senml =senml + ",{'n':'maxBusVoltage'"; senml =senml + ", 'v':"; senml =senml + String(max_busvoltage); senml =senml + ", 'u':'V'}"; // Min voltage senml =senml + ",{'n':'minBusVoltage'"; senml =senml + ", 'v':"; senml =senml + String(min_busvoltage); senml =senml + ", 'u':'V'}"; // Current senml =senml + ",{'n':'Current'"; senml =senml + ", 'v':"; senml =senml + String(current_mA); senml =senml + ", 'u':'mA'}"; // Max current senml =senml + ",{'n':'MaxCurrent'"; senml =senml + ", 'v':'"; senml =senml + String(max_current_mA); senml =senml + "', 'u':'mA'}"; // mAh consumed... senml =senml + ",{'n':'mAh'"; senml =senml + ", 'v':"; senml =senml + String(0); // TODO! senml =senml + ", 'u':'mAh'}"; senml =senml + ",{'n':'powerState"; senml =senml + "', 'bv':"; if (isPowered()) { senml =senml + "true"; } else { senml =senml + "false"; } senml =senml + "}"; for (int channel=0; channel 0 &&onAt  0 &&offAt  
TinamousMQTTClient.inoArduino
This file handled the MQTT connectivity (i.e. it's the bit that responds to Alexa commands).
// ======================================// Tinamous connectivity via MQTT// ======================================#include #include #include "secrets.h"// WiFi and MQTT settings in Secrets.h// Be sure to use WiFiSSLClient for an SSL connection.// for a non ssl (port 1883) use regular WiFiClient.//WiFiClient networkClient; WiFiSSLClient networkClient; // https://github.com/256dpi/arduino-mqtt// Specifying 4096 bytes buffer sizeMQTTClient mqttClient(4096); // If we have been connected since powered up bool was_connected =false;String senml ="";unsigned long nextSendMeasurementsAt =0;// =================================================// Setup the MQTT connection information// =================================================bool setupMqtt() { senml.reserve(4096); Serial.print("Connecting to Tinamous MQTT Server on port:"); Serial.println(MQTT_SERVERPORT); Serial.print("Server:"); Serial.println(MQTT_SERVER); mqttClient.begin(MQTT_SERVER, MQTT_SERVERPORT, networkClient); // Handle received messages. mqttClient.onMessage(messageReceived); connectToMqttServer();}// =================================================// Connect to the MQTT server. This can be called // repeatedly and will be ignored if already connected// =================================================bool connectToMqttServer() { if (mqttClient.connected()) { return true; } Serial.println("Reconnecting...."); Serial.println("checking wifi..."); if (WiFi.status() !=WL_CONNECTED) { Serial.print("WiFi Not Connected. Status:"); Serial.print(WiFi.status(), HEX); Serial.println(); Verzögerung (10000); falsch zurückgeben; } Serial.println("Connecting to MQTT Server..."); if (!mqttClient.connect(MQTT_CLIENT_ID, MQTT_USERNAME, MQTT_PASSWORD)) { Serial.println("Failed to connect to MQTT Server."); Serial.print("Error:"); Serial.print(mqttClient.lastError()); Serial.print(", Return Code:"); Serial.print(mqttClient.returnCode()); Serial.println(); if (mqttClient.lastError() ==LWMQTT_CONNECTION_DENIED) { Serial.println("Access denied. Check your username and password. Username should be 'DeviceName.AccountName' e.g. MySensor.MyHome"); } if (mqttClient.lastError() ==-6) { Serial.println("Check your Arduino has the SSL Certificate loaded for Tinmaous.com"); // Load the Firmware Updater sketch onto the Arduino. // Use the Tools -> WiFi Firmware Updater utility } // Wait 10s before it gets re-tried. Verzögerung (10000); falsch zurückgeben; } Serial.println("Connected to Tinamous MQTT!"); mqttClient.subscribe("/Tinamous/V1/Status.To/" DEVICE_USERNAME); Serial.println("Subscribed to status.to topic."); // Say Hi. publishTinamousStatus("Hello! Usb switch is now connected. @ me with help for help."); was_connected =true; return true;} // =================================================// Loop for mqtt processing.// =================================================void mqttLoop() { // Call anyway, does nothing if already connected. connectToMqttServer(); mqttClient.loop(); }// =================================================// Publish a status message on the Tinamous timeline// =================================================void publishTinamousStatus(String message) { Serial.println("Status:" + message); mqttClient.publish("/Tinamous/V1/Status", message); }// =================================================// Publish measurements using the plain json format// =================================================void publishTinamousJsonMeasurements(String json) { Serial.println("Measurement:" + json); mqttClient.publish("/Tinamous/V1/Measurements/Json", json); }// =================================================// Publish measurements using senml json format// =================================================void publishTinamousSenMLMeasurements(String senml) { Serial.println("SenML Measurement:" + senml); mqttClient.publish("/Tinamous/V1/Measurements/SenML", senml); if (mqttClient.lastError() !=0) { Serial.print("MQTT Error:"); Serial.print(mqttClient.lastError()); Serial.println(); } Serial.println("Done.");}// =================================================// Message received from the MQTT server// =================================================void messageReceived(String &topic, String &payload) { Serial.println("Message from Tinamous on topic:" + topic + " - " + payload); // If it starts with @ it's a status message to this device. if (payload.startsWith("@")) { payload.toLowerCase(); if (handleStatusMessage(payload)) { Serial.println("@ me status message handled."); Rückkehr; } } // Didn't get an expected command, so the message was to us. // Publish a help message. publishTinamousStatus("Hello! Sorry I didn't understand the message. @ me with help for help.");} // =================================================// Message was a Status Post (probably Alexa)// =================================================bool handleStatusMessage(String payload) {char buffer[25]; // for 1..4 (maps to 0..3) for (int port =0; port  0) { Serial.print("Turn on port "); Serial.println(port); setUsb(port, true); return true; } sprintf(buffer, "turn off port-%01d", port + 1); if (payload.indexOf(buffer)> 0) { Serial.print("Turn off port "); Serial.println(port); setUsb(port, false); return true; } } // No port specified, turn on all. if (payload.indexOf("turn on")> 0) { allOn(); return true; } if (payload.indexOf("turn off")> 0) { allOff(); return true; } if (payload.indexOf("help")> 0) { Serial.println("Sending help..."); publishTinamousStatus( "Send a message to me (@" DEVICE_USERNAME ") then:" "'Turn on Port-1' to turn on usb port 1," "'Turn off Port-1' to turn off usb port 1," "'Turn on' to turn on all usb ports," "'Turn off' to turn off all usb ports," " \n* Port number can be 1, 2, 3 or 4." ); return true; } Serial.print("Unknown status message:"); Serial.println(payload); return false;}
UsbControl.inoArduino
This file is responsible for the iterations with the USB power switching.
// ======================================// USB Port power control// and indication.// ======================================// Determine if one or more of the ports is poweredbool hasPoweredPorts() { for (int channel =0; channel  
WiFiClient.inoArduino
This file deals with WiFi Connectivity
// ======================================// WiFi handling// ======================================#include "Secrets.h" char ssid[] =SECRET_SSID; char pass[] =SECRET_PASS; int status =WL_IDLE_STATUS; void setupWiFi() { Serial.println("Connecting to WiFi..."); // check for the presence of the shield:if (WiFi.status() ==WL_NO_SHIELD) { Serial.println("WiFi shield not present"); // don't continue:while (true); } // attempt to connect to WiFi network:while ( status !=WL_CONNECTED) { Serial.print("Attempting to connect to WPA SSID:"); Serial.println (ssid); // Connect to WPA/WPA2 network:status =WiFi.begin(ssid, pass); // 10 Sekunden auf Verbindung warten:delay(10000); } // you're connected now, so print out the data:Serial.println("You're connected to the network"); printCurrentNet(); printWiFiData();}// ---------------------------------------// WiFivoid printWiFiData() { // print your WiFi shield's IP address:IPAddress ip =WiFi.localIP(); Serial.print ("IP-Adresse:"); Serial.println (ip); Serial.println (ip); // print your MAC address:byte mac[6]; WiFi.macAddress(mac); Serial.print("MAC address:"); Serial.print(mac[5], HEX); Serial.print(":"); Serial.print(mac[4], HEX); Serial.print(":"); Serial.print(mac[3], HEX); Serial.print(":"); Serial.print(mac[2], HEX); Serial.print(":"); Serial.print(mac[1], HEX); Serial.print(":"); Serial.println(mac[0], HEX);}void printCurrentNet() { // print the SSID of the network you're attached to:Serial.print("SSID:"); Serial.println(WiFi.SSID()); // print the MAC address of the router you're attached to:byte bssid[6]; WiFi.BSSID(bssid); Serial.print("BSSID:"); Serial.print(bssid[5], HEX); Serial.print(":"); Serial.print(bssid[4], HEX); Serial.print(":"); Serial.print(bssid[3], HEX); Serial.print(":"); Serial.print(bssid[2], HEX); Serial.print(":"); Serial.print(bssid[1], HEX); Serial.print(":"); Serial.println(bssid[0], HEX); // print the received signal strength:long rssi =WiFi.RSSI(); Serial.print("signal strength (RSSI):"); Serial.println(rssi); // print the encryption type:byte encryption =WiFi.encryptionType(); Serial.print("Encryption Type:"); Serial.println(encryption, HEX); Serial.println();}String hostName ="www.google.com";void doPing() { Serial.print("Pinging "); Serial.print(hostName); Serial.print(":"); int pingResult =WiFi.ping(hostName); if (pingResult>=0) { Serial.print("SUCCESS! RTT ="); Serial.print(pingResult); Serial.println(" ms"); } else { Serial.print("FAILED! Error code:"); Serial.println(pingResult); }} void reconnectWiFi() { // attempt to reconnect to WiFi network if the connection was lost:while ( status !=WL_CONNECTED) { Serial.print("Attempting to connect to WPA SSID:"); Serial.println (ssid); // Connect to WPA/WPA2 network:status =WiFi.begin(ssid, pass); if (status ==WL_CONNECTED) { Serial.print("You're re-connected to the network"); printCurrentNet(); printWiFiData(); Rückkehr; } delay(5000); } }
Secrets.hArduino
You need to update this with your own settings.
#define SECRET_SSID ""#define SECRET_PASS ""/************************* Tinamous MQTT Setup *********************************/#define MQTT_SERVER ".tinamous.com"#define MQTT_SERVERPORT 8883 #define MQTT_USERNAME "."#define MQTT_PASSWORD "The devices password"#define MQTT_CLIENT_ID "A random client id"#define DEVICE_USERNAME ""

Kundenspezifische Teile und Gehäuse

This is the best bet if you don't know how you'll connect. It's got holes for the Arduino, terminal block and additional USB micro.This is the all connectors version, but doesn't include the first layers of text which some printers may struggle with.This is the simplest version and quickest to print.

Schaltpläne

Send this off to OSHPark or DirtyPCBs to get your own one made. arduinostandaloneusbswitch-4port_q16AoF01Aq.brd arduinostandaloneusbswitch-v2_Xd45dtjndI.sch
GitHub USB Power Switcher Repository
You want:Arduino/StandAlone/ folder and the 4 port version.https://github.com/ThingySticks/USBPowerSwitcher

Herstellungsprozess

  1. C#-switch-Anweisung
  2. Akkuladegeräte bieten eine höhere Leistungsdichte und schnelleres Laden
  3. Stromausfallsensor
  4. Raspberry Pi/Hologramm SMS-gesteuerter Netzschalter
  5. Windkraft
  6. Leitfaden für Power Hammers
  7. Was ist eine automatische Kraftpresse?
  8. Was ist ein Powerchuck?
  9. Eine Kurzanleitung zu Power Chucks
  10. Wasserkraft verstehen