jhagas / ESP32-Supabase

Connect ESP32/8266 with Supabase. Enhance your IoT project with open-source database service
MIT License
32 stars 12 forks source link

Realtime support #13

Open shlomozippel opened 10 months ago

shlomozippel commented 10 months ago

The readme todo lists Implement several methods to implement [Supabase Realtime](https://supabase.com/docs/guides/realtime).

Happy to help with this effort - did you start it at all? Can you point me in the direction of the "several methods" before I dive in?

jhagas commented 10 months ago

I haven't started implementing this yet (i don't understand ws or wss enough to start it).. But i'm noticing it should be simple enough to implement that..

shlomozippel commented 10 months ago

Sounds good - I'll take a stab in the next few days

IvanRomero03 commented 8 months ago

Any updates on this?

fubr commented 5 months ago

Any updates on this?

Doesn't look like it unfortunately

shlomozippel commented 5 months ago

We ended up using mqtt as a bandaid and still haven't ported to supabase realtime so I haven't looked at this yet. Hopefully someone else picks it up

vojtavozda commented 1 month ago

Hi, I managed to successfully connect and listen to the supabase realtime.

Here is the code:


#include <Arduino.h>

#include <WiFi.h>
#include <WiFiMulti.h>
#include <WiFiClientSecure.h>

#include <WebSocketsClient.h>

// Web socket mechanism is implemented from this script:
// https://github.com/Links2004/arduinoWebSockets/blob/master/examples/esp32/WebSocketClient/WebSocketClient.ino

// This is from supabase realtime documentation:
// (https://supabase.com/docs/guides/realtime/protocol)
// I am not sure about "topic" and "ref" fields
// It was mentioned here:
// https://stackoverflow.com/questions/77696837/listening-to-database-changes-in-supabase-hosted-project-using-websocket-or-any
const char* jsonRealtimeConfig = R"({
  "event": "phx_join",
  "topic": "realtime:[channel-name]",
  "payload": {
    "config": {
      "broadcast": {
        "self": false
      },
      "presence": {
        "key": ""
      },
      "postgres_changes": [
        {
          "event": "*",
          "schema": "public",
          "table": "*"
        }
      ]
    }
  },
  "ref": "sentRef"
})";

// This is from supabase realtime documentation:
// (https://supabase.com/docs/guides/realtime/protocol)
const char* jsonRealtimeHeartbeat = R"({
  "event": "heartbeat",
  "topic": "phoenix",
  "payload": {},
  "ref": ""
})";

WiFiMulti wifi;
WebSocketsClient webSocket;

void hexdump(const void *mem, uint32_t len, uint8_t cols = 16) {
    const uint8_t* src = (const uint8_t*) mem;
    Serial.printf("\n[HEXDUMP] Address: 0x%08X len: 0x%X (%d)", (ptrdiff_t)src, len, len);
    for(uint32_t i = 0; i < len; i++) {
        if(i % cols == 0) {
            Serial.printf("\n[0x%08X] 0x%08X: ", (ptrdiff_t)src, i);
        }
        Serial.printf("%02X ", *src);
        src++;
    }
    Serial.printf("\n");
}

void webSocketEvent(WStype_t type, uint8_t * payload, size_t length) {

    switch(type) {
        case WStype_DISCONNECTED:
            Serial.printf("[WSc] Disconnected!\n");
            break;
        case WStype_CONNECTED:
            Serial.printf("[WSc] Connected to url: %s\n", payload);
            // send message to server when Connected
            webSocket.sendTXT(jsonRealtimeConfig);
            break;
        case WStype_TEXT:
            Serial.printf("[WSc] get text: %s\n", payload);

            // send message to server
            // webSocket.sendTXT("message here");
            break;
        case WStype_BIN:
            Serial.printf("[WSc] get binary length: %u\n", length);
            hexdump(payload, length);

            // send data to server
            // webSocket.sendBIN(payload, length);
            break;
        case WStype_ERROR:            
        case WStype_FRAGMENT_TEXT_START:
        case WStype_FRAGMENT_BIN_START:
        case WStype_FRAGMENT:
        case WStype_FRAGMENT_FIN:
            break;
    }

}

void setup() {
    Serial.begin(115200);
    Serial.printf("\n=====[ WiFi WebSocket test started ]=====\n\n");

    wifi.addAP("ssid", "pswd");

    Serial.printf("Connecting to wifi .");
    while(wifi.run() != WL_CONNECTED) {
        Serial.printf(".");
        delay(500);
    }
    Serial.printf(" Done!\n");

    // Server address, port and URL
    // 1st param: Enter your project URL there
    // 2nd param: I have no idea, but it does not work with others than 443
    // Port number found here: https://github.com/esp8266/Arduino/issues/1442
    // 3rd param: url containing you anon key
    webSocket.beginSSL(
        "fwvlsdafhowjbveruihu.supabase.co",
        443,
        "/realtime/v1/websocket?apikey=[your_anon_key]&vsn=1.0.0"
    );
    // If you want you can test with this one:
    // webSocket.beginSSL("echo.websocket.org",443);

    // event handler
    webSocket.onEvent(webSocketEvent);

    Serial.println("-----[ setup finished ]-----");
}

int last_ms = millis();

void loop() {

    webSocket.loop();

    if (millis()-last_ms > 30000) {
        last_ms = millis();
        Serial.println("Sending Heartbeat message");
        webSocket.sendTXT(jsonRealtimeHeartbeat);
    }

}

I hope somebody will find time to implement it.

Well, once there is a working websocket between the supabase and the client, it would be nice to do all inserts and updates etc. via that websocket. But I have no idea how and maybe this is even not possible as realtime is focused on listening.