
Andy B.
Members-
Posts
82 -
Joined
-
Last visited
-
Days Won
3
Andy B. last won the day on June 5 2024
Andy B. had the most liked content!
Profile Information
-
Gender
Male
-
Location
Virginia, United States
Recent Profile Visitors
The recent visitors block is disabled and is not being shown to other users.
Andy B.'s Achievements
-
Event parameters for PMDG777 flight deck knobs
Andy B. replied to Andy B.'s topic in FSUIPC Client DLL for .NET
I did, and it didn't work. I tried with a button click to increase it by 1 or 2, then I tried hooking up a keydown event in a textbox to see if that would work. Still doesn't work. These aren't the only 'knobs' I am having problems with either. The cargo temp panel in overhead maint has temp knobs. They are giving me the same problem. Sending any type of value fails unless the 777 directly changes it with a state load. -
Andy B. started following Offset.ValueChanged and triggering events , Event parameters for PMDG777 flight deck knobs , Proto buf type (6) and 1 other
-
Hi, I am trying to set the position of the lighting knobs in the PMDG777 for MSFS2020. Unfortunately, nothing I do seems to work. I know it has something to do with the parameters I am sending, because the values change in our app when the 777 changes the values itself. EG: when loading a panel state. Here is an example from the master brightness knob. The other ones like circiut breaker, glare shield, overhead, and dome light are probably the same. The SDK states that the valid values are 0-100 for all of them. However, sending a left click, right click, mouse wheel up, mouse wheel down, left drag, or right drag don't change the values. What do I send for the parameters? I figured I would come here and ask because I am using your library. Here is what I have (C#) in dotnet 9.0. FSUIPCConnection.SendControlToFS(PMDG_777X_Control.EVT_OH_MASTER_BRIGHT_ROTATE, ...);
-
Can you let me know when you are done?
-
Yes, it appears to be stable. I tried it around 20 times in the debugger, and none of them threw the protobuf error. Out of interest, is the entire airports database thread safe, or only parts of it? Just wondering, because we use it in a multi threaded environment quite often.
-
I don't think this has anything to do with make runways, but this is what I get now. I never modified my code, so it is the same as before. System.InvalidOperationException HResult=0x80131509 Message=Collection was modified; enumeration operation may not execute. Source=System.Private.CoreLib StackTrace: at System.ThrowHelper.ThrowInvalidOperationException_InvalidOperation_EnumFailedVersion() at System.Collections.Generic.List`1.ForEach(Action`1 action) at FSUIPC.FsAirport.LoadComponents(Byte ClassInstance, AirportComponents Components) at FSUIPC.FsAirportCollection.GetPlayerLocation(Byte ClassInstance, AirportComponents Components) at FSUIPC.FsAirportCollection.GetPlayerLocation(AirportComponents Components) at tfm.Airplanes.Airplane.get_CurrentLocation() in C:\Users\a_bor\Documents\GitHub\talking-flight-monitor\source\Airplanes\Airplane.cs:line 155 at tfm.Airplanes.Airplane.<DetectILS>d__191.MoveNext() in C:\Users\a_bor\Documents\GitHub\talking-flight-monitor\source\Airplanes\Airplane.cs:line 1403
-
Hi, It happens with most airports, especially in the United States. A prime example that gives me this problem is KSFO, KLAX, or anything on the west coast. Sometimes KJFK and KBOS do it, but it is almost nonexistent. I also noticed that when I pull out if the player is on the runway, and what runway they are on, I get unpredictable results. A good example is runways 24 and 25 at KSFO. Going into KRNO last night to runway 17R, my PMDG738 had CMDA and CMDB on, landed on the runway, but the scenery extract from the airports database was telling me that I wasn't on a runway at all. Visually, the landing was perfect. I am running the newest library version. This is MSFS2020. We aren't using 3rd party scenery, only the MSFS2020 default.
-
Hi, I get the following exception when doing the following: Public PlayerInfo CurrentLocation { get => FSUIPCConnection.AirportsDatabase.GetPlayerLocation(AirportComponents.All); } Here is the error I get. Strangely enough, the airports database built without problems. How would I fix this? The only way I get the below is to run it through the debugger in Visual Studio 2022. ProtoBuf.ProtoException HResult=0x80131500 Message=Invalid wire-type (6); this usually means you have over-written a file without truncating or setting the length; see https://stackoverflow.com/q/2152978/23354 Source=protobuf-net.Core StackTrace: at ProtoBuf.ProtoReader.State.ThrowProtoException(String message) at ProtoBuf.ProtoReader.State.ThrowWireTypeException() at ProtoBuf.Internal.Serializers.SimpleCompiledSerializer`1.ProtoBuf.Serializers.ISerializer<T>.Read(State& state, T value) at ProtoBuf.ProtoReader.State.ReadAsRoot[T](T value, ISerializer`1 serializer) at ProtoBuf.Internal.DynamicStub.ConcreteStub`1.TryDeserialize(ObjectScope scope, TypeModel model, State& state, Object& value) at ProtoBuf.Internal.DynamicStub.TryDeserialize(ObjectScope scope, Type type, TypeModel model, State& state, Object& value) at ProtoBuf.Meta.TypeModel.Deserialize(ObjectScope scope, State& state, Type type, Object value) at ProtoBuf.Meta.TypeModel.DeserializeWithLengthPrefix(Stream source, Object value, Type type, PrefixStyle style, Int32 expectedField, TypeResolver resolver, Int64& bytesRead, Boolean& haveObject, SerializationContext context) at ProtoBuf.Meta.TypeModel.DeserializeWithLengthPrefix(Stream source, Object value, Type type, PrefixStyle style, Int32 expectedField, TypeResolver resolver, Int64& bytesRead) at ProtoBuf.Meta.TypeModel.DeserializeWithLengthPrefix(Stream source, Object value, Type type, PrefixStyle style, Int32 fieldNumber) at ProtoBuf.Serializer.DeserializeWithLengthPrefix[T](Stream source, PrefixStyle style, Int32 fieldNumber) at FSUIPC.DataStore.ReadSelection[T](String fileName, List`1 collection, String ICAO) at FSUIPC.FsAirport.LoadComponents(Byte ClassInstance, AirportComponents Components) at FSUIPC.FsAirportCollection.GetPlayerLocation(Byte ClassInstance, AirportComponents Components) at FSUIPC.FsAirportCollection.GetPlayerLocation(AirportComponents Components) at tfm.Airplanes.Airplane.get_CurrentLocation() in C:\Users\a_bor\Documents\GitHub\talking-flight-monitor\source\Airplanes\Airplane.cs:line 155 at tfm.Airplanes.Airplane.<DetectILS>d__191.MoveNext() in C:\Users\a_bor\Documents\GitHub\talking-flight-monitor\source\Airplanes\Airplane.cs:line 1403 The relevant line of code is: if (tfm.Properties.Settings.Default.ReadILS && !this.CurrentLocation.OnGround) Found in the method below: protected async virtual void DetectILS() { if (_isFirstRun) return; { if (tfm.Properties.Settings.Default.ReadILS && !this.CurrentLocation.OnGround) { // Detect the glide slope. if (_nav1GSOffset.Value == 1 && _glideSlopeDetected == false) { AudioManager.Output("Glide slope is alive"); _glideSlopeDetected = true; } // Detect the localizer. if (NavRadios.RadioFlags[7] && _hasLocalizer == false) { AudioManager.Output("Nav1 has localizer"); _hasLocalizer = true; } // The localizer is alive. if (NavRadios.Nav1Signal == 256 && NavRadios.RadioFlags[7] && _localizerDetected == false) { //double magvar = (double)_magneticVariationOffset.Value * 360d / 65536d; //double rwyHeading = (double)NavRadios.InverseRunwayHeading * 360d / 65536d + 180d - magvar; //rwyHeading = Math.Truncate(rwyHeading); if (FlightPlanning.FlightPlan.DestinationRunway != null) { var course = NavRadios.Nav1Course; AudioManager.Output($"Localizer is alive: Course {course}"); _localizerDetected = true; _ilsTimer.AutoReset = true; _ilsTimer.Enabled = true; } else { AudioManager.Output("Warning! Destination runway not set."); } } // Has the glide slope. if (NavRadios.AutoPilotRadioFlags[6] && _hasGlideSlope == false) { AudioManager.Output("Nav1 has glide slope"); _hasGlideSlope = true; } } else { _ilsTimer.Enabled = false; _hasGlideSlope = false; _hasLocalizer = false; _localizerDetected = false; _glideSlopeDetected = false; } } }
-
Moving aircraft to gates or runways
Andy B. replied to Andy B.'s topic in FSUIPC Client DLL for .NET
Yes, it works just fine in my setup. My aircraft heading and the runway heading might be off by a degree or so, but I never ran off the runway like that. One of my staff members reported some time ago that he used our app to reposition to the runway, attempted o takeoff, and crashed into something. When he reloaded and used GSX or another app to reposition to the runway, he didn't crash. Nobody can confirm if it is because make runways data is bad, because our app rounds headings to the nearest degree, or both, but I guess it is a problem. I can't even confirm if our app is to blame for his crash or many of our users getting placed off the centerline. -
Hi, When using the built-in move aircraft method for a runway, users are reporting that it is putting the aircraft to the left or right of the centerline, not directly on the centerline. This is also reported by Vatsim ATC as well. Here is a little sample of how we use the MoveAircraftHere method for a runway. Is there a way to get i to put us on the centerline of the runway? Users are also reporting that it puts them in a strange location on the runway such as a taxiway or not on the lineup or holding point. if(row is RunwayDataGridRow runwayData) { var airport = FSUIPCConnection.AirportsDatabase.Airports[airportIcaoTextBox.Text.ToUpper()]; airport.LoadComponents(AirportComponents.Runways); var runway = airport.Runways[runwayData.ID.ToString()]; runway.MoveAircraftHere(false); this.Close(); }
-
Offset.ValueChanged and triggering events
Andy B. replied to Andy B.'s topic in FSUIPC Client DLL for .NET
Got this to work. All I had to do is add a firstRun flag. Set it to true by default, then at the end of the constructor, set it to false after a 500ms delay. Then, in each event handler implementation, put this at the top of the event handler. Private Void AnnounceSomething(Object sender, PMDG777ValueChangedEventArgs e) { if(isFirstRun) return; // Rest of the code. } Works perfectly, and it doesn't interfere with the rest of the working code. I still am going to create public methods for attaching/detaching different groups of events in case I need to use them. -
Offset.ValueChanged and triggering events
Andy B. replied to Andy B.'s topic in FSUIPC Client DLL for .NET
So, for example, in my main window, I have a menu item that when clicked, creates an instance of this class and assigns it to a property in another class. Once that is done, the menu item's click event can attach the event handlers. This should stop the spam when the 777 loads? -
I have event handlers that handle the announcement of offset values when they change. So far, everything is working perfectly. However, when starting our app, we get announcements for different 777 controls. Some of them include MCP heading, MCP speed, MCP altitude, flight director status, and auto throttle left/right status. Given the class partials below, is there a way to stop these announcements while the class instance is created? We need it to be silent during startup. I tried setting a loaded or initialized flag, but that doesn't really work. It seems that when the timer starts, it triggers the event handlers in mass for the first time - this is what we need to deal with I think. using tfm.Utilities; using tfm.Airplanes.PMDG777.Shared; using System.Windows.Threading; using FSUIPC; using tfm.Airplanes; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using NLog; namespace tfm.Airplanes.PMDG777 { public partial class PMDG777: Airplane { private bool isInitialized = false; // Parking brake. public KeyValuePair<object, string> ParkingBrake { get { KeyValuePair<object, string> item = new KeyValuePair<object, string>(); if(_offsets.BRAKES_ParkingBrakeLeverOn.Value == 0) { item = new KeyValuePair<object, string>(0, "off"); } else if(_offsets.BRAKES_ParkingBrakeLeverOn.Value == 1) { item = new KeyValuePair<object, string>(1, "on"); } return item; } } // Flaps public KeyValuePair<object, string> Flaps { get { KeyValuePair<object, string> item = new KeyValuePair<object, string>(); if (_offsets.FCTL_Flaps_Lever.Value == 0) item = new KeyValuePair<object, string>(0, "up"); else if (_offsets.FCTL_Flaps_Lever.Value == 1) item = new KeyValuePair<object, string>(1, "1"); else if (_offsets.FCTL_Flaps_Lever.Value == 2) item = new KeyValuePair<object, string>(2, "5"); else if (_offsets.FCTL_Flaps_Lever.Value == 3) item = new KeyValuePair<object, string>(3, "15"); else if (_offsets.FCTL_Flaps_Lever.Value == 4) item = new KeyValuePair<object, string>(4, "20"); else if (_offsets.FCTL_Flaps_Lever.Value == 5) item = new KeyValuePair<object, string>(5, "25"); else if (_offsets.FCTL_Flaps_Lever.Value == 6) item = new KeyValuePair<object, string>(6, "30"); return item; } } public CDU1 CDU1 { get => _cdu1; } public CDU2 CDU2 { get => _cdu2; } // Events. #region public EventHandler<PMDG777ValueChangedEventArgs> ParkingBrakeChanged; public EventHandler<PMDG777ValueChangedEventArgs> FlapsChanged; #endregion public PMDG777() { logger.Info($"Starting support for {this.Title}"); // Start timer. logger.Info("Starting services."); _timer = new DispatcherTimer() { Interval = TimeSpan.FromMilliseconds(500), }; _timer.Tick += ProcessOffsets; _timer.Start(); AttachEventHandlers(); Task.Delay(500).ContinueWith(t => { isInitialized = true; }); } // Timer implementation. private void ProcessOffsets(object sender, EventArgs e) { _offsets.RefreshData(); // parking brake. if (_offsets.BRAKES_ParkingBrakeLeverOn.ValueChanged) { ParkingBrakeChanged?.Invoke(this, new PMDG777ValueChangedEventArgs(ParkingBrake)); } // Flaps lever. if (_offsets.FCTL_Flaps_Lever.ValueChanged) { FlapsChanged?.Invoke(this, new PMDG777ValueChangedEventArgs(this.Flaps)); } // MCP speed (indicated/mach). if (_offsets.MCP_IASMach.ValueChanged) { MCPSpeedChanged?.Invoke(this, new PMDG777ValueChangedEventArgs(MCPSpeed)); } // MCP speed intervene. if (_offsets.MCP_IASBlan.ValueChanged) { MCPSpeedInterveneChanged?.Invoke(this, new PMDG777ValueChangedEventArgs(MCPSpeedIntervene)); } // MCP heading if (_offsets.MCP_Heading.ValueChanged) MCPHeadingChanged?.Invoke(this, new PMDG777ValueChangedEventArgs(MCPHeading)); // MCP altitude. if (_offsets.MCP_Altitude.ValueChanged) MCPAltitudeChanged?.Invoke(this, new PMDG777ValueChangedEventArgs(MCPAltitude)); // MCP vertical speed. if (_offsets.MCP_VertSpeed.ValueChanged) MCPVerticalSpeedChanged?.Invoke(this, new PMDG777ValueChangedEventArgs(MCPVerticalSpeed)); // MCP FPA. if (_offsets.MCP_FPA.ValueChanged) MCPFPAChanged.Invoke(this, new PMDG777ValueChangedEventArgs(MCPFPA)); // MCP vertical speed intervene if (_offsets.MCP_VertSpeedBlank.ValueChanged) MCPVerticalSpeedInterveneChanged?.Invoke(this, new PMDG777ValueChangedEventArgs(MCPVerticalSpeedIntervene)); // Flight director switches. if (_offsets.MCP_FD_Sw_On[0].ValueChanged) LeftFlightDirectorSwitchChanged?.Invoke(this, new PMDG777ValueChangedEventArgs(LeftFlightDirectorSwitch)); if (_offsets.MCP_FD_Sw_On[1].ValueChanged) RightFlightDirectorSwitchChanged?.Invoke(this, new PMDG777ValueChangedEventArgs(RightFlightDirectorSwitch)); // Auto throttle switches. if (_offsets.MCP_ATArm_Sw_On[0].ValueChanged) LeftAutoThrottleSwitchChanged?.Invoke(this, new PMDG777ValueChangedEventArgs(LeftAutoThrottleSwitch)); if (_offsets.MCP_ATArm_Sw_On[1].ValueChanged) RightAutoThrottleSwitchChanged?.Invoke(this, new PMDG777ValueChangedEventArgs(RightAutoThrottleSwitch)); // Bank limit selector. if (_offsets.MCP_BankLimitSel.ValueChanged) BankLimitSelectorChanged?.Invoke(this, new PMDG777ValueChangedEventArgs(BankLimitSelector)); // Disengage bar. if (_offsets.MCP_DisengageBar.ValueChanged) DisengageBarChanged?.Invoke(this, new PMDG777ValueChangedEventArgs(DisengageBar)); // MCP heading mode (HDG/TRK). if (_offsets.MCP_HDGDial_Mode.ValueChanged) MCPHeadingModeChanged?.Invoke(this, new PMDG777ValueChangedEventArgs(MCPHeadingMode)); // MCP vertical speed mode. if (_offsets.MCP_VSDial_Mode.ValueChanged) MCPVerticalSpeedModeChanged(this, new PMDG777ValueChangedEventArgs(MCPVerticalSpeedMode)); // Auto pilot annunciators. if (_offsets.MCP_annunAP[0].ValueChanged) LeftAutoPilotAnnunciatorChanged?.Invoke(this, new PMDG777ValueChangedEventArgs(LeftAutoPilotAnnunciator)); if (_offsets.MCP_annunAP[1].ValueChanged) RightAutoPilotAnnunciatorChanged?.Invoke(this, new PMDG777ValueChangedEventArgs(RightAutoPilotAnnunciator)); // Auto throttle annunciator. if (_offsets.MCP_annunAT.ValueChanged) AutoThrottleAnnunciatorChanged?.Invoke(this, new PMDG777ValueChangedEventArgs(AutoThrottleAnnunciator)); // LNav annunciator. if (_offsets.MCP_annunLNAV.ValueChanged) LNavAnnunciatorChanged?.Invoke(this, new PMDG777ValueChangedEventArgs(LNavAnnunciator)); // VNav annunciator. if (_offsets.MCP_annunVNAV.ValueChanged) VNavAnnunciatorChanged?.Invoke(this, new PMDG777ValueChangedEventArgs(VNavAnnunciator)); // Level change annunciator. if (_offsets.MCP_annunFLCH.ValueChanged) LevelChangeAnnunciatorChanged?.Invoke(this, new PMDG777ValueChangedEventArgs(LevelChangeAnnunciator)); // Heading hold annunciator. if (_offsets.MCP_annunHDG_HOLD.ValueChanged) HeadingHoldAnnunciatorChanged?.Invoke(this, new PMDG777ValueChangedEventArgs(HeadingHoldAnnunciator)); // Vertical speed annunciator. if (_offsets.MCP_annunVS_FPA.ValueChanged) VerticalSpeedAnnunciatorChanged?.Invoke(this, new PMDG777ValueChangedEventArgs(VerticalSpeedAnnunciator)); // Altitude hold annunciator. if (_offsets.MCP_annunALT_HOLD.ValueChanged) AltitudeHoldAnnunciatorChanged?.Invoke(this, new PMDG777ValueChangedEventArgs(AltitudeHoldAnnunciator)); // Localizer hold annunciator. if (_offsets.MCP_annunLOC.ValueChanged) LocalizerAnnunciatorChanged?.Invoke(this, new PMDG777ValueChangedEventArgs(LocalizerAnnunciator)); // Approach mode annunciator. if (_offsets.MCP_annunAPP.ValueChanged) ApproachModeAnnunciatorChanged?.Invoke(this, new PMDG777ValueChangedEventArgs(ApproachModeAnnunciator)); } // Event implementations. #region private void AnnounceParkingBrake(object sender, PMDG777ValueChangedEventArgs e) { Task.Run(() => AudioManager.Output($"Parking brake {e.NewValue.Value}")); } private void AnnounceFlaps(object sender, PMDG777ValueChangedEventArgs e) { Task.Run(() => AudioManager.Output($"Flaps {e.NewValue.Value}")); } #endregion private void AttachEventHandlers() { #region ParkingBrakeChanged += AnnounceParkingBrake; FlapsChanged += AnnounceFlaps; MCPSpeedChanged += AnnounceMCPSpeed; MCPSpeedInterveneChanged += AnnounceMCPSpeedIntervene; MCPHeadingChanged += AnnounceMCPHeading; MCPAltitudeChanged += AnnounceMCPAltitude; MCPVerticalSpeedChanged += AnnounceMCPVerticalSpeed; MCPFPAChanged += AnnounceMCPFPA; MCPVerticalSpeedInterveneChanged += AnnounceMCPVerticalSpeedIntervene; LeftFlightDirectorSwitchChanged += AnnounceLeftFlightDirectorSwitch; RightFlightDirectorSwitchChanged += AnnounceRightFlightDirectorSwitch; LeftAutoThrottleSwitchChanged += AnnounceLeftAutothrottleSwitch; RightAutoThrottleSwitchChanged += AnnounceRightAutoThrottleSwitch; BankLimitSelectorChanged += AnnounceBankLimitSelector; DisengageBarChanged += AnnounceDisengageBar; MCPHeadingModeChanged += AnnounceMCPHeadingMode; MCPVerticalSpeedModeChanged += AnnounceMCPVerticalSpeedMode; LeftAutoPilotAnnunciatorChanged += AnnounceLeftAutoPilotAnnunciator; RightAutoPilotAnnunciatorChanged += AnnounceRightAutoPilotAnnunciator; AutoThrottleAnnunciatorChanged += AnnounceAutoThrottleAnnunciator; LNavAnnunciatorChanged += AnnounceLNavAnnunciator; VNavAnnunciatorChanged += AnnounceVNavAnnunciator; LevelChangeAnnunciatorChanged += AnnounceLevelChangeAnnunciator; HeadingHoldAnnunciatorChanged += AnnounceHeadingHoldAnnunciator; VerticalSpeedAnnunciatorChanged += AnnounceVerticalSpeedAnnunciator; AltitudeHoldAnnunciatorChanged += AnnounceAltitudeHoldAnnunciator; LocalizerAnnunciatorChanged += AnnounceLocalizerAnnunciator; ApproachModeAnnunciatorChanged += AnnounceApproachModeAnnunciator; #endregion } } } using tfm.Airplanes.Shared; using FSUIPC; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using tfm.Airplanes.PMDG777.Shared; using tfm.Utilities; namespace tfm.Airplanes.PMDG777 { public partial class PMDG777: Airplane { // Properties #region // MCP speed. public KeyValuePair<object, string> MCPSpeed { get { KeyValuePair<object, string> item = new KeyValuePair<object, string>(); if (_offsets.MCP_IASMach.Value < 10) item = new KeyValuePair<object, string>(_offsets.MCP_IASMach.Value, "mach"); else item = new KeyValuePair<object, string>(_offsets.MCP_IASMach.Value, "indicated"); return item; } } // Speed intervene. public KeyValuePair<object, string> MCPSpeedIntervene { get { KeyValuePair<object, string> item = new KeyValuePair<object, string>(); item = _offsets.MCP_IASBlan.Value == 0 ? new KeyValuePair<object, string>(0, "on") : new KeyValuePair<object, string>(1, "off"); return item; } } // MCP heading. public KeyValuePair<object, string> MCPHeading { get => new KeyValuePair<object, string>(_offsets.MCP_Heading.Value, _offsets.MCP_Heading.Value.ToString()); } // MCP altitude public KeyValuePair<object, string> MCPAltitude { get => new KeyValuePair<object, string>(_offsets.MCP_Altitude.Value, _offsets.MCP_Altitude.Value.ToString()); } // MCP vertical speed. public KeyValuePair<object, string> MCPVerticalSpeed { get => new KeyValuePair<object, string>(_offsets.MCP_VertSpeed.Value, _offsets.MCP_VertSpeed.Value.ToString()); } // MCP FPA. public KeyValuePair<object, string> MCPFPA { get => new KeyValuePair<object, string>(_offsets.MCP_FPA.Value, _offsets.MCP_FPA.Value.ToString()); } // MCP vertical speed intervene public KeyValuePair<object, string> MCPVerticalSpeedIntervene { get { KeyValuePair<object, string> item = new KeyValuePair<object, string>(); if (_offsets.MCP_VertSpeedBlank.Value == 0) item = new KeyValuePair<object, string>(0, "on"); else item = new KeyValuePair<object, string>(1, "off"); return item; } } // Left flight director switch. public KeyValuePair<object, string> LeftFlightDirectorSwitch { get { KeyValuePair<object, string> item = new KeyValuePair<object, string>(); if (_offsets.MCP_FD_Sw_On[0].Value == 0) item = new KeyValuePair<object, string>(0, "off"); else item = new KeyValuePair<object, string>(1, "on"); return item; } } // Right flight director switch. public KeyValuePair<object, string> RightFlightDirectorSwitch { get { KeyValuePair<object, string> item = new KeyValuePair<object, string>(); if (_offsets.MCP_FD_Sw_On[1].Value == 0) item = new KeyValuePair<object, string>(0, "off"); else item = new KeyValuePair<object, string>(1, "on"); return item; } } // Left auto throttle switch. public KeyValuePair<object, string> LeftAutoThrottleSwitch { get => _offsets.MCP_ATArm_Sw_On[0].Value == 0 ? new KeyValuePair<object, string>(0, "disarmed") : new KeyValuePair<object, string>(1, "armed"); } // Right auto throttle switch. public KeyValuePair<object, string> RightAutoThrottleSwitch { get => _offsets.MCP_ATArm_Sw_On[1].Value == 0 ? new KeyValuePair<object, string>(0, "disarmed") : new KeyValuePair<object, string>(1, "armed"); } // Bank limit selector. public KeyValuePair<object, string> BankLimitSelector { get { KeyValuePair<object, string> item = new KeyValuePair<object, string>(); if (_offsets.MCP_BankLimitSel.Value == 0) item = new KeyValuePair<object, string>(0, "auto"); else if (_offsets.MCP_BankLimitSel.Value == 1) item = new KeyValuePair<object, string>(1, "5"); else if (_offsets.MCP_BankLimitSel.Value == 2) item = new KeyValuePair<object, string>(2, "10"); else if (_offsets.MCP_BankLimitSel.Value == 3) item = new KeyValuePair<object, string>(3, "15"); else if (_offsets.MCP_BankLimitSel.Value == 4) item = new KeyValuePair<object, string>(4, "20"); else if (_offsets.MCP_BankLimitSel.Value == 5) item = new KeyValuePair<object, string>(5, "25"); return item; } } // Disengage bar. public KeyValuePair<object, string> DisengageBar { get => _offsets.MCP_DisengageBar.Value == 0 ? new KeyValuePair<object, string>(0, "off") : new KeyValuePair<object, string>(1, "on"); } // MCP heading mode (HDG/TRK). public KeyValuePair<object, string> MCPHeadingMode { get => _offsets.MCP_HDGDial_Mode.Value == 0 ? new KeyValuePair<object, string>(0, "HDG") : new KeyValuePair<object, string>(1, "TRK"); } // MCP vertical speed mode. public KeyValuePair<object, string> MCPVerticalSpeedMode { get => _offsets.MCP_VSDial_Mode.Value == 0 ? new KeyValuePair<object, string>(0, "VS") : new KeyValuePair<object, string>(1, "FPA"); } // Left Auto pilot annunciator public KeyValuePair<object, string> LeftAutoPilotAnnunciator { get => _offsets.MCP_annunAP[0].Value == 0 ? new KeyValuePair<object, string>(0, "off") : new KeyValuePair<object, string>(1, "on"); } // Right auto pilot annunciator public KeyValuePair<object, string> RightAutoPilotAnnunciator { get => _offsets.MCP_annunAP[1].Value == 0 ? new KeyValuePair<object, string>(0, "off") : new KeyValuePair<object, string>(1, "on"); } // Auto throttle annunciator. public KeyValuePair<object, string> AutoThrottleAnnunciator { get => _offsets.MCP_annunAT.Value == 0 ? new KeyValuePair<object, string>(0, "off") : new KeyValuePair<object, string>(1, "on"); } // Lnav public KeyValuePair<object, string> LNavAnnunciator { get => _offsets.MCP_annunLNAV.Value == 0 ? new KeyValuePair<object, string>(0, "off") : new KeyValuePair<object, string>(1, "on"); } // VNav annunciator. public KeyValuePair<object, string> VNavAnnunciator { get => _offsets.MCP_annunVNAV.Value == 0 ? new KeyValuePair<object, string>(0, "off") : new KeyValuePair<object, string>(1, "on"); } // Level change annunciator. public KeyValuePair<object, string> LevelChangeAnnunciator { get => _offsets.MCP_annunFLCH.Value == 0 ? new KeyValuePair<object, string>(0, "off") : new KeyValuePair<object, string>(1, "on"); } // Heading hold annunciator. public KeyValuePair<object, string> HeadingHoldAnnunciator { get => _offsets.MCP_annunHDG_HOLD.Value == 0 ? new KeyValuePair<object, string>(0, "off") : new KeyValuePair<object, string>(1, "on"); } // VS/FPA annunciator. public KeyValuePair<object, string> VerticalSpeedAnnunciator { get => _offsets.MCP_annunVS_FPA.Value == 0 ? new KeyValuePair<object, string>(0, "off") : new KeyValuePair<object, string>(1, "on"); } // Altitude hold annunciator. public KeyValuePair<object, string> AltitudeHoldAnnunciator { get => _offsets.MCP_annunALT_HOLD.Value == 0 ? new KeyValuePair<object, string>(0, "off") : new KeyValuePair<object, string>(1, "on"); } // Localizer annunciator. public KeyValuePair<object, string> LocalizerAnnunciator { get => _offsets.MCP_annunLOC.Value == 0 ? new KeyValuePair<object, string>(0, "off") : new KeyValuePair<object, string>(1, "on"); } // Approach mode annunciator. public KeyValuePair<object, string> ApproachModeAnnunciator { get => _offsets.MCP_annunAPP.Value == 0 ? new KeyValuePair<object, string>(0, "off") : new KeyValuePair<object, string>(1, "on"); } #endregion // Event definitions #region public EventHandler<PMDG777ValueChangedEventArgs> MCPSpeedChanged; public EventHandler<PMDG777ValueChangedEventArgs> MCPSpeedInterveneChanged; public EventHandler<PMDG777ValueChangedEventArgs> MCPHeadingChanged; public EventHandler<PMDG777ValueChangedEventArgs> MCPAltitudeChanged; public EventHandler<PMDG777ValueChangedEventArgs> MCPVerticalSpeedChanged; public EventHandler<PMDG777ValueChangedEventArgs> MCPFPAChanged; public EventHandler<PMDG777ValueChangedEventArgs> MCPVerticalSpeedInterveneChanged; public EventHandler<PMDG777ValueChangedEventArgs> LeftFlightDirectorSwitchChanged; public EventHandler<PMDG777ValueChangedEventArgs> RightFlightDirectorSwitchChanged; public EventHandler<PMDG777ValueChangedEventArgs> LeftAutoThrottleSwitchChanged; public EventHandler<PMDG777ValueChangedEventArgs> RightAutoThrottleSwitchChanged; public EventHandler<PMDG777ValueChangedEventArgs> BankLimitSelectorChanged; public EventHandler<PMDG777ValueChangedEventArgs> DisengageBarChanged; public EventHandler<PMDG777ValueChangedEventArgs> MCPHeadingModeChanged; public EventHandler<PMDG777ValueChangedEventArgs> MCPVerticalSpeedModeChanged; public EventHandler<PMDG777ValueChangedEventArgs> LeftAutoPilotAnnunciatorChanged; public EventHandler<PMDG777ValueChangedEventArgs> RightAutoPilotAnnunciatorChanged; public EventHandler<PMDG777ValueChangedEventArgs> AutoThrottleAnnunciatorChanged; public EventHandler<PMDG777ValueChangedEventArgs> LNavAnnunciatorChanged; public EventHandler<PMDG777ValueChangedEventArgs> VNavAnnunciatorChanged; public EventHandler<PMDG777ValueChangedEventArgs> LevelChangeAnnunciatorChanged; public EventHandler<PMDG777ValueChangedEventArgs> HeadingHoldAnnunciatorChanged; public EventHandler<PMDG777ValueChangedEventArgs> VerticalSpeedAnnunciatorChanged; public EventHandler<PMDG777ValueChangedEventArgs> AltitudeHoldAnnunciatorChanged; public EventHandler<PMDG777ValueChangedEventArgs> LocalizerAnnunciatorChanged; public EventHandler<PMDG777ValueChangedEventArgs> ApproachModeAnnunciatorChanged; #endregion // Event implementations. #region private async void AnnounceMCPSpeed(object sender, PMDG777ValueChangedEventArgs e) { if (isInitialized) { await Task.Run(() => { float speed = (float)e.NewValue.Key; string announcement = string.Empty; announcement = speed < 10 ? $"{e.NewValue.Value} {speed}" : $"{speed} {e.NewValue.Value}"; AudioManager.Output(announcement); }); } } private void AnnounceMCPSpeedIntervene(object sender, PMDG777ValueChangedEventArgs e) { Task.Run(() => AudioManager.Output($"Speed intervene {e.NewValue.Value}")); } private void AnnounceMCPHeading(object sender, PMDG777ValueChangedEventArgs e) { Task.Run(() => AudioManager.Output(e.NewValue.Value)); } private async void AnnounceMCPAltitude(object sender, PMDG777ValueChangedEventArgs e) { await Task.Run(() => AudioManager.Output(MCPAltitude.Value)); } private async void AnnounceMCPVerticalSpeed(object sender, PMDG777ValueChangedEventArgs e) { await Task.Run(() => AudioManager.Output(MCPVerticalSpeed.Value)); } private async void AnnounceMCPFPA(object sender, PMDG777ValueChangedEventArgs e) { await Task.Run(() => AudioManager.Output(e.NewValue.Value)); } private async void AnnounceMCPVerticalSpeedIntervene(object sender, PMDG777ValueChangedEventArgs e) { await Task.Run(() => AudioManager.Output($"Vertical speed intervene {e.NewValue.Value}")); } private async void AnnounceLeftFlightDirectorSwitch(object sender, PMDG777ValueChangedEventArgs e) { await Task.Run(() => AudioManager.Output($"Left flight director {e.NewValue.Value}")); } private async void AnnounceRightFlightDirectorSwitch(object sender, PMDG777ValueChangedEventArgs e) { await Task.Run(() => AudioManager.Output($"Right flight director {e.NewValue.Value}")); } private async void AnnounceLeftAutothrottleSwitch(object sender, PMDG777ValueChangedEventArgs e) { await Task.Run(() => AudioManager.Output($"Left auto throttle {e.NewValue.Value}")); } private async void AnnounceRightAutoThrottleSwitch(object sender, PMDG777ValueChangedEventArgs e) { await Task.Run(() => AudioManager.Output($"Right auto throttle {e.NewValue.Value}")); } private async void AnnounceBankLimitSelector(object sender, PMDG777ValueChangedEventArgs e) { await Task.Run(() => AudioManager.Output($"Bank limit {e.NewValue}")); } private async void AnnounceDisengageBar(object sender, PMDG777ValueChangedEventArgs e) { await Task.Run(() => AudioManager.Output($"Disengage bar {e.NewValue.Value}")); } private async void AnnounceMCPHeadingMode(object sender, PMDG777ValueChangedEventArgs e) { await Task.Run(() => AudioManager.Output($"MCP heading mode {e.NewValue.Value}")); } private async void AnnounceMCPVerticalSpeedMode(object sender, PMDG777ValueChangedEventArgs e) { await Task.Run(() => AudioManager.Output($"Vertical speed mode {e.NewValue.Value}")); } private async void AnnounceLeftAutoPilotAnnunciator(object sender, PMDG777ValueChangedEventArgs e) { if (tfm.Properties.pmdg777_offsets.Default.MCP_annunAP1) { await Task.Run(() => AudioManager.Output($"Left auto pilot annunciator {e.NewValue.Value}")); } } private async void AnnounceRightAutoPilotAnnunciator(object sender, PMDG777ValueChangedEventArgs e) { if (tfm.Properties.pmdg777_offsets.Default.MCP_annunAP2) { await Task.Run(() => AudioManager.Output($"Right auto pilot annunciator {e.NewValue.Value}")); } } private async void AnnounceAutoThrottleAnnunciator(object sender, PMDG777ValueChangedEventArgs e) { if (tfm.Properties.pmdg777_offsets.Default.MCP_annunAT) { await Task.Run(() => AudioManager.Output($"Auto throttle annunciator {e.NewValue.Value}")); } } private async void AnnounceLNavAnnunciator(object sender, PMDG777ValueChangedEventArgs e) { if (tfm.Properties.pmdg777_offsets.Default.MCP_annunLNAV) { await Task.Run(() => AudioManager.Output($"LNav {e.NewValue.Value}")); } } private async void AnnounceVNavAnnunciator(object sender, PMDG777ValueChangedEventArgs e) { if (tfm.Properties.pmdg777_offsets.Default.MCP_annunVNAV) { await Task.Run(() => AudioManager.Output($"VNav {e.NewValue.Value}")); } } private async void AnnounceLevelChangeAnnunciator(object sender, PMDG777ValueChangedEventArgs e) { if (tfm.Properties.pmdg777_offsets.Default.MCP_annunFLCH) { await Task.Run(() => AudioManager.Output($"Level change {e.NewValue.Value}")); } } private async void AnnounceHeadingHoldAnnunciator(object sender, PMDG777ValueChangedEventArgs e) { if (tfm.Properties.pmdg777_offsets.Default.MCP_annunHDG_HOLD) await Task.Run(() => AudioManager.Output($"Heading hold {e.NewValue.Value}")); } private async void AnnounceVerticalSpeedAnnunciator(object sender, PMDG777ValueChangedEventArgs e) { if (tfm.Properties.pmdg777_offsets.Default.MCP_annunVS_FPA) await Task.Run(() => AudioManager.Output($"Vertical speed {e.NewValue.Value}")); } private async void AnnounceAltitudeHoldAnnunciator(object sender, PMDG777ValueChangedEventArgs e) { if (tfm.Properties.pmdg777_offsets.Default.MCP_annunALT_HOLD) await Task.Run(() => AudioManager.Output($"Altitude hold {e.NewValue.Value}")); } private async void AnnounceLocalizerAnnunciator(object sender, PMDG777ValueChangedEventArgs e) { if (tfm.Properties.pmdg777_offsets.Default.MCP_annunLOC) await Task.Run(() => AudioManager.Output($"Localizer hold {e.NewValue.Value}")); } private async void AnnounceApproachModeAnnunciator(object sender, PMDG777ValueChangedEventArgs e) { if (tfm.Properties.pmdg777_offsets.Default.MCP_annunAPP) await Task.Run(() => AudioManager.Output($"Approach mode {e.NewValue.Value}")); } #endregion // Methods for MCP buttons and switches. #region public void SetMCPIndicatedAirspeed(string speedText) { Task.Run(() => { bool isParsed = int.TryParse(speedText, out int speed); if (isParsed) { FSUIPCConnection.SendControlToFS(PMDG_777X_Control.EVT_MCP_IAS_SET, speed); } else { throw new InvalidSpeedException("Invalid speed because it is the wrong format or out of range.", speedText); } }); } public void SetMCPMachSpeed(double speed) { Task.Run(() => { int parameter = (int)(speed / 0.001d); FSUIPCConnection.SendControlToFS(PMDG_777X_Control.EVT_MCP_MACH_SET, parameter); }); } public void AltitudeIntervene() { Task.Run(() => FSUIPCConnection.SendControlToFS(PMDG_777X_Control.EVT_MCP_ALTITUDE_PUSH_SWITCH, ClkL)); } public void VerticalSpeedIntervene() { Task.Run(() => FSUIPCConnection.SendControlToFS(PMDG_777X_Control.EVT_MCP_VS_SWITCH, ClkL)); } public void ToggleVNav() { Task.Run(() => { FSUIPCConnection.SendControlToFS(PMDG_777X_Control.EVT_MCP_VNAV_SWITCH, ClkL); }); } public void ToggleAltitudeHold() { Task.Run(() => { FSUIPCConnection.SendControlToFS(PMDG_777X_Control.EVT_MCP_ALT_HOLD_SWITCH, ClkL); }); } public void ToggleLevelChange() { Task.Run(() => { FSUIPCConnection.SendControlToFS(PMDG_777X_Control.EVT_MCP_LVL_CHG_SWITCH, ClkL); }); } public void SetMCPAltitude(string altitudeText) { bool isAltitudeParsed = ushort.TryParse(altitudeText, out ushort altitude); if (isAltitudeParsed) { FSUIPCConnection.SendControlToFS(PMDG_777X_Control.EVT_MCP_ALT_SET, altitude); } else { throw new InvalidAltitudeException("Altitude is incorrect format or out of range.", altitudeText); } } public void ToggleVerticalSpeedMode() { Task.Run(() => { FSUIPCConnection.SendControlToFS(PMDG_777X_Control.EVT_MCP_VS_FPA_SWITCH, ClkL); }); } public void SetMCPVerticalSpeed(string verticalSpeedText) { Task.Run(() => { bool isParsed = ushort.TryParse(verticalSpeedText, out ushort verticalSpeed); if (isParsed) { FSUIPCConnection.SendControlToFS(PMDG_777X_Control.EVT_MCP_VS_SET, (verticalSpeed + 10000)); } else { throw new InvalidAltitudeException("Vertical speed is an invalid format or out of range.", verticalSpeedText); } }); } public void SetMCPFPA(string fpaText) { Task.Run(() => { bool isParsed = double.TryParse(fpaText, out double FPA); if (isParsed) { FSUIPCConnection.SendControlToFS(PMDG_777X_Control.EVT_MCP_FPA_SET, ((int)((FPA + 10) / 0.1))); } else { throw new InvalidAltitudeException("Invalid FPA because it is an invalid format or out of range.", fpaText); } }); } public void SetMCPHeading(string headingText) { Task.Run(() => { bool isParsed = ushort.TryParse(headingText, out ushort heading); if (isParsed) { FSUIPCConnection.SendControlToFS(PMDG_777X_Control.EVT_MCP_HDGTRK_SET, heading); } else { throw new InvalidHeadingException("Invalid heading because of wrong format or is out of range.", headingText); } }); } public void HeadingIntervene() { Task.Run(() => FSUIPCConnection.SendControlToFS(PMDG_777X_Control.EVT_MCP_HEADING_PUSH_SWITCH, ClkL)); } public void ToggleHeadingHold() { Task.Run(() => { FSUIPCConnection.SendControlToFS(PMDG_777X_Control.EVT_MCP_HDG_HOLD_SWITCH, ClkL); }); } public void ToggleLNav() { Task.Run(() => { FSUIPCConnection.SendControlToFS(PMDG_777X_Control.EVT_MCP_LNAV_SWITCH, ClkL); }); } public void ToggleMCPHeadingMode() { Task.Run(() => { FSUIPCConnection.SendControlToFS(PMDG_777X_Control.EVT_MCP_HDG_TRK_SWITCH, ClkL); }); } public void ToggleLeftFlightDirector() { Task.Run(() => { var action = LeftFlightDirectorSwitch.Value == "off" ? ClkL : ClkR; FSUIPCConnection.SendControlToFS(PMDG_777X_Control.EVT_MCP_FD_SWITCH_L, action); }); } public void ToggleRightFlightDirector() { Task.Run(() => { var action = RightFlightDirectorSwitch.Value == "off" ? ClkL : ClkR; FSUIPCConnection.SendControlToFS(PMDG_777X_Control.EVT_MCP_FD_SWITCH_R, action); }); } public void ToggleLeftAutoPilot() { Task.Run(() => { FSUIPCConnection.SendControlToFS(PMDG_777X_Control.EVT_MCP_AP_L_SWITCH, ClkL); }); } public void ToggleRightAutoPilot() { Task.Run(() => { FSUIPCConnection.SendControlToFS(PMDG_777X_Control.EVT_MCP_AP_R_SWITCH, ClkL); }); } public void ToggleLeftAutoThrottle() { Task.Run(() => { var action = LeftAutoThrottleSwitch.Value == "disarmed" ? ClkL : ClkR; FSUIPCConnection.SendControlToFS(PMDG_777X_Control.EVT_MCP_AT_ARM_SWITCH_L, action); }); } public void ToggleRightAutoThrottle() { Task.Run(() => { var action = RightAutoThrottleSwitch.Value == "disarmed" ? ClkL : ClkR; FSUIPCConnection.SendControlToFS(PMDG_777X_Control.EVT_MCP_AT_ARM_SWITCH_R, action); }); } public void ToggleAutoThrottle() { Task.Run(() => { FSUIPCConnection.SendControlToFS(PMDG_777X_Control.EVT_MCP_AT_SWITCH, ClkL); }); } public void ToggleContinuousThrust() { Task.Run(() => FSUIPCConnection.SendControlToFS(PMDG_777X_Control.EVT_MCP_CLB_CON_SWITCH, ClkL)); } public void ToggleIASMach() { Task.Run(() => FSUIPCConnection.SendControlToFS(PMDG_777X_Control.EVT_MCP_IAS_MACH_SWITCH, ClkL)); } public void ToggleSpeedIntervene() { Task.Run(() => FSUIPCConnection.SendControlToFS(PMDG_777X_Control.EVT_MCP_SPEED_PUSH_SWITCH, ClkL)); } public void ToggleDisengageBar() { Task.Run(() => { var action = DisengageBar.Value == "off" ? ClkL : ClkR; FSUIPCConnection.SendControlToFS(PMDG_777X_Control.EVT_MCP_DISENGAGE_BAR, action); }); } public void ToggleHDGTRK() { Task.Run(() => FSUIPCConnection.SendControlToFS(PMDG_777X_Control.EVT_MCP_HDG_TRK_SWITCH, ClkL)); } public void ToggleLocalizerHold() { Task.Run(() => FSUIPCConnection.SendControlToFS(PMDG_777X_Control.EVT_MCP_LOC_SWITCH, ClkL)); } public void ToggleApproachMode() { Task.Run(() => FSUIPCConnection.SendControlToFS(PMDG_777X_Control.EVT_MCP_APP_SWITCH, ClkL)); } public void CycleBankLimiter() { Task.Run(() => { var counter = (byte)BankLimitSelector.Key; var parameter = counter == 4 ? 0 : counter + 1; FSUIPCConnection.SendControlToFS(PMDG_777X_Control.EVT_MCP_BANK_ANGLE_SELECTOR, parameter); }); } #endregion } }
-
I am using version 3.12 of your library.
-
Hi, Here is what I find with 'testing'. * Offsets work in a simple test app (WPF). * Offsets work in the previous version of our app. * In the new design (wpf/dotnet 8.0), offsets work. However, it seems as though they don't receive an initial value until the timer can tick at least once. When the process timer ticks, the initial value doesn't change, so nothing happens. To demonstrate, I will explain what happens. The example is the aircraft title (0x3d00). When the base Aircraft instance is created through inherited classes (the PMDG737/777). The class creates an instance of Offset<string>(0x3d00, 256) and assigns it to a variable _title. In the constructor of base Airplane class, I start a timer that checks for _title.ValueChanged. If it has, perform some logging to track the value. In this example, the _title offset is always empty, so nothing ever happens. Even though process is called elsewhere (connection manager), the offset's initial values are not loaded. On the other hand, calling Process outside a timer while in the constructor seems to load the initial data into the offsets. I'm confused with the entire issue. I am not using DispatcherTimer in any of my non UI classes. Could this be causing the problem? * An instance of Airplane is created. * Start a process timer. * In the timer event, check for changes to the title offset. * Do an action if it changes. * The title offset is empty because it never arrives at its MSFS provided value.
-
This still didn't work. I can send you the entire app for a lookover if it would help.