1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126
extern crate xml; extern crate regex; use std::io::Result; use http::exec; pub struct YamahaAvr { ip: String } #[derive(Debug, Clone)] pub struct SystemConfig { pub inputs: Vec<Input> } #[derive(Debug, Clone)] pub struct Input { pub name: String, pub display_name: Option<String> } fn parse_system_config(xml: String) -> Result<SystemConfig> { let mut reader = xml::reader::EventReader::from_str(&xml); let mut inputs: Vec<Input> = Vec::new(); let mut in_inputs = false; let mut current_input: Option<Input> = None; for e in reader { match e { Ok(xml::reader::XmlEvent::StartElement { name, .. }) => { if name.local_name == "Input" { in_inputs = true; }else if in_inputs { current_input = Some(Input { name: name.local_name, display_name: None }); } } Ok(xml::reader::XmlEvent::EndElement { name, .. }) => { if in_inputs { if name.local_name == "Input" { in_inputs = false; }else { inputs.push(current_input.unwrap()); current_input = None; } } } Ok(xml::reader::XmlEvent::Characters(s)) => { if in_inputs && current_input.is_some() { current_input = Some(Input { name: current_input.unwrap().name, display_name: Some(s.trim().to_owned()) }); } } _ => {} } } let regex = regex::Regex::new(r"^([A-Z]+)_([0-9]+)$").unwrap(); let inputs: Vec<Input> = inputs.iter_mut() .map(|input| { let i = input.clone(); let mut name: String = i.name; if input.name == "V_AUX" { name = "V-AUX".to_owned(); }else { let iname = name.clone(); let cap = regex.captures(&iname); if cap.is_some() { let cap = cap.unwrap(); name = format!("{}{}", &cap[1], &cap[2]) } } Input { name, display_name: i.display_name } }).collect(); Ok(SystemConfig { inputs }) } impl YamahaAvr { pub fn new(ip: String) -> YamahaAvr { YamahaAvr { ip } } fn exec(&mut self, xml: String) -> Result<()> { exec(self.ip.clone(), xml) } pub fn power(&mut self, value: bool) -> Result<()> { let cmd = format!("<YAMAHA_AV cmd=\"PUT\"><Main_Zone><Power_Control><Power>{}</Power></Power_Control></Main_Zone></YAMAHA_AV>", if value { "On" } else { "Standby" }); self.exec(cmd).unwrap(); Ok(()) } pub fn mute(&mut self, value: bool) -> Result<()> { let cmd = format!("<YAMAHA_AV cmd=\"PUT\"><Main_Zone><Volume><Mute>{}</Mute></Volume></Main_Zone></YAMAHA_AV>", if value { "On" } else { "Off" }); self.exec(cmd).unwrap(); Ok(()) } pub fn select_input(&mut self, input: String) -> Result<()> { let cmd = format!("<YAMAHA_AV cmd=\"PUT\"><Main_Zone><Input><Input_Sel>{}</Input_Sel></Input></Main_Zone></YAMAHA_AV>", input); self.exec(cmd).unwrap(); Ok(()) } pub fn get_inputs(&mut self) -> Result<Vec<Input>> { let config = self.get_system_config()?; Ok(config.inputs) } fn get_system_config(&mut self) -> Result<SystemConfig> { let cmd = "<YAMAHA_AV cmd=\"GET\"><System><Config>GetParam</Config></System></YAMAHA_AV>".to_owned(); let res = "<YAMAHA_AV rsp=\"GET\" RC=\"0\"><System><Config><Model_Name>RX-V473</Model_Name><System_ID>05852093</System_ID><Version>1.14/1.04</Version><Feature_Existence><Main_Zone>1</Main_Zone><Zone_2>0</Zone_2><Zone_3>0</Zone_3><Zone_4>0</Zone_4><Tuner>1</Tuner><HD_Radio>0</HD_Radio><Rhapsody>0</Rhapsody><SIRIUS_IR>0</SIRIUS_IR><Pandora>0</Pandora><SERVER>1</SERVER><NET_RADIO>1</NET_RADIO><USB>1</USB><iPod_USB>1</iPod_USB><AirPlay>1</AirPlay></Feature_Existence><Name><Input><HDMI_1> Chrome </HDMI_1><HDMI_2>Raspberry</HDMI_2><HDMI_3> PC </HDMI_3><HDMI_4> Game </HDMI_4><AV_1> </AV_1><AV_2> PC </AV_2><AV_3> TV </AV_3><AV_4> </AV_4><AV_5> Wii </AV_5><AV_6>Turntable</AV_6><V_AUX> V-AUX </V_AUX><USB> USB </USB></Input></Name></Config></System></YAMAHA_AV>".to_owned(); parse_system_config(res) } }