public List <AlexaProperty> FindRelatedProperties(IPremiseObject endpoint, string currentController) { List <AlexaProperty> relatedProperties = new List <AlexaProperty>(); DiscoveryEndpoint discoveryEndpoint = PremiseServer.GetDiscoveryEndpointAsync(endpoint).GetAwaiter().GetResult(); if (discoveryEndpoint == null) { return(relatedProperties); } foreach (Capability capability in discoveryEndpoint.capabilities) { if (capability.@interface == currentController) { continue; } if (PremiseServer.Controllers.ContainsKey(capability.@interface)) { IAlexaController controller = PremiseServer.Controllers[capability.@interface]; controller.SetEndpoint(endpoint); relatedProperties.AddRange(controller.GetPropertyStates()); } } return(relatedProperties); }
public Dictionary <string, IPremiseSubscription> SubscribeToSupportedProperties(IPremiseObject endpoint, DiscoveryEndpoint discoveryEndpoint, Action <dynamic> callback) { Dictionary <string, IPremiseSubscription> subscriptions = new Dictionary <string, IPremiseSubscription>(); foreach (Capability capability in discoveryEndpoint.capabilities) { if (capability.HasProperties() == false) { continue; } if (!capability.properties.proactivelyReported) { continue; } IAlexaController controller = null; switch (capability.@interface) { case "Alexa.ChannelController": controller = new AlexaChannelController(); break; case "Alexa.InputController": controller = new AlexaInputController(); break; case "Alexa.PlaybackController": controller = new AlexaPlaybackController(); break; case "Alexa.Speaker": controller = new AlexaSpeaker(); break; } if (controller == null) { continue; } foreach (string premiseProperty in controller.GetPremiseProperties()) { string index = discoveryEndpoint.endpointId + $".{premiseProperty}." + capability.@interface; if (subscriptions.ContainsKey(index)) { continue; } IPremiseSubscription subscription = endpoint.SubscribeAsync(premiseProperty, GetType().AssemblyQualifiedName, callback).GetAwaiter().GetResult(); if (subscription != null) { subscriptions.Add(index, subscription); } } } return(subscriptions); }
public static void AlexaPropertyChanged(dynamic @params) { Subscription sub = (Subscription)@params; using (deDupeLock.Lock()) { // Premise can send multiple notifications for a single object, one for each // subscribed property that changes. The state report function here will capture // states of all properties, so the DeDupeDictionary prevents multiple state reports // from being sent for essentially the same event. if (DeDupeDictionary.ContainsKey(sub.sysObjectId)) { return; } DeDupeDictionary.Add(sub.sysObjectId, sub); } Task.Run(() => { // get the endpoint and endpoint capabilities Guid premiseId = new Guid(sub.sysObjectId); IPremiseObject endpoint = HomeObject.GetObjectAsync(premiseId.ToString("B")).GetAwaiter().GetResult(); if (!endpoint.IsValidObject()) { return; } DiscoveryEndpoint discoveryEndpoint = GetDiscoveryEndpointAsync(endpoint).GetAwaiter().GetResult(); if (discoveryEndpoint == null) { return; } // get the authorization code for the notification string authCode; using (asyncObjectsLock.Lock()) { authCode = (string)HomeObject.GetValueAsync("AlexaAsyncAuthorizationCode").GetAwaiter().GetResult(); } // build the change report AlexaChangeReport changeReport = new AlexaChangeReport(); [email protected] = Guid.NewGuid().ToString("D"); [email protected].@namespace = "Alexa"; [email protected] = "3"; [email protected] = "BearerToken"; [email protected] = authCode; [email protected] = premiseId.ToString("D").ToUpper(); [email protected] = discoveryEndpoint.cookie; [email protected] = "PHYSICAL_INTERACTION"; // get the device type and controller (e.g. AlexaAV, AlexaHVAC) IAlexaDeviceType deviceType = null; IAlexaController controller = null; List <AlexaProperty> relatedPropertyStates = null; bool hasScene = false; foreach (IAlexaController controllerToTest in Controllers.Values) { if (!controllerToTest.HasPremiseProperty(sub.propertyName)) { continue; } controller = controllerToTest; Type type = Type.GetType(controller.GetAssemblyTypeName()); if (type == null) { continue; } // found a controller, get an instance of the assembly deviceType = (IAlexaDeviceType)Activator.CreateInstance(type); // Determine if this deviceType supports the desired capability // note: This handles situation where the same property name is used by different // controllers. e.g. "brightness" is used in both ColorController and BrightnessController relatedPropertyStates = deviceType.FindRelatedProperties(endpoint, ""); foreach (AlexaProperty property in relatedPropertyStates) { // if so, this is the correct type if (property.@namespace == controller.GetNameSpace()) { break; } } } // ReSharper disable once ConditionIsAlwaysTrueOrFalse if ((deviceType == null) || (controller == null || relatedPropertyStates == null)) { return; } foreach (AlexaProperty prop in relatedPropertyStates) { if (prop.@namespace == "Alexa.SceneController") { hasScene = true; continue; } if (([email protected] == 0) && (prop.name == controller.MapPremisePropertyToAlexaProperty(sub.propertyName))) { [email protected](prop); } else { string propKey = prop.@namespace + "." + prop.name; changeReport.context.propertiesInternal.Add(propKey, prop); } } [email protected] = "ChangeReport"; // scenes are special case if (hasScene) { AlexaSetSceneController sceneController = new AlexaSetSceneController(endpoint); changeReport = sceneController.AlterChangeReport(changeReport); } StateChangeReportWrapper item = new StateChangeReportWrapper { ChangeReport = changeReport }; stateReportQueue.Enqueue(item); using (deDupeLock.Lock()) { DeDupeDictionary.Remove(sub.sysObjectId); } }); }