Möchte in meiner Xamarin Forms App einen Shelly 1 Pro per Url ansprechen.
Seit der Pro Version wird eine Digest Authentifizierung benötigt ansonsten ist der Shelly ungeschützt.
Wenn ich die Authentifizierung ausschalte funktioniert der nachfolgende Code:
private void LmuButton(object sender, EventArgs e)
{
HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create("http://192.168.10.68/relay/0?turn=on");
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
}
Die Doko vom Shelly beinhaltet JavaScript Code die ich bisher leider nicht richtig in c# übersetzen kann.
https://shelly-api-docs.shelly.cloud/gen2/Overview/CommonDeviceTraits/#authentication
Hier Ausschnitte aus der Doku
Schritte im Prozess:
Der Client fordert eine geschützte Ressource an, ohne Anmeldeinformationen bereitzustellen.
Eine Serverantwort mit Fehler 401 (nicht autorisiert) wird empfangen.
Der Client fordert dieselbe geschützte Ressource an, gibt aber diesmal Anmeldeinformationen an.
Die Anforderung ist erfolgreich und der Zugriff auf die Ressource wird gewährt.
Bei der Kommunikation über HTTP muss dieser Vorgang für jede Anfrage wiederholt werden, die Sie an das Gerät senden. Für die Kommunikation über Websocket müssen die Schritte 1 und 2 jedoch nicht mehr als einmal durchlaufen werden: Sie müssen das authObjekt nur einmal erstellen (mehr dazu weiter unten ) und es dann für alle aufeinanderfolgenden Anforderungen an dieses Gerät verwenden.
Authentifizierung über
Bei der Kommunikation über einen HTTP-Kanal finden Sie diese Informationen im WWW-Authenticate- Header der Antwort.
Beispiel:
Anfrage
curl -X POST -i -d '{"id":1, "method":"Shelly.GetStatus"}' http://${SHELLY}/rpc
Antwort
HTTP/1.1 401 Unauthorized
Server: Mongoose/6.18
Content-Type: application/json
Access-Control-Allow-Origin: *
Access-Control-Allow-Headers: *
Content-Length: 0
Connection: close
WWW-Authenticate: Digest qop="auth", realm="shellypro4pm-f008d1d8b8b8", nonce="60dc59c6", algorithm=SHA-256
Authentifizierung über
Bei der Kommunikation über einen Websocket-Kanal enthält die Antwort einen Fehlerrahmen, in dem die oben genannten Attribute zu finden sind.
Beispiel:
Anfrage
curl -X POST -d '{"id":1, "method":"Shelly.DetectLocation"}' http://${SHELLY}/rpc
Antwort
{
"id": 1,
"src": "shellypro4pm-f008d1d8b8b8",
"dst": "user_1",
"error": {
"code": 401,
"message": "{\"auth_type\": \"digest\", \"nonce\": 1625038762, \"nc\": 1, \"realm\": \"shellypro4pm-f008d1d8b8b8\", \"algorithm\": \"SHA-256\"}"
}
}
Erfolgreiche Anfrage mit
Damit die Anfrage richtig funktioniert, authsollte dem Anfragerahmen ein zusätzliches JSON-Objekt hinzugefügt werden. Es sollte enthalten:
realm: string, device_id des Shelly-Geräts. Erforderlich
username: string, muss auf admin gesetzt werden . Erforderlich
nonce: Zahl, Zufalls- oder Pseudo-Zufallszahl zur Verhinderung von Replay-Angriffen, entnommen aus der Fehlermeldung. Erforderlich
cnonce: Nummer, Client-Nonce, vom Client generierte Zufallszahl. Erforderlich
response: string, Kodierung des Strings <ha1> + ":" + <nonce> + ":" + <nc> + ":" + <cnonce> + ":" + "auth" + ":" + <ha2>in SHA256. Erforderlich
ha1: Zeichenfolge, <user>:<realm>:<password>codiert in SHA256
ha2: string, "dummy_method:dummy_uri" codiert in SHA256
algorithm: Zeichenkette, SHA-256 . Erforderlich
Beispiel:
Anfrage1
curl -X POST -d '{"id":1, "method":"Shelly.DetectLocation", "auth":
{"realm": "shellypro4pm-f008d1d8b8b8", "username": "admin", "nonce": 1625038762,
"cnonce": 313273957, "response": "eab75cbbd7acdb7082164cb52148cfbe351f28bf80856f93a23387c6157dbb69",
"algorithm": "SHA-256"}}' \
http://${SHELLY}/rpc
Oder:
Anfrage2
curl --digest -u admin:mypass http://${SHELLY}/rpc/Shelly.DetectLocation
Oder:
Anfrage3
curl --anyauth -u admin:mypass -X POST -d '{"id":1, "method":"Shelly.DetectLocation"}' http://${SHELLY}/rpc
Antwort
{
"id": 1,
"src": "shellypro4pm-f008d1d8b8b8",
"dst": "user_1",
"result": {
"tz": "Europe/Sofia",
"lat": 42.67236,
"lon": 23.38738
}
}
Ich hoffe mir kann einer weiterhelfen?
Viele Grüße
Christoph