Skip to content

Commit d305ba0

Browse files
committed
Slow search
1 parent 6e70bb7 commit d305ba0

File tree

1 file changed

+129
-29
lines changed

1 file changed

+129
-29
lines changed

lineus/lineus.py

Lines changed: 129 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -2,41 +2,59 @@
22
import shlex
33
import re
44
from zeroconf import ServiceBrowser, Zeroconf
5+
import netifaces
6+
import ipaddress
7+
8+
# python setup.py sdist
9+
# twine upload dist/lineus-0.1.3.tar.gz
510

611

712
class LineUs:
813
"""An example class to show how to use the Line-us API"""
914

15+
__line_us = None
16+
__connected = False
17+
__hello_message = ''
18+
on_found_line_us_callback = None
19+
zeroconf = Zeroconf()
20+
listener = None
21+
browser = None
22+
line_us_name = ''
23+
info = {}
24+
__default_port = 1337
25+
__default_slow_search_timeout = 0.2
26+
1027
def __init__(self):
11-
self.__line_us = None
12-
self.__connected = False
13-
self.__hello_message = ''
14-
self.on_found_line_us_callback = None
15-
self.zeroconf = Zeroconf()
1628
self.listener = LineUsListener()
1729
self.browser = ServiceBrowser(self.zeroconf, "_lineus._tcp.local.", self.listener)
18-
self.line_us_name = ''
19-
self.info = {}
2030

21-
def connect(self, line_us_name=None):
31+
def connect(self, line_us_name=None, timeout=None):
2232
if line_us_name is None:
2333
line_us_name = self.listener.get_first_line_us()[2]
2434
self.__line_us = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
35+
if timeout is not None:
36+
self.__line_us.settimeout(timeout)
2537
try:
26-
self.__line_us.connect((line_us_name, 1337))
27-
except:
38+
self.__line_us.connect((line_us_name, self.__default_port))
39+
except OSError:
2840
return False
2941
self.__connected = True
3042
self.line_us_name = line_us_name
3143
self.__hello_message = self.__read_response()
3244
return True
3345

46+
def set_timeout(self, timeout):
47+
self.__line_us.settimeout(timeout)
48+
3449
def connected(self):
3550
return self.__connected
3651

3752
def get_name(self):
3853
return self.line_us_name
3954

55+
def get_line_us_list(self):
56+
return self.listener.get_line_us_list()
57+
4058
def get_info(self):
4159
info = {}
4260
raw_info = self.send_gcode('M122', '')
@@ -53,10 +71,18 @@ def get_info(self):
5371
return info
5472

5573
def get_hello_string(self):
74+
hello_message = {}
5675
if self.__connected:
57-
return self.__hello_message.encode('ascii')
76+
hello = self.__hello_message.decode('utf-8')
77+
fields = shlex.split(hello)
78+
if fields.pop(0) != 'hello':
79+
return None
80+
for field in fields:
81+
split_fields = field.split(':', 1)
82+
hello_message[split_fields[0]] = split_fields[1]
83+
return hello_message
5884
else:
59-
return 'Not connected'
85+
return None
6086

6187
def disconnect(self):
6288
"""Close the connection to the Line-us"""
@@ -114,7 +140,6 @@ def list_lineus_files(self):
114140
info.append((file_number, file_size, detail[0]))
115141
return info
116142

117-
118143
def __read_response(self):
119144
"""Read from the socket one byte at a time until we get a null"""
120145
line = b''
@@ -134,16 +159,38 @@ def __send_command(self, command):
134159
def on_found_line_us(self, callback):
135160
self.listener.on_found_line_us(callback)
136161

162+
def slow_search(self, return_first=True, timeout=None):
163+
found_line_us = []
164+
if timeout is None:
165+
timeout = self.__default_slow_search_timeout
166+
nets = NetFinder()
167+
for ip in nets.get_all_ips():
168+
if self.connect(str(ip), timeout):
169+
hello = self.get_hello_string()
170+
line_us = (hello['NAME'], f'{hello["NAME"]}.local', str(ip), self.__default_port)
171+
if return_first:
172+
return [line_us]
173+
else:
174+
found_line_us.append(line_us)
175+
return found_line_us
176+
177+
@staticmethod
178+
def get_network_list():
179+
return NetFinder().get_network_list()
180+
137181

138182
class LineUsListener:
139183

140184
def __init__(self):
141185
self.on_found_line_us_callback = None
142186
self.line_us_list = []
143187

144-
@staticmethod
145-
def remove_service(_self, _zeroconf, _service_type, name):
146-
print("Service %s removed" % (name,))
188+
def remove_service(self, zeroconf, service_type, name):
189+
info = zeroconf.get_service_info(service_type, name)
190+
line_us_name = info.server.split('.')[0]
191+
line_us = (line_us_name, info.server, socket.inet_ntoa(info.address), info.port)
192+
self.line_us_list.remove(line_us)
193+
print(f'Service {name} removed')
147194

148195
def add_service(self, zeroconf, service_type, name):
149196
info = zeroconf.get_service_info(service_type, name)
@@ -167,23 +214,76 @@ def get_line_us(self, number):
167214
return self.line_us_list[number]
168215

169216
def get_line_us_list(self):
170-
return
217+
return self.line_us_list
171218

172219

173-
if __name__ == '__main__':
220+
class NetFinder:
174221

175-
connected = False
222+
network_list = []
176223

177-
def callback_func(line_us):
178-
global connected
179-
connected = True
180-
print(f'callback: {line_us[0]}')
224+
def __init__(self):
225+
interfaces = netifaces.interfaces()
226+
for interface in interfaces:
227+
if netifaces.ifaddresses(interface) is not None and netifaces.AF_INET in netifaces.ifaddresses(interface):
228+
this_interface = netifaces.ifaddresses(interface)[netifaces.AF_INET][0]
229+
this_interface_detail = {'name': interface}
230+
for field in ('addr', 'netmask', 'broadcast'):
231+
if field in this_interface:
232+
this_interface_detail[field] = this_interface[field]
233+
if 'addr' in this_interface_detail and 'netmask' in this_interface_detail:
234+
if 'broadcast' in this_interface_detail:
235+
if not this_interface_detail['addr'].startswith('127'):
236+
self.network_list.append(this_interface_detail)
237+
238+
def get_network_list(self):
239+
return self.network_list
240+
241+
def get_all_ips(self, interface=None):
242+
ips = []
243+
if interface is None:
244+
interface_list = self.network_list
245+
else:
246+
interface_list = self.network_list[interface]
247+
for interface in interface_list:
248+
addr = interface['addr']
249+
netmask_bits = self.netmask_to_cidr(interface['netmask'])
250+
# print(f'{addr} - {netmask_bits}')
251+
network = ipaddress.ip_network(f'{addr}/{netmask_bits}', strict=False)
252+
for host in network.hosts():
253+
ips.append(host)
254+
return ips
255+
256+
@staticmethod
257+
def netmask_to_cidr(netmask):
258+
return sum([bin(int(x)).count('1') for x in netmask.split('.')])
259+
260+
261+
if __name__ == '__main__':
181262

263+
# found_line_us = False
264+
#
265+
# def callback_func(line_us):
266+
# global found_line_us
267+
# found_line_us = True
268+
# print(f'callback: {line_us[0]}')
182269

183270
my_line_us = LineUs()
184-
my_line_us.on_found_line_us(callback_func)
185-
while not connected:
186-
pass
187-
my_line_us.connect()
188-
files = my_line_us.list_lineus_files()
189-
print(files)
271+
print(my_line_us.get_network_list())
272+
# line_us_list = my_line_us.slow_search(False)
273+
# print(line_us_list)
274+
# my_line_us.connect(line_us_list[0][1])
275+
# print(my_line_us.get_info())
276+
# my_line_us.on_found_line_us(callback_func)
277+
# while not found_line_us:
278+
# pass
279+
# my_line_us.connect()
280+
# print(my_line_us.get_hello_string())
281+
# print(f'Found some machines: {my_line_us.get_line_us_list()}')
282+
# my_line_us.connect()
283+
# files = my_line_us.list_lineus_files()
284+
# print(files)
285+
# for i in range(80, 254):
286+
# print(i)
287+
# if my_line_us.connect(f'192.168.1.{i}', .3):
288+
# my_line_us.set_timeout(20)
289+
# print(my_line_us.get_info())

0 commit comments

Comments
 (0)