adding timer test
This commit is contained in:
parent
fe5a0c8cce
commit
6456944767
5 changed files with 166 additions and 16 deletions
161
firmware-arduino/test/timer_test.cpp
Normal file
161
firmware-arduino/test/timer_test.cpp
Normal file
|
|
@ -0,0 +1,161 @@
|
||||||
|
#include <WiFi.h>
|
||||||
|
#include "time.h"
|
||||||
|
#include "esp_sleep.h"
|
||||||
|
|
||||||
|
// ====== WiFi credentials ======
|
||||||
|
const char* WIFI_SSID = "556_2.4G";
|
||||||
|
const char* WIFI_PASS = "14141414";
|
||||||
|
|
||||||
|
// ====== Your LED pins ======
|
||||||
|
const int BLUE_LED_PIN = 13;
|
||||||
|
const int RED_LED_PIN = 9;
|
||||||
|
const int GREEN_LED_PIN = 8;
|
||||||
|
|
||||||
|
// ====== Schedule ======
|
||||||
|
static const int TARGET_HOUR = 11; // 11:15 local time
|
||||||
|
static const int TARGET_MINUTE = 52;
|
||||||
|
|
||||||
|
// Blink settings
|
||||||
|
static const uint32_t BLINK_DURATION_MS = 30 * 1000; // blink for 30 seconds
|
||||||
|
static const uint32_t BLINK_PERIOD_MS = 500; // 0.5s on/off
|
||||||
|
|
||||||
|
// ICT timezone (UTC+7) without DST
|
||||||
|
// This sets localtime() correctly.
|
||||||
|
static const char* TZ_ICT = "ICT-7"; // POSIX TZ format: "STDoffset" where offset is *west* of UTC.
|
||||||
|
// "ICT-7" corresponds to UTC+7.
|
||||||
|
|
||||||
|
void setAllLeds(bool on) {
|
||||||
|
digitalWrite(RED_LED_PIN, on ? HIGH : LOW);
|
||||||
|
digitalWrite(GREEN_LED_PIN, on ? HIGH : LOW);
|
||||||
|
digitalWrite(BLUE_LED_PIN, on ? HIGH : LOW);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool syncTimeWithNTP(uint32_t timeoutMs = 20000) {
|
||||||
|
// Use NTP pool; you can replace with a closer server if you want.
|
||||||
|
configTzTime(TZ_ICT, "pool.ntp.org", "time.google.com", "time.cloudflare.com");
|
||||||
|
|
||||||
|
const uint32_t start = millis();
|
||||||
|
struct tm timeinfo;
|
||||||
|
while (millis() - start < timeoutMs) {
|
||||||
|
if (getLocalTime(&timeinfo, 1000)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t secondsUntilNextTarget() {
|
||||||
|
time_t now;
|
||||||
|
time(&now);
|
||||||
|
|
||||||
|
struct tm t;
|
||||||
|
localtime_r(&now, &t);
|
||||||
|
|
||||||
|
// Build "today at 11:15"
|
||||||
|
struct tm target = t;
|
||||||
|
target.tm_hour = TARGET_HOUR;
|
||||||
|
target.tm_min = TARGET_MINUTE;
|
||||||
|
target.tm_sec = 0;
|
||||||
|
|
||||||
|
time_t targetEpoch = mktime(&target);
|
||||||
|
|
||||||
|
// If we're already past today's 11:15, schedule for tomorrow.
|
||||||
|
if (difftime(targetEpoch, now) <= 0) {
|
||||||
|
target.tm_mday += 1; // normalize via mktime
|
||||||
|
targetEpoch = mktime(&target);
|
||||||
|
}
|
||||||
|
|
||||||
|
double diff = difftime(targetEpoch, now);
|
||||||
|
if (diff < 1) diff = 1;
|
||||||
|
|
||||||
|
return (uint64_t)diff;
|
||||||
|
}
|
||||||
|
|
||||||
|
void goToSleepForSeconds(uint64_t seconds) {
|
||||||
|
// Turn off LEDs before sleeping
|
||||||
|
setAllLeds(false);
|
||||||
|
|
||||||
|
// Timer wakeup
|
||||||
|
esp_sleep_enable_timer_wakeup((uint64_t)seconds * 1000000ULL);
|
||||||
|
|
||||||
|
// Optional: reduce power (WiFi already off after disconnect)
|
||||||
|
WiFi.mode(WIFI_OFF);
|
||||||
|
btStop();
|
||||||
|
|
||||||
|
esp_deep_sleep_start();
|
||||||
|
}
|
||||||
|
|
||||||
|
void blinkRgbThenSleep() {
|
||||||
|
const uint32_t start = millis();
|
||||||
|
bool on = false;
|
||||||
|
|
||||||
|
while (millis() - start < BLINK_DURATION_MS) {
|
||||||
|
on = !on;
|
||||||
|
setAllLeds(on);
|
||||||
|
delay(BLINK_PERIOD_MS);
|
||||||
|
}
|
||||||
|
|
||||||
|
// After blinking, compute next wake time and sleep again
|
||||||
|
uint64_t secs = secondsUntilNextTarget();
|
||||||
|
goToSleepForSeconds(secs);
|
||||||
|
}
|
||||||
|
|
||||||
|
void setup() {
|
||||||
|
Serial.begin(115200);
|
||||||
|
delay(200);
|
||||||
|
|
||||||
|
pinMode(RED_LED_PIN, OUTPUT);
|
||||||
|
pinMode(GREEN_LED_PIN, OUTPUT);
|
||||||
|
pinMode(BLUE_LED_PIN, OUTPUT);
|
||||||
|
setAllLeds(false);
|
||||||
|
|
||||||
|
// Connect WiFi to sync time
|
||||||
|
WiFi.mode(WIFI_STA);
|
||||||
|
WiFi.begin(WIFI_SSID, WIFI_PASS);
|
||||||
|
|
||||||
|
Serial.print("Connecting to WiFi");
|
||||||
|
uint32_t wifiStart = millis();
|
||||||
|
while (WiFi.status() != WL_CONNECTED && millis() - wifiStart < 20000) {
|
||||||
|
delay(300);
|
||||||
|
Serial.print(".");
|
||||||
|
}
|
||||||
|
Serial.println();
|
||||||
|
|
||||||
|
if (WiFi.status() != WL_CONNECTED) {
|
||||||
|
Serial.println("WiFi failed. Sleeping 10 minutes then retrying.");
|
||||||
|
goToSleepForSeconds(10 * 60);
|
||||||
|
}
|
||||||
|
|
||||||
|
Serial.println("WiFi connected. Syncing time...");
|
||||||
|
if (!syncTimeWithNTP()) {
|
||||||
|
Serial.println("NTP sync failed. Sleeping 10 minutes then retrying.");
|
||||||
|
goToSleepForSeconds(10 * 60);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Print current local time for debugging
|
||||||
|
struct tm nowTm;
|
||||||
|
if (getLocalTime(&nowTm)) {
|
||||||
|
Serial.printf("Local time: %04d-%02d-%02d %02d:%02d:%02d\n",
|
||||||
|
nowTm.tm_year + 1900, nowTm.tm_mon + 1, nowTm.tm_mday,
|
||||||
|
nowTm.tm_hour, nowTm.tm_min, nowTm.tm_sec);
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we woke up at/near the target time, blink.
|
||||||
|
// Otherwise sleep until next 11:15.
|
||||||
|
uint64_t secs = secondsUntilNextTarget();
|
||||||
|
|
||||||
|
// If it's within ~90 seconds of 11:15, do the blink routine now.
|
||||||
|
// (This helps if wake happened a bit late/early.)
|
||||||
|
if (secs > (24ULL * 3600ULL - 90ULL) || secs < 90ULL) {
|
||||||
|
Serial.println("At/near target time. Blinking now.");
|
||||||
|
blinkRgbThenSleep();
|
||||||
|
} else {
|
||||||
|
Serial.printf("Sleeping until next %02d:%02d (in %llu seconds)\n",
|
||||||
|
TARGET_HOUR, TARGET_MINUTE, (unsigned long long)secs);
|
||||||
|
goToSleepForSeconds(secs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop() {
|
||||||
|
// Not used — ESP32 will deep sleep from setup()
|
||||||
|
}
|
||||||
|
|
@ -59,7 +59,7 @@ wss.on("connection", async (ws: WSWebSocket, payload: IPayload) => {
|
||||||
ws.send(
|
ws.send(
|
||||||
JSON.stringify({
|
JSON.stringify({
|
||||||
type: "auth",
|
type: "auth",
|
||||||
volume_control: user.device?.volume ?? 100,
|
volume_control: user.device?.volume ?? 50,
|
||||||
is_ota: user.device?.is_ota ?? false,
|
is_ota: user.device?.is_ota ?? false,
|
||||||
is_reset: user.device?.is_reset ?? false,
|
is_reset: user.device?.is_reset ?? false,
|
||||||
pitch_factor: user.personality?.pitch_factor ?? 1,
|
pitch_factor: user.personality?.pitch_factor ?? 1,
|
||||||
|
|
|
||||||
|
|
@ -83,7 +83,7 @@ export const connectToElevenLabs = async ({
|
||||||
let elevenLabsConnection: WebSocketConnection | null = null;
|
let elevenLabsConnection: WebSocketConnection | null = null;
|
||||||
let hasResponseStarted = false;
|
let hasResponseStarted = false;
|
||||||
let elevenInputSampleRate = 16000;
|
let elevenInputSampleRate = 16000;
|
||||||
let elevenOutputSampleRate = 16000;
|
let elevenOutputSampleRate = 24000;
|
||||||
|
|
||||||
// Handle messages from ESP32 ws client.
|
// Handle messages from ESP32 ws client.
|
||||||
const handleClientMessage = async (data: any, isBinary: boolean) => {
|
const handleClientMessage = async (data: any, isBinary: boolean) => {
|
||||||
|
|
@ -269,17 +269,6 @@ export const connectToElevenLabs = async ({
|
||||||
event.user_transcription_event.user_transcript,
|
event.user_transcription_event.user_transcript,
|
||||||
user,
|
user,
|
||||||
);
|
);
|
||||||
|
|
||||||
if (!hasResponseStarted) {
|
|
||||||
console.log(
|
|
||||||
"Sending RESPONSE.CREATED to ESP32 (agent audio starting)",
|
|
||||||
);
|
|
||||||
ws.send(JSON.stringify({
|
|
||||||
type: "server",
|
|
||||||
msg: "RESPONSE.CREATED",
|
|
||||||
}));
|
|
||||||
hasResponseStarted = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
@ -346,7 +335,7 @@ export const connectToElevenLabs = async ({
|
||||||
});
|
});
|
||||||
|
|
||||||
elevenLabsConnection.onDisconnect((details: DisconnectionDetails) => {
|
elevenLabsConnection.onDisconnect((details: DisconnectionDetails) => {
|
||||||
console.log("ElevenLabs connection closed:", details.reason);
|
console.log("ElevenLabs connection closed:", details);
|
||||||
opus.close();
|
opus.close();
|
||||||
ws.close();
|
ws.close();
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -226,7 +226,7 @@ export const connectToGemini = async ({
|
||||||
geminiSession?.sendRealtimeInput({
|
geminiSession?.sendRealtimeInput({
|
||||||
audio: {
|
audio: {
|
||||||
data: base64Data,
|
data: base64Data,
|
||||||
mimeType: "audio/pcm;rate=24000",
|
mimeType: "audio/pcm;rate=16000",
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -46,7 +46,7 @@ export const connectToHume = ({
|
||||||
audio: {
|
audio: {
|
||||||
encoding: "linear16",
|
encoding: "linear16",
|
||||||
channels: 1,
|
channels: 1,
|
||||||
sample_rate: 16000,
|
sample_rate: 24000,
|
||||||
},
|
},
|
||||||
system_prompt: systemPrompt,
|
system_prompt: systemPrompt,
|
||||||
}));
|
}));
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue