示例#1
0
文件: server.py 项目: agmangas/wot-py
async def main():
    """Main entrypoint."""

    LOGGER.info("Creating WebSocket server on: {}".format(PORT_WS))

    ws_server = WebsocketServer(port=PORT_WS)

    LOGGER.info("Creating HTTP server on: {}".format(PORT_HTTP))

    http_server = HTTPServer(port=PORT_HTTP)

    LOGGER.info("Creating MQTT server on broker: {}".format(MQTT_BROKER))

    mqtt_server = MQTTServer(MQTT_BROKER)

    LOGGER.info(
        "Creating servient with TD catalogue on: {}".format(PORT_CATALOGUE))

    servient = Servient(catalogue_port=PORT_CATALOGUE)
    servient.add_server(ws_server)
    servient.add_server(http_server)
    servient.add_server(mqtt_server)

    LOGGER.info("Starting servient")

    wot = await servient.start()

    LOGGER.info("Exposing System Monitor Thing")

    exposed_thing = wot.produce(json.dumps(DESCRIPTION))
    exposed_thing.set_property_read_handler("cpuPercent", cpu_percent_handler)
    exposed_thing.properties["cpuThreshold"].write(DEFAULT_CPU_THRESHOLD)
    exposed_thing.expose()

    create_cpu_check_task(exposed_thing)
def main():
    LOGGER.info("Creating COAP server on: {}".format(COAP_PORT))
    coap_server = CoAPServer(port=COAP_PORT)

    LOGGER.info("Creating servient with TD catalogue on: {}".format(CATALOGUE_PORT))
    servient = Servient(catalogue_port=CATALOGUE_PORT)
    servient.add_server(coap_server)

    LOGGER.info("Starting servient")
    wot = yield servient.start()

    LOGGER.info("Exposing and configuring Thing")
    exposed_thing = wot.produce(json.dumps(DESCRIPTION))
    exposed_thing.expose()
def main():
    ssl_context = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)
    ssl_context.load_cert_chain(certfile="../rsa.crt", keyfile="../rsa.key")
    LOGGER.info("Creating HTTPs server on: {}".format(HTTP_PORT))
    http_server = HTTPServer(port=HTTP_PORT, ssl_context=ssl_context)

    LOGGER.info(
        "Creating servient with TD catalogue on: {}".format(CATALOGUE_PORT))
    servient = Servient(catalogue_port=CATALOGUE_PORT)
    servient.add_server(http_server)

    LOGGER.info("Starting servient")
    wot = yield servient.start()

    LOGGER.info("Exposing and configuring Thing")
    exposed_thing = wot.produce(json.dumps(DESCRIPTION))
    exposed_thing.expose()
示例#4
0
def all_protocols_servient():
    """Returns a Servient configured to use all available protocol bindings."""

    servient = Servient(catalogue_port=None)

    http_port = find_free_port()
    http_server = HTTPServer(port=http_port)
    servient.add_server(http_server)

    ws_port = find_free_port()
    ws_server = WebsocketServer(port=ws_port)
    servient.add_server(ws_server)

    if is_coap_supported():
        from wotpy.protocols.coap.server import CoAPServer
        coap_port = find_free_port()
        coap_server = CoAPServer(port=coap_port)
        servient.add_server(coap_server)

    if is_mqtt_supported():
        from wotpy.protocols.mqtt.server import MQTTServer
        from tests.protocols.mqtt.broker import get_test_broker_url, is_test_broker_online
        if is_test_broker_online():
            mqtt_server = MQTTServer(broker_url=get_test_broker_url())
            servient.add_server(mqtt_server)

    @tornado.gen.coroutine
    def start():
        raise tornado.gen.Return((yield servient.start()))

    wot = tornado.ioloop.IOLoop.current().run_sync(start)

    td_dict = {
        "id": uuid.uuid4().urn,
        "title": uuid.uuid4().hex,
        "properties": {
            uuid.uuid4().hex: {
                "observable": True,
                "type": "string"
            }
        }
    }

    td = ThingDescription(td_dict)

    exposed_thing = wot.produce(td.to_str())
    exposed_thing.expose()

    yield servient

    @tornado.gen.coroutine
    def shutdown():
        yield servient.shutdown()

    tornado.ioloop.IOLoop.current().run_sync(shutdown)
示例#5
0
def main():
    global buf
    LOGGER.info("Creating HTTP server on: {}".format(HTTP_PORT))
    http_server = HTTPServer(port=HTTP_PORT)

    LOGGER.info("Creating servient with TD catalogue on: {}".format(CATALOGUE_PORT))
    servient = Servient(catalogue_port=CATALOGUE_PORT)
    servient.add_server(http_server)

    while len(buf) < int(sys.argv[1]):
        r = random.random()
        c = math.floor(r*256)
        buf += format(c, 'x')

    LOGGER.info("Starting servient")
    wot = yield servient.start()

    LOGGER.info("Exposing and configuring Thing")
    exposed_thing = wot.produce(json.dumps(DESCRIPTION))
    exposed_thing.set_property_read_handler("bench", bench_handler)
    exposed_thing.expose()
示例#6
0
def main():
    global buf
    ssl_context = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)
    ssl_context.load_cert_chain(certfile="../rsa.crt", keyfile="../rsa.key")
    LOGGER.info("Creating HTTPs server on: {}".format(HTTP_PORT))
    http_server = HTTPServer(port=HTTP_PORT, ssl_context=ssl_context)

    LOGGER.info("Creating servient with TD catalogue on: {}".format(CATALOGUE_PORT))
    servient = Servient(catalogue_port=CATALOGUE_PORT)
    servient.add_server(http_server)

    while len(buf) < int(sys.argv[1]):
        r = random.random()
        c = math.floor(r*256)
        buf += format(c, 'x')

    LOGGER.info("Starting servient")
    wot = yield servient.start()

    LOGGER.info("Exposing and configuring Thing")
    exposed_thing = wot.produce(json.dumps(DESCRIPTION))
    exposed_thing.set_property_read_handler("bench", bench_handler)
    exposed_thing.expose()
示例#7
0
文件: utils.py 项目: agmangas/wot-py
def build_servient(parsed_args, clients_config=None):
    """Factory function to build a Servient with a set
    of servers depending on the input arguments."""

    logger = logging.getLogger()

    logger.info("Creating servient with TD catalogue on: {}".format(
        parsed_args.port_catalogue))

    servient = Servient(catalogue_port=parsed_args.port_catalogue,
                        hostname=parsed_args.hostname,
                        clients_config=clients_config)

    if parsed_args.port_ws > 0:
        logger.info("Creating WebSocket server on: {}".format(
            parsed_args.port_ws))
        servient.add_server(WebsocketServer(port=parsed_args.port_ws))

    if parsed_args.port_http > 0:
        logger.info("Creating HTTP server on: {}".format(
            parsed_args.port_http))
        servient.add_server(HTTPServer(port=parsed_args.port_http))

    if parsed_args.mqtt_broker:
        try:
            from wotpy.protocols.mqtt.server import MQTTServer
            logger.info("Creating MQTT server on broker: {}".format(
                parsed_args.mqtt_broker))
            mqtt_server = MQTTServer(parsed_args.mqtt_broker,
                                     servient_id=servient.hostname)
            servient.add_server(mqtt_server)
            logger.info("MQTT server created with ID: {}".format(
                mqtt_server.servient_id))
        except NotImplementedError as ex:
            logger.warning(ex)

    if parsed_args.port_coap > 0:
        try:
            from wotpy.protocols.coap.server import CoAPServer
            logger.info("Creating CoAP server on: {}".format(
                parsed_args.port_coap))
            servient.add_server(CoAPServer(port=parsed_args.port_coap))
        except NotImplementedError as ex:
            logger.warning(ex)

    return servient
示例#8
0
def test_servient_start_stop():
    """The servient and contained ExposedThings can be started and stopped."""

    fake = Faker()

    ws_port = find_free_port()
    ws_server = WebsocketServer(port=ws_port)

    servient = Servient()
    servient.disable_td_catalogue()
    servient.add_server(ws_server)

    @tornado.gen.coroutine
    def start():
        raise tornado.gen.Return((yield servient.start()))

    wot = tornado.ioloop.IOLoop.current().run_sync(start)

    thing_id = uuid.uuid4().urn
    name_prop_string = fake.user_name()
    name_prop_boolean = fake.user_name()

    td_doc = {
        "id": thing_id,
        "title": Faker().sentence(),
        "properties": {
            name_prop_string: {
                "observable": True,
                "type": "string"
            },
            name_prop_boolean: {
                "observable": True,
                "type": "boolean"
            }
        }
    }

    td_str = json.dumps(td_doc)

    exposed_thing = wot.produce(td_str)
    exposed_thing.expose()

    value_boolean = fake.pybool()
    value_string = fake.pystr()

    @tornado.gen.coroutine
    def get_property(prop_name):
        """Gets the given property using the WS Link contained in the thing description."""

        td = ThingDescription.from_thing(exposed_thing.thing)
        consumed_thing = ConsumedThing(servient, td=td)

        value = yield consumed_thing.read_property(prop_name)

        raise tornado.gen.Return(value)

    @tornado.gen.coroutine
    def assert_thing_active():
        """Asserts that the retrieved property values are as expected."""

        retrieved_boolean = yield get_property(name_prop_boolean)
        retrieved_string = yield get_property(name_prop_string)

        assert retrieved_boolean == value_boolean
        assert retrieved_string == value_string

    @tornado.gen.coroutine
    def test_coroutine():
        yield exposed_thing.write_property(name=name_prop_boolean,
                                           value=value_boolean)
        yield exposed_thing.write_property(name=name_prop_string,
                                           value=value_string)

        yield assert_thing_active()

        exposed_thing.destroy()

        with pytest.raises(Exception):
            yield assert_thing_active()

        with pytest.raises(Exception):
            exposed_thing.expose()

        yield servient.shutdown()

    run_test_coroutine(test_coroutine)
示例#9
0
def websocket_servient():
    """Returns a Servient that exposes a Websockets server and one ExposedThing."""

    ws_port = find_free_port()
    ws_server = WebsocketServer(port=ws_port)

    servient = Servient(catalogue_port=None)
    servient.add_server(ws_server)

    @tornado.gen.coroutine
    def start():
        raise tornado.gen.Return((yield servient.start()))

    wot = tornado.ioloop.IOLoop.current().run_sync(start)

    property_name_01 = uuid.uuid4().hex
    property_name_02 = uuid.uuid4().hex
    action_name_01 = uuid.uuid4().hex
    event_name_01 = uuid.uuid4().hex

    td_dict = {
        "id": uuid.uuid4().urn,
        "name": uuid.uuid4().hex,
        "properties": {
            property_name_01: {
                "observable": True,
                "type": "string"
            },
            property_name_02: {
                "observable": True,
                "type": "string"
            }
        },
        "actions": {
            action_name_01: {
                "input": {
                    "type": "object"
                },
                "output": {
                    "type": "string"
                },
            }
        },
        "events": {
            event_name_01: {
                "type": "string"
            }
        },
    }

    td = ThingDescription(td_dict)

    exposed_thing = wot.produce(td.to_str())
    exposed_thing.expose()

    @tornado.gen.coroutine
    def action_handler(parameters):
        input_value = parameters.get("input")
        arg_b = input_value.get("arg_b") or uuid.uuid4().hex
        raise tornado.gen.Return(input_value.get("arg_a") + arg_b)

    exposed_thing.set_action_handler(action_name_01, action_handler)

    yield servient

    @tornado.gen.coroutine
    def shutdown():
        yield servient.shutdown()

    tornado.ioloop.IOLoop.current().run_sync(shutdown)
示例#10
0
def main():
    LOGGER.info('Creating WebSocket server on: {}'.format(WEBSOCKET_PORT))
    ws_server = WebsocketServer(port=WEBSOCKET_PORT)

    LOGGER.info('Creating HTTP server on: {}'.format(HTTP_PORT))
    http_server = HTTPServer(port=HTTP_PORT)

    LOGGER.info(
        'Creating servient with TD catalogue on: {}'.format(CATALOGUE_PORT))
    servient = Servient(catalogue_port=CATALOGUE_PORT)
    servient.add_server(ws_server)
    servient.add_server(http_server)

    LOGGER.info('Starting servient')
    wot = yield servient.start()

    LOGGER.info('Exposing and configuring Thing')

    # Produce the Thing from Thing Description
    exposed_thing = wot.produce(json.dumps(TD))

    # Initialize the property values
    yield exposed_thing.properties['allAvailableResources'].write({
        'water':
        read_from_sensor('water'),
        'milk':
        read_from_sensor('milk'),
        'chocolate':
        read_from_sensor('chocolate'),
        'coffeeBeans':
        read_from_sensor('coffeeBeans'),
    })
    yield exposed_thing.properties['possibleDrinks'].write([
        'espresso', 'americano', 'cappuccino', 'latte', 'hotChocolate',
        'hotWater'
    ])
    yield exposed_thing.properties['maintenanceNeeded'].write(False)
    yield exposed_thing.properties['schedules'].write([])

    # # Observe the value of maintenanceNeeded property
    exposed_thing.properties['maintenanceNeeded'].subscribe(

        # Notify a "maintainer" when the value has changed
        # (the notify function here simply logs a message to the console)
        on_next=lambda data: notify(
            f'Value changed for an observable property: {data}'),
        on_completed=notify(
            'Subscribed for an observable property: maintenanceNeeded'),
        on_error=lambda error: notify(
            f'Error for an observable property maintenanceNeeded: {error}'))

    # Override a write handler for servedCounter property,
    # raising maintenanceNeeded flag when the value exceeds 1000 drinks
    @tornado.gen.coroutine
    def served_counter_write_handler(value):

        yield exposed_thing._default_update_property_handler(
            'servedCounter', value)

        if value > 1000:
            yield exposed_thing.properties['maintenanceNeeded'].write(True)

    exposed_thing.set_property_write_handler('servedCounter',
                                             served_counter_write_handler)

    # Now initialize the servedCounter property
    yield exposed_thing.properties['servedCounter'].write(
        read_from_sensor('servedCounter'))

    # Set up a handler for makeDrink action
    async def make_drink_action_handler(params):
        params = params['input'] if params['input'] else {}

        # Default values
        drinkId = 'americano'
        size = 'm'
        quantity = 1

        # Size quantifiers
        sizeQuantifiers = {'s': 0.1, 'm': 0.2, 'l': 0.3}

        # Drink recipes showing the amount of a resource consumed for a particular drink
        drinkRecipes = {
            'espresso': {
                'water': 1,
                'milk': 0,
                'chocolate': 0,
                'coffeeBeans': 2,
            },
            'americano': {
                'water': 2,
                'milk': 0,
                'chocolate': 0,
                'coffeeBeans': 2,
            },
            'cappuccino': {
                'water': 1,
                'milk': 1,
                'chocolate': 0,
                'coffeeBeans': 2,
            },
            'latte': {
                'water': 1,
                'milk': 2,
                'chocolate': 0,
                'coffeeBeans': 2,
            },
            'hotChocolate': {
                'water': 0,
                'milk': 0,
                'chocolate': 1,
                'coffeeBeans': 0,
            },
            'hotWater': {
                'water': 1,
                'milk': 0,
                'chocolate': 0,
                'coffeeBeans': 0,
            },
        }

        # Check if params are provided
        drinkId = params.get('drinkId', drinkId)
        size = params.get('size', size)
        quantity = params.get('quantity', quantity)

        # Read the current level of allAvailableResources
        resources = await exposed_thing.read_property('allAvailableResources')

        # Calculate the new level of resources
        newResources = resources.copy()
        newResources['water'] -= math.ceil(quantity * sizeQuantifiers[size] *
                                           drinkRecipes[drinkId]['water'])
        newResources['milk'] -= math.ceil(quantity * sizeQuantifiers[size] *
                                          drinkRecipes[drinkId]['milk'])
        newResources['chocolate'] -= math.ceil(
            quantity * sizeQuantifiers[size] *
            drinkRecipes[drinkId]['chocolate'])
        newResources['coffeeBeans'] -= math.ceil(
            quantity * sizeQuantifiers[size] *
            drinkRecipes[drinkId]['coffeeBeans'])

        # Check if the amount of available resources is sufficient to make a drink
        for resource, value in six.iteritems(newResources):
            if value <= 0:
                # Emit outOfResource event
                exposed_thing.emit_event(
                    'outOfResource',
                    f'Low level of {resource}: {resources[resource]}%')
                return {
                    'result': False,
                    'message': f'{resource} level is not sufficient'
                }

        # Now store the new level of allAvailableResources and servedCounter
        await exposed_thing.properties['allAvailableResources'].write(
            newResources)

        servedCounter = await exposed_thing.read_property('servedCounter')
        servedCounter += quantity
        await exposed_thing.properties['servedCounter'].write(servedCounter)

        # Finally deliver the drink
        return {'result': True, 'message': f'Your {drinkId} is in progress!'}

    exposed_thing.set_action_handler('makeDrink', make_drink_action_handler)

    # Set up a handler for setSchedule action
    async def set_schedule_action_handler(params):
        params = params['input'] if params['input'] else {}

        # Check if required fields are provided in input
        if 'time' in params and 'mode' in params:

            # Use default values for non-required fields if not provided
            params['drinkId'] = params.get('drinkId', 'americano')
            params['size'] = params.get('size', 'm')
            params['quantity'] = params.get('quantity', 1)

            # Now read the schedules property, add a new schedule to it and then rewrite the schedules property
            schedules = await exposed_thing.read_property('schedules')
            schedules.append(params)
            await exposed_thing.properties['schedules'].write(schedules)
            return {'result': True, 'message': 'Your schedule has been set!'}

        return {
            'result': False,
            'message':
            'Please provide all the required parameters: time and mode.'
        }

    exposed_thing.set_action_handler('setSchedule',
                                     set_schedule_action_handler)

    exposed_thing.expose()
    LOGGER.info(f'{TD["title"]} is ready')
示例#11
0
def coap_servient():
    """Returns a Servient that exposes a CoAP server and one ExposedThing."""

    from wotpy.protocols.coap.server import CoAPServer

    coap_port = find_free_port()
    the_coap_server = CoAPServer(port=coap_port)

    servient = Servient(catalogue_port=None)
    servient.add_server(the_coap_server)

    @tornado.gen.coroutine
    def start():
        raise tornado.gen.Return((yield servient.start()))

    wot = tornado.ioloop.IOLoop.current().run_sync(start)

    property_name_01 = uuid.uuid4().hex
    action_name_01 = uuid.uuid4().hex
    event_name_01 = uuid.uuid4().hex

    td_dict = {
        "id": uuid.uuid4().urn,
        "title": uuid.uuid4().hex,
        "properties": {
            property_name_01: {
                "observable": True,
                "type": "string"
            }
        },
        "actions": {
            action_name_01: {
                "input": {
                    "type": "number"
                },
                "output": {
                    "type": "number"
                },
            }
        },
        "events": {
            event_name_01: {
                "type": "string"
            }
        },
    }

    td = ThingDescription(td_dict)

    exposed_thing = wot.produce(td.to_str())
    exposed_thing.expose()

    @tornado.gen.coroutine
    def action_handler(parameters):
        input_value = parameters.get("input")
        raise tornado.gen.Return(int(input_value) * 2)

    exposed_thing.set_action_handler(action_name_01, action_handler)

    yield servient

    @tornado.gen.coroutine
    def shutdown():
        yield servient.shutdown()

    tornado.ioloop.IOLoop.current().run_sync(shutdown)
示例#12
0
def test_consumed_client_protocols_preference():
    """The Servient selects different protocol clients to consume Things
    depending on the protocol choices displayed on the Thing Description."""

    servient = Servient(catalogue_port=None)

    @tornado.gen.coroutine
    def servient_start():
        raise tornado.gen.Return((yield servient.start()))

    @tornado.gen.coroutine
    def servient_shutdown():
        yield servient.shutdown()

    http_port = find_free_port()
    http_server = HTTPServer(port=http_port)

    servient.add_server(http_server)

    ws_port = find_free_port()
    ws_server = WebsocketServer(port=ws_port)

    servient.add_server(ws_server)

    client_server_map = {
        HTTPClient: http_server,
        WebsocketClient: ws_server
    }

    wot = tornado.ioloop.IOLoop.current().run_sync(servient_start)

    prop_name = uuid.uuid4().hex

    td_produce = ThingDescription({
        "id": uuid.uuid4().urn,
        "name": uuid.uuid4().hex,
        "properties": {
            prop_name: {
                "observable": True,
                "type": "string"
            }
        }
    })

    exposed_thing = wot.produce(td_produce.to_str())
    exposed_thing.expose()

    td_forms_all = ThingDescription.from_thing(exposed_thing.thing)

    client_01 = servient.select_client(td_forms_all, prop_name)
    client_01_class = client_01.__class__

    assert client_01_class in six.iterkeys(client_server_map)

    tornado.ioloop.IOLoop.current().run_sync(servient_shutdown)
    servient.remove_server(client_server_map[client_01_class].protocol)
    tornado.ioloop.IOLoop.current().run_sync(servient_start)

    td_forms_removed = ThingDescription.from_thing(exposed_thing.thing)

    client_02 = servient.select_client(td_forms_removed, prop_name)
    client_02_class = client_02.__class__

    assert client_02_class != client_01_class
    assert client_02_class in six.iterkeys(client_server_map)

    tornado.ioloop.IOLoop.current().run_sync(servient_shutdown)