private async Task OnMessage(string msg, CancellationToken ct) { if (!msg.IsValidJson(out var json)) { return; } var message = new WebSocketMessage(json); switch (message.MessageType) { case "auth_required": LogInfo("Authorization requested. Sending access token..."); await SendWs(new AuthCommand(_accessToken), ct); return; case "auth_ok": LogInfo("Authorization completed, subscribing to events..."); await SubscribeToEvents(ct); return; case "result": // Isn't an event, log and exit. LogDebug($"Result message: {msg.ToPrettyJson()}"); return; case "event": break; // continue processing default: { // Isn't an event! And event's are what we're working with. LogWarn($"Unsupported message (not an 'event'): {msg.ToPrettyJson()}"); return; } } var entId = message.EventEntityId; var matchedApps = _apps .Where(a => a.MatchEntity(entId)) .ToArray(); if (!matchedApps.Any()) { // No matched apps, log and exit. if (EncounteredEntityIdsWithoutSubscription.Add(entId)) { LogTrace($"First time encounter of message with an EntityId that we're not listening on: {entId}"); } return; } // Found matched apps! Log and determine which type LogInfo(msg.ToPrettyJson()); Click clickData = null; StateChanged stateChangedData = null; var eventType = message.EventType; switch (eventType) { case "click": { clickData = new Click { ClickType = (string)json["event"]["data"]["click_type"] }; break; } case "state_changed": { //entity_boolean doesn't have a "last_triggered" attribute. //if (!entId.Contains("input_boolean.")) //{ // if (!message.HasNewStateWithLastTriggered) // { // return; // Irrelevant event, we need new states that has "last time triggered" otherwise it might be an event provoked by reloading Hass. Unsure about this. // } //} if (!message.IsTheMostRelevantStateChangeEvent) { return; // Is most probably a 'duped' event, throw it away .. } if (!message.HasNewState) { return; // Irrelevant event, we need new states only .. } stateChangedData = message.DeserializeStateChanged(); break; } } var eventData = new EventData(entId, stateChangedData, clickData, msg); foreach (var hassApp in matchedApps) { hassApp.DispatchEvent(eventData); } }