i8beef / HomeAutio.Mqtt.GoogleHome

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Mediastate error

sognen opened this issue · comments

Hi,
I'm getting an error on trait media state (StreamingBox). When I for instance ask the assistant to pause playback it pauses media but also responds by saying that its homeautio is unavailable. The log entry for mediastate is found at the bottom.

I clicked into the mentioned trait to verify its configuration. All looked good, but when clicking the Update button it says:

Error
#/activityState: NotInEnumeration
#/playbackState: NotInEnumeration

I noticed that valuemap was set to [], and not null as in the example.

Udate:
I get a similar error on FanSpeed. The error message is

Error
#/: NotOneOf
#/: NotOneOf

Log entry - Mediastate:
e.Controllers.GoogleHomeController (HomeAutio.Mqtt.GoogleHome). [22:21:53 INF] Received EXECUTE intent for commands: action.devices.commands.mediaPause [22:21:53 INF] Executed action HomeAutio.Mqtt.GoogleHome.Controllers.GoogleHomeController.Post (HomeAutio.Mqtt.GoogleHome) in 5.1699ms [22:21:53 INF] Executed endpoint 'HomeAutio.Mqtt.GoogleHome.Controllers.GoogleHomeController.Post (HomeAutio.Mqtt.GoogleHome)' [22:21:53 ERR] Connection id "0HM5F1U2AAMK0", Request id "0HM5F1U2AAMK0:00000002": An unhandled exception was thrown by the application. System.NullReferenceException: Object reference not set to an instance of an object. at HomeAutio.Mqtt.GoogleHome.Extensions.DictionaryExtensions.ToFlatDictionary(IDictionary2 source, String delimiter) in /app/HomeAutio.Mqtt.GoogleHome/Extensions/DictionaryExtensions.cs:line 21
at HomeAutio.Mqtt.GoogleHome.IntentHandlers.ExecuteIntentHandler.Handle(ExecuteIntent intent) in /app/HomeAutio.Mqtt.GoogleHome/IntentHandlers/ExecuteIntentHandler.cs:line 149
at HomeAutio.Mqtt.GoogleHome.Controllers.GoogleHomeController.Post(Request request) in /app/HomeAutio.Mqtt.GoogleHome/Controllers/GoogleHomeController.cs:line 68
at lambda_method437(Closure , Object , Object[] )
at Microsoft.AspNetCore.Mvc.Infrastructure.ActionMethodExecutor.SyncActionResultExecutor.Execute(IActionResultTypeMapper mapper, ObjectMethodExecutor executor, Object controller, Object[] arguments)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.InvokeActionMethodAsync()
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.InvokeNextActionFilterAsync()
--- End of stack trace from previous location ---
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Rethrow(ActionExecutedContextSealed context)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.InvokeInnerFilterAsync()
--- End of stack trace from previous location ---
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.g__Awaited|24_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Rethrow(ResourceExecutedContextSealed context)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.InvokeFilterPipelineAsync()
--- End of stack trace from previous location ---
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.g__Logged|17_1(ResourceInvoker invoker)
at Microsoft.AspNetCore.Routing.EndpointMiddleware.g__AwaitRequestTask|6_0(Endpoint endpoint, Task requestTask, ILogger logger)
at Microsoft.AspNetCore.Authorization.Policy.AuthorizationMiddlewareResultHandler.HandleAsync(RequestDelegate next, HttpContext context, AuthorizationPolicy policy, PolicyAuthorizationResult authorizeResult)
at Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)
at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context)
at HomeAutio.Mqtt.GoogleHome.RequestResponseLoggingMiddleware.Invoke(HttpContext context) in /app/HomeAutio.Mqtt.GoogleHome/RequestResponseLoggingMiddleware.cs:line 46
at Microsoft.AspNetCore.Builder.Extensions.UsePathBaseMiddleware.Invoke(HttpContext context)
at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpProtocol.ProcessRequests[TContext](IHttpApplication1 application)

The error messages for the JsonSchema validator leave something to be desired. I thought I added an indicator which thing errored (attributes, commands, state) but I must have missed that, I'll have to go back and add that.

For the MediaState one:

  1. activitystate only supports the following values: "INACTIVE", "STANDBY", "ACTIVE"
  2. playbackState only supports the following values: "PAUSED", "PLAYING", "FAST_FORWARDING", "REWINDING", "BUFFERING", "STOPPED"

For FanSpeed I think I need to see your config for that device to troubleshoot. There could be several reasons something is messed up there, including a mistake on my side.

Hi,
I have attached a screenshot of MediaState and FanSpeed. Both worked with the latest 1.x version.
mediaState

fanSpeed

The fanSpeed is configured as follows:

Attribute:
{
"availableFanSpeeds": {
"speeds": [
{
"speed_name": "superlow",
"speed_values": [
{
"speed_synonym": [
"Super Low"
],
"lang": "en"
}
]
},
{
"speed_name": "low",
"speed_values": [
{
"speed_synonym": [
"Low"
],
"lang": "en"
}
]
},
{
"speed_name": "medium",
"speed_values": [
{
"speed_synonym": [
"Medium"
],
"lang": "en"
}
]
},
{
"speed_name": "high",
"speed_values": [
{
"speed_synonym": [
"High"
],
"lang": "en"
}
]
}
],
"ordered": true
},
"reversible": false,
"supportsFanSpeedPercent": true
}

Commands:
{
"action.devices.commands.SetFanSpeed": {
"fanSpeed": "homie/bedroom-hvac/fan/fanSpeed/set",
"fanSpeedPercent": "homie/bedroom-hvac/fan/fanSpeedPercent/set"
},
"action.devices.commands.SetFanSpeedRelative": {
"fanSpeedRelativeWeight": "homie/bedroom-hvac/fan/fanSpeedRelativeWeight/set",
"fanSpeedRelativePercent": "homie/bedroom-hvac/fan/fanSpeedRelativePercent/set"
}
}

State:
{
"currentFanSpeedSetting": {
"topic": "homie/bedroom-hvac/fan/fanSpeed",
"valueMap": [
{
"google": "superlow",
"mqtt": "superlow",
"type": "value"
},
{
"google": "low",
"mqtt": "low",
"type": "value"
},
{
"google": "medium",
"mqtt": "medium",
"type": "value"
},
{
"google": "high",
"mqtt": "high",
"type": "value"
}
]
},
"currentFanSpeedPercent": {
"topic": "homie/bedroom-hvac/fan/fanSpeedPercent",
"valueMap": null
}
}

The MediaState one is a bug. Ill put out a fix here shortly, along with some better messages there.

The FanSpeed one though seems to be a misunderstanding of Google's spec. For the command supported params, you are using two EXCLUSIONARY approaches. Google specifies that

  1. SetFanSpeed can use fanSpeed OR fanSpeedPercent but NOT both at the same time
  2. SetFanSpeedRelative can use fanSpeedRelativeWeight OR fanSpeedRelativePercent but NOT both at the same time

If that seems incorrect, it might be worth reporting / asking on Google's schema repo to see if they just messed up the schema.

Thanks, I will do some more investigations later today and report back with my findings.

Actually let me think about that FanSpeed one... I might have to rethink my approach of using the command validators as is, their schema is correct for validating a SINGLE command, but I'm trying to validate ALL POSSIBLE command paths at once using it. This is an edge case to that approach (A command that supports multiple "modes" of command structures) which Im likely going to have to adjust for.

Ok, I just pushed a new version (2.0.0.159) that SHOULD take that as is (works in my tests anyway). I might need to consider doing some of these transforms to the schema files themselves instead of doing it on the fly in code... that changes my model a little bit from how I envisioned it, but some of these recursive hacks to the JsonSchema structure are starting to feel a little hacky already.

Issues like this will help me nail down all the weird edge cases though.

Thanks, I pulled the latest version, and spent some time to go through each of my devices and traits.

Trait: Toggle

{
"action.devices.commands.SetToggles": {
"updateToggleSettings.rotation": "homie/bedroom-hvac/fan/rotation/set",
"updateToggleSettings.economy": "homie/bedroom-hvac/fan/economy/set"
}
}

Error:
Commands (action.devices.commands.SetToggles): #/updateToggleSettings: TooManyProperties

Comment:
It appears that it fails with the error above when having more than one parameter.

Trait: SensorState

{
"currentSensorStateData.[0].name": {
"topic": null,
"valueMap": [
{
"google": "SmokeLevel",
"type": "static"
}
]
},
"currentSensorStateData.[0].currentSensorState": {
"topic": "homie/bedroom-sensors/smoke/currentSensorState",
"valueMap": null
},
"currentSensorStateData.[0].rawValue": {
"topic": "homie/bedroom-sensors/smoke/rawValue",
"valueMap": null
}
}

Error:
State: #/currentSensorStateData[0]: ArrayItemNotValid

Comment:
I have verified against schema and examples, not clear to me what is wrong here.

Trait: TemperatureSetting

Commands:
{
"action.devices.commands.ThermostatTemperatureSetpoint": {
"thermostatTemperatureSetpoint": "homie/bedroom-hvac/thermostat/thermostatTemperatureSetpoint/set"
},
"action.devices.commands.ThermostatTemperatureSetRange": {
"thermostatTemperatureSetpointHigh": "homie/bedroom-hvac/thermostat/thermostatTemperatureSetpointHigh/set",
"thermostatTemperatureSetpointLow": "homie/bedroom-hvac/thermostat/thermostatTemperatureSetpointLow/set"
},
"action.devices.commands.ThermostatSetMode": {
"thermostatMode": "homie/bedroom-hvac/thermostat/thermostatMode/set"
},
"action.devices.commands.TemperatureRelative": {
"thermostatTemperatureRelativeDegree": "homie/bedroom-hvac/thermostat/thermostatTemperatureRelativeDegree/set",
"thermostatTemperatureRelativeWeight": "homie/bedroom-hvac/thermostat/thermostatTemperatureRelativeWeight/set"
}
}

States:
{
"thermostatMode": {
"topic": "homie/bedroom-hvac/thermostat/thermostatMode",
"valueMap": null
},
"thermostatTemperatureSetpoint": {
"topic": "homie/bedroom-hvac/thermostat/thermostatTemperatureSetpoint",
"valueMap": null
},
"thermostatTemperatureAmbient": {
"topic": "homie/bedroom-hvac/thermostat/thermostatTemperatureAmbient",
"valueMap": null
},
"thermostatTemperatureSetpointHigh": {
"topic": "homie/bedroom-hvac/thermostat/thermostatTemperatureSetpointHigh",
"valueMap": null
},
"thermostatTemperatureSetpointLow": {
"topic": "homie/bedroom-hvac/thermostat/thermostatTemperatureSetpointLow",
"valueMap": null
}
}

Error:
State: #/: NotOneOf
Commands (action.devices.commands.ThermostatSetMode): #/thermostatMode: NotAnyOf

Comment:
I have verified against schema and examples, not clear to me what is wrong here.

I forgot to mention that with the latest pull I no longer get an error when clicking the update button. When pausing my media player I get a voice message saying that homeautio is unavailable right now. The command is executed though. Initially, I thought this had to do with the Mediastate trait, but conscious that it may be something different. Should I log this is as a new issue?

This is what the log says:

[13:02:52 INF] Received EXECUTE intent for commands: action.devices.commands.mediaPause [13:02:52 INF] Executed action HomeAutio.Mqtt.GoogleHome.Controllers.GoogleHomeController.Post (HomeAutio.Mqtt.GoogleHome) in 3.1017ms [13:02:52 INF] Executed endpoint 'HomeAutio.Mqtt.GoogleHome.Controllers.GoogleHomeController.Post (HomeAutio.Mqtt.GoogleHome)' [13:02:52 ERR] Connection id "0HM5FR78LPPSQ", Request id "0HM5FR78LPPSQ:00000002": An unhandled exception was thrown by the application. System.NullReferenceException: Object reference not set to an instance of an object. at HomeAutio.Mqtt.GoogleHome.Extensions.DictionaryExtensions.ToFlatDictionary(IDictionary2 source, String delimiter) in /app/HomeAutio.Mqtt.GoogleHome/Extensions/DictionaryExtensions.cs:line 21 at HomeAutio.Mqtt.GoogleHome.IntentHandlers.ExecuteIntentHandler.Handle(ExecuteIntent intent) in /app/HomeAutio.Mqtt.GoogleHome/IntentHandlers/ExecuteIntentHandler.cs:line 149 at HomeAutio.Mqtt.GoogleHome.Controllers.GoogleHomeController.Post(Request request) in /app/HomeAutio.Mqtt.GoogleHome/Controllers/GoogleHomeController.cs:line 68 at lambda_method376(Closure , Object , Object[] ) at Microsoft.AspNetCore.Mvc.Infrastructure.ActionMethodExecutor.SyncActionResultExecutor.Execute(IActionResultTypeMapper mapper, ObjectMethodExecutor executor, Object controller, Object[] arguments) at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.InvokeActionMethodAsync() at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted) at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.InvokeNextActionFilterAsync() --- End of stack trace from previous location --- at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Rethrow(ActionExecutedContextSealed context) at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted) at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.InvokeInnerFilterAsync() --- End of stack trace from previous location --- at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.g__Awaited|24_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted) at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Rethrow(ResourceExecutedContextSealed context) at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted) at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.InvokeFilterPipelineAsync() --- End of stack trace from previous location --- at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.g__Logged|17_1(ResourceInvoker invoker) at Microsoft.AspNetCore.Routing.EndpointMiddleware.g__AwaitRequestTask|6_0(Endpoint endpoint, Task requestTask, ILogger logger) at Microsoft.AspNetCore.Authorization.Policy.AuthorizationMiddlewareResultHandler.HandleAsync(RequestDelegate next, HttpContext context, AuthorizationPolicy policy, PolicyAuthorizationResult authorizeResult) at Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context) at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context) at HomeAutio.Mqtt.GoogleHome.RequestResponseLoggingMiddleware.Invoke(HttpContext context) in /app/HomeAutio.Mqtt.GoogleHome/RequestResponseLoggingMiddleware.cs:line 46 at Microsoft.AspNetCore.Builder.Extensions.UsePathBaseMiddleware.Invoke(HttpContext context) at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpProtocol.ProcessRequests[TContext](IHttpApplication1 application) [13:02:52 INF] Request finished HTTP/1.1 POST http://192.168.1.104:5000/google/home/smarthome application/json;charset=UTF-8 265 - 500 0 - 14.4145ms [13:02:52 INF] MQTT message received for topic homie/livingroom-hts/kodi/playbackState: PAUSED [13:02:52 INF] Start processing HTTP request POST https://oauth2.googleapis.com/token [13:02:52 INF] Sending HTTP request POST https://oauth2.googleapis.com/token [13:02:52 INF] Received HTTP response headers after 11.8814ms - 200 [13:02:52 INF] End processing HTTP request after 12.3935ms - 200 [13:02:52 INF] Start processing HTTP request POST https://homegraph.googleapis.com/v1/devices:reportStateAndNotification [13:02:52 INF] Sending HTTP request POST https://homegraph.googleapis.com/v1/devices:reportStateAndNotification [13:02:52 INF] MQTT message received for topic homie/livingroom-hts/kodi/activityState: STANDBY [13:02:52 INF] Start processing HTTP request POST https://oauth2.googleapis.com/token [13:02:52 INF] Sending HTTP request POST https://oauth2.googleapis.com/token [13:02:52 INF] Received HTTP response headers after 14.5699ms - 200 [13:02:52 INF] End processing HTTP request after 15.3058ms - 200 [13:02:52 INF] Start processing HTTP request POST https://homegraph.googleapis.com/v1/devices:reportStateAndNotification [13:02:52 INF] Sending HTTP request POST https://homegraph.googleapis.com/v1/devices:reportStateAndNotification [13:02:52 INF] Received HTTP response headers after 471.3228ms - 200 [13:02:52 INF] End processing HTTP request after 472.2443ms - 200 [13:02:52 INF] Google Home Graph updated for devices: livingroom/kodi [13:02:52 INF] Received HTTP response headers after 475.7044ms - 200 [13:02:52 INF] End processing HTTP request after 476.7338ms - 200 [13:02:52 INF] Google Home Graph updated for devices: livingroom/kodi [13:02:59 INF] Request starting HTTP/1.1 POST http://192.168.1.104:5000/google/home/smarthome application/json;charset=UTF-8 135 [13:02:59 INF] Successfully validated the token. [13:02:59 INF] Authorization was successful. [13:02:59 INF] Executing endpoint 'HomeAutio.Mqtt.GoogleHome.Controllers.GoogleHomeController.Post (HomeAutio.Mqtt.GoogleHome)' [13:02:59 INF] Route matched with {action = "Post", controller = "GoogleHome"}. Executing controller action with signature Microsoft.AspNetCore.Mvc.IActionResult Post(HomeAutio.Mqtt.GoogleHome.

Yes, log that one as a separate issue.

Thank you for the other ones. I'm going to need to work on those a bit.

I am pushing a new version with validation for command / state properties turned off for now. You have presented enough evidence that my scheme doesn't really work for that, and generating transformed validation schemas from Google's is proving more difficult than I'd hoped. This should at least let you get back to working, even though it means we'll lose the validation safety net for a while.

Attribute validation, GoogleType derivation, examples, and command result / state segregation are still all big wins for 2.0. I just have to determine a better way of using these schema files.

Also I should have fixed your other issue here with the mediaState EXECUTE.

Try 2.0.0.161.

Also a note, for your thermostat state it looks like Google supports thermostatTemperatureSetpoint OR thermostatTemperatureSetpointLow and thermostatTemperatureSetpointHigh, but not used together like you have. It looks like they want you to choose one or the other.

Thanks I am no longer getting the mediaState execute error.
I am aware that I have a few that "don't" go together but have trusted their validator page to flag any errors. My understanding that thermostatTemperatureSetpoint and thermostatTemperatureSetpointLow/High can be combined, but now and then they like to change something and other times their developer pages are not clear or out of date. Proudly rocking No errors found ;)

Im going by Google's state schemas that specify that. Im not sure if they are actively using that to validate SYNC examples or not (gonna say NOT since you aren't getting an error). Just something I noticed when I was looking at your examples above. Google's docs definitely leave something to be desired, but they have begun generating some of the trait docs from these schema files, and it does say "The payload contains one of the following" instead of "any of the following" about these two options.

If they DO support both modes of operation at the same time in practice, it might be worth mentioning it to them in an issue on the schema repo. It could be a mistake where they MEANT AnyOf.

I'll log it tomorrow.

Closing out as original issues are all addressed at this point. Reopen if I missed something.

Ill be addressing adding validation back in at a later date.