实现 BLE 双向状态回传
This commit is contained in:
parent
2f5cfdb1c8
commit
1aaca3d83c
16
main/main.c
16
main/main.c
@ -82,6 +82,11 @@ void app_main(void)
|
||||
|
||||
int frame_counter = 0;
|
||||
uint32_t ble_ui_update_count = 0;
|
||||
TickType_t last_status_notify_tick = 0;
|
||||
int latest_battery_percent = -1;
|
||||
int latest_battery_mv = -1;
|
||||
int latest_temperature_c10 = -999;
|
||||
int latest_humidity_percent = -1;
|
||||
while (1) {
|
||||
vTaskDelay(pdMS_TO_TICKS(30));
|
||||
|
||||
@ -101,15 +106,26 @@ void app_main(void)
|
||||
int battery_percent = 0;
|
||||
int battery_mv = 0;
|
||||
if (battery_monitor_take_latest(&battery_percent, &battery_mv)) {
|
||||
latest_battery_percent = battery_percent;
|
||||
latest_battery_mv = battery_mv;
|
||||
ui_screen_update_battery(battery_percent, battery_mv);
|
||||
}
|
||||
|
||||
int temperature_c10 = 0;
|
||||
int humidity_percent = 0;
|
||||
if (temp_humidity_monitor_take_latest(&temperature_c10, &humidity_percent)) {
|
||||
latest_temperature_c10 = temperature_c10;
|
||||
latest_humidity_percent = humidity_percent;
|
||||
ui_screen_update_environment(temperature_c10, humidity_percent);
|
||||
}
|
||||
|
||||
TickType_t now_tick = xTaskGetTickCount();
|
||||
if ((now_tick - last_status_notify_tick) >= pdMS_TO_TICKS(5000)) {
|
||||
last_status_notify_tick = now_tick;
|
||||
metrics_ble_notify_status(latest_battery_percent, latest_battery_mv,
|
||||
latest_temperature_c10, latest_humidity_percent);
|
||||
}
|
||||
|
||||
lv_lock();
|
||||
lv_timer_handler();
|
||||
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
#include "metrics_ble.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "esp_err.h"
|
||||
@ -25,15 +26,22 @@ static const char *DEVICE_NAME = "RLCD-Metrics";
|
||||
|
||||
// Service: 9f4af548-1a14-4fc1-8f5a-4b9f00000001
|
||||
// Write char: 9f4af548-1a14-4fc1-8f5a-4b9f00000002
|
||||
// Status notify char: 9f4af548-1a14-4fc1-8f5a-4b9f00000003
|
||||
static const ble_uuid128_t metrics_svc_uuid =
|
||||
BLE_UUID128_INIT(0x01, 0x00, 0x00, 0x00, 0x9f, 0x4b, 0x5a, 0x8f,
|
||||
0xc1, 0x4f, 0x14, 0x1a, 0x48, 0xf5, 0x4a, 0x9f);
|
||||
static const ble_uuid128_t metrics_chr_uuid =
|
||||
BLE_UUID128_INIT(0x02, 0x00, 0x00, 0x00, 0x9f, 0x4b, 0x5a, 0x8f,
|
||||
0xc1, 0x4f, 0x14, 0x1a, 0x48, 0xf5, 0x4a, 0x9f);
|
||||
static const ble_uuid128_t status_chr_uuid =
|
||||
BLE_UUID128_INIT(0x03, 0x00, 0x00, 0x00, 0x9f, 0x4b, 0x5a, 0x8f,
|
||||
0xc1, 0x4f, 0x14, 0x1a, 0x48, 0xf5, 0x4a, 0x9f);
|
||||
|
||||
static uint8_t own_addr_type;
|
||||
static uint16_t metrics_chr_val_handle;
|
||||
static uint16_t status_chr_val_handle;
|
||||
static uint16_t s_conn_handle;
|
||||
static bool s_status_notify_enabled;
|
||||
static QueueHandle_t s_metrics_queue;
|
||||
static uint32_t s_ble_write_count;
|
||||
|
||||
@ -115,6 +123,12 @@ static const struct ble_gatt_svc_def metrics_gatt_svcs[] = {
|
||||
.flags = BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_WRITE_NO_RSP,
|
||||
.val_handle = &metrics_chr_val_handle,
|
||||
},
|
||||
{
|
||||
.uuid = &status_chr_uuid.u,
|
||||
.access_cb = metrics_gatt_access,
|
||||
.flags = BLE_GATT_CHR_F_NOTIFY,
|
||||
.val_handle = &status_chr_val_handle,
|
||||
},
|
||||
{0},
|
||||
},
|
||||
},
|
||||
@ -160,8 +174,12 @@ static int metrics_gap_event(struct ble_gap_event *event, void *arg)
|
||||
case BLE_GAP_EVENT_CONNECT:
|
||||
if (event->connect.status == 0) {
|
||||
ESP_LOGI(TAG, "BLE connected");
|
||||
s_conn_handle = event->connect.conn_handle;
|
||||
s_status_notify_enabled = false;
|
||||
metrics_request_2m_phy(event->connect.conn_handle);
|
||||
} else {
|
||||
s_conn_handle = 0;
|
||||
s_status_notify_enabled = false;
|
||||
metrics_advertise();
|
||||
}
|
||||
return 0;
|
||||
@ -175,9 +193,19 @@ static int metrics_gap_event(struct ble_gap_event *event, void *arg)
|
||||
|
||||
case BLE_GAP_EVENT_DISCONNECT:
|
||||
ESP_LOGI(TAG, "BLE disconnected");
|
||||
s_conn_handle = 0;
|
||||
s_status_notify_enabled = false;
|
||||
metrics_advertise();
|
||||
return 0;
|
||||
|
||||
case BLE_GAP_EVENT_SUBSCRIBE:
|
||||
if (event->subscribe.attr_handle == status_chr_val_handle) {
|
||||
s_status_notify_enabled = event->subscribe.cur_notify;
|
||||
ESP_LOGI(TAG, "status notify %s",
|
||||
s_status_notify_enabled ? "enabled" : "disabled");
|
||||
}
|
||||
return 0;
|
||||
|
||||
case BLE_GAP_EVENT_ADV_COMPLETE:
|
||||
metrics_advertise();
|
||||
return 0;
|
||||
@ -269,3 +297,31 @@ bool metrics_ble_take_latest(ui_metrics_t *metrics)
|
||||
|
||||
return xQueueReceive(s_metrics_queue, metrics, 0) == pdTRUE;
|
||||
}
|
||||
|
||||
bool metrics_ble_notify_status(int battery_percent, int battery_mv,
|
||||
int temperature_c10, int humidity_percent)
|
||||
{
|
||||
if (!s_status_notify_enabled || s_conn_handle == 0 || status_chr_val_handle == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
char line[96];
|
||||
int len = snprintf(line, sizeof(line), "STA,%d,%d,%d,%d,%lu",
|
||||
battery_percent, battery_mv, temperature_c10, humidity_percent,
|
||||
(unsigned long)s_ble_write_count);
|
||||
if (len <= 0 || len >= (int)sizeof(line)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
struct os_mbuf *om = ble_hs_mbuf_from_flat(line, len);
|
||||
if (om == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int rc = ble_gatts_notify_custom(s_conn_handle, status_chr_val_handle, om);
|
||||
if (rc != 0) {
|
||||
ESP_LOGW(TAG, "status notify failed: %d", rc);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -10,6 +10,8 @@ extern "C" {
|
||||
|
||||
void metrics_ble_start(void);
|
||||
bool metrics_ble_take_latest(ui_metrics_t *metrics);
|
||||
bool metrics_ble_notify_status(int battery_percent, int battery_mv,
|
||||
int temperature_c10, int humidity_percent);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@ -22,6 +22,7 @@ from bleak import BleakClient, BleakScanner
|
||||
|
||||
DEFAULT_DEVICE_NAME = "RLCD-Metrics"
|
||||
DEFAULT_CHAR_UUID = "9f4af548-1a14-4fc1-8f5a-4b9f00000002"
|
||||
DEFAULT_STATUS_CHAR_UUID = "9f4af548-1a14-4fc1-8f5a-4b9f00000003"
|
||||
MAX_DISK_ROWS = 4
|
||||
MAX_DISK_TEXT = 124
|
||||
CODEX_DAILY_BAR_COUNT = 14
|
||||
@ -1056,6 +1057,11 @@ async def find_device(name: str, address: str | None, timeout: float):
|
||||
async def push_loop(args) -> int:
|
||||
sampler = MetricsSampler(args.disk)
|
||||
|
||||
def status_callback(_sender, data: bytearray):
|
||||
text = bytes(data).decode("ascii", errors="replace").strip()
|
||||
if text:
|
||||
print(f"BLE status: {text}", flush=True)
|
||||
|
||||
while True:
|
||||
print(f"Scanning for {args.name}...", flush=True)
|
||||
device = await find_device(args.name, args.address, args.scan_timeout)
|
||||
@ -1070,6 +1076,11 @@ async def push_loop(args) -> int:
|
||||
try:
|
||||
async with BleakClient(device, timeout=args.connect_timeout) as client:
|
||||
print("BLE connected. Streaming metrics.", flush=True)
|
||||
try:
|
||||
await client.start_notify(args.status_char_uuid, status_callback)
|
||||
print("BLE status notify subscribed.", flush=True)
|
||||
except Exception as exc:
|
||||
print(f"BLE status notify unavailable: {exc}", file=sys.stderr, flush=True)
|
||||
while True:
|
||||
line = sampler.sample_line()
|
||||
await client.write_gatt_char(args.char_uuid, line.encode("ascii"), response=True)
|
||||
@ -1091,6 +1102,7 @@ def parse_args():
|
||||
parser.add_argument("--name", default=DEFAULT_DEVICE_NAME)
|
||||
parser.add_argument("--address", default=None)
|
||||
parser.add_argument("--char-uuid", default=DEFAULT_CHAR_UUID)
|
||||
parser.add_argument("--status-char-uuid", default=DEFAULT_STATUS_CHAR_UUID)
|
||||
parser.add_argument("--interval", type=float, default=1.0)
|
||||
parser.add_argument("--scan-timeout", type=float, default=20.0)
|
||||
parser.add_argument("--connect-timeout", type=float, default=20.0)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user