tanganelli / coapthon Goto Github PK
View Code? Open in Web Editor NEWCoAPthon is a python library to the CoAP protocol aligned with the RFC
License: MIT License
CoAPthon is a python library to the CoAP protocol aligned with the RFC
License: MIT License
using byte values in CoAP options can lead to conversion errors.
E.g. using the ETAG option which is considered to contain an OPAQUE content, is forced to be converted to a string which ends up in
UnicodeDecodeError: 'ascii' codec can't decode byte 0xff in position 0: ordinal not in range(128)
Does max-age is been used somehow, except as data field in resource? It seems, that it affects nothing when running coapreverseproxy.py
example. Should max-age field be processed in self-written proxy server?
The response code name should be "DELETED" but in the mapping is listed as "DELETE" which doesn't match up with the other direction.
Hi,
I have a question regarding "add_resource" from server\coap.py: Why don't we allow to leave out intermediate nodes while creating a resource tree? For example:
/small
/large
/other/color
/other/transparence
Why do we have to define /other before creating the sub nodes?
Regards
pi@raspberrypi:~/CoAPthon $ python coapclient.py
Operation must be specified
Command: coapclient.py -o -p [-P]
Options:
-o, --operation= GET|PUT|POST|DELETE|DISCOVER|OBSERVE
-p, --path= Path of the request
-P, --payload= Payload of the request
-f, --payload-file= File with payload of the request
if anyone can help in better understanding what the arguments mean and how the client and server transfer data it will be much appreciated.
Thanking in anticipation.
regards
@rajshah
File layer\resource.py lines 80 and 183 raise TypeError. This is because the self._parent is of type coapthon2.server.coap_protocol.CoAP and origin_class is a subclass of Resource.
Not clear the intention of that part of code. Do you mean self._parent.root.value?
I'm trying to configure a Resource to act as observable. "Observable" is set to true but how do I define/implement when to send the notifications? (I haven't found an example nor test that do this).
All resources inherite from coapthon2.resource.resource which has the _observable and _observe_count member variables. CoAP() has the functionality of notify() and prepare_notification() which seems useful but I don't really understand how all parts fit together at the moment and I might have too many moving targets trying to debug the server with Copper firefox plugin (sending observe messages that even wireshark can't dissect).
My best bet is to use prepare_notification() somehow but not sure how to properly create a thread (or use existing one) so I don't lock processing of incoming requests (looping in my render_GET() seems wrong).
My questions
When I repeatedly create HelperClients within the same process, i.e.,
while True:
c = HelperClient(...)
c.get(...)
c.stop()
sleep(...)
I would expect at most one socket to be open. On Linux if I watch what happens using netstat, I see that the process rapidly accumulates sockets, one for every new HelperClient, even though each client is stopped.
This seems to be down to only doing socket.close() on stop inside the client - if I manually try call socket.shutdown(socket.SHUT_RDWR) before stop the socket appears to be cleaned up correctly.
This seems to be a Python socket 'feature', even for UDP: https://engineering.imvu.com/2014/03/06/charming-python-how-to-actually-close-a-socket-by-calling-shutdown-before-calling-close/
On 4.0.2 I can work around this by manually supplying a socket and shutting it down myself, but the built-in socket should really do this too.
Trying to deserialize a CoAP message with content-type option like so:
from coapthon.messages.request import Request
from coapthon.messages.option import Option
from coapthon import defines
from coapthon.serializer import Serializer
r = Request()
r.mid = 0
r.code = defines.inv_codes["GET"]
r.type = defines.inv_types["CON"]
opt = Option()
opt.number = defines.inv_options["Content-Type"]
opt.value = defines.inv_content_types["text/plain"]
r.add_option(opt)
ser = Serializer()
bytes = ser.serialize(r)
msg = ser.deserialize(bytes, None, None)
Results in TypeError:
Traceback (most recent call last): File "test.py", line 17, in <module> msg = ser.deserialize(bytes, None, None) File "/home/jaakuk03/Development/CoAPthon/coapthon/serializer.py", line 99, in deserialize value = (value << 8) | b TypeError: unsupported operand type(s) for |: 'int' and 'str'
File "server.py", line 2, in
from exampleresources import BasicResource
ImportError: No module named exampleresources
How to solve it?
def connect_server(self, message):
try:
print "\n + Preparing to connect."
client = HelperClient(message.destination)
print "\n + Observing start."
if message is not None:
print "\n + Connection established."
received_message = client.send_request(message)
print received_message
if received_message:
print "\n + Validating response."
print received_message.mid
print received_message.token
print received_message.payload
client.stop()
print "\n + Connection Closed."
except:
print "Errors"
finally:
# Finally clause:
print("Finally clause reached")
but not handling in errors
i am trying to handle server unavailability event .
Am I able to use IPv6 addresses in reverse-proxy xml mapping?
I am trying to implement a CoAP server that handles requests of the following format:
GET /element
to select all elements
GET /element/:id
e.g. /element/12 to select a specific element
GET /element/:id/property
to get a certain property of a specific element
Is there any way to do this with this library? I could not directly find support for such a thing.
I'm interested in using a Python CoAP client library for a project that requires security. I happened upon this library and was pleased to see recent activity. Is there a likely timeframe for implementing DTLS support?
Would you be able to implement blockwise transfers in near future ?
From all python 2.x CoAP implementations, this one seems to be the best, but I would really appreciate blockwise support.
Thanks!
When sending a GET request to URI path "/seperate" of the coapserver.py
example using a CON
message with a token, the empty ACK
echos the token of the CON
message. Correct would be to only echo the message ID and not sending a token.
In the CoAP specification Section 2.2 in figure 4 piggybacked responses are shown, where the ACK does contain a token (as it contains a response to match a request). In figure 5 a separate response is shown and the ACK does not contain a token, but the delayed response does.
Regards,
maribu
Hello,
I am trying to use CoAPthon to open a server and client with port 5683 simultaneously. The idea is CoAPthon server to receive any instantaneous request from external coap client. CoAPthon client is sending ping request to external soap server. All coap transactions are on port 5683. CoAPthon client is able to ping external coap server, but external coap client is not able request CoAPthon server.
When I start the server by running cia-server.py script, I see the server started with device ip address and port 5683. But when I am sending request from external server I don't see any message received by CoAPthon server.
Is there something I am missing. Any help is appreciated
Thanks,
Prasant
Hello, I'm trying to start the Server with a Multicast IP:
python coapserver.py -i 224.0.1.187 -p 5683
The result is the following error message:
socket.error: [Errno 10049] The requested address is not valid in its context
If this content type is not currently supported. Is there any scope of its implementation in near future?
Please confirm.
Hoping to hear from you soon
Thank you
Line 331 in client/coap_protocol.py the 'Token' is always overwritten with 'ciao'. Is that intentional?
Function: def observe(self, client_callback, _args, *_kwargs):
Line 320 retrieves the 'Token' from the arguments but in line 331 the 'Token' is overwritten with a default 'ciao'.
Hi kind sir,
Thank you for implementing this for Python, saved much time and headache.
I've noticed that if the default server listener is used, then the dublicate message is handled incorrectly - server sends response and returns from listen() and thus is stopped. I think there should be continue
instead of return
.
From RFC 7252, section 3.5.2:
In a piggybacked response, the Message ID of the Confirmable request and the Acknowledgement MUST match, and the tokens of the response and original request MUST match. In a separate response, just the tokens of the response and original request MUST match.
When sending an empty token to a CoAPthon server (something that the RFC specifies to be doable and that CoAPthon clients do) the CoAPthon server generates a token and sends it back to the client. Lets call this behaviour CoAPthon server's auto-token generation.
Most clients, incliuding CoAPthon, don't check the returning token when they sent it empty so this CoAPthon server's auto-token generation behaviour does not influence them, but to fulfill the RFC 7252 the clients should reject ACKs with a token not corresponding to the one they sent, as specified a couple lines below the previous cite:
In case a message carrying a response is unexpected (the client is not waiting for a response from the identified endpoint, at the endpoint addressed, and/or with the given token), the response is rejected (Sections 4.2 and 4.3).
Thus, CoAPthon server's auto-token generation breaks the RFC and should be avoided (if the token is used internally, at least it shouldn't be sent in the ACK message if the CON request had an empty token.
Additionally, to fulfill the RFC fully, CoAPthon client should check that the ACK token matches. This second part is not broadly extended among client implementations (and you could always interpret this behaviour not to be mandatory as sending an empty token implies you are not expecting anything, thus not receiving an unexpected token), so implementing should be lower priority, but server auto-token generation must be removed to fulfill RFC 7252.
Hi,
Could you kindly explain the difference between CoAPthon and txThings ?
Thanks,
Venkat
Hi,
I am planning to use Coap DTLS client from this library "test_secure.py". But i am using javascript webserver as my Coap Server. So, my question- will following piece of code will work to validate the key that has been used from the test_secure,py ?
const coap = require('../') // or coap
const path = require('path');
var SegfaultHandler = require('segfault-handler');
SegfaultHandler.registerHandler("crash.log"); // With no argument, SegfaultHandler will generate a generic log file name
const dtls_opts = {
key: path.join(__dirname, '/test/server.pem'),
debug: 1,
handshakeTimeoutMin: 3000
};
const server = coap.createServer(
{
dtls: dtls_opts,
port: 5684,
}
);
server.on('request', function(req, res) {
console.log('request arrives:\n'+JSON.stringify(req));
res.end('Hello ' + req.url.split('/')[1] + '\n')
})
server.listen(function() {
console.log('server started')
});
Thanks,
Jyoti Raj
I am implementing an IoT_Lab for Students. The aim is to develop a coapserver which serves different actors and sensors connected to a pi as resources.
My proof of concept fails at quite a simple Task. I Have a Button which polls its Value periodically and if it sees a change, writes the changed property. But it seems the changedproperty is not read by the server, so no notification to the observers is sent.
I can no see any other way to notify the server about a changed sensor value, is observ only implemented for changes which result through a coap request?
Hello,
I'm opening this issue in link with #37 .
I commented over there, but it went unnoticed, and it's an unrelated problem.
I'll write down below what I posted over here.
I'm sorry for reopening this issue, but there is still a little bug.
It's when you do a request with a full IPv6 (example fd01:0000:0000:3ead:c5b2:bad0:6bb1:6dbf
) but when the response received only gives back the shortened address (aka fd01::3ead:c5b2:bad0:6bb1:6dbf
).
I believe the trouble starts here (or end here ;-) ), line 108 in messagelayer.py, function receive_response
. This function hashes the tuple (host, port, response.mid)
, with the data received in the response, and then tries to compare it with the hash made in the function send_request
, in the same file at line 216.
So I believe the function parse_uri
(here) could be modified to include a contraction of the consecutive 0 in IPv6 addresses.
Ciao Giacomo,
siamo due tesisti che studiano il CoAP(ti avevamo già contattato in precedenza via email) e stiamo utilizzando la tua implementazione. Per il nostro progetto abbiamo modificato il file coapthon/server/coap_protocol.py in quanto non rendeva possibile al server il join a gruppi differenti da quello da te definito in defines.ALL_COAP_NODES. Abbiamo risolto implementando una funzione che permettesse di scegliere il gruppo appena istanziato e cambiando di conseguenza il parametro in ingresso alla funzione di join:
def setGroup(self,g):
self.group = g
self.transport.joinGroup(self.group)
Facci sapere cosa ne pensi, o se quanto da te fatto era una semplice scelta progettuale.
In coapthon2/server/coap_protocol.py#27 logfile is specificed to reside in /home/[username]/.coapthon/ but if this directory doesn't exist the server fail to start.
Creating the folder solves the problem.
For a separate response to work there needs to be a token. The HelperClient only has a token for the Post method (not that it works because other code needs it to be lower case).
I have attached a patch with changes to helperclient.py with the tokens added. The patch has also got changes to allow a timeout to be set through the helper methods.
CoAPthonHelper.zip
First, thank you for this library.
I'm trying to get a PUT response with a payload, however I'm not able to do it, the response always comes with an empty payload. Is it possible to do so with this library?
Here is the relevant part of my code:
def render_PUT(self, request):
if request.payload == "0":
self.payload = "message 1"
else:
self.payload = "message 2"
return self
Traceback (most recent call last):
File "coapserver.py", line 24, in
main()
File "coapserver.py", line 19, in main
reactor.listenUDP(5683, server, "127.0.0.1")
File "C:\Program Files (x86)\Python\lib\site-packages\twisted\internet\posixbase.py", line 364, in listenUDP
p.startListening()
File "C:\Program Files (x86)\Python\lib\site-packages\twisted\internet\udp.py", line 102, in startListening
self._connectToProtocol()
File "C:\Program Files (x86)\Python\lib\site-packages\twisted\internet\udp.py", line 123, in _connectToProtocol
self.protocol.makeConnection(self)
File "C:\Program Files (x86)\Python\lib\site-packages\twisted\internet\protocol.py", line 691, in makeConnection
self.doStart()
File "C:\Program Files (x86)\Python\lib\site-packages\twisted\internet\protocol.py", line 655, in doStart
self.startProtocol()
File "D:\[email protected]\projects\EIT ICT\RICH\CoAPthon\coapthon2\server\coap_protocol.py", line 67, in startProtocol
self.transport.joinGroup(defines.ALL_COAP_NODES)
AttributeError: 'Port' object has no attribute 'joinGroup'
Is there any way to pull out "Get" and "Put" module ?
I want to control Led through "PUT" and acquire fixed sources data through "GET".
Hi @Tanganelli ,
Could you please publish CoAPthon to pip so that users can install it directly ?
Thanks,
Venkat
There is no license in the repository.
I'm trying to find out which Python version this is targetted at. The 'print' statements suggest it's Python 2.x, but when I try running it (e.g. coapserver.py) it can't import 'concurrent.futures', which is a Python 3.x module. How can I get this to run?
Thanks
Ian
I am using the HelperClient class. It seems to only send a single datagram and then wait forever for a response.
The code at the moment does not wrap the message id when it reaches 65525. The += 1 needs to be on a separate line so that it happens before the modulo.
I need this as I will only start my resource as soon as find an observer for the resource
With intermittent connections, where duplicate requests end up being generated, the following happens:
(client)
self._blockLayer.receive_response(transaction)
File "/usr/local/lib/python2.7/dist-packages/coapthon/layers/blocklayer.py", line 182, in receive_response
transaction.response.payload = self._block2_sent[key_token].payload + transaction.response.payload
TypeError: cannot concatenate 'str' and 'NoneType' objects
This occurred using the forward proxy (with multiple simultaneous requests) and the problem seems to be, after correctly receiving the first block, the sending of a delayed response/ACK to the initial request but as if it was block 2 with 0 bytes:
(forward proxy)
2017-04-10 11:34:19,463 - MainThread - coapthon.forward_proxy.coap - DEBUG - receive_datagram - From ('a:1::10', 47197), To None, CON-21046, GET-None, [Uri-Path: big, Proxy-Uri: coap://[a:2::20]:5683/big/, ] No payload
2017-04-10 11:34:19,463 - MainThread - coapthon.layers.messagelayer - DEBUG - receive_request - From ('a:1::10', 47197), To None, CON-21046, GET-None, [Uri-Path: big, Proxy-Uri: coap://[a:2::20]:5683/big/, ] No payload
2017-04-10 11:34:19,464 - MainThread - coapthon.forward_proxy.coap - DEBUG - message duplicated,transaction completed
2017-04-10 11:34:19,464 - MainThread - coapthon.layers.messagelayer - DEBUG - send_response - From None, To ('a:1::10', 47197), ACK-21046, CONTENT-None, [Block2: 22, ] ...0 bytes
2017-04-10 11:34:19,473 - MainThread - coapthon.forward_proxy.coap - DEBUG - send_datagram - From None, To ('a:1::10', 47197), ACK-21046, CONTENT-None, [Block2: 22, ] ...0 bytes
More complete output from the client side:
2017-04-10 11:34:01,852 - MainThread - coapthon.layers.messagelayer - DEBUG - send_request - From None, To ('a:1::1', 5683), CON-21046, GET-None, [Uri-Path: big, Proxy-Uri: coap://[a:2::20]:5683/big/, ] No payload
2017-04-10 11:34:01,855 - MainThread - coapthon.client.coap - DEBUG - send_datagram - From None, To ('a:1::1', 5683), CON-21046, GET-None, [Uri-Path: big, Proxy-Uri: coap://[a:2::20]:5683/big/, ] No payload
2017-04-10 11:34:01,856 - Thread-1 - coapthon.client.coap - DEBUG - Start receiver Thread
2017-04-10 11:34:01,857 - MainThread-Retry-21046 - coapthon.client.coap - DEBUG - retransmit loop ... enter
2017-04-10 11:34:04,451 - MainThread-Retry-21046 - coapthon.client.coap - DEBUG - retransmit loop ... retransmit Request
2017-04-10 11:34:04,459 - MainThread-Retry-21046 - coapthon.client.coap - DEBUG - send_datagram - From None, To ('a:1::1', 5683), CON-21046, GET-None, [Uri-Path: big, Proxy-Uri: coap://[a:2::20]:5683/big/, ] No payload
2017-04-10 11:34:09,647 - MainThread-Retry-21046 - coapthon.client.coap - DEBUG - retransmit loop ... retransmit Request
2017-04-10 11:34:09,653 - MainThread-Retry-21046 - coapthon.client.coap - DEBUG - send_datagram - From None, To ('a:1::1', 5683), CON-21046, GET-None, [Uri-Path: big, Proxy-Uri: coap://[a:2::20]:5683/big/, ] No payload
2017-04-10 11:34:19,461 - Thread-1 - coapthon.client.coap - DEBUG - receive_datagram - From ('a:1::1', 5683), To None, ACK-21046, CONTENT-None, [Block2: 14, ] Lorem ipsum dolor si...1024 bytes
2017-04-10 11:34:19,461 - Thread-1 - coapthon.layers.messagelayer - DEBUG - receive_response - From ('a:1::1', 5683), To None, ACK-21046, CONTENT-None, [Block2: 14, ] Lorem ipsum dolor si...1024 bytes
2017-04-10 11:34:19,461 - Thread-1 - coapthon.client.coap - DEBUG - Waiting for retransmit thread to finish ...
2017-04-10 11:34:19,471 - Thread-1 - coapthon.client.coap - DEBUG - Waiting for retransmit thread to finish ...
2017-04-10 11:34:19,482 - Thread-1 - coapthon.client.coap - DEBUG - Waiting for retransmit thread to finish ...
2017-04-10 11:34:19,490 - MainThread-Retry-21046 - coapthon.client.coap - DEBUG - retransmit loop ... exit
2017-04-10 11:34:19,492 - Thread-1 - coapthon.layers.messagelayer - DEBUG - send_request - From None, To ('a:1::1', 5683), CON-None, GET-None, [Uri-Path: big, Proxy-Uri: coap://[a:2::20]:5683/big/, Block2: 22, ] No payload
2017-04-10 11:34:19,498 - Thread-1 - coapthon.client.coap - DEBUG - send_datagram - From None, To ('a:1::1', 5683), CON-6285, GET-None, [Uri-Path: big, Proxy-Uri: coap://[a:2::20]:5683/big/, Block2: 22, ] No payload
2017-04-10 11:34:19,499 - Thread-1-Retry-6285 - coapthon.client.coap - DEBUG - retransmit loop ... enter
2017-04-10 11:34:19,500 - Thread-1 - coapthon.client.coap - DEBUG - receive_datagram - From ('a:1::1', 5683), To None, ACK-21046, CONTENT-None, [Block2: 22, ] No payload
2017-04-10 11:34:19,500 - Thread-1 - coapthon.layers.messagelayer - DEBUG - receive_response - From ('a:1::1', 5683), To None, ACK-21046, CONTENT-None, [Block2: 22, ] No payload
Exception in thread Thread-1:
...
I followed the install instructions in the README and it all seemed to work but the bitstring package didn't install properly. I noticed this when generating documentation. Bitstring is mentioned in the requirements.txt file so it should have worked the first time around.
I just ran "sudo pip install bitstring" and it installed fine and now I can generate documentation properly. I will see if I get time to reproduce the installation error later on in a VM.
Hello, I have implemented the server as mention in read_me file. When i issue the start command via putty it gives be response as below:
Now when i try to access this via Firefox plugin "Copper" it gives me no response.
Can you please help me? What i actually want to do is to run a server with CoAP, so that all my iot devices can communicate via coap. Any help will be appreciated.
how to use coapforwardproxy between coapclient and coapserver
We have investigated the problem. It seems that once one block is successfully transferred the message.acknowledged flag is set to true. However, as soon as a next block hits hits the timeout it does not enter the re-transmission logic.
Probably because the line #125 in client/coap.py:
`while retransmit_count < defines.MAX_RETRANSMIT and (not message.acknowledged and not message.rejected) \
and not self.stopped.isSet():`
the "message.acknowledged" is True due to the prior success of the earlier block. So, the loop is not actually entered and the client keeps waiting checking whether file descriptor was set rather then proactively setting the descriptor through re-sending the datagram.
I was trying to carry out function of observe by changing value of payload to present time of ObservableResource in Plugtest_resorces.py. but it always reponse blank payload(i tried to access from fitefox to coap)
Dear Sir
I have created an RandomResource in exampleresources.py and would like to send an random value to the client for every 5 seconds using an thread RandomThread , I used RandomResource._coap_server.notify(RandomResource) to send the updated value. Please take a look through the code. Don't know what mistake am doing
class RandomResource(Resource):
class RandomThread(threading.Thread):
def run(self):
while True:
sleep(5)
randnum = randint(1,50)
RandomResource.payload="response:" +str(randnum)
RandomResource._coap_server.notify(RandomResource)
def __init__(self,name="RandomResource",coap_server=None):
super(RandomResource,self).__init__(name, coap_server, visible=True,
observable=True, allow_children=True)
try:
t1 = self.RandomThread()
t1.start()
except:
print "Error: Unable to start thread"
def render_GET(self,request):
return self
Hi,
I have sent payload message from Raspberry Pi3 via python shell script. However, i need some example code to execute DTLS. Please help to provide example script to run DTLS.
Thanks,
Jyoti Raj Sharma
Possibly due to https://bugs.python.org/issue27151, I find that the HelperClient queue is leaking pipes if I create and stop multiple HelperClients in succession.
Regardless of what happens with the multiprocessing queue issue in Python itself, there is no reason HelperClient needs to use a multiprocessing queue at all because it does not do multiprocessing - creating OS pipes is therefore wasteful. To synchronize under multi-threading, the standard synchronized queue class is sufficient.
I read on the documentation saying that CoAP to HTTP proxy is in the to do list. Is the development is still in progress?
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.