File events.h¶
File List > espos_voice > include > espos_voice > protocol > events.h
Go to the documentation of this file
/* SPDX-FileCopyrightText: 2026 Dirk Wahrheit */
/* SPDX-License-Identifier: Apache-2.0 */
#pragma once
// Wyoming protocol events the satellite cares about — builders for the
// events we SEND and light parsers for the fields we READ. Mirrors
// signalk-wyoming/src/protocol/events.ts, but only the subset a satellite
// needs (the orchestrator implements the rest).
//
// `width` is BYTES per sample (2 = 16-bit signed little-endian PCM).
#include <cstddef>
#include <cstdint>
#include <string>
#include <vector>
#include "espos_voice/protocol/framing.h"
namespace espos_voice {
struct AudioFormat {
uint32_t rate = 16000;
uint8_t width = 2;
uint8_t channels = 1;
bool valid() const { return rate > 0 && width > 0 && channels > 0; }
};
// What this satellite advertises in its `info` reply to `describe`.
struct SatelliteInfo {
std::string name = "espos"; // overridden from WyomingSatelliteConfig::name
AudioFormat mic_format; // capture format we can stream (Phase 2)
AudioFormat snd_format; // playback format we expect in audio-start
bool supports_trigger = true; // orchestrator may trigger a pipeline
// active_wake_words stays empty until Phase 3.
};
// ---- Builders: append the encoded event to `out` -------------------------
// `info` reply. Seven program lists are all present (asr/tts/handle/intent/
// wake empty; mic + snd advertise our formats); plus a satellite artifact.
void build_info(std::vector<uint8_t>& out, const SatelliteInfo& info);
// `pong` — echoes the ping's optional text (pass "" for none).
void build_pong(std::vector<uint8_t>& out, const std::string& text);
// `played` — playback of an audio-start..audio-stop span finished.
void build_played(std::vector<uint8_t>& out);
// ---- Voice-in (push-to-talk) builders ------------------------------------
// `run-pipeline` — ask the orchestrator to run asr..tts on the audio we're
// about to stream. `name` identifies this satellite.
void build_run_pipeline(std::vector<uint8_t>& out, const std::string& name);
// `audio-start` / `audio-chunk` / `audio-stop` for the OUTBOUND mic stream.
void build_audio_start(std::vector<uint8_t>& out, const AudioFormat& fmt);
void build_audio_chunk(std::vector<uint8_t>& out, const AudioFormat& fmt,
const int16_t* samples, size_t frames);
void build_audio_stop(std::vector<uint8_t>& out);
// ---- Wake-word detection builders (satellite -> wake service) ------------
// `detect` — arm the wake service for the given word names (empty = any).
// Sent once after connecting to the wake service, before streaming mic audio.
void build_detect(std::vector<uint8_t>& out,
const std::vector<std::string>& names);
// ---- Parsers: pull the fields we need from a DecodedEvent ----------------
// Parse a `transcript` event's text. Returns false if not a transcript.
bool parse_transcript(const DecodedEvent& ev, std::string* text);
// Parse a `detection` event's wake-word name (empty if the field is absent).
// Returns false if the event isn't a detection.
bool parse_detection(const DecodedEvent& ev, std::string* name);
// Parse an audio-start's format. Returns false if the event isn't
// audio-start or the format is unusable.
bool parse_audio_start(const DecodedEvent& ev, AudioFormat* out);
// Extract the optional `text` field of a ping (empty if absent).
std::string parse_ping_text(const DecodedEvent& ev);
} // namespace espos_voice