Пример #1
0
    def test_discover_homekit_devices_missing_c(self):
        zeroconf = Zeroconf()
        desc = {
            'id': '00:00:01:00:00:03',
            'md': 'unittest',
            's#': '1',
            'ci': '5',
            'sf': '0'
        }
        info = ServiceInfo('_hap._tcp.local.',
                           'foo3._hap._tcp.local.',
                           addresses=[socket.inet_aton('127.0.0.1')],
                           port=1234,
                           properties=desc,
                           weight=0,
                           priority=0)
        zeroconf.unregister_all_services()
        zeroconf.register_service(info, allow_name_change=True)

        result = discover_homekit_devices()
        test_device = self.find_device(desc, result)

        zeroconf.unregister_all_services()

        self.assertIsNone(test_device)
Пример #2
0
class DiscoveryServerService:
    _SERVICE_TYPE = '_http._tcp.local.'
    _SERVICE_NAME = 'sound-system-server._http._tcp.local.'

    def __init__(self, host, port):
        self._host = host
        self._port = port
        self._zeroconf = None
        self._info = None
        self._registered = False

    def start(self):
        if not self._registered:
            self._zeroconf = Zeroconf()
            self._start_service()

    def stop(self):
        if self._registered:
            self._zeroconf.unregister_all_services()
            self._zeroconf = None
            self._registered = False

    def _start_service(self):
        self._info = ServiceInfo(self._SERVICE_TYPE, self._SERVICE_NAME,
                                 socket.inet_aton(self._host), self._port, 0,
                                 0, {})
        logging.debug('Registered zeroconf service %s host %s:%d',
                      self._SERVICE_NAME, self._host, self._port)
        self._zeroconf.register_service(self._info)
        self._registered = True
Пример #3
0
class MdnsBrowser:
    def __init__(self, acteur):
        self.__logger = logging.getLogger(__name__ + '.' +
                                          self.__class__.__name__)

        self.zeroconf: Optional[Zeroconf] = None

        service_types = [
            '_mghttps._tcp.local.',
            '_mgamqps._tcp.local.',
        ]
        self.listener = MdnsListener(acteur)

        # Activer zeroconf avec IPv4 et IPv6 (all)
        try:
            self.zeroconf = Zeroconf(ip_version=IPVersion.All)
            self.browser = ServiceBrowser(self.zeroconf,
                                          service_types,
                                          listener=self.listener)
        except OSError:
            self.__logger.warning(
                "Erreur chargement mdns avec IPv4 et IPv6, tenter de charger avec IPv4 uniquement"
            )
            self.zeroconf = Zeroconf(ip_version=IPVersion.V4Only)
            self.browser = ServiceBrowser(self.zeroconf,
                                          service_types,
                                          listener=self.listener)

    def entretien(self):
        pass

    def fermer(self):
        self.zeroconf.unregister_all_services()
        self.zeroconf.close()
Пример #4
0
def main():
    # Catch CNTRL-C signel
    global shutdown
    signal.signal(signal.SIGINT, signal_cntrl_c)

    init_logging("", 2)

    configs = load_configfile("bridge.ini")
    ignore_list = configs.getlist('Device', 'Ignore')
    context = zmq.Context.instance()
    zeroconf = Zeroconf()
    listener = ZeroConfDashTCPListener(context)
    browser = ServiceBrowser(zeroconf, "_DashIO._tcp.local.", listener)
    pinger = TCPPoller(port=5000, context=context)
    b = tcp_dashBridge(
        configs.get('Dash', 'Username'),
        configs.get('Dash', 'Password'),
        host=configs.get('Dash', 'Server'),
        port=configs.getint('Dash', 'Port'),
        ignore_devices=ignore_list,
        context=context
    )

    while not shutdown:
        time.sleep(5)

    zeroconf.unregister_all_services()
    zeroconf.close()
Пример #5
0
class HomeKitServer(ThreadingMixIn, HTTPServer):
    def __init__(self, config_file, logger=sys.stderr):
        """
        Create a new server that acts like a homekit accessory.

        :param config_file: the file that contains the configuration data. Must be a string representing an absolute
        path to the file
        :param logger: this can be None to disable logging, sys.stderr to use the default behaviour of the python
        implementation or an instance of logging.Logger to use this.
        """
        if logger is None or logger == sys.stderr or isinstance(
                logger, logging.Logger):
            self.logger = logger
        else:
            raise Exception('Invalid logger given.')
        self.data = HomeKitServerData(config_file)
        self.data.increase_configuration_number()
        self.sessions = {}
        self.zeroconf = Zeroconf()
        self.mdns_type = '_hap._tcp.local.'
        self.mdns_name = self.data.name + '._hap._tcp.local.'

        self.accessories = Accessories()

        HTTPServer.__init__(self, (self.data.ip, self.data.port),
                            HomeKitRequestHandler)

    def publish_device(self):
        desc = {
            'md': 'My Lightbulb',  # model name of accessory
            'ci': Categories[
                'Lightbulb'],  # category identifier (page 254, 2 means bridge)
            'pv': '1.0',  # protocol version
            'c#': str(self.data.configuration_number),
            # configuration (consecutive number, 1 or greater, must be changed on every configuration change)
            'id': self.data.
            accessory_pairing_id_bytes,  # id MUST look like Mac Address
            'ff': '0',  # feature flags
            's#': '1',  # must be 1
            'sf':
            '1'  # status flag, lowest bit encodes pairing status, 1 means unpaired
        }
        if self.data.is_paired:
            desc['sf'] = '0'

        info = ServiceInfo(self.mdns_type, self.mdns_name,
                           socket.inet_aton(self.data.ip), self.data.port, 0,
                           0, desc, 'ash-2.local.')
        self.zeroconf.unregister_all_services()
        self.zeroconf.register_service(info)

    def unpublish_device(self):
        self.zeroconf.unregister_all_services()

    def shutdown(self):
        # tell all handlers to close the connection
        for session in self.sessions:
            self.sessions[session]['handler'].close_connection = True
        self.socket.close()
        HTTPServer.shutdown(self)
Пример #6
0
def mDNS():
	#zerconf info
	#logging.basicConfig(level=logging.DEBUG)
	#logging.getLogger('zeroconf').setLevel(logging.DEBUG)
	info = []
	zeroconf = Zeroconf(InterfaceChoice.All)
	output = subprocess.check_output('for /f "usebackq tokens=2 delims=:" %f in (`ipconfig ^| findstr /c:"IPv4 Address"`) do @echo off && echo%f',shell=True , stderr=subprocess.STDOUT,stdin=subprocess.PIPE).decode("utf-8")
	#F**K PYTHON
	output = output[:-1]
	i = 0
	infs = sorted(output.split('\n'))
	for ip in output.split('\n'):
		i += 1
		print(ip)
		info.append(ServiceInfo(
			"_coap._udp.local.",
			"hwmon" + str(i) + "._coap._udp.local.",
			addresses=[socket.inet_aton(ip)],
			port=5683,
			server="hwmon" + str(i) + ".local.",
			#host_ttl=0,
			#other_ttl=0,
		))
		zeroconf.register_service(info[-1])
	print("service started")
	while (stop_threads == False):
		output = subprocess.check_output('for /f "usebackq tokens=2 delims=:" %f in (`ipconfig ^| findstr /c:"IPv4 Address"`) do @echo off && echo%f',shell=True , stderr=subprocess.STDOUT,stdin=subprocess.PIPE).decode("utf-8")
		#F**K PYTHON TWICE
		output = output[:-1]
		i = 0
		if(sorted(output.split('\n')) != infs):
			for inf in info:
				try:
					zeroconf.unregister_service(inf)
				except :
					pass
			zeroconf.unregister_all_services()
			info.clear()
			print("new interface")
			for ip in output.split('\n'):
				i += 1
				print(ip)
				info.append(ServiceInfo(
					"_coap._udp.local.",
					"hwmon" + str(i) + "._coap._udp.local.",
					addresses=[socket.inet_aton(ip)],
					port=5683,
					server="hwmon" + str(i) + ".local.",
					#host_ttl=0,
					#other_ttl=0,
				))
				zeroconf.register_service(info[-1])
			infs = sorted(output.split('\n'))
		time.sleep(1)
	zeroconf.close()
class IPBroadcaster():
    def __init__(self):
        print("Starting service")
        self.ip_version = IPVersion.V4Only
        self.service = None
        self.hostname = ""
        self.ip_address = ""
        self.zeroconf = None

    def __del__(self):
        print("Stopping service")
        self.zeroconf.close()

    def createService(self):
        self.hostname = socket.gethostname()
        self.ip_address = get_ip_address()

        type = ''
        if IS_PRINTER:
            type = 'nordin_printer'
        else:
            type = 'nordin_device'
        desc = {
            'type': type,
            'name': self.hostname,
            'series': HARDWARE_SERIES,
            'version': HARDWARE_VERSION
        }

        return ServiceInfo(
            "_http._tcp.local.",
            "{}beacon._http._tcp.local.".format(self.hostname),
            addresses=[socket.inet_aton(self.ip_address)],
            port=5000,
            properties=desc,
            server="{}.local.".format(self.hostname),
        )

    def start(self):
        try:
            self.zeroconf.unregister_service(self.service)
            self.zeroconf.close()
        except AttributeError:
            pass
        self.service = self.createService()
        print("Registering mDNS")
        self.zeroconf = Zeroconf(ip_version=self.ip_version)
        try:
            self.zeroconf.register_service(self.service)
        except NonUniqueNameException:
            self.zeroconf.unregister_all_services()
            print("Nonunique-error")
Пример #8
0
    def test_find_with_device(self):
        zeroconf = Zeroconf()
        desc = {'id': '00:00:02:00:00:02'}
        info = ServiceInfo('_hap._tcp.local.', 'foo1._hap._tcp.local.', address=socket.inet_aton('127.0.0.1'),
                           port=1234, properties=desc, weight=0, priority=0)
        zeroconf.unregister_all_services()
        zeroconf.register_service(info, allow_name_change=True)

        result = find_device_ip_and_port('00:00:02:00:00:02', 10)

        zeroconf.unregister_all_services()

        self.assertIsNotNone(result)
        self.assertEqual(result['ip'], '127.0.0.1')
Пример #9
0
def main():
    # Catch CNTRL-C signel
    global shutdown
    signal.signal(signal.SIGINT, signal_cntrl_c)

    init_logging("", 2)
    context = zmq.Context.instance()
    zeroconf = Zeroconf()
    listener = ZeroConfListener(context)
    browser = ServiceBrowser(zeroconf, "_DashZMQ._tcp.local.", listener)

    b = zmq_tcpBridge(tcp_port=5001, context=context)

    while not shutdown:
        time.sleep(1)

    print("Goodbye")
    zeroconf.unregister_all_services()
    b.close()
    time.sleep(1)
    zeroconf.close()
Пример #10
0
class AirDropServer:
    """
    Announces an HTTPS AirDrop server in the local network via mDNS.
    """
    def __init__(self, config):
        self.config = config

        # Use IPv6
        self.serveraddress = ('::', self.config.port)
        self.ServerClass = HTTPServerV6
        self.ServerClass.allow_reuse_address = False

        self.ip_addr = AirDropUtil.get_ip_for_interface(self.config.interface,
                                                        ipv6=True)
        if self.ip_addr is None:
            if self.config.interface == 'awdl0':
                raise RuntimeError(
                    'Interface {} does not have an IPv6 address. '
                    'Make sure that `owl` is running.'.format(
                        self.config.interface))
            else:
                raise RuntimeError(
                    'Interface {} does not have an IPv6 address'.format(
                        self.config.interface))

        self.Handler = AirDropServerHandler
        self.Handler.config = self.config

        self.zeroconf = Zeroconf(interfaces=[str(self.ip_addr)],
                                 ip_version=IPVersion.V6Only,
                                 apple_p2p=platform.system() == 'Darwin')

        self.http_server = self._init_server()
        self.service_info = self._init_service()

    def _init_service(self):
        properties = self.get_properties()
        server = self.config.host_name + '.local.'
        service_name = self.config.service_id + '._airdrop._tcp.local.'
        info = ServiceInfo('_airdrop._tcp.local.',
                           service_name,
                           port=self.config.port,
                           properties=properties,
                           server=server,
                           addresses=[self.ip_addr.packed])
        return info

    def start_service(self):
        logger.info('Announcing service: host {}, address {}, port {}'.format(
            self.config.host_name, self.ip_addr, self.config.port))
        self.zeroconf.register_service(self.service_info)

    def _init_server(self):
        try:
            httpd = self.ServerClass(self.serveraddress, self.Handler)
        except OSError:
            # Address in use. Change port
            self.config.port = self.config.port + 1
            self.serveraddress = (self.serveraddress[0], self.config.port)
            httpd = self.ServerClass(self.serveraddress, self.Handler)

        # Adapt socket for awdl0
        if self.config.interface == 'awdl0' and platform.system() == 'Darwin':
            httpd.socket.setsockopt(socket.SOL_SOCKET, 0x1104, 1)

        httpd.socket = self.config.get_ssl_context().wrap_socket(
            sock=httpd.socket, server_side=True)

        return httpd

    def start_server(self):
        logger.info('Starting HTTPS server')
        self.http_server.serve_forever()

    def stop(self):
        self.zeroconf.unregister_all_services()
        self.http_server.shutdown()

    def get_properties(self):
        properties = {b'flags': str(self.config.flags).encode('utf-8')}
        return properties
Пример #11
0
        # clean failed node
        if not len(failed_node) == 0:
            for node_name in failed_node:
                print(f"I: Node {node_name} failed.")
                node_list[node_name][2].close()
                del reverse_node_list[str(node_list[node_name][0])]
                del node_list[node_name]
                # print(node_list)

except KeyboardInterrupt as e: # Shutdown the server
    print(e)
    exit(0)

finally:
    print("I: cleaning up")
    zeroconf.unregister_all_services()
    zeroconf.close()

    for _, node in node_list.items():
        node[2].close()

    for s in telnet_sockets_going_in:
        s.close()

    for s in telnet_sockets_going_out:
        s.close()

    telnet_server.close()

telnet_server.close()
Пример #12
0
class TCPConnection(threading.Thread):
    """Setups and manages a connection thread to iotdashboard via TCP."""
    def _zconf_publish_tcp(self, port):
        zconf_desc = {'ConnectionUUID': self.connection_id}
        zconf_info = ServiceInfo(
            "_DashIO._tcp.local.",
            "{}._DashIO._tcp.local.".format(self.connection_id),
            addresses=[socket.inet_aton(self.local_ip)],
            port=port,
            properties=zconf_desc,
            server=self.host_name + ".",
        )
        self.zeroconf.register_service(zconf_info)

    def add_device(self, device):
        device.rx_zmq_sub.connect(
            CONNECTION_PUB_URL.format(id=self.connection_id))
        device.rx_zmq_sub.setsockopt(zmq.SUBSCRIBE, self.b_connection_id)
        device.add_control(self.tcp_control)

        self.rx_zmq_sub.connect(DEVICE_PUB_URL.format(id=device.zmq_pub_id))
        self.rx_zmq_sub.setsockopt_string(zmq.SUBSCRIBE, device.zmq_pub_id)

    @staticmethod
    def _is_port_in_use(port):
        with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as port_s:
            return port_s.connect_ex(('localhost', port)) == 0

    def __init__(self,
                 ip_address="*",
                 port=5650,
                 use_zero_conf=True,
                 context=None):
        """TCP Connection

        Parameters
        ---------
            ip_address (str, optional): 
                IP Address to use. Defaults to "*".
            port (int, optional): 
                Port to use. Defaults to 5650.
            use_zero_conf (bool, optional): 
                Use mDNS to advertise the connection. Defaults to True.
            context (optional): ZMQ context. Defaults to None.
        """

        threading.Thread.__init__(self, daemon=True)
        self.context = context or zmq.Context.instance()
        self.connection_id = shortuuid.uuid()
        self.b_connection_id = self.connection_id.encode('utf-8')
        self.use_zeroconf = use_zero_conf
        while self._is_port_in_use(port) and use_zero_conf:
            # increment port until we find one that is free.
            port += 1
        self.ext_url = "tcp://" + ip_address + ":" + str(port)

        self.socket_ids = []
        self.running = True

        host_name = socket.gethostname()
        host_list = host_name.split(".")
        # rename for .local mDNS advertising
        self.host_name = f"{host_list[0]}.local"
        self.local_ip = ip.get_local_ip_address()
        if self.use_zeroconf:
            self.zeroconf = Zeroconf(ip_version=IPVersion.V4Only)
            self.tcp_control = TCP(self.connection_id, "", 0)
            self._zconf_publish_tcp(port)
        else:
            self.tcp_control = TCP(self.connection_id, self.local_ip, port)
        self.start()
        time.sleep(1)

    def close(self):
        """Close the connection."""

        if self.use_zeroconf:
            self.zeroconf.unregister_all_services()
            self.zeroconf.close()
        self.running = False

    def run(self):
        tcpsocket = self.context.socket(zmq.STREAM)

        def _zmq_tcp_send(tcp_id, data):
            try:
                tcpsocket.send(tcp_id, zmq.SNDMORE)
                tcpsocket.send(data, zmq.NOBLOCK)
            except zmq.error.ZMQError as zmq_e:
                logging.debug("Sending TX Error: %s", zmq_e)
                # self.socket_ids.remove(tcp_id)

        tx_zmq_pub = self.context.socket(zmq.PUB)
        tx_zmq_pub.bind(CONNECTION_PUB_URL.format(id=self.connection_id))

        self.rx_zmq_sub = self.context.socket(zmq.SUB)
        # Subscribe on ALL, and my connection
        self.rx_zmq_sub.setsockopt_string(zmq.SUBSCRIBE, "ALL")
        self.rx_zmq_sub.setsockopt_string(zmq.SUBSCRIBE, "ALARM")
        self.rx_zmq_sub.setsockopt_string(zmq.SUBSCRIBE, self.connection_id)
        # rx_zmq_sub.setsockopt_string(zmq.SUBSCRIBE, "ANNOUNCE")

        tcpsocket.bind(self.ext_url)
        tcpsocket.set(zmq.SNDTIMEO, 5)

        poller = zmq.Poller()
        poller.register(tcpsocket, zmq.POLLIN)
        poller.register(self.rx_zmq_sub, zmq.POLLIN)

        tcp_id = tcpsocket.recv()
        tcpsocket.recv()  # empty data here

        while self.running:
            try:
                socks = dict(poller.poll(50))
            except zmq.error.ContextTerminated:
                break

            if tcpsocket in socks:
                tcp_id = tcpsocket.recv()
                message = tcpsocket.recv()
                if tcp_id not in self.socket_ids:
                    logging.debug("Added Socket ID: %s", tcp_id.hex())
                    self.socket_ids.append(tcp_id)
                logging.debug("TCP ID: %s, Rx:\n%s", tcp_id.hex(),
                              message.decode('utf-8').rstrip())
                if message:
                    tx_zmq_pub.send_multipart(
                        [self.b_connection_id, tcp_id, message])
                else:
                    if tcp_id in self.socket_ids:
                        logging.debug("Removed Socket ID: %s", tcp_id.hex())
                        self.socket_ids.remove(tcp_id)
            if self.rx_zmq_sub in socks:
                [address, msg_id, data] = self.rx_zmq_sub.recv_multipart()
                if not data:
                    continue
                if address == b'ALL':
                    for tcp_id in self.socket_ids:
                        logging.debug("TCP ID: %s, Tx:\n%s", tcp_id.hex(),
                                      data.decode('utf-8').rstrip())
                        _zmq_tcp_send(tcp_id, data)
                elif address == self.b_connection_id:
                    logging.debug("TCP ID: %s, Tx:\n%s", msg_id.hex(),
                                  data.decode('utf-8').rstrip())
                    _zmq_tcp_send(msg_id, data)

        for tcp_id in self.socket_ids:
            _zmq_tcp_send(tcp_id, b'')

        tcpsocket.close()
        tx_zmq_pub.close()
        self.rx_zmq_sub.close()
Пример #13
0
class AutoAnnounce(object):
    def __init__(self, port, ssl=False, run=True):
        """
        Announces network settings via mdns

        :type self: AutoAnnounce
        :param self: AutoAnnounce
        :type port: int
        :param port: port of service to announce
        :type ssl: bool
        :param ssl: flag that determine this service uses ssl
        :type run: bool
        :param run: flag that determine whether the announce service starts automatically
        """
        try:
            self.__running = True

            protocol = 'http'
            if ssl:
                protocol = 'https'

            self.zeroconf = Zeroconf()
            ip, hostname = self.get_local_ip()
            desc = {
                'version': RemoteDslrApi.__version__,
                'api_url': protocol + '://' + ip + ':' + str(port) + '/api/',
                'url': protocol + '://' + ip + ':' + str(port)
            }
            self.service = ServiceInfo("_http._tcp.local.",
                                       "RemoteDslrApi._http._tcp.local.",
                                       socket.inet_aton(ip), port, 0, 0, desc,
                                       hostname)

            # logging.basicConfig(level=logging.DEBUG)
            # logging.getLogger('zeroconf').setLevel(logging.DEBUG)

            if run:
                self.run()
        except Exception as ex:
            print ex

    def run(self):
        """
        announces current configuration via mdns

        :type self: AutoAnnounce
        """
        self.zeroconf.register_service(self.service)

    def close(self):
        """
        stop announcing

        :type self: AutoAnnounce
        """
        self.zeroconf.unregister_all_services()
        self.zeroconf.close()
        self.__running = False

    @staticmethod
    def get_local_ip():
        """
        returns current ip and hostname

        :returns: a tuple with IP and Hostname
        :rtype: (string, string)
        """
        s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        s.connect(('8.8.8.8', 53))
        ip = s.getsockname()[0]
        s.close()

        hostname = socket.gethostname()
        return ip, hostname
Пример #14
0
class MainWindow(tk.Tk):
    __EVENT_DATE_TIME_UPDATE = "<<UPDATE_DATE_TIME_EVENT>>"
    __EVENT_COMMAND_UPDATE = "<<UPDATE_COMMAND_EVENT>>"
    __EVENT_EMAIL_UPDATE = "<<UPDATE_EMAIL_EVENT>>"
    __EVENT_NEWS_UPDATE = "<<UPDATE_NEWS_EVENT>>"
    __EVENT_STOCK_UPDATE = "<<UPDATE_STOCK_EVENT>>"
    __EVENT_WEATHER_UPDATE = "<<UPDATE_WEATHER_EVENT>>"

    def __init__(self, ip=None):
        super().__init__()
        self.protocol('WM_DELETE_WINDOW', self.on_exit)

        self.resizable(width=False, height=False)
        self.geometry('{w}x{h}+{x}+{y}'.format(w=800, h=480, x=0, y=0))
        self.overrideredirect(True)  # disable title bar etc.

        self.sock_data = None

        self.logger = logging.getLogger(__name__)

        if ip is None:
            raise ValueError("Listen ip is None")

        self.socket_server = CustomTCPServer((ip, 0), ClientRequestHandler, gui=self,
                                             logger=self.logger)
        self.socket_thread = threading.Thread(target=self.socket_server.serve_forever)
        self.socket_thread.setDaemon(True)
        self.socket_thread.start()
        self.ip = self.socket_server.socket.getsockname()[0]
        self.port = self.socket_server.socket.getsockname()[1]
        self.logger.info("Listening on " + self.ip + ":" + str(self.port))

        self.zeroconf = Zeroconf()
        self.__setup_zeroconf()
        self.logger.info("Zeroconf service registered.")

        self.bind(sequence=self.__EVENT_DATE_TIME_UPDATE, func=self.handle_date_time_update)
        self.bind(sequence=self.__EVENT_COMMAND_UPDATE, func=self.handle_command_update)
        self.bind(sequence=self.__EVENT_EMAIL_UPDATE, func=self.handle_email_update)
        self.bind(sequence=self.__EVENT_NEWS_UPDATE, func=self.handle_news_update)
        self.bind(sequence=self.__EVENT_STOCK_UPDATE, func=self.handle_exchange_update)
        self.bind(sequence=self.__EVENT_WEATHER_UPDATE, func=self.handle_weather_update)

        self.mail_frame = None
        self.news_label = None
        self.exchange_label = None
        self.btn_quit = None
        self.after(10, self.__init_widgets__)

    def __init_widgets__(self):

        __first_row = tk.Frame(self, borderwidth=0, width=800, height=100)

        self.mail_frame = MailFrame(master=__first_row, width=200, height=100)
        self.mail_frame.pack(side=tk.LEFT, fill=tk.X, expand=True, padx=50)

        self.time_frame = TimeFrame(master=__first_row, width=400, height=100)
        self.time_frame.pack(side=tk.LEFT, anchor=tk.CENTER, fill=tk.X, expand=True)

        self.weather_frame = WeatherFrame(master=__first_row, width=200, height=100)
        self.weather_frame.pack(side=tk.LEFT, fill=tk.X, expand=True)

        __first_row.pack(fill=tk.X, expand=True)

        self.news_label = SlidingLabel(master=self, text_length=25)
        self.news_label.pack(after=__first_row, fill=tk.X)

        self.news_label.load_lines(["Breaking News"])

        self.exchange_label = SlidingLabel(master=self, separator="|", text_length=25)
        self.exchange_label.pack(after=self.news_label, fill=tk.X)

        self.exchange_label.load_lines(["Exchange Rates"])

    def trigger_gui_update(self, data_type):
        if data_type == UpdateType.DATETIME:
            self.event_generate(self.__EVENT_DATE_TIME_UPDATE)
        elif data_type == UpdateType.COMMAND:
            self.event_generate(self.__EVENT_COMMAND_UPDATE)
        elif data_type == UpdateType.EMAIL:
            self.event_generate(self.__EVENT_EMAIL_UPDATE)
        elif data_type == UpdateType.NEWS:
            self.event_generate(self.__EVENT_NEWS_UPDATE)
        elif data_type == UpdateType.EXCHANGE:
            self.event_generate(self.__EVENT_STOCK_UPDATE)
        elif data_type == UpdateType.WEATHER:
            self.event_generate(self.__EVENT_WEATHER_UPDATE)
        else:
            self.logger.error("Unknown data type: " + data_type)

    def handle_date_time_update(self, event):
        time_string = self.sock_data['time']
        date_string = self.sock_data['date']
        self.time_frame.update_date_time(time_string=time_string, date_sting=date_string)

    def handle_command_update(self, event):
        cmd = self.sock_data
        if 'quit' == cmd:
            self.on_exit()

    def handle_email_update(self, event):
        print(self.sock_data)
        self.mail_frame.update_count(self.sock_data)

    def handle_news_update(self, event):
        self.news_label.load_lines(self.sock_data)

    def handle_exchange_update(self, event):
        self.exchange_label.load_lines(self.sock_data)

    def handle_weather_update(self, event):
        data = self.sock_data
        self.weather_frame.update_data(temperature=data['temp'], city=data['city'])
        pass

    def on_exit(self):
        self.logger.info("Unregistering Zeroconf services...")
        self.zeroconf.unregister_all_services()
        self.zeroconf.close()

        self.logger.info("Closing socket...")
        self.socket_server.socket.shutdown(socket.SHUT_RDWR)
        self.socket_server.socket.close()

        self.logger.info("Exiting...")
        self.destroy()

    def __setup_zeroconf(self):
        service_desc = {}

        self.zeroconf_info = ServiceInfo("_scpi-raw._tcp.local.",
                                         "Auxiliary Display on {host}._scpi-raw._tcp.local.".format(
                                             host=socket.gethostname()),
                                         address=socket.inet_aton(self.ip), port=self.port,
                                         properties=service_desc)

        self.zeroconf.register_service(self.zeroconf_info)
Пример #15
0
class StreamAdvert(threading.Thread):
    def __init__(self, config):
        threading.Thread.__init__(self)
        self.daemon = True
        self.config = config
        self.logger = logging.getLogger("visiond." + __name__)

        # Attempt to redirect the default handler into our log files
        default_zeroconf_logger = logging.getLogger("zeroconf")
        default_zeroconf_logger.setLevel(logging.INFO)  # TODO: Set based on config
        default_zeroconf_logger.propagate = True
        for handler in logging.getLogger("visiond").handlers:
            default_zeroconf_logger.addHandler(handler)

        self.zeroconf = None
        self._should_shutdown = threading.Event()
        self._q = queue.Queue()

        self.ip_version = IPVersion.V4Only  # IPVersion.All
        self.service_info = self.build_service_info()

    def build_service_info(self, props=None, _type='visiond'):
        if _type == 'visiond':
            _subdesc = "{}:{}".format(socket.gethostname(), self.config.args.name if self.config.args.name else self.config.args.output_port)
            _rtspurl = f"rtsp://{socket.getfqdn()}:{self.config.args.output_port}/video"
            return ServiceInfo(
                "_rtsp._udp.local.",
                f"{_type} ({_subdesc}) ._rtsp._udp.local.",
                addresses=[socket.inet_aton(self.config.args.output_dest)],
                port=int(self.config.args.output_port),
                properties={
                    "port": self.config.args.output_port, 
                    "name": _subdesc, 
                    "service_type": "visiond",
                    "rtspUrl": _rtspurl,
                    "uuid": self.instance_uuid(_rtspurl),
                }
            )
        elif _type == 'webrtc':
            _subdesc = "{}:{}".format(socket.gethostname(), self.config.args.name if self.config.args.name else 6011)
            _wsEndpoint = f"wss://{socket.getfqdn()}:6011"
            return ServiceInfo(
                "_webrtc._udp.local.",
                f"visiond-webrtc ({_subdesc})._webrtc._udp.local.",
                addresses=[socket.inet_aton('0.0.0.0')],
                port=6011,
                properties={
                    "hostname": socket.getfqdn(),
                    "port": 6011, 
                    "name": _subdesc, 
                    "service_type": "webrtc", 
                    "wsEndpoint": _wsEndpoint,
                    "uuid": self.instance_uuid(_wsEndpoint),
                },
            )

    def instance_uuid(self, url):
        # Create a repeatable uuid based on unique url
        return str(uuid.uuid5(uuid.NAMESPACE_URL, url))

    def run(self):
        self.logger.info("Zeroconf advertisement thread is starting...")
        try:
            self.zeroconf = Zeroconf(ip_version=self.ip_version)
            self.register_service(self.service_info)
        except OSError as e:
            # the port was blocked
            self.logger.info.error(
                f"Unable to start zeroconf advertisement thread due to {e}"
            )
            self.clean_up()

        while not self._should_shutdown.is_set():
            try:
                # The following will block for at most [timeout] seconds
                desc_update = self._q.get(block=True, timeout=2)
            except queue.Empty:
                desc_update = None
            if desc_update:
                self.update_service(desc_update)

        # We only get here when shutdown has been called
        self.clean_up()

    def clean_up(self):
        self.logger.info("Zeroconf advertisement thread is stopping...")
        if self.zeroconf:
            self.zeroconf.unregister_all_services()
            self.zeroconf.close()
        self.logger.info("Zeroconf advertisement thread has stopped.")

    def register_service(self, service_info):
        self.zeroconf.register_service(service_info, cooperating_responders=True)

    def update_service(self, desc_update):
        # it does not look like there is a nice way to update
        #  the properties field of a service.
        #  Make a new service with the same details,
        #  but update the properties.

        # Merge the dicts and apply the updates
        self.service_info = self.build_service_info(desc_update)
        self.zeroconf.update_service(self.service_info)

    def unregister_service(self):
        self.zeroconf.unregister_service(self.service_info)

    def shutdown(self):
        self._should_shutdown.set()

    def update(self, desc_update):
        self._q.put_nowait(desc_update)
Пример #16
0
class zmq_tcpBridge(threading.Thread):
    """Setups and manages a connection thread to iotdashboard via TCP."""
    def connect_zmq_device(self, name, ip_address, sub_port, pub_port):
        if name not in self.devices:
            self.devices.append(name)
            logging.debug("Connect: %s, %s, %s, %s", name.decode('utf-8'),
                          ip_address.decode('utf-8'), sub_port.decode('utf-8'),
                          pub_port.decode('utf-8'))
            tx_url = "tcp://{}:{}".format(ip_address.decode('utf-8'),
                                          sub_port.decode('utf-8'))
            rx_url = "tcp://{}:{}".format(ip_address.decode('utf-8'),
                                          pub_port.decode('utf-8'))

            self.tx_zmq_pub.connect(tx_url)
            self.rx_zmq_sub.connect(rx_url)

    def disconnect_zmq_device(self, name, ip_address, sub_port, pub_port):
        if name in self.devices:
            self.devices.remove(name)
            tx_url = "tcp://{}:{}".format(ip_address, sub_port)
            rx_url = "tcp://{}:{}".format(ip_address, pub_port)

            self.tx_zmq_pub.disconnect(tx_url)
            self.rx_zmq_sub.disconnect(rx_url)

        #  Badness 10000
    def __get_local_ip_address(self):
        s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        s.connect(("8.8.8.8", 80))
        return s.getsockname()[0]

    def __zconf_publish_tcp(self, port):
        zconf_desc = {
            'deviceID': self.device_id,
            'deviceType': self.device_type,
            'deviceName': self.device_name
        }
        zconf_info = ServiceInfo(
            "_DashIO._tcp.local.",
            "Bridge-{}._DashIO._tcp.local.".format(port),
            addresses=[socket.inet_aton(self.local_ip)],
            port=port,
            properties=zconf_desc,
            server=self.host_name + ".",
        )
        self.zeroconf.register_service(zconf_info)
        self.zero_service_list.append(zconf_info)

    def __init__(self, tcp_port=5000, context=None):
        """
        """

        threading.Thread.__init__(self, daemon=True)

        self.device_id = "3141592654"
        self.device_type = "TCPBridge"
        self.device_name = "MulipleTCP"
        self.local_ip = self.__get_local_ip_address()
        self.ext_url = "tcp://" + self.local_ip + ":" + str(tcp_port)
        self.host_name = socket.gethostname()
        hs = self.host_name.split(".")
        # rename for .local mDNS advertising
        self.host_name = "{}.local".format(hs[0])
        self.zeroconf = Zeroconf(ip_version=IPVersion.V4Only)
        self.zero_service_list = []
        self.__zconf_publish_tcp(tcp_port)

        logging.debug("HostName: %s", self.host_name)
        logging.debug("      IP: %s", self.local_ip)

        self.context = context or zmq.Context.instance()

        self.socket_ids = []
        self.devices = []
        self.running = True
        self.start()

    def close(self):
        for id in self.socket_ids:
            self._zmq_send(id, "")
        self.zeroconf.unregister_all_services()
        self.zeroconf.close()
        self.running = False

    def run(self):
        self.tx_zmq_pub = self.context.socket(zmq.PUB)
        self.rx_zmq_sub = self.context.socket(zmq.SUB)
        self.rx_zmq_sub.setsockopt(zmq.SUBSCRIBE, b'')

        rx_zconf_pull = self.context.socket(zmq.PULL)
        rx_zconf_pull.connect("inproc://zconf")

        # Subscribe on ALL, and my connection

        self.tcpsocket = self.context.socket(zmq.STREAM)
        self.tcpsocket.bind(self.ext_url)
        self.tcpsocket.set(zmq.SNDTIMEO, 5)

        poller = zmq.Poller()
        poller.register(self.tcpsocket, zmq.POLLIN)
        poller.register(self.rx_zmq_sub, zmq.POLLIN)
        poller.register(rx_zconf_pull, zmq.POLLIN)

        def __zmq_tcp_send(id, data):
            try:
                self.tcpsocket.send(id, zmq.SNDMORE)
                self.tcpsocket.send(data, zmq.NOBLOCK)
            except zmq.error.ZMQError as e:
                logging.debug("Sending TX Error: " + str(e))
                self.socket_ids.remove(id)

        while self.running:
            socks = dict(poller.poll(50))
            if self.tcpsocket in socks:
                id = self.tcpsocket.recv()
                message = self.tcpsocket.recv()
                if id not in self.socket_ids:
                    logging.debug("Added Socket ID: " + id.hex())
                    self.socket_ids.append(id)
                logging.debug("TCP ID: %s, RX: %s", id.hex(),
                              message.decode('utf-8').rstrip())
                if message:
                    logging.debug("ZMQ PUB TX: %s",
                                  message.decode('utf-8').rstrip())
                    self.tx_zmq_pub.send(message)
                else:
                    if id in self.socket_ids:
                        logging.debug("Removed Socket ID: " + id.hex())
                        self.socket_ids.remove(id)
            if self.rx_zmq_sub in socks:
                data = self.rx_zmq_sub.recv()
                for id in self.socket_ids:
                    logging.debug("TCP ID: %s, Tx: %s", id.hex(),
                                  data.decode('utf-8').rstrip())
                    __zmq_tcp_send(id, data)
            if rx_zconf_pull in socks:
                name, action, ip_address, sub_port, pub_port = rx_zconf_pull.recv_multipart(
                )
                if action == b'add':
                    logging.debug("Added device: %s", name.decode('utf-8'))
                    self.connect_zmq_device(name, ip_address, sub_port,
                                            pub_port)
                elif action == b'remove':
                    logging.debug("Remove device: %s", name.decode('utf-8'))
                    try:
                        self.disconnect_zmq_device(name, ip_address, sub_port,
                                                   pub_port)
                    except zmq.error.ZMQError:
                        pass

        self.zeroconf.unregister_all_services()
        self.zeroconf.close()
        self.tcpsocket.close()
        self.tx_zmq_pub.close()
        self.rx_zmq_sub.close()
        self.rx_zconf_pull.close()
Пример #17
0
class Server(object):
    '''
        NetRNG server
    
    '''
    
    
    
    
    def __init__(self,
                 listen_address=None,
                 port=None,
                 max_clients=None,
                 sample_size_bytes=None,
                 hwrng_device=None,
                 use_zeroconf=False):
        log.info('NetRNG server: initializing')

        # Listen address used by the server
        self.listen_address = listen_address

        # TCP port to listen on
        self.port = port



        # Maximum number of clients to accept, this prevents your HWRNG from being
        # overloaded, starving clients. This requires testing and depends entirely on
        # how fast your HWRNG can be read. A device that can spit out 1mbps (100KB/s) could
        # give 100 clients 1KB/s, but a device that can only generate 128bps may only
        # be able to serve 1 client slowly
        self.max_clients = max_clients

        # How much random data to request from the device for each client push
        self.sample_size_bytes = sample_size_bytes



        # Source device to use for random data, should be something fast and
        # high quality, DON'T set this to /dev/random
        self.hwrng_device = hwrng_device

        # open the hwrng for reading later during client requests
        self.hwrng = open(self.hwrng_device, 'rb')




        
        # lock to prevent multiple clients from getting the same random samples
        self.rng_lock = RLock()
        
        self.use_zeroconf = use_zeroconf
        
        if self.use_zeroconf:
            self.zeroconf_controller = Zeroconf()


    def broadcast_service(self):
        if self.listen_address == '0.0.0.0':
            raise Exception('NetRNG server: zeroconf currently requires a specific listen address in /etc/netrng.conf')
        desc = {'version': __version__}
        info = ServiceInfo('_netrng._tcp.local.', '{}._netrng._tcp.local.'.format(socket.gethostname()), socket.inet_aton(self.listen_address), self.port, 0, 0, desc)
        log.info('NetRNG server: registering service with Bonjour: %s', info)
        self.zeroconf_controller.register_service(info)

    def unregister_service(self):
        log.info('NetRNG server: unregistering all bonjour services')
        self.zeroconf_controller.unregister_all_services()

    def serve(self, sock, address):
        '''
            Serves client connections providing random samples to them in a one-to-many 
            request response architecture, with locking to ensure each client gets unique
            samples
    
        '''
        log.debug('NetRNG server: client connected %s', address)

        try:
            while True:
                log.debug('NetRNG server: receive cycle start')
                requestmsg = b""
                with Timeout(3, gevent.Timeout):
                    while True:
                        data = sock.recv(1024)
                        requestmsg = requestmsg + data
                        log.debug('NetRNG server: receive cycle')
                        if SOCKET_DELIMITER in requestmsg:
                            break
                        gevent.sleep()
                requestmsg = requestmsg.replace(SOCKET_DELIMITER, b'')
                request = msgpack.unpackb(requestmsg)
                log.debug('NetRNG server: receive cycle done')
                log.debug('NetRNG server: request received %s', request)
                if request[b'get'] == b'sample':
                    with self.rng_lock:
                        log.debug('NetRNG server: rng lock acquired')
                        sample = self.hwrng.read(self.sample_size_bytes)
                    log.debug('NetRNG server: rng lock released')
                    log.debug('NetRNG server: sending response')
                    responsemsg = msgpack.packb({b'push': b'sample', b'sample': sample})
                    sock.sendall(responsemsg + SOCKET_DELIMITER)
                if request[b'get'] == b'heartbeat':
                    log.debug('NetRNG server: sending heartbeat response to %s', address)
                    responsemsg = msgpack.packb({b'push': b'heartbeat'})
                    sock.sendall(responsemsg + SOCKET_DELIMITER)
        except socket.error as e:
            if isinstance(e.args, tuple):
                if e[0] == errno.EPIPE:
                    log.debug('NetRNG server: client disconnected %s', address)
            else:
                log.exception('NetRNG server: socket error %s', e)
        except gevent.Timeout as timeout:
            log.debug('NetRNG server: client socket timeout')
        except Exception as e:
            log.exception('NetRNG server: %s', e)
        finally:
            sock.close()


    def calibrate(self):
        '''
            Naive implementation of auto-calibration for entropy source, should
            check how much entropy can be received in a given number of seconds
            and use that information to decide how much entropy can be distributed
            per second. With that information, it should be possible to decide
            how many clients can be promised `sample_size_bytes` per second

        '''
        log.info('NetRNG server: starting entropy source performance calibration')
        calibration_period = 15 # seconds
        received_entropy = ""
        stop_time = time.time() + calibration_period
        while time.time() < stop_time:
            with self.rng_lock:
                received_entropy += self.hwrng.read(self.sample_size_bytes)
        received_entropy_size = len(received_entropy)
        received_entropy_per_second = received_entropy_size / calibration_period
        log.info('NetRNG server: entropy source can provide %.2f bytes per second', received_entropy_per_second)

    def start(self):
        '''
            Server starts listening on a TCP socket and spawns a greenlet for each
            new connection. Blocks caller.

        '''
        self.pool = Pool(self.max_clients)
        self.server = StreamServer((self.listen_address, self.port), self.serve, spawn=self.pool)
        log.info('NetRNG server: serving up to %d connections on %s:%d)', self.max_clients, self.listen_address, self.port)
        try:
            self.server.start()
            if self.use_zeroconf:
                self.broadcast_service()
            gevent.wait()
        except KeyboardInterrupt as e:
            log.debug('NetRNG server: exiting due to keyboard interrupt')
            sys.exit(0)


    def stop(self):
        '''
            Server stops listening on the TCP socket, stops accepting new connections
            and finally kills spawned connection handlers

        '''
        log.debug('NetRNG server: stopping server and killing existing client connections')
        if self.use_zeroconf:
            self.unregister_service()
        self.server.stop()