text: #!/usr/bin/env python3
  import os
  import re
  import logging
  import requests
  
  log = logging.getLogger(__name__)
  
  baseurl = os.environ.get("UNIFI_BASEURL", "https://unifi:8443")
  username = os.environ.get("UNIFI_USERNAME")
  password = os.environ.get("UNIFI_PASSWORD")
  site = os.environ.get("UNIFI_SITE", "default")
  fixed_only = os.environ.get("FIXED_ONLY", "False") == "True"
  log_level = os.environ.get("LOG_LEVEL", "INFO")
  slug_names = os.environ.get("SLUG_NAMES", "False") == "True"
  
  bad_chars_pattern = re.compile("[^a-zA-Z0-9-]+")
  
  
  def get_configured_clients(session):
      # Get configured clients
      r = session.get(f"{baseurl}/api/s/{site}/list/user", verify=False)
      r.raise_for_status()
      return r.json()["data"]
  
  
  def get_active_clients(session):
      # Get active clients
      r = session.get(f"{baseurl}/api/s/{site}/stat/sta", verify=False)
      r.raise_for_status()
      return r.json()["data"]
  
  
  def get_clients():
      log.debug("Getting clients")
      s = requests.Session()
      # Log in to controller
      r = s.post(
          f"{baseurl}/api/login",
          json={"username": username, "password": password},
          verify=False,
      )
      r.raise_for_status()
  
      clients = get_configured_clients(s)
      if not fixed_only:
          clients.extend(get_active_clients(s))
  
      # Merge configured and active clients on mac
      # Filter out clients with no/invalid names
      clients_by_mac = {}
      for c in clients:
          log.debug("Client: %s", c)
          name = c.get("name")
          # IP in use is more relevant than configured fixed IP
          ip = c.get("ip") or c.get("fixed_ip")
          if not name or not ip:
              continue
          if slug_names:
              name = slug_name(name)
          elif re.search(bad_chars_pattern, name):
              log.warning("%s skipped due to invalid characters.", name)
              continue
          clients_by_mac[c["mac"]] = {"name": name, "ip": ip}
      return sorted(clients_by_mac.values(), key=lambda c: c["name"])
  
  
  def slug_name(name):
      slug = re.sub(bad_chars_pattern, "-", name)
      if slug != name:
          log.info("%s was slugged to %s", name, slug)
      return slug
  
  
  if __name__ == "__main__":
      logging.basicConfig(
          format="%(asctime)s - %(levelname)s: %(message)s", level=log_level
      )
      try:
          for c in get_clients():
              print(f"{c['ip']} {c['name']}")
              log.debug("Host entry: %s %s", c["ip"], c["name"])
      except requests.exceptions.ConnectionError:
          log.critical("Could not connect to unifi controller at %s", baseurl)
          log.debug("Exception information below", exc_info=True)
          exit(1)
      except requests.exceptions.HTTPError:
          # Bound to be a common error:
          if baseurl.startswith("http://"):
              log.error(
                  "Error connecting to %s. You should probably connect using HTTPS instead of HTTP",
                  baseurl
              )
              log.debug("Exception information below", exc_info=True)
              exit(1)
          raise
  