def to_xml(self): ctl = ET.Element('ctl', {'td': self.name}) for key, value in self.args.items(): if type(value) is dict: inner = ET.Element(key, value) ctl.append(inner) else: ctl.set(key, value) return ctl
def to_xml(self): ctl = ET.Element('ctl', {'td': self.name}) for key, value in self.args.items(): if type(value) is dict: inner = ET.Element(key, value) ctl.append(inner) elif type(value) is list: for item in value: ixml = self.listobject_to_xml(key, item) ctl.append(ixml) else: ctl.set(key, value) return ctl
def _ctl_to_dict_api(self, action, xmlstring): xml = ET.fromstring(xmlstring) xmlchild = xml.getchildren() if len(xmlchild) > 0: result = xmlchild[0].attrib.copy() #Fix for difference in XMPP vs API response #Depending on the report will use the tag and add "report" to fit the mold of sucks library if xmlchild[0].tag == "clean": result['event'] = "CleanReport" elif xmlchild[0].tag == "charge": result['event'] = "ChargeState" elif xmlchild[0].tag == "battery": result['event'] = "BatteryInfo" else: #Default back to replacing Get from the api cmdName result['event'] = action.name.replace("Get", "", 1) else: result = xml.attrib.copy() result['event'] = action.name.replace("Get", "", 1) if 'ret' in result: #Handle errors as needed if result['ret'] == 'fail': if action.name == "Charge": #So far only seen this with Charge, when already docked result['event'] = "ChargeState" for key in result: if not RepresentsInt( result[key]): #Fix to handle negative int values result[key] = stringcase.snakecase(result[key]) return result
def _handle_battery_info(self, iq): try: self.battery_status = float(iq['power']) / 100 except ValueError: _LOGGER.warning("couldn't parse battery status " + ET.tostring(iq)) else: self.batteryEvents.notify(self.battery_status) _LOGGER.debug("*** battery_status = {:.0%}".format(self.battery_status))
def listobject_to_xml(self, tag, conv_object): rtnobject = ET.Element(tag) if type(conv_object) is dict: for key, value in conv_object.items(): rtnobject.set(key, value) else: rtnobject.set(tag, conv_object) return rtnobject
def _wrap_command(self, cmd, recipient): #Remove the td from ctl xml for RestAPI payloadxml = cmd.to_xml() payloadxml.attrib.pop("td") return { 'auth': { 'realm': EcoVacsAPI.REALM, 'resource': self.resource, 'token': self.secret, 'userid': self.user, 'with': 'users', }, "cmdName": cmd.name, "payload": ET.tostring(payloadxml).decode(), "payloadType": "x", "td": "q", "toId": recipient, "toRes": self.vacuum['resource'], "toType": self.vacuum['class'] }
def _ctl_to_dict_mqtt(self, topic, xmlstring): #I haven't seen the need to fall back to data within the topic (like we do with IOT rest call actions), but it is here in case of future need xml = ET.fromstring( xmlstring ) #Convert from string to xml (like IOT rest calls), other than this it is similar to XMPP #Including changes from jasonarends @ 28da7c2 below result = xml.attrib.copy() if 'td' not in result: # This happens for commands with no response data, such as PlaySound # Handle response data with no 'td' if 'type' in result: # single element with type and val result[ 'event'] = "LifeSpan" # seems to always be LifeSpan type else: if len(xml) > 0: # case where there is child element if 'clean' in xml[0].tag: result['event'] = "CleanReport" elif 'charge' in xml[0].tag: result['event'] = "ChargeState" elif 'battery' in xml[0].tag: result['event'] = "BatteryInfo" else: return result.update(xml[0].attrib) else: # for non-'type' result with no child element, e.g., result of PlaySound return else: # response includes 'td' result['event'] = result.pop('td') if xml: result.update(xml[0].attrib) for key in result: #Check for RepresentInt to handle negative int values, and ',' for ignoring position updates if not RepresentsInt(result[key]) and ',' not in result[key]: result[key] = stringcase.snakecase(result[key]) return result
def send_ping(self, to): q = self.make_iq_get(ito=to, ifrom=self._my_address()) q.xml.append(ET.Element('ping', {'xmlns': 'urn:xmpp:ping'})) _LOGGER.debug("*** sending ping ***") q.send()