diff --git a/.gitignore b/.gitignore index 4f5ac156..6fc5e17c 100644 --- a/.gitignore +++ b/.gitignore @@ -11,3 +11,7 @@ htmlcov # generated by `setup.py tests` .eggs + +# pyc files +*.pyc + diff --git a/aiocoap/protocol.py b/aiocoap/protocol.py index 4bf17637..c517feac 100644 --- a/aiocoap/protocol.py +++ b/aiocoap/protocol.py @@ -160,7 +160,7 @@ async def _append_tokenmanaged_transport(self, token_interface_constructor): self.request_interfaces.append(tman) @classmethod - async def create_client_context(cls, *, loggername="coap", loop=None): + async def create_client_context(cls, site=None, *, loggername="coap", loop=None): """Create a context bound to all addresses on a random listening port. This is the easiest way to get an context suitable for sending client @@ -170,7 +170,7 @@ async def create_client_context(cls, *, loggername="coap", loop=None): if loop is None: loop = asyncio.get_event_loop() - self = cls(loop=loop, serversite=None, loggername=loggername) + self = cls(loop=loop, serversite=site, loggername=loggername) # FIXME make defaults overridable (postponed until they become configurable too) for transportname in defaults.get_default_clienttransports(loop=loop): diff --git a/client_coap_server_GET.py b/client_coap_server_GET.py new file mode 100755 index 00000000..e7f9b4d5 --- /dev/null +++ b/client_coap_server_GET.py @@ -0,0 +1,51 @@ +#!/usr/bin/env python3 + +# This file is part of the Python aiocoap library project. +# +# Copyright (c) 2012-2014 Maciej Wasilak , +# 2013-2014 Christian Amsüss +# +# aiocoap is free software, this file is published under the MIT license as +# described in the accompanying LICENSE file. + +"""This is a usage example of aiocoap that demonstrates how to implement a +simple client. See the "Usage Examples" section in the aiocoap documentation +for some more information.""" + +import logging +import asyncio +from os import environ + +from aiocoap import * +from aiocoap import resource + +logging.basicConfig(level=logging.INFO) + + +async def main(): + # TCPClient that acts as CoAP client and CoAP server + from server import TimeResource, BlockResource, SeparateLargeResource + + # Offer the same site as the server does + root = resource.Site() + + root.add_resource(('.well-known', 'core'), resource.WKCResource(root.get_resources_as_linkheader)) + root.add_resource(('time',), TimeResource()) + root.add_resource(('other', 'block'), BlockResource()) + root.add_resource(('other', 'separate'), SeparateLargeResource()) + + tcp_context = await Context.create_client_context(site=root) + + request = Message(code=Code.GET, uri='coap+tcp://localhost/time') + + try: + response = await tcp_context.request(request).response + except Exception as e: + print('Failed to fetch resource:') + print(e) + else: + print('Result: %s\n%r' % (response.code, response.payload)) + +if __name__ == "__main__": + asyncio.Task(main()) + asyncio.get_event_loop().run_forever() diff --git a/server.py b/server.py index c432d993..ff015c1d 100755 --- a/server.py +++ b/server.py @@ -91,7 +91,7 @@ def update_observation_count(self, count): async def render_get(self, request): payload = datetime.datetime.now().\ - strftime("%Y-%m-%d %H:%M").encode('ascii') + strftime("%Y-%m-%d %H:%M:%S").encode('ascii') return aiocoap.Message(payload=payload) # logging setup diff --git a/server_bi_directional_coap.py b/server_bi_directional_coap.py new file mode 100755 index 00000000..d17d8efa --- /dev/null +++ b/server_bi_directional_coap.py @@ -0,0 +1,83 @@ +#!/usr/bin/env python3 + +# This file is part of the Python aiocoap library project. +# +# Copyright (c) 2012-2014 Maciej Wasilak , +# 2013-2014 Christian Amsüss +# +# aiocoap is free software, this file is published under the MIT license as +# described in the accompanying LICENSE file. + +"""This is a usage example of aiocoap that demonstrates how to implement a +simple server. See the "Usage Examples" section in the aiocoap documentation +for some more information.""" + +import asyncio +import logging +from os import environ + +import aiocoap +import aiocoap.resource as resource +from aiocoap import Message +from aiocoap.numbers.codes import Code +# logging setup +from server import TimeResource, BlockResource, SeparateLargeResource + +logging.basicConfig(level=logging.INFO) +LOGGER_NAME = "coap-client-server" +logging.getLogger(LOGGER_NAME).setLevel(logging.DEBUG) + + +async def run_bi_directional_coap_server(root): + """ Bidirectional in the sense that the TCP server will send requests to it's client (connections) and will + act as client as well. + + This approach is interesting when the (UDP/TCP) client is in a private network. + + In this example an tcp connection is preferred because this library stores all incoming connection in a pool. + The server sends a client request every 10 seconds to each opened (incoming) connection. + """ + environ['AIOCOAP_SERVER_TRANSPORT'] = "tcpserver" # Dirty hack to force tcp communication + + protocol = await aiocoap.Context.create_server_context(root, bind=("", aiocoap.COAP_PORT), loggername=LOGGER_NAME) + + # Assumed that there is only 1 transport endpoint, namely the 'tcpserver' + tcp_server_interface = protocol.request_interfaces[0].token_interface + + while True: + await asyncio.sleep(10) + + for conn in tcp_server_interface._pool: # Hack to obtain the list of existing connections. + request = Message(code=Code.GET) + request.remote = conn + + request.opt.uri_path = ["time"] + + try: + logging.getLogger(LOGGER_NAME).info("Sending request to connection %s", conn.hostinfo) + response = await protocol.request(request, handle_blockwise=False).response + except Exception as e: + print('Failed to fetch resource:') + print(e) + else: + print('Result: %s\n%r' % (response.code, response.payload)) + + logging.info("Sleeping for 10 seconds") + + +def main(): + # Resource tree creation + root = resource.Site() + + root.add_resource(('.well-known', 'core'), resource.WKCResource(root.get_resources_as_linkheader)) + root.add_resource(('time',), TimeResource()) + root.add_resource(('other', 'block'), BlockResource()) + root.add_resource(('other', 'separate'), SeparateLargeResource()) + + asyncio.Task(run_bi_directional_coap_server(root)) + + asyncio.get_event_loop().run_forever() + + +if __name__ == "__main__": + main()