summaryrefslogtreecommitdiff
path: root/netdisco/discovery.py
blob: 27bce19132a916c7499996129afb4f1d9d54119f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
"""Combine all the different protocols into a simple interface."""
import logging
import os
import importlib

from .ssdp import SSDP
from .mdns import MDNS
from .gdm import GDM
from .lms import LMS
from .tellstick import Tellstick
from .daikin import Daikin
from .smartglass import XboxSmartGlass

_LOGGER = logging.getLogger(__name__)


class NetworkDiscovery:
    """Scan the network for devices.

    mDNS scans in a background thread.
    SSDP scans in the foreground.
    GDM scans in the foreground.
    LMS scans in the foreground.
    Tellstick scans in the foreground
    Xbox One scans in the foreground

    start: is ready to scan
    scan: scan the network
    discover: parse scanned data
    get_in
    """

    # pylint: disable=too-many-instance-attributes
    def __init__(self):
        """Initialize the discovery."""

        self.mdns = None
        self.ssdp = None
        self.gdm = None
        self.lms = None
        self.tellstick = None
        self.daikin = None
        self.xbox_smartglass = None

        self.is_discovering = False
        self.discoverables = None

    def scan(self):
        """Start and tells scanners to scan."""
        self.is_discovering = True

        self.mdns = MDNS()

        # Needs to be after MDNS init
        self._load_device_support()

        self.mdns.start()

        self.ssdp = SSDP()
        self.ssdp.scan()

        self.gdm = GDM()
        self.gdm.scan()

        self.lms = LMS()
        self.lms.scan()

        self.tellstick = Tellstick()
        self.tellstick.scan()

        self.daikin = Daikin()
        self.daikin.scan()

        self.xbox_smartglass = XboxSmartGlass()
        self.xbox_smartglass.scan()

    def stop(self):
        """Turn discovery off."""
        if not self.is_discovering:
            return

        self.mdns.stop()

        # Not removing SSDP because it tracks state
        self.mdns = None
        self.gdm = None
        self.lms = None
        self.tellstick = None
        self.daikin = None
        self.xbox_smartglass = None
        self.discoverables = None
        self.is_discovering = False

    def discover(self):
        """Return a list of discovered devices and services."""
        if not self.is_discovering:
            raise RuntimeError("Needs to be called after start, before stop")

        return [dis for dis, checker in self.discoverables.items()
                if checker.is_discovered()]

    def get_info(self, dis):
        """Get a list with the most important info about discovered type."""
        return self.discoverables[dis].get_info()

    def get_entries(self, dis):
        """Get a list with all info about a discovered type."""
        return self.discoverables[dis].get_entries()

    def _load_device_support(self):
        """Load the devices and services that can be discovered."""
        self.discoverables = {}

        discoverables_format = __name__.rsplit('.', 1)[0] + '.discoverables.{}'

        for module_name in os.listdir(os.path.join(os.path.dirname(__file__),
                                                   'discoverables')):
            if module_name[-3:] != '.py' or module_name == '__init__.py':
                continue

            module_name = module_name[:-3]

            module = importlib.import_module(
                discoverables_format.format(module_name))

            self.discoverables[module_name] = module.Discoverable(self)

    def print_raw_data(self):
        """Helper method to show what is discovered in your network."""
        from pprint import pprint

        print("Zeroconf")
        pprint(self.mdns.entries)
        print("")
        print("SSDP")
        pprint(self.ssdp.entries)
        print("")
        print("GDM")
        pprint(self.gdm.entries)
        print("")
        print("LMS")
        pprint(self.lms.entries)
        print("")
        print("Tellstick")
        pprint(self.tellstick.entries)
        print("")
        print("Xbox SmartGlass")
        pprint(self.xbox_smartglass.entries)