Skip to content

Commit

Permalink
Merge pull request #9 from jonatino/main
Browse files Browse the repository at this point in the history
Add support for sending luna commands
  • Loading branch information
kziemianek authored Oct 7, 2024
2 parents fd39270 + e7a6f9a commit e28b152
Show file tree
Hide file tree
Showing 3 changed files with 74 additions and 14 deletions.
20 changes: 10 additions & 10 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,15 @@ license-file = "LICENSE"
keywords = ["lg", "webos", "client"]

[dependencies]
tokio-tungstenite = "0.18.0"
futures = "0.3.25"
futures-util = "0.3.25"
tokio = { version = "1.24.1", default-features = false, features = ["rt"] }
url = "2.3.1"
serde_json = "1.0.91"
serde = { version = "1.0.152", features = ["derive"]}
log = "0.4.17"
tokio-tungstenite = { version = "0.24.0", features = ["url"]}
futures = "0.3.31"
futures-util = "0.3.31"
tokio = { version = "1.40.0", default-features = false, features = ["rt"] }
url = "2.5.2"
serde_json = "1.0.128"
serde = { version = "1.0.210", features = ["derive"]}
log = "0.4.22"

[dev-dependencies]
env_logger = "0.10.0"
tokio = { version = "1.24.1", default-features = false, features = ["full"] }
env_logger = "0.11.5"
tokio = { version = "1.40.0", default-features = false, features = ["full"] }
52 changes: 49 additions & 3 deletions src/client/mod.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use futures::channel::oneshot;
use futures::channel::oneshot::{Receiver, Sender};
use futures::{Sink, Stream, StreamExt};
use futures_util::lock::Mutex;
use futures_util::stream::SplitSink;
Expand All @@ -6,10 +8,8 @@ use futures_util::{
SinkExt,
};
use log::debug;
use serde_json::Value;
use serde_json::{json, Value};
use std::{collections::HashMap, sync::Arc};
use futures::channel::oneshot;
use futures::channel::oneshot::{Receiver, Sender};
use tokio_tungstenite::tungstenite::Error;
use tokio_tungstenite::{
connect_async, tungstenite::protocol::Message, MaybeTlsStream, WebSocketStream,
Expand Down Expand Up @@ -164,6 +164,52 @@ where
.collect())
}

/// Sends a special luna command and waits for response
pub async fn send_luna_command(
&self,
luna_uri: &'static str,
params: Value,
) -> Result<CommandResponse, ClientError> {
// https://github.com/chros73/bscpylgtv/blob/master/bscpylgtv/webos_client.py#L1098
// n.b. this is a hack which abuses the alert API
// to call the internal luna API which is otherwise
// not exposed through the websocket interface
// An important limitation is that any returned
// data is not accessible

// set desired action for click, fail and close
// for redundancy/robustness

let luna_uri = format!("luna://{}", luna_uri);

let buttons = vec![json!({
"label": "",
"onClick": luna_uri,
"params": params
})];

let payload = json!({
"message": " ",
"buttons": buttons,
"onclose": {"uri": luna_uri, "params": params},
"onfail": {"uri": luna_uri, "params": params},
});

let alert = self.send_command(Command::CreateAlert(payload)).await?;

let alert_id = alert.payload.map(|v| {
let str = v["alertId"].as_str().unwrap();
// We first need to convert to str before calling to_string else this does not parse properly.
str.to_string()
});

if let Some(alert_id) = alert_id {
self.send_command(Command::CloseAlert(alert_id)).await
} else {
Err(ClientError::CommandSendError)
}
}

async fn prepare_command_to_send(
&self,
cmd: Command,
Expand Down
16 changes: 15 additions & 1 deletion src/command/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,14 @@ use serde_json::{json, Value};
#[serde(rename_all = "camelCase")]
pub struct CommandRequest {
id: String,
r#type: String,
r#type: String, // Required by lg api
uri: String,
payload: Option<Value>,
}

pub enum Command {
CreateAlert(Value),
CloseAlert(String),
CreateToast(String),
OpenBrowser(String),
TurnOff,
Expand Down Expand Up @@ -46,6 +48,18 @@ pub struct CommandResponse {

pub fn create_command(id: String, cmd: Command) -> CommandRequest {
match cmd {
Command::CreateAlert(payload) => CommandRequest {
id,
r#type: String::from("request"),
uri: String::from("ssap://system.notifications/createAlert"),
payload: Some(payload),
},
Command::CloseAlert(alert_id) => CommandRequest {
id,
r#type: String::from("request"),
uri: String::from("ssap://system.notifications/closeAlert"),
payload: Some(json!({"alertId": alert_id})),
},
Command::CreateToast(text) => CommandRequest {
id,
r#type: String::from("request"),
Expand Down

0 comments on commit e28b152

Please sign in to comment.