def __init__(self, device_ip, device_id): # Get this from any of the Midea based apps, you can find one on Yitsushi's github page self.device_ip = device_ip self.device_id = device_id self.device_port = 6444 self.security = security() self._retries = 0
def __init__(self, device_id): self.command = None self.security = security() # aa20ac00000000000003418100ff03ff000200000000000000000000000006f274 # Init the packet with the header data. self.packet = bytearray([ # 2 bytes - StaicHeader 0x5a, 0x5a, # 2 bytes - mMessageType 0x01, 0x11, # 1 bytes - PacketLenght 0x68, # 3 bytes 0x00, 0x20, 0x00, # 4 bytes - MessageId 0x00, 0x00, 0x00, 0x00, # 8 bytes - Date&Time 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, # 6 bytes - mDeviceID 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, # 14 bytes 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ]) _LOGGER.debug("add packet_time") self.packet[12:20] = self.packet_time() self.packet[20:26] = bytearray.fromhex(device_id)
def __init__(self, device_id: int): self.command = None self.security = security() # aa20ac00000000000003418100ff03ff000200000000000000000000000006f274 # Init the packet with the header data. self.packet = bytearray([ # 2 bytes - StaicHeader 0x5a, 0x5a, # 2 bytes - mMessageType 0x01, 0x11, # 2 bytes - PacketLenght 0x00, 0x00, # 2 bytes 0x20, 0x00, # 4 bytes - MessageId 0x00, 0x00, 0x00, 0x00, # 8 bytes - Date&Time 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, # 6 bytes - mDeviceID 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, # 12 bytes 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ]) self.packet[12:20] = self.packet_time() self.packet[20:28] = device_id.to_bytes(8, 'little')
def discover(debug: int): """Discover Midea Devices with UDP Broadcast""" if debug: logging.basicConfig(level=logging.DEBUG) _LOGGER.info("Debug mode active") else: logging.basicConfig(level=logging.INFO) _security = security() sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEPORT, 1) sock.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1) sock.settimeout(5) found_devices = {} _LOGGER.info("msmart version: {}".format(VERSION)) _LOGGER.info( "Discovering devices with UDP Broadcast, press CTRL-C to quit...") for i in range(10): try: sock.sendto(BROADCAST_MSG, ("255.255.255.255", 6445)) while True: data, addr = sock.recvfrom(512) m_ip = addr[0] m_id, m_type, m_sn, m_ssid = 'unknown', 'unknown', 'unknown', 'unknown' if len(data) >= 104 and (data[:2].hex() == '5a5a' or data[8:10].hex() == '5a5a' ) and m_ip not in found_devices: _LOGGER.info("Midea Local Data {} {}".format( m_ip, data.hex())) if data[8:10].hex() == '5a5a': data = data[8:-16] m_id = convert_device_id_int(data[20:26].hex()) found_devices[m_ip] = m_id encrypt_data = data[40:-16] reply = _security.aes_decrypt(encrypt_data) m_sn = reply[14:14 + 26].decode("utf-8") # ssid like midea_xx_xxxx net_xx_xxxx m_ssid = reply[14 + 27:14 + 27 + 13].decode("utf-8") m_type = m_ssid.split('_')[1] m_support = support_test(m_ip, int(m_id)) _LOGGER.info( "*** Found a {} '0x{}' at {} - id: {} - sn: {} - ssid: {}" .format(m_support, m_type, m_ip, m_id, m_sn, m_ssid)) elif m_ip not in found_devices: _LOGGER.info("Maybe not midea local data {} {}".format( m_ip, data.hex())) except socket.timeout: continue except KeyboardInterrupt: sys.exit(0)
def __init__(self, device_ip, device_id, device_port=6444): self.device_ip = device_ip self.device_id = device_id self.device_port = device_port self.security = security() self._retries = 0 self._socket = None self._token = None self._key = None self._timestamp = time.time() self._tcp_key = None self._local = None self._remote = device_ip + ":" + str(device_port)
def discover(debug: int): """Discover Midea Devices with UDP Broadcast""" if debug: logging.basicConfig(level=logging.DEBUG) _LOGGER.info("Debug mode active") else: logging.basicConfig(level=logging.INFO) _security = security() sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEPORT, 1) sock.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1) sock.settimeout(5) found_devices = {} _LOGGER.info( "Discovering devices with UDP Broadcast, press CTRL-C to quit...") for i in range(10): try: sock.sendto(BROADCAST_MSG, ("255.255.255.255", 6445)) while True: data, addr = sock.recvfrom(512) m_ip = addr[0] if len(data) >= 41 and m_ip not in found_devices: m_id = convert_device_id_int(data[20:26].hex()) found_devices[m_ip] = m_id data = data[40:40 + 64] reply = _security.aes_decrypt(data) m_sn = reply[14:14 + 26].decode("utf-8") m_ssid = reply[14 + 27:].decode("utf-8") m_type = m_ssid.split('_')[1] m_support = 'unknown' if m_type == 'ac': m_support = support_test(m_ip, int(m_id)) _LOGGER.info( "Found a {} '0x{}' at {} - id: {} - sn: {} - ssid: {}". format(m_support, m_type, m_ip, m_id, m_sn, m_ssid)) except socket.timeout: continue except KeyboardInterrupt: sys.exit(0)
def __init__(self, email, password): # Get this from any of the Midea based apps, you can find one on Yitsushi's github page # self.app_key = app_key self.login_account = email # Your email address for your Midea account self.password = password # An obscure log in ID that is seperate to the email address self.login_id = None # A session dictionary that holds the login information of the current user self.session = {} # A list of home groups used by the API to seperate "zones" self.home_groups = [] # A list of appliances associated with the account self.appliance_list = [] self._api_lock = Lock() self.security = security() self._retries = 0
def discover(debug: int): """Send Device Scan Broadcast""" if debug: logging.basicConfig(level=logging.DEBUG) _LOGGER.info("Debug mode active") else: logging.basicConfig(level=logging.INFO) _security = security() sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) sock.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1) try: sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEPORT, 1) except AttributeError: # Will be raised when executed in Windows. Safe to ignore. pass sock.settimeout(5) found_devices = {} _LOGGER.info("msmart version: {}".format(VERSION)) _LOGGER.info("Sending Device Scan Broadcast...") for i in range(10): try: sock.sendto(BROADCAST_MSG, ("255.255.255.255", 6445)) sock.sendto(BROADCAST_MSG, ("255.255.255.255", 20086)) while True: data, addr = sock.recvfrom(512) m_ip = addr[0] if m_ip in found_devices: continue m_id, m_type, m_sn, m_ssid, m_version, m_support = 'unknown', 'unknown', 'unknown', 'unknown', 'unknown', 'unknown' if len(data) >= 104 and (data[:2].hex() == '5a5a' or data[8:10].hex() == '5a5a'): _LOGGER.info("Midea Local Data {} {}".format( m_ip, data.hex())) data_string = data.decode("utf-8", errors="replace") # _LOGGER.info(data.decode("utf-8", errors="replace")) # root=ET.fromstring(data.decode(encoding="utf-8", errors="replace")) if data[:2].hex() == '5a5a': m_version = 'V2' if data[:2].hex() == '8370': m_version = 'V3' if data[8:10].hex() == '5a5a': data = data[8:-16] m_id = convert_device_id_int(data[20:26].hex()) found_devices[m_ip] = m_id encrypt_data = data[40:-16] reply = _security.aes_decrypt(encrypt_data) _LOGGER.info("Decrypt Reply: {} {}".format( m_ip, reply.hex())) m_ip = '.'.join([str(i) for i in reply[3::-1]]) m_port = str(bytes2port(reply[4:8])) m_sn = reply[8:40].decode("utf-8") # ssid like midea_xx_xxxx net_xx_xxxx m_ssid = reply[41:41 + reply[40]].decode("utf-8") # if len(reply) > 54: m_type = m_ssid.split('_')[1] m_support = support_test(m_ip, int(m_id), int(m_port)) _LOGGER.info( "*** Found a {} device - type: '0x{}' - version: {} - ip: {} - port: {} - id: {} - sn: {} - ssid: {}" .format(m_support, m_type, m_version, m_ip, m_port, m_id, m_sn, m_ssid)) if data[:6].hex() == '3c3f786d6c20': m_version = 'V1' root = ET.fromstring( data.decode(encoding="utf-8", errors="replace")) child = root.find('body/device') m = child.attrib m_port, m_sn, m_type = m['port'], m['apc_sn'], str( hex(int(m['apc_type'])))[2:] response = get_device_info(m_ip, int(m_port)) m_id = get_id_from_response(response) _LOGGER.info( "*** Found a {} device - type: '0x{}' - version: {} - ip: {} - port: {} - id: {} - sn: {} - ssid: {}" .format(m_support, m_type, m_version, m_ip, m_port, m_id, m_sn, m_ssid)) except socket.timeout: continue except KeyboardInterrupt: sys.exit(0)
parser.add_argument('-f', "--fiter_type", type=str, dest="fiter_type", help='fliter type from midea message', default='all', choices=['all', 'get', 'reply', 'set', 'unknown', 'error']) parser.add_argument("--tcp-raw", action='store_true') parser.add_argument("--msg-raw", action='store_true') args = parser.parse_args() cap = pyshark.FileCapture( args.pcapfile, display_filter=("tcp && data.len == 104 && data[:2] == 5a5a")) _security = security() for packet in cap: packet.data.raw_mode = True tcp_data = packet.data.data tcp_data_bytes = bytearray.fromhex(tcp_data) tcp_data_len = int(tcp_data_bytes[4:5].hex(), 16) if len(tcp_data_bytes) != tcp_data_len: continue device_id = tcp_data_bytes[20:26].hex() midea_data = tcp_data_bytes[40:88] reply = _security.aes_decrypt(midea_data) msg_type_hex = 255 msg_type = 'error'
def __init__(self, device_ip, device_id, device_port=6444): self.device_ip = device_ip self.device_id = device_id self.device_port = device_port self.security = security() self._retries = 0