|
@@ -1,51 +1,99 @@
|
|
|
+use crate::ems::bms::bms::Bms;
|
|
|
use crate::ems::pcs::pcs::Pcs;
|
|
|
use crate::ems::Service;
|
|
|
use crate::internal::utils;
|
|
|
+use log::info;
|
|
|
use std::collections::HashMap;
|
|
|
use std::sync::Arc;
|
|
|
use tokio::sync;
|
|
|
use tokio::sync::Mutex;
|
|
|
|
|
|
-type ServiceChannels = Arc<HashMap<String, Mutex<sync::mpsc::Receiver<String>>>>;
|
|
|
+/// 抽象设备结构
|
|
|
+/// id: 设备唯一ID
|
|
|
+/// name: 设备名称
|
|
|
+/// service: 设备的服务
|
|
|
+/// channel: 广播接收器
|
|
|
+pub struct Device {
|
|
|
+ pub id: String,
|
|
|
+ pub name: String,
|
|
|
+ pub service: Arc<Mutex<dyn Service>>,
|
|
|
+ pub channel: Arc<Mutex<sync::mpsc::Receiver<String>>>,
|
|
|
+}
|
|
|
|
|
|
-/// services 是所有实现了Service接口的设备集合
|
|
|
-/// tx 是EMU向其他设备广播消息的发送器
|
|
|
-/// service_channels 是所有设备向EMU发送消息的通道集合
|
|
|
+/// EMU 能量管理处理单元
|
|
|
+/// devices: 设备集合
|
|
|
+/// tx: 广播发生器
|
|
|
pub struct Emu {
|
|
|
- pub services: Vec<Arc<Mutex<dyn Service>>>,
|
|
|
+ pub devices: HashMap<String, Arc<Device>>,
|
|
|
pub tx: sync::broadcast::Sender<String>,
|
|
|
- pub service_channels: ServiceChannels,
|
|
|
}
|
|
|
+
|
|
|
impl Emu {
|
|
|
+ /// 创建EMU实例
|
|
|
pub async fn new() -> Self {
|
|
|
//初始化日志
|
|
|
utils::log::init_log("inpower_iot_mgc_rs::ems::emu::*", "logs/emu.log").await;
|
|
|
+ //EMU消息广播器
|
|
|
let (tx, _) = sync::broadcast::channel::<String>(8);
|
|
|
- let mut services: Vec<Arc<Mutex<dyn Service>>> = Vec::new();
|
|
|
- let mut service_channels = HashMap::new();
|
|
|
- log::info!("EMU初始化完成");
|
|
|
- //↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ 创建PCS
|
|
|
- let (pcs_tx, pcs_rx) = sync::mpsc::channel::<String>(8);
|
|
|
- let pcs = Arc::new(Mutex::new(Pcs::new(pcs_tx, tx.subscribe()).await));
|
|
|
- services.push(pcs);
|
|
|
- service_channels.insert(1.to_string(), Mutex::new(pcs_rx));
|
|
|
- //↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑
|
|
|
- Emu {
|
|
|
- services,
|
|
|
- service_channels: Arc::new(service_channels),
|
|
|
- tx,
|
|
|
+ let mut devices = HashMap::new();
|
|
|
+ info!("EMU初始化完成");
|
|
|
+ {
|
|
|
+ //↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ 创建PCS
|
|
|
+ let (pcs_tx, pcs_rx) = sync::mpsc::channel::<String>(8);
|
|
|
+ let pcs = Arc::new(Mutex::new(Pcs::new(pcs_tx, tx.subscribe()).await));
|
|
|
+ let pcs_dev = Device {
|
|
|
+ id: "".to_string(),
|
|
|
+ name: "PCS".to_string(),
|
|
|
+ service: pcs,
|
|
|
+ channel: Arc::new(Mutex::new(pcs_rx)),
|
|
|
+ };
|
|
|
+ devices.insert("pcs".to_string(), Arc::new(pcs_dev));
|
|
|
+ //↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑
|
|
|
+
|
|
|
+ //↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ 创建BMS
|
|
|
+ let (bms_tx, bms_rx) = sync::mpsc::channel::<String>(8);
|
|
|
+ let bms = Arc::new(Mutex::new(Bms::new(bms_tx, tx.subscribe()).await));
|
|
|
+ let bms_dev = Device {
|
|
|
+ id: "".to_string(),
|
|
|
+ name: "".to_string(),
|
|
|
+ service: bms,
|
|
|
+ channel: Arc::new(Mutex::new(bms_rx)),
|
|
|
+ };
|
|
|
+ devices.insert("bms".to_string(), Arc::new(bms_dev));
|
|
|
+ //↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑
|
|
|
}
|
|
|
+ Emu { devices, tx }
|
|
|
}
|
|
|
|
|
|
pub async fn run(self: Arc<Self>) {
|
|
|
let mut handles = Vec::new();
|
|
|
- for service in self.services.iter() {
|
|
|
- let service_clone = service.clone();
|
|
|
- let handle = tokio::spawn(async move {
|
|
|
- service_clone.lock().await.serve().await;
|
|
|
+ for (_tp, dev) in self.devices.iter() {
|
|
|
+ //启动协程处理服务
|
|
|
+ let handle = tokio::spawn({
|
|
|
+ //Arc指针计数+1
|
|
|
+ let dev_clone = Arc::clone(dev);
|
|
|
+ async move {
|
|
|
+ //启动服务, serve()函数签名是&self, 暂时可以不用Mutex锁
|
|
|
+ dev_clone.service.clone().lock().await.serve().await;
|
|
|
+ }
|
|
|
});
|
|
|
handles.push(handle);
|
|
|
}
|
|
|
+ let x = &self.devices;
|
|
|
+ let a = x.get(&"pcs".to_string()).unwrap().clone();
|
|
|
+ tokio::spawn(async move {
|
|
|
+ loop {
|
|
|
+ let str = a.channel.lock().await.recv().await.unwrap();
|
|
|
+ info!("[BMS] {}", str)
|
|
|
+ }
|
|
|
+ });
|
|
|
+ let sender = self.tx.clone();
|
|
|
+ tokio::spawn(async move {
|
|
|
+ loop {
|
|
|
+ sender.send(String::from("BMS发出了信号")).unwrap();
|
|
|
+ tokio::time::sleep(tokio::time::Duration::from_secs(5)).await;
|
|
|
+ }
|
|
|
+ });
|
|
|
for handler in handles {
|
|
|
match handler.await {
|
|
|
Ok(_) => {}
|