Positive Scenario Usage of StatusReport google home trait - google-smart-home

In Google documentation, they explained how to use "statusReport" trait for query intent when there is an error or exception occurred for a device. I'm facing issue while using it for success status without any exception. I tried sending the response with simple status as SUCCESS, Google Home is saying the response "Sorry Unable to reach device".
The response which I was sending:
{ "requestId": "ff36a3cc-ec34-11e6-b1a0-64510650abcf", "payload": { "devices": { "123": { "online": true, "status": "SUCCESS" } } } }
can anyone help me to solve this issue?

After looking at the code, it is clear that you’re not sending the correct & complete response of the StatusReport trait. Your response contains the online attribute but missing the currentStatusReport attribute (it is required as it defines the current error statuses of the associated device IDs). For more information, visit https://developers.google.com/assistant/smarthome/traits/statusreport?hl=en

Related

Logic App not able to deserialized Azure data factory pipeline error message

I am facing the below issue with Azure Data Factory using Logic App.
I am using the Azure Data Factory pipeline for migration and Logic App for sending "Success & Failure" notification to the technical team.
Now success is working fine as the message is hardcoded, but failure is not as the Logic App web activity is not able to parse data factory pipeline error.
Here is the input that is going to Logic App web activity
Input
{
"url": "https://xxxxxxxxxxxxxxxxx",
"method": "POST",
"headers": {},
"body": "{\n \"title\": \"PIPELINE RUN FAILED\",\n \"message\":\"Operation on target Migration Validation failed: Execution fail against sql server. Sql error number: 50000. Error Message: The DELETE statement conflicted with the REFERENCE constraint \"FK_cmclientapprovedproducts_cmlinkclientchannel\". The conflict occurred in database \"Core7\", table \"dbo.cmClientApprovedProducts\", column 'linkclientchannelid'.\",\n \"color\": \"Red\",\n \"dataFactoryName\": \"LFC-TO-MCP-ADF\",\n \"pipelineName\": \"LFC TO MCP MIGRATION\",\n \"pipelineRunId\": \"f4f84365-58f0-4da1-aa00-64c3a4daa9e1\",\n \"time\": \"2020-07-31T22:44:01.6477435Z\"\n}"
}
Here is the error logic app is throwing
failures
{
"errorCode": "2108",
"message": "{\"error\":{\"code\":\"InvalidRequestContent\",\"message\":\"The request content is not valid and could not be deserialized: 'After parsing a value an unexpected character was encountered: F. Path 'message', line 3, position 202.'.\"}}",
"failureType": "UserError",
"target": "Send Failed Notification",
"details": []
}
I have tried various options, like set variable and convert by using various existing methods (string, json, replace etc), but no luck
e.g #string(activity('LOS migration').Error.Message)
Struggling almost all day this...please suggest if anyone faced a similar issue...
Below is the data flow activity
now it is working...
Pasting body content into the body text field box WITHOUT clicking on 'Add Dynamic Content' in web activity calling Logic App.
For the failure case, pass the error output use #{activity('LOS migration').error.message.
For sending email, it doesn't know if it's going to send a failure or success email. We have to adapt the body so the activity can use parameters, which we'll define later:
{
"DataFactoryName": "#{pipeline().DataFactory}",
"PipelineName": "#{pipeline().Pipeline}",
"Subject": "#{pipeline().parameters.Subject}",
"ErrorMessage": "#{pipeline().parameters.ErrorMessage}",
"EmailTo": "#pipeline().parameters.EmailTo"
}
We can reference this variables in the body by using the following format: #pipeline().parameters.parametername. For more details, you could refer to this article.
If you want to use the direct error message of the data factory activity as an input to the logic app email expression, you could try.
"ErrorMessage": "#{string(replace(activity('activity_name').Error.Message, '"',''''))}"
Replace 'activity_name' with your failing activity name.

Problem with StatusReport trait in Smart Home Actions

I have a Security System with traits action.devices.traits.ArmDisarm and action.devices.traits.StatusReport and some other sensors: WaterLeak Sensor, Door Sensor ...
I report some errors about other devices with StatusReport state.
For example: when the door sensor detects that the door is open, the security system must give deviceOpen error.
When I say, "Is my security system ok?", my server's response to the query intent is the JSON below, but Google Assistant says that he couldn't reach my action (Unexpected error happened).
Is there anything wrong with this response?
{
"requestId": "10417064006786362499",
"payload": {
"devices": {
"3rL3QL7Kq2HrQjs53Y7o": {
"isArmed": true,
"currentStatusReport": [
{
"blocking": true,
"deviceTarget": "4BCIpzBWpgLA24mMI7r2",
"priority": 0,
"statusCode": "deviceOpen"
},
{
"blocking": true,
"deviceTarget": "MxRCd6ERRSWzYzyNTE8S",
"priority": 0,
"statusCode": "waterLeakDetected"
}
],
"status": "EXCEPTIONS",
"online": true
}
}
}
}
In Firebase Console there are no errors.
Logs in Firebase Console
Your response to the query intent looks right, but there might be an error in other parts of the process. You can follow the Troubleshooting Guide to see how your failed intent is counted in the Smart Home metrics and what are the details on your logs. (Firebase logs only gives info about your server. The logging mentioned in the guide (Google Cloud Logging) is a different and more comprehensive for the intent handling)

Files GraphAPI do return 403 until the file is loaded by the user

As User#1, we're using this API to create a shared link:
https://graph.microsoft.com/v1.0/drives/{{driveId}}/items/{{itemId}}/createLink
This is successful and returns a ShareURI.
As User#2, we're using this API to get information about the item shared by User#1.
https://graph.microsoft.com/v1.0/shares/{{base64ShareURI}}/driveItem
However, /driveItem returns a status code of 403 with the following body:
HTTP 403
{
"error": {
"code": "accessDenied",
"message": "The sharing link no longer exists, or you do not have
permission to access it.",
"innerError": {
"request-id": "73e65e0a-54b8-4722-9726-82297076276e",
"date": "2018-11-07T16:20:03"
}
}
}
To prevent this 403 from happening, User#2 needs to load the ShareURI in a web browser. Once User#2 does this, then the request to the exact same URI
https://graph.microsoft.com/v1.0/shares/{{base64ShareURI}}/driveItem
return 200OK and the expected json body.
Why does User#2 have to load the ShareURI in a browser before being able to use Graph APIs on that ShareURI? Is there a workaround?
To open it directly without visiting link just add header Prefer with value redeemSharingLink to request https://graph.microsoft.com/v1.0/shares/{{base64ShareURI}}/driveItem.
Docs:
redeemSharingLink should be considered equivalent to the caller navigating to the sharing link the browser (accepting the sharing gesture)
Reference: https://learn.microsoft.com/en-us/graph/api/shares-get?view=graph-rest-1.0&tabs=javascript

Better error message when missing required fields from request

When missing a required field currently ProtoRPC returns a message like this:
{
"error": {
"code": 400,
"errors": [
{
"domain": "global",
"message": "Error parsing ProtoRPC request (Unable to parse request content: Message CombinedContainer is missing required field api_key)",
"reason": "badRequest"
}
],
"message": "Error parsing ProtoRPC request (Unable to parse request content: Message CombinedContainer is missing required field api_key)"
}
}
Is it possible to provide a better error message? Ideally, "missing required field api_key" in this example.
According to the Google Code Issue Tracker and Github issues this was once being worked on. However, there does not appear to be any activity.
I'd greatly appreciate any solutions or workarounds.
As of today, the ProtoRPC still returns the same unraised error which makes it harder for one to return a customized error response.
A simple workaround is to make the Message fields optional and enforce the requirement constraint somewhere in the endpoint handler/method.
So instead of;
class Request(Message):
name = StringField(1, required=True)
Set 'name' as optional,
class Request(Message):
name = StringField(1)
The requirement constraint can then be enforced in the endpoint handler method by simple if statements OR by mapping these fields to a Datastore entity that requires these fields, hence will allow exception handling of BadValueError and return a more customized error response.
Example:
try:
account = Account(name=request.name)
account.put()
except BadValueError:
return Response(status=False, message='Missing field "name"')

Error when trying to get Google Drive File

I am getting an error when trying to get a Google Drive File using:
file = service.files().get(fileId=<googleDriveFileId>).execute()
The error is:
<HttpError 404 when requesting https://www.googleapis.com/drive/v2/files/0B6Cpn8NXwgGPQjB6ZlRjb21ZdXc?alt=json returned "File not found: 0B6Cpn8NXwgGPQjB6ZlRjb21ZdXc">
However, when I copy and paste that link directly in the browser like this:
https://www.googleapis.com/drive/v2/files/0B6Cpn8NXwgGPQjB6ZlRjb21ZdXc?alt=json
I get a different error:
{
"error": {
"errors": [
{
"domain": "usageLimits",
"reason": "dailyLimitExceededUnreg",
"message": "Daily Limit Exceeded. Please sign up",
"extendedHelp": "https://code.google.com/apis/console"
}
],
"code": 403,
"message": "Daily Limit Exceeded. Please sign up"
}
}
I am no where even close to exceeding the daily limit, the console shows 0% usage.
I know the fileId is correct, I am using Google Picker to get the fileId.
Any ideas?
I have found elsewhere that this is known issue with Google Drive that they are working to resolve. They offer the following workaround that I have confirmed works.
Add the following to when building the picker:
enableFeature(google.picker.Feature.MULTISELECT_ENABLED).
complete code:
var picker = new google.picker.PickerBuilder().
addView(view).
addView(uploadView).
setAppId("pressomatic").
setCallback(pickerCallback).
enableFeature(google.picker.Feature.MULTISELECT_ENABLED).
build();
picker.setVisible(true);
This same workaround solves another problem I have posted about, when trying to upload to a specific folder with Google Picker using setParent on a DocsUploadView. You still add the same feature to the Picker, not the DocsUploadView, and everything works as it should.

Resources