various fixes, improvements, documentation

This commit is contained in:
Franzi 2021-12-12 14:22:30 +01:00
parent 300ca56d3b
commit 3818e5b6c3
Signed by: kunsi
GPG key ID: 12E3D2136B818350
4 changed files with 179 additions and 55 deletions

View file

@ -1,20 +1,11 @@
#define LED_COUNT 10
#define LED_BRIGHTNESS 100
#define LED_PIN 12
#include <config.h>
#define WIFI_SSID ""
#define WIFI_PASS ""
#define OBS_HOST ""
#define OBS_PORT 4444
//#define OBS_PASS ""
#define OBS_SOURCE "ATEM"
static_assert(sizeof(WIFI_SSID) > 1, "WIFI_SSID is empty");
static_assert(sizeof(OBS_HOST) > 1, "OBS_HOST is empty");
static_assert(sizeof(OBS_SOURCE) > 1, "OBS_SOURCE is empty");
#define FASTLED_ESP8266_RAW_PIN_ORDER
// END CONFIGURATION
#include <Arduino.h>
#include <Hash.h>
#include <ESP8266WiFi.h>
@ -27,6 +18,8 @@ CRGB leds[LED_COUNT];
WebSocketsClient webSocket;
#ifdef OBS_PASS
static_assert(sizeof(OBS_PASS) > 1, "OBS_PASS must be non-empty if defined");
#include <SHA256.h>
#define HASH_SIZE 32
@ -35,6 +28,7 @@ SHA256 sha256;
bool is_currently_live = false;
bool is_currently_preview = false;
bool is_currently_connected = false;
void set_program() {
Serial.println("[Tally] PROGRAM");
@ -73,23 +67,19 @@ void handleWebSocketEvent(WStype_t type, uint8_t * payload, size_t length) {
We can't set the LEDs to "error", because if someone
quits OBS, we will get disconnected.
*/
is_currently_connected = false;
break;
case WStype_CONNECTED:
Serial.printf("[WS] connected to %s\n", payload);
#ifdef OBS_PASS
// Find out if we need authentication
webSocket.sendTXT("{\"request-type\":\"GetAuthRequired\",\"message-id\":\"1\"}");
#else
webSocket.sendTXT("{\"request-type\":\"GetCurrentScene\",\"message-id\":\"3\"}");
webSocket.sendTXT("{\"request-type\":\"GetPreviewScene\",\"message-id\":\"4\"}");
#endif
break;
case WStype_TEXT: {
Serial.printf("[WS] %s\n", payload);
StaticJsonDocument<5000> doc;
StaticJsonDocument<10000> doc;
DeserializationError error = deserializeJson(doc, payload);
if (error) {
@ -98,59 +88,77 @@ void handleWebSocketEvent(WStype_t type, uint8_t * payload, size_t length) {
break;
}
#ifdef OBS_PASS
if (doc.containsKey("authRequired")) {
Serial.println("[OBS] auth requested");
if (doc["authRequired"]) {
#ifdef OBS_PASS
Serial.println("[OBS] auth requested");
sha256.reset();
sha256.update(OBS_PASS, strlen(OBS_PASS));
const char* salt = doc["salt"];
sha256.update(salt, strlen(salt));
char value[HASH_SIZE];
sha256.finalize(value, HASH_SIZE);
sha256.reset();
sha256.update(OBS_PASS, strlen(OBS_PASS));
const char* salt = doc["salt"];
sha256.update(salt, strlen(salt));
char value[HASH_SIZE];
sha256.finalize(value, HASH_SIZE);
Serial.print("[OBS] sha256 authentication hash is: ");
for (size_t i = 0; i < HASH_SIZE; i++) {
Serial.print(static_cast<unsigned int>(value[i]), HEX);
Serial.print("[OBS] sha256 authentication hash is: ");
for (size_t i = 0; i < HASH_SIZE; i++) {
Serial.print(static_cast<unsigned int>(value[i]), HEX);
}
Serial.println();
int encodedLength = Base64.encodedLength(HASH_SIZE);
char encodedPassSaltHash[encodedLength];
Base64.encode(encodedPassSaltHash, value, HASH_SIZE);
const char* challenge = doc["challenge"];
sha256.reset();
sha256.update(encodedPassSaltHash, encodedLength);
sha256.update(challenge, strlen(challenge));
sha256.finalize(value, HASH_SIZE);
Serial.print("[OBS] sha256 challenge hash is: ");
for (size_t i = 0; i < HASH_SIZE; i++) {
Serial.print(static_cast<unsigned int>(value[i]), HEX);
}
Serial.println();
char encodedAuthString[encodedLength];
Base64.encode(encodedAuthString, value, HASH_SIZE);
String authRequest = String("{\"request-type\":\"Authenticate\",\"message-id\":\"2\",\"auth\":\"") + encodedAuthString + "\"}";
webSocket.sendTXT(authRequest);
#else
Serial.println("[OBS] auth requested, but not configured!");
set_error();
delay(10000);
ESP.restart();
#endif
} else {
#ifdef OBS_PASS
Serial.println("[OBS] auth configured, but not needed");
#endif
webSocket.sendTXT("{\"request-type\":\"GetCurrentScene\",\"message-id\":\"3\"}");
webSocket.sendTXT("{\"request-type\":\"GetPreviewScene\",\"message-id\":\"4\"}");
is_currently_connected = true;
}
Serial.println();
int encodedLength = Base64.encodedLength(HASH_SIZE);
char encodedPassSaltHash[encodedLength];
Base64.encode(encodedPassSaltHash, value, HASH_SIZE);
const char* challenge = doc["challenge"];
sha256.reset();
sha256.update(encodedPassSaltHash, encodedLength);
sha256.update(challenge, strlen(challenge));
sha256.finalize(value, HASH_SIZE);
Serial.print("[OBS] sha256 challenge hash is: ");
for (size_t i = 0; i < HASH_SIZE; i++) {
Serial.print(static_cast<unsigned int>(value[i]), HEX);
}
Serial.println();
char encodedAuthString[encodedLength];
Base64.encode(encodedAuthString, value, HASH_SIZE);
String authRequest = String("{\"request-type\":\"Authenticate\",\"message-id\":\"2\",\"auth\":\"") + encodedAuthString + "\"}";
webSocket.sendTXT(authRequest);
break;
#ifdef OBS_PASS
} else if (doc.containsKey("message-id") && doc["message-id"] == "2") {
if (strcmp(doc["status"], "ok") == 0) {
Serial.println("[OBS] authentication successful");
webSocket.sendTXT("{\"request-type\":\"GetCurrentScene\",\"message-id\":\"3\"}");
webSocket.sendTXT("{\"request-type\":\"GetPreviewScene\",\"message-id\":\"4\"}");
is_currently_connected = true;
} else {
Serial.println("[OBS] authentication FAILED");
set_error();
delay(10000);
ESP.restart();
}
break;
}
#endif
if (doc.containsKey("sources")) {
} else if (doc.containsKey("sources")) {
bool my_source_in_current_event = false;
for (uint8_t i = 0; i < doc["sources"].size(); i++) {
@ -180,6 +188,7 @@ void handleWebSocketEvent(WStype_t type, uint8_t * payload, size_t length) {
Serial.println("[OBS] quit");
is_currently_preview = false;
is_currently_live = false;
is_currently_connected = false;
} else if (strcmp(doc["update-type"], "StudioModeSwitched") == 0 && !doc["new-state"]) {
Serial.println("[OBS] studio mode disabled");
is_currently_preview = false;
@ -210,6 +219,14 @@ void handleWebSocketEvent(WStype_t type, uint8_t * payload, size_t length) {
case WStype_FRAGMENT_FIN:
break;
}
#ifdef STATUS_LED
if (is_currently_connected) {
digitalWrite(STATUS_LED, LOW);
} else {
digitalWrite(STATUS_LED, HIGH);
}
#endif
}
void setup() {
@ -220,6 +237,10 @@ void setup() {
FastLED.addLeds<WS2812B, LED_PIN, GRB>(leds, LED_COUNT);
FastLED.setBrightness(LED_BRIGHTNESS);
#ifdef STATUS_LED
pinMode(STATUS_LED, OUTPUT);
#endif
set_error();
delay(100);
set_idle();