/// <summary>
        /// Send a message.
        /// </summary>
        /// <param name="controller">Concerned controller.</param>
        /// <param name="message">Message to send.</param>
        internal static bool Send(ControllerDto controller, MessageToDto message)
        {
            // get serial message
            MessageDto serialMessage;
            using (var ctx = new MessageProcessDtoFactory())
            {
                serialMessage = ctx.Convert(message);
            }

            // wait for sending turn & request process
            Queue.WaitMessageSending.WaitOne(DeviceConstants.WaitEventTimeout);
            Queue.WaitMessageReception.WaitOne(DeviceConstants.WaitEventTimeout);

            // set processed message
            Queue.MessageTo = message;

            // send message
            var result = PortBusiness.Send(Queue.Controller.Port, serialMessage);

            Queue.WaitMessageReception.Set();

            // wait round time trip
            Thread.Sleep(MessageConstants.WaitForRoundTimeTrip);
            return result;
        }
        /// <summary>
        /// Create message for serial port.
        /// </summary>
        /// <param name="message">Message.</param>
        /// <returns>Message frame.</returns>
        public MessageDto Convert(MessageToDto message)
        {
            var content = CreateFrame(message);
            var result = new MessageDto
            {
                Header = (MessageHeader)content[0],
                Content = content,
                IsComplete = true,
                Size = content.Count
            };

            return result;
        }
        /// <summary>
        /// Create a command message.
        /// </summary>
        /// <param name="node">Concerned node.</param>
        /// <param name="content">Content to send.</param>
        /// <returns>Message.</returns>
        private static MessageToDto CreateCommandMessage(DeviceDto node, List<byte> content)
        {
            var result = new MessageToDto
            {
                Command = MessageCommand.SendData,
                Content = new List<byte> { (byte)RequestCommandClass.Configuration },
                IsConfiguration = true,
                IsValid = true,
                Node = node,
                Type = MessageType.Request,
                ZIdentifier = node.ZIdentifier
            };

            // fill content
            result.Content.AddRange(content);
            result.Content.Insert(0, (byte)result.Content.Count);

            return result;
        }
        /// <summary>
        /// Create a command message.
        /// </summary>
        /// <param name="controller">Contextual node of the message.</param>
        /// <param name="command">Command to process.</param>
        /// <param name="zId">Node identifier to send in message. 0x00 if no node is concerned.</param>
        /// <returns>Message.</returns>
        private static MessageToDto CreateCommandMessage(MessageCommand command, DeviceDto controller, int zId = 0)
        {
            var result = new MessageToDto
            {
                Command = command,
                IsValid = true,
                Node = controller,
                ZIdentifier = (byte)zId,
                Type = MessageType.Request,
            };

            return result;
        }
        /// <summary>
        /// Create a command message.
        /// </summary>
        /// <param name="controller">Contextual node of the message.</param>
        /// <param name="zId">Node identifier to send in message. 0x00 if no node is concerned.</param>
        /// <returns>Message.</returns>
        private static MessageToDto CreateCommandMessage(DeviceDto controller, int zId)
        {
            var result = new MessageToDto
            {
                Command = MessageCommand.SendData,
                IsValid = true,
                Node = controller,
                ZIdentifier = (byte)zId,
                Type = MessageType.Request,
                Content = new List<byte> { 0x02, (byte)RequestCommandClass.Constructor, (byte)ConstructorAction.Get },

                IsConstructor = true
            };

            return result;
        }
        /// <summary>
        /// Create raw frame.
        /// </summary>
        /// <param name="message">Original message.</param>
        /// <returns>Message.</returns>
        private static List<byte> CreateFrame(MessageToDto message)
        {
            var result = new List<byte>
            {
                (byte) MessageHeader.StartOfFrame,
                0,
                (byte) message.Type,
                (byte) message.Command
            };

            if (message.ZIdentifier != 0)
            {
                result.Add((byte)message.ZIdentifier);
            }

            result.AddRange(message.Content);
            result.Add((byte)(TransmitOptions.Acknowlegment | TransmitOptions.Explore | TransmitOptions.NoRoute));
            result[1] = (byte)(result.Count - 1);
            result.Add(GenerateChecksum(result));

            return result;
        }