-
Notifications
You must be signed in to change notification settings - Fork 195
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Protocol 3.5 Device Discovery Updates #516
Comments
I wonder if we could use a function to pull the local IPs and broadcast addresses. This would require psutil or netifaces: import importlib
def get_ip_to_broadcast():
if importlib.util.find_spec('psutil'):
import psutil
import socket
interfaces = psutil.net_if_addrs()
ip_to_broadcast = {}
for addresses in interfaces.values():
for addr in addresses:
if addr.family == socket.AF_INET and addr.broadcast: # AF_INET is for IPv4
ip_to_broadcast[addr.address] = addr.broadcast
return ip_to_broadcast
elif importlib.util.find_spec('netifaces'):
import netifaces
interfaces = netifaces.interfaces()
ip_to_broadcast = {}
for interface in interfaces:
addresses = netifaces.ifaddresses(interface)
ipv4 = addresses.get(netifaces.AF_INET)
if ipv4:
for addr in ipv4:
if 'broadcast' in addr:
ip_to_broadcast[addr['addr']] = addr['broadcast']
return ip_to_broadcast
else:
raise ImportError("Neither psutil nor netifaces is installed. Please install one of these packages to proceed.")
# Example usage:
print(get_ip_to_broadcast()) |
That looks like it would work. The scanner already uses netifaces if it is installed to get the force-scan list. Instead of raising an error if neither are installed, we could also use the |
Hmm, I just tried it on one of my single board computers but it blew up with
It seems importlib.util is separate from importlib https://discuss.python.org/t/python3-11-importlib-no-longer-exposes-util/25641 and I'm not sure which python version added importlib.util. |
Ok, this is what I'm planning on adding to the scanner. I flipped addr and broadcast in the ip_to_broadcast dict so interfaces with multiple IPs in the same subnet are only added once. ...
try:
import psutil # pylint: disable=E0401
PSULIBS = True
except ImportError:
PSULIBS = False
...
def get_ip_to_broadcast():
ip_to_broadcast = {}
if NETIFLIBS:
interfaces = netifaces.interfaces()
for interface in interfaces:
addresses = netifaces.ifaddresses(interface)
ipv4 = addresses.get(netifaces.AF_INET)
if ipv4:
for addr in ipv4:
if 'broadcast' in addr and 'addr' in addr and addr['broadcast'] != addr['addr']:
ip_to_broadcast[addr['broadcast']] = addr['addr']
if ip_to_broadcast:
return ip_to_broadcast
if PSULIBS:
interfaces = psutil.net_if_addrs()
for addresses in interfaces.values():
for addr in addresses:
if addr.family == socket.AF_INET and addr.broadcast and addr.address and addr.address != addr.broadcast: # AF_INET is for IPv4
ip_to_broadcast[addr.broadcast] = addr.address
if ip_to_broadcast:
return ip_to_broadcast
ip_to_broadcast['255.255.255.255'] = getmyIP()
return ip_to_broadcast |
Device discovery packets redux
Newer v3.5 devices do not send out unsolicited discovery broadcasts. Instead, they listen for broadcasts from a client app and send their discovery packet directly to that client.
The client broadcast contains the payload
{"from":"app","ip":"192.168.1.42"}
and is sent to the subnet broadcast address (i.e. 192.168.1.255) on port 7000. It is GCM encrypted the same way as broadcasts above.When a device receives a client broadcast, it responds by sending a device discovery packet directly to the IP address specified in the client broadcast. This again uses port 7000 and is GCM encrypted the same way as broadcasts above. The device I used in my testing will send the device discovery packet out as a broadcast if the client app specifies "255.255.255.255" as the IP address, however I suspect this is an accident and is not something they intended to be used.
Originally posted by @uzlonewolf in #260 (comment)
The text was updated successfully, but these errors were encountered: