#!/usr/bin/python3

# This is a python 3 script for 
# detecting dydaqlog/dydaqmeas devices
# inside the local network segment

# Backwards compatibility to python2
from __future__ import print_function

import socket
import errno
import time

num_devices = 0
device = []

def is_new_device(data, addr):
  global device, num_devices
  for dev in device:
    if dev['addr'] == addr:
      return False
  new_device = {}
  new_device['addr'] = addr
  new_device['data'] = data
  device.append(new_device)
  num_devices+=1
  return True

def is_link_local_ipv6(addr):
	if addr.startswith("FE80::"):
		return True
	if addr.startswith("fe80::"):
		return True
	return False

try:
	# create ipv4 socket and configure it for broadcast
	server = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
	server.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
	# create ipv6 socket and configure it for multicast
	server6 = socket.socket(socket.AF_INET6, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
	server6.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_MULTICAST_IF, 0)
	server6.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_MULTICAST_HOPS, 255)
	server6.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_MULTICAST_LOOP, 1)
	# Set a timeout so the socket does not block
	# indefinitely when trying to receive data.
	server.settimeout(0.2)
	server6.settimeout(0.2)
	# send out broadcast/multicast message
	# to all dydaq devices in the same
	# local network segment
	message = b"*IDN?"
	print("Searching dydaqlog/dydaqmeas devices ...")
	server.sendto(message, ("<broadcast>", 9959))
	server6.sendto(message, ("ff02::1", 9959))
	print("")
	# receive and display answer from devices
	for loop in range(5):
		# receive device answer via IPv4
		while True:
			try:
				data, addr = server.recvfrom(1472)
				#print("Received answer: '"+data.decode("utf-8")+"' from",addr[0])
				if is_new_device(data, addr):
					x = data.decode("utf-8").split(",")
					if len(x) >= 6 and x[0] == "GBM" and x[1][0:5] == "dydaq":
						print("Found device:")
						print("  Device Family =",x[1])
						print("  Device Type =",x[2])
						print("  Serial Number =",x[3])
						print("  Hostname =",x[4])
						print("  Firmware Version =",x[5])
						print("  IPv4 address =",addr[0])
						print("  Browser Link = http://"+addr[0]+"/")
						print("")
			except socket.timeout:
				break
		# receive device answer via IPv6
		while True:
			try:
				data, addr = server6.recvfrom(1472)
				if is_new_device(data, addr):
					#print("Received answer: '"+data.decode("utf-8")+"' from",addr[0])
					x = data.decode("utf-8").split(",")
					if len(x) >= 6 and x[0] == "GBM" and x[1][0:5] == "dydaq":
						print("Found device:")
						print("  Device Family =",x[1])
						print("  Device Type =",x[2])
						print("  Serial Number =",x[3])
						print("  Hostname =",x[4])
						print("  Firmware Version =",x[5])
						print("  IPv6 address =",addr[0])
						# Browsers often don't support link-local addressing
						if not is_link_local_ipv6(addr[0]):
							print("  Browser Link = http://["+addr[0]+"]/")
						print("")
			except socket.timeout:
				break
	print("... done.")
except IOError as e:
	if e.errno == errno.ENETUNREACH:
		print ( "Network Error - {0}".format(e) )
		print ( "Please connect the network first and then try again" )
	else:
		raise
