636 lines
24 KiB
C
636 lines
24 KiB
C
/*
|
|
* SPDX-FileCopyrightText: 2024-2026 Espressif Systems (Shanghai) CO LTD
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
#include <stdbool.h>
|
|
#include <stddef.h>
|
|
#include <stdint.h>
|
|
#include "esp_err.h"
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
typedef struct {
|
|
float initial_angle;
|
|
int rotate_speed_us;
|
|
} domain_direction_axis_config_t;
|
|
|
|
typedef struct {
|
|
bool enabled;
|
|
float calibration_angle;
|
|
float step_angle_deg;
|
|
float max_sweep_deg;
|
|
bool search_clockwise;
|
|
int settle_delay_ms;
|
|
} domain_direction_calibration_t;
|
|
|
|
typedef enum {
|
|
DOMAIN_BATTERY_CHARGE_UNKNOWN = 0,
|
|
DOMAIN_BATTERY_CHARGE_NOT_CHARGING,
|
|
DOMAIN_BATTERY_CHARGE_CHARGING,
|
|
} domain_battery_charge_state_t;
|
|
|
|
typedef enum {
|
|
DOMAIN_BATTERY_LEVEL_UNKNOWN = 0,
|
|
DOMAIN_BATTERY_LEVEL_NORMAL,
|
|
DOMAIN_BATTERY_LEVEL_LOW,
|
|
DOMAIN_BATTERY_LEVEL_CRITICAL,
|
|
} domain_battery_level_state_t;
|
|
|
|
typedef struct {
|
|
int voltage_mv;
|
|
int latest_adc_mv;
|
|
int latest_sample_mv;
|
|
uint8_t percentage;
|
|
domain_battery_charge_state_t charge_state;
|
|
domain_battery_level_state_t level_state;
|
|
bool valid;
|
|
bool latest_sample_valid;
|
|
bool measurement_suppressed;
|
|
bool high_load_active;
|
|
bool cooldown_active;
|
|
uint32_t consecutive_failures;
|
|
int64_t last_valid_sample_time_ms;
|
|
} domain_battery_status_t;
|
|
|
|
/** Initialize the battery measurement domain. Idempotent and thread-safe. */
|
|
esp_err_t domain_battery_init(void);
|
|
|
|
/** Acquire and process one battery sample without applying product policy. */
|
|
esp_err_t domain_battery_sample(void);
|
|
|
|
/** Copy the latest battery SSOT snapshot into `out_status`. */
|
|
esp_err_t domain_battery_get_status(domain_battery_status_t *out_status);
|
|
|
|
/** Reserved policy hook; this release intentionally performs no shutdown. */
|
|
esp_err_t domain_battery_prepare_shutdown(void);
|
|
|
|
typedef enum {
|
|
DOMAIN_WIFI_PROMPT_WIFI_SUCCESS = 0,
|
|
DOMAIN_WIFI_PROMPT_AFTER_WIFI_SUCCESS,
|
|
DOMAIN_WIFI_PROMPT_WIFI_CONNECTING,
|
|
DOMAIN_WIFI_PROMPT_WIFI_FAILED,
|
|
DOMAIN_WIFI_PROMPT_WIFI_CONFIG,
|
|
} domain_wifi_prompt_id_t;
|
|
|
|
typedef struct {
|
|
void (*set_keep_awake)(bool keep_awake);
|
|
esp_err_t (*play_prompt)(domain_wifi_prompt_id_t prompt);
|
|
esp_err_t (*play_prompt_file)(const char *path);
|
|
} domain_wifi_behavior_hooks_t;
|
|
|
|
typedef enum {
|
|
DOMAIN_MULTIMODAL_TRANSPORT_EVENT_CONNECTED = 0,
|
|
DOMAIN_MULTIMODAL_TRANSPORT_EVENT_DISCONNECTED,
|
|
DOMAIN_MULTIMODAL_TRANSPORT_EVENT_ERROR,
|
|
DOMAIN_MULTIMODAL_TRANSPORT_EVENT_TEXT_MESSAGE,
|
|
DOMAIN_MULTIMODAL_TRANSPORT_EVENT_BINARY_MESSAGE,
|
|
} domain_multimodal_transport_event_type_t;
|
|
|
|
typedef struct {
|
|
domain_multimodal_transport_event_type_t type;
|
|
const uint8_t *data;
|
|
size_t data_len;
|
|
} domain_multimodal_transport_event_t;
|
|
|
|
typedef void (*domain_multimodal_transport_event_callback_t)(
|
|
const domain_multimodal_transport_event_t *event,
|
|
void *user_data);
|
|
|
|
typedef esp_err_t (*domain_multimodal_audio_uplink_cb_t)(
|
|
const uint8_t *data,
|
|
size_t len,
|
|
void *user_data);
|
|
|
|
typedef enum {
|
|
DOMAIN_LOCAL_COMMAND_MIAO_ZHANG_GUI = 1,
|
|
} domain_local_command_id_t;
|
|
|
|
typedef enum {
|
|
DOMAIN_LOCAL_COMMAND_EVENT_DETECTED = 0,
|
|
} domain_local_command_event_type_t;
|
|
|
|
typedef struct {
|
|
domain_local_command_event_type_t type;
|
|
domain_local_command_id_t command_id;
|
|
uint32_t confidence_x10000;
|
|
uint32_t detection_generation;
|
|
} domain_local_command_event_t;
|
|
|
|
typedef void (*domain_local_command_event_callback_t)(
|
|
const domain_local_command_event_t *event,
|
|
void *user_data);
|
|
|
|
typedef struct {
|
|
bool started;
|
|
bool detection_running;
|
|
uint32_t detection_generation;
|
|
uint32_t detection_count;
|
|
uint32_t dropped_pcm_frames;
|
|
uint32_t task_stack_high_water_bytes;
|
|
} domain_local_command_snapshot_t;
|
|
|
|
typedef enum {
|
|
DOMAIN_MULTIMODAL_DOWNSTREAM_PLAYBACK_STARTED = 0,
|
|
DOMAIN_MULTIMODAL_DOWNSTREAM_PLAYBACK_COMPLETED,
|
|
DOMAIN_MULTIMODAL_DOWNSTREAM_PLAYBACK_STOPPED,
|
|
DOMAIN_MULTIMODAL_DOWNSTREAM_PLAYBACK_STALLED,
|
|
} domain_multimodal_downstream_playback_event_type_t;
|
|
|
|
typedef struct {
|
|
domain_multimodal_downstream_playback_event_type_t type;
|
|
uint32_t playback_generation;
|
|
} domain_multimodal_downstream_playback_event_t;
|
|
|
|
typedef void (*domain_multimodal_downstream_playback_callback_t)(
|
|
const domain_multimodal_downstream_playback_event_t *event,
|
|
void *user_data);
|
|
|
|
typedef enum {
|
|
DOMAIN_EXPRESSION_IDLE = 0,
|
|
DOMAIN_EXPRESSION_SERVER_ERROR,
|
|
DOMAIN_EXPRESSION_SLOT_REELS,
|
|
DOMAIN_EXPRESSION_WIFI_CONNECTING,
|
|
DOMAIN_EXPRESSION_WIFI_DISCONNECTED,
|
|
DOMAIN_EXPRESSION_WEALTH_SPIN,
|
|
DOMAIN_EXPRESSION_WEALTH_DIRECTION,
|
|
DOMAIN_EXPRESSION_MUYU,
|
|
DOMAIN_EXPRESSION_CHOUQIAN,
|
|
DOMAIN_EXPRESSION_WUXING,
|
|
DOMAIN_EXPRESSION_LISTENING,
|
|
} domain_expression_id_t;
|
|
|
|
typedef enum {
|
|
DOMAIN_EXPRESSION_TRIGGER_UNSPECIFIED = 0,
|
|
DOMAIN_EXPRESSION_TRIGGER_SERVER_TASK_FAILED,
|
|
DOMAIN_EXPRESSION_TRIGGER_SERVER_OUTPUT_ERROR,
|
|
DOMAIN_EXPRESSION_TRIGGER_SLOT_SWITCH,
|
|
DOMAIN_EXPRESSION_TRIGGER_WIFI_BOOTSTRAP,
|
|
DOMAIN_EXPRESSION_TRIGGER_WIFI_DISCONNECTED,
|
|
DOMAIN_EXPRESSION_TRIGGER_WIFI_RECONNECTED,
|
|
DOMAIN_EXPRESSION_TRIGGER_MODEL_DIRECTION,
|
|
DOMAIN_EXPRESSION_TRIGGER_DAILY_FORTUNE,
|
|
DOMAIN_EXPRESSION_TRIGGER_PTT_DOUBLE_CLICK,
|
|
DOMAIN_EXPRESSION_TRIGGER_SW2_SINGLE_CLICK,
|
|
DOMAIN_EXPRESSION_TRIGGER_SW2_DOUBLE_CLICK,
|
|
DOMAIN_EXPRESSION_TRIGGER_LOCAL_WAKE,
|
|
} domain_expression_trigger_t;
|
|
|
|
typedef struct {
|
|
domain_expression_id_t id;
|
|
domain_expression_trigger_t trigger;
|
|
size_t direction_index; /* Only used by DOMAIN_EXPRESSION_WEALTH_DIRECTION */
|
|
size_t chouqian_result_index; /* Optional for DOMAIN_EXPRESSION_CHOUQIAN */
|
|
bool chouqian_result_index_valid;
|
|
} domain_expression_request_t;
|
|
|
|
esp_err_t domain_init(const domain_direction_axis_config_t *config,
|
|
const domain_direction_calibration_t *calibration);
|
|
const domain_direction_axis_config_t *domain_direction_default_axis_config(void);
|
|
const domain_direction_calibration_t *domain_direction_default_calibration(void);
|
|
bool domain_is_initialized(void);
|
|
size_t domain_get_direction_count(void);
|
|
bool domain_get_direction_view(size_t index,
|
|
const char **out_name_cn,
|
|
const char **out_name_en,
|
|
float *out_angle);
|
|
bool domain_find_direction_by_name(const char *input, size_t *out_index);
|
|
bool domain_get_current_direction_index(size_t *out_index);
|
|
float domain_get_current_angle(void);
|
|
void domain_set_current_angle(float angle);
|
|
int domain_get_rotate_speed_us(void);
|
|
/**
|
|
* @brief Rotate to an absolute direction angle.
|
|
*
|
|
* `timeout_ms <= 0` uses the default domain timeout. The timeout is the total
|
|
* caller-visible budget, including state-lock acquisition and motor movement.
|
|
*/
|
|
esp_err_t domain_rotate_to_angle_with_timeout(float target_angle, int timeout_ms);
|
|
esp_err_t domain_apply_rotation_delta(float delta);
|
|
void domain_set_calibration(const domain_direction_calibration_t *config);
|
|
bool domain_get_calibration(domain_direction_calibration_t *out_config);
|
|
/**
|
|
* @brief Run direction calibration.
|
|
*
|
|
* `timeout_ms <= 0` uses the default calibration timeout. The timeout is the
|
|
* total caller-visible budget, including state-lock acquisition, movement
|
|
* steps, switch settle delays, and release sweep.
|
|
*/
|
|
esp_err_t domain_calibrate_with_timeout(const domain_direction_calibration_t *config, int timeout_ms);
|
|
|
|
esp_err_t domain_runtime_multimodal_transport_start(
|
|
const char *bearer_token,
|
|
const char *workspace_id,
|
|
domain_multimodal_transport_event_callback_t cb,
|
|
void *user_data);
|
|
/**
|
|
* @brief Stop the multimodal transport with bounded teardown.
|
|
*
|
|
* `timeout_ms < 0` is invalid, zero requests asynchronous stop, and positive
|
|
* values wait up to the bound before lower layers apply deterministic fallback.
|
|
*/
|
|
esp_err_t domain_runtime_multimodal_transport_stop(int timeout_ms);
|
|
bool domain_runtime_multimodal_transport_is_connected(void);
|
|
esp_err_t domain_runtime_multimodal_transport_send_text(const char *label, const char *text);
|
|
esp_err_t domain_runtime_multimodal_transport_send_text_realtime(const char *label, const char *text);
|
|
esp_err_t domain_runtime_multimodal_transport_send_binary_realtime(const uint8_t *data, size_t len);
|
|
|
|
esp_err_t domain_runtime_multimodal_audio_init(void);
|
|
void domain_runtime_multimodal_audio_deinit(void);
|
|
esp_err_t domain_runtime_multimodal_audio_start_uplink(
|
|
domain_multimodal_audio_uplink_cb_t cb,
|
|
void *user_data);
|
|
|
|
/**
|
|
* @brief Stop multimodal uplink capture/stream with bounded teardown.
|
|
*
|
|
* `timeout_ms < 0` is invalid, zero requests asynchronous stop, and positive
|
|
* values wait up to the bound before lower layers apply deterministic fallback.
|
|
*/
|
|
esp_err_t domain_runtime_multimodal_audio_stop_uplink(int timeout_ms);
|
|
bool domain_runtime_multimodal_audio_is_uplink_running(void);
|
|
bool domain_runtime_multimodal_audio_is_initialized(void);
|
|
/**
|
|
* @brief Start local MultiNet detection for the Chinese phrase "喵掌柜".
|
|
*
|
|
* The callback runs in the domain inference task and must be bounded and
|
|
* non-blocking. Repeated start with the same callback is idempotent.
|
|
*/
|
|
esp_err_t domain_runtime_local_command_start(
|
|
domain_local_command_event_callback_t callback,
|
|
void *user_data);
|
|
esp_err_t domain_runtime_local_command_suspend(int timeout_ms);
|
|
esp_err_t domain_runtime_local_command_resume(int timeout_ms);
|
|
esp_err_t domain_runtime_local_command_stop(int timeout_ms);
|
|
esp_err_t domain_runtime_local_command_get_snapshot(
|
|
domain_local_command_snapshot_t *out_snapshot);
|
|
esp_err_t domain_runtime_multimodal_audio_play_downstream_opus(const uint8_t *data, size_t len);
|
|
esp_err_t domain_runtime_multimodal_audio_begin_downstream_response(
|
|
uint32_t *out_playback_generation);
|
|
esp_err_t domain_runtime_multimodal_audio_finish_downstream_response(void);
|
|
esp_err_t domain_runtime_multimodal_audio_stop_downstream_playback(void);
|
|
esp_err_t domain_runtime_multimodal_audio_register_downstream_playback_callback(
|
|
domain_multimodal_downstream_playback_callback_t cb,
|
|
void *user_data);
|
|
esp_err_t domain_runtime_multimodal_ptt_button_init(void);
|
|
bool domain_runtime_multimodal_ptt_button_is_pressed(void);
|
|
esp_err_t domain_runtime_slot_feature_switch_init(void);
|
|
bool domain_runtime_slot_feature_switch_is_active(void);
|
|
|
|
esp_err_t domain_runtime_prepare_storage(void);
|
|
esp_err_t domain_runtime_mount_littlefs(void);
|
|
esp_err_t domain_runtime_mount_logfs(void);
|
|
void domain_runtime_read_device_identity(char *device_id,
|
|
size_t device_id_len,
|
|
char *serial_number,
|
|
size_t serial_number_len);
|
|
esp_err_t domain_runtime_read_firmware_version(char *out, size_t out_len);
|
|
|
|
esp_err_t domain_runtime_write_device_identity(const char *device_id, const char *serial_number);
|
|
|
|
typedef enum {
|
|
DOMAIN_RUNTIME_AUTH_RECORD_KEY_MATERIAL = 0,
|
|
DOMAIN_RUNTIME_AUTH_RECORD_STATE,
|
|
} domain_runtime_auth_record_t;
|
|
|
|
/**
|
|
* @brief Domain-owned device-auth persistence port, backed by platform blobs.
|
|
*
|
|
* The domain facade owns only the auth record slots, storage key mapping, and
|
|
* legacy migration boundary. Callers own the serialized record schema and pass
|
|
* opaque bytes. `load_record` returns `ESP_ERR_NOT_FOUND` when no record exists
|
|
* yet; `save_record` commits atomically.
|
|
*/
|
|
esp_err_t domain_runtime_auth_store_load_record(domain_runtime_auth_record_t record,
|
|
void *out,
|
|
size_t out_len,
|
|
size_t *out_len_actual);
|
|
esp_err_t domain_runtime_auth_store_save_record(domain_runtime_auth_record_t record,
|
|
const void *data,
|
|
size_t len);
|
|
|
|
/* ------------------------------------------------------------------------- */
|
|
/* Daily fortune: user birth profile + server-computed daily result. */
|
|
/* Owned by the domain layer; see docs/adr/0002-daily-fortune-contracts.md. */
|
|
/* ------------------------------------------------------------------------- */
|
|
|
|
#define DOMAIN_BIRTH_PLACE_MAX_LEN 64
|
|
#define DOMAIN_BIRTH_RESIDENCE_MAX_LEN 64
|
|
#define DOMAIN_BIRTH_MBTI_MAX_LEN 8
|
|
#define DOMAIN_BIRTH_TZ_MAX_LEN 32
|
|
|
|
typedef struct {
|
|
int year;
|
|
int month;
|
|
int day;
|
|
int hour;
|
|
int minute;
|
|
char birth_place[DOMAIN_BIRTH_PLACE_MAX_LEN];
|
|
char current_residence[DOMAIN_BIRTH_RESIDENCE_MAX_LEN];
|
|
char mbti[DOMAIN_BIRTH_MBTI_MAX_LEN];
|
|
char timezone[DOMAIN_BIRTH_TZ_MAX_LEN];
|
|
bool valid;
|
|
} domain_birth_profile_t;
|
|
|
|
#define DOMAIN_FORTUNE_BAZI_MAX_LEN 64
|
|
#define DOMAIN_FORTUNE_ELEMENT_MAX_LEN 8
|
|
#define DOMAIN_FORTUNE_DIRECTION_MAX_LEN 16
|
|
#define DOMAIN_FORTUNE_DATE_MAX_LEN 12
|
|
|
|
typedef struct {
|
|
char bazi[DOMAIN_FORTUNE_BAZI_MAX_LEN];
|
|
char element[DOMAIN_FORTUNE_ELEMENT_MAX_LEN];
|
|
char lucky_color[DOMAIN_FORTUNE_ELEMENT_MAX_LEN];
|
|
char wealth_direction[DOMAIN_FORTUNE_DIRECTION_MAX_LEN];
|
|
char target_date[DOMAIN_FORTUNE_DATE_MAX_LEN];
|
|
size_t wealth_direction_index;
|
|
bool valid;
|
|
} domain_fortune_result_t;
|
|
|
|
typedef void (*domain_birth_profile_observer_t)(const domain_birth_profile_t *profile, void *user_data);
|
|
|
|
/**
|
|
* @brief Persist / query the user birth profile (NVS-backed via the platform store).
|
|
*
|
|
* `set` requires a valid profile, persists it, then notifies the registered
|
|
* observer with a snapshot (invoked outside any lock). `get` returns false when
|
|
* no valid profile has been stored. Storage is the single source of truth; no
|
|
* higher-layer mirror should be kept.
|
|
*/
|
|
esp_err_t domain_birth_profile_store_set(const domain_birth_profile_t *profile);
|
|
bool domain_birth_profile_store_get(domain_birth_profile_t *out_profile);
|
|
|
|
/**
|
|
* @brief Persist / query the most recent daily fortune result.
|
|
*/
|
|
esp_err_t domain_fortune_result_store_set(const domain_fortune_result_t *result);
|
|
bool domain_fortune_result_store_get(domain_fortune_result_t *out_result);
|
|
esp_err_t domain_fortune_result_store_clear(void);
|
|
|
|
/**
|
|
* @brief Register the single observer notified when a new birth profile is
|
|
* stored (e.g. submitted over the LAN configuration page). Pass NULL to clear it. The
|
|
* callback must be lightweight (it runs in the caller's context).
|
|
*/
|
|
void domain_runtime_register_birth_profile_observer(domain_birth_profile_observer_t cb, void *user_data);
|
|
|
|
/**
|
|
* @brief Wall-clock time synchronization, bridged to the platform SNTP
|
|
* primitive. `start` is idempotent and sets the process time zone
|
|
* (`posix_tz`, e.g. "CST-8"); `is_synced` reports whether the clock has
|
|
* been set. Call `start` after the network is up.
|
|
*/
|
|
esp_err_t domain_runtime_time_sync_start(const char *sntp_server, const char *posix_tz);
|
|
bool domain_runtime_time_is_synced(void);
|
|
|
|
#define DOMAIN_USER_CONFIG_HOSTNAME_MAX_LEN 32
|
|
|
|
typedef struct {
|
|
uint16_t port;
|
|
char hostname[DOMAIN_USER_CONFIG_HOSTNAME_MAX_LEN];
|
|
} domain_user_config_server_config_t;
|
|
|
|
typedef struct {
|
|
bool running;
|
|
uint16_t port;
|
|
char hostname[DOMAIN_USER_CONFIG_HOSTNAME_MAX_LEN];
|
|
} domain_user_config_server_state_t;
|
|
|
|
/**
|
|
* @brief Start the domain-owned user profile and fortune web application.
|
|
*
|
|
* The platform supplies only the bounded raw HTTP transport. This domain
|
|
* service owns the routes, JSON semantics, validation, and embedded page.
|
|
* Start is idempotent while the service is starting or running.
|
|
*/
|
|
esp_err_t domain_user_config_server_start(
|
|
const domain_user_config_server_config_t *config);
|
|
|
|
/**
|
|
* @brief Stop the user configuration server with bounded teardown.
|
|
*
|
|
* `timeout_ms < 0` is invalid, zero requests asynchronous stop, and positive
|
|
* values wait up to the bound before the platform applies deterministic
|
|
* fallback.
|
|
*/
|
|
esp_err_t domain_user_config_server_stop(int timeout_ms);
|
|
esp_err_t domain_user_config_server_get_state(
|
|
domain_user_config_server_state_t *out_state);
|
|
|
|
/**
|
|
* @brief POST domain JSON data through the lower-layer HTTPS transport adapter.
|
|
*
|
|
* Optional `device_id` is sent as X-Device-Id and optional `bearer_token` is
|
|
* sent as Authorization: Bearer <token>. The response body is written to the
|
|
* caller-owned buffer and NUL-terminated on success. A completed HTTP exchange
|
|
* returns ESP_OK regardless of status code; callers inspect `out_status`.
|
|
*
|
|
* `timeout_ms < 0` is invalid. `timeout_ms == 0` uses the platform HTTPS
|
|
* default bounded timeout. On `ESP_ERR_TIMEOUT`, the lower-layer exchange is
|
|
* aborted and cleaned up before this function returns; no retry is performed.
|
|
*/
|
|
esp_err_t domain_runtime_post_json(const char *url,
|
|
const char *payload,
|
|
const char *device_id,
|
|
const char *bearer_token,
|
|
int timeout_ms,
|
|
int tx_buffer_size,
|
|
int rx_buffer_size,
|
|
char *response_body,
|
|
size_t response_body_capacity,
|
|
size_t *out_response_body_len,
|
|
int *out_status);
|
|
|
|
#define DOMAIN_OTA_VERSION_MAX_LEN 32
|
|
#define DOMAIN_OTA_URL_MAX_LEN 2048
|
|
#define DOMAIN_OTA_SHA256_HEX_LEN 64
|
|
|
|
typedef enum {
|
|
DOMAIN_OTA_REPORT_NO_UPDATE = 0,
|
|
DOMAIN_OTA_REPORT_UPDATE_AVAILABLE,
|
|
DOMAIN_OTA_REPORT_SERVER_ERROR,
|
|
} domain_ota_report_outcome_t;
|
|
|
|
typedef struct {
|
|
const char *report_url;
|
|
const char *device_id;
|
|
const char *serial_number;
|
|
const char *current_version;
|
|
const char *device_jwt;
|
|
const char *internal_auth_secret;
|
|
int timeout_ms;
|
|
} domain_ota_report_request_t;
|
|
|
|
typedef struct {
|
|
char version[DOMAIN_OTA_VERSION_MAX_LEN];
|
|
char url[DOMAIN_OTA_URL_MAX_LEN];
|
|
char sha256[DOMAIN_OTA_SHA256_HEX_LEN + 1];
|
|
uint64_t size_bytes;
|
|
bool forced;
|
|
bool confirmed;
|
|
} domain_ota_firmware_t;
|
|
|
|
typedef struct {
|
|
domain_ota_report_outcome_t outcome;
|
|
int http_status;
|
|
int business_code;
|
|
domain_ota_firmware_t firmware;
|
|
} domain_ota_report_response_t;
|
|
|
|
typedef struct {
|
|
uint32_t free_internal;
|
|
uint32_t largest_internal;
|
|
uint32_t largest_dma;
|
|
} domain_ota_memory_headroom_t;
|
|
|
|
typedef void (*domain_ota_progress_callback_t)(uint64_t bytes_received,
|
|
uint64_t total_bytes,
|
|
void *user_data);
|
|
typedef bool (*domain_ota_cancel_callback_t)(void *user_data);
|
|
|
|
esp_err_t domain_runtime_ota_report(const domain_ota_report_request_t *request,
|
|
domain_ota_report_response_t *response);
|
|
esp_err_t domain_runtime_ota_install(const domain_ota_firmware_t *firmware,
|
|
int timeout_ms,
|
|
domain_ota_progress_callback_t progress_cb,
|
|
domain_ota_cancel_callback_t cancel_cb,
|
|
void *user_data);
|
|
esp_err_t domain_runtime_ota_confirm_running_image(void);
|
|
esp_err_t domain_runtime_ota_get_memory_headroom(domain_ota_memory_headroom_t *out);
|
|
void domain_runtime_restart(void);
|
|
|
|
/**
|
|
* @brief Console (UART) line-transport primitives, bridged to the platform.
|
|
*
|
|
* `read_bytes` returns bytes read (0 on timeout, <0 on error). A zero timeout
|
|
* polls once; negative timeouts are invalid and return <0. Used by the factory
|
|
* provisioning CLI.
|
|
*/
|
|
esp_err_t domain_runtime_console_install(void);
|
|
int domain_runtime_console_read_bytes(uint8_t *buf, size_t len, int timeout_ms);
|
|
void domain_runtime_console_write_line(const char *line);
|
|
|
|
void domain_runtime_behavior_set_keep_awake(bool keep_awake);
|
|
esp_err_t domain_runtime_behavior_play_prompt(domain_wifi_prompt_id_t prompt);
|
|
esp_err_t domain_runtime_behavior_play_prompt_file(const char *path);
|
|
void domain_runtime_wifi_portal_set_behavior_hooks(const domain_wifi_behavior_hooks_t *hooks);
|
|
esp_err_t domain_runtime_wifi_portal_init_defaults(const char *seed_ssid, const char *seed_password);
|
|
bool domain_runtime_wifi_portal_has_saved_credentials(void);
|
|
bool domain_runtime_wifi_portal_sta_is_connected(void);
|
|
esp_err_t domain_runtime_wifi_portal_start_config_ap(const char *ssid_prefix);
|
|
bool domain_runtime_wifi_connect_error_keeps_credentials(esp_err_t err);
|
|
|
|
/**
|
|
* @brief Connect STA using stored credentials with explicit timeout.
|
|
*
|
|
* Semantics:
|
|
* - `timeout_ms <= 0`: use default timeout.
|
|
* - Returns `ESP_OK` when STA is already connected (idempotent).
|
|
* - Returns explicit failure on timeout/connection error.
|
|
*/
|
|
esp_err_t domain_runtime_wifi_portal_connect_sta(int timeout_ms);
|
|
/**
|
|
* @brief Validate candidate credentials before replacing persisted Wi-Fi state.
|
|
*
|
|
* The previous credentials remain available when the bounded connection trial
|
|
* fails. A successful trial commits only the new credentials.
|
|
*/
|
|
esp_err_t domain_runtime_wifi_portal_connect_sta_with_credentials(
|
|
const char *ssid,
|
|
const char *password,
|
|
int timeout_ms);
|
|
esp_err_t domain_runtime_wifi_portal_reconnect_sta(int timeout_ms);
|
|
esp_err_t domain_runtime_wifi_portal_stop_sta(void);
|
|
bool domain_runtime_is_network_connect_error(esp_err_t err);
|
|
esp_err_t domain_runtime_wifi_portal_save_credentials(const char *ssid, const char *password);
|
|
esp_err_t domain_runtime_wifi_portal_clear_saved_credentials(void);
|
|
|
|
#define DOMAIN_WIFI_PROVISIONING_SSID_MAX_LEN 33
|
|
#define DOMAIN_WIFI_PROVISIONING_PASSWORD_MAX_LEN 65
|
|
|
|
typedef struct {
|
|
char ssid[DOMAIN_WIFI_PROVISIONING_SSID_MAX_LEN];
|
|
char password[DOMAIN_WIFI_PROVISIONING_PASSWORD_MAX_LEN];
|
|
} domain_wifi_provisioning_credentials_t;
|
|
|
|
typedef enum {
|
|
DOMAIN_WIFI_PROVISIONING_EVENT_CREDENTIALS = 0,
|
|
DOMAIN_WIFI_PROVISIONING_EVENT_BAD_JSON,
|
|
DOMAIN_WIFI_PROVISIONING_EVENT_EMPTY_SSID,
|
|
} domain_wifi_provisioning_event_type_t;
|
|
|
|
typedef struct {
|
|
domain_wifi_provisioning_event_type_t type;
|
|
domain_wifi_provisioning_credentials_t credentials;
|
|
} domain_wifi_provisioning_event_t;
|
|
|
|
typedef void (*domain_wifi_provisioning_event_callback_t)(
|
|
const domain_wifi_provisioning_event_t *event,
|
|
void *user_data);
|
|
|
|
typedef enum {
|
|
DOMAIN_WIFI_PROVISIONING_STATUS_WIFI_CONNECTING = 0,
|
|
DOMAIN_WIFI_PROVISIONING_STATUS_WIFI_GOT_IP,
|
|
DOMAIN_WIFI_PROVISIONING_STATUS_SAVING_WIFI,
|
|
DOMAIN_WIFI_PROVISIONING_STATUS_READY,
|
|
DOMAIN_WIFI_PROVISIONING_STATUS_FAIL_BAD_JSON,
|
|
DOMAIN_WIFI_PROVISIONING_STATUS_FAIL_EMPTY_SSID,
|
|
DOMAIN_WIFI_PROVISIONING_STATUS_FAIL_TIMEOUT,
|
|
DOMAIN_WIFI_PROVISIONING_STATUS_FAIL_CONNECT,
|
|
} domain_wifi_provisioning_status_t;
|
|
|
|
/** Start the fixed TalkingQ mini-program BLE provisioning protocol. */
|
|
esp_err_t domain_runtime_mini_program_provisioning_start(
|
|
domain_wifi_provisioning_event_callback_t callback,
|
|
void *user_data);
|
|
esp_err_t domain_runtime_mini_program_provisioning_notify(
|
|
domain_wifi_provisioning_status_t status);
|
|
esp_err_t domain_runtime_mini_program_provisioning_stop(int timeout_ms);
|
|
|
|
esp_err_t domain_runtime_init_lcd_device(void);
|
|
void domain_runtime_start_lcd_render_loop(void);
|
|
/**
|
|
* @brief Stop LCD render loop with bounded teardown.
|
|
*
|
|
* `timeout_ms < 0` is invalid, zero requests asynchronous stop, and positive
|
|
* values wait up to the bound before lower layers apply deterministic fallback.
|
|
*/
|
|
esp_err_t domain_runtime_stop_lcd_render_loop(int timeout_ms);
|
|
|
|
/** Map the domain battery snapshot to persistent LCD status overlays. */
|
|
esp_err_t domain_runtime_update_battery_overlay(const domain_battery_status_t *status);
|
|
|
|
esp_err_t domain_runtime_request_expression(const domain_expression_request_t *request);
|
|
|
|
/**
|
|
* @brief Preload assets for an expression without changing the active display.
|
|
*
|
|
* Intended for asset-backed expressions that are likely to play soon. The
|
|
* request is copied, the LCD render task performs the preload between display
|
|
* frames, and the caller waits for its result. Unsupported or non-asset
|
|
* expressions return an explicit error.
|
|
*/
|
|
esp_err_t domain_runtime_preheat_expression(const domain_expression_request_t *request);
|
|
|
|
/**
|
|
* @brief Request an expression and block until its finite asset sequence
|
|
* completes, or @p timeout_ms elapses.
|
|
*
|
|
* Intended for finite presentations such as the wealth spin intro. Returns the
|
|
* underlying request error if queuing fails, ESP_ERR_TIMEOUT if playback does
|
|
* not finish within the timeout (the caller may proceed anyway), or
|
|
* ESP_ERR_INVALID_STATE if the LCD is not running. A looping expression
|
|
* (repeat_count == 0) never completes and will time out.
|
|
*/
|
|
esp_err_t domain_runtime_request_expression_blocking(const domain_expression_request_t *request,
|
|
uint32_t timeout_ms);
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|