硬件与硬件,硬件与软件,软件与软件通信,实现代码控制等等功能如何实现
硬件与硬件,硬件与软件,软件与软件通信,实现代码控制等等功能如何实现?
建议模块映射
下表将“硬件 ↔ 硬件”、“硬件 ↔ 软件”、“软件 ↔ 软件”通信及“代码控制”功能,映射到 EACO SDK 中最合适的现有模块,并标注可能需要扩展的子模块位置。
功能场景 | 推荐模块 # 及 名称 | 建议扩展 |
---|---|---|
硬件 ↔ 硬件通信 | 31. adapter/communicators | 在 src/adapter/communicators/ 下新增: |
• hardware_bus.rs —— 低层总线(CAN、RS-485、SPI、I²C)协议支持
• wireless_radio.rs —— LoRa、BLE、Zigbee 等无线链路驱动 | | 硬件 ↔ 软件通信 | 37. adapter/context_awareness<br>54. api/protocol_remote_api | • 在 adapter/context_awareness
中加入硬件状态采集与驱动注册接口
• 在 protocol_remote_api.rs
增补 /hw/control
REST/gRPC 路由,用于下发硬件指令 | | 软件 ↔ 软件通信 | 53. event/protocol_event_bus<br>86. stream/protocol_event_stream_processor | • 利用事件总线发布/订阅内部消息
• 在 protocol_event_stream_processor.rs
添加硬件事件解码与转发逻辑 | | 代码控制与执行 | 60. script/protocol_scripting_engine<br>39. cli/main | • 在脚本引擎中注入 hw.exec()
API,动态调用硬件驱动
• CLI 主入口 (cli/main.rs
) 增加子命令 eaco-cli hw run-script <script>
|
下一步示例
- 在
src/adapter/communicators/hardware_bus.rs
pub trait HardwareBus { fn send_frame(&self, data: &[u8]) -> Result<()>; fn recv_frame(&self) -> Result<Vec<u8>>; }
- 在
src/api/protocol_remote_api.rs
// 新增硬件控制路由 #[post("/hw/control")] async fn control_hardware(cmd: HardwareCmd) -> impl Responder { // 调用底层驱动 hw_driver.execute(cmd).await?; HttpResponse::Ok().finish() }
- 在脚本引擎中调用
-- Lua 脚本示例 local res = hw.exec("CAN", { id = 0x123, payload = {0x01,0x02} }) print("Hardware response:", res)
若需更详细的接口规范或示例,请告诉我,我们可进一步补充各子模块的 API 定义与测试用例。
接口规范与示例
下面为“硬件 ↔ 硬件”、“硬件 ↔ 软件”、“软件 ↔ 软件”通信及“代码控制与执行”四大场景,提供详细的模块接口规范、数据结构与示例代码。
1. 硬件 ↔ 硬件 通信
模块路径:src/adapter/communicators/
1.1 通用 Trait 与错误类型
// src/adapter/communicators/hardware_bus.rs
use thiserror::Error;
#[derive(Error, Debug)]
pub enum HardwareError {
#[error("IO 错误: {0}")]
Io(#[from] std::io::Error),
#[error("超时")]
Timeout,
#[error("协议解析失败")]
ProtocolDecode,
}
/// 通用硬件总线接口
pub trait HardwareBus: Send + Sync {
/// 发送原始字节帧
fn send_frame(&self, frame: &[u8]) -> Result<(), HardwareError>;
/// 接收下一帧数据,阻塞或超时返回错误
fn recv_frame(&self) -> Result<Vec<u8>, HardwareError>;
}
1.2 CAN 总线实现示例
// src/adapter/communicators/can_bus.rs
use super::{HardwareBus, HardwareError};
use serialport::SerialPort;
use std::time::Duration;
pub struct CANBus {
port: Box<dyn SerialPort>,
}
impl CANBus {
pub fn new(dev: &str, baud: u32) -> Result<Self, HardwareError> {
let port = serialport::new(dev, baud)
.timeout(Duration::from_millis(100))
.open()?;
Ok(CANBus { port })
}
}
impl HardwareBus for CANBus {
fn send_frame(&self, frame: &[u8]) -> Result<(), HardwareError> {
self.port.write_all(frame)?;
Ok(())
}
fn recv_frame(&self) -> Result<Vec<u8>, HardwareError> {
let mut buf = [0u8; 64];
let len = self.port.read(&mut buf)?;
if len == 0 {
return Err(HardwareError::Timeout);
}
Ok(buf[..len].to_vec())
}
}
1.3 无线链路驱动示例
// src/adapter/communicators/wireless_radio.rs
use super::{HardwareBus, HardwareError};
pub struct LoRaRadio {
// 底层 SPI 或 UART 句柄
}
impl LoRaRadio {
pub fn init() -> Result<Self, HardwareError> {
// 初始化 SPI/UART 并配置频道、功率
Ok(LoRaRadio {})
}
}
impl HardwareBus for LoRaRadio {
fn send_frame(&self, frame: &[u8]) -> Result<(), HardwareError> {
// 通过无线发送
Ok(())
}
fn recv_frame(&self) -> Result<Vec<u8>, HardwareError> {
// 无线接收并返回
Ok(vec![])
}
}
2. 硬件 ↔ 软件 通信
模块路径:
- 驱动注册与状态:
src/adapter/context_awareness.rs
- REST API:
src/api/protocol_remote_api.rs
2.1 驱动注册与状态采集接口
// src/adapter/context_awareness.rs
use crate::adapter::communicators::HardwareBus;
use std::collections::HashMap;
use std::sync::{Arc, Mutex};
pub struct ContextRegistry {
drivers: Mutex<HashMap<String, Arc<dyn HardwareBus>>>,
}
impl ContextRegistry {
pub fn new() -> Self {
ContextRegistry {
drivers: Mutex::new(HashMap::new()),
}
}
/// 注册一个硬件驱动
pub fn register_driver(&self, name: &str, driver: Arc<dyn HardwareBus>) {
self.drivers.lock().unwrap().insert(name.into(), driver);
}
/// 列出所有驱动名称
pub fn list_drivers(&self) -> Vec<String> {
self.drivers.lock().unwrap().keys().cloned().collect()
}
}
2.2 REST 接口定义
// src/api/protocol_remote_api.rs
use actix_web::{get, post, web, HttpResponse, Responder};
use serde::{Deserialize, Serialize};
use std::sync::Arc;
use crate::adapter::context_awareness::ContextRegistry;
#[derive(Deserialize)]
pub struct HardwareCmd {
pub driver: String,
pub frame: Vec<u8>,
}
#[derive(Serialize)]
pub struct HardwareStatus {
pub driver: String,
pub ok: bool,
}
#[post("/hw/control")]
pub async fn control_hardware(
registry: web::Data<Arc<ContextRegistry>>,
cmd: web::Json<HardwareCmd>,
) -> impl Responder {
match registry
.drivers
.lock()
.unwrap()
.get(&cmd.driver)
.map(|d| d.send_frame(&cmd.frame))
{
Some(Ok(())) => HttpResponse::Ok().json("Sent"),
Some(Err(e)) => HttpResponse::BadRequest().json(format!("Error: {}", e)),
None => HttpResponse::NotFound().body("Driver not found"),
}
}
#[get("/hw/list")]
pub async fn list_drivers(registry: web::Data<Arc<ContextRegistry>>) -> impl Responder {
let list = registry.list_drivers();
HttpResponse::Ok().json(list)
}
2.3 gRPC Proto 示例(可选)
syntax = "proto3";
service HardwareControl {
rpc ListDrivers(Empty) returns (DriverList);
rpc SendCommand(HardwareCommand) returns (CommandResponse);
}
message Empty {}
message DriverList {
repeated string drivers = 1;
}
message HardwareCommand {
string driver = 1;
bytes frame = 2;
}
message CommandResponse {
bool success = 1;
string message = 2;
}
2.4 客户端调用示例
// 使用 reqwest 发送 REST 请求
use reqwest::Client;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let client = Client::new();
let resp = client
.post("http://localhost:8080/hw/control")
.json(&serde_json::json!({
"driver": "can0",
"frame": [0x01, 0x02, 0x03]
}))
.send()
.await?;
println!("响应: {:?}", resp.text().await?);
Ok(())
}
3. 软件 ↔ 软件 通信
模块路径:
- 事件总线:
src/event/protocol_event_bus.rs
- 流处理:
src/stream/protocol_event_stream_processor.rs
3.1 事件总线接口
// src/event/protocol_event_bus.rs
use async_trait::async_trait;
use std::sync::Arc;
pub type Topic = String;
pub type Payload = Vec<u8>;
#[derive(Clone)]
pub struct Event {
pub topic: Topic,
pub payload: Payload,
}
#[async_trait]
pub trait EventBus: Send + Sync {
/// 发布事件到指定主题
async fn publish(&self, event: Event);
/// 订阅某个主题,返回事件流
async fn subscribe(&self, topic: &str) -> Box<dyn futures::Stream<Item = Event> + Unpin + Send>;
}
3.2 流处理器示例
// src/stream/protocol_event_stream_processor.rs
use crate::event::protocol_event_bus::{Event, EventBus};
use futures::StreamExt;
pub struct HardwareEventForwarder {
bus: Arc<dyn EventBus>,
}
impl HardwareEventForwarder {
pub fn new(bus: Arc<dyn EventBus>) -> Self {
HardwareEventForwarder { bus }
}
pub async fn start(&self) {
let mut stream = self.bus.subscribe("hardware_events").await;
while let Some(event) = stream.next().await {
// 解码并转发到硬件总线
// let cmd = decode_hardware_cmd(&event.payload);
// hw_driver.send_frame(&cmd)?;
}
}
}
4. 代码控制与执行
模块路径:
- 脚本引擎:
src/script/protocol_scripting_engine.rs
- CLI:
src/application/cli/main.rs
4.1 脚本 API 扩展
// src/script/protocol_scripting_engine.rs
use rlua::{Lua, UserData, UserDataMethods, Value, Result as LuaResult};
use crate::adapter::communicators::HardwareBus;
use std::sync::Arc;
struct HwHandle {
driver: Arc<dyn HardwareBus>,
}
impl UserData for HwHandle {}
pub fn init_scripting_engine(registry: Arc<dyn Iterator<Item = Arc<dyn HardwareBus>>>) -> Lua {
let lua = Lua::new();
let hw_table = lua.create_table().unwrap();
for driver in registry {
let handle = HwHandle { driver: driver.clone() };
hw_table.set("exec", handle).unwrap();
}
lua.globals().set("hw", hw_table).unwrap();
lua
}
脚本中调用示例(Lua):
-- example.lua
local ok, res = pcall(function()
return hw.exec("can0", {0x01,0x02})
end)
print("HW exec result:", ok, res)
4.2 CLI 子命令示例
// src/application/cli/main.rs
use clap::{Parser, Subcommand};
#[derive(Parser)]
struct Cli {
#[command(subcommand)]
command: Commands,
}
#[derive(Subcommand)]
enum Commands {
/// 往硬件总线发送原始帧
BusSend {
#[arg(long)] driver: String,
#[arg(long)] frame: Vec<u8>,
},
/// 运行硬件控制脚本
RunScript {
#[arg(long)] script: String,
},
}
fn main() {
let cli = Cli::parse();
match cli.command {
Commands::BusSend { driver, frame } => {
// 加载 registry 并执行 send_frame
}
Commands::RunScript { script } => {
// 加载脚本引擎并执行脚本
}
}
}
Shell 使用示例:
# 1. 直接发送 CAN 帧
eaco-cli bus-send --driver can0 --frame 1 2 3
# 2. 运行脚本控制多种硬件
eaco-cli run-script --script ./example.lua
以上即为四大场景的完整接口规范与示例。如需进一步的测试用例、文档生成模板或多语言绑定示例,请继续告知!
硬件与硬件,硬件与软件,软件与软件通信,实现代码控制等等功能,添加到哪个模块合适,请帮忙标注一下,谢谢。