/// <summary>
 /// Sends diagnostic data to the dashboard
 /// </summary>
 /// <param name="sender">The timer</param>
 /// <param name="e">The event args</param>
 private static void SendDiagnosticData(object sender, System.Timers.ElapsedEventArgs e)
 {
     //collect and send diagnostic robot data to the dashboard
     if (!ConnectionLive || !RobotController.SystemOnline)
     {
         return;
     }
     string[] diagnosticData = new string[]
     {
         RobotController.ControlStatus.ToString(),
              RobotController.GetRobotStatus().ToString(),
              RobotController.RobotAutoControlState.ToString(),
              Hardware.SignalVoltageRaw.ToString(),                                                                       //raw signal voltage
              Hardware.SignalCurrentRaw.ToString(),                                                                       //raw signal current
              Hardware.PowerVoltageRaw.ToString(),                                                                        //raw power voltage
              Hardware.PowerVoltage.ToString(),                                                                           //raw power current
              Hardware.WaterLevel.ToString(),                                                                             //water level
              Hardware.TempatureRaw.ToString(),                                                                           //raw tempature
         "NC",                                                                                                            //CH6 (unused)
         "NC",                                                                                                            //CH7 (unused)
              Hardware.LeftDrive.GetSignInt().ToString(),                                                                 //sign
              Math.Round(Hardware.LeftDrive.GetActiveDutyCyclePercentage(), 2).ToString(),                                //mag
         Hardware.LeftEncoder.Clicks.ToString(),                                                                          //encoder
         Hardware.RightDrive.GetSignInt().ToString(),                                                                     //sign
         Math.Round(Hardware.RightDrive.GetActiveDutyCyclePercentage(), 2).ToString(),                                    //mag
         Hardware.RightEncoder.Clicks.ToString(),                                                                         //encoder
         Hardware.SignalVoltage.ToString(),                                                                               //signal voltage
         Hardware.SignalCurrent.ToString(),                                                                               //signal current
         Hardware.PowerVoltage.ToString(),                                                                                //power voltage
         Hardware.PowerCurrent.ToString(),                                                                                //power current
         Hardware.AccelerationX.ToString(),                                                                               //accel X
         Hardware.AccelerationY.ToString(),                                                                               //accel Y
         Hardware.AccelerationZ.ToString(),                                                                               //accel Z
         Hardware.GyroX.ToString(),                                                                                       //gyro X
         Hardware.GyroY.ToString(),                                                                                       //gyro Y
         Hardware.GyroZ.ToString(),                                                                                       //gyro Z
         Hardware.Augar_Output.ToString(),                                                                                //collection relay
         Hardware.Impeller_Output.ToString(),                                                                             //another collection relay
         Hardware.VelocityX.ToString(),                                                                                   //velocity data
         Hardware.VelocityY.ToString(),                                                                                   //velocity data
         Hardware.VelocityZ.ToString(),                                                                                   //velocity data
         Hardware.RotationX.ToString(),                                                                                   //rotation data
         Hardware.RotationY.ToString(),                                                                                   //rotation data
         Hardware.RotationZ.ToString(),                                                                                   //rotation data
         Hardware.Tempature_2.ToString(),                                                                                 //MPU temp data
         Hardware.SideReciever == null? "null": Convert.ToByte(Hardware.SideReciever.WallDetected).ToString(),            //side wall detection
         Hardware.FrontReciever == null? "null": Convert.ToByte(Hardware.FrontReciever.WallDetected).ToString(),          //front wall detection
         Hardware.the_only_distance_sensor == null? "null" : Hardware.the_only_distance_sensor.Distance_in_cm.ToString(), //proximity
         Hardware.PositionX.ToString(),                                                                                   //positionx
         Hardware.PositionY.ToString(),                                                                                   //positiony
         Hardware.PositionZ.ToString(),                                                                                   //positionz
     };
     LogNetwork(string.Join(',', diagnosticData), MessageType.DiagnosticData);
 }
        private async void InitRobot(object sender, RoutedEventArgs e)
        {
            if (!Hardware.InitGPIO())
            {
                //https://stackoverflow.com/questions/32677597/how-to-exit-or-close-an-uwp-app-programmatically-windows-10
                Application.Current.Exit();
                return;
            }

            //init the robot networking
            if (!NetworkUtils.InitComms())
            {
                RobotController.SetRobotStatus(RobotStatus.Error);
                Application.Current.Exit();
                return;
            }

            //DEBUG: wait for dashboard logging connection
            if (NetworkUtils.DEBUG_FORCE_DASHBOARD_CONNECT)
            {
                while (!NetworkUtils.ConnectionLive)
                {
                    System.Threading.Thread.Sleep(100);
                }
                NetworkUtils.LogNetwork("dashboard connected via force wait", MessageType.Debug);
            }

            //encoders
            NetworkUtils.LogNetwork("Initializing Encoders", MessageType.Info);
            if (!Hardware.InitEncoders())
            {
                NetworkUtils.LogNetwork("Encoders Failed to initialize", MessageType.Error);
                RobotController.SetRobotStatus(RobotStatus.Error);
                Application.Current.Exit();
            }

            //proximity

            /*
             * NetworkUtils.LogNetwork("Encoders initialized, loading proximity sensor", MessageType.Info);
             * if(!Hardware.InitDistanceSensor())
             * {
             *  NetworkUtils.LogNetwork("Proximity Failed to initialize", MessageType.Error);
             *  RobotController.SetRobotStatus(RobotStatus.Error);
             *  Application.Current.Exit();
             * }*/

            //SPI/ADC
            NetworkUtils.LogNetwork("Proximity initialized, initializing SPI interface", MessageType.Info);
            //http://blog.stephencleary.com/2012/07/dont-block-on-async-code.html
            //https://docs.microsoft.com/en-us/uwp/api/windows.devices.enumeration.deviceinformation.findallasync
            //https://stackoverflow.com/questions/33587832/prevent-winforms-ui-block-when-using-async-await
            if (!await Hardware.InitSPI())
            {
                NetworkUtils.LogNetwork("SPI failed to intialize", MessageType.Error);
                RobotController.SetRobotStatus(RobotStatus.Error);
                Application.Current.Exit();
                return;
            }

            //pwm
            NetworkUtils.LogNetwork("SPI Interface initialization complete, loading PWM", MessageType.Info);
            if (!await Hardware.InitPWM())
            {
                NetworkUtils.LogNetwork("PWM failed to intialize", MessageType.Error);
                RobotController.SetRobotStatus(RobotStatus.Error);
                Application.Current.Exit();
                return;
            }

            //I2c
            NetworkUtils.LogNetwork("PWM loading complete, I2C", MessageType.Info);
            if (!await Hardware.InitI2C())
            {
                NetworkUtils.LogNetwork("I2C Failed to Initialize", MessageType.Error);
                RobotController.SetRobotStatus(RobotStatus.Error);
                Application.Current.Exit();
            }

            //main control system
            NetworkUtils.LogNetwork("I2C loading complete, Initializing Main Robot controller", MessageType.Info);
            if (!RobotController.InitController(this.Dispatcher))
            {
                NetworkUtils.LogNetwork("Controller failed to intialize", MessageType.Error);
                RobotController.SetRobotStatus(RobotStatus.Error);
                Application.Current.Exit();
                return;
            }
            NetworkUtils.LogNetwork("Controller initialized, system online", MessageType.Info);
            RobotController.SystemOnline = true;
        }
        /// <summary>
        /// The main worker method for the networking thread, UDP method
        /// </summary>
        /// <param name="sender">The BackgroundWorker object</param>
        /// <param name="e">The event args</param>
        public static void ManageConnections(object sender, DoWorkEventArgs e)
        {
            if (ConnectionLive)
            {
                ConnectionLive = false;
            }
            NetworkPin.Write(ConnectionLive ? GpioPinValue.High : GpioPinValue.Low);
            while (true)
            {
                if (ConnectionManager.CancellationPending)
                {
                    e.Cancel = true;
                    HeartbeatTimer.Stop();
                    DiagnosticTimer.Stop();
                    return;
                }
                //verify stop the timer
                HeartbeatTimer.Stop();
                DiagnosticTimer.Stop();
                //setup and bind listener
                RobotRecieverIPEndPoint = new IPEndPoint(IPAddress.Parse(RobotIPV4Address), RobotRecieverPort);
                RobotRecieverUDPClient  = new UdpClient();
                RobotRecieverUDPClient.Client.SendTimeout    = 5000;//value is miliseconds
                RobotRecieverUDPClient.Client.ReceiveTimeout = 5000;
                RobotRecieverUDPClient.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
                RobotRecieverUDPClient.Client.Bind(RobotRecieverIPEndPoint);
                //wait for receiver client to get the ip address of the dashboard
                bool   receivedIP = false;
                string result     = null;
                while (!receivedIP)
                {
                    if (ConnectionManager.CancellationPending)
                    {
                        e.Cancel = true;
                        HeartbeatTimer.Stop();
                        DiagnosticTimer.Stop();
                        return;
                    }
                    try
                    {
                        result     = Encoding.UTF8.GetString(RobotRecieverUDPClient.Receive(ref RobotRecieverIPEndPoint));
                        receivedIP = true;
                    }
                    catch (Exception)
                    {
                    }
                }
                //parse the ip address sent by the dashboard
                IPAddress address;
                try
                {
                    address = IPAddress.Parse(result);
                }
                catch (Exception)
                {
                    RobotController.SetRobotStatus(RobotStatus.Exception);
                    e.Cancel = true;
                    return;
                }
                if (address.AddressFamily == AddressFamily.InterNetworkV6)
                {
                    DashboardIPV6Address = address.ToString();
                }
                else if (address.AddressFamily == AddressFamily.InterNetwork)
                {
                    DashboardIPV4Address = address.ToString();
                }
                //setup and connect sender
                RobotSenderIPEndPoint = new IPEndPoint(IPAddress.Parse(string.IsNullOrWhiteSpace(DashboardIPV6Address) ? DashboardIPV4Address : DashboardIPV6Address), RobotSenderPort);
                RobotSenderUDPClient  = new UdpClient();
                RobotSenderUDPClient.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
                RobotSenderUDPClient.Client.SendTimeout    = 5000;//value is miliseconds
                RobotSenderUDPClient.Client.ReceiveTimeout = 5000;
                bool senderConnected = false;
                while (!senderConnected)
                {
                    if (ConnectionManager.CancellationPending)
                    {
                        e.Cancel = true;
                        HeartbeatTimer.Stop();
                        DiagnosticTimer.Stop();
                        return;
                    }
                    try
                    {
                        RobotSenderUDPClient.Connect(RobotSenderIPEndPoint);
                        senderConnected = true;
                    }
                    catch (Exception)
                    {
                    }
                }
                //send ack
                RobotSenderUDPClient.Send(Encoding.UTF8.GetBytes("ack"), Encoding.UTF8.GetByteCount("ack"));
                //start to send heartbeats
                NumHeartbeatsSent = 0;
                HeartbeatTimer.Start();
                DiagnosticTimer.Start();
                ConnectionLive = true;
                NetworkPin.Write(ConnectionLive ? GpioPinValue.High : GpioPinValue.Low);
                if (RecoveredException != null)
                {
                    LogNetwork("The network thread just recovered from an exception level event\n" + RecoveredException.ToString(), MessageType.Exception);
                    RecoveredException = null;
                }
                //listen for dashboard events
                while (ConnectionLive)
                {
                    if (ConnectionManager.CancellationPending)
                    {
                        e.Cancel = true;
                        HeartbeatTimer.Stop();
                        DiagnosticTimer.Stop();
                        return;
                    }
                    try
                    {
                        result = Encoding.UTF8.GetString(RobotRecieverUDPClient.Receive(ref RobotRecieverIPEndPoint));
                    }
                    catch (SocketException)
                    {
                        if (DEBUG_IGNORE_TIMEOUT && !DEBUG_TCP_TEST)
                        {
                            continue;
                        }
                        //the dashboard has disocnnected!
                        ConnectionLive = false;
                        NetworkPin.Write(ConnectionLive ? GpioPinValue.High : GpioPinValue.Low);
                        e.Cancel = true;
                        HeartbeatTimer.Stop();
                        DiagnosticTimer.Stop();
                        return;
                    }
                    int    messageTypeInt    = -1;
                    string messageTypeString = result.Split(',')[0];
                    if (int.TryParse(messageTypeString, out messageTypeInt))
                    {
                        MessageType messageType = (MessageType)messageTypeInt;
                        switch (messageType)
                        {
                        case MessageType.Heartbeat:
                            //do nothing
                            break;

                        case MessageType.Control:
                            string controlMessage = result.Substring(messageTypeString.Count() + 1);
                            if (!controlMessage.Equals(ManualControlCommands))
                            {
                                //assuming thread access is atomic...
                                ManualControlCommands = controlMessage;
                                if (ManualControlCommands.Equals("Start"))
                                {
                                    RobotController.ControlStatus = ControlStatus.RequestManual;
                                    RobotController.ControllerThread.CancelAsync();
                                }
                                else if (ManualControlCommands.Equals("Stop"))
                                {
                                    RobotController.ControlStatus = ControlStatus.RelaseManual;
                                    RobotController.ControllerThread.CancelAsync();
                                }
                                else if (ManualControlCommands.Split(',')[0].Equals("Shutdown"))
                                {
                                    RobotController.Poweroff(TimeSpan.FromSeconds(int.Parse(ManualControlCommands.Split(',')[1])));
                                }
                                else if (ManualControlCommands.Split(',')[0].Equals("Reboot"))
                                {
                                    RobotController.Reboot(TimeSpan.FromSeconds(int.Parse(ManualControlCommands.Split(',')[1])));
                                }
                                else if (ManualControlCommands.Split(',')[0].Equals("Cancel_Shutdown"))
                                {
                                    RobotController.CancelShutdown();
                                }
                            }
                            break;
                        }
                    }
                }
            }
        }
        /// <summary>
        /// The main worker method for the networking thread, TCP method
        /// </summary>
        /// <param name="sender">The BackgroundWorker object</param>
        /// <param name="e">The event args</param>
        public static void ManageConnections_tcp(object sender, DoWorkEventArgs e)
        {
            ConnectionLive = false;
            //Robot only
            NetworkPin.Write(ConnectionLive ? GpioPinValue.High : GpioPinValue.Low);
            while (true)
            {
                if (ConnectionManager.CancellationPending)
                {
                    e.Cancel = true;
                    HeartbeatTimer.Stop();
                    DiagnosticTimer.Stop();
                    return;
                }
                //verify stop the timer
                HeartbeatTimer.Stop();
                DiagnosticTimer.Stop();
                //setup and bind listener
                RobotRecieverIPEndPoint  = new IPEndPoint(IPAddress.Parse(RobotIPV4Address), RobotRecieverPort);
                RobotReceiverTCPListener = new TcpListener(RobotRecieverIPEndPoint);
                RobotReceiverTCPListener.Server.SendTimeout    = 5000;//value is miliseconds
                RobotReceiverTCPListener.Server.ReceiveTimeout = 5000;
                //set socket before binding!
                RobotReceiverTCPListener.Server.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
                RobotReceiverTCPListener.Start();//now it's bound
                //wait for receiver client to get the ip address of the dashboard
                IPAddress address           = null;
                bool      recieverConnected = false;
                while (!recieverConnected)
                {
                    if (ConnectionManager.CancellationPending)
                    {
                        e.Cancel = true;
                        HeartbeatTimer.Stop();
                        DiagnosticTimer.Stop();
                        return;
                    }
                    try
                    {
                        //try to accept the tcp connection and parse the ip address
                        RobotRecieverTCPClient = RobotReceiverTCPListener.AcceptTcpClient();
                        address           = IPAddress.Parse(TCPRecieve(RobotRecieverTCPClient));
                        recieverConnected = true;
                    }
                    catch (Exception)
                    {
                        //RobotController.RobotStatus = RobotStatus.Exception;
                        //keep trying
                    }
                }
                if (address.AddressFamily == AddressFamily.InterNetworkV6)
                {
                    DashboardIPV6Address = address.ToString();
                }
                else if (address.AddressFamily == AddressFamily.InterNetwork)
                {
                    DashboardIPV4Address = address.ToString();
                }
                //for now we'er just force using the IPV4 stuff
                //setup and bind sender to send ack
                RobotSenderIPEndPoint = new IPEndPoint(IPAddress.Parse(string.IsNullOrWhiteSpace(DashboardIPV6Address) ? DashboardIPV4Address : DashboardIPV6Address), RobotSenderPort);
                RobotSenderTCPClient  = new TcpClient();
                RobotSenderTCPClient.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
                RobotSenderTCPClient.Client.SendTimeout    = 5000;//value is miliseconds
                RobotSenderTCPClient.Client.ReceiveTimeout = 5000;
                bool senderConnected = false;
                while (!senderConnected)
                {
                    if (ConnectionManager.CancellationPending)
                    {
                        e.Cancel = true;
                        HeartbeatTimer.Stop();
                        DiagnosticTimer.Stop();
                        return;
                    }
                    try
                    {
                        RobotSenderTCPClient.Connect(RobotSenderIPEndPoint);
                        senderConnected = true;
                    }
                    catch (SocketException)
                    {
                        //keep trying
                    }
                }
                RobotSenderTCPStream = RobotSenderTCPClient.GetStream();
                //set new timeout settings for the robot receiver
                if (RobotRecieverTCPClient.Client.ReceiveTimeout != 5000)
                {
                    RobotRecieverTCPClient.Client.ReceiveTimeout = 5000;
                }
                if (RobotRecieverTCPClient.Client.SendTimeout != 5000)
                {
                    RobotRecieverTCPClient.Client.SendTimeout = 5000;
                }
                if (RobotRecieverTCPClient.GetStream().CanTimeout)
                {
                    if (RobotRecieverTCPClient.GetStream().ReadTimeout != 5000)
                    {
                        RobotRecieverTCPClient.GetStream().ReadTimeout = 5000;
                    }
                    if (RobotRecieverTCPClient.GetStream().WriteTimeout != 5000)
                    {
                        RobotRecieverTCPClient.GetStream().WriteTimeout = 5000;
                    }
                }
                //send ack to dashboard
                if (!TCPSend(RobotSenderTCPStream, "ack"))
                {
                    continue;
                }
                //start to send heartbeats
                ConnectionLive = true;
                NetworkPin.Write(ConnectionLive ? GpioPinValue.High : GpioPinValue.Low);
                NumHeartbeatsSent = 0;
                HeartbeatTimer.Start();
                DiagnosticTimer.Start();
                if (RecoveredException != null)
                {
                    LogNetwork("The network thread just recovered from an exception level event\n" + RecoveredException.ToString(), MessageType.Exception);
                    RecoveredException = null;
                }
                //listen for dashboard events
                string result = null;
                while (ConnectionLive)
                {
                    if (ConnectionManager.CancellationPending)
                    {
                        e.Cancel = true;
                        HeartbeatTimer.Stop();
                        DiagnosticTimer.Stop();
                        return;
                    }
                    result = TCPRecieve(RobotRecieverTCPClient);
                    if (string.IsNullOrWhiteSpace(result))
                    {
                        if (DEBUG_IGNORE_TIMEOUT && DEBUG_TCP_TEST)
                        {
                            Thread.Sleep(1000);
                            continue;
                        }
                        //the dashboard has disocnnected!
                        ConnectionLive = false;
                        NetworkPin.Write(ConnectionLive ? GpioPinValue.High : GpioPinValue.Low);
                        Disconnect();
                        break;
                    }
                    int    messageTypeInt    = -1;
                    string messageTypeString = result.Split(',')[0];
                    if (int.TryParse(messageTypeString, out messageTypeInt))
                    {
                        MessageType messageType = (MessageType)messageTypeInt;
                        switch (messageType)
                        {
                        case MessageType.Heartbeat:
                            //do nothing
                            break;

                        case MessageType.Control:
                            string controlMessage = result.Substring(messageTypeString.Count() + 1);
                            if (!controlMessage.Equals(ManualControlCommands))
                            {
                                //assuming thread access is atomic...
                                ManualControlCommands = controlMessage;
                                if (ManualControlCommands.Equals("Start"))
                                {
                                    RobotController.ControlStatus = ControlStatus.RequestManual;
                                    RobotController.ControllerThread.CancelAsync();
                                }
                                else if (ManualControlCommands.Equals("Stop"))
                                {
                                    RobotController.ControlStatus = ControlStatus.RelaseManual;
                                    RobotController.ControllerThread.CancelAsync();
                                }
                                else if (ManualControlCommands.Split(',')[0].Equals("Shutdown"))
                                {
                                    RobotController.Poweroff(TimeSpan.FromSeconds(int.Parse(ManualControlCommands.Split(',')[1])));
                                }
                                else if (ManualControlCommands.Split(',')[0].Equals("Reboot"))
                                {
                                    RobotController.Reboot(TimeSpan.FromSeconds(int.Parse(ManualControlCommands.Split(',')[1])));
                                }
                                else if (ManualControlCommands.Split(',')[0].Equals("Cancel_Shutdown"))
                                {
                                    RobotController.CancelShutdown();
                                }
                            }
                            break;
                        }
                    }
                }
            }
        }
예제 #5
0
 /// <summary>
 /// Occures when the application encounters an unhandled exception. The applicatoin is unloaded and all resources released
 /// </summary>
 /// <param name="sender">The source that caused the exception</param>
 /// <param name="e">The exception object entry</param>
 private void Application_UnhandledException(object sender, Windows.UI.Xaml.UnhandledExceptionEventArgs e)
 {
     RobotController.SetRobotStatus(RobotStatus.Exception);
     NetworkUtils.LogNetwork(e.ToString(), MessageType.Exception);
     Current.Exit();
 }