INVALID_ARGUMENT error by Google speech API - json

I want to use Google Speech API's asynchronous transcription service. I've uploaded my audio file on Google buckets and I'm trying to use it with the following code (I've removed my key and my filename from the command, everything else is copied).
curl -H "Content-Type: application/json"
--data '{"audio":{"uri":"https://storage.cloud.google.com/<mybucketname>/<filename>"},
"config":{"encoding":"FLAC","sample_rate_hertz":"16000","language_code":"en_US"}}'
https://speech.googleapis.com/v1/speech:longrunningrecognize?key=<mykey>
I get a 400 INVALID_ARGUMENT error telling me "Request contains an invalid argument". What am I doing wrong in my curl request?

Apparently the problem was in my URI. Google has a special way for referencing items in Google buckets, with "gs:" as the prefix.
curl -H "Content-Type: application/json"
--data '{"audio":{"uri":"gs://<mybucketname>/<filename>"},
"config":{"encoding":"FLAC","sample_rate_hertz":"16000","language_code":"en_US"}}'
https://speech.googleapis.com/v1/speech:longrunningrecognize?key=<mykey>
Note that I got a permission error that I could not overcome after I switched to this approach, but I don't think this is related to the way I'm making my curl request anymore.

Should there be a double quotation mark after <filename> ?

Check the sample_rate_Hertz. You may find that is the format for SYNCHRONOUS requests.
ASYNCHRONOUS is sampleRateHertz.
I have just got it to work so revert if you need to while my memory is still fresh!

I was using the Node JS Client and google storage to store the file.
// The audio file's encoding, sample rate in Hertz, and BCP-47 language code
const audio = {
uri: 'gs://sst_bbc/',
};
const config = {
enableWordTimeOffsets: true,
encoding: 'FLAC',
// sampleRateHertz: 16000,
languageCode: 'en-US',
};
const request = {
audio: audio,
config: config,
};
// Detects speech in the audio file
const [operation] = await client.longRunningRecognize(request);
const [response] = await operation.promise();
fs.writeFileSync('ted_talk.json', JSON.stringify(response), 'utf8');
I made a mistake by not referring to the exact object. The error in the console is very ambiguous. After I set the correct path it started to work properly.
const audio = {
uri: 'gs://sst_bbc/ted_talk.flac',
};
if the file location is correct then double check the encoding type.I

Related

How to get an Authorization Code from UIPath

I am trying to start a robot in my UIpath-orchestrator via Google Appscript.
I have already implemented everything into my script from this documentation:
https://dev.joget.org/community/display/KBv6/Integration+with+UiPath+Robotic+Process+Automation#IntegrationwithUiPathRoboticProcessAutomation-1.GetAccessandIDTokens
But I am actually facing a problem:
Like described in 1.2 of the documentation, I need the authorization code for generating a refresh token. Since I want to write a script to obtain this automatically, the described way with pasting the URL into the browser manually with the code challenge (which btw works fine in my case) is not the way to go for me, as you probably can imagine.
Does anybody have an idea how to achieve this? I would also be fine, if you have a working Postman- or curl-approach - it wouldn’t be a problem to transform this then by myself.
Thank you in advance.
This will be deprecated anyway... :(
Actually what I have to try now is to set up an external application, which I did. I also created an access token like this:
function getAccessToken() {
var data = {
'grant_type': 'client_credentials',
'client_id': '****',
'client_secret': '*****',
'scope': 'OR.Machines'
};
var header = {
'method': 'post',
'payload': data,
};
var response = UrlFetchApp.fetch("https://cloud.uipath.com/identity_/connect/token", header);
Logger.log(response);
var messageContent = response.getContentText();
var result = JSON.parse(messageContent);
var access_token = result['access_token'];
return access_token;
}
Now what I try to do now is to get a process Release Key with whom I can start the job then...
For testing reasons, I tried it with curl:
curl -H "accept: application/json" -H "Content-type: application/json" -H "X-UIPATH-TenantName: [tenantName]" -H "X-UIPATH-OrganizationUnitId: default" --insecure -v https://cloud.uipath.com/[organization]/[TenantName]/odata/Releases?$filter=ProcessKey" -H "Authorization: Bearer [accesstoken]"
Actually what I see in the return is a 400 Bad request...
What have I done wrong?

Google Cloud HTTP function - Why is the function so picky for cURL json format

I could use some help understanding why my Google Cloud Function is so picky about the format that I pass in JSON.
I was following this guide from Google Cloud. The very first example on the page has you create a function exactly like this:
exports.helloHttp = (req, res) => {
res.send(`Hello ${escapeHtml(req.query.name || req.body.name || 'World')}!`);
};
Then they ask you to trigger it via curl:
curl -X POST HTTP_TRIGGER_ENDPOINT -H "Content-Type:application/json" -d '{"name":"Jane"}'
To my surprise I could not get it to work, I have spent a lot of time playing around with params and options until this worked for me:
curl -X POST HTTP_TRIGGER_ENDPOINT -H "Content-Type:application/json" -d {\"name\":\"Jane\"}
I am using a Windows 10 machine and on a terminal that has node(10) installed(In case that matters).
1. What makes me need to remove the single quotes and add the backslashes, does this format have a name or keywords?
2. Can the answer to question 1 be used in a vanilla javascript XMLHttpRequest? As I have not been able to apply my curl modifications successfully.
var xhr = new XMLHttpRequest();
xhr.open("POST", "myFunctionURL");
xhr.setRequestHeader('Content-Type', 'application/json');
xhr.send(`{\"name\":\"Jane"}`);
xhr.onreadystatechange = function () {
if (xhr.readyState === 4) {
console.log('response: ', JSON.stringify(xhr), ' status: ', xhr.status);
}
}
I have tried passing numerous params into the send including:
var body = {};
body.name = 'Jane';
*passing body into xhr.send*
var body = `{\"name\",\"Jane\"};
*passing body into xhr.send*
It's not Google Cloud Function, it's the Windows Version of CURL command which has an issue with single quotes when posting JSON payload.
Take a look at the following threads which seem to discuss the same issues but in a different context:
https://superuser.com/questions/1016710/how-to-make-a-curl-post-call-in-windows
https://superuser.com/questions/1291352/curl-command-runs-in-linux-but-not-windows-2008

How do I make a secure API request from an Arduino ESP32, programmed in the Arduino IDE using ArduinoJson?

I have been hacking away at this for a few days with no luck.
I am trying to make a secure (SSL/HTTPS) API request in an Arduino environment. The controller I am using is an ESP32, which connects through wifi fine, and can retrieve/post data. However I am having no luck connecting to a secure API.
I'm trying to connect to this API https://strike.acinq.co/documentation/api-reference
EXAMPLE CURL REQUEST IN API'S DOCUMENTATION:
$ curl https://api.dev.strike.acinq.co/api/v1/charges \
-u sk_pJDwxFxCVw5fQJhRRMpf29jReUjjN: \
-X POST \
-d amount=42000 \
-d currency="btc" \
-d description="1%20Blockaccino"
Here is my Arduino code, I am using the ArduinoJson.h and WiFi.h libraries:
// Connect to HTTP server
WiFiClient client;
client.setTimeout(10000);
if (!client.connect("api.strike.acinq.co", 80)) {
Serial.println(F("Connection failed"));
return;
}
Serial.println(F("Connected!"));
// Send HTTP request
client.println(F("GET /api/v1/charges?id=MYKEY&amount=4200&currency=btc HTTP/1.0"));
client.println(F("Host: api.strike.acinq.co"));
client.println(F("Content-Type: application/x-www-form-urlencoded"));
client.println(F("Connection: close"));
if (client.println() == 0) {
Serial.println(F("Failed to send request"));
return;
}
// Check HTTP status
char status[32] = {0};
client.readBytesUntil('\r', status, sizeof(status));
if (strcmp(status, "HTTP/1.1 200 OK") != 0) {
Serial.print(F("Unexpected response: "));
Serial.println(status);
return;
}
A 401 "Invalid API Key" Is the closest I have got. I know the API-key works, and that I am just using it wrong. I've tried moving the key to:
client.println(F("id: MYKEY"));
but that didn't work either.
I have tried other libraries and ArduinoJson seems to be the best. I think the issue is the fact its a secure server and the layout of my request. I found many resources for connecting to open API's on Arduino, but nothing on connecting to secure ones. I think I am almost there with the code...
UPDATE
So I have updated my code. I am still trying to use ArduinoJson. I can connect to the API but it keeps spitting out "HTTP/1.1 400 BAD_REQUEST". I don't know weather this is because its over HTTPS or the formatting of my request.
In the API docs -u and -X don't have a field name like "amount=4200", so I am assuming -u would just be added client.print("?="+apiKey);
//open weather map api key
String apiKey= "myapikey";
int status = WL_IDLE_STATUS;
char server[] = "api.strike.acinq.co";
Serial.println("\nStarting connection to server...");
// if you get a connection, report back via serial:
if (client.connect(server, 80)) {
Serial.println("connected to server");
// Make a HTTP request:
client.print("POST /api/v1/charges");
client.print("?="+apiKey);
client.print("&amount=4200");
client.print("&currency='btc'");
client.println("&description='sweets'");
client.println("Host: api.strike.acinq.co");
client.println("Connection: close");
client.println();
}
else {
Serial.println("unable to connect");
}
UPDATE
I figured out the println and print actually mean something and have subsequently organised my request much better. It still comes back with 400 Unauthorized?
String PostData = "&description=\"car\"&amount=1000&currency=\"sweetsandthat\"";
client.println("POST /api/v1/charges HTTP/1.1");
client.println("Host: api.strike.acinq.co");
client.println("Authorization: Basic "+apiKey);
client.print("Content-Length: ");
client.println(PostData.length());
client.println(); // blank line required
client.println(PostData);
Serial.println("POSTED DATA: " + PostData);
// client.stop();
client.println();
} else {
Serial.println("unable to connect");
}
delay(1000);
String line = "";
while (client.connected()) {
line = client.readStringUntil('999');
Serial.println(line);
Serial.println("parsingValues");
//create a json buffer where to store the json data
StaticJsonBuffer<5000> jsonBuffer;
JsonObject& root = jsonBuffer.parseObject(line);
if (!root.success()) {
Serial.println("parseObject() failed");
return;
}
//get the data from the json tree
String nextWeatherTime0 = root["id"][0];
// Print values.
Serial.println(nextWeatherTime0);
}
client.println("Connection: close");
client.stop();
}
Check the response for a BAD request, We usually get it when we deal with a bad URL or URL not found. check whether you are connecting to the same url mentioned in docs.
First connect to the api and after that make queries like providing your api key and feilds
remove this.
client.println("Host: api.strike.acinq.co");
and use GET request to get the response of the data you have in these fields
String PostData = "&description=\"car\"&amount=1000&currency=\"sweetsandthat\""
I have also been struggling to get an https post to work on the esp32. A few things, the wifi.h module, I believe, does not support https. The WiFiClientSecure.h does, and you need to set the port to 443. I have also failed to get a POST to work, but I succeed in a basic GET test connection to howsmysssl.com. Andreas Spiess covers this well in a youtube video. He goes beyond SSL to establishing trust. I just want basic SSL to work, so if you get this figured out, please let me know. Hopefully I got you one step closer. :)

Node-red - Posting data to influxdb via http

Im trying to post data to an Influxdb via Node-red.
Via CURL i can post this:
curl -i -XPOST 'http://localhost:8086/write?db=waterlevel' --data-binary 'vattenstand,lake=siljan,region=dalarna value=160.80'
and it puts data to InfluxDb.
When I try to post via Node-red and an HTTP request I get the error:
{"error":"unable to parse '{\"url\":\"http://192.168.1.116:8086/write?db=waterlevel\",\"method\":\"POST\",\"body\":\"vattenstand,lake=siljan,region=dalarna value=160.80\",}': missing tag value"}
I use this code in a function in Node-red and pass it to the HTTP request:
var dataString = 'vattenstand,lake=siljan,region=dalarna value=160.80';
msg.payload = {
'url': 'http://192.168.1.116:8086/write?db=waterlevel',
'method': 'POST',
'body': dataString,
};
msg.headers = {
Accept: "application/json"
};
return msg;
The sidebar help for the node details the msg properties you should be setting to configure the node.
You are passing in URL, method and body as properties of msg.payload. That is not correct.
They should be set as msg.url, msg.method for the first two, and msg.payload should be the body of the request.
In this instance, you have already configured the node with a URL and method directly, so there's no need to pass them in with the message. In fact, as you have configured the URL in the node you will find you cannot override it with msg.url. if you want to set the URL with each message, you must leave the node's URL field blank in the editor.
You may also need to set the content-type header.
Assuming you are happy to leave the URL and method hard coded in the node, you function should be something like:
msg.payload = 'vattenstand,lake=siljan,region=dalarna value=160.80';
msg.headers = {
Accept: "application/json"
};
msg.headers['Content-type'] = 'application/x-www-form-urlencoded';
return msg;
Why don't you use the spezial influxdb node?
https://flows.nodered.org/node/node-red-contrib-influxdb
Advantage: The http header need not be created. You can reuse the defined connection for other data.

How to use update function to upload attachment in CouchDB

I would like to know what can I do to upload attachments in CouchDB using the update function.
here you will find an example of my update function to add documents:
function(doc, req){
if (!doc) {
if (!req.form._id) {
req.form._id = req.uuid;
}
req.form['|edited_by'] = req.userCtx.name
req.form['|edited_on'] = new Date();
return [req.form, JSON.stringify(req.form)];
}
else {
return [null, "Use POST to add a document."]
}
}
example for remove documents:
function(doc, req){
if (doc) {
for (var i in req.form) {
doc[i] = req.form[i];
}
doc['|edited_by'] = req.userCtx.name
doc['|edited_on'] = new Date();
doc._deleted = true;
return [doc, JSON.stringify(doc)];
}
else {
return [null, "Document does not exist."]
}
}
thanks for your help,
It is possible to add attachments to a document using an update function by modifying the document's _attachments property. Here's an example of an update function which will add an attachment to an existing document:
function (doc, req) {
// skipping the create document case for simplicity
if (!doc) {
return [null, "update only"];
}
// ensure that the required form parameters are present
if (!req.form || !req.form.name || !req.form.data) {
return [null, "missing required post fields"];
}
// if there isn't an _attachments property on the doc already, create one
if (!doc._attachments) {
doc._attachments = {};
}
// create the attachment using the form data POSTed by the client
doc._attachments[req.form.name] = {
content_type: req.form.content_type || 'application/octet-stream',
data: req.form.data
};
return [doc, "saved attachment"];
}
For each attachment, you need a name, a content type, and body data encoded as base64. The example function above requires that the client sends an HTTP POST in application/x-www-form-urlencoded format with at least two parameters: name and data (a content_type parameter will be used if provided):
name=logo.png&content_type=image/png&data=iVBORw0KGgoA...
To test the update function:
Find a small image and base64 encode it:
$ base64 logo.png | sed 's/+/%2b/g' > post.txt
The sed script encodes + characters so they don't get converted to spaces.
Edit post.txt and add name=logo.png&content_type=image/png&data= to the top of the document.
Create a new document in CouchDB using Futon.
Use curl to call the update function with the post.txt file as the body, substituting in the ID of the document you just created.
curl -X POST -d #post.txt http://127.0.0.1:5984/mydb/_design/myddoc/_update/upload/193ecff8618678f96d83770cea002910
This was tested on CouchDB 1.6.1 running on OSX.
Update: #janl was kind enough to provide some details on why this answer can lead to performance and scaling issues. Uploading attachments via an upload handler has two main problems:
The upload handlers are written in JavaScript, so the CouchDB server may have to fork() a couchjs process to handle the upload. Even if a couchjs process is already running, the server has to stream the entire HTTP request to the external process over stdin. For large attachments, the transfer of the request can take significant time and system resources. For each concurrent request to an update function like this, CouchDB will have to fork a new couchjs process. Since the process runtime will be rather long because of what is explained next, you can easily run out of RAM, CPU or the ability to handle more concurrent requests.
After the _attachments property is populated by the upload handler and streamed back to the CouchDB server (!), the server must parse the response JSON, decode the base64-encoded attachment body, and write the binary body to disk. The standard method of adding an attachment to a document -- PUT /db/docid/attachmentname -- streams the binary request body directly to disk and does not require the two processing steps.
The function above will work, but there are non-trivial issues to consider before using it in a highly-scalable system.