@@ -21,9 +21,9 @@ def __init__(self):
2121 self .entries = [] # type: List[Dict[str, Any]]
2222 self .last_scan = None
2323
24- def scan (self ):
24+ def scan (self , scan_for_clients = False ):
2525 """Scan the network."""
26- self .update ()
26+ self .update (scan_for_clients )
2727
2828 def all (self ):
2929 """Return all found entries.
@@ -46,28 +46,43 @@ def find_by_data(self, values):
4646 if all (item in entry ['data' ].items ()
4747 for item in values .items ())]
4848
49- def update (self ):
49+ def update (self , scan_for_clients ):
5050 """Scan for new GDM services.
5151
52- Example of the dict list assigned to self.entries by this function:
52+ Examples of the dict list assigned to self.entries by this function:
53+
54+ Server:
5355 [{'data': {
5456 'Content-Type': 'plex/media-server',
5557 'Host': '53f4b5b6023d41182fe88a99b0e714ba.plex.direct',
5658 'Name': 'myfirstplexserver',
5759 'Port': '32400',
5860 'Resource-Identifier': '646ab0aa8a01c543e94ba975f6fd6efadc36b7',
59- 'Updated-At': '1444852697',
60- 'Version': '0.9.12.13.1464-4ccd2ca',
61- },
62- 'from': ('10.10.10.100', 32414)}]
61+ 'Updated-At': '1585769946',
62+ 'Version': '1.18.8.2527-740d4c206',
63+ },
64+ 'from': ('10.10.10.100', 32414)}]
65+
66+ Clients:
67+ [{'data': {'Content-Type': 'plex/media-player',
68+ 'Device-Class': 'stb',
69+ 'Name': 'plexamp',
70+ 'Port': '36000',
71+ 'Product': 'Plexamp',
72+ 'Protocol': 'plex',
73+ 'Protocol-Capabilities': 'timeline,playback,playqueues,playqueues-creation',
74+ 'Protocol-Version': '1',
75+ 'Resource-Identifier': 'b6e57a3f-e0f8-494f-8884-f4b58501467e',
76+ 'Version': '1.1.0',
77+ },
78+ 'from': ('10.10.10.101', 32412)}]
6379 """
6480
65- gdm_ip = '239.0.0.250' # multicast to PMS
66- gdm_port = 32414
6781 gdm_msg = 'M-SEARCH * HTTP/1.0' .encode ('ascii' )
6882 gdm_timeout = 1
6983
7084 self .entries = []
85+ known_responses = []
7186
7287 # setup socket for discovery -> multicast message
7388 sock = socket .socket (socket .AF_INET , socket .SOCK_DGRAM )
@@ -78,21 +93,36 @@ def update(self):
7893 socket .IP_MULTICAST_TTL ,
7994 struct .pack ("B" , gdm_timeout ))
8095
96+ if scan_for_clients :
97+ # setup socket for broadcast to Plex clients
98+ sock .setsockopt (socket .SOL_SOCKET , socket .SO_REUSEADDR , 1 )
99+ sock .setsockopt (socket .SOL_SOCKET , socket .SO_BROADCAST , 1 )
100+ gdm_ip = '255.255.255.255'
101+ gdm_port = 32412
102+ else :
103+ # setup socket for multicast to Plex server(s)
104+ gdm_ip = '239.0.0.250'
105+ gdm_port = 32414
106+
81107 try :
82108 # Send data to the multicast group
83109 sock .sendto (gdm_msg , (gdm_ip , gdm_port ))
84110
85111 # Look for responses from all recipients
86112 while True :
87113 try :
88- bdata , server = sock .recvfrom (1024 )
114+ bdata , host = sock .recvfrom (1024 )
89115 data = bdata .decode ('utf-8' )
90116 if '200 OK' in data .splitlines ()[0 ]:
91117 ddata = {k : v .strip () for (k , v ) in (
92118 line .split (':' ) for line in
93119 data .splitlines () if ':' in line )}
120+ identifier = ddata .get ('Resource-Identifier' )
121+ if identifier and identifier in known_responses :
122+ continue
123+ known_responses .append (identifier )
94124 self .entries .append ({'data' : ddata ,
95- 'from' : server })
125+ 'from' : host })
96126 except socket .timeout :
97127 break
98128 finally :
@@ -105,8 +135,12 @@ def main():
105135
106136 gdm = GDM ()
107137
108- pprint ("Scanning GDM..." )
109- gdm .update ()
138+ pprint ("Scanning GDM for servers..." )
139+ gdm .scan ()
140+ pprint (gdm .entries )
141+
142+ pprint ("Scanning GDM for clients..." )
143+ gdm .scan (scan_for_clients = True )
110144 pprint (gdm .entries )
111145
112146
0 commit comments