Incomplete JSON data when saving to database in google cloud functions - javascript

I am now trying out how to use the Google cloud functions as part of my IOT application.
But I am having issues when I send a JSON POST to the trigger endpoint. There are times that it works perfectly and sometimes the payload hex is cut in the middle.
For example the original payloadhex would be "0011029e02ffb1ffd6ffd8ffdaffe0fff500000008" and sometimes get suddenly cut to "0011029e02ffb1" when it is being saved to the database.
How I test the endpoint would be that I would send an HTTP POST using Postman with data below.
{
"DevEUI_uplink": {
"DevEUI": "BC9740FFFE10549E",
"payload_hex": "0011029e02ffb1ffd6ffd8ffdaffe0fff500000008",
}}
And inside the cloud function would be the nodejs12 code:
/**
* Responds to any HTTP request.
*
* #param {!express:Request} req HTTP request context.
* #param {!express:Response} res HTTP response context.
*/
const moment = require("moment");
const mysql = require("mysql");
require("dotenv").config();
exports.saveFunction = (req, res) => {
let now = moment().format('YYYY-MM-DD HH:mm:ss');
let deveui = req.body.DevEUI_uplink.DevEUI;
let payload = req.body.DevEUI_uplink.payload_hex;
function convertTempData(data) {
data = parseInt(data, 16);
if ((data & 0x8000) > 0) {
data = data - 0x10000;
}
return data;
}
// Slice the Request Data
let raw_payload = payload;
let version = parseInt(payload.slice(0, 2), 16);
let gem1 = parseInt(payload.slice(2, 4), 16);
let gem2 = parseInt(payload.slice(4, 6), 16);
let battery = parseInt(payload.slice(6, 8), 16) / 2;
let payload_id = parseInt(payload.slice(8, 10), 16);
let tempNow = convertTempData(payload.slice(10, 14));
let tempVar1 = convertTempData(payload.slice(14, 18));
let tempVar2 = convertTempData(payload.slice(18, 22));
let tempVar3 = convertTempData(payload.slice(22, 26));
let tempVar4 = convertTempData(payload.slice(26, 30));
let tempVar5 = convertTempData(payload.slice(30, 34));
let tempVar6 = convertTempData(payload.slice(34, 38));
let tempVar7 = convertTempData(payload.slice(38, 42));
// Connection String
const conn = mysql.createConnection({
host: process.env.SERVER_HOST,
user: process.env.SERVER_USER,
password: process.env.SERVER_PASS,
database: process.env.SERVER_DB,
port: process.env.SERVER_PORT,
});
conn.connect(function (err) {
if (err) {
return res
.status(404)
.json({ message: "Invalid Request", error: err.message });
}
var sqlcoms =
"UPDATE sd_payload SET payload = '" +
raw_payload +
"' , version='" +
version +
"', gem1='" +
gem1 +
"' , gem2='" +
gem2 +
"' , battery='" +
battery +
"',payload_id='" +
payload_id +
"',tempNow='" +
tempNow +
"',tempVar1='" +
tempVar1 +
"',tempVar2='" +
tempVar2 +
"',tempVar3='" +
tempVar3 +
"',tempVar4='" +
tempVar4 +
"',tempVar5='" +
tempVar5 +
"',tempVar6='" +
tempVar6 +
"',tempVar7='" +
tempVar7 +
"',updated_at='" +
now +
"' WHERE DevEUI = '" +
deveui +
"'";
conn.query(sqlcoms, function (err, result) {
if (err) {
return res
.status(404)
.json({ message: "Invalid Request", error: err.message });
}
return res.status(201).json(result);
});
});
};
I wanted to save the entire payload to the database for checking purposes. Would you be able to advise why the post json body is being cut midway in some inserts and some inserts would be complete?

I would suggest to first console.log(payload) so to verify if it's received in full by the function, or it gets chopped somewhere on the way.

Related

I am getting an error in rendering some of the things from cricket api

const express = require("express");
const bodyParser = require("body-parser");
const https = require("https");
const app = express();
app.get("/", function (request, response) {
//it is the endpoint of the api
const url =
"https://api.cricapi.com/v1/currentMatches?apikey=acdcba6a-5e79-4d7d-8efc-650c785096e2&offset=0";
https.get(url, function (res) {
console.log(res);
console.log(res.statusCode);
response.write("<h1><center>Cricket Score</center></h1><hr>");
response.write;
res.on("data", function (data) {
const cricket = JSON.parse(data);
for (var i = 0; i < cricket.data.length; i++) {
//it is stringify the r component of data.score[0].r
const cricketscore0 = JSON.stringify(cricket.data[i].score[0].r);
const cricketscore1 = JSON.stringify(cricket.data[i].score[1].r);
const cricketwickets0 = JSON.stringify(cricket.data[i].score[0].w);
const cricketwickets1 = JSON.stringify(cricket.data[i].score[1].w);
const cricketover0 = JSON.stringify(cricket.data[i].score[0].o);
const cricketover1 = JSON.stringify(cricket.data[i].score[1].o);
response.write("<h2>\n" + cricket.data[i].name + "</h2>");
response.write("<h3>\nMatch type :- " + cricket.data[0].matchType);
response.write(
"<h3>\n" +
cricket.data[i].score[0].inning +
" :-" +
cricketscore0 +
"/" +
cricketwickets0 +
"(" +
cricketover0 +
")</h3>"
);
response.write(
"<h3>\n" +
cricket.data[i].score[1].inning +
" :-" +
cricketscore1 +
"/" +
cricketwickets1 +
"(" +
cricketover1 +
")</h3>"
);
response.write("<h3><em>" + cricket.data[i].status + "</em></h3>");
}
response.send();
console.log();
});
});
});
app.listen(3000, function (req, res) {
console.log("The server is running on the port 3000");
});
I am getting into rendering the components of the data.score[1]. It is giving an error that they are undefined so I want you to please help me out in the above problem. I am unable to render it using for loop but I can get it if specify the value of I individually. when I am using for loop it is saying that components of data.score[1] does not exit. please help me out in this case. Please specify the answer and if possible please tell the problem with a solution code so that I can understand my problem and know what I am doing and avoid it in the future
This question will resolve the problems related to the rendering of things through APIs also. Please help me out with this problem.
I have made use of axios for this. You may use https. some of the objects are undefined for score index 1 that is why you are getting that error.
I have made use of axios for this. You may use https. some of the objects are undefined for score index 1 that is why you are getting that error.
const express = require('express');
const axios = require("axios");
const app = express();
const port = 3000;
app.use(express.json())
app.use(express.urlencoded())
const url = "https://api.cricapi.com/v1/currentMatches?apikey=acdcba6a-5e79-4d7d-8efc-650c785096e2&offset=0";
// middleware
app.use((req, res, next) => {
next()
});
const getCricketScors = async () => {
const resData = await axios.get(url)
// console.log(resData.data)
const { data } = resData
// console.log(data)
return data
}
app.get('/', async (req, res, next) => {
try {
const { data } = await getCricketScors()
// res.status(200).json(data)
if (!data) {
res.write("<h1><center>Cricket Score</center></h1><hr>");
res.write("<h4><center>Somthing went wrong</center></h4>");
res.send();
return
}
res.write("<h1><center>Cricket Score</center></h1><hr>");
res.write;
for (var i = 0; i < data.length; i++) {
const score0 = JSON.stringify(data[i].score[0])
const cricketscore0 = score0.r;
const cricketwickets0 = score0.w;
const cricketover0 = score0.o;
if (data[i].score.length > 1) {
const score1 = JSON.stringify(data[i].score[1])
const cricketscore1 = score1.r;
const cricketwickets1 = score1.w;
const cricketover1 = score1.o;
} else {
const cricketscore1 = '-'
const cricketwickets1 = '-'
const cricketover1 = '-'
}
res.write("<h2>\n" + data[i].name + "</h2>");
res.write("<h3>\nMatch type :- " + data[0].matchType);
res.write(
"<h3>\n" +
score0.inning +
" :-" +
cricketscore0 +
"/" +
cricketwickets0 +
"(" +
cricketover0 +
")</h3>"
);
if (score1) {
res.write(
"<h3>\n" +
score1?.inning +
" :-" +
cricketscore1 +
"/" +
cricketwickets1 +
"(" +
cricketover1 +
")</h3>"
);
}
res.write("<h3><em>" + data[i].status + "</em></h3>");
}
res.send();
} catch (error) {
console.log({ error })
res.status(500).json(error.message)
}
});
app.listen(port, '0.0.0.0', () => {
console.log(`Example app listening on port ${port}`);
});

Check if UUID is included in pastebin

I would like for to check if my UUID is includedin my pastebin.
Any idea how I can check that in JavaScript?
The code to actually get the UUID is this:
// GET UUID
const execSync = require("child_process").execSync;
const { type } = require("os");
const { SSL_OP_EPHEMERAL_RSA } = require("constants");
let response = execSync("wmic csproduct get uuid");
let serial = String(response).split("\n")[1];
console.log(serial);
async function fetchText() {
let response = await fetch("https://pastebin.com/raw/4hxgLxyd");
let data = await response.text();
console.log(data.indexOf(serial));
if (data.indexOf(serial) !== -1) {
console.log("included");
} else {
console.log("not included");
}
}
fetchText();
I am new to JS - in Python I know how to check it with a request command.
Anyone knows how to handle this in JS maybe?
As requested my Python code:
def init(): # check HWID
try:
HWID = subprocess.check_output('wmic csproduct get uuid').decode().split('\n')[1].strip()
except:
cmd = "system_profiler SPHardwareDataType | grep 'Serial Number' | awk '{print $4}'"
result = subprocess.run(cmd, stdout=subprocess.PIPE, shell=True, check=True)
HWID = result.stdout.decode().strip()
print('Checking license...')
# -------------------------------------------
# Below this - I need the code for JavaScript
# -------------------------------------------
r = requests.get('https://pastebin.com/xxx')
try:
if HWID in r.text:
pass
else:
print('[ERROR] HWID not registered!')
print(f'HWID: {HWID}')
time.sleep(5)
sys.exit(0)
except:
print('[ERROR] Failed to initiate')
time.sleep(5)
sys.exit(0)
print(f'HWID: {HWID}')
print('--- License is valid ---')
In javascript, you can use indexOf to search for the occurrence of a string. The function will return -1 if it does not exist, otherwise the index the first occurrence.
Additionally, make sure you account for things like case sensitivity and placement of dashes and whitespace.
var str = "Hello world, welcome to the universe.";
var n = str.indexOf("welcome");
See the Node.Js documentation for performing the http request.
// GET UUID
const execSync = require("child_process").execSync;
const response = execSync("wmic csproduct get uuid");
const serial = String(response).split("\n")[1].replace("-", "").trim().toLowerCase();
const https = require('https')
const options = {
hostname: 'pastebin.com',
port: 443,
path: '/xxx',
method: 'GET'
}
const req = https.request(options, res => {
console.log(`statusCode: ${res.statusCode}`)
res.on('data', d => {
var dnorm= d.replace("-", "").trim().toLowerCase();
process.stdout.write(dnorm.indexOf(serial))
})
})
req.on('error', error => {
console.error(error)
})
req.end()
Since it appears you are having a whitespace or encoding issue, please manually compare the contents of the string:
function debugComp(a, b)
{
a= a.toString().trim();
b= a.toString().trim();
console.log("a: '" + a + "' - Length: " + a.length);
console.log("b: '" + b + "' - Length: " + b.length);
if(a.indexOf(b)>-1)
{
console.log("Found at index " + a.indexOf(b));
}
else if(a.length==b.length)
{
for(var i=0; i< a.length; i++)
{
console.log("a[" + i + "]= '" + a[i] + "' - b[" + i + "] = '" + b[i]);
console.log("a[" + i + "] == b[" + i+ "] = " + (a[i]==b[i]));
}
}
else {
console.log("Strings have different lengths");
}
}
debugComp("D340D9AE-A43F-DF47-AFED-A93222AB3646", "D340D9AE-A43F-DF47-AFED-A93222AB3646");

Node js Verify Crypto Message

I send a request from the client to the server and the server responses back to both the client and the controller with a token. Then, the client receives the token back and sign the token with some extra information (Client IP, time and own blockchain address). After, the client sends the signed information with its own public key. All is good until here.
Now, the controller receives the message with signed information and the public key. Tries to verify this signed information with the coming public key and the message which already has.
Here is Client part code:
var message = token + "," + client.address().address + "," + time + "," + my_public;
var message_buf = Buffer.from(message);
const sign = crypto.createSign('SHA256');
sign.write(message_buf);
sign.end();
const signature = sign.sign(my_private, 'hex');
var sign_pub = signature.toString() + "," + my_public.toString();
var sign_pub_buf = Buffer.from(sign_pub);
console.log("sign_pub = ", sign_pub_buf);
client.send(sign_pub_buf, sdn_port, host, function(error){
if(error){
client.close();
}
else{
console.log('Sign+Public_K has been sent to SDN !!!');
}
Here is Controller part code:
udpsocket_sdn.on('message', function(msg, rinfo) {
console.log('Data received from CLIENT : ' ,msg);
var sig_pub = msg.toString().split(",");
var sig = sig_pub[0];
var pub = sig_pub[1];
console.log("sig = ", sig);
console.log("pub = ", pub);
var message = token + "," + rinfo.address + "," + time + "," + pub;
var message_buf = Buffer.from(message);
const verify = crypto.createVerify('SHA256');
verify.write(message_buf);
verify.end();
var isGood = verify.verify(pub, sig, 'hex');
if(isGood){
console.log('All Good');
}
else {
console.log('Nope !');
}
}
Ok, I fixed it. It is working now.
Here is the Client part code:
const { privateKey, publicKey } = crypto.generateKeyPairSync('rsa', {
modulusLength: 2048,
});
var my_public = publicKey.export({type: 'spki', format: 'pem'});
var my_private = privateKey;
var time = 100;
client.on('message',function(msg, info){
if(data_cnt == 1){
console.log('Random number received from SERVER !');
data_cnt++;
var token_tot = msg.toString().split(",")
usr1_pub_pem = token_tot[0];
token = token_tot[1];
var message = token + "," + ip + "," + time + "," + Buffer.from(my_public);
console.log("Client address = ", ip)
const sign = crypto.createSign('SHA256');
sign.write(message);
sign.end();
const signature = sign.sign(my_private, 'hex');
client.send(signature, sdn_port, host, function(error){
if(error){
client.close();
}
else{
console.log('Signature has been sent to SDN !!!');
client.send(my_public, sdn_port, host, function(error){
if(error){
client.close();
}
else{
console.log('Public Key has been sent to SDN !!!');
}
});
}
});
}
});
Now, the Controller part :
var time = 100;
udpsocket_sdn.on('message', function(msg, rinfo) {
count_sdn = count_sdn + 1;
if(count_sdn == 1){
console.log('Signature data received from CLIENT !!');
sig_pub = msg.toString();
}
else if (count_sdn == 2){
console.log('Public key data received from CLIENT !! ');
pub = msg;
var message = token + "," + rinfo.address + "," + time + "," + pub;
console.log("Client address = ", rinfo.address)
const verify = crypto.createVerify('SHA256');
verify.write(message);
verify.end();
var isGood = verify.verify(pub, sig_pub, 'hex');
if(isGood){
console.log('All Good');
}
else {
console.log('Nope !');
}
}
});

Running parallel execution of fuctions using Promise all

I have a requirement to execute several parallel functions
First functions:
Database get operation ie find inventory details from database
Second functions:
Process db results and save the result as a file
I am using two promise all, back to back to execute the above functions, I don't feel like this is the correct way to do this. Is there a
better way of handling these function calls. I am getting the result as per below code but want to know any other way.
Doing it following way:
let allQuery = {
sql: "SELECT * from inventory",
};
let inventoryQuery = {
sql: "SELECT * from inventory where inventory='1'",
};
let nearbyQuery = {
sql: "SELECT * from inventory where inventory='2",
};
let firstPromises = [dbService.fetch(allQuery),
dbService.fetch(inventoryQuery),
dbService.fetch(nearbyQuery)
];
Promise.all(firstPromises)
.then((values) => {
let all = values[0];
let inventory = values[1];
let nearby = values[2];
let fileKey1 = folderName + '/' + all.QueryExecutionId + '.csv';
let fileName1 = all.QueryExecutionId + '.csv';
let fileKey2 = folderName + '/' + inventory.QueryExecutionId + '.csv';
let fileName2 = inventory.QueryExecutionId + '.csv';
let fileKey3 = folderName + '/' + nearby.QueryExecutionId + '.csv';
let fileName3 = nearby.QueryExecutionId + '.csv';
let secondPromises = [s3Service.s3StreamDownload(bucketName, fileKey1, fileName1),
s3Service.s3StreamDownload(bucketName, fileKey2, fileName2),
s3Service.s3StreamDownload(bucketName, fileKey3, fileName3)
];
Promise.all(secondPromises)
.then((values) => {
console.log('Do later operation');
}).catch((error) => {
debug(`Error in promises ${error}`);
});
}).catch((error) => {
debug(`Error in promises ${error}`);
});
I think it can be more readable to extract the inner function and then chain them together:
Promise.all(firstPromises)
.then(transformToSecondPromises)
.then(Promise.all)
.then(values => {/* do later operation */})
.catch(error => { debug(`Error in promises ${error}`) })
function transformToSecondPromises ([all, inventory, nearby]) {
const fileKey1 = folderName + '/' + all.QueryExecutionId + '.csv';
const fileName1 = all.QueryExecutionId + '.csv';
const fileKey2 = folderName + '/' + inventory.QueryExecutionId + '.csv';
const fileName2 = inventory.QueryExecutionId + '.csv';
const fileKey3 = folderName + '/' + nearby.QueryExecutionId + '.csv';
const fileName3 = nearby.QueryExecutionId + '.csv';
return [
s3Service.s3StreamDownload(bucketName, fileKey1, fileName1),
s3Service.s3StreamDownload(bucketName, fileKey2, fileName2),
s3Service.s3StreamDownload(bucketName, fileKey3, fileName3)
];
}

Array empty after pushes were made in get request in Node.js/Express

I am writing a function calling an API to fetch URLs. These are the steps that I wish to accomplish:
Parsing in an array of objects (restaurants) as arguments
For each object, call the Google Search API to get some imageURLs
Store those imageURLs in an array
Add imageURLs as an attribute called imageURLs to each object within the array in the argument
The code is able to log the imageURLs within the GET request, but outside of the request, imageURLs is just an empty array.
var googleSearch = function(restaurants, cb){
console.log("google starts");
const apiKey = google_apiKey;
const cseKey = cseID;
Array.from(restaurants).forEach(function(restaurant){
var keyWord = restaurant.name + " "+ restaurant.location.city
+ " "+ restaurant.location.state + " food";
var googleURL = "https://www.googleapis.com/customsearch/v1?key="+ apiKey +
"&q="+ keyWord +
"&searchType=image" +
"&cx=" + cseKey +
"&num=7" +
"&safe=medium"
;
//image URLs of each restaurants to be displayed in the front end
var imageURLs = [];
request
.get(googleURL,
{
json : true, headers: {
'User-Agent' : 'thaorell'
}
})
.then(function(response){
Array.from(response.items).forEach(function(item){
imageURLs.push(item.link)
});
})
.catch(e => {
console.log(e);
})
restaurant.imageURLs = imageURLs
})
cb(null, restaurants);
}
You're misunderstanding the Promise API:
var googleSearch = function (restaurants, cb) {
console.log("google starts");
const apiKey = google_apiKey;
const cseKey = cseID;
return Promise.all(Array.from(restaurants).map(function (restaurant) {
var keyWord = restaurant.name + " " + restaurant.location.city
+ " " + restaurant.location.state + " food";
var googleURL = "https://www.googleapis.com/customsearch/v1?key=" + apiKey +
"&q=" + keyWord +
"&searchType=image" +
"&cx=" + cseKey +
"&num=7" +
"&safe=medium"
;
return request
.get(googleURL,
{
json: true, headers: {
'User-Agent': 'thaorell'
}
}
)
.then(function (response) {
restaurant.imageURLs = Array.from(response.items).map(function (item) {
return item.link;
});
return restaurant;
})
})
)
.then(restaurants2 => cb(null, restaurants2))
.catch(cb)
}
As you can see you need to wait for all of the requests to finish before you pass the data back to the callback.

Categories