actions-on-google / actions-on-google-java

Java/Kotlin library for Actions on Google
Apache License 2.0
286 stars 39 forks source link

sync response report error with customData string #28

Closed kingskylar closed 4 years ago

kingskylar commented 5 years ago

gcp error log,when use actions-on-google build response,the customData parameter only can be set to String or JSONObject,can't set to a map: { insertId: "18ele3sg4g4ys72"
logName: "**"
receiveTimestamp: "2019-08-02T02:45:43.962689625Z"
resource: { labels: { action_id: "SMART_HOME_SYNC"
project_id: "*"
version_id: ""
} type: "assistant_action"
} severity: "ERROR"
textPayload: "SYNC: Request ID 14473429503853394047 update devices failed: INVALID_ARGUMENT. Detail: Error:
[Expect a map object but found: "{\"on\":\"corridor_light_status\",\"brightness\":\"brightness_level\",\"color\":\"argb_value\"}"]** while parsing JSON [{"payload":{"agentUserId":"708039437023605410076199124993","devices":[{"attributes":

{"colorModel":"rgb"},"customData":"{\"on\":\"corridor_light_status\",\"brightness\":\"brightness_level\",\"color\":\"argb_value\"}","deviceInfo":{"hwVersion":"1.0","manufacturer":"Aqara","model":"lumi.gateway.aqhm01","swVersion":"1.0"},"id":"***,"name":{"defaultNames":["Light"],"name":"GateWay Light","nicknames":["Light"]},"traits":["action.devices.traits.OnOff","action.devices.traits.Brightness","action.devices.traits.ColorSetting"],"type":"action.devices.types.LIGHT","willReportState":true}]},"requestId":"14473429503853394047"}]"
timestamp: "2019-08-02T02:45:43.939331180Z"
}

Fleker commented 5 years ago

Custom Data is meant to be a string, or some other sort of opaque data. In your case, it doesn't seem like your string is being serialized correctly to a string.

kingskylar commented 5 years ago

Thank you for reply! I used SyncResponse build this Custom Data ,it is a json string:

SyncResponse.Payload.Device.Builder().setCustomData("{\"on\":\"corridor_light_status\",\"brightness\":\"brightness_level\",\"color\":\"argb_value\"}") or SyncResponse.Payload.Device.Builder().setCustomData(new org.json.JSONObject("{\"on\":\"corridor_light_status\",\"brightness\":\"brightness_level\",\"color\":\"argb_value\"}")) The GCP Log error: textPayload: "SYNC: Request ID 18051937407930965209 update devices failed: INVALID_ARGUMENT. Detail: Error: [Expect a map object but found: "{\"brightness\":\"brightness_level\",\"color\":\"argb_value\",\"on\":\"corridor_light_status\"}"] while parsing JSON [{"payload":{"agentUserId":"708039437023605410076199124993","devices":[{"attributes":{"colorModel":"rgb"},"customData":"{\"brightness\":\"brightness_level\",\"color\":\"argb_value\",\"on\":\"corridor_light_status\"}","deviceInfo":{"hwVersion":"1.0","manufacturer":"**","model":"**","swVersion":"1.0"},"id":"**","name":{"defaultNames":["Light"],"name":"Light","nicknames":["Light"]},"traits":["action.devices.traits.OnOff","action.devices.traits.Brightness","action.devices.traits.ColorSetting"],"type":"action.devices.types.LIGHT","willReportState":true},{"attributes":{"colorModel":"rgb"},"customData":"{\"brightness\":\"brightness_level\",\"color\":\"argb_value\",\"on\":\"corridor_light_status\"}","deviceInfo":{"hwVersion":"1.0","manufacturer":"***","model":"**","swVersion":"1.0"},"id":"***","name":{"defaultNames":["Light"],"name":"Hub","nicknames":["Hub"]},"traits":["action.devices.traits.OnOff","action.devices.traits.Brightness","action.devices.traits.ColorSetting"],"type":"action.devices.types.LIGHT","willReportState":true}]},"requestId":"18051937407930965209"}]"

While i used a json file to build Response according to action.devices.SYNC customData: Object. Optional; this is a special object defined by the partner which will be attached to future QUERY and EXECUTE requests. Partners can use this object to store additional information about the device to improve performance or routing within their cloud, such as the global region of the device. Data in this object has a few constraints: it worked well response custom Date as a Json Object not a String:

"customData":{ "brightness":"brightness_level", "color":"argb_value", "on":"corridor_light_status" },

then i change this file to example: "customData":"{\"fooValue\": 74, \"barValue\": true, \"bazValue\": \"foo\"}" gcp error as mentioned before!

I wonder if this Custom Data can be a String!

Fleker commented 5 years ago

What Java type is your input? Is it a String or JSONObject?

kingskylar commented 5 years ago

I have tried String and JSONObject based on SyncResponse's customData builder and JSONObject will be converted to String before send back to google!

I want to know what the differences between CustomData and Attributes in google definition:


 fun setCustomData(customData: JSONObject): Builder {
    protoBuilder.customData = customData.toString()
    return this
    }
fun setAttributes(attributesJson: JSONObject): Builder {
                    val attributeBuilder = Struct.newBuilder()
                    try {
                        JsonFormat.parser()
                                .ignoringUnknownFields()
                                .merge(attributesJson.toString(), attributeBuilder)
                    } catch (e: Exception) {
                        throw RuntimeException(e)
                    }

                    protoBuilder.setAttributes(attributeBuilder)
                    return this
                }

If i build syncResponse set CustomData same as Attributes,google response ok!

Fleker commented 5 years ago

I was incorrect. customData needs to be an object, not a string. So the library needs to be patched.

kingskylar commented 5 years ago

How long does this patch release, I am waiting to use it.Thank you!

Fleker commented 5 years ago

At first I thought it would be a simple change. However, the type for custom data is developed from the protobuf, where it's defined as a string. So now I'm trying to see if the proto needs to be updated.

RayBa82 commented 5 years ago

I am waiting for this too. For now i use a very "nice" workaround, this might not work for everyone, but i know my data does not contain other data like this. And my customData content are all string values.

val result = assistantApp.handleRequest(body, headerMap).get() .replace("\"{", "{") .replace("}\"", "}") .replace("\\\"", "\"")

RayBa82 commented 5 years ago

Are here some news? This is a major bug and it takes over 3 months to fix?

Fleker commented 4 years ago

We have updated the proto in 1569c90389a48afada9c258cb008259004ed8247, which now is a struct type. The string-based methods have been deprecated and now accept a JSON object.