|
|
- """Daikin device discovery."""
- import socket
-
- from datetime import timedelta
- from urllib.parse import unquote
-
- DISCOVERY_MSG = b"DAIKIN_UDP/common/basic_info"
-
- UDP_SRC_PORT = 30000
- UDP_DST_PORT = 30050
-
- DISCOVERY_ADDRESS = '<broadcast>'
- DISCOVERY_TIMEOUT = timedelta(seconds=2)
-
-
- class Daikin:
- """Base class to discover Daikin devices."""
-
- def __init__(self):
- """Initialize the Daikin discovery."""
- self.entries = []
-
- def scan(self):
- """Scan the network."""
- self.update()
-
- def all(self):
- """Scan and return all found entries."""
- self.scan()
- return self.entries
-
- def update(self):
- """Scan network for Daikin devices."""
- entries = []
-
- sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
- sock.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
- sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
- sock.settimeout(DISCOVERY_TIMEOUT.seconds)
- sock.bind(("", UDP_SRC_PORT))
-
- try:
-
- sock.sendto(DISCOVERY_MSG, (DISCOVERY_ADDRESS, UDP_DST_PORT))
-
- while True:
- try:
- data, (address, _) = sock.recvfrom(1024)
-
- # pylint: disable=consider-using-dict-comprehension
- entry = dict([e.split('=')
- for e in data.decode("UTF-8").split(',')])
-
- # expecting product, mac, activation code, version
- if 'ret' not in entry or entry['ret'] != 'OK':
- # non-OK return on response
- continue
-
- if 'mac' not in entry:
- # no mac found for device"
- continue
-
- if 'type' not in entry or entry['type'] != 'aircon':
- # no mac found for device"
- continue
-
- if 'name' in entry:
- entry['name'] = unquote(entry['name'])
-
- # in case the device was not configured to have an id
- # then use the mac address
- if 'id' in entry and entry['id'] == '':
- entry['id'] = entry['mac']
-
- entries.append({
- 'id': entry['id'],
- 'name': entry['name'],
- 'ip': address,
- 'mac': entry['mac'],
- 'ver': entry['ver'],
- })
-
- except socket.timeout:
- break
-
- finally:
- sock.close()
-
- self.entries = entries
-
-
- def main():
- """Test Daikin discovery."""
- from pprint import pprint
- daikin = Daikin()
- pprint("Scanning for Daikin devices..")
- daikin.update()
- pprint(daikin.entries)
-
-
- if __name__ == "__main__":
- main()
|