Example #1
0
    def __init__(self,
                 hostname=None,
                 catalogue_port=9090,
                 clients=None,
                 clients_config=None,
                 dnssd_enabled=False,
                 dnssd_instance_name=None):
        self._hostname = hostname if hostname is not None else _get_hostname_fallback(
        )

        if not isinstance(self._hostname, six.string_types):
            raise ValueError("Invalid hostname: {}".format(self._hostname))

        if isinstance(clients, list):
            clients = {item.protocol: item for item in clients}

        self._servers = {}
        self._clients = clients if clients else {}
        self._clients_config = clients_config
        self._catalogue_port = catalogue_port
        self._catalogue_server = None
        self._exposed_thing_set = ExposedThingSet()
        self._servient_lock = tornado.locks.Lock()
        self._is_running = False
        self._dnssd_enabled = dnssd_enabled if dnssd_enabled and is_dnssd_supported(
        ) else False
        self._dnssd_instance_name = dnssd_instance_name
        self._dnssd = None
        self._enabled_exposed_thing_ids = set()

        if not len(self._clients):
            self._build_default_clients()
Example #2
0
#!/usr/bin/env python
# -*- coding: utf-8 -*-

"""
DNS Service Discovery (based on Multicast DNS) Thing discovery service.

.. autosummary::
    :toctree: _dnssd

    wotpy.wot.discovery.dnssd.service
"""

from wotpy.support import is_dnssd_supported

if is_dnssd_supported() is False:
    raise NotImplementedError("DNS-SD is not supported in this platform")
Example #3
0
        observable = wot.discover(thing_filter)

        subscription = observable.subscribe(
            on_next=lambda td_str: found.append(ThingDescription(td_str)
                                                ) or resolve())

        yield future_done

        assert_equal_td_sequences(found, [TD_DICT_01, TD_DICT_02])

        subscription.dispose()

    run_test_coroutine(test_coroutine)


@pytest.mark.skipif(not is_dnssd_supported(),
                    reason="Only for platforms that support DNS-SD")
def test_discovery_method_multicast_dnssd():
    """Things can be discovered usin the multicast method supported by DNS-SD."""

    catalogue_port_01 = find_free_port()
    catalogue_port_02 = find_free_port()

    instance_name_01 = "servient-01-{}".format(Faker().pystr())
    instance_name_02 = "servient-02-{}".format(Faker().pystr())

    servient_01 = Servient(catalogue_port=catalogue_port_01,
                           dnssd_enabled=True,
                           dnssd_instance_name=instance_name_01)

    servient_02 = Servient(catalogue_port=catalogue_port_02,
Example #4
0
import collections
import logging
import socket

import pytest
import tornado.gen
import tornado.ioloop
from faker import Faker

from tests.utils import find_free_port
from wotpy.support import is_dnssd_supported
from wotpy.wot.servient import Servient

collect_ignore = []

if not is_dnssd_supported():
    logging.warning("Skipping DNS-SD tests due to unsupported platform")
    collect_ignore.extend(["test_service.py"])


@pytest.fixture
def asyncio_zeroconf():
    """Builds an aiozeroconf service instance and starts browsing for WoT Servient services.
    Provides a deque that contains the service state change history."""

    from aiozeroconf import Zeroconf, ServiceBrowser
    from wotpy.wot.discovery.dnssd.service import DNSSDDiscoveryService

    loop = tornado.ioloop.IOLoop.current()

    service_history = collections.deque([])
Example #5
0
    'faker>=0.8.15,<0.9', 'Sphinx>=1.7.5,<2.0.0',
    'sphinx-rtd-theme>=0.4.0,<0.5.0', 'futures>=3.1.1,<4.0.0',
    'pyOpenSSL>=18.0.0,<19.0.0', 'coveralls>=1.0,<2.0', 'coverage>=5.0<6.0',
    'autopep8>=1.4,<2.0', 'rope>=0.14.0,<1.0'
]

if sys.version_info[0] is 3:
    test_requires.append("bump2version>=1.0,<2.0")

if is_coap_supported():
    install_requires.append('aiocoap[linkheader]==0.4a1')

if is_mqtt_supported():
    install_requires.append('hbmqtt>=0.9.4,<1.0')

if is_dnssd_supported():
    install_requires.append('zeroconf>=0.21.3,<0.22.0')
    test_requires.append('aiozeroconf==0.1.8')

this_dir = path.abspath(path.dirname(__file__))

with open(path.join(this_dir, 'README.md')) as fh:
    long_description = fh.read()

setup(name='wotpy',
      version=__version__,
      description=
      'Python implementation of a W3C WoT Runtime and the WoT Scripting API',
      long_description=long_description,
      long_description_content_type='text/markdown',
      keywords='wot iot gateway fog w3c',
Example #6
0
    def _build_dnssd_discover_observable(self, thing_filter,
                                         dnssd_find_kwargs):
        """Builds an Observable to discover Things using the multicast method based on DNS-SD."""

        if not is_dnssd_supported():
            warnings.warn("Unsupported DNS-SD multicast discovery")
            # noinspection PyUnresolvedReferences
            return Observable.empty()

        dnssd_find_kwargs = dnssd_find_kwargs if dnssd_find_kwargs else {}

        if not self._servient.dnssd:
            # noinspection PyUnresolvedReferences
            return Observable.empty()

        def subscribe(observer):
            """Browses the Servient services using DNS-SD and retrieves the TDs that match the filters."""

            state = {"stop": False}

            @handle_observer_finalization(observer)
            @tornado.gen.coroutine
            def callback():
                address_port_pairs = yield self._servient.dnssd.find(
                    **dnssd_find_kwargs)

                def build_pair_url(idx, path=None):
                    addr, port = address_port_pairs[idx]
                    base = "http://{}:{}".format(addr, port)
                    path = path if path else ''
                    return "{}/{}".format(base, path.strip("/"))

                http_client = AsyncHTTPClient()

                catalogue_resps = [
                    http_client.fetch(build_pair_url(idx))
                    for idx in range(len(address_port_pairs))
                ]

                wait_iter = tornado.gen.WaitIterator(*catalogue_resps)

                while not wait_iter.done() and not state["stop"]:
                    try:
                        catalogue_resp = yield wait_iter.next()
                    except Exception as ex:
                        self._logr.warning(
                            "Exception on HTTP request to TD catalogue: {}".
                            format(ex))
                    else:
                        catalogue = json.loads(catalogue_resp.body)

                        if state["stop"]:
                            return

                        td_resps = yield [
                            http_client.fetch(
                                build_pair_url(wait_iter.current_index,
                                               path=path))
                            for thing_id, path in six.iteritems(catalogue)
                        ]

                        tds = [
                            ThingDescription(td_resp.body)
                            for td_resp in td_resps
                        ]

                        tds_filtered = [
                            td for td in tds
                            if self._is_fragment_match(td, thing_filter)
                        ]

                        [observer.on_next(td.to_str()) for td in tds_filtered]

            def unsubscribe():
                state["stop"] = True

            tornado.ioloop.IOLoop.current().add_callback(callback)

            return unsubscribe

        # noinspection PyUnresolvedReferences
        return Observable.create(subscribe)