diff --git a/Windows/Rust/CubeLib/src/websocket/client.rs b/Windows/Rust/CubeLib/src/websocket/client.rs index 0b4373c..b71203f 100644 --- a/Windows/Rust/CubeLib/src/websocket/client.rs +++ b/Windows/Rust/CubeLib/src/websocket/client.rs @@ -637,7 +637,7 @@ impl WebSocketClient { /// Send a text message pub async fn send(&self, msg_type: &str, data: Value) -> Result<(), WebSocketError> { let message = WebSocketMessage::new(msg_type, data); - let json = serde_json::to_string(&message)?; + let json = message.to_json_string()?; self.send_raw_text(json).await } diff --git a/Windows/Rust/CubeLib/src/websocket/message.rs b/Windows/Rust/CubeLib/src/websocket/message.rs index 01b92eb..adf6cd2 100644 --- a/Windows/Rust/CubeLib/src/websocket/message.rs +++ b/Windows/Rust/CubeLib/src/websocket/message.rs @@ -45,6 +45,26 @@ impl WebSocketMessage { let data = serde_json::to_value(data)?; Ok(Self::new(msg_type, data)) } + + /// Serialize to JSON string with Type field first (required by MasterSuite protocol) + /// Note: serde's default serialization order follows field definition order, + /// but this method guarantees Type comes first regardless of any future changes + pub fn to_json_string(&self) -> Result { + let mut map = serde_json::Map::new(); + + // Type is always first + map.insert("Type".to_string(), serde_json::Value::String(self.msg_type.clone())); + + // Data field + map.insert("Data".to_string(), self.data.clone()); + + // MessageId (optional, skip if None) + if let Some(ref id) = self.id { + map.insert("MessageId".to_string(), serde_json::Value::String(id.clone())); + } + + serde_json::to_string(&map) + } } /// Client type enumeration