private async Task EstablishSerial(CancellationToken token)
        {
            IsBusy = true;
            Dictionary <string, SerialComm> comms = Globals.Serials;

            if (!comms.ContainsKey(COMPORT))
            {
                comms.Add(COMPORT, new SerialComm());
                _serial = comms[COMPORT];
            }
            else
            {
                _serial = comms[COMPORT];
                if (_serial.IsOpen)
                {
                    return;
                }
            }

            Globals.Logger.LogInformation($"Opened serial port {COMPORT}");
            if (await CreateNewMeter() == null)
            {
                _serial.Close();
                IsBusy    = false;
                Completed = false;
                return;
            }

            Completed = true;

            // Send message to create new tab that will be able to commission a meter
            (Application.Current.Properties["MessageBus"] as MessageBus)
            .Publish(new MessageCenter("newTab", new Tuple <string, string>(_comPort, _id)));
        }
        /// <summary>
        /// Issues Phase Diagnostic call for meter
        /// </summary>
        /// <returns>Boolean indicating success of Phase Diagnostic call</returns>
        private string Process()
        {
            CancellationToken token = _cts.Token;
            var task = _serial.PhaseDiagnostic(token);

            // Waits X seconds for Phase Diagnostic call to finish execution if not then display
            // modal to user and attempt to reconnect
            int timeout = _serial.NewFirmware ? 7000 : 5000;

            if (!task.Wait(timeout, token))
            {
                // Create thread that launches modal window for user and continues to poll
                // original process to determine if it has completed
                Thread t = new Thread(new ThreadStart(() =>
                {
                    InfoView info      = null;
                    InfoViewModel ifvm = new InfoViewModel(task, _cts, "Serial Connection Lost", "Attempting to Reconnect");

                    Application.Current.Dispatcher.Invoke(() =>
                    {
                        info = new InfoView
                        {
                            Owner = Application.Current.MainWindow,
                            WindowStartupLocation = WindowStartupLocation.CenterOwner,
                            DataContext           = ifvm
                        };

                        info.Show();
                    });

                    var monitor = ifvm.Poll();
                    if (monitor)
                    {
                        // Close the window if the program has successfully re-established communication
                        Application.Current.Dispatcher.Invoke(() =>
                        {
                            ifvm.UserClosedWindow = false;
                            info.Close();
                        });
                    }
                    else
                    {
                        // Wait for the task to complete
                        while (task.Status != TaskStatus.RanToCompletion)
                        {
                        }

                        // exit this function
                        return;
                    }
                }));

                t.SetApartmentState(ApartmentState.STA);
                t.IsBackground = true;
                t.Start();
                t.Join();
            }

            // Iterate over each line and extract the voltage, current and kW for each channel and phase of the meter
            string buffer      = task.Result;
            int    meter       = 0;
            bool   phase1      = true;
            int    lineNumber  = 0;
            bool   corrupted   = false;
            float  voltageASum = 0.0f;
            float  voltageBSum = 0.0f;
            float  voltageCSum = 0.0f;
            float  voltageANum = 0;
            float  voltageBNum = 0;
            float  voltageCNum = 0;

            foreach (string s in buffer.Split(new char[] { '\n', '\r' }, System.StringSplitOptions.RemoveEmptyEntries))
            {
                string[] cols = s.Split(new char[0], StringSplitOptions.RemoveEmptyEntries);

                // if not data row continue to next line
                if (s.Contains("Amps") || (!_serial.NewFirmware && cols.Length != 10) || (_serial.NewFirmware && cols.Length != 9))
                {
                    continue;
                }

                if (!_serial.NewFirmware)
                {
                    if (Regex.IsMatch(cols[0], "^(3[2-9]|4[0-3])$") && Regex.IsMatch(cols[3], "^[12]$") && Convert.ToInt32(cols[0]) - 32 == lineNumber / 2)
                    {
                        meter  = Convert.ToInt32(cols[0]) - 32;
                        phase1 = cols[3] == "1" ? true : false;

                        if (phase1)
                        {
                            if (Regex.IsMatch(cols[6], @"^\d*\.\d*$"))
                            {
                                Phase1Text[meter, 0] = float.Parse(cols[6]).ToString("0.00");
                            }
                            else
                            {
                                Phase1Text[meter, 0] = "--";
                                corrupted            = true;
                            }

                            if (Regex.IsMatch(cols[8], @"^\d*\.\d*$"))
                            {
                                float watts = float.Parse(cols[8]);
                                Phase1Text[meter, 1] = (watts / 1000).ToString("0.00");

                                if (Regex.IsMatch(cols[9], @"^\d*\.\d*$"))
                                {
                                    double temp = Math.Atan2(float.Parse(cols[9]), watts);

                                    if (double.IsNaN(temp))
                                    {
                                        Phase1Text[meter, 2] = "--";
                                    }
                                    else
                                    {
                                        Phase1Text[meter, 2] = temp.ToString("0.00");
                                    }
                                }
                                else
                                {
                                    Phase1Text[meter, 2] = "--";
                                    corrupted            = true;
                                }
                            }
                            else
                            {
                                Phase1Text[meter, 1] = "--";
                                Phase1Text[meter, 2] = "--";
                                corrupted            = true;
                            }

                            // Set the voltages for the Meter Information box
                            if (Regex.IsMatch(cols[7], @"^\d*\.\d*$"))
                            {
                                if (Phase1Text[meter, 4] == "A")
                                {
                                    voltageASum += float.Parse(cols[7]);
                                    voltageANum++;
                                }
                                else if (Phase1Text[meter, 4] == "B")
                                {
                                    voltageBSum += float.Parse(cols[7]);
                                    voltageBNum++;
                                }
                                else if (Phase1Text[meter, 4] == "C")
                                {
                                    voltageCSum += float.Parse(cols[7]);
                                    voltageCNum++;
                                }
                            }
                            else
                            {
                                corrupted = true;
                            }
                        }
                        else
                        {
                            if (Regex.IsMatch(cols[6], @"^\d*\.\d*$"))
                            {
                                Phase2Text[meter, 0] = float.Parse(cols[6]).ToString("0.00");
                            }
                            else
                            {
                                Phase2Text[meter, 0] = "--";
                                corrupted            = true;
                            }

                            if (Regex.IsMatch(cols[8], @"^\d*\.\d*$"))
                            {
                                float watts = float.Parse(cols[8]);
                                Phase2Text[meter, 1] = (watts / 1000).ToString("0.00");

                                if (Regex.IsMatch(cols[9], @"^\d*\.\d*$"))
                                {
                                    double temp = Math.Atan2(float.Parse(cols[9]), watts);

                                    if (double.IsNaN(temp))
                                    {
                                        Phase2Text[meter, 2] = "--";
                                    }
                                    else
                                    {
                                        Phase2Text[meter, 2] = temp.ToString("0.00");
                                    }
                                }
                                else
                                {
                                    Phase2Text[meter, 2] = "--";
                                    corrupted            = true;
                                }
                            }
                            else
                            {
                                Phase2Text[meter, 1] = "--";
                                Phase2Text[meter, 2] = "--";
                                corrupted            = true;
                            }

                            // Set the voltages for the Meter Information box
                            if (Regex.IsMatch(cols[7], @"^\d*\.\d*$"))
                            {
                                if (Phase2Text[meter, 4] == "A")
                                {
                                    voltageASum += float.Parse(cols[7]);
                                    voltageANum++;
                                }
                                else if (Phase2Text[meter, 4] == "B")
                                {
                                    voltageBSum += float.Parse(cols[7]);
                                    voltageBNum++;
                                }
                                else if (Phase2Text[meter, 4] == "C")
                                {
                                    voltageCSum += float.Parse(cols[7]);
                                    voltageCNum++;
                                }
                            }
                            else
                            {
                                corrupted = true;
                            }
                        }
                    }
                    else
                    {
                        if (lineNumber % 2 == 0)
                        {
                            Phase1Text[lineNumber / 2, 0] = "--";   // Amps
                            Phase1Text[lineNumber / 2, 1] = "--";   // Watts
                            Phase1Text[lineNumber / 2, 2] = "--";   // PF
                        }
                        else
                        {
                            Phase2Text[lineNumber / 2, 0] = "--";   // Amps
                            Phase2Text[lineNumber / 2, 1] = "--";   // Watts
                            Phase2Text[lineNumber / 2, 2] = "--";   // PF
                        }

                        corrupted = true;
                    }
                }
                else
                {
                    if (Regex.IsMatch(cols[0], "^[12]$"))
                    {
                        phase1 = cols[0] == "1" ? true : false;

                        if (phase1)
                        {
                            if (Regex.IsMatch(cols[3], @"^\d*\.\d*$"))
                            {
                                Phase1Text[meter, 0] = float.Parse(cols[3]).ToString("0.00");
                            }
                            else
                            {
                                Phase1Text[meter, 0] = "--";
                                corrupted            = true;
                            }

                            if (Regex.IsMatch(cols[5], @"^\d*\.\d*$"))
                            {
                                float watts = float.Parse(cols[5]);
                                Phase1Text[meter, 1] = (watts / 1000).ToString("0.00");

                                if (Regex.IsMatch(cols[6], @"^\d*\.\d*$"))
                                {
                                    double temp = Math.Atan2(float.Parse(cols[6]), watts);
                                    if (double.IsNaN(temp))
                                    {
                                        Phase1Text[meter, 2] = "--";
                                    }
                                    else
                                    {
                                        Phase1Text[meter, 2] = temp.ToString("0.00");
                                    }
                                }
                                else
                                {
                                    Phase1Text[meter, 2] = "--";
                                    corrupted            = true;
                                }
                            }
                            else
                            {
                                Phase1Text[meter, 1] = "--";
                                Phase1Text[meter, 2] = "--";
                                corrupted            = true;
                            }

                            // Set the voltages for the Meter Information box
                            if (Regex.IsMatch(cols[4], @"^\d*\.\d*$"))
                            {
                                if (Phase1Text[meter, 4] == "A")
                                {
                                    voltageASum += float.Parse(cols[4]);
                                    voltageANum++;
                                }
                                else if (Phase1Text[meter, 4] == "B")
                                {
                                    voltageBSum += float.Parse(cols[4]);
                                    voltageBNum++;
                                }
                                else if (Phase1Text[meter, 4] == "C")
                                {
                                    voltageCSum += float.Parse(cols[4]);
                                    voltageCNum++;
                                }
                            }
                            else
                            {
                                corrupted = true;
                            }
                        }
                        else
                        {
                            if (Regex.IsMatch(cols[3], @"^\d*\.\d*$"))
                            {
                                Phase2Text[meter, 0] = float.Parse(cols[3]).ToString("0.00");
                            }
                            else
                            {
                                Phase2Text[meter, 0] = "--";
                                corrupted            = true;
                            }

                            if (Regex.IsMatch(cols[5], @"^\d*\.\d*$"))
                            {
                                float watts = float.Parse(cols[5]);
                                Phase2Text[meter, 1] = (watts / 1000).ToString("0.00");

                                if (Regex.IsMatch(cols[6], @"^\d*\.\d*$"))
                                {
                                    double temp = Math.Atan2(float.Parse(cols[6]), watts);
                                    if (double.IsNaN(temp))
                                    {
                                        Phase2Text[meter, 2] = "--";
                                    }
                                    else
                                    {
                                        Phase2Text[meter, 2] = temp.ToString("0.00");
                                    }
                                }
                                else
                                {
                                    Phase2Text[meter, 2] = "--";
                                    corrupted            = true;
                                }
                            }
                            else
                            {
                                Phase2Text[meter, 1] = "--";
                                Phase2Text[meter, 2] = "--";
                                corrupted            = true;
                            }

                            // Set the voltages for the Meter Information box
                            if (Regex.IsMatch(cols[4], @"^\d*\.\d*$"))
                            {
                                if (Phase2Text[meter, 4] == "A")
                                {
                                    voltageASum += float.Parse(cols[4]);
                                    voltageANum++;
                                }
                                else if (Phase2Text[meter, 4] == "B")
                                {
                                    voltageBSum += float.Parse(cols[4]);
                                    voltageBNum++;
                                }
                                else if (Phase2Text[meter, 4] == "C")
                                {
                                    voltageCSum += float.Parse(cols[4]);
                                    voltageCNum++;
                                }
                            }
                            else
                            {
                                corrupted = true;
                            }

                            meter++;
                        }
                    }
                    else
                    {
                        if (lineNumber % 2 == 0)
                        {
                            Phase1Text[lineNumber / 2, 0] = "--";   // Amps
                            Phase1Text[lineNumber / 2, 1] = "--";   // Watts
                            Phase1Text[lineNumber / 2, 2] = "--";   // PF
                        }
                        else
                        {
                            Phase2Text[lineNumber / 2, 0] = "--";   // Amps
                            Phase2Text[lineNumber / 2, 1] = "--";   // Watts
                            Phase2Text[lineNumber / 2, 2] = "--";   // PF
                        }

                        corrupted = true;
                    }
                }

                lineNumber++;
            }

            // Display average of Voltages instead of last voltage received
            // aids in troubleshooting
            VoltageA = (voltageASum / voltageANum).ToString("0.00") + " V";
            VoltageB = (voltageBSum / voltageBNum).ToString("0.00") + " V";
            VoltageC = (voltageCSum / voltageCNum).ToString("0.00") + " V";

            OnPropertyChanged(nameof(Phase1Text));
            OnPropertyChanged(nameof(Phase2Text));

            // If present data is corrupted, increment corrupted counter
            if (corrupted)
            {
                _numCorrupted++;
            }
            // Reset corrupted counter if data isn't corrupt
            else
            {
                _numCorrupted = 0;
            }

            // If data is corrupt, 3 times in a row
            // display modal to user and stop reading
            if (_numCorrupted == 3)
            {
                InfoView      info = null;
                InfoViewModel ifvm = new InfoViewModel("Corrupted Data", "Corrupted Data has been received multiple times. Please check set up. Pausing serial port reads.");

                Application.Current.Dispatcher.Invoke(() =>
                {
                    info = new InfoView
                    {
                        Owner = Application.Current.MainWindow,
                        WindowStartupLocation = WindowStartupLocation.CenterOwner,
                        DataContext           = ifvm
                    };

                    info.Show();
                });

                // Stops async processes and closes serial port
                // but leaves current tab open
                _break = true;
                _serial.Close();
            }

            return(buffer);
        }