213 lines
7.3 KiB
C
Executable File
213 lines
7.3 KiB
C
Executable File
/*
|
|
* proxalarm.c -- Proximity Alarm module main entry point (unified)
|
|
*
|
|
* SPDX-License-Identifier: GPL-2.0-or-later
|
|
*
|
|
* OreBolt OS module: Unified Proximity Alarm / Radar.
|
|
*
|
|
* Packs RF scanning, kinematics, and radar UI as a single .mod binary
|
|
* with three internal layers.
|
|
*
|
|
* Three-layer architecture:
|
|
* bledsp -- Unified RF/DSP layer (BLE scanning + WiFi stub + RSSI)
|
|
* proxvec -- Kinematics layer (target tracking + alarm FSM)
|
|
* radar_ui -- Presentation layer (LVGL radar display)
|
|
*
|
|
* Input controls (via H2 rotary encoder + buttons):
|
|
* ROTATE Cycle sensitivity (NEAR threshold: -40, -50, -60, -70 dBm)
|
|
* PLAY Toggle scan pause/resume
|
|
* NEXT Cycle RF source (BLE <-> WIFI)
|
|
* BACK Exit module
|
|
*
|
|
* This binary is fork+exec'd by the h2_test launcher.
|
|
* It initialises its own LVGL instance and runs its own event loop.
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <unistd.h>
|
|
#include <fcntl.h>
|
|
#include <errno.h>
|
|
|
|
#include "h2_ui.h"
|
|
#include "log_manager.h"
|
|
#include "bledsp.h"
|
|
#include "proxvec.h"
|
|
#include "radar_ui.h"
|
|
|
|
/* ------------------------------------------------------------------ */
|
|
/* Sensitivity presets (dBm thresholds for the "near" alarm zone) */
|
|
/* ------------------------------------------------------------------ */
|
|
|
|
static const int8_t sens_presets[] = { -40, -50, -60, -70 };
|
|
#define SENS_COUNT (int)(sizeof(sens_presets) / sizeof(sens_presets[0]))
|
|
static int sens_idx = 1; /* default: -50 dBm */
|
|
|
|
/* ------------------------------------------------------------------ */
|
|
/* State */
|
|
/* ------------------------------------------------------------------ */
|
|
|
|
static volatile int running = 1;
|
|
static int paused = 0;
|
|
static int prev_alarms = 0;
|
|
static uint32_t last_scan_ms;
|
|
|
|
/* ------------------------------------------------------------------ */
|
|
/* Helpers */
|
|
/* ------------------------------------------------------------------ */
|
|
|
|
static uint32_t mono_ms(void)
|
|
{
|
|
struct timespec ts;
|
|
clock_gettime(CLOCK_MONOTONIC, &ts);
|
|
return (uint32_t)(ts.tv_sec * 1000U + ts.tv_nsec / 1000000U);
|
|
}
|
|
|
|
static void update_sensitivity(void)
|
|
{
|
|
int8_t thresh = sens_presets[sens_idx];
|
|
bledsp_set_near_threshold(thresh);
|
|
/* Map alarm radius: lower threshold (closer) = smaller radius.
|
|
* -40 dBm -> radius 30, -70 dBm -> radius 90 */
|
|
int radius = 30 + (sens_idx) * 20;
|
|
proxvec_set_alarm_radius((int16_t)radius);
|
|
|
|
char buf[32];
|
|
snprintf(buf, sizeof(buf), "NEAR: %ddBm", thresh);
|
|
radar_ui_set_sensitivity_label(buf);
|
|
|
|
LOG_INF("proxalarm: sensitivity set to %d dBm (radius %d grid units)",
|
|
thresh, radius);
|
|
}
|
|
|
|
/* ------------------------------------------------------------------ */
|
|
/* Signal handler */
|
|
/* ------------------------------------------------------------------ */
|
|
|
|
#include <signal.h>
|
|
static void on_signal(int sig) { (void)sig; running = 0; }
|
|
|
|
/* ------------------------------------------------------------------ */
|
|
/* Main */
|
|
/* ------------------------------------------------------------------ */
|
|
|
|
int main(int argc, char **argv)
|
|
{
|
|
(void)argc; (void)argv;
|
|
|
|
signal(SIGINT, on_signal);
|
|
signal(SIGTERM, on_signal);
|
|
|
|
/* Initialise logging */
|
|
if (log_init("/data/vault/syslog.log") < 0) {
|
|
fprintf(stderr, "[-] proxalarm: log_init failed\n");
|
|
return 1;
|
|
}
|
|
LOG_INF("proxalarm: starting (unified proximity sensing)");
|
|
|
|
/* Initialise LVGL (own instance for this module) */
|
|
init_h2_graphics_runtime("PROXALARM v1.7");
|
|
|
|
/* Initialise the three layers (bottom-up) */
|
|
if (bledsp_init() < 0) {
|
|
LOG_ERR("proxalarm: bledsp_init failed");
|
|
log_close();
|
|
return 1;
|
|
}
|
|
proxvec_init();
|
|
radar_ui_init();
|
|
|
|
/* Set initial sensitivity */
|
|
update_sensitivity();
|
|
|
|
/* Set source label (shows BLE/WIFI/SIM depending on mode) */
|
|
radar_ui_set_source_label(bledsp_source_label());
|
|
|
|
/* Open input device */
|
|
int input_fd = open("/dev/input/event0", O_RDONLY | O_NONBLOCK);
|
|
if (input_fd < 0) {
|
|
LOG_WARN("proxalarm: cannot open input device: %s", strerror(errno));
|
|
}
|
|
|
|
last_scan_ms = mono_ms();
|
|
|
|
LOG_INF("proxalarm: ready (ROTATE=sens PLAY=pause NEXT=source BACK=exit)");
|
|
|
|
/* ---- Main loop ---- */
|
|
while (running) {
|
|
lv_timer_handler();
|
|
|
|
/* Process input events */
|
|
if (input_fd >= 0) {
|
|
struct input_event ev;
|
|
while (read(input_fd, &ev, sizeof(ev)) > 0) {
|
|
if (ev.type == EV_REL && ev.code == H2_ROTARY_REL && ev.value != 0) {
|
|
/* Cycle sensitivity */
|
|
sens_idx += (ev.value > 0) ? 1 : -1;
|
|
if (sens_idx < 0) sens_idx = SENS_COUNT - 1;
|
|
if (sens_idx >= SENS_COUNT) sens_idx = 0;
|
|
update_sensitivity();
|
|
}
|
|
if (ev.type == EV_KEY && ev.value == 1) {
|
|
if (ev.code == H2_KEY_PLAY) {
|
|
paused = !paused;
|
|
LOG_INF("proxalarm: %s", paused ? "PAUSED" : "RESUMED");
|
|
}
|
|
if (ev.code == H2_KEY_NEXT) {
|
|
/* Cycle RF source: BLE <-> WIFI */
|
|
bledsp_cycle_source();
|
|
radar_ui_set_source_label(bledsp_source_label());
|
|
LOG_INF("proxalarm: source=%s", bledsp_source_label());
|
|
}
|
|
if (ev.code == H2_KEY_BACK) {
|
|
running = 0;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Periodic scan + update (respect BLE scan interval) */
|
|
uint32_t now = mono_ms();
|
|
if (!paused && (now - last_scan_ms >= (uint32_t)BLE_DSP_SCAN_INTERVAL_MS)) {
|
|
last_scan_ms = now;
|
|
|
|
/* Layer 1: poll BLE hardware */
|
|
bledsp_poll();
|
|
|
|
/* Layer 2: feed device data to kinematics engine */
|
|
bledsp_device_t devs[BLE_DSP_MAX_DEVICES];
|
|
int dev_count = bledsp_get_devices(devs, BLE_DSP_MAX_DEVICES);
|
|
proxvec_update(devs, dev_count);
|
|
|
|
/* Layer 3: get targets and refresh display */
|
|
proxvec_target_t tgts[PROXVEC_MAX_TARGETS];
|
|
int tgt_count = proxvec_get_targets(tgts, PROXVEC_MAX_TARGETS);
|
|
int alarm_count = proxvec_get_alarm_count();
|
|
radar_ui_refresh(tgts, tgt_count, alarm_count);
|
|
|
|
/* Alarm flash management */
|
|
if (alarm_count > 0 && prev_alarms == 0) {
|
|
radar_ui_set_alarm_flash(1);
|
|
LOG_INF("proxalarm: ALARM triggered (%d target%s in zone)",
|
|
alarm_count, alarm_count == 1 ? "" : "s");
|
|
} else if (alarm_count == 0 && prev_alarms > 0) {
|
|
radar_ui_set_alarm_flash(0);
|
|
LOG_INF("proxalarm: alarm cleared");
|
|
}
|
|
prev_alarms = alarm_count;
|
|
}
|
|
|
|
usleep(5000); /* ~200 Hz input poll, LVGL tick */
|
|
}
|
|
|
|
/* ---- Cleanup ---- */
|
|
if (input_fd >= 0) close(input_fd);
|
|
radar_ui_set_alarm_flash(0);
|
|
radar_ui_destroy();
|
|
proxvec_shutdown();
|
|
bledsp_shutdown();
|
|
log_close();
|
|
|
|
return 0;
|
|
} |