Amazon Alexa Device Discovery for Smart Home API with Lambda Failing - aws-lambda

I have setup an Alexa Smart Home Skill, all settings done, oauth2 processed done and skill is enabled on my Amazon Echo device. Lambda function is setup and linked to the skill. When I "Discover Devices" I can see the payload hit my Lambda function in the log. I am literally returning via the context.succeed() method the following JSON with a test appliance. However Echo tells me that it fails to find any devices.
{
"header": {
"messageId": "42e0bf9c-18e2-424f-bb11-f8a12df1a79e",
"name": "DiscoverAppliancesResponse",
"namespace": "Alexa.ConnectedHome.Discovery",
"payloadVersion": "2"
},
"payload": {
"discoveredAppliances": [
{
"actions": [
"incrementPercentage",
"decrementPercentage",
"setPercentage",
"turnOn",
"turnOff"
],
"applianceId": "0d6884ab-030e-8ff4-ffffaa15c06e0453",
"friendlyDescription": "Study Light connected to Loxone Kit",
"friendlyName": "Study Light",
"isReachable": true,
"manufacturerName": "Loxone",
"modelName": "Spot"
}
]
}
}
Does the above payload look correct?

According to https://developer.amazon.com/public/solutions/alexa/alexa-skills-kit/docs/smart-home-skill-api-reference#discovery-messages the version attribute is required. Your response seems to be missing that attribute.
In my (very short) experience with this, even the smallest mistake in the response would generate a silent error like the one you are experiencing.

I had the same problem. If you are creating discovery for "Entertainment Device", make sure you have wrapped the output in 'event' key for context.succeed
var payload = {
endpoints:
[
{
"endpointId": "My-id",
"manufacturerName": "Manufacturer",
"friendlyName": "Living room TV",
"description": "65in LED TV from Demo AV Company",
"displayCategories": [ ],
"cookie": {
"data": "e.g. ip address",
},
"capabilities":
[
{
"interface": "Alexa.Speaker",
"version": "1.0",
"type": "AlexaInterface"
},
]
}
]
};
var header = request.directive.header;
header.name = "Discover.Response";
context.succeed({ event: {
header: header, payload: payload
} });
Although, in the sample code, this is never mentioned and an incorrect example is given (https://developer.amazon.com/public/solutions/alexa/alexa-skills-kit/docs/steps-to-create-a-smart-home-skill). However, the response body provided includes the "event" key.

Recreating lambda function helped me fix the issue. I also set "Enable trigger" check button while creating, though I'm not sure if that matters. After that my device provided by skill was found successfully.

Edit: Answer was wrong. Only useful information was this
This context.fail syntax is actually deprecated. Look up the Lambda context object properties, it should look more like "callback(null, resultObj)" now.

Did you include the return statement in your function?
return {
"header": header,
"payload": payload
}
It was missing in the example and after adding it, I was able to 'discover' my device.

Related

Teams is not displaying my unfurl response

I have a Teams integration with link unfurling set up. I have the messaging endpoint pointed to a public ngrok URL and ngrok proxying a local node.js server that returns the example payload Microsoft has in it's documentation.
This is my endpoint (express.js):
app.post('/bot-test', (req, res) => {
res.send({
"composeExtension": {
"type": "result",
"attachmentLayout": "list",
"attachments": [
{
"contentType": "application/vnd.microsoft.teams.card.o365connector",
"content": {
"sections": [
{
"activityTitle": "[85069]: Create a cool app",
"activityImage": "https://placekitten.com/200/200"
},
{
"title": "Details",
"facts": [
{
"name": "Assigned to:",
"value": "[Larry Brown](mailto:larryb#example.com)"
},
{
"name": "State:",
"value": "Active"
}
]
}
]
}
}
]
}
});
});
When I post a URL in a message in Teams, I see it POST to that endpoint and it responds without errors, but nothing shows up in Teams. What's going wrong? I can't find any logs on Microsoft's side either. I would expect that Teams renders a card with the response payload.
Office 365 Connector cards are not supported for link unfurls ("Message extension previews" in MS parlance). Changing the response to a supported card type worked. Unfortunately, MS doesn't surface this problem anywhere and it just silently discards the response. I was able to find a somewhat useful error description by inspecting the network request that went out from the Teams web client, however.
See this for supported card types: https://learn.microsoft.com/en-us/microsoftteams/platform/task-modules-and-cards/cards/cards-reference

Why I can't save my connector on Microsoft Teams?

I made a custom connector for teams that display notifications on channels and add Tab on teams.
For the tab parts -> Everything is working well
But I have a problem for the connector parts, I get an error when I try to save my settings in the developer console:
Received error from connectors {"seq":1585127802210,"timestamp":1585127814174,"flightSettings":{"Name":"ConnectorFrontEndSettings","AriaSDKT....
-> registerOnSaveHandler is called
-> setSettings is correctly set with entityId, contentUrl (same configurationUrl as the connector configuration) and the configName.
getSettings -> is called to save to my app the webhook url -> it works
-> notifySuccess is then called and
I checked on the connector dashboard everything seems fine, on the App Studio everything is green also!
I don't know what is happening..
My manifest
{
"$schema": "https://developer.microsoft.com/en-us/json-schemas/teams/v1.5/MicrosoftTeams.schema.json",
"manifestVersion": "1.5",
"version": "1.0.0",
"id": "ca153ede-92f2-46e7-8695-3726b5343bf4",
"packageName": "com.kagilum.icescrum",
"developer": {
"name": "Kagilum SAS",
"websiteUrl": "https://www.icescrum.com",
"privacyUrl": "https://www.icescrum.com/privacy",
"termsOfUseUrl": "https://www.icescrum.com/termsofuser"
},
"icons": {
"color": "color.png",
"outline": "outline.png"
},
"name": {
"short": "iceScrum",
"full": "Connect with iceScrum"
},
"description": {
"short": "A true Agile project management tool",
"full": "iceScrum is a web application for using Scrum while keeping the spirit of a collaborative workspace. It also offers virtual boards with post-its for sprint backlog, product backlog and others."
},
"accentColor": "#FFFFFF",
"configurableTabs": [
{
"configurationUrl": "https://preview.icescrum.com/msTeams/setupTab/",
"canUpdateConfiguration": true,
"scopes": [
"team",
"groupchat"
],
"supportedSharePointHosts": [
"sharePointFullPage",
"sharePointWebPart"
]
}
],
"connectors": [
{
"connectorId": "f00d8890-daa8-4c87-89f5-83cbab0bccd4",
"configurationUrl": "https://preview.icescrum.com/msTeams/setup/",
"scopes": [
"team"
]
}
],
"permissions": [
"identity",
"messageTeamMembers"
],
"validDomains": [
"preview.icescrum.com"
]
}
Piece of code related to
microsoftTeams.settings.registerOnSaveHandler(function(saveEvent) {
microsoftTeams.settings.setSettings({
entityId: 'icescrum-pkey-' + $scope.settings.project.pkey,
contentUrl: isSettings.serverUrl + '/msTeams/setup/',
configName: $scope.settings.project.name
});
microsoftTeams.settings.getSettings(function(settings) {
$scope.settings.webhookUrl = settings.webhookUrl;
return FormService.httpPost('msTeams/save', $scope.settings, true).then(function() {
saveEvent.notifySuccess(); //wait that the settings are really saved on iceScrum side
});
});
});
microsoftTeams.settings.getSettings(function(settings) {
$scope.setup = !settings.configName;
var tokenData = JSON.parse(localStorage.getItem("msTeams-oauth"));
var userData = JSON.parse(localStorage.getItem("msTeams-user"));
if (tokenData) {
FormService.httpGet('ws/project/user/' + userData.id + '?light=true', {headers: {'Authorization': 'Bearer ' + tokenData['accessToken']}}, true).then(function(projects) {
$scope.projects = projects;
if (settings.entityId) {
$scope.settings.project = _.find($scope.projects, {pkey: settings.entityId.split('icescrum-pkey-')[1]});
}
$scope.ready = true;
});
}
});
Full error:
angular.min.js:113 2020-03-25T20:35:25.953Z Received error from connectors {"seq":1585168484680,"timestamp":1585168525943,"flightSettings":{"Name":"ConnectorFrontEndSettings","AriaSDKToken":"d127f72a3abd41c9b9dd94faca947689-d58285e6-3a68-4cab-a458-37b9d9761d35-7033","SPAEnabled":true,"ClassificationFilterEnabled":true,"ClientRoutingEnabled":true,"EnableYammerGroupOption":true,"EnableFadeMessage":false,"EnableDomainBasedOwaConnectorList":false,"EnableDomainBasedTeamsConnectorList":false,"DevPortalSPAEnabled":true,"ShowHomeNavigationButtonOnConfigurationPage":false,"DisableConnectToO365InlineDeleteFeedbackPage":true},"status":500,"clientType":"SkypeSpaces","connectorType":"f00d8890-daa8-4c87-89f5-83cbab0bccd4","name":"handleMessageError"}
In case this helps anyone else, I spent ages today trying to get to the bottom of this and couldn't find a solution. Until...as a last gasp show of desperation I decide to use App Studio to recreate the entire connector manifest from scratch, including creating a new connector in the portal.
For some reason, this then worked fine - even though I can see that the two manifest files are identical with the exception of the ID (and I already tried regenerating the ID for the original one).
Bit late to the story, but having followed multiple github issues like this and stack overflow posts, I'm pretty convinced that its the problem with Connectors dashboard. If you made any change to settings, they are not really propageted/saved correctly.
So for example, if you changed validDomains or configurationPage URL, they won't actually do anything. You can verify that with your devtools. For me, after changing the configurationPage the Teams is still making request to old URL as well as the new one, but the old request produces error that's listed in question.
The only workaround I was able to find is to recreate connector in dashboard. Reported problem to MS Teams dev team, waiting to hear back.
Also late here, but I ran into this problem and the below was the solution after 3 days of frustration.
Despite everything mentioned in the documentation, the following is required otherwise you'll get this error. This fixed things for me.
microsoftTeams.settings.registerOnSaveHandler(saveEvent => {
microsoftTeams.settings.setSettings({
contentUrl: "https://xxxxxx.ngrok.io/teams/connector"
});
saveEvent.notifySuccess();
});
The documentation states that registering a save handler is optional and Teams will handle notify success if it's not declared. WRONG. You must register a save handler.
The documentation does not state that setSettings is required. WRONG. You must set settings or else you will receive this error.
The documentation does not state that you must save a contentURL. WRONG. You must set content URL in the setSettings. You can apparently omit other things when setting your settings, but not content URL.
The documentation does not specifically mention it, but the contentURL must comply with your validURLs in your manifest. If it does not, you'll also see this error.
So in your case, you must ensure that isSettings.serverUrl (setSettings() contentURL) does match preview.icescrum.com (manifest validURLs). If they do not, you'll see this error.

MailChimp Campaign Update

i am trying to use campaigns/update in MailChimp.
However i still cannot understand how can i use it.
Can anyone please explain to me, for example how can i change the "from_email" parameter?
my current json for that purpose looks like this:
{
"apikey": "my_api_key",
"cid": "my_campaign_id",
"name": "options",
"value": ["list_id_value","subject_value","from_email_value"]
}
However when i send this json to campaigns/update, it returns error saying that "Can not update unknown option "2"".
How can i change the json so that i can update the "from_email"?
The API docs seem to be wrong. Try replacing [ ] with { } and giving field:pair values inside it. So, example to change the subject:
{
"apikey": "my_api_key",
"cid": "my_campaign_id",
"name": "options",
"value": {"subject": "My new subject"}
}

What services can I use to fetch an image of a person based on their email address, without authentication

I know gravatar allows this, and I'd like to look into facebook, google plus, twitter, instagram, and anything else.
Do you guys know of any services like this?
EDIT: to clarify, by "without authentication" do I mean user authentication, I expect to use some sort of API
One possible approach, using Facebook Graph Api would be to perform a search against the name for users objects and also retrieve their pictures, using API version 2.2 it would be a call like:
GET graph.facebook.com
/search?q=miles davis&type=user&fields=id,name,picture
This would retrieve id, name and picture object for a search on miles davis, first results as example:
{
"data": [
{
"id": "805353876185303",
"name": "Miles Davis",
"picture": {
"data": {
"is_silhouette": true,
"url": "https://fbcdn-profile-a.akamaihd.net/hprofile-ak-xfp1/v/t1.0-1/c15.0.50.50/p50x50/10354686_10150004552801856_220367501106153455_n.jpg?oh=XXXXXXXXXXXXXXXX&oe=XXXXXX&__gda__=XXXXXXX_XXXXXXXXXXXXX"
}
}
},
{
"id": "1572370603017419",
"name": "Miles Davis",
"picture": {
"data": {
"is_silhouette": false,
"url": "https://fbcdn-profile-a.akamaihd.net/hprofile-ak-xap1/v/t1.0-1/p50x50/1501761_1382020035385811_1384168153_n.jpg?oh=XXXXXXXXX&oe=XXXXXXXXXXX&__gda__=XXXXXX_XXXXXX"
}
}
}, ...........
The field is_silhouette is false if the user has a profile picure.

Intel XDK : Parse.com integration "Unauthorized"

I am very new to Intel XDK and i try to make a very simple app like this in that video tutorial: Using Services Datafeed in App Designer.
But instead of the specific service from Rotten Tomatoes i want to integrate a database i have in Parse.com. For that i followed this video tutorial: "Integrating a New Service"
"[https]://software.intel.com/en-us/html5/videos/integrating-a-new-service",
and at the end the response was: "Unauthorized".
Then i found only this answer which comes from Intel's HTML5 Development Forums. I did not get anything either with this. The response was again: "Unauthorized".
And now i am confused and disappointed because:
I can't find other resources to help my self
I don't want to do it someone else instead of me, but
Without a full example, how is supposed to make it to learn?
My code now is similar with this in video: "Integrating a New Service"
In apiconfig.json
{
"MyService": {
"name": "The external service",
"description": "A great API with an external service",
"dashboardUrl": "https://parse.com",
"auth": "key",
"signature": "apiSecret"
}
}
In MyService.js
(function (credentials) {
var exports = {};
exports.ServiceObject = function(params) {
var url = 'https://api.parse.com/1/classes/ServiceObject';
params['apiKey'] = credentials.apiKey;
url = url + '?' + $.param(params);
return $.ajax({url: url, type: 'GET'});
};
return exports;
})
And in MyService.json
{
"endpoints": [
{
"name": "classes",
"dashboardUrl": "https://parse.com/docs/rest",
"methods": [
{
"MethodName": "ServiceObject",
"Synopsis": "Show the entries",
"parameters": [
{
"Name": "objectId",
"Required": "N",
"Default": "",
"Type": "string",
"Description": "The object ID"
},
{
"Name": "text",
"Required": "N",
"Default": "",
"Type": "string",
"Description": "The text"
}
]
}
]
}
]
}
Can someone help me more? In whatever way he thinks best.
Thank you all
Edit:
After the following answer, my problem solved.
"MyService.js" file after the correction is:
(function (credentials) {
var exports = {};
exports.ServiceObject = function(params) {
var url = 'https://api.parse.com/1/classes/ServiceObject';
return $.ajax({
url : url,
headers : {
'X-Parse-Application-Id' : credentials.apiKey,
'X-Parse-REST-API-Key' : credentials.apiSecret
}
});
};
return exports;
})
# user1736947: Your answer was concise and precise, exactly what i needed.
Certainly in the future I will need a lot of help, but for now I can go on my self-education thanks to you.
Thank you very much.
The way the authentication keys are accepted is different for different services. The example in the video.. rottentomatoes.. it accepted keys as a url parameter, so we append the key to the url and send it. However, seems like parse wants the keys in the headers (according to this)
So the equivalent ajax call will be something like :
exports.ServiceObject = function(params) {
var url = 'https://api.parse.com/1/classes/ServiceObject';
return $.ajax({
url : url,
headers : {
'X-Parse-Application-Id' : credentials.apiKey,
'X-Parse-REST-API-Key' : credentials.apiSecret
}
});
This might not fix everything but it will move you a step beyond the authorization issue. Let me know if you are able to retreive the class this way.
To get a particular row entry, append the url with params.objectID.
Also, the XDK services tab has a parse-similar service ... kinvey. It also allows you to create a database online and retreive it.

Resources