Files
hms/crates/erp-health/src/dto/ble_gateway_dto.rs
iven 7e57565ecd
Some checks failed
CI / rust-check (push) Has been cancelled
CI / rust-test (push) Has been cancelled
CI / frontend-build (push) Has been cancelled
CI / security-audit (push) Has been cancelled
feat(health): BLE 网关后端接入 — 网关管理 + API Key 认证 + 多患者批量上报
- 新增 ble_gateways + gateway_patient_bindings 表迁移 (000113)
- 网关 CRUD:注册/编辑/删除/重生成 API Key,含患者绑定管理
- API Key 认证中间件(SHA-256 hash + prefix 快速查找)
- 网关数据上报端点:多患者批量读数,复用 device_reading_service 管道
- 网关心跳端点:固件版本/IP 更新 + last_heartbeat_at
- 10 个管理端路由(JWT)+ 2 个网关端路由(API Key)
- health.ble-gateways.list/manage 权限声明
- 修复 000112 迁移 ForeignKey 借用错误
2026-05-04 20:28:26 +08:00

142 lines
4.0 KiB
Rust
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
use serde::{Deserialize, Serialize};
use uuid::Uuid;
// ---------------------------------------------------------------------------
// BLE Gateway DTOs
// ---------------------------------------------------------------------------
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct BleGatewayResp {
pub id: Uuid,
pub tenant_id: Uuid,
pub gateway_id: String,
pub name: String,
pub status: String,
pub firmware_version: Option<String>,
pub ip_address: Option<String>,
pub last_heartbeat_at: Option<chrono::DateTime<chrono::Utc>>,
pub metadata: Option<serde_json::Value>,
pub created_at: chrono::DateTime<chrono::Utc>,
pub updated_at: chrono::DateTime<chrono::Utc>,
pub version: i32,
/// 网关 API Key仅在创建时返回一次
pub api_key: Option<String>,
/// 绑定的患者数量
pub patient_count: Option<i64>,
}
#[derive(Debug, Clone, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct CreateBleGatewayReq {
pub gateway_id: String,
pub name: String,
pub firmware_version: Option<String>,
pub metadata: Option<serde_json::Value>,
}
#[derive(Debug, Clone, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct UpdateBleGatewayReq {
pub name: Option<String>,
pub status: Option<String>,
pub firmware_version: Option<String>,
pub metadata: Option<serde_json::Value>,
}
#[derive(Debug, Clone, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct UpdateBleGatewayWithVersion {
pub version: i32,
pub data: UpdateBleGatewayReq,
}
#[derive(Debug, Clone, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct ListBleGatewaysParams {
pub status: Option<String>,
pub page: Option<u64>,
pub page_size: Option<u64>,
}
// ---------------------------------------------------------------------------
// GatewayPatientBinding DTOs
// ---------------------------------------------------------------------------
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct GatewayBindingResp {
pub id: Uuid,
pub tenant_id: Uuid,
pub gateway_id_fk: Uuid,
pub patient_id: Uuid,
pub peripheral_mac: Option<String>,
pub device_type: Option<String>,
pub status: String,
pub created_at: chrono::DateTime<chrono::Utc>,
pub updated_at: chrono::DateTime<chrono::Utc>,
pub version: i32,
}
#[derive(Debug, Clone, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct CreateBindingReq {
pub patient_id: Uuid,
pub peripheral_mac: Option<String>,
pub device_type: Option<String>,
}
#[derive(Debug, Clone, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct BatchBindReq {
pub bindings: Vec<CreateBindingReq>,
}
// ---------------------------------------------------------------------------
// 网关数据上报 DTOs
// ---------------------------------------------------------------------------
/// 网关多患者批量上报请求
#[derive(Debug, Clone, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct GatewayUploadReq {
pub readings: Vec<PatientReadingBatch>,
}
/// 单个患者的读数批次
#[derive(Debug, Clone, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct PatientReadingBatch {
pub patient_id: Uuid,
pub device_id: String,
pub device_model: Option<String>,
pub readings: Vec<ReadingEntry>,
}
/// 单条读数
#[derive(Debug, Clone, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct ReadingEntry {
pub device_type: String,
pub values: serde_json::Value,
pub measured_at: String,
}
/// 网关上报结果
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct GatewayUploadResp {
pub total_patients: u64,
pub total_readings: u64,
pub total_duplicates: u64,
pub errors: Vec<String>,
}
/// 网关心跳请求
#[derive(Debug, Clone, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct HeartbeatReq {
pub firmware_version: Option<String>,
pub ip_address: Option<String>,
}