|
|
@@ -2,6 +2,7 @@ use awc::{Client, BoxedSocket, ws::{Frame, Message, Codec}};
|
|
|
use actix_codec::Framed;
|
|
|
use futures_util::{SinkExt, StreamExt};
|
|
|
use serde_json::{Value, from_str, json};
|
|
|
+use tokio::sync::mpsc;
|
|
|
|
|
|
pub async fn connect_to_ha(
|
|
|
ip: String,
|
|
|
@@ -51,37 +52,64 @@ pub async fn connect_to_ha(
|
|
|
Err("Websocket closed before authentication completed".into())
|
|
|
}
|
|
|
|
|
|
-pub async fn listen(mut connection: Framed<BoxedSocket, Codec>) {
|
|
|
- let mut message_id = 1;
|
|
|
+pub async fn listen(
|
|
|
+ ip: String,
|
|
|
+ token: String,
|
|
|
+ mut outbound_rx: mpsc::UnboundedReceiver<Message>
|
|
|
+) {
|
|
|
+ loop {
|
|
|
+ let mut connection = match connect_to_ha(ip.clone(), token.clone()).await {
|
|
|
+ Ok(c) => c,
|
|
|
+ Err(e) => {
|
|
|
+ eprintln!("Failed to connect to HA: {e}. Retrying in 10s...");
|
|
|
+ tokio::time::sleep(std::time::Duration::from_secs(10)).await;
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ };
|
|
|
|
|
|
- while let Some(Ok(msg)) = connection.next().await {
|
|
|
- match msg {
|
|
|
- Frame::Text(bytes) => {
|
|
|
- let text = match String::from_utf8(bytes.to_vec()) {
|
|
|
- Ok(t) => t,
|
|
|
- Err(_) => continue
|
|
|
- };
|
|
|
- let parsed: Value = match from_str(&text) {
|
|
|
- Ok(v) => v,
|
|
|
- Err(_) => continue
|
|
|
- };
|
|
|
+ loop {
|
|
|
+ tokio::select! {
|
|
|
+ msg = connection.next() => {
|
|
|
+ match msg {
|
|
|
+ Some(Ok(Frame::Text(bytes))) => {
|
|
|
+ let text = match String::from_utf8(bytes.to_vec()) {
|
|
|
+ Ok(t) => t,
|
|
|
+ Err(_) => continue
|
|
|
+ };
|
|
|
+ let parsed: Value = match from_str(&text) {
|
|
|
+ Ok(v) => v,
|
|
|
+ Err(_) => continue
|
|
|
+ };
|
|
|
|
|
|
- if parsed["type"] == "result" {
|
|
|
- println!("result");
|
|
|
- println!("{:#?}", parsed);
|
|
|
+ if parsed["type"] == "result" {
|
|
|
+ println!("result");
|
|
|
+ println!("{:#?}", parsed);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ Some(Ok(Frame::Ping(bytes))) => {
|
|
|
+ let _ = connection.send(Message::Pong(bytes)).await;
|
|
|
+ }
|
|
|
+ Some(Ok(Frame::Close(reason))) => {
|
|
|
+ println!("HA closed connection: {:?}", reason);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ Some(Err(e)) => {
|
|
|
+ eprintln!("Websocket error: {e}");
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ None => break,
|
|
|
+ _ => {}
|
|
|
+ }
|
|
|
+ }
|
|
|
+ Some(out_msg) = outbound_rx.recv() => {
|
|
|
+ if let Err(e) = connection.send(out_msg).await {
|
|
|
+ eprintln!("Failed to send outbound message: {e}");
|
|
|
+ }
|
|
|
}
|
|
|
- },
|
|
|
- Frame::Ping(bytes) => {
|
|
|
- let _ = connection.send(Message::Pong(bytes)).await;
|
|
|
- },
|
|
|
- Frame::Close(reason) => {
|
|
|
- println!("HA closed connection {:?}", reason);
|
|
|
-
|
|
|
-
|
|
|
- },
|
|
|
- _ => {}
|
|
|
+ }
|
|
|
}
|
|
|
- }
|
|
|
|
|
|
- println!("HA websocket connection closed");
|
|
|
+ println!("HA connection closed, reconnecting in 10s...");
|
|
|
+ tokio::time::sleep(std::time::Duration::from_secs(10)).await;
|
|
|
+ }
|
|
|
}
|