Skip to content

Latest commit

 

History

History
411 lines (308 loc) · 11.4 KB

README.md

File metadata and controls

411 lines (308 loc) · 11.4 KB

Build Status Coverage Status Documentation Status BuyMeACoffe

CoAPthon

CoAPthon is a python 2.7 library to the CoAP protocol compliant with the RFC. Branch is available for the Twisted framework.

For python 3 please visit https://github.com/Tanganelli/CoAPthon3

Citation

If you use CoAPthon software in your research, please cite:

G.Tanganelli, C. Vallati, E.Mingozzi, "CoAPthon: Easy Development of CoAP-based IoT Applications with Python", IEEE World Forum on Internet of Things (WF-IoT 2015)

Software available at https://github.com/Tanganelli/CoAPthon

What is implemented

  • CoAP server
  • CoAP client
  • CoAP to CoAP Forward proxy
  • CoAP to CoAP Reverse Proxy
  • HTTP to CoAP Forward Proxy
  • CoAP to HTTP/HTTPS Forward Proxy
  • Caching feature
  • Observe feature
  • CoRE Link Format parsing
  • Multicast server discovery
  • Blockwise feature

TODO

  • DTLS support

Install instructions

To install the library you need the pip program:

Debian/Ubuntu

$ sudo apt-get install python-pip

Fedora/CentOS

$ sudo yum install python-pip

Archlinux

$ sudo pacman -S python-pip

To install last release:

$ sudo pip install CoAPthon

To install master branch:

$ git clone https://github.com/Tanganelli/CoAPthon.git
$ cd CoAPthon
$ python setup.py sdist
$ sudo pip install dist/CoAPthon-4.0.2.tar.gz -r requirements.txt

Running:

The library is installed in the default path as well as the bins that you can use and customize. In order to start the example CoAP server issue:

$ coapserver.py

To uninstall:

$ sudo pip uninstall CoAPthon

Install instructions on Arduino Yun

Log through ssh to the Yun and issue the following:

# opkg update #updates the available packages list
# opkg install distribute #it contains the easy_install command line tool
# opkg install python-openssl #adds ssl support to python
# easy_install pip #installs pip

Then you need to modify the setup.py and comment the line conditionalExtensions=getExtensions(). Then :

# python setup.py build_py build_scripts install --skip-build

Install instructions for CoRE Resource Directory

To use Resource Directory functionalities, you need to install mongoDB database following the official documentation.

Then you need to configure Resource Directory database. Start mongod process and open a mongo shell. In mongo shell use these commands:

> use resourceDirectory
> db.createUser( {user: "RD",pwd: "res-dir",roles: [ { role: "readWrite", db: "resourceDirectory" } ] } )
> db.resources.createIndex( { "ep": 1, "d": 1 }, { unique: true } )

You can change user, password and database name in the commands above. If you change some parameters, then you must change them also in mongoDB parameters in coapthon/defines.py file where you will find also the path for your mongoDB configuration file. The default configuration file is /usr/local/etc/mongod.conf.

User Guide

CoAP server

In order to implements a CoAP server the basic class must be extended. Moreover the server must add some resources.

from coapthon.server.coap import CoAP
from exampleresources import BasicResource

class CoAPServer(CoAP):
    def __init__(self, host, port):
        CoAP.__init__(self, (host, port))
        self.add_resource('basic/', BasicResource())

def main():
    server = CoAPServer("0.0.0.0", 5683)
    try:
        server.listen(10)
    except KeyboardInterrupt:
        print "Server Shutdown"
        server.close()
        print "Exiting..."

if __name__ == '__main__':
    main()

Resources are extended from the class resource.Resource. Simple examples can be found in example_resource.py.

from coapthon.resources.resource import Resource

class BasicResource(Resource):
    def __init__(self, name="BasicResource", coap_server=None):
        super(BasicResource, self).__init__(name, coap_server, visible=True,
                                            observable=True, allow_children=True)
        self.payload = "Basic Resource"

    def render_GET(self, request):
        return self

    def render_PUT(self, request):
        self.payload = request.payload
        return self

    def render_POST(self, request):
        res = BasicResource()
        res.location_query = request.uri_query
        res.payload = request.payload
        return res

    def render_DELETE(self, request):
        return True

Advanced Use

Separate Responses

To always reply following the separate mode:

from coapthon.resources.resource import Resource

class Separate(Resource):

    def __init__(self, name="Separate", coap_server=None):
        super(Separate, self).__init__(name, coap_server, visible=True, observable=True, allow_children=True)
        self.payload = "Separate"
        self.max_age = 60

    def render_GET(self, request):
        return self, self.render_GET_separate

    def render_GET_separate(self, request):
        time.sleep(5)
        return self

    def render_POST(self, request):
        return self, self.render_POST_separate

    def render_POST_separate(self, request):
        self.payload = request.payload
        return self

    def render_PUT(self, request):
        return self, self.render_PUT_separate

    def render_PUT_separate(self, request):
        self.payload = request.payload
        return self

    def render_DELETE(self, request):
        return self, self.render_DELETE_separate

    def render_DELETE_separate(self, request):
        return True

Advanced interface

Resources can be implemented also through a more advanced interface.

class AdvancedResource(Resource):
    def __init__(self, name="Advanced"):
        super(AdvancedResource, self).__init__(name)
        self.payload = "Advanced resource"

    def render_GET_advanced(self, request, response):
        response.payload = self.payload
        response.max_age = 20
        response.code = defines.Codes.CONTENT.number
        return self, response

    def render_POST_advanced(self, request, response):
        self.payload = request.payload
        from coapthon.messages.response import Response
        assert(isinstance(response, Response))
        response.payload = "Response changed through POST"
        response.code = defines.Codes.CREATED.number
        return self, response

    def render_PUT_advanced(self, request, response):
        self.payload = request.payload
        from coapthon.messages.response import Response
        assert(isinstance(response, Response))
        response.payload = "Response changed through PUT"
        response.code = defines.Codes.CHANGED.number
        return self, response

    def render_DELETE_advanced(self, request, response):
        response.payload = "Response deleted"
        response.code = defines.Codes.DELETED.number
        return True, response

Separate mode with advanced interface

class AdvancedResourceSeparate(Resource):
    def __init__(self, name="Advanced"):
        super(AdvancedResourceSeparate, self).__init__(name)
        self.payload = "Advanced resource"

    def render_GET_advanced(self, request, response):
        return self, response, self.render_GET_separate

    def render_POST_advanced(self, request, response):
        return self, response, self.render_POST_separate

    def render_PUT_advanced(self, request, response):

        return self, response, self.render_PUT_separate

    def render_DELETE_advanced(self, request, response):
        return self, response, self.render_DELETE_separate

    def render_GET_separate(self, request, response):
        time.sleep(5)
        response.payload = self.payload
        response.max_age = 20
        return self, response

    def render_POST_separate(self, request, response):
        self.payload = request.payload
        response.payload = "Response changed through POST"
        return self, response

    def render_PUT_separate(self, request, response):
        self.payload = request.payload
        response.payload = "Response changed through PUT"
        return self, response

    def render_DELETE_separate(self, request, response):
        response.payload = "Response deleted"
        return True, response

CoAP client

from coapthon.client.helperclient import HelperClient

host = "127.0.0.1"
port = 5683
path ="basic"

client = HelperClient(server=(host, port))
response = client.get(path)
print response.pretty_print()
client.stop()

CoRE Resource Directory

Resource Directory server

You can start a CoRE Resource Directory server using ResourceDirectory class as follows:

from coapthon.resource_directory.resourceDirectory import ResourceDirectory


def main():
    server = ResourceDirectory("127.0.0.1", 5683)
    try:
        server.listen(10)
    except KeyboardInterrupt:
        print "Server Shutdown"
        server.close()
        print "Exiting..."


if __name__ == '__main__':
    main()

Resource Directory client examples

def main():
    host = "127.0.0.1"
    port = 5683
    client = HelperClient(server=(host, port))

    # Test discover
    path = "/.well-known/core"
    response = client.get(path)
    print response.pretty_print()

    # Create a registration resource
    path = "rd?ep=node1&con=coap://local-proxy-old.example.com:5683&et=oic.d.sensor"
    ct = {'content_type': defines.Content_types["application/link-format"]}
    payload = '</sensors/temp>;ct=41;rt="temperature-c";if="sensor";anchor="coap://spurious.example.com:5683",' \
              '</sensors/light>;ct=41;rt="light-lux";if="sensor"'
    response = client.post(path, payload, None, None, **ct)
    location_path = response.location_path
    print response.pretty_print()

    # Resource lookup
    path = 'rd-lookup/res?if=sensor'
    response = client.get(path)
    print response.pretty_print()

    # Update a registration resource
    path = location_path + "?con=coaps://new.example.com:5684"
    response = client.post(path, '')
    print response.pretty_print()

    # Read endpoint links
    path = location_path
    response = client.get(path)
    print response.pretty_print()

    # Endpoint lookup
    path = 'rd-lookup/ep?et=oic.d.sensor'
    response = client.get(path)
    print response.pretty_print()

    # Delete a registration resource
    path = location_path
    response = client.delete(path)
    print response.pretty_print()

    client.stop()

Build the documentation

The documentation is based on the Sphinx framework. In order to build the documentation issue the following:

$ pip install Sphinx
$ cd CoAPthon/docs
$ make html

The documentation will be build in CoAPthon/docs/build/html. Let's start from index.html to have an overview of the library.