/// <summary> /// Gestore interno del watch dog sulle FSUIPC. In caso di errore sorreva un ErrorOccurredEvent /// </summary> private void TickHandle(object sender, ElapsedEventArgs e) { try { PositioningEvent toBeRaised = new PositioningEvent(); AircraftPosition currentPosition = new AircraftPosition(); #if FEDE_DEBUG currentPosition.IndicatedAirspeedSpeed = (new Random()).NextDouble() * 100; currentPosition.Altitude = 0; currentPosition.AutopilotHeading = 100; currentPosition.AvailableFuel = 100; currentPosition.GroundSpeed = currentPosition.IndicatedAirspeedSpeed; currentPosition.Heading = 196; currentPosition.IsAirborne = false; currentPosition.IsEngineStarted = false; currentPosition.Latitude = 44; currentPosition.Longitude = 11; currentPosition.Nav1 = 112.2; currentPosition.Nav1DME = 0.7; currentPosition.Nav1Glide = 0; currentPosition.Nav1OBS = 270; currentPosition.Nav1Radial = 291; currentPosition.Nav1Localizer = 50; currentPosition.QNH = 1013; currentPosition.RadioAltitude = 0; currentPosition.Timestamp = DateTime.Now; currentPosition.TrueAirspeedSpeed = currentPosition.IndicatedAirspeedSpeed; currentPosition.ThrottlePercentage = 75; toBeRaised.Position = currentPosition; FlightSimEvent(toBeRaised); return; #endif FSUIPCConnection.Process(); //issue 63 #region gestione di ivap IvapStatus.Instance.IsRunning = ((byte)ivapDetected.Value == 1); if (IvapStatus.Instance.IsRunning) { IvapStatus.Instance.IvapTrasponderIsInStandby = ((byte)ivapTrasponder.Value == 1); } else { IvapStatus.Instance.IvapTrasponderIsInStandby = true; } #endregion //issue 11 #region versione FS switch ((short)ivapTrasponder.Value) { case 7: IvapStatus.Instance.FSVersion = FlightSimulatorVersion.FS2004; break; case 9: IvapStatus.Instance.FSVersion = FlightSimulatorVersion.FSX; break; default: IvapStatus.Instance.FSVersion = FlightSimulatorVersion.Altro; break; } #endregion //ground speed currentPosition.GroundSpeed = ((double)groundspeed.Value / 65536d) * 1.943844492; //Knots //airspeed currentPosition.TrueAirspeedSpeed = ((double)airspeed.Value / 128); //issue 38 currentPosition.IndicatedAirspeedSpeed = ((double)indicatedAirspeed.Value / 128); //latitude currentPosition.Latitude = (double)latitude.Value * 90d / (10001750d * 65536d * 65536d); //longitude currentPosition.Longitude = (double)longitude.Value * 360d / (65536d * 65536d * 65536d * 65536d); //altitude currentPosition.Altitude = (int)altitude.Value * 3.28d; //radio altitude currentPosition.RadioAltitude = (double)radioAlt.Value / 65536; //heading currentPosition.Heading = heading.Value * 360d / (65536d * 65536d); if (currentPosition.Heading < 0) { currentPosition.Heading = 360 + currentPosition.Heading; } //QNH letto sull'altimetro currentPosition.QNH = (int)qnh.Value / 16; //NAV 1 currentPosition.Nav1 = 100 + ReadBCD((short)nav1.Value); currentPosition.Nav1Localizer = (short)(byte)nav1_loc.Value; if (currentPosition.Nav1Localizer > 128) { currentPosition.Nav1Localizer = (short)(-256 + currentPosition.Nav1Localizer); } currentPosition.Nav1Glide = (byte)nav1_glide.Value; currentPosition.Nav1OBS = (short)nav1_obs.Value; if (currentPosition.Nav1OBS < 0) { currentPosition.Nav1OBS = (180 - currentPosition.Nav1OBS); } currentPosition.Nav1Radial = ((short)nav1_radial.Value) * 360 / 65536; if (currentPosition.Nav1Radial < 0) { currentPosition.Nav1Radial = (180 - currentPosition.Nav1Radial); } currentPosition.Nav1DME = ReadDME((byte[])nav1_dme.Value); //Throttle if ((short)throttle1.Value <= 0) { currentPosition.ThrottlePercentage = 0; //inversori di spinta inseriti } else { currentPosition.ThrottlePercentage = (int)((short)throttle1.Value / 16384d * 100); } //Autopilot currentPosition.AutopilotHeading = ((short)autopilot_hdg.Value) * 360 / 65536; if (currentPosition.AutopilotHeading < 0) { currentPosition.AutopilotHeading = (180 - currentPosition.AutopilotHeading); } //fuel currentPosition.AvailableFuel = 0; currentPosition.AvailableFuel += fuelCap1.Value * ((double)(fuelQty1.Value) / (128 * 65536)); currentPosition.AvailableFuel += fuelCap2.Value * ((double)(fuelQty2.Value) / (128 * 65536)); currentPosition.AvailableFuel += fuelCap3.Value * ((double)(fuelQty3.Value) / (128 * 65536)); currentPosition.AvailableFuel += fuelCap4.Value * ((double)(fuelQty4.Value) / (128 * 65536)); currentPosition.AvailableFuel += fuelCap5.Value * ((double)(fuelQty5.Value) / (128 * 65536)); currentPosition.AvailableFuel += fuelCap6.Value * ((double)(fuelQty6.Value) / (128 * 65536)); currentPosition.AvailableFuel += fuelCap7.Value * ((double)(fuelQty7.Value) / (128 * 65536)); toBeRaised.Position = currentPosition; //sollevo l'evento FlightSimEvent(toBeRaised); //gestione stato airborne currentPosition.IsAirborne = (airborne.Value == 0) || /*issue 36*/ (currentPosition.RadioAltitude > 10); if (!LastPosition.IsAirborne && currentPosition.IsAirborne) { //decollato FSEvent to = new TakeOffEvent(); FlightSimEvent(to); } else if (LastPosition.IsAirborne && !currentPosition.IsAirborne) { //atterrato FSEvent ldg = new LandingEvent(); FlightSimEvent(ldg); } //gestione dello stato del motore (ed invio eventi associati) issue 29 currentPosition.IsEngineStarted = currentPosition.AvailableFuel < LastPosition.AvailableFuel; if (!LastPosition.IsEngineStarted && currentPosition.IsEngineStarted) { //il motore si è acceso FSEvent evt = new EngineStartUpEvent(); FlightSimEvent(evt); } else if (LastPosition.IsEngineStarted && !currentPosition.IsEngineStarted) { if (isFirsPosWithNoFuelFlow) { //visto che è la prima volta che questo accade, lascio una tolleranza di un giro //issue 44 isFirsPosWithNoFuelFlow = false; currentPosition.IsEngineStarted = true; } else { //il motore si è spento davvero FSEvent evt = new EngineShutDownEvent(); FlightSimEvent(evt); isFirsPosWithNoFuelFlow = true; } } //gestione del movimento (ed invio eventi associati) issue 29 //l'1 invece dello 0 è dovuto a potenziali errori di arrotondamento nel calcolo della velocità if (LastPosition.GroundSpeed <= 1 && currentPosition.GroundSpeed > 1) { //inizia a muoversi FSEvent evt = new StartMovingEvent(); FlightSimEvent(evt); } else if (LastPosition.GroundSpeed >= 1 && currentPosition.GroundSpeed < 1) { //si ferma FSEvent evt = new EndMovingEvent(); FlightSimEvent(evt); } LastPosition = currentPosition; } catch (Exception ex) { ErrorOccurred(ex); } }
/// <summary> /// Metodo fondamentale: è il listener che viene notificato ogni volta che si ricevono dati "freschi" /// da FS, quindi è qui che si decide cosa fa l'applazione in risposta a ciascuna situazione /// </summary> /// <param name="e">L'evento di FS da gestire. Consultare la tassonomia con capostipite FSEvent /// per sapere quali sono gli eventi gestibili</param> private void HandleEvent(FSEvent e) { lock (this) { if (e is PositioningEvent) { PositioningEvent pe = (PositioningEvent)e; status.CurrentPosition = pe.Position; if (PositionUpdated != null) { PositionUpdated(pe.Position); } } else if (e is TakeOffEvent) { //se sono già airborne o atterrato vuol dire che è un touch 'n' go o un goaround, quindi non faccio nulla if (status.CurrentStatus <= FlightStates.TakeOffTaxi)//il <= inserito per issue 51 { status.DepartureTime = e.Timestamp; } status.CurrentStatus = FlightStates.Airborne; //isssue 63 if (IPSConfiguration.AUTO_TRASPONDER) { if (IvapStatus.Instance.IsRunning && IvapStatus.Instance.IvapTrasponderIsInStandby) { //ivap è presente ma il trasponder è in Sierra, quindi lo metto in charlie flightSim.SetTrasponderMode(true); } } } else if (e is LandingEvent) { if (status.CurrentStatus == FlightStates.Airborne) { status.CurrentStatus = FlightStates.Landed; status.ArrivalTime = e.Timestamp; //in questo modo l'ultimo atterraggio è sempre quello che fa fede per l'ora di arrivo //isssue 63: if (IPSConfiguration.AUTO_TRASPONDER) { if (IvapStatus.Instance.IsRunning && !IvapStatus.Instance.IvapTrasponderIsInStandby) { //ivap è presente ma il trasponder è in Sierra, quindi lo metto in charlie flightSim.SetTrasponderMode(false); } } } } else if (e is EngineStartUpEvent) { //se è la prima accensione la considero come quella "buona" if (status.CurrentStatus == FlightStates.Before_Departed) { status.CurrentStatus = FlightStates.Engine_Started; status.DepartureFuel = status.CurrentFuel; } } else if (e is EngineShutDownEvent) { //seconda condizione del primo if è aggiunta per issue 49 //se c'è vento l'indicata non scende sotto 1 e quindi non si passa mai nello stato "ai blocchi" if (status.CurrentStatus == FlightStates.OnBlocks || status.CurrentStatus == FlightStates.Landed) { status.CurrentStatus = FlightStates.EngineOff; status.ArrivalFuel = status.CurrentFuel; } else if (status.CurrentStatus == FlightStates.Engine_Started || status.CurrentStatus == FlightStates.TakeOffTaxi) { status.CurrentStatus = FlightStates.Before_Departed; } } else if (e is StartMovingEvent) { if (status.CurrentStatus <= FlightStates.Engine_Started) { status.CurrentStatus = FlightStates.TakeOffTaxi; //issue 54 if (status.DepartureFuel == 0) { status.DepartureFuel = status.CurrentFuel; } } else if (status.CurrentStatus == FlightStates.OnBlocks) { //vuol dire che non ero realmente ai blocchi, ma che mi ero solo arrestato durante il taxi dopo l'atterraggio status.CurrentStatus = FlightStates.Landed; } //negli altri casi è un normale stop durante il rullaggio di partenza o di arrivo } else if (e is EndMovingEvent) { if (status.CurrentStatus == FlightStates.Landed || status.CurrentStatus == FlightStates.OnBlocks) { //la seconda condizione è per evitare di avere problemi se mi fermo durante il taxi dopo l'atterraggio status.CurrentStatus = FlightStates.OnBlocks; //l'ultimo tra on-bock e shutdown motori determina l'ultimo calcolo di fuel status.ArrivalFuel = status.CurrentFuel; } } else { throw new InvalidOperationException("non implementato"); } if (!(e is PositioningEvent)) { Log(e.GetType().FullName.Substring(e.GetType().FullName.LastIndexOf('.'))); } } //rinfresco la view viewMainForm.mainPanel.DrawStatus(status); utilBar.UpdateView(status); }