///////////////////////////////////////////////////////////////////////////////////////////
 /// <summary>
 /// Writes the opc tag value to the server syncronously
 /// </summary>
 /// <param name="tag"></param>
 /// <returns></returns>
 ///////////////////////////////////////////////////////////////////////////////////////////
 private void SyncWrite(OPCTag tag)
 {
     try {
         Array serverErrors = default(Array);
         Array serverHandles = new int[2];
         serverHandles.SetValue((int)tag.OPCItem.ServerHandle, 1);
         Array values = GetValue(tag);
         tag.OPCGroup.SyncWrite(1, ref serverHandles, ref values, out serverErrors);
         HandleServerError(serverErrors);
     } catch (Exception ex) {
         //Excpetion event
     }
 }
        ///////////////////////////////////////////////////////////////////////////////////////////
        /// <summary>
        /// Writes the opc tag value to the server asyncronously
        /// </summary>
        /// <param name="tag"></param>
        /// <returns></returns>
        ///////////////////////////////////////////////////////////////////////////////////////////
        private void AsyncWrite(OPCTag tag)
        {
            try {
                Array serverErrors = default(Array);
                Array serverHandles = new int[2];
                serverHandles.SetValue((int)tag.OPCItem.ServerHandle, 1);
                Array values = GetValue(tag);

                int cancelID;
                int transID = GetNextTransID();
                tag.OPCGroup.AsyncWrite(1, ref serverHandles, ref values, out serverErrors, transID, out cancelID);
                mAcyncWriteTags.Add(transID, tag);

                HandleServerError(serverErrors);
            } catch (Exception ex) {
                //Exception EVent
            }
        }
 ///////////////////////////////////////////////////////////////////////////////////////////////
 /// <summary>
 /// Converts the tag value to an array for writing to the OPC Server
 /// </summary>
 /// <param name="tag"></param>
 /// <returns></returns>
 ///////////////////////////////////////////////////////////////////////////////////////////////
 private Array GetValue(OPCTag tag)
 {
     Array values = new object[2];
     switch (tag.BaseTag.DataType) {
         case DataType.Bool:
             values.SetValue(Convert.ToBoolean(tag.Value), 1);
             break;
         case DataType.Byte:
             values.SetValue(Convert.ToByte(tag.Value), 1);
             break;
         case DataType.Int16:
             values.SetValue(Convert.ToInt16(tag.Value), 1);
             break;
         case DataType.Int32:
             values.SetValue(Convert.ToInt32(tag.Value), 1);
             break;
         case DataType.Int64:
             values.SetValue(Convert.ToInt64(tag.Value), 1);
             break;
         case DataType.UInt16:
             values.SetValue(Convert.ToUInt16(tag.Value), 1);
             break;
         case DataType.UInt32:
             values.SetValue(Convert.ToUInt32(tag.Value), 1);
             break;
         case DataType.UInt64:
             values.SetValue(Convert.ToUInt64(tag.Value), 1);
             break;
         case DataType.Real32:
             values.SetValue(Convert.ToSingle(tag.Value), 1);
             break;
         case DataType.Real64:
             values.SetValue(Convert.ToDouble(tag.Value), 1);
             break;
         case DataType.String:
             values.SetValue(Convert.ToString(tag.Value), 1);
             break;
     }
     return values;
 }
        ///////////////////////////////////////////////////////////////////////////////////////////
        /// <summary>
        /// Adds a tag to the opc server
        /// </summary>
        /// <param name="tag"></param>
        ///////////////////////////////////////////////////////////////////////////////////////////
        public bool AddTag(Tag tag)
        {
            OPCTag opcTag = new OPCTag(tag);
            if (mTagsByName.ContainsKey(opcTag.Name)) return false;

            if ((tag.Direction & TagDirection.Output) == TagDirection.Output) {
                tag.TagChanged += new TagEventHandler(OnTagChanged);
            }

            //Add an OPC Group if the update time does not alread exist
            OPCGroup group = GetGroup(opcTag.UpdateTime);
            OPCItem item = group.OPCItems.AddItem(opcTag.Name, mTagsByName.Count + 1);
            opcTag.OPCItem = item;
            opcTag.OPCGroup = group;

            if (item != null) {
                //Save the opctag in a dictionary for quick lookup by name or by ClientHandle
                mTagsByName.Add(opcTag.Name, opcTag);
                mTagsByHandle.Add(item.ClientHandle, opcTag);
                return true;
            } else {
                return false;
            }
        }