how to make async call using request-promise in google home action - actions-on-google

I am trying to call a API in onSync() and return payload so that I will get number of devices. Even the api is returning me the proper data I am unable to show the devices. Following is the code snippet.
app.onSync((body) => {
// TODO: Implement SYNC response
console.log('************** inside sync **************');
var payload = {
agentUserId:'123',
devices:[]
};
//Calling Discove Devices API
requestAPI('------ calling API ------')
.then(function(data){
let result = JSON.parse(data);
console.log('********** RESULT ********** '+util.inspect(result,{depth:null}));
var count = 0;
count = Object.keys(result.Devices).length;
console.log('********** DEVICE COUNT ********** '+count);
//forming payload json of devices
for(var i in result.Devices){
var item = result.Devices[i];
payload.devices.push({
"id" : item.ieee_address,
"type" : 'action.devices.types.OUTLET',
"traits" : ['action.devices.traits.OnOff'],
name : {
"defaultNames" : [item.mapped_load],
"name" : item.mapped_load,
"nicknames" : [item.mapped_load],
},
"willReportState" : false,
"deviceInfo" : {
"manufacturer" : 'some manufacturer',
"model" : 'Smart-Plug',
"hwVersion" : '1.0',
"swVersion" : '1.0.1',
},
});
}
}).catch(function(err){
console.log(err);
});
console.log('PAYLOAD %J ',payload); <----- it is always empty
return {
requestId: body.requestId,
payload: payload,
};
});
API is returning me correct value but the payload is always empty.
Please help. I am new to node.js and I dont know how to make async call.

You're using an asynchronous call to get devices, and you'll need to make sure you don't return data before your request is complete. You return the Promise to the function, so it will wait:
app.onSync((body) => {
return requestApi('...')
.then(data => {
return {
requestId: body.requestId,
payload: payload
}
})
})

Related

Axios/mongodb request, PromiseState stuck on pending, then() part is not called

I'm trying to update my mongodb database in javascript by accessing some documents from the database, changing a specific document and then performing a patch request via axios.
When I get to the patch request I'm able to update the database however the promise is stuck on pending and thus, the then() part of the code is not run.
This is the main structure of the code:
In the first part the documents are requested from the database via axios.get:
function updateDocument(someinputdata){
g = axios.all([axios.get('/getData1),axios.get('/getData2)])
.then(response => {
Data1 = response[0].data;
Data2 = response[1].data;
adjustData(Data1,Data2);
});
}
In the second part a specific document is changed and a patch request is called:
function adjustData(Data1,Data2){
...getting specific document and change value from specific field...
var newRec = {
title: "dummyTitle",
rate: newRateValue
};
promise = axios({
url: '/patch/The Real Title',
method: 'PATCH',
data: newRec,
headers: { "Content-Type": "application/json" }
})
.then(() => {
console.log('I want this text to display but it doesn't')
});
}
If I console.log(promise):
Promise {<pending>}
__proto__: Promise
[[PromiseState]]: "pending"
[[PromiseResult]]: undefined
On the server side I have this:
router.patch('/patch/:title', (req,res) => {
const updatedPost = Model.updateOne(
{ "title": req.params.title},
{ $set: { "rate" : req.body.rate}},
(err, result) => {
if(err) {
console.log(err);
throw err;
}
})
.then(
console.log('This text is displayed');
)
})
I want to use the first then() part to update some HTML
Why is the patch request stuck on pending (so not fulfilled or rejected)?
I've figured out what my problem was.
I needed to add
res.json({msg: "Your data has been saved"});
to the code on the server side.

Why my filter is not working in v2.ODataModel "read"?

I am using the OData model to read data. But it doesn't work. Check the code below:
getGuid: function(pernr) {
var self = this;
var url = "/PersonalDetailSet?$filter=Pernr eq '00000001'";
self.setBusy(true);
this.oModel.read(url, {
success: function(res) {
// ...
},
error: function() {
// ...
}
});
}
I don't know why the filter in url is not working now?
Check if your OData service supports the $filter query in the first place.
Use the read method correctly:myV2ODataModel.read("/PersonalDetailSet"/* No $filter queries here! */, {
filters: [ // <-- Should be an array, not a Filter instance!
new Filter({ // required from "sap/ui/model/Filter"
path: "myField",
operator: FilterOperator.EQ, // required from "sap/ui/model/FilterOperator"
value1: "..."
})
],
// ...
});
API reference: sap.ui.model.odata.v2.ODataModel#read
API reference: sap.ui.model.Filter
First you check whether you are getting model in the scope or not. As i can see this.oModel which is not proper way of getting model. Better use this.getModel() or this.getView().getModel() and then check the call. Passing filter is not the right way but still it should work.
If you want to apply additional URL Parameters in the read function you have to do this via the "urlParameters" parameter:
getGuid: function(pernr){
var self = this;
var url = "/PersonalDetailSet";
self.setBusy(true);
this.oModel.read(url, {
urlParameters: {
"$filter" : "Pernr eq '00000001'"
},
success: function(res){
self.setBusy(false);
self.guid = res.results[0].Guid;
},
error: function() {
self.setBusy(false);
}
});
}

What am I doing wrong when manipulating data in Meteor/MongoDB?

I have this helper
myClub: function(){
var currentUserId = Meteor.userId();
var user = Meteor.users.findOne({_id: currentUserId});
return user;
}
I want it to return user.role
Here is my user in MongoDB
{
"_id" : "RdirmrLG3t8qBk4js",
"createdAt" : ISODate("2016-04-17T19:40:56.877Z"),
"services" : {
"password" : {
"bcrypt" : "$2a$10$cPe92XR9DT238bH/RanYEu.J6K2ImvAEbWOcVq6j9luI0BH08Qdly"
},
"resume" : {
"loginTokens" : [
{
"when" : ISODate("2016-04-17T19:51:49.474Z"),
"hashedToken" : "uVKUj/7JEkkOuizXhjl212Z38E47HXCex+D4zRikQ1k="
}
]
}
},
"username" : "worker",
"role" : "worker",
"club" : "hzSKAJfPXo7hSpTYS"
}
The code above works just fine. So it finds the current user and outputs info about it. But when I change user to user.role I get the following errormessage.
TypeError: Cannot read property 'role' of undefined
at Object.myClub
How can it be undefined? Is my syntax incorrect?
Template helpers are reactive, which means they update themselves as the app state changes or new data appears. In your case, the helper is called immediately when the template is rendered and before the Meteor.users collection is filled. Therefore, the .findOne() method returns undefined. It will be corrected in the second pass after new data arrives.
The simple fix here is to check whether the data is present inside the helper:
myClub: function(){
var currenUserId = Meteor.userId();
var user = Meteor.users.findOne({_id: currenUserId});
if(!user) return 'NO DATA';
return user.role;
},
In real life you'll probably want to wait for the basic data to be loaded before you render the template. That is usually done on the controller level.
Try:
myClub: function(){
return Meteor.user() && Meteor.user().role;
}
This is shorthand for return the role if there's a user.
As far as the role field not showing up, make sure that you are publishing that key from the server and subscribing to it. For example:
Meteor.publish('me',function(){
return Meteor.users.find(this.userId,{fields: {role: 1, username: 1, profile: 1, emails: 1}});
});
And on the client:
var me = Meteor.subscribe('me');
if ( me.ready() ) console.log("Ta-da! The role is: "+Meteor.user().role);
make sure that you subscribed to all data you need.
By the way, you can try following:
role: function(){ return (Meteor.user() || {}).role; }
Cheers

inlineCount not working for non-EF server

I am running following query
var query = breeze.EntityQuery
.from('employees').inlineCount(true).then(function(data) {
console.log(data.inlineCount); //undefined
});
This is the data returned by server (written in python, a non-EF server).
{ "inlineCount" : 100, "results" : <result_object> }
I am also using jsonResultsAdapter.
extractResults: function (data) {
var results = data.results;
if (!results) throw new Error("Unable to resolve 'results' property");
return results;
},
Any idea what I am doing wrong here? Will it not work with non-EF source?

How to pass model name to angularJS restful api

I am new to AngularJS, but have used Backbone for a while now.
I want to create a reusable restful api that I can pass the model name to so that I can use it for different models.
At the moment I have:
angular.module('healthplanApiServices', ['ngResource'])
.factory('Api', function($resource) {
return $resource(base_url + 'api/:object/:id', {
id : '#id', object : 'actions'
}, {
query : {
method : 'GET',
isArray : true,
callback : "JSON_CALLBACK"
},
save : {
method : '#id' ? 'PUT' : 'POST',
isArray : true,
callback : "JSON_CALLBACK"
}
});
});
... which sets the model as 'actions'. Then in my controller I use:
// get the collection
Api.query(function(r) {
$scope.actions = r;
});
$scope.toggleDone = function(a) {
a.done = !a.done;
//save an item
Api.save(a);
}
That's all fine, but how do I pass the model name ('actions' in this case) for each model type: e.g., instead of putting it in the factory function like so:
id : '#id', object : 'actions'
... but rather something more like:
var ActionApi = Api.setObject('actions');
ActionApi.query(function(r) {
$scope.actions = r;
});
UPDATE:
I just figured out a way. It may not be the best, but it does work. Any other suggestions would be welcome!
Just add the 'object' attribute to the model:
Api.query({object: 'actions'}, function(r) {
$scope.actions = r;
angular.forEach($scope.actions, function(a) {
a.object = 'actions' });
});
Api.save(a);// also works
You may want to try https://github.com/klederson/ModelCore ( ModelCore )
Its easy to model and structure and of course ... to use.
model.$find({ filter : "John" },{},true); //to find all with query parameters
model.$get(1); //to retreive the user with id 1
model.$save()
model.$deelte();
And so on.. checkout the documentation