Reading a influx measurement using an esp32 and Ardino - influxdb

I need to read a temperature present in an influx v1.8 database, using esp8266 and esp32 in Arduino.
I am using the ESP8266 influxdb v3.12.1 library.
This query works from a command prompt:
curl --insecure -XPOST https://10.1.1.40:8086/api/v2/query -sS \
-H 'Accept:application/csv' \
-H 'Content-type:application/vnd.flux' \
-d 'from(bucket:"test01")
|> range(start:-5m)
|> filter(fn:(r) => r._measurement == "sens848a6a6")'
In my Arduino code I have:
void loop() {
String query = "from(bucket:\"test01\") |> range(start:-5m) |> filter(fn:(r) => r._measurement == \"sens848a6a6\")";
// Send query to the server and get result
FluxQueryResult result = client.query(query);
// Check if there was an error
if(result.getError() != "") {
Serial.print("Query result error: ");
Serial.println(result.getError());
}
while (result.next()) {
// Get typed value for flux result column 'temperature'
String temp = result.getValueByName("temperature").getString();
Serial.print("temperature: ");
Serial.print(temp);
// Get converted value for flux result column '_value' where there is temperature value
long value = result.getValueByName("_value").getLong();
Serial.print(value);
Serial.println();
}
}
But is not working:
Query result error: send header failed
temperature: 0
Help appreciated!

That send header failed might give us some hint on the Arduino SDK you are using. InflxuDB instance should be. The issue I assume should be inside the Arduino HTTP client. You should use Postman to mock the behavior of Arduino HTTP client, which set up the HTTP headers and send the Flux query in the body to see whether it works or not.
Besides, you are using HTTPS, there was an issue of Arduino HTTP client calling HTTPS. You might just try HTTP first and then switch to HTTPS when the client is stable or you could provide the certificates.

Related

Server doesn't accept double quotes in the query

I'm trying to make the same request as here using requests and python. This is my code:
address = "0x800d0c1e4fb219a2d9bd2f292aa91abdcd862915"
data= """{"query":"{poolSnapshots(where:{pool:"%s"}, orderBy: date){id baseTokenLiquidity datatokenLiquidity spotPrice}}","variables":null,"operationName":null}"""%(address)
response = requests.post('https://v4.subgraph.polygon.oceanprotocol.com/subgraphs/name/oceanprotocol/ocean-subgraph', data=data).json()
But when I execute the code I got the following error:
GraphQL server error (client error): expected ,or} at line 1 column 39: 0
What am I missing? I'm texting the double quotes wrongly? Thanks for answers!
The API expects a stringified JSON that you wrapped into the triple quotes. The right way is to use json.dumps to stringify the query payload (dict). It will convert the payload data types to corresponding JSON types.
import requests
import json
address = "0x800d0c1e4fb219a2d9bd2f292aa91abdcd862915"
url = 'https://v4.subgraph.polygon.oceanprotocol.com/subgraphs/name/oceanprotocol/ocean-subgraph'
data = {
"query": "{poolSnapshots(where:{pool:\"%s\"}, orderBy: date){id baseTokenLiquidity datatokenLiquidity spotPrice}}" % address,
"operationName": None,
"variables": None,
}
response = requests.post(url, data=json.dumps(data))
print(response.json())

How to write a Rest command in Delphi 7 to use REST API from parse.com

i hope somebody can help me how to translate the following REST command to delphi 7 to use with Indy idHttp (or other component). I'm using the parse.com plataform, their tutorial generate rest request in CURL and Python, for example:
In Python a POST example:
import json,httplib
connection = httplib.HTTPSConnection('api.parse.com', 443)
connection.connect()
connection.request('POST', '/1/classes/GameScore', json.dumps({
"score": 1337,
"playerName": "Sean Plott",
"cheatMode": False
}), {
"X-Parse-Application-Id": "here-go-application-id",
"X-Parse-REST-API-Key": "here-go-rest-api-key",
"Content-Type": "application/json"
})
result = json.loads(connection.getresponse().read())
print result
Here the same POST example in CURL:
curl -X POST \
-H "X-Parse-Application-Id: here-go-application-id" \
-H "X-Parse-REST-API-Key: here-go-rest-api-key" \
-H "Content-Type: application/json" \
-d '{"score":1337,"playerName":"Sean Plott","cheatMode":false}' \
https://api.parse.com/1/classes/GameScore
And how GET request in python an curl:
in python:
import json,httplib
connection = httplib.HTTPSConnection('api.parse.com', 443)
connection.connect()
connection.request('GET', '/1/classes/GameScore/Ed1nuqPvcm', '', {
"X-Parse-Application-Id": "here-go-application-id",
"X-Parse-REST-API-Key": "here-go-rest-api-key"
})
result = json.loads(connection.getresponse().read())
print result
in CURL:
curl -X GET \
-H "X-Parse-Application-Id: here-go-application-id" \
-H "X-Parse-REST-API-Key: here-go-rest-api-key" \
https://api.parse.com/1/classes/GameScore/Ed1nuqPvcm
My question is, how can I do the same, but in Delphi 7. I hope my question is clear, because I need this answers.
One option, using some part of our mORMot Open Source framework:
uses
SynCrtSock, // for HTTP process
SynCommons; // for TDocVariant type support
var t: variant;
begin
// POST example
// 1. prepare the JSON content (several ways to do the same)
t := _Obj(['score',1337,'playerName','Sean Plott','cheatMode',False]);
// same as:
t := _Json('"score":1337,"playerName":"Sean Plott","cheatMode":False');
// or with MongoDB extended syntax:
t := _Json('score:1337,playerName:"Sean Plott",cheatMode:False');
// or using late-binding to create the object
TDocVariant.New(t);
t.score := 1337;
t.playerName := 'Sean Plott';
t.cheatMode := false;
// 2. create the resource on the server
TWinHTTP.Post( // or TWinINet.Post(
'https://api.parse.com/1/classes/GameScore',t,
'X-Parse-Application-Id: here-go-application-id'#13#10+
'Content-Type: application/json');
// GET example
// 1. retrieve the resource
t := _Json(TWinHTTP.Get('https://api.parse.com/1/classes/GameScore/Ed1nuqPvcm',
'X-Parse-Application-Id: here-go-application-id'#13#10+
'Content-Type: application/json'));
// 2. access the resource members via late-binding of the variant value
writeln('score = ',t.score);
writeln('playerName = ',t.playerName);
writeln('cheatMode = ',t.cheatMode);
end.
It will use either the WinHTTP API or the WinINet API for the HTTP requests.
And our new TDocVariant custom variant type for easy JSON process, including late-binding of property names.
Above code is IMHO pretty easy to follow, and will work from Delphi 6 up to XE5. Ensure you retrieve the latest 1.18 unstable version of our units, since TDocVariant was just introduced.

Twitter stream API - Erlang client

I'm very new in Erlang world and I'm trying to write a client for the Twitter Stream API. I'm using httpc:request to make a POST request and I constantly get 401 error, I'm obviously doing something wrong with how I'm sending the request... What I have looks like this:
fetch_data() ->
Method = post,
URL = "https://stream.twitter.com/1.1/statuses/filter.json",
Headers = "Authorization: OAuth oauth_consumer_key=\"XXX\", oauth_nonce=\"XXX\", oauth_signature=\"XXX%3D\", oauth_signature_method=\"HMAC-SHA1\", oauth_timestamp=\"XXX\", oauth_token=\"XXX-XXXXX\", oauth_version=\"1.0\"",
ContentType = "application/json",
Body = "{\"track\":\"keyword\"}",
HTTPOptions = [],
Options = [],
R = httpc:request(Method, {URL, Headers, ContentType, Body}, HTTPOptions, Options),
R.
At this point I'm confident there's no issue with the signature as the same signature works just fine when trying to access the API with curl. I'm guessing there's some issue with how I'm making the request.
The response I'm getting with the request made the way demonstrated above is:
{ok,{{"HTTP/1.1",401,"Unauthorized"},
[{"cache-control","must-revalidate,no-cache,no-store"},
{"connection","close"},
{"www-authenticate","Basic realm=\"Firehose\""},
{"content-length","1243"},
{"content-type","text/html"}],
"<html>\n<head>\n<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\"/>\n<title>Error 401 Unauthorized</title>\n</head>\n<body>\n<h2>HTTP ERROR: 401</h2>\n<p>Problem accessing '/1.1/statuses/filter.json'. Reason:\n<pre> Unauthorized</pre>\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n</body>\n</html>\n"}}
When trying with curl I'm using this:
curl --request 'POST' 'https://stream.twitter.com/1.1/statuses/filter.json' --data 'track=keyword' --header 'Authorization: OAuth oauth_consumer_key="XXX", oauth_nonce="XXX", oauth_signature="XXX%3D", oauth_signature_method="HMAC-SHA1", oauth_timestamp="XXX", oauth_token="XXX-XXXX", oauth_version="1.0"' --verbose
and I'm getting the events just fine.
Any help on this would be greatly appreciated, new with Erlang and I've been pulling my hair out on this one for quite a while.
There are several issues with your code:
In Erlang you are encoding parameters as a JSON body while with curl, you are encoding them as form data (application/x-www-form-urlencoded). Twitter API expects the latter. In fact, you get a 401 because the OAuth signature does not match, as you included the track=keyword parameter in the computation while Twitter's server computes it without the JSON body, as it should per OAuth RFC.
You are using httpc with default options. This will not work with the streaming API as the stream never ends. You need to process results as they arrive. For this, you need to pass {sync, false} option to httpc. See also stream and receiver options.
Eventually, while httpc can work initially to access Twitter streaming API, it brings little value to the code you need to develop around it to stream from Twitter API. Depending on your needs you might want to replace it a simple client directly built on ssl, especially considering it can decode HTTP packets (what is left for you is the HTTP chunk encoding).
For example, if your keywords are rare, you might get a timeout from httpc. Besides, it might be easier to update the list of keywords or your code with no downtime without httpc.
A streaming client directly based on ssl could be implemented as a gen_server (or a simple process, if you do not follow OTP principles) or even better a gen_fsm to implement reconnection strategies. You could proceed as follows:
Connect using ssl:connect/3,4 specifying that you want the socket to decode the HTTP packets with {packet, http_bin} and you want the socket to be configured in passive mode {active, false}.
Send the HTTP request packet (preferably as an iolist, with binaries) with ssl:send/2,3. It shall spread on several lines separated with CRLF (\r\n), with first the query line (GET /1.1/statuses/filter.json?... HTTP/1.1) and then the headers including the OAuth headers. Make sure you include Host: stream.twitter.com as well. End with an empty line.
Receive the HTTP response. You can implement this with a loop (since the socket is in passive mode), calling ssl:recv/2,3 until you get http_eoh (end of headers). Note down whether the server will send you data chunked or not by looking at the Transfer-Encoding response header.
Configure the socket in active mode with ssl:setopts/2 and specify you want packets as raw and data in binary format. In fact, if data is chunked, you could continue to use the socket in passive mode. You could also get data line by line or get data as strings. This is a matter of taste: raw is the safest bet, line by line requires that you check the buffer size to prevent truncation of a long JSON-encoded tweet.
Receive data from Twitter as messages sent to your process, either with receive (simple process) or in handle_info handler (if you implemented this with a gen_server). If data is chunked, you shall first receive the chunk size, then the tweets and the end of the chunk eventually (cf RFC 2616). Be prepared to have tweets that spread on several chunks (i.e. maintain some kind of buffer). The best here is to do the minimum decoding in this process and send tweets to another process, possibly in binary format.
You should also handle errors and socket being closed by Twitter. Make sure you follow Twitter's guidelines for reconnection.

Get Request from happstack-lite API

How would I go about getting the Request data from the happstack-lite API? I'm trying to get the client's IP address. From what I can tell it's in Request::rqPeer, and I get confused trying to dive into the monadic-layers of the happstack API.
You can use askRq in any ServerMonad to get at the Request, which you could pattern match on with record syntax to get the client hostname:
do Request {rqPeer = (host,_)} <- askRq
ok $ "Your IP: " ++ host

python: how to fetch an url? (with improper response headers)

I want to build a small script in python which needs to fetch an url. The server is a kind of crappy though and replies pure ASCII without any headers.
When I try:
import urllib.request
response = urllib.request.urlopen(url)
print(response.read())
I obtain a http.client.BadStatusLine: 100 error because this isn't a properly formatted HTTP response.
Is there another way to fetch an url and get the raw content, without trying to parse the response?
Thanks
It's difficult to answer your direct question without a bit more information; not knowing exactly how the (web) server in question is broken.
That said, you might try using something a bit lower-level, a socket for example. Here's one way (python2.x style, and untested):
#!/usr/bin/env python
import socket
from urlparse import urlparse
def geturl(url, timeout=10, receive_buffer=4096):
parsed = urlparse(url)
try:
host, port = parsed.netloc.split(':')
except ValueError:
host, port = parsed.netloc, 80
sock = socket.create_connection((host, port), timeout)
sock.sendall('GET %s HTTP/1.0\n\n' % parsed.path)
response = [sock.recv(receive_buffer)]
while response[-1]:
response.append(sock.recv(receive_buffer))
return ''.join(response)
print geturl('http://www.example.com/') #<- the trailing / is needed if no
other path element is present
And here's a stab at a python3.2 conversion (you may not need to decode from bytes, if writing the response to a file for example):
#!/usr/bin/env python
import socket
from urllib.parse import urlparse
ENCODING = 'ascii'
def geturl(url, timeout=10, receive_buffer=4096):
parsed = urlparse(url)
try:
host, port = parsed.netloc.split(':')
except ValueError:
host, port = parsed.netloc, 80
sock = socket.create_connection((host, port), timeout)
method = 'GET %s HTTP/1.0\n\n' % parsed.path
sock.sendall(bytes(method, ENCODING))
response = [sock.recv(receive_buffer)]
while response[-1]:
response.append(sock.recv(receive_buffer))
return ''.join(r.decode(ENCODING) for r in response)
print(geturl('http://www.example.com/'))
HTH!
Edit: You may need to adjust what you put in the request, depending on the web server in question. Guanidene's excellent answer provides several resources to guide you on that path.
What you need to do in this case is send a raw HTTP request using sockets.
You would need to do a bit of low level network programming using the socket python module in this case. (Network sockets actually return you all the information sent by the server as it as, so you can accordingly interpret the response as you wish. For example, the HTTP protocol interprets the response in terms of standard HTTP headers - GET, POST, HEAD, etc. The high-level module urllib hides this header information from you and just returns you the data.)
You also need to have some basic information about HTTP headers. For your case, you just need to know about the GET HTTP request. See its definition here - http://djce.org.uk/dumprequest, see an example of it here - http://en.wikipedia.org/wiki/HTTP#Example_session. (If you wish to capture live traces of HTTP requests sent from your browser, you would need a packet sniffing software like wireshark.)
Once you know basics about socket module and HTTP headers, you can go through this example - http://coding.debuntu.org/python-socket-simple-tcp-client which tells you how to send a HTTP request over a socket to a server and read its reply back. You can also refer to this unclear question on SO.
(You can google python socket http to get more examples.)
(Tip: I am not a Java fan, but still, if you don't find enough convincing examples on this topic under python, try finding it under Java, and then accordingly translate it to python.)
urllib.urlretrieve('http://google.com/abc.jpg', 'abc.jpg')

Resources