tplink_shome_protocol/lib.rs
1//! Simple library to easily communicate with a tp link smart device.
2//! # Usage
3//! ```rust
4//! use std::io;
5//! use std::net::TcpStream;
6//!
7//! use tplink_shome_protocol::{receive_message, send_message};
8//!
9//! fn main() -> io::Result<()> {
10//! let stream = TcpStream::connect("192.168.1.1:9999")?;
11//! let raw = r#"{"system":{"get_sysinfo":{}}}"#;
12//! send_message(&stream, raw)?;
13//! let message = receive_message(&stream)?;
14//! ...
15//! }
16//! ```
17use std::{
18 io::{self, Read, Write},
19 net::TcpStream,
20};
21
22pub fn encrypt(data: &[u8]) -> Vec<u8> {
23 let mut encryption_key = 0xAB;
24 data.iter()
25 .map(|e| {
26 let res = e ^ encryption_key;
27 encryption_key = res;
28 res
29 })
30 .collect()
31}
32
33pub fn decrypt(encrypted: &[u8]) -> Vec<u8> {
34 let mut encryption_key = 0xAB;
35 encrypted
36 .iter()
37 .map(|e| {
38 let res = e ^ encryption_key;
39 encryption_key = *e;
40 res
41 })
42 .collect()
43}
44
45///
46/// Blocks until it receives a message from the [TcpStream]
47///
48/// Example
49/// ```
50///use std::io;
51///use std::net::TcpStream;
52///
53///use tplink_shome_protocol::receive_message;
54///
55///fn main() -> io::Result<()> {
56/// let stream = TcpStream::connect("192.168.1.1:9999")?;
57/// let response = receive_message(&stream)?;
58/// ...
59///}
60/// ```
61///
62pub fn receive_message(mut stream: &TcpStream) -> io::Result<String> {
63 let mut lenbuff = [0; 4];
64 stream.read_exact(&mut lenbuff)?;
65 let num = u32::from_be_bytes(lenbuff);
66 let mut buffer: Vec<u8> = vec![0; num as usize];
67 stream.read_exact(&mut buffer)?;
68 let decrypted = decrypt(&buffer);
69 match std::str::from_utf8(&decrypted) {
70 Ok(v) => Ok(v.to_string()),
71 Err(e) => Err(io::Error::new(
72 io::ErrorKind::InvalidData,
73 format!("received message is invalid {e}"),
74 )),
75 }
76}
77
78///
79/// Sends a message to the smart device connected via the [TcpStream]
80///
81/// Example
82/// ```
83///use std::io;
84///use std::net::TcpStream;
85///
86/// use tplink_shome_protocol::send_message;
87///
88///fn main() -> io::Result<()> {
89/// let stream = TcpStream::connect("192.168.1.1:9999")?;
90/// let raw = r#"{"system":{"get_sysinfo":{}}}"#;
91/// let response = receive_message(&stream)?;
92/// ...
93///}
94/// ```
95///
96pub fn send_message(mut stream: &TcpStream, message: &str) -> io::Result<()> {
97 let encrypted = encrypt(message.as_bytes());
98 let b32len: u32 = encrypted.len() as u32;
99 let lenbytes = b32len.to_be_bytes();
100
101 // send first length of data
102 stream.write_all(&lenbytes)?;
103
104 stream.write_all(&encrypted)?;
105 Ok(())
106}