Пример #1
0
    def test_coroutine():
        wot = WoT(servient=servient)

        td_01_str = json.dumps(TD_DICT_01)
        td_02_str = json.dumps(TD_DICT_02)

        exposed_thing_01 = wot.produce(td_01_str)
        exposed_thing_02 = wot.produce(td_02_str)

        exposed_thing_01.expose()
        exposed_thing_02.expose()

        catalogue = yield fetch_catalogue(servient)

        assert len(catalogue) == 2
        assert exposed_thing_01.thing.url_name in catalogue.get(
            TD_DICT_01["id"])
        assert exposed_thing_02.thing.url_name in catalogue.get(
            TD_DICT_02["id"])

        td_01_catalogue = yield fetch_catalogue_td(servient, TD_DICT_01["id"])

        assert td_01_catalogue["id"] == TD_DICT_01["id"]
        assert td_01_catalogue["title"] == TD_DICT_01["title"]

        catalogue_expanded = yield fetch_catalogue(servient, expanded=True)

        num_props = len(TD_DICT_01.get("properties", {}).keys())

        assert len(catalogue_expanded) == 2
        assert TD_DICT_01["id"] in catalogue_expanded
        assert TD_DICT_02["id"] in catalogue_expanded
        assert len(
            catalogue_expanded[TD_DICT_01["id"]]["properties"]) == num_props
Пример #2
0
def test_discovery_method_local():
    """All TDs contained in the Servient are returned when using the local
    discovery method without defining the fragment nor the query fields."""

    servient = Servient(dnssd_enabled=False)
    wot = WoT(servient=servient)
    wot.produce(ThingFragment(TD_DICT_01))
    wot.produce(ThingFragment(TD_DICT_02))

    future_done, found = tornado.concurrent.Future(), []

    def resolve():
        len(found) == 2 and not future_done.done() and future_done.set_result(
            True)

    @tornado.gen.coroutine
    def test_coroutine():
        thing_filter = ThingFilterDict(method=DiscoveryMethod.LOCAL)
        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)
Пример #3
0
def test_discovery_fragment():
    """The Thing filter fragment attribute enables discovering Things by matching TD fields."""

    servient = Servient(dnssd_enabled=False)
    wot = WoT(servient=servient)
    wot.produce(ThingFragment(TD_DICT_01))
    wot.produce(ThingFragment(TD_DICT_02))

    def first(thing_filter):
        """Returns the first TD discovery for the given Thing filter."""

        future_done, found = tornado.concurrent.Future(), []

        def resolve():
            not future_done.done() and future_done.set_result(True)

        @tornado.gen.coroutine
        def discover_first():
            observable = wot.discover(thing_filter)

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

            yield future_done

            subscription.dispose()

            assert len(found)

            raise tornado.gen.Return(found[0])

        return tornado.ioloop.IOLoop.current().run_sync(
            discover_first, timeout=TIMEOUT_DISCOVER)

    fragment_td_pairs = [({
        "name": TD_DICT_01.get("name")
    }, TD_DICT_01), ({
        "version": {
            "instance": "2.0.0"
        }
    }, TD_DICT_02), ({
        "id": TD_DICT_02.get("id")
    }, TD_DICT_02), ({
        "security": [{
            "scheme": "psk"
        }]
    }, TD_DICT_01)]

    for fragment, td_expected in fragment_td_pairs:
        td_found = first(
            ThingFilterDict(method=DiscoveryMethod.LOCAL, fragment=fragment))
        assert_equal_tds(td_found, td_expected)
Пример #4
0
def test_produce_model_consumed_thing():
    """Things can be produced from ConsumedThing instances."""

    servient = Servient()
    wot = WoT(servient=servient)

    td_str = json.dumps(TD_EXAMPLE)
    consumed_thing = wot.consume(td_str)
    exposed_thing = wot.produce(consumed_thing)

    assert exposed_thing.id == consumed_thing.td.id
    assert exposed_thing.name == consumed_thing.td.name
    assert len(exposed_thing.properties) == len(consumed_thing.td.properties)
    assert len(exposed_thing.actions) == len(consumed_thing.td.actions)
    assert len(exposed_thing.events) == len(consumed_thing.td.events)
Пример #5
0
def test_produce_model_thing_template():
    """Things can be produced from ThingTemplate instances."""

    thing_id = Faker().url()
    thing_name = Faker().sentence()

    thing_template = ThingFragment({"id": thing_id, "name": thing_name})

    servient = Servient()
    wot = WoT(servient=servient)

    exp_thing = wot.produce(thing_template)

    assert servient.get_exposed_thing(thing_id)
    assert exp_thing.id == thing_id
    assert exp_thing.name == thing_name
Пример #6
0
def test_produce_model_str():
    """Things can be produced from TD documents serialized to JSON-LD string."""

    td_str = json.dumps(TD_EXAMPLE)
    thing_id = TD_EXAMPLE.get("id")

    servient = Servient()
    wot = WoT(servient=servient)

    assert wot.servient is servient

    exp_thing = wot.produce(td_str)

    assert servient.get_exposed_thing(thing_id)
    assert exp_thing.thing.id == thing_id
    assert_exposed_thing_equal(exp_thing, TD_EXAMPLE)
Пример #7
0
async def main(td_url, sleep_time):
    """Subscribes to all events and properties on the remote Thing."""

    wot = WoT(servient=Servient())
    consumed_thing = await wot.consume_from_url(td_url)

    LOGGER.info("ConsumedThing: {}".format(consumed_thing))

    subscriptions = []

    def subscribe(intrct):
        LOGGER.info("Subscribing to: {}".format(intrct))

        sub = intrct.subscribe(
            on_next=lambda item: LOGGER.info("{} :: Next :: {}".format(intrct, item)),
            on_completed=lambda: LOGGER.info("{} :: Completed".format(intrct)),
            on_error=lambda error: LOGGER.warning("{} :: Error :: {}".format(intrct, error)))

        subscriptions.append(sub)

    for name in consumed_thing.properties:
        if consumed_thing.properties[name].observable:
            subscribe(consumed_thing.properties[name])

    for name in consumed_thing.events:
        subscribe(consumed_thing.events[name])

    await asyncio.sleep(sleep_time)

    for subscription in subscriptions:
        LOGGER.info("Disposing: {}".format(subscription))
        subscription.dispose()
Пример #8
0
async def fetch_consumed_thing(td_url, protocol):
    """Gets the remote Thing Description and returns a ConsumedThing."""

    clients = [build_protocol_client(protocol)]
    wot = WoT(servient=Servient(clients=clients))
    consumed_thing = await wot.consume_from_url(td_url)

    return consumed_thing
Пример #9
0
    def start(self):
        """Starts the servers and returns an instance of the WoT object."""

        with (yield self._servient_lock.acquire()):
            self.refresh_forms()
            yield [server.start() for server in six.itervalues(self._servers)]
            self._start_catalogue()
            yield self._start_dnssd()
            self._is_running = True

            raise tornado.gen.Return(WoT(servient=self))
Пример #10
0
def test_duplicated_thing_names(servient):
    """A Servient rejects Things with duplicated IDs."""

    description_01 = {
        "@context": [WOT_TD_CONTEXT_URL],
        "id": uuid.uuid4().urn,
        "title": Faker().sentence()
    }

    description_02 = {
        "@context": [WOT_TD_CONTEXT_URL],
        "id": uuid.uuid4().urn,
        "title": Faker().sentence()
    }

    description_03 = {
        "@context": [WOT_TD_CONTEXT_URL],
        "id": description_01.get("id"),
        "title": Faker().sentence()
    }

    description_01_str = json.dumps(description_01)
    description_02_str = json.dumps(description_02)
    description_03_str = json.dumps(description_03)

    wot = WoT(servient=servient)

    wot.produce(description_01_str)
    wot.produce(description_02_str)

    with pytest.raises(ValueError):
        wot.produce(description_03_str)
Пример #11
0
    def test_coroutine():
        wot = WoT(servient=servient)

        td_01_str = json.dumps(TD_DICT_01)
        td_02_str = json.dumps(TD_DICT_02)

        wot.produce(td_01_str).expose()
        wot.produce(td_02_str)

        catalogue = yield fetch_catalogue(servient)

        assert len(catalogue) == 1
        assert TD_DICT_01["id"] in catalogue
Пример #12
0
def test_produce_from_url(td_example_tornado_app):
    """ExposedThings can be created from URLs that provide Thing Description documents."""

    app_port = find_free_port()
    td_example_tornado_app.listen(app_port)

    url_valid = "http://localhost:{}/".format(app_port)
    url_error = "http://localhost:{}/{}".format(app_port, Faker().pystr())

    wot = WoT(servient=Servient())

    @tornado.gen.coroutine
    def test_coroutine():
        exposed_thing = yield wot.produce_from_url(url_valid)

        assert exposed_thing.thing.id == TD_EXAMPLE.get("id")

        with pytest.raises(Exception):
            yield wot.produce_from_url(url_error)

    run_test_coroutine(test_coroutine)
Пример #13
0
async def main():
    wot = WoT(servient=Servient())
    consumed_thing = await wot.consume_from_url(
        'http://127.0.0.1:9090/urn-dev-wot-example-coffee-machine-97e83de1-f5c9-a4a0-23b6-be918d3a22ca'
    )

    LOGGER.info('Consumed Thing: {}'.format(consumed_thing))

    # Read property allAvailableResources
    allAvailableResources = await consumed_thing.read_property(
        'allAvailableResources')
    LOGGER.info(
        'allAvailableResources value is: {}'.format(allAvailableResources))

    # Now let's change water level to 80
    allAvailableResources['water'] = 80
    await consumed_thing.write_property('allAvailableResources',
                                        allAvailableResources)

    # And see that the water level has changed
    allAvailableResources = await consumed_thing.read_property(
        'allAvailableResources')
    LOGGER.info('allAvailableResources value after change is: {}'.format(
        allAvailableResources))

    # It's also possible to set a client-side handler for observable properties
    consumed_thing.properties['maintenanceNeeded'].subscribe(
        on_next=lambda data: LOGGER.info(
            f'Value changed for an observable property: {data}'),
        on_completed=LOGGER.info(
            'Subscribed for an observable property: maintenanceNeeded'),
        on_error=lambda error: LOGGER.info(
            f'Error for an observable property maintenanceNeeded: {error}'))

    # Now let's make 3 cups of latte!
    makeCoffee = await consumed_thing.invoke_action('makeDrink', {
        'drinkId': 'latte',
        'size': 'l',
        'quantity': 3
    })
    if makeCoffee.get('result'):
        LOGGER.info('Enjoy your drink! \n{}'.format(makeCoffee))
    else:
        LOGGER.info('Failed making your drink: {}'.format(makeCoffee))

    # See how allAvailableResources property value has changed
    allAvailableResources = await consumed_thing.read_property(
        'allAvailableResources')
    LOGGER.info(
        'allAvailableResources value is: {}'.format(allAvailableResources))

    # Let's add a scheduled task
    scheduledTask = await consumed_thing.invoke_action(
        'setSchedule', {
            'drinkId': 'espresso',
            'size': 'm',
            'quantity': 2,
            'time': '10:00',
            'mode': 'everyday'
        })
    LOGGER.info(f'{scheduledTask["message"]} \n{scheduledTask}')

    # See how it has been added to the schedules property
    schedules = await consumed_thing.read_property('schedules')
    LOGGER.info('schedules value is: \n{}'.format(
        json.dumps(schedules, indent=2)))

    # Let's set up a handler for outOfResource event
    consumed_thing.events['outOfResource'].subscribe(
        on_next=lambda data: LOGGER.info(f'New event is emitted: {data}'),
        on_completed=LOGGER.info('Subscribed for an event: outOfResource'),
        on_error=lambda error: LOGGER.info(
            f'Error for an event outOfResource: {error}'))

    # Keep the client awake unless explicitly stopped
    while True:
        await asyncio.sleep(1)
Пример #14
0
async def main():
    wot = WoT(servient=Servient())
    consumed_thing = await wot.consume_from_url(sys.argv[1])

    print("ConsumedThing: {}".format(consumed_thing))