# Path: fluxghost/api/discover.py
# def get_online_message(source, device):
#     st = None
#     doc = {
#         "uuid": device.uuid.hex,
#         "alive": True,
#         "source": source,
#         "serial": device.serial,
#         "version": str(device.version),
#         "model": device.model_id,
#     }
# 
#     if source == "lan":
#         doc.update({
#             "name": device.name,
#             "ipaddr": device.ipaddr,
#             "password": device.has_password,
#         })
#         st = device.status
#     elif source == "h2h":
#         st = device.device_status
#         doc.update({
#             "name": device.nickname,
#             "addr": device.addr,
#         })
#     else:
#         st = {}
# 
#     doc.update({
#         "st_ts": st.get("st_ts"),
#         "st_id": st.get("st_id"),
#         "st_prog": st.get("st_prog"),
#         "head_module": st.get("st_head", st.get("head_module")),
#         "error_label": st.get("st_err", st.get("error_label"))
#     })
#     return doc
# 
# def get_offline_message(source, device=None, uuid=None):
#     return {
#         "uuid": device.uuid.hex if device else uuid.hex,
#         "alive": False,
#         "source": source
#     }
# 
# Path: fluxghost/pipe/base.py
# class PipeBase(ApiBase):
#     POOL_TIME = 30.0
# 
#     def __init__(self, stdin, stdout, options):
#         self.stdin, self.stdout = stdin, stdout
#         self.options = options
#         self.rlist = [self]
#         self.running = True
# 
#         self._recv_buf = b""
#         self._recv_len = None
#         self._recv_bin = None
# 
#     def fileno(self):
#         return self.stdin.fileno()
# 
#     def serve_forever(self):
#         try:
#             ApiBase.serve_forever(self)
#         except KeyboardInterrupt:
#             self.close()
#         except Exception:
#             logger.exception("Unhandle exception")
#         finally:
#             pass
# 
#     def _serve_forever(self):
#         while self.running:
#             rl = select(self.rlist, (), (), self.POOL_TIME)[0]
#             for r in rl:
#                 r.on_read()
# 
#             self.on_loop()
# 
#     def on_read(self):
#         if self._recv_len is None:
#             buf = self.stdin.read(8 - len(self._recv_buf))
#             if len(buf):
#                 self._recv_buf += buf
#                 if len(buf) == 8:
#                     self._recv_len = int(self._recv_buf[1:], 16)
#                     tp = self._recv_buf[0]
#                     if tp == 116:
#                         self._recv_bin = False
#                     elif tp == 98:
#                         self._recv_bin = True
#                     else:
#                         logger.error("Unknow message type: %s", tp)
#                         self.close()
#                     self._recv_buf = b""
#                     self._on_read_body()
#             else:
#                 self.close()
#         else:
#             self._on_read_body()
# 
#     def _on_read_body(self):
#         buf = self.stdin.read(self._recv_len - len(self._recv_buf))
#         if len(buf):
#             self._recv_buf += buf
#             if len(buf) == self._recv_len:
#                 self._on_message(self._recv_buf, self._recv_bin)
#             else:
#                 return
#         else:
#             self.close()
# 
#     def _on_message(self, buf, is_binary):
#         try:
#             if is_binary:
#                 self.on_binary_message(self._recv_buf)
#             else:
#                 self.on_text_message(self._recv_buf.decode("utf8"))
#         except Exception:
#             pass
# 
#     def close(self):
#         self.running = False
#         self.stdout.close()
#         self.stdin.close()
# 
#     def _on_loop(self):
#         pass
# 
#     def on_loop(self):
#         pass
# 
#     def send_text(self, text):
#         buf = text.encode()
#         self.stdout.write(("t%07x" % len(buf)).encode())
#         self.stdout.write(buf)
#         self.stdout.flush()
# 
#     def send_binary(self, buf):
#         self.stdout.write(("t%07x" % len(buf)).encode())
#         self.stdout.write(buf)
#         self.stdout.flush()


from select import select
from time import time
from fluxclient.upnp import UpnpDiscover
from fluxghost.api.discover import get_online_message, get_offline_message
from .base import PipeBase

class DevicesMonitor(object):
    def __init__(self, offline_timeout=15):
        self.offline_timeout = offline_timeout
        self.all_devices = {}
        self.alive_devices = set()

    def online_device(self, device):
        self.all_devices[device.uuid] = device
        self.alive_devices.add(device.uuid)
        return get_online_message(device)

    def offline_devices(self):
        t = time()
        for uuid, device in self.all_devices.items():
            if t - device.last_update > self.offline_timeout:
                if uuid in self.alive_devices:
                    self.alive_devices.remove(uuid)

                    yield get_offline_message(device)


class PipeDiscover(PipeBase):
    def __init__(self, *args):
        super().__init__(*args)
        self.devices_monitor = DevicesMonitor()
        self.discover = UpnpDiscover()

    def _serve_forever(self):
        while self.running:

# Path: fluxghost/api/discover.py
# def get_online_message(source, device):
#     st = None
#     doc = {
#         "uuid": device.uuid.hex,
#         "alive": True,
#         "source": source,
#         "serial": device.serial,
#         "version": str(device.version),
#         "model": device.model_id,
#     }
# 
#     if source == "lan":
#         doc.update({
#             "name": device.name,
#             "ipaddr": device.ipaddr,
#             "password": device.has_password,
#         })
#         st = device.status
#     elif source == "h2h":
#         st = device.device_status
#         doc.update({
#             "name": device.nickname,
#             "addr": device.addr,
#         })
#     else:
#         st = {}
# 
#     doc.update({
#         "st_ts": st.get("st_ts"),
#         "st_id": st.get("st_id"),
#         "st_prog": st.get("st_prog"),
#         "head_module": st.get("st_head", st.get("head_module")),
#         "error_label": st.get("st_err", st.get("error_label"))
#     })
#     return doc
# 
# def get_offline_message(source, device=None, uuid=None):
#     return {
#         "uuid": device.uuid.hex if device else uuid.hex,
#         "alive": False,
#         "source": source
#     }
# 
# Path: fluxghost/pipe/base.py
# class PipeBase(ApiBase):
#     POOL_TIME = 30.0
# 
#     def __init__(self, stdin, stdout, options):
#         self.stdin, self.stdout = stdin, stdout
#         self.options = options
#         self.rlist = [self]
#         self.running = True
# 
#         self._recv_buf = b""
#         self._recv_len = None
#         self._recv_bin = None
# 
#     def fileno(self):
#         return self.stdin.fileno()
# 
#     def serve_forever(self):
#         try:
#             ApiBase.serve_forever(self)
#         except KeyboardInterrupt:
#             self.close()
#         except Exception:
#             logger.exception("Unhandle exception")
#         finally:
#             pass
# 
#     def _serve_forever(self):
#         while self.running:
#             rl = select(self.rlist, (), (), self.POOL_TIME)[0]
#             for r in rl:
#                 r.on_read()
# 
#             self.on_loop()
# 
#     def on_read(self):
#         if self._recv_len is None:
#             buf = self.stdin.read(8 - len(self._recv_buf))
#             if len(buf):
#                 self._recv_buf += buf
#                 if len(buf) == 8:
#                     self._recv_len = int(self._recv_buf[1:], 16)
#                     tp = self._recv_buf[0]
#                     if tp == 116:
#                         self._recv_bin = False
#                     elif tp == 98:
#                         self._recv_bin = True
#                     else:
#                         logger.error("Unknow message type: %s", tp)
#                         self.close()
#                     self._recv_buf = b""
#                     self._on_read_body()
#             else:
#                 self.close()
#         else:
#             self._on_read_body()
# 
#     def _on_read_body(self):
#         buf = self.stdin.read(self._recv_len - len(self._recv_buf))
#         if len(buf):
#             self._recv_buf += buf
#             if len(buf) == self._recv_len:
#                 self._on_message(self._recv_buf, self._recv_bin)
#             else:
#                 return
#         else:
#             self.close()
# 
#     def _on_message(self, buf, is_binary):
#         try:
#             if is_binary:
#                 self.on_binary_message(self._recv_buf)
#             else:
#                 self.on_text_message(self._recv_buf.decode("utf8"))
#         except Exception:
#             pass
# 
#     def close(self):
#         self.running = False
#         self.stdout.close()
#         self.stdin.close()
# 
#     def _on_loop(self):
#         pass
# 
#     def on_loop(self):
#         pass
# 
#     def send_text(self, text):
#         buf = text.encode()
#         self.stdout.write(("t%07x" % len(buf)).encode())
#         self.stdout.write(buf)
#         self.stdout.flush()
# 
#     def send_binary(self, buf):
#         self.stdout.write(("t%07x" % len(buf)).encode())
#         self.stdout.write(buf)
#         self.stdout.flush()


# Path: fluxghost/pipe/discover.py
from select import select
from time import time
from fluxclient.upnp import UpnpDiscover
from fluxghost.api.discover import get_online_message, get_offline_message
from .base import PipeBase


class DevicesMonitor(object):
    def __init__(self, offline_timeout=15):
        self.offline_timeout = offline_timeout
        self.all_devices = {}
        self.alive_devices = set()

    def online_device(self, device):
        self.all_devices[device.uuid] = device
        self.alive_devices.add(device.uuid)
        return get_online_message(device)

    def offline_devices(self):
        t = time()
        for uuid, device in self.all_devices.items():
            if t - device.last_update > self.offline_timeout:
                if uuid in self.alive_devices:
                    self.alive_devices.remove(uuid)

                    yield get_offline_message(device)


class PipeDiscover(PipeBase):
    def __init__(self, *args):
        super().__init__(*args)
        self.devices_monitor = DevicesMonitor()
        self.discover = UpnpDiscover()

    def _serve_forever(self):
        while self.running:

            rlist = list(self.rlist) + list(self.discover.socks)