From e85e210ad6565f4e1f81c19c6f1eb3967fb45ef3 Mon Sep 17 00:00:00 2001 From: akdeb Date: Mon, 21 Apr 2025 12:32:39 +0100 Subject: [PATCH] updating readme --- README.md | 28 ++++++++++++++--- firmware-arduino/README.md | 2 +- firmware-arduino/src/Config.cpp | 4 +-- firmware-arduino/src/Config.h | 2 +- frontend-nextjs/app/components/Footer.tsx | 17 +--------- frontend-nextjs/app/page.tsx | 2 +- server-deno/.env.example | 2 +- server-deno/utils.ts | 38 ++++++++++++++--------- 8 files changed, 54 insertions(+), 41 deletions(-) diff --git a/README.md b/README.md index c3886a3..a605ccd 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ Realtime AI Speech powered by OpenAI Realtime API, ESP32, Secure WebSockets, and
[![Discord Follow](https://dcbadge.vercel.app/api/server/KJWxDPBRUj?style=flat)](https://discord.gg/KJWxDPBRUj) -[![License: GPLv3](https://img.shields.io/badge/license-MIT-blue)](https://www.gnu.org/licenses/gpl-3.0.en.html)    +[![License: MIT](https://img.shields.io/badge/license-MIT-blue)](https://www.gnu.org/licenses/gpl-3.0.en.html)    ![Node.js](https://img.shields.io/badge/Node.js-22.13.0-yellow.svg) ![Next.js](https://img.shields.io/badge/Next.js-14.2.7-brightgreen.svg) ![React](https://img.shields.io/badge/React-18.2.0-blue.svg) @@ -25,8 +25,9 @@ https://github.com/user-attachments/assets/aa60e54c-5847-4a68-80b5-5d6b1a5b9328 ## Getting Started -1. Set up your Local Supabase Backend. From the root directory, run: +1. Install [Supabase CLI](https://supabase.com/docs/guides/local-development/cli/getting-started) and set up your Local Supabase Backend. From the root directory, run: ```bash +brew install supabase/tap/supabase supabase start # Starts your local Supabase server with the default migrations and seed data. ``` @@ -34,10 +35,18 @@ supabase start # Starts your local Supabase server with the default migrations a ```bash cd frontend-nextjs npm install + +# Set your environment variables +cp .env.example .env.local +# NEXT_PUBLIC_SUPABASE_URL=http://127.0.0.1:54321 +# NEXT_PUBLIC_SUPABASE_ANON_KEY= +# OPENAI_API_KEY= + +# Run the development server npm run dev ``` -3. Add your ESP32-S3 Device MAC Address to the Settings page in the NextJS Frontend. This links your device to your account. +3. Add your ESP32-S3 Device MAC Address to the [Settings page](http://localhost:3000/home/settings) in the NextJS Frontend. This links your device to your account. To find your ESP32-S3 Device's MAC Address, build and upload `test/print_mac_address_test.cpp` using PlatformIO. 4. Add your OpenAI API Key in the `server-deno/.env` and `frontend-nextjs/.env.local` file. @@ -47,16 +56,27 @@ OPENAI_API_KEY= 5. Start the Deno server. ([See the Deno server README](server-deno/README.md)) ```bash +# Navigate to the server directory cd server-deno + +# Set your environment variables +cp .env.example .env +# NEXT_PUBLIC_SUPABASE_URL=http://127.0.0.1:54321 +# NEXT_PUBLIC_SUPABASE_ANON_KEY= +# OPENAI_API_KEY= + +# Run the server at port 8000 deno run -A --env-file=.env main.ts ``` 5. Set up your ESP32 Arduino Client. ([See the ESP32 README](firmware-arduino/README.md)) On PlatformIO, first `Build` the project, then `Upload` the project to your ESP32. -6. The ESP32 should open an AP `ELATO-DEVICE` to connect to Wifi. Connect to it and go to `http://192.168.4.1` to configure the device. +6. The ESP32 should open an AP `ELATO-DEVICE` to connect to Wifi. Connect to it and go to `http://192.168.4.1` to configure the device wifi. 7. Once your Wifi is configured, turn the device off and on again and it should connect to your Wifi and the Deno edge server. +8. Now you can talk to your AI Character! + ## 📌 Project Architecture ElatoAI consists of three main components: diff --git a/firmware-arduino/README.md b/firmware-arduino/README.md index 4d434a0..0c000dd 100644 --- a/firmware-arduino/README.md +++ b/firmware-arduino/README.md @@ -36,7 +36,7 @@ This firmware turns your ESP32 device into a WebSocket audio client for Elato, e 1. Install Visual Studio Code and the PlatformIO extension 2. Clone this repository -3. Open the project folder in PlatformIO +3. Open the project folder in PlatformIO. `Open > Open Project > firmware-arduino` 4. Edit `src/Config.cpp` with your server details: - If using locally: Set your computer's IP address in `ws_server` and `backend_server` - If using production: Ensure proper certificates are set diff --git a/firmware-arduino/src/Config.cpp b/firmware-arduino/src/Config.cpp index 2d4a8fd..6c879bf 100644 --- a/firmware-arduino/src/Config.cpp +++ b/firmware-arduino/src/Config.cpp @@ -27,11 +27,11 @@ bool factory_reset_status = false; */ #ifdef DEV_MODE -const char *ws_server = "10.2.1.187"; +const char *ws_server = "10.2.1.136"; const uint16_t ws_port = 8000; const char *ws_path = "/"; // Backend server details -const char *backend_server = "10.2.1.187"; +const char *backend_server = "10.2.1.136"; const uint16_t backend_port = 3000; #else diff --git a/firmware-arduino/src/Config.h b/firmware-arduino/src/Config.h index 52384eb..902ed46 100644 --- a/firmware-arduino/src/Config.h +++ b/firmware-arduino/src/Config.h @@ -58,7 +58,7 @@ extern const uint16_t backend_port; extern const uint32_t SAMPLE_RATE; // ---------- Development ------------ -// #define DEV_MODE +#define DEV_MODE #define TOUCH_MODE // ----------------- Pin Definitions ----------------- diff --git a/frontend-nextjs/app/components/Footer.tsx b/frontend-nextjs/app/components/Footer.tsx index 787ea0d..83e3965 100644 --- a/frontend-nextjs/app/components/Footer.tsx +++ b/frontend-nextjs/app/components/Footer.tsx @@ -38,8 +38,7 @@ export default function Footer() {
{/* */} @@ -77,20 +76,6 @@ export default function Footer() { - - - Privacy Policy - - - - Terms of Service - {/* */} diff --git a/frontend-nextjs/app/page.tsx b/frontend-nextjs/app/page.tsx index 91651c4..d9f5e7e 100644 --- a/frontend-nextjs/app/page.tsx +++ b/frontend-nextjs/app/page.tsx @@ -97,7 +97,7 @@ export default async function LandingPage() { Arduino - Espressif ESP32 + Espressif ESP32 PlatformIO diff --git a/server-deno/.env.example b/server-deno/.env.example index 37db8cf..dfd3254 100644 --- a/server-deno/.env.example +++ b/server-deno/.env.example @@ -1,7 +1,7 @@ # Supabase keys SUPABASE_URL= SUPABASE_KEY= -JWT_SECRET= +JWT_SECRET=super-secret-jwt-token-with-at-least-32-characters-long # Encryption Key (useful for encrypting secrets in the database) ENCRYPTION_KEY= diff --git a/server-deno/utils.ts b/server-deno/utils.ts index f6fad50..dc6adbf 100644 --- a/server-deno/utils.ts +++ b/server-deno/utils.ts @@ -1,25 +1,27 @@ -import * as jose from 'https://deno.land/x/jose@v5.9.6/index.ts'; -import { getUserByEmail } from './supabase.ts'; -import { SupabaseClient } from '@supabase/supabase-js'; -import crypto from 'node:crypto'; -import { Buffer } from 'node:buffer'; +import * as jose from "https://deno.land/x/jose@v5.9.6/index.ts"; +import { getUserByEmail } from "./supabase.ts"; +import { SupabaseClient } from "@supabase/supabase-js"; +import crypto from "node:crypto"; +import { Buffer } from "node:buffer"; export const authenticateUser = async ( supabaseClient: SupabaseClient, authToken: string, ): Promise => { try { - const jwtSecret = Deno.env.get('JWT_SECRET'); + const jwtSecret = Deno.env.get("JWT_SECRET"); + console.log("jwtSecret", jwtSecret); - if (!jwtSecret) throw new Error('JWT_SECRET not configured'); + if (!jwtSecret) throw new Error("JWT_SECRET not configured"); const secretBytes = new TextEncoder().encode(jwtSecret); const payload = await jose.jwtVerify(authToken, secretBytes); const { payload: { email } } = payload; const user = await getUserByEmail(supabaseClient, email as string); + console.log("user", user); return user; } catch (error: any) { - throw new Error(error.message || 'Failed to authenticate user'); + throw new Error(error.message || "Failed to authenticate user"); } }; @@ -30,20 +32,26 @@ export const authenticateUser = async ( * @param masterKey - 32-byte string or buffer * @returns the original plaintext secret */ -export function decryptSecret(encryptedData: string, iv: string, masterKey: string) { +export function decryptSecret( + encryptedData: string, + iv: string, + masterKey: string, +) { // Decode the base64 master key - const decodedKey = Buffer.from(masterKey, 'base64'); + const decodedKey = Buffer.from(masterKey, "base64"); if (decodedKey.length !== 32) { - throw new Error('ENCRYPTION_KEY must be 32 bytes when decoded from base64.'); + throw new Error( + "ENCRYPTION_KEY must be 32 bytes when decoded from base64.", + ); } const decipher = crypto.createDecipheriv( - 'aes-256-cbc', + "aes-256-cbc", decodedKey, // Use the decoded key instead of raw masterKey - Buffer.from(iv, 'base64'), + Buffer.from(iv, "base64"), ); - let decrypted = decipher.update(encryptedData, 'base64', 'utf8'); - decrypted += decipher.final('utf8'); + let decrypted = decipher.update(encryptedData, "base64", "utf8"); + decrypted += decipher.final("utf8"); return decrypted; }