/// <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;
                        }
                    }
                }
            }
        }
        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;
        }
Beispiel #3
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();
 }