22import shlex
33import re
44from 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
712class 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
138182class 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