Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added site support for CoAP client including example #132

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,7 @@ htmlcov

# generated by `setup.py tests`
.eggs

# pyc files
*.pyc

4 changes: 2 additions & 2 deletions aiocoap/protocol.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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):
Expand Down
51 changes: 51 additions & 0 deletions client_coap_server_GET.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
#!/usr/bin/env python3

# This file is part of the Python aiocoap library project.
#
# Copyright (c) 2012-2014 Maciej Wasilak <http://sixpinetrees.blogspot.com/>,
# 2013-2014 Christian Amsüss <[email protected]>
#
# 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()
2 changes: 1 addition & 1 deletion server.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
83 changes: 83 additions & 0 deletions server_bi_directional_coap.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
#!/usr/bin/env python3

# This file is part of the Python aiocoap library project.
#
# Copyright (c) 2012-2014 Maciej Wasilak <http://sixpinetrees.blogspot.com/>,
# 2013-2014 Christian Amsüss <[email protected]>
#
# 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()