/// <summary>
        /// Process our data
        /// </summary>
        /// <param name="state"></param>
        private static void ProcessData(object state)
        {
            object[] InVals     = (object[])state;
            String[] InLines    = (string[])InVals[0];
            Type     TargetType = (Type)InVals[1];

            PropertyInfo[] HeaderInfo = (PropertyInfo[])InVals[2];
            try
            {
                if (TargetType != null)
                {
                    Array OutList = Array.CreateInstance(TargetType, InLines.Length);
                    for (int a = 0; a < InLines.Length; a++)
                    {
                        OutList.SetValue(MM_Serialization.Deserialize(HeaderInfo, InLines[a].Split(','), Activator.CreateInstance(TargetType)), a);
                    }
                    MM_EMS_Data_Updater.ProcessUpdate(TargetType, OutList);
                    OutList = null;
                }
            }
            catch (Exception ex)
            {
                MM_Notification.WriteLine(ConsoleColor.Red, "Error sending {0} data: {1}", (TargetType == null ? "UNKNOWN" : TargetType.Name), ex);
            }
        }
 /// <summary>
 /// Send our message internally
 /// </summary>
 /// <param name="SystemGuid"></param>
 /// <param name="ProcedureName"></param>
 /// <param name="Parameters"></param>
 private static void SendMessageInternal(MethodInfo Method, MM_WCF_Interface FoundConnection, object[] parameters)
 {
     try
     {
         Method.Invoke(FoundConnection.ConversationHandler, parameters);
     }
     catch (Exception ex)
     {
         MM_Notification.WriteLine(ConsoleColor.Red, "Error sending {0} to {1}: {2}", Method.Name, FoundConnection.User.UserName, ex.Message);
     }
 }
 /// <summary>
 /// Send our message internally
 /// </summary>
 /// <param name="SystemGuid"></param>
 /// <param name="ProcedureName"></param>
 /// <param name="Parameters"></param>
 private static void SendMessageInternal(MethodInfo Method, MM_Administrator_Types FoundConnection, object[] parameters)
 {
     try
     {
         Method.Invoke(FoundConnection.ConversationHandler, parameters);
     }
     catch (Exception ex)
     {
         MM_Notification.WriteLine(ConsoleColor.Red, "Error sending {0} to {1}: {2}", Method.Name, "ADMIN", ex.Message);
     }
 }
        /// <summary>
        /// Handle a client first connecting
        /// </summary>
        /// <returns></returns>
        public Guid RegisterApplicationStartup(String IPAddress, int Port, String MachineName)
        {
            MM_Notification.WriteLine(ConsoleColor.Cyan, "New connection from {0} {1} on port {2}", IPAddress, MachineName, Port);
            Guid UserGUID = Guid.NewGuid();

            this.User = new MM_User()
            {
                UserId = UserGUID, UserName = "******", LoggedOnTime = DateTime.Now, IPAddress = IPAddress, MachineName = MachineName, Port = Port, LastReceivedMessage = DateTime.Now
            };
            User.LastReceivedMessage = DateTime.Now;
            MM_Server.AddUser(this);
            return(UserGUID);
        }
        /// <summary>
        /// Handle a user login
        /// </summary>
        /// <param name="Name"></param>
        /// <param name="Password"></param>
        /// <param name="UserGuid"></param>
        /// <returns></returns>
        public string[] HandleUserLogin(string Name, string Password)
        {
            MM_Notification.WriteLine(ConsoleColor.Cyan, "User {0} attempting to log in from {1} on {2}", Name, User.IPAddress, DateTime.Now);
            User.UserName = Name;
            if (Settings.Default.AllowTestCredentials && Name == "**MacomberMapTesting**")
            {
                User.LoggedOnTime = DateTime.Now;
                User.ERCOTUser    = true;
                return(new string[] { "ERCOT" });
            }

            //Validate the user's credentials against active directory (thanks to http://stackoverflow.com/questions/290548/validate-a-username-and-password-against-active-directory)
            bool IsValid = false;

            try
            {
                using (PrincipalContext pc = new PrincipalContext(ContextType.Domain))
                    IsValid = pc.ValidateCredentials(Name, Password);
            }
            catch { }
            if (IsValid && Settings.Default.AcceptAllDomainUsers)
            {
                return new string[] { "ERCOT" }
            }
            ;

            if (!IsValid || !File.Exists(Properties.Settings.Default.LoginFileLocation))
            {
                MM_Notification.WriteLine(ConsoleColor.Red, "User {0} log on from {1} failed: invalid credentials or no PERMIT area file.", Name, User.IPAddress);

                return(new String[0]);
            }

            //Now, check against our user names
            foreach (String str in File.ReadAllLines(Properties.Settings.Default.LoginFileLocation))
            {
                if (str.StartsWith(Name + ",", StringComparison.CurrentCultureIgnoreCase))
                {
                    User.LoggedOnTime = DateTime.Now;
                    String[] PermissionAreas = str.Substring(str.IndexOf(',') + 1).Split(',');
                    User.ERCOTUser = PermissionAreas.Contains("ERCOT");
                    return(PermissionAreas);
                }
            }

            //We didn't find our user, so log out.
            MM_Notification.WriteLine(ConsoleColor.Red, "User {0} log on from {1} failed: not found in PERMIT area file.", Name, User.IPAddress);
            return(new string[0]);
        }
        /// <summary>
        /// Read our XML configuration file
        /// </summary>
        public static void DetermineFileTypes()
        {
            //Add in our list of file paths
            foreach (Type FoundType in typeof(MM_Line_Data).Assembly.GetTypes())
            {
                UpdateCommandAttribute    UpdateCommand    = null;
                RetrievalCommandAttribute RetrievalCommand = null;
                FileNameAttribute         FileName         = null;

                foreach (object obj in FoundType.GetCustomAttributes(false))
                {
                    if (obj is UpdateCommandAttribute)
                    {
                        UpdateCommand = (UpdateCommandAttribute)obj;
                    }
                    else if (obj is FileNameAttribute)
                    {
                        FileName = (FileNameAttribute)obj;
                    }
                    else if (obj is RetrievalCommandAttribute)
                    {
                        RetrievalCommand = (RetrievalCommandAttribute)obj;
                    }
                }

                if (UpdateCommand != null && FileName != null)
                {
                    MM_EMSReader_TCP.InputTypes.Add(FileName.FileName, FoundType);
                    MM_EMSReader_TCP.UpdateCommands.Add(FileName.FileName, UpdateCommand.UpdateCommand);
                    if (!String.IsNullOrEmpty(Settings.Default.TEDESourceFolder))
                    {
                        MM_EMSReader_File.FileInfo.Add(FileName.FileName, new MM_EMSReader_File(Path.Combine(Settings.Default.TEDESourceFolder, FileName.FileName), UpdateCommand.UpdateCommand, FoundType));
                    }
                }

                // FileInfo.Add(FileName.FileName, new MM_EMSReader_FileInformation(Path.Combine(Settings.Default.SourceFolder,FileName.FileName), UpdateCommand.UpdateCommand, FoundType));

                //Check our update command, make sure it's okay
                if (UpdateCommand != null && FileName != null && typeof(IMM_ConversationMessage_Types).GetMethod(UpdateCommand.UpdateCommand) == null)
                {
                    MM_Notification.WriteLine(ConsoleColor.Yellow, "Unable to find update command {0} for type {1}", UpdateCommand.UpdateCommand, FileName.FileName);
                }
                if (RetrievalCommand != null && FileName != null && typeof(IMM_EMS_Types).GetMethod(RetrievalCommand.RetrievalCommand) == null)
                {
                    MM_Notification.WriteLine(ConsoleColor.Yellow, "Unable to find retrieval command {0} for type {1}", RetrievalCommand.RetrievalCommand, FileName.FileName);
                }
            }
        }
        /// <summary>
        /// Retrieve our file, and create our output
        /// </summary>
        /// <returns></returns>
        public void ReadFileAndSendResults(object state)
        {
            while (true)
            {
                try
                {
                    //First, wait for our trigger. If we timed out, set it, so that our next run works properly.
                    bool TriggerTimeout = !ResetEvent.WaitOne(TimeSpan.FromSeconds(55));
                    //Thread.Sleep(250);

                    //Now, read our file
                    bool     Success    = false;
                    int      RetryCount = 0;
                    FileInfo fI         = new FileInfo(FileName);
                    if (fI.Exists && fI.Length > 0 && (fI.LastWriteTime != LastFileWrite || TriggerTimeout))
                    {
                        LastFileWrite = fI.LastWriteTime;
                        do
                        {
                            try
                            {
                                DateTime StartTime = DateTime.Now;
                                using (FileStream fS = WaitForFile(FileName, FileMode.Open, FileAccess.Read, FileShare.Read))
                                    if (fS != null)
                                    {
                                        using (StreamReader sRd = new StreamReader(fS, new UTF8Encoding(false)))
                                            ProcessStreamRead(sRd, FileName, TargetType, ref LatestBatchID);
                                    }

                                Success = true;
                            }
                            catch (Exception ex)
                            {
                                MM_Notification.WriteLine(ConsoleColor.Red, "Error reading {0}: {1}", FileName, ex.Message);
                                RetryCount++;
                            }
                        } while (!Success && RetryCount < 2);
                        fI = null;
                    }
                    ResetEvent.Reset();
                }
                catch (Exception ex2)
                {
                    MM_Notification.WriteLine(ConsoleColor.Red, "Thread for {0} shutting down: {1}", FileName, ex2);
                }
            }
        }
 /// <summary>
 /// Start our listener
 /// </summary>
 /// <param name="state"></param>
 private static void StartListener(object state)
 {
     Listener = new TcpListener(IPAddress.Any, Properties.Settings.Default.TCPListener);
     Listener.Start();
     MM_Notification.WriteLine(ConsoleColor.Green, "EMS: Listening for incoming TCP connections on {0}", Listener.LocalEndpoint);
     while (true)
     {
         try
         {
             ThreadPool.QueueUserWorkItem(new WaitCallback(ProcessTCPMessage), Listener.AcceptTcpClient());
         }
         catch (Exception ex)
         {
             MM_Notification.WriteLine(ConsoleColor.Red, "EMS: Unable to accept an incoming connection: {0}", ex);
         }
     }
 }
        /// <summary>
        /// Start our History listener
        /// </summary>
        /// <param name="state"></param>
        private static void StartHistoryListener(object state)
        {
            //Load our XML configuration, and start up our History server
            try
            {
                HistoryServer = MM_History_Server.FindServer(Settings.Default.HistoryServer);
                HistoryServer.Open();
                MM_Notification.WriteLine(ConsoleColor.Green, "History: Connected to History Server {0}", HistoryServer.Name);
            }
            catch (Exception ex)
            {
                MM_Notification.WriteLine(ConsoleColor.Red, "History: Unable to connect to History server: {0}", ex.ToString());
            }

            //Now, create our Historype and handle appropriately
            StartTime = DateTime.Now;
            while (true)
            {
                mreQueryReady.Reset();

                //Check whether there are any queries worth running and pruning
                int RanQueries = 0, PrunedQueries = 0;
                foreach (MM_Historic_Query Query in Queries.Values.ToArray())
                {
                    if (Query.State == MM_Historic_Query.enumQueryState.Queued)
                    {
                        Query.State = MM_Historic_Query.enumQueryState.InProgress;
                        RanQueries++;
                        ThreadPool.QueueUserWorkItem(new WaitCallback(RunQuery), Query);
                    }
                    else if (Query.State == MM_Historic_Query.enumQueryState.Retrieved)
                    {
                        PrunedQueries++;
                        Queries.Remove(Query.Id);
                    }
                }

                MM_Notification.WriteLine(ConsoleColor.Green, "History: Ran {0} queries, removed {1} queries.", RanQueries, PrunedQueries);

                mreQueryReady.WaitOne();
            }
        }
        /// <summary>
        /// Open our database connection
        /// </summary>
        private static void OpenDatabaseConnection()
        {
            String ConnectionParameter = Settings.Default.DatabaseConnectionString;

            if (!String.IsNullOrEmpty(Settings.Default.DatabaseEncryptedPassword))
            {
                ConnectionParameter = ConnectionParameter.Replace("[Password]", MM_Encryption.Decrypt(Settings.Default.DatabaseEncryptedPassword));
            }
            Assembly DatabaseAssembly = Assembly.Load(Settings.Default.DatabaseAssembly);

            oConn = (DbConnection)Activator.CreateInstance(DatabaseAssembly.GetType(Settings.Default.DatabaseConnectionType));
            oConn.ConnectionString = Settings.Default.DatabaseConnectionString;
            try
            {
                oConn.Open();
                MM_Notification.WriteLine(ConsoleColor.Green, "Database: Connected to {0} ({1}).", oConn.DataSource, oConn.ServerVersion);
            }
            catch (Exception ex)
            {
                MM_Notification.WriteLine(ConsoleColor.Red, "Database: Error connecting to {0}: {1}", oConn.DataSource, ex);
            }
        }
        /// <summary>
        /// Send a command
        /// </summary>
        /// <param name="Command"></param>
        /// <param name="OldValue"></param>
        /// <returns></returns>
        public bool SendCommand(string Command, String OldValue)
        {
            byte[]   OutBytes = new UTF8Encoding(false).GetBytes("#CMD_TYPE,APP,FAM,CMD_NAME,DB,RECORD,FIELD,TEID,VALUE" + Environment.NewLine + Command + Environment.NewLine);
            DateTime SimTime  = MM_Server.SimulatorTimeData.Length == 0 ? DateTime.Now : MM_Server.SimulatorTimeData[0].Simulation_Time;

            if (!String.IsNullOrEmpty(Settings.Default.OperatorCommandTCPAddress))
            {
                try
                {
                    using (TcpClient Client = new TcpClient())
                    {
                        Client.Connect(Settings.Default.OperatorCommandTCPAddress, Settings.Default.OperatorCommandTCPPort);
                        using (NetworkStream nS = Client.GetStream())
                            nS.Write(OutBytes, 0, OutBytes.Length);
                        MM_Notification.WriteLine(ConsoleColor.White, "Sent {1} command to TEDE/TCP: by {0} on {2}. SimTime {3}", User.UserName, Command, DateTime.Now, SimTime);
                        MM_Database_Connector.LogCommand(Command, User, "TCP");
                    }
                }
                catch (Exception ex)
                {
                    MM_Notification.WriteLine(ConsoleColor.Red, "Error sending {1} command to TEDE/TCP: by {0} on {2} SimTime {3}: {4} ", User.UserName, Command, DateTime.Now, SimTime, ex);
                    return(false);
                }
            }

            if (!String.IsNullOrEmpty(Properties.Settings.Default.OperatorCommandPath))
            {
                String[] splStr         = Command.TrimEnd(',').Split(',');
                String   TargetFileName = Path.Combine(Properties.Settings.Default.OperatorCommandPath, ((splStr[0].Equals("REFRESH")) ? "EMS_REFRESH_" : "EMS_COMMANDS_") + RandomGenerator.Next().ToString() + ".csv");
                using (FileStream fS = new FileStream(TargetFileName, FileMode.CreateNew, FileAccess.Write))
                    fS.Write(OutBytes, 0, OutBytes.Length);
                MM_Notification.WriteLine(ConsoleColor.White, "Sent {1} command to TEDE/File: by {0} on {2}. SimTime {3}", User.UserName, Command, DateTime.Now, SimTime);
                MM_Database_Connector.LogCommand(Command, User, "File");
            }

            //Now, write out our command
            MM_EMS_Command[] OutCommands = new MM_EMS_Command[] { new MM_EMS_Command(Command, User.UserName, User.MachineName, SimTime, OldValue) };
            try
            {
                List <String> OutLines = new List <string>();
                if (!File.Exists("EMSCommands.csv"))
                {
                    OutLines.Add(MM_EMS_Command.HeaderLine());
                }

                OutLines.Add(OutCommands[0].BuildLine());
                File.AppendAllLines("EMSCommands.csv", OutLines.ToArray());
            }
            catch (Exception ex)
            {
                MM_Notification.WriteLine(ConsoleColor.Red, "Unable to write out command to local log: {0}", ex);
            }

            //Now, send our commands to all administrators
            if (Properties.Settings.Default.ForwardCommandsToAdminClients)
            {
                foreach (MM_Administrator_Types Interface in MM_Server.ConnectedAdministatorList)
                {
                    try
                    {
                        MM_Administrator_Types.SendMessageToConsole(Interface.ConversationGuid, "AddEMSCommands", new object[] { OutCommands });
                    }
                    catch (Exception ex)
                    {
                        MM_Notification.WriteLine(ConsoleColor.Red, "Unable to send {0} to Admin: {1}", "AddEMSCommands", ex);
                    }
                }
            }

            //Now, send out our commands to all clients
            if (Properties.Settings.Default.ForwardCommandsToERCOTClients)
            {
                foreach (MM_WCF_Interface Interface in MM_Server.ConnectedUserList)
                {
                    if (Interface.User.LoggedOnTime != default(DateTime) && Interface.User.ERCOTUser)
                    {
                        try
                        {
                            MM_WCF_Interface.SendMessage(Interface.User.UserId, "AddEMSCommands", new object[] { OutCommands });
                        }
                        catch (Exception ex)
                        {
                            MM_Notification.WriteLine(ConsoleColor.Red, "Unable to send {0} to {1}: {2}", "AddEMSCommands", Interface.User.UserName, ex);
                        }
                    }
                }
            }
            User.LastCommand = DateTime.Now;
            return(true);
        }
        /// <summary>
        /// Process an incoming client
        /// </summary>
        /// <param name="state"></param>
        private static void ProcessTCPMessage(object state)
        {
            //Now, notify that we have a connection, let's create our stream reader around it, and retrieve our header
            TcpClient Conn      = (TcpClient)state;
            String    FileName  = "";
            DateTime  StartTime = DateTime.Now;

            //If our source IP address changes, notify the console
            IPAddress Address = ((IPEndPoint)Conn.Client.RemoteEndPoint).Address;

            if (Address.ToString() != MM_Server.LastTEDEAddress.ToString())
            {
                MM_Notification.WriteLine(ConsoleColor.Yellow, "TEDE: IP Source Address change detected: {0}, last {1}", Address, MM_Server.LastTEDEAddress);
            }
            MM_Server.LastTEDEAddress = Address;

            using (NetworkStream nRd = Conn.GetStream())
                using (StreamReader sRd = new StreamReader(nRd))
                    try
                    {
                        //Define our key variables
                        List <String>  OutList     = new List <string>();
                        bool           AtBeginning = true;
                        PropertyInfo[] HeaderInfo  = null;
                        DateTime       BatchId     = default(DateTime);
                        Type           TargetType  = null;

                        //Now, read in all of our lines of data, using reflection to store our data
                        String InLine;
                        while ((InLine = sRd.ReadLine()) != null)
                        {
                            if (InLine.StartsWith("#"))
                            {
                                String[] splStr = InLine.TrimStart('#').TrimEnd(',').Split(',');
                                MM_Server.LastTEDEUpdate = DateTime.Now;

                                //If we're at the beginning, process accordingly
                                if (AtBeginning)
                                {
                                    StartTime = DateTime.Now;
                                    //Pull in, and parse our first line.
                                    BatchId  = new DateTime(1970, 1, 1).AddSeconds(Convert.ToDouble(splStr[0]));
                                    FileName = splStr[1];
                                    if (!FileName.EndsWith(".csv", StringComparison.CurrentCultureIgnoreCase))
                                    {
                                        FileName += ".csv";
                                    }

                                    if (InputTypes.TryGetValue(FileName, out TargetType))
                                    {
                                        //Now that we have our first, line, build our outgoing list
                                        OutList.Clear();

                                        //Read our header
                                        String[] HeaderLine = sRd.ReadLine().TrimStart('#').Split(',');

                                        HeaderInfo = MM_Serialization.GetHeaderInfo(TargetType, HeaderLine);
                                        for (int a = 0; a < HeaderLine.Length; a++)
                                        {
                                            if (HeaderInfo[a] == null)
                                            {
                                                MM_Notification.WriteLine(ConsoleColor.Yellow, "Unknown variable {0} in {1}", HeaderLine[a], FileName);
                                            }
                                        }

                                        //Confirm all of our headers are present
                                        foreach (PropertyInfo pI in TargetType.GetProperties())
                                        {
                                            if (Array.FindIndex <String>(HeaderLine, T => T.Equals(pI.Name, StringComparison.CurrentCultureIgnoreCase)) == -1)
                                            {
                                                MM_Notification.WriteLine(ConsoleColor.Yellow, "Missing variable {0} ({1}) in {2} / {3}", pI.Name, pI.PropertyType.Name, TargetType.Name, FileName);
                                            }
                                        }
                                    }
                                    else
                                    {
                                        //Console.WriteLine("Rereading file " + FileName);
                                        sRd.ReadLine();
                                    }

                                    AtBeginning = false;
                                }
                                else
                                {
                                    DateTime EndTime = new DateTime(1970, 1, 1).AddSeconds(Convert.ToDouble(splStr[0]));
                                    if (EndTime != BatchId)
                                    {
                                        MM_Notification.WriteLine(ConsoleColor.Red, "Mismatch date on {0}: Start {1}, End {2}", FileName, BatchId, EndTime);
                                    }
                                    if (OutList != null)
                                    {
                                        ThreadPool.QueueUserWorkItem(new WaitCallback(ProcessData), new object[] { OutList.ToArray(), TargetType, HeaderInfo });
                                    }
                                    else
                                    {
                                        //MM_Notification.WriteLine(ConsoleColor.Yellow, "Ignore processing data from {0}.", FileName);
                                    }
                                    AtBeginning = true;
                                }
                            }
                            else if (OutList != null)
                            {
                                OutList.Add(InLine);
                            }
                        }
                    }
                    catch (Exception ex)
                    {
                        MM_Notification.WriteLine(ConsoleColor.Red, "Error reading {0} from {1}: {2}", FileName, Conn.Client.RemoteEndPoint, ex);
                    }
        }
        /// <summary>
        /// Process a stream, reading and parsing its content
        /// </summary>
        /// <param name="InLines"></param>
        /// <param name="FileName"></param>
        public static void ProcessStreamRead(StreamReader sRd, String FileName, Type TargetType, ref DateTime LatestBatchID)
        {
            //Now, parse our stream
            IList OutList = (IList)Activator.CreateInstance(typeof(List <>).MakeGenericType(TargetType));

            //Read our header
            String FirstLine = sRd.ReadLine().TrimStart('#').TrimEnd(',');

            String[] HeaderLine;
            Double   ProperDate;
            DateTime BatchId = DateTime.Now;

            if (Double.TryParse(FirstLine, out ProperDate))
            {
                BatchId    = new DateTime(1970, 1, 1).AddSeconds(ProperDate);
                HeaderLine = sRd.ReadLine().TrimStart('#').Split(',');
            }
            else
            {
                HeaderLine = FirstLine.Split(',');
            }

            if (BatchId < LatestBatchID)
            {
                MM_Notification.WriteLine(ConsoleColor.Red, "Aborting {0} Batch {1} because it's older than {1}", FileName, BatchId, LatestBatchID);
                return;
            }
            else
            {
                LatestBatchID = BatchId;
            }

            PropertyInfo[] HeaderInfo = MM_Serialization.GetHeaderInfo(TargetType, HeaderLine);
            for (int a = 0; a < HeaderLine.Length; a++)
            {
                if (HeaderInfo[a] == null)
                {
                    MM_Notification.WriteLine(ConsoleColor.Yellow, "Unknown variable {0} in {1}", HeaderLine[a], FileName);
                }
            }

            //Confirm all of our headers are present
            foreach (PropertyInfo pI in TargetType.GetProperties())
            {
                if (Array.FindIndex <String>(HeaderLine, T => T.Equals(pI.Name, StringComparison.CurrentCultureIgnoreCase)) == -1)
                {
                    MM_Notification.WriteLine(ConsoleColor.Yellow, "Missing variable {0} ({1}) in {2} / {3}", pI.Name, pI.PropertyType.Name, TargetType.Name, FileName);
                }
            }

            //Now, read in all of our lines of data, using reflection to store our data
            String InLine;

            while ((InLine = sRd.ReadLine()) != null)
            {
                if (InLine.StartsWith("#"))
                {
                    DateTime EndTime = new DateTime(1970, 1, 1).AddSeconds(Convert.ToDouble(InLine.TrimStart('#').TrimEnd(',')));
                    if (EndTime != BatchId)
                    {
                        MM_Notification.WriteLine(ConsoleColor.Red, "Mismatch date on {0}: Start {1}, End {2}", FileName, BatchId, EndTime);
                    }
                }
                else
                {
                    Object OutObj = MM_Serialization.Deserialize(HeaderInfo, InLine.Split(','), Activator.CreateInstance(TargetType));
                    //if (OutObj is MacomberMapCommunications.Messages.EMS.MM_BreakerSwitch_Data)
                    //{
                    //    MacomberMapCommunications.Messages.EMS.MM_BreakerSwitch_Data bs = (MacomberMapCommunications.Messages.EMS.MM_BreakerSwitch_Data)OutObj;
                    //    if (bs.TEID_CB == 118964)
                    //        MM_Notification.WriteLine(ConsoleColor.Magenta, "   TEID=" + bs.TEID_CB.ToString() + "    status=" + (bs.Open_CB ? "Open" : "Closed"));
                    //}
                    OutList.Add(OutObj);
                }
            }

            //Once our data are done, use the interprocess communication to update our data
            if (TargetType == typeof(MM_EMS_Command))
            {
                MM_Server.EMSCommands.Clear();
                foreach (Object obj in OutList)
                {
                    MM_Server.EMSCommands.Add((MM_EMS_Command)obj);
                }
            }
            else
            {
                MM_EMS_Data_Updater.ProcessUpdate(TargetType, (Array)OutList.GetType().GetMethod("ToArray").Invoke(OutList, null));
            }
            OutList.Clear();
            OutList = null;
        }