/// <summary>
        /// Write generic property with optional auto flag.
        /// </summary>
        private static void WriteProperty(Device device, CameraProperty property)
        {
            if (property.ReadOnly)
            {
                return;
            }

            NodeMap nodeMap = device.RemoteNodeList;

            // Switch OFF the auto flag if needed, to be able to write the main property.
            if (!string.IsNullOrEmpty(property.AutomaticIdentifier))
            {
                Node nodeAuto = BaumerHelper.GetNode(nodeMap, property.AutomaticIdentifier);
                if (nodeAuto != null)
                {
                    bool writeable   = nodeAuto.IsWriteable;
                    bool currentAuto = ReadAuto(nodeAuto, property.AutomaticIdentifier);
                    if (writeable && property.CanBeAutomatic && currentAuto && !property.Automatic)
                    {
                        WriteAuto(nodeAuto, property.AutomaticIdentifier, false);
                    }
                }
            }

            // At this point the auto flag is off. Write the main property.
            Node node = BaumerHelper.GetNode(nodeMap, property.Identifier);

            if (node == null)
            {
                return;
            }

            if (!node.IsReadable || !node.IsWriteable)
            {
                return;
            }

            try
            {
                switch (property.Type)
                {
                case CameraPropertyType.Integer:
                {
                    long value = long.Parse(property.CurrentValue, CultureInfo.InvariantCulture);
                    long min   = node.Min;
                    long max   = node.Max;
                    long step  = node.Inc;
                    value      = FixValue(value, min, max, step);
                    node.Value = value;
                    break;
                }

                case CameraPropertyType.Float:
                {
                    double value = double.Parse(property.CurrentValue, CultureInfo.InvariantCulture);
                    double min   = node.Min;
                    double max   = node.Max;
                    value      = FixValue(value, min, max);
                    node.Value = value;
                    break;
                }

                case CameraPropertyType.Boolean:
                {
                    bool value = bool.Parse(property.CurrentValue);
                    node.Value = value;
                    break;
                }

                default:
                    break;
                }
            }
            catch
            {
                log.ErrorFormat("Error while writing Baumer GenICam property {0}.", property.Identifier);
            }

            // Finally, switch ON the auto flag if needed.
            if (!string.IsNullOrEmpty(property.AutomaticIdentifier))
            {
                Node nodeAuto = BaumerHelper.GetNode(nodeMap, property.AutomaticIdentifier);
                if (nodeAuto != null && nodeAuto.IsWriteable && property.CanBeAutomatic && property.Automatic)
                {
                    WriteAuto(nodeAuto, property.AutomaticIdentifier, true);
                }
            }
        }
        /// <summary>
        /// Write either width or height as a centered region of interest.
        /// </summary>
        private static void WriteSize(Device device, CameraProperty property, string identifierOffset)
        {
            if (property.ReadOnly)
            {
                return;
            }

            NodeMap nodemap = device.RemoteNodeList;
            Node    node    = BaumerHelper.GetNode(nodemap, property.Identifier);

            if (node == null || !node.IsReadable || !node.IsWriteable)
            {
                return;
            }

            long value = long.Parse(property.CurrentValue, CultureInfo.InvariantCulture);
            long min   = node.Min;
            long step  = node.Inc;

            // Do not clamp on max, the max is based on the offset instead of the true max.
            value = Math.Max(value, min);
            long remainder = (value - min) % step;

            if (remainder != 0)
            {
                value = value - remainder + step;
            }

            // Offset handling.
            // Some cameras have a CenterX/CenterY property.
            // When it is set, the offset is automatic and becomes read-only.
            // If the offset can be written we use the normal computation.
            Node nodeOffset = BaumerHelper.GetNode(nodemap, identifierOffset);
            bool setOffset  = nodeOffset != null && node.IsReadable && node.IsWriteable;

            if (setOffset)
            {
                long currentValue = node.Value;
                long max          = currentValue + nodeOffset.Max;
                long offset       = (max - value) / 2;
                long minOffset    = nodeOffset.Min;
                long stepOffset   = nodeOffset.Inc;

                long remainderOffset = (offset - minOffset) % stepOffset;
                if (remainderOffset != 0)
                {
                    offset = offset - remainderOffset + stepOffset;
                }

                // We need to be careful with the order and not write a value that doesn't fit due to the offset, or vice versa.
                if (value > currentValue)
                {
                    nodeOffset.Value = offset;
                    node.Value       = value;
                }
                else
                {
                    node.Value       = value;
                    nodeOffset.Value = offset;
                }
            }
            else
            {
                node.Value = value;
            }
        }