/// <summary>
        /// Called when receiving a message from the server
        /// </summary>
        /// <param name="message">Message from server</param>
        /// <param name="reply">Pre-generated reply message template. Modify it to indicate the result.</param>
        internal virtual void MessageReceived(SinricMessage message, SinricMessage reply)
        {
            Debug.Print($"Sensor {Name} of type {Type} received action: {message.Payload.Action}");

            // what action is being requested?
            ActionStateEnums.TryGetValue(message.Payload.Action, out var enumType);

            // handle a state change if a known/supported enum
            if (enumType != null)
            {
                BasicState.TryGetValue(message.Payload.Action, out var currentState);

                // state that the server is trying to set:
                var newState = message.Payload.GetValue <string>(SinricValue.State);

                var genericType          = typeof(BasicStateChangeInfo <>);
                var boundType            = genericType.MakeGenericType(enumType);
                var basicStateChangeInfo = (BasicStateChangeInfo)Activator.CreateInstance(boundType);

                //ActionType = actionStateEnum,
                basicStateChangeInfo.Action   = message.Payload.Action;
                basicStateChangeInfo.Device   = this;
                basicStateChangeInfo.OldState = currentState;
                basicStateChangeInfo.NewState = newState;
                basicStateChangeInfo.Success  = true;

                // look up the enum value by the receive description attribute
                var enumValues = Enum.GetValues(enumType).Cast <object>();
                var enumValue  = enumValues.FirstOrDefault(e => SinricMessageAttribute.Get(e)?.ReceiveValue == newState);

                basicStateChangeInfo.ReceiveValue = newState;
                basicStateChangeInfo.SendValue    = SinricMessageAttribute.Get(enumValue).SendValue;

                // set the basicStateChangeInfo<T>.NewStateEnum field
                basicStateChangeInfo.GetType()
                .GetProperty("NewStateEnum", BindingFlags.Public | BindingFlags.Instance)
                ?.SetValue(basicStateChangeInfo, enumValue, null);

                // check if general handler is registered. call the handler and return the result
                Handlers.TryGetValue(message.Payload.Action, out var delegateFunc);
                var method = delegateFunc?.GetType().GetMethod("Invoke");
                method?.Invoke(delegateFunc, new object[] { basicStateChangeInfo });

                // check if conditional handler is registered. call the handler and return the result
                Handlers.TryGetValue(message.Payload.Action + ":" + newState, out var delegateFuncConditional);
                method?.Invoke(delegateFuncConditional, new object[] { basicStateChangeInfo });

                // reply with the result
                reply.Payload.SetState(basicStateChangeInfo.SendValue);
                reply.Payload.Success = basicStateChangeInfo.Success;

                Debug.Print($"Sensor {Name} of type {Type} reply was: {basicStateChangeInfo.NewState}, success: {basicStateChangeInfo.Success}");
            }
        }
        public string SetLocalState <T>(T stateEnumValue) where T : Enum
        {
            // newState will be the description of the enum value, ie. open or closed
            var actionVerb = SinricActionAttribute.GetActionVerb(typeof(T));
            var newState   = SinricMessageAttribute.Get(stateEnumValue).SendValue;

            // set local state
            BasicState[actionVerb] = newState;

            return(newState);
        }
        public void SetHandler <T>(T conditionState, Action <BasicStateChangeInfo <T> > actionDelegate)
        {
            var actionVerb = SinricActionAttribute.GetActionVerb(typeof(T));

            Handlers[actionVerb + ":" + SinricMessageAttribute.Get(conditionState).ReceiveValue] = actionDelegate;
        }