SSE with Leshan LWM2M Demo Server - http

I am trying to do an http api that interact with a Leshan Demo Server.
I was trying to handle the OBSERVE in LWM2M, but I need to handle the notification with http.
I discovered that leshan notify using SSE. So I was trying to implement the sse client in python using requests and sseclient.
This is my code:
response= requests.post(url_request , "format=TLV" , stream= True)
client = sseclient.SSEClient(response)
for event in client.events():
print(json.loads(event.data))
I tried to run my script but it seems like the stream is not opening and it close immediately without waiting for the answer of the server, even if requests by default implement keep_alive for TCP connection under HTTP and the stream is True.
Does someone know why?

Reading the sseclient documentation, the correct way so use SSEClient seems to be :
from sseclient import SSEClient
messages = SSEClient('http://example.com/sse_stream/')
for msg in messages:
do_something_useful(msg)
Reading the answer on Leshan Github, the stream URL for Leshan Server Demo seems to be http://your.leshan.server.org/event?ep=your_device_endpoint_name
So I tried that :
from sseclient import SSEClient
messages = SSEClient('http://localhost:8080/event?ep=my_device')
for msg in messages:
print (msg.event, msg.data)
And it works for me 🎉 ! Getting this kind of results when I observe the temperature instance of Leshan Client Demo :
(u'NOTIFICATION', u'{"ep":"my_device","res":"/3303/0","val":{"id":0,"resources":[{"id":5601,"value":-18.9},{"id":5602,"value":31.2},{"id":5700,"value":-18.4},{"id":5701,"value":"cel"}]}}')
(u'COAPLOG', u'{"timestamp":1592296453808,"incoming":true,"type":"CON","code":"POST","mId":29886,"token":"889372029F81C124","options":"Uri-Path: \\"rd\\", \\"reWfKIgPYD\\"","ep":"my_device"}')
(u'COAPLOG', u'{"timestamp":1592296453809,"incoming":false,"type":"ACK","code":"2.04","mId":29886,"token":"889372029F81C124","ep":"my_device"}')
(u'UPDATED', u'{"registration":{"endpoint":"my_device","registrationId":"reWfKIgPYD","registrationDate":"2020-06-16T10:02:25+02:00","lastUpdate":"2020-06-16T10:34:13+02:00","address":"127.0.0.1:44400","lwM2mVersion":"1.0","lifetime":300,"bindingMode":"U","rootPath":"/","objectLinks":[{"url":"/","attributes":{"rt":"\\"oma.lwm2m\\""}},{"url":"/1/0","attributes":{}},{"url":"/3/0","attributes":{}},{"url":"/6/0","attributes":{}},{"url":"/3303/0","attributes":{}}],"secure":false,"additionalRegistrationAttributes":{}},"update":{"registrationId":"reWfKIgPYD","identity":{"peerAddress":{}},"additionalAttributes":{}}}')
(u'COAPLOG', u'{"timestamp":1592296455150,"incoming":true,"type":"NON","code":"2.05","mId":29887,"token":"3998C5DE2588F835","options":"Content-Format: \\"application/vnd.oma.lwm2m+tlv\\" - Observe: 2979","payload":"Hex:e3164563656ce8164408c03199999999999ae815e108c032e66666666666e815e208403f333333333333","ep":"my_device"}')
If you are interested by notification only, just add a if msg.event == 'NOTIFICATION': block.

Related

Adafruit_requests library functions differently than Python requests library

So I'm trying to run a post request to a TD Ameritrade API on an adafruit Magtag device using the adafruit_requests module. I have run the same code in Python using the requests module, which has proven to work fine.
My Magtag device has successfully connected to the internet and executed the test requests adafruit supplied, but will not work with my code and returns a "duplicate headers" error. Below is the complete code that I ran on my MagTag device as well as the error message that was returned.
import ssl
import wifi
import socketpool
import adafruit_requests
import json
# Get wifi details from a secrets.py file
from secrets import secrets
# Connect to wifi
wifi.radio.connect(secrets["ssid"],secrets["password"])
pool = socketpool.SocketPool(wifi.radio)
requests = adafruit_requests.Session(pool, ssl.create_default_context())
# Get json data
refreshToken = ''
client_id = ''
with open("TDtokens.json","r") as tokens_file, open("TDsecrets.json","r") as secrets_file:
refreshToken = json.load(tokens_file)['refresh_token']
client_id = json.load(secrets_file)['client_id']
# Refresh token needs to be triggered every 30 minutes, as authToken expires.
url = r"https://api.tdameritrade.com/v1/oauth2/token"
headers = {'Content-Type':'application/x-www-form-urlencoded'}
data = {'grant_type': 'refresh_token','refresh_token': refreshToken,'client_id':client_id}
authReply = requests.post(url=url, headers=headers, data=data)
print(authReply.json())
{'fault': {'faultstring': 'Duplicate Header "Content-Type"', 'detail': {'errorcode': 'protocol.http.DuplicateHeader'}}}
I have done a lot of tweaking and I can't figure out where this error is coming from, whether from adafruit or TD Ameritrade's side. Upon reading the documentation for the adafruit_requests module I do not see any reason why an error would be raised for this type of request.
If you have any experience with adafruit or Python requests any advice would be greatly appreciated.

httr authentication login/password in "xtb" API

I need to authenticate and get prices using this api
I have no experience with api so my attempt to login gives an error
login <- "vikov98261#jesdoit.com"
pass <- "QazQaz123"
library(httr)
resp <- POST("xapi.xtb.com",
body=list(userId = login,
password = pass) )
Error in curl::curl_fetch_memory(url, handle = handle) :
Failed to connect to xapi.xtb.com port 80: Timed out
Can someone show me how to do it right.
I would like an example of how the login request works.
And also I would like an example of how to get the prices of any currency
Their API documentation uses WebSocket syntax, so I assume xapi.xtb.com may only be used by the clients. I, for once, only managed to get WebSocket to work.
In order to make this work in r you would need a WebSocket client library for r, such as websocket. Once you have that:
1. Define connection
ws <- WebSocket$new("wss://ws.xtb.com/demo")
2. Log in
WebSocket clients work with events. The 'open' event is generated once the connection is established and the 'message' events are generated when messages are received. You need to write handlers for them to orchestrate the way you want to use the XTB API.
The first event will be 'open', so use that to send the login command.
ws$onOpen(function(event) {
ws$send({
"command":"login",
"arguments": {
"userId":"1000",
"password":"PASSWORD",
"appId":"test",
"appName":"test"
}
})
})
3. Your logic
The response to your login command will trigger a 'message' event, the output of which you will need to handle in your code.
ws$onMessage( <your-code-goes-here> )
The easiest way would probably be to send new commands based on what is the structure of the received message, although it can get really complicated with many commands.
4. Connect
After all handles have been defined, don't forget to connect.
ws$connect()

How do you initialize the Twilio Client in Meteor JS?

I'm having incredible difficulty setting up the Twilio Client in Meteor JS, and would really appreciate any help.
I have extracted the relevant code and error logs below. So far as I can tell, it should be simple. The code is just grabbing an authtoken which I have previously generated, and then trying to set up the device using that authtoken. But it's not working.
'click #initializeDevice'(event) {
var thisAuthToken = Session.get('myAuthToken');
console.log(thisAuthToken); // I have confirmed with Twilio support that these authtokens are correctly generated
const Device = require('twilio-client').Device;
Device.setup(thisAuthToken, { debug: true });
var myStatus = Device.status()
console.log(myStatus); //this is logging "offline"
Device.on('ready',function (device) {
log('Twilio.Device Ready!'); //this is not logging anything
});
},
When that code runs, it generates the following logs:
eyJhbGciDpvdXRnb2luZz9hcHBTaWQ9QVA2NDE2MzJmMzA1ZjJiY2I[Note:I have deleted part of the middle of the logged authtoken for the purpose of this public post]5YmMxOGQyOWVlNGU2ZGM0NjdmMzRiNDVhNCIsImV4cCI6MTU3Nz0ygbJKTx15GgNCWDkm-iUPjn_O1NZU6yovp4vjE
modules.js?hash=69069bec9aeba9503ae3467590cf182be57d9e62:3605 Setting up VSP
modules.js?hash=69069bec9aeba9503ae3467590cf182be57d9e62:3605 WSTransport.open() called...
modules.js?hash=69069bec9aeba9503ae3467590cf182be57d9e62:3605 Attempting to connect...
modules.js?hash=69069bec9aeba9503ae3467590cf182be57d9e62:3605 Closing and cleaning up WebSocket...
modules.js?hash=69069bec9aeba9503ae3467590cf182be57d9e62:3605 No WebSocket to clean up.
modules.js?hash=69069bec9aeba9503ae3467590cf182be57d9e62:3605 Could not connect to endpoint: ws does not work in the browser. Browser clients must use the native WebSocket object
modules.js?hash=69069bec9aeba9503ae3467590cf182be57d9e62:3605 Closing and cleaning up WebSocket...
modules.js?hash=69069bec9aeba9503ae3467590cf182be57d9e62:3605 No WebSocket to clean up.
calltemplate.js:31 offline
I'm doing this all from a local server, tunneled through NGROK. I've also set up the Twilio back end, linked the app, purchased a number, etc.
So far as I can tell, the issue, from the logs, appears to be something to do with the way that Meteor uses WebSockets.
Could not connect to endpoint: ws does not work in the browser. Browser clients must use the native WebSocket object
This is a not a Meteor related problem rather than browser issue.
Make sure your browser supports WebRTC
BTW, Your browser might be supporting it but you'd need to enable it.

Firebase push notifications always arrive as an empty message

I have been trying to get push notifications working using firebase. So far I have got as far as successfully sending an empty message "tickle". The problem is adding the message payload seems to have no affect on what the client receives. That is the service worker just sees it as another empty message.
I started by going through googles guide here - https://developers.google.com/web/ilt/pwa/introduction-to-push-notifications
After going through how to send an empty message it says the message payload must be encrypted and suggests using an existing library to do it. To quote - "As with anything related to encryption, it's usually easier to use an actively maintained library than to write your own code".
I tried to use web-push-php which is one of the libraries recommended by googles guide. After having trouble with that i discovered web-php-push doesn't actually support firebase.
Looking on here i find examples that look really simple and don't event encrypt the message payload. It is simply sent in plain json. Doing this has no affect and the receiving end still thinks it's an empty message. See my code below.
I am at a complete loss with this and i'm confused why googles guide says the message data must be encrypted but there are countless examples on SO where it is just send in plain json text.
This is what i am posting from my server to the end point.
POST https://fcm.googleapis.com/fcm/send Authorization: key=[my server
key] Content-Type: application/json {"priority":10,"to":"[subscriber
id]","notification":{"body":"test body","title":"test title"}}
Here is my event listener in my service-worker.js
self.addEventListener('push', function(e) {
var body;
if (e.data) {
body = e.data.text();
} else {
body = "No message "+JSON.stringify(e);
}
var options = {
body: body
};
e.waitUntil(
self.registration.showNotification('Launtel Residential', options)
);
});
When i run the post request above the push notification occurs and triggers the service worker 'push' event as expected but no message data is present. e.data returns null. The 'e' object always just contains a flag set to true. e.isTrusted==true

Asynchronous WebSockets in Winhttp Windows 8

I want just to add WebSockets to my app that uses WinHTTP in async mode.
When I need a WebSocket I call the following.
Before sending request:
WinHttpSetOption(context->hRequest, WINHTTP_OPTION_UPGRADE_TO_WEB_SOCKET, NULL, 0);
In WINHTTP_CALLBACK_STATUS_SENDREQUEST_COMPLETE:
appContext->pIoRequest->hWebSocketHandle = WinHttpWebSocketCompleteUpgrade(appContext->hRequest, NULL);
WinHttpWebSocketReceive(appContext->pIoRequest->hWebSocketHandle, appContext->pszOutBuffer,RESPONSE_BUFFER_SIZE, NULL, NULL);
all without errors.
Now I see in Fiddler that the server sends some data to my WebSocket but there is no WINHTTP_CALLBACK_STATUS_READ_COMPLETE triggered.
Any ideas why this is? How can I read asynchronously from my WebSocket? Sending data to the WebSocket works well.
Omg! I found how its work!
You MUST call additional WinHttpSetStatusCallback to set WebSocket callback for WebSocketHandle returned in WinHttpWebSocketCompleteUpgrade and this callback MUST differ then that from call WinHttpWebSocketCompleteUpgrade was made!
It is no possible to set a context pointer by WinHttpSetOption with WINHTTP_OPTION_CONTEXT_VALUE flag! Its not work. dwContext In WebSocketCallback has wrong data. Call to WinHttpQueryOption in WebSocketCallback return wrong context data. I think that is a BUG in Windows 8.1. I write my own handler to connect my context with WebSocketHandle.
All of this is NOT documented in MSDN! Most of all, I did not google any info about async winhttp websocket usage... So, I am the first=) I will be very glad if my research will help you!
It seems websockets do not get PING and PONG messages to the callback!

Resources