コード例 #1
0
        /// <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}");
            }
        }
コード例 #2
0
        /// <summary>
        /// Enqueue message thread safe
        /// </summary>
        /// <param name="message"></param>
        internal void AddMessageToQueue(SinricMessage message)
        {
            var payloadJson = JsonConvert.SerializeObject(message.Payload);

            message.RawPayload = new JRaw(payloadJson);

            // compute the signature using our secret key so that the service can verify authenticity
            message.Signature.Hmac = HmacSignature.Signature(payloadJson, SecretKey);

            OutgoingMessages.Enqueue(message);
            Debug.Print("Queued websocket message for sending");
        }
コード例 #3
0
 /// <summary>
 /// Send message immediately
 /// </summary>
 /// <param name="message"></param>
 private void SendMessage(SinricMessage message)
 {
     try
     {
         // serialize the message to json
         var json = JsonConvert.SerializeObject(message);
         WebSocket.Send(json);
         Debug.Print("Websocket message sent:\n" + json + "\n");
     }
     catch (Exception ex)
     {
         Debug.Print("Websocket send exception: " + ex);
     }
 }
コード例 #4
0
        /// <summary>
        /// Creates a new  message with base information filled in for contacting the server.
        /// The caller must add remaining info & sign the message for it to be valid.
        /// </summary>
        /// <returns>A newly generated message will be returned</returns>
        internal SinricMessage NewMessage(string messageType)
        {
            var message = new SinricMessage
            {
                TimestampUtc = DateTime.UtcNow,
                Payload      =
                {
                    DeviceId     = DeviceId,
                    CreatedAtUtc = DateTime.UtcNow,
                    ReplyToken   = Guid.NewGuid().ToString(),
                    Type         = messageType,
                    Success      = SinricPayload.Result.Success
                }
            };

            return(message);
        }
コード例 #5
0
        internal static bool ValidateMessageSignature(SinricMessage message, string secretKey)
        {
            var payloadString = message.RawPayload?.Value as string;

            if (!string.IsNullOrEmpty(payloadString))
            {
                // if the message contains a payload then we need to validate its signature

                // todo validate timestamp of message, must be within X seconds of local clock, and must be > than the last message time received to protect against replay attacks

                // compute a local signature from the raw payload using our secret key:
                var signature = HmacSignature.Signature(payloadString, secretKey);

                // compare the locally computed signature with the one supplied in the message:
                return(signature == message.Signature.Hmac);
            }

            return(true);
        }
コード例 #6
0
        /// <summary>
        /// Given a message, creates a valid response with predetermined defaults filled in.
        /// The caller must add remaining info & sign the message for it to be valid.
        /// </summary>
        /// <param name="message">The message being replied to</param>
        /// <param name="result"></param>
        /// <returns>A newly generated message containing the reply details will be returned</returns>
        internal static SinricMessage CreateReplyMessage(SinricMessage message, bool result = SinricPayload.Result.Fail)
        {
            var reply = new SinricMessage
            {
                TimestampUtc = DateTime.UtcNow,
                Payload      =
                {
                    CreatedAtUtc = DateTime.UtcNow,
                    Type         = SinricPayload.MessageType.Response,
                    Message      = SinricPayload.Messages.Ok,
                    DeviceId     = message.Payload.DeviceId,
                    ReplyToken   = message.Payload.ReplyToken,
                    Action       = message.Payload.Action,
                    Success      = result,
                }
            };

            return(reply);
        }