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()