private bool PublishObservationMessage(int observationId, byte[] bytes)
 {
     if (UseAtomicTransactions && _transactionOpen)
     {
         throw new ArgumentException("Unable to use atomic transactions when object has an open transaction.");
     }
     if (IsConnected())
     {
         string           routingKey = MessageRoutingKey.GenerateDeviceObservationRoutingKey(_MID, observationId);
         IBasicProperties properties = GetMessageProperties(1);
         try
         {
             lock (_modelLock)
             {
                 _model.BasicPublish(_rmqExchangeName, routingKey, true, properties, bytes);
             }
             return(true);
         }
         catch (Exception e)
         {
             LastErrorMessage = e.Message;
         }
     }
     return(false);
 }
 bool Dispatch(string routingKey, IDictionary <string, object> headers, byte[] body, ulong deliveryTag)
 {
     if (routingKey != null && routingKey.Length > 0)
     {
         string MID = MessageRoutingKey.ParseMID(routingKey);
         if (MID == _MID && body != null && body.Length > 0)
         {
             if (MessageRoutingKey.IsDeviceCommand(routingKey))
             {
                 string  json    = Encoding.UTF8.GetString(body);
                 Command command = JsonConvert.DeserializeObject <Command>(json);
                 CommandSubscription <Command> cs = _commandSubscriptions.Find(s => s.CommandId == command.Id);
                 if (cs != null)
                 {
                     cs.CommandHandler(MID, command);
                     lock (_modelLock)
                     {
                         _model.BasicAck(deliveryTag, false);
                     }
                     return(true);
                 }
             }
             else if (MessageRoutingKey.IsApplicationPulse(routingKey))
             {
                 string            json  = Encoding.UTF8.GetString(body);
                 Pulse             pulse = JsonConvert.DeserializeObject <Pulse>(json);
                 PulseSubscription ps    = _pulseSubscriptions.Find(s => s.PulseId == pulse.PulseId);
                 if (ps != null)
                 {
                     ps.PulseHandler(MID, pulse.PulseId, pulse);
                     lock (_modelLock)
                     {
                         _model.BasicAck(deliveryTag, false);
                     }
                     return(true);
                 }
             }
         }
         lock (_modelLock)
         {
             _model.BasicNack(deliveryTag, false, false);
         }
     }
     return(false);
 }
        /// <summary>
        /// Sends a device pulse to the server.
        /// </summary>
        /// <param name="timestamp">Timestamp in UTC indicating the time of the pulse. null for current time.</param>
        /// <returns>True if successful, False otherwise.</returns>
        public bool SendPulse(DateTime?timestamp, int expiryMilliseconds = 300000)
        {
            if (UseAtomicTransactions && _transactionOpen)
            {
                throw new ArgumentException("Unable to use atomic transactions when object has an open transaction.");
            }
            if (IsConnected())
            {
                if (!timestamp.HasValue)
                {
                    timestamp = DateTime.UtcNow;
                }

                Pulse pulse = new Pulse()
                {
                    Timestamp = timestamp.Value,
                    MID       = _MID,
                    PulseId   = 0 // Devices must always use PulseId = 0
                };

                IBasicProperties properties = GetMessageProperties(1);
                if (expiryMilliseconds > 0)
                {
                    properties.Expiration = expiryMilliseconds.ToString("F0");
                }
                string routingKey = MessageRoutingKey.GeneratePulseRoutingKey(pulse.MID);
                string json       = JsonConvert.SerializeObject(pulse);
                byte[] body       = Encoding.UTF8.GetBytes(json);
                try
                {
                    lock (_modelLock)
                    {
                        _model.BasicPublish(_rmqExchangeName, routingKey, true, properties, body);
                    }
                    return(true);
                }
                catch (Exception e)
                {
                    LastErrorMessage = e.Message;
                }
            }
            return(false);
        }
        /// <summary>
        /// Return command response to server.
        /// </summary>
        /// <param name="command">Command object to respond to.</param>
        /// <param name="wasAccepted">True if command was accepted, False otherwise.</param>
        /// <param name="timestamp">Timestamp in UTC when command was accepted. null for current time (optional).</param>
        /// <param name="resultCode">Integer describing result of command execution (optional).</param>
        /// <param name="comment">Text field of up to 1024 characters for additional free text information (optional).</param>
        /// <returns>True if successful, False otherwise.</returns>
        public bool PublishCommandResponse(Command command, Boolean wasAccepted = true, DateTime?timestamp = null, int?resultCode = null, string comment = null)
        {
            if (UseAtomicTransactions && _transactionOpen)
            {
                throw new ArgumentException("Unable to use atomic transactions when object has an open transaction.");
            }
            if (IsConnected())
            {
                if (!timestamp.HasValue)
                {
                    timestamp = DateTime.UtcNow;
                }

                CommandResponse response = new CommandResponse()
                {
                    Id          = command.Id,
                    Timestamp   = command.Timestamp,
                    DeliveredAt = timestamp,
                    WasAccepted = wasAccepted,
                    ResultCode  = resultCode,
                    Comment     = comment
                };
                IBasicProperties properties = GetMessageProperties(2);
                string           routingKey = MessageRoutingKey.GenerateDeviceCommandResponseRoutingKey(_MID, command.Id, command.Timestamp);
                string           json       = JsonConvert.SerializeObject(response);
                byte[]           body       = Encoding.UTF8.GetBytes(json);
                try
                {
                    lock (_modelLock)
                    {
                        _model.BasicPublish(_rmqExchangeName, routingKey, true, properties, body);
                    }
                    return(true);
                }
                catch (Exception e)
                {
                    LastErrorMessage = e.Message;
                }
            }
            return(false);
        }