1
0
mirror of synced 2024-06-25 22:57:40 +00:00

Added: engine, landing gear and light state functions as an implementation proof of concept

Added: IFSXSimConnect interface and data handling prototype
This commit is contained in:
Mark van Renswoude 2013-02-18 21:46:32 +00:00
parent d665f2d979
commit b66659cd95
9 changed files with 614 additions and 94 deletions

View File

@ -13,7 +13,6 @@ uses
LEDColorIntf in 'Units\LEDColorIntf.pas', LEDColorIntf in 'Units\LEDColorIntf.pas',
LEDColor in 'Units\LEDColor.pas', LEDColor in 'Units\LEDColor.pas',
LEDFunctionIntf in 'Units\LEDFunctionIntf.pas', LEDFunctionIntf in 'Units\LEDFunctionIntf.pas',
ObserverIntf in 'Units\ObserverIntf.pas',
LEDFunction in 'Units\LEDFunction.pas', LEDFunction in 'Units\LEDFunction.pas',
StaticLEDFunction in 'Units\StaticLEDFunction.pas', StaticLEDFunction in 'Units\StaticLEDFunction.pas',
ConfigConversion in 'Units\ConfigConversion.pas', ConfigConversion in 'Units\ConfigConversion.pas',

View File

@ -173,7 +173,6 @@
<DCCReference Include="Units\LEDColorIntf.pas"/> <DCCReference Include="Units\LEDColorIntf.pas"/>
<DCCReference Include="Units\LEDColor.pas"/> <DCCReference Include="Units\LEDColor.pas"/>
<DCCReference Include="Units\LEDFunctionIntf.pas"/> <DCCReference Include="Units\LEDFunctionIntf.pas"/>
<DCCReference Include="Units\ObserverIntf.pas"/>
<DCCReference Include="Units\LEDFunction.pas"/> <DCCReference Include="Units\LEDFunction.pas"/>
<DCCReference Include="Units\StaticLEDFunction.pas"/> <DCCReference Include="Units\StaticLEDFunction.pas"/>
<DCCReference Include="Units\ConfigConversion.pas"/> <DCCReference Include="Units\ConfigConversion.pas"/>

View File

@ -0,0 +1,366 @@
unit FSXLEDFunction;
interface
uses
FSXLEDFunctionProvider,
LEDFunction,
LEDFunctionIntf;
type
{ Base classes }
TFSXOnOffFunction = class(TCustomFSXFunction)
protected
procedure RegisterStates; override;
end;
{ Function implementations }
TFSXEngineFunction = class(TCustomFSXFunction)
protected
procedure RegisterStates; override;
function GetWorkerClass: TCustomLEDFunctionWorkerClass; override;
end;
TFSXGearFunction = class(TCustomFSXFunction)
protected
procedure RegisterStates; override;
function GetWorkerClass: TCustomLEDFunctionWorkerClass; override;
end;
TFSXLightFunction = class(TFSXOnOffFunction)
protected
function GetCategoryName: string; override;
function GetWorkerClass: TCustomLEDFunctionWorkerClass; override;
function DoCreateWorker(ASettings: ILEDFunctionWorkerSettings): TCustomLEDFunctionWorker; override;
protected
function GetLightMask: Integer; virtual; abstract;
end;
TFSXLandingLightsFunction = class(TFSXLightFunction)
protected
function GetLightMask: Integer; override;
end;
TFSXInstrumentLightsFunction = class(TFSXLightFunction)
protected
function GetLightMask: Integer; override;
end;
TFSXBeaconLightsFunction = class(TFSXLightFunction)
protected
function GetLightMask: Integer; override;
end;
TFSXNavLightsFunction = class(TFSXLightFunction)
protected
function GetLightMask: Integer; override;
end;
TFSXStrobeLightsFunction = class(TFSXLightFunction)
protected
function GetLightMask: Integer; override;
end;
TFSXTaxiLightsFunction = class(TFSXLightFunction)
protected
function GetLightMask: Integer; override;
end;
TFSXRecognitionLightsFunction = class(TFSXLightFunction)
protected
function GetLightMask: Integer; override;
end;
implementation
uses
System.Math,
System.SysUtils,
FSXSimConnectIntf,
FSXResources,
LEDColorIntf,
LEDState,
LEDStateIntf,
SimConnect;
type
{ Worker implementations }
TFSXEngineFunctionWorker = class(TCustomFSXFunctionWorker)
protected
procedure RegisterVariables; override;
procedure HandleData(AData: Pointer); override;
end;
TFSXGearFunctionWorker = class(TCustomFSXFunctionWorker)
protected
procedure RegisterVariables; override;
procedure HandleData(AData: Pointer); override;
end;
TFSXLightStatesFunctionWorker = class(TCustomFSXFunctionWorker)
private
FStateMask: Integer;
protected
procedure RegisterVariables; override;
procedure HandleData(AData: Pointer); override;
public
property StateMask: Integer read FStateMask write FStateMask;
end;
{ TFSXOnOffFunction }
procedure TFSXOnOffFunction.RegisterStates;
begin
RegisterState(TLEDState.Create(FSXStateUIDOn, FSXStateDisplayNameOn, lcGreen));
RegisterState(TLEDState.Create(FSXStateUIDOff, FSXStateDisplayNameOff, lcRed));
end;
{ TFSXEngineFunction }
procedure TFSXEngineFunction.RegisterStates;
begin
RegisterState(TLEDState.Create(FSXStateUIDEngineNoEngines, FSXStateDisplayNameEngineNoEngines, lcOff));
RegisterState(TLEDState.Create(FSXStateUIDEngineAllRunning, FSXStateDisplayNameEngineAllRunning, lcGreen));
RegisterState(TLEDState.Create(FSXStateUIDEnginePartiallyRunning, FSXStateDisplayNameEnginePartiallyRunning, lcAmber));
RegisterState(TLEDState.Create(FSXStateUIDEngineAllOff, FSXStateDisplayNameEngineAllOff, lcRed));
RegisterState(TLEDState.Create(FSXStateUIDEngineFailed, FSXStateDisplayNameEngineFailed, lcFlashingRedNormal));
RegisterState(TLEDState.Create(FSXStateUIDEngineOnFire, FSXStateDisplayNameEngineOnFire, lcFlashingRedFast));
end;
function TFSXEngineFunction.GetWorkerClass: TCustomLEDFunctionWorkerClass;
begin
Result := TFSXEngineFunctionWorker;
end;
{ TFSXEngineFunctionWorker }
procedure TFSXEngineFunctionWorker.RegisterVariables;
var
engineIndex: Integer;
begin
Definition.AddVariable('NUMBER OF ENGINES', FSX_UNIT_NUMBER, SIMCONNECT_DATAType_INT32);
for engineIndex := 1 to FSX_MAX_ENGINES do
Definition.AddVariable(Format('GENERAL ENG COMBUSTION:%d', [engineIndex]), FSX_UNIT_BOOL, SIMCONNECT_DATAType_INT32);
for engineIndex := 1 to FSX_MAX_ENGINES do
Definition.AddVariable(Format('ENG FAILED:%d', [engineIndex]), FSX_UNIT_BOOL, SIMCONNECT_DATAType_INT32);
for engineIndex := 1 to FSX_MAX_ENGINES do
Definition.AddVariable(Format('ENG ON FIRE:%d', [engineIndex]), FSX_UNIT_BOOL, SIMCONNECT_DATAType_INT32);
end;
procedure TFSXEngineFunctionWorker.HandleData(AData: Pointer);
type
PEngineData = ^TEngineData;
TEngineData = packed record
NumberOfEngines: Integer;
Combustion: array[1..FSX_MAX_ENGINES] of Integer;
Failed: array[1..FSX_MAX_ENGINES] of Integer;
OnFire: array[1..FSX_MAX_ENGINES] of Integer;
end;
var
engineData: PEngineData;
engineCount: Integer;
engineIndex: Integer;
hasFire: Boolean;
hasFailure: Boolean;
runningCount: Integer;
begin
engineData := AData;
if engineData^.NumberOfEngines > 0 then
begin
engineCount := Min(engineData^.NumberOfEngines, FSX_MAX_ENGINES);
hasFire := False;
hasFailure := False;
runningCount := 0;
for engineIndex := 1 to engineCount do
begin
if engineData^.OnFire[engineIndex] <> 0 then
hasFire := True;
if engineData^.Failed[engineIndex] <> 0 then
hasFailure := True;
if engineData^.Combustion[engineIndex] <> 0 then
Inc(runningCount);
end;
if hasFire then
SetCurrentState(FSXStateUIDEngineOnFire)
else if hasFailure then
SetCurrentState(FSXStateUIDEngineFailed)
else if runningCount = 0 then
SetCurrentState(FSXStateUIDEngineAllOff)
else if runningCount = engineCount then
SetCurrentState(FSXStateUIDEngineAllRunning)
else
SetCurrentState(FSXStateUIDEnginePartiallyRunning);
end else
SetCurrentState(FSXStateUIDEngineNoEngines);
end;
{ TFSXGearFunction }
procedure TFSXGearFunction.RegisterStates;
begin
RegisterState(TLEDState.Create(FSXStateUIDGearNotRetractable, FSXStateDisplayNameGearNotRetractable, lcOff));
RegisterState(TLEDState.Create(FSXStateUIDGearRetracted, FSXStateDisplayNameGearRetracted, lcRed));
RegisterState(TLEDState.Create(FSXStateUIDGearBetween, FSXStateDisplayNameGearBetween, lcAmber));
RegisterState(TLEDState.Create(FSXStateUIDGearExtended, FSXStateDisplayNameGearExtended, lcGreen));
RegisterState(TLEDState.Create(FSXStateUIDGearSpeedExceeded, FSXStateDisplayNameGearSpeedExceeded, lcFlashingAmberNormal));
RegisterState(TLEDState.Create(FSXStateUIDGearDamageBySpeed, FSXStateDisplayNameGearDamageBySpeed, lcFlashingRedFast));
end;
function TFSXGearFunction.GetWorkerClass: TCustomLEDFunctionWorkerClass;
begin
Result := TFSXGearFunctionWorker;
end;
{ TFSXGearFunctionWorker }
procedure TFSXGearFunctionWorker.RegisterVariables;
begin
Definition.AddVariable('IS GEAR RETRACTABLE', FSX_UNIT_BOOL, SIMCONNECT_DATAType_INT32);
Definition.AddVariable('GEAR TOTAL PCT EXTENDED', FSX_UNIT_PERCENT, SIMCONNECT_DATAType_FLOAT64);
Definition.AddVariable('GEAR DAMAGE BY SPEED', FSX_UNIT_BOOL, SIMCONNECT_DATAType_INT32);
Definition.AddVariable('GEAR SPEED EXCEEDED', FSX_UNIT_BOOL, SIMCONNECT_DATAType_INT32);
end;
procedure TFSXGearFunctionWorker.HandleData(AData: Pointer);
type
PGearData = ^TGearData;
TGearData = packed record
IsGearRetractable: Cardinal;
TotalPctExtended: Double;
DamageBySpeed: Integer;
SpeedExceeded: Integer;
end;
var
gearData: PGearData;
begin
gearData := AData;
if gearData^.DamageBySpeed <> 0 then
SetCurrentState(FSXStateUIDGearDamageBySpeed)
else if gearData^.SpeedExceeded <> 0 then
SetCurrentState(FSXStateUIDGearSpeedExceeded)
else if gearData^.IsGearRetractable <> 0 then
begin
case Trunc(gearData ^.TotalPctExtended * 100) of
0: SetCurrentState(FSXStateUIDGearRetracted);
95..100: SetCurrentState(FSXStateUIDGearExtended);
else SetCurrentState(FSXStateUIDGearBetween);
end;
end else
SetCurrentState(FSXStateUIDGearNotRetractable);
end;
{ TFSXLightFunction }
function TFSXLightFunction.GetCategoryName: string;
begin
Result := FSXCategoryLights;
end;
function TFSXLightFunction.GetWorkerClass: TCustomLEDFunctionWorkerClass;
begin
Result := TFSXLightStatesFunctionWorker;
end;
function TFSXLightFunction.DoCreateWorker(ASettings: ILEDFunctionWorkerSettings): TCustomLEDFunctionWorker;
begin
Result := inherited DoCreateWorker(ASettings);
(Result as TFSXLightStatesFunctionWorker).StateMask := GetLightMask;
end;
{ TFSXLandingLightsFunction }
function TFSXLandingLightsFunction.GetLightMask: Integer;
begin
Result := FSX_LIGHTON_LANDING;
end;
{ TFSXInstrumentLightsFunction }
function TFSXInstrumentLightsFunction.GetLightMask: Integer;
begin
Result := FSX_LIGHTON_PANEL;
end;
{ TFSXBeaconLightsFunction }
function TFSXBeaconLightsFunction.GetLightMask: Integer;
begin
Result := FSX_LIGHTON_BEACON;
end;
{ TFSXNavLightsFunction }
function TFSXNavLightsFunction.GetLightMask: Integer;
begin
Result := FSX_LIGHTON_NAV;
end;
{ TFSXStrobeLightsFunction }
function TFSXStrobeLightsFunction.GetLightMask: Integer;
begin
Result := FSX_LIGHTON_STROBE;
end;
{ TFSXTaxiLightsFunction }
function TFSXTaxiLightsFunction.GetLightMask: Integer;
begin
Result := FSX_LIGHTON_TAXI;
end;
{ TFSXRecognitionLightsFunction }
function TFSXRecognitionLightsFunction.GetLightMask: Integer;
begin
Result := FSX_LIGHTON_RECOGNITION;
end;
{ TFSXLightStatesFunctionWorker }
procedure TFSXLightStatesFunctionWorker.RegisterVariables;
begin
Definition.AddVariable('LIGHT ON STATES', FSX_UNIT_MASK, SIMCONNECT_DATATYPE_INT32);
end;
procedure TFSXLightStatesFunctionWorker.HandleData(AData: Pointer);
begin
if (PCardinal(AData)^ and StateMask) <> 0 then
SetCurrentState(FSXStateUIDOn)
else
SetCurrentState(FSXStateUIDOff);
end;
end.

View File

@ -8,8 +8,7 @@ uses
FSXSimConnectIntf, FSXSimConnectIntf,
LEDFunction, LEDFunction,
LEDFunctionIntf, LEDFunctionIntf,
LEDStateIntf, LEDStateIntf;
ObserverIntf;
type type
@ -17,24 +16,21 @@ type
TCustomFSXFunctionList = TObjectList<TCustomFSXFunction>; TCustomFSXFunctionList = TObjectList<TCustomFSXFunction>;
TFSXLEDFunctionProvider = class(TCustomLEDFunctionProvider) TFSXLEDFunctionProvider = class(TCustomLEDFunctionProvider, IFSXSimConnectObserver)
private private
FConnectedFunctions: TCustomFSXFunctionList; FSimConnect: IFSXSimConnect;
FSimConnectHandle: THandle; FSimConnectLock: TCriticalSection;
protected
procedure SimConnect;
procedure SimDisconnect;
procedure Connect(AFunction: TCustomFSXFunction); virtual;
procedure Disconnect(AFunction: TCustomFSXFunction); virtual;
property ConnectedFunctions: TCustomFSXFunctionList read FConnectedFunctions;
property SimConnectHandle: THandle read FSimConnectHandle;
protected protected
procedure RegisterFunctions; override; procedure RegisterFunctions; override;
function GetUID: string; override; function GetUID: string; override;
protected
{ IFSXSimConnectObserver }
procedure ObserveDestroy(Sender: IFSXSimConnect);
public public
constructor Create;
destructor Destroy; override;
function GetSimConnect: IFSXSimConnect; function GetSimConnect: IFSXSimConnect;
end; end;
@ -45,9 +41,6 @@ type
FDisplayName: string; FDisplayName: string;
FUID: string; FUID: string;
protected protected
procedure SimConnected; virtual;
procedure SimDisconnected; virtual;
property Provider: TFSXLEDFunctionProvider read FProvider; property Provider: TFSXLEDFunctionProvider read FProvider;
protected protected
function GetCategoryName: string; override; function GetCategoryName: string; override;
@ -58,7 +51,10 @@ type
end; end;
TCustomFSXFunctionWorker = class(TCustomLEDFunctionWorker) TCustomFSXFunctionClass = class of TCustomFSXFunction;
TCustomFSXFunctionWorker = class(TCustomLEDFunctionWorker, IFSXSimConnectDataHandler)
private private
FSimConnect: IFSXSimConnect; FSimConnect: IFSXSimConnect;
FDefinition: IFSXSimConnectDefinition; FDefinition: IFSXSimConnectDefinition;
@ -73,6 +69,9 @@ type
property SimConnect: IFSXSimConnect read FSimConnect; property SimConnect: IFSXSimConnect read FSimConnect;
protected protected
function GetCurrentState: ILEDStateWorker; override; function GetCurrentState: ILEDStateWorker; override;
{ IFSXSimConnectDataHandler }
procedure HandleData(AData: Pointer); virtual; abstract;
public public
constructor Create(AStates: ILEDMultiStateFunction; ASettings: ILEDFunctionWorkerSettings; ASimConnect: IFSXSimConnect); constructor Create(AStates: ILEDMultiStateFunction; ASettings: ILEDFunctionWorkerSettings; ASimConnect: IFSXSimConnect);
destructor Destroy; override; destructor Destroy; override;
@ -85,15 +84,63 @@ uses
FSXLEDFunction, FSXLEDFunction,
FSXResources, FSXResources,
FSXSimConnectClient,
LEDFunctionRegistry, LEDFunctionRegistry,
SimConnect; SimConnect;
{ TFSXLEDFunctionProvider } { TFSXLEDFunctionProvider }
constructor TFSXLEDFunctionProvider.Create;
begin
inherited Create;
FSimConnectLock := TCriticalSection.Create;
end;
destructor TFSXLEDFunctionProvider.Destroy;
begin
FreeAndNil(FSimConnectLock);
inherited Destroy;
end;
procedure TFSXLEDFunctionProvider.RegisterFunctions; procedure TFSXLEDFunctionProvider.RegisterFunctions;
begin begin
RegisterFunction(TFSXGearFunction.Create(Self, FSXFunctionDisplayNameGear, FSXFunctionUIDGear)); {
AConsumer.AddFunction(FUNCTION_FSX_CARBHEAT, 'Anti-ice');
AConsumer.AddFunction(FUNCTION_FSX_AUTOPILOT, 'Auto pilot (main)');
AConsumer.AddFunction(FUNCTION_FSX_AUTOPILOT_AMBER, 'Auto pilot (main - off / amber)');
AConsumer.AddFunction(FUNCTION_FSX_AUTOPILOT_ALTITUDE, 'Auto pilot - Altitude');
AConsumer.AddFunction(FUNCTION_FSX_AUTOPILOT_APPROACH, 'Auto pilot - Approach');
AConsumer.AddFunction(FUNCTION_FSX_AUTOPILOT_BACKCOURSE, 'Auto pilot - Backcourse');
AConsumer.AddFunction(FUNCTION_FSX_AUTOPILOT_HEADING, 'Auto pilot - Heading');
AConsumer.AddFunction(FUNCTION_FSX_AUTOPILOT_NAV, 'Auto pilot - Nav');
AConsumer.AddFunction(FUNCTION_FSX_AVIONICSMASTER, 'Avionics master switch');
AConsumer.AddFunction(FUNCTION_FSX_BATTERYMASTER, 'Battery master switch');
AConsumer.AddFunction(FUNCTION_FSX_ENGINE, 'Engine');
AConsumer.AddFunction(FUNCTION_FSX_EXITDOOR, 'Exit door');
AConsumer.AddFunction(FUNCTION_FSX_FLAPS, 'Flaps');
AConsumer.AddFunction(FUNCTION_FSX_PARKINGBRAKE, 'Parking brake');
AConsumer.AddFunction(FUNCTION_FSX_PRESSURIZATIONDUMPSWITCH, 'Pressurization dump switch');
AConsumer.AddFunction(FUNCTION_FSX_SPOILERS, 'Spoilers (air brake)');
AConsumer.AddFunction(FUNCTION_FSX_TAILHOOK, 'Tail hook');
}
{ Misc }
RegisterFunction(TFSXEngineFunction.Create( Self, FSXFunctionDisplayNameEngine, FSXFunctionUIDEngine));
RegisterFunction(TFSXGearFunction.Create( Self, FSXFunctionDisplayNameGear, FSXFunctionUIDGear));
{ Lights }
RegisterFunction(TFSXBeaconLightsFunction.Create( Self, FSXFunctionDisplayNameBeaconLights, FSXFunctionUIDBeaconLights));
RegisterFunction(TFSXInstrumentLightsFunction.Create( Self, FSXFunctionDisplayNameInstrumentLights, FSXFunctionUIDInstrumentLights));
RegisterFunction(TFSXLandingLightsFunction.Create( Self, FSXFunctionDisplayNameLandingLights, FSXFunctionUIDLandingLights));
RegisterFunction(TFSXNavLightsFunction.Create( Self, FSXFunctionDisplayNameNavLights, FSXFunctionUIDNavLights));
RegisterFunction(TFSXRecognitionLightsFunction.Create(Self, FSXFunctionDisplayNameRecognitionLights, FSXFunctionUIDRecognitionLights));
RegisterFunction(TFSXStrobeLightsFunction.Create( Self, FSXFunctionDisplayNameStrobeLights, FSXFunctionUIDStrobeLights));
RegisterFunction(TFSXTaxiLightsFunction.Create( Self, FSXFunctionDisplayNameTaxiLights, FSXFunctionUIDTaxiLights));
end; end;
@ -103,57 +150,34 @@ begin
end; end;
procedure TFSXLEDFunctionProvider.ObserveDestroy(Sender: IFSXSimConnect);
begin
FSimConnectLock.Acquire;
try
FSimConnect := nil;
finally
FSimConnectLock.Release;
end;
end;
function TFSXLEDFunctionProvider.GetSimConnect: IFSXSimConnect; function TFSXLEDFunctionProvider.GetSimConnect: IFSXSimConnect;
begin begin
// TODO FSimConnectLock.Acquire;
end; try
if not Assigned(FSimConnect) then
begin
FSimConnect := TFSXSimConnectInterface.Create;
FSimConnect.Attach(Self);
end;
Result := FSimConnect;
procedure TFSXLEDFunctionProvider.SimConnect; finally
var FSimConnectLock.Release;
fsxFunction: TCustomFSXFunction;
begin
if SimConnectHandle <> 0 then
exit;
// FSimConnectHandle :=
if SimConnectHandle <> 0 then
begin
for fsxFunction in ConnectedFunctions do
fsxFunction.SimConnected;
end; end;
end; end;
procedure TFSXLEDFunctionProvider.SimDisconnect;
begin
if SimConnectHandle = 0 then
exit;
end;
procedure TFSXLEDFunctionProvider.Connect(AFunction: TCustomFSXFunction);
begin
if ConnectedFunctions.IndexOf(AFunction) = -1 then
begin
ConnectedFunctions.Add(AFunction);
if ConnectedFunctions.Count > 0 then
SimConnect;
end;
end;
procedure TFSXLEDFunctionProvider.Disconnect(AFunction: TCustomFSXFunction);
begin
ConnectedFunctions.Remove(AFunction);
if ConnectedFunctions.Count = 0 then
SimDisconnect;
end;
{ TCustomFSXFunction } { TCustomFSXFunction }
constructor TCustomFSXFunction.Create(AProvider: TFSXLEDFunctionProvider; const ADisplayName, AUID: string); constructor TCustomFSXFunction.Create(AProvider: TFSXLEDFunctionProvider; const ADisplayName, AUID: string);
begin begin
@ -183,16 +207,6 @@ begin
end; end;
procedure TCustomFSXFunction.SimConnected;
begin
end;
procedure TCustomFSXFunction.SimDisconnected;
begin
end;
{ TCustomFSXFunctionWorker } { TCustomFSXFunctionWorker }
constructor TCustomFSXFunctionWorker.Create(AStates: ILEDMultiStateFunction; ASettings: ILEDFunctionWorkerSettings; ASimConnect: IFSXSimConnect); constructor TCustomFSXFunctionWorker.Create(AStates: ILEDMultiStateFunction; ASettings: ILEDFunctionWorkerSettings; ASimConnect: IFSXSimConnect);
begin begin
@ -203,7 +217,9 @@ begin
FDefinition := ASimConnect.CreateDefinition; FDefinition := ASimConnect.CreateDefinition;
RegisterVariables; RegisterVariables;
ASimConnect.AddDefinition(FDefinition);
// TODO pass self as callback for this definition
ASimConnect.AddDefinition(FDefinition, Self);
end; end;

View File

@ -3,18 +3,45 @@ unit FSXResources;
interface interface
const const
FSXProviderUID = 'fsx'; FSXProviderUID = 'fsx';
FSXCategory = 'Flight Simulator X'; FSXCategory = 'Flight Simulator X';
FSXCategoryLights = FSXCategory + ' - Lights';
FSXStateUIDOn = 'on';
FSXStateUIDOff = 'off';
FSXStateDisplayNameOn = 'On';
FSXStateDisplayNameOff = 'Off';
FSXFunctionUIDEngine = 'engine';
FSXFunctionDisplayNameEngine = 'Engine';
FSXStateUIDEngineNoEngines = 'noEngines';
FSXStateUIDEngineAllRunning = 'allRunning';
FSXStateUIDEnginePartiallyRunning = 'partiallyRunning';
FSXStateUIDEngineAllOff = 'allOff';
FSXStateUIDEngineFailed = 'failed';
FSXStateUIDEngineOnFire = 'onFire';
FSXStateDisplayNameEngineNoEngines = 'No engines';
FSXStateDisplayNameEngineAllRunning = 'All running';
FSXStateDisplayNameEnginePartiallyRunning = 'Partially running';
FSXStateDisplayNameEngineAllOff = 'All off';
FSXStateDisplayNameEngineFailed = 'Engine failure';
FSXStateDisplayNameEngineOnFire = 'On fire';
FSXFunctionUIDGear = 'gear'; FSXFunctionUIDGear = 'gear';
FSXFunctionDisplayNameGear = 'Landing gear'; FSXFunctionDisplayNameGear = 'Landing gear';
FSXStateUIDGearNotRetractable = 'notRetractable';
FSXStateUIDGearRetracted = 'retracted'; FSXStateUIDGearRetracted = 'retracted';
FSXStateUIDGearBetween = 'between'; FSXStateUIDGearBetween = 'between';
FSXStateUIDGearExtended = 'extended'; FSXStateUIDGearExtended = 'extended';
FSXStateUIDGearSpeedExceeded = 'speedExceeded'; FSXStateUIDGearSpeedExceeded = 'speedExceeded';
FSXStateUIDGearDamageBySpeed = 'damageBySpeed'; FSXStateUIDGearDamageBySpeed = 'damageBySpeed';
FSXStateDisplayNameGearNotRetractable = 'Not retractable';
FSXStateDisplayNameGearRetracted = 'Retracted'; FSXStateDisplayNameGearRetracted = 'Retracted';
FSXStateDisplayNameGearBetween = 'Extending / retracting'; FSXStateDisplayNameGearBetween = 'Extending / retracting';
FSXStateDisplayNameGearExtended = 'Extended'; FSXStateDisplayNameGearExtended = 'Extended';
@ -22,6 +49,27 @@ const
FSXStateDisplayNameGearDamageBySpeed = 'Damage by speed'; FSXStateDisplayNameGearDamageBySpeed = 'Damage by speed';
FSXFunctionUIDLandingLights = 'landingLights';
FSXFunctionDisplayNameLandingLights = 'Landing lights';
FSXFunctionUIDInstrumentLights = 'instrumentLights';
FSXFunctionDisplayNameInstrumentLights = 'Instrument lights';
FSXFunctionUIDBeaconLights = 'beaconLights';
FSXFunctionDisplayNameBeaconLights = 'Beacon lights';
FSXFunctionUIDNavLights = 'navLights';
FSXFunctionDisplayNameNavLights = 'Nav lights';
FSXFunctionUIDStrobeLights = 'strobeLights';
FSXFunctionDisplayNameStrobeLights = 'Strobe lights';
FSXFunctionUIDTaxiLights = 'taxiLights';
FSXFunctionDisplayNameTaxiLights = 'Taxi lights';
FSXFunctionUIDRecognitionLights = 'recognitionLights';
FSXFunctionDisplayNameRecognitionLights = 'Recognition lights';
implementation implementation

View File

@ -2,20 +2,29 @@ unit FSXSimConnectClient;
interface interface
uses uses
Classes,
OtlTaskControl, OtlTaskControl,
FSXSimConnectIntf; FSXSimConnectIntf;
type type
TFSXSimConnectInterface = class(TInterfacedObject, IFSXSimConnect) TFSXSimConnectInterface = class(TInterfacedObject, IFSXSimConnect)
private private
FClient: IOmniTaskControl; FClient: IOmniTaskControl;
FObservers: TInterfaceList;
protected protected
property Client: IOmniTaskControl read FClient; property Client: IOmniTaskControl read FClient;
property Observers: TInterfaceList read FObservers;
protected protected
{ IFSXSimConnect } { IFSXSimConnect }
procedure Attach(AObserver: IFSXSimConnectObserver);
procedure Detach(AObserver: IFSXSimConnectObserver);
function CreateDefinition: IFSXSimConnectDefinition; function CreateDefinition: IFSXSimConnectDefinition;
procedure AddDefinition(ADefinition: IFSXSimConnectDefinition); procedure AddDefinition(ADefinition: IFSXSimConnectDefinition; ADataHandler: IFSXSimConnectDataHandler);
procedure RemoveDefinition(ADataHandler: IFSXSimConnectDataHandler);
public public
constructor Create; constructor Create;
destructor Destroy; override; destructor Destroy; override;
@ -29,6 +38,11 @@ uses
SimConnect; SimConnect;
const
TM_ADDDEFINITION = 3001;
TM_REMOVEDEFINITION = 3002;
type type
TFSXSimConnectClient = class(TOmniWorker) TFSXSimConnectClient = class(TOmniWorker)
end; end;
@ -58,11 +72,15 @@ var
begin begin
worker := TFSXSimConnectClient.Create; worker := TFSXSimConnectClient.Create;
FClient := CreateTask(worker); FClient := CreateTask(worker);
FObservers := TInterfaceList.Create;
end; end;
destructor TFSXSimConnectInterface.Destroy; destructor TFSXSimConnectInterface.Destroy;
begin begin
FreeAndNil(FObservers);
FClient.Terminate; FClient.Terminate;
FClient := nil; FClient := nil;
@ -70,15 +88,34 @@ begin
end; end;
procedure TFSXSimConnectInterface.Attach(AObserver: IFSXSimConnectObserver);
begin
Observers.Add(AObserver as IFSXSimConnectObserver);
end;
procedure TFSXSimConnectInterface.Detach(AObserver: IFSXSimConnectObserver);
begin
Observers.Remove(AObserver as IFSXSimConnectObserver);
end;
function TFSXSimConnectInterface.CreateDefinition: IFSXSimConnectDefinition; function TFSXSimConnectInterface.CreateDefinition: IFSXSimConnectDefinition;
begin begin
Result := TFSXSimConnectDefinition.Create(Self); Result := TFSXSimConnectDefinition.Create(Self);
end; end;
procedure TFSXSimConnectInterface.AddDefinition(ADefinition: IFSXSimConnectDefinition); procedure TFSXSimConnectInterface.AddDefinition(ADefinition: IFSXSimConnectDefinition; ADataHandler: IFSXSimConnectDataHandler);
begin begin
// TODO Client.Comm.Send(TM_ADDDEFINITION, [ADefinition, ADataHandler]);
// TODO pass to thread; if definition already exists (same variables), link to existing definition to avoid too many SimConnect definition
end;
procedure TFSXSimConnectInterface.RemoveDefinition(ADataHandler: IFSXSimConnectDataHandler);
begin
Client.Comm.Send(TM_REMOVEDEFINITION, ADataHandler);
end; end;

View File

@ -6,13 +6,30 @@ uses
type type
IFSXSimConnect = interface;
IFSXSimConnectDefinition = interface; IFSXSimConnectDefinition = interface;
IFSXSimConnectObserver = interface
['{ACE8979A-D656-4F97-A332-A54BB615C4D1}']
procedure ObserveDestroy(Sender: IFSXSimConnect);
end;
IFSXSimConnectDataHandler = interface
['{29F00FB8-00AB-419F-83A3-A6AB3582599F}']
procedure HandleData(AData: Pointer);
end;
IFSXSimConnect = interface IFSXSimConnect = interface
['{B6BE3E7C-0804-43D6-84DE-8010C5728A07}'] ['{B6BE3E7C-0804-43D6-84DE-8010C5728A07}']
procedure Attach(AObserver: IFSXSimConnectObserver);
procedure Detach(AObserver: IFSXSimConnectObserver);
function CreateDefinition: IFSXSimConnectDefinition; function CreateDefinition: IFSXSimConnectDefinition;
procedure AddDefinition(ADefinition: IFSXSimConnectDefinition); procedure AddDefinition(ADefinition: IFSXSimConnectDefinition; ADataHandler: IFSXSimConnectDataHandler);
procedure RemoveDefinition(ADataHandler: IFSXSimConnectDataHandler);
end; end;
@ -30,6 +47,16 @@ const
FSX_UNIT_BOOL = 'bool'; FSX_UNIT_BOOL = 'bool';
FSX_UNIT_NUMBER = 'number'; FSX_UNIT_NUMBER = 'number';
FSX_LIGHTON_NAV = $0001;
FSX_LIGHTON_BEACON = $0002;
FSX_LIGHTON_LANDING = $0004;
FSX_LIGHTON_TAXI = $0008;
FSX_LIGHTON_STROBE = $0010;
FSX_LIGHTON_PANEL = $0020;
FSX_LIGHTON_RECOGNITION = $0040;
FSX_LIGHTON_CABIN = $0200;
FSX_MAX_ENGINES = 4;
implementation implementation

View File

@ -5,11 +5,14 @@ uses
Classes, Classes,
LEDFunctionIntf, LEDFunctionIntf,
LEDStateIntf, LEDStateIntf;
ObserverIntf;
type type
TCustomLEDFunctionWorker = class;
TCustomLEDFunctionWorkerClass = class of TCustomLEDFunctionWorker;
TCustomLEDFunctionProvider = class(TInterfacedObject, ILEDFunctionProvider) TCustomLEDFunctionProvider = class(TInterfacedObject, ILEDFunctionProvider)
private private
FFunctions: TInterfaceList; FFunctions: TInterfaceList;
@ -45,7 +48,12 @@ type
protected protected
procedure RegisterStates; virtual; abstract; procedure RegisterStates; virtual; abstract;
function RegisterState(AState: ILEDState): ILEDState; virtual; function RegisterState(AState: ILEDState): ILEDState; virtual;
function GetWorkerClass: TCustomLEDFunctionWorkerClass; virtual; abstract;
function DoCreateWorker(ASettings: ILEDFunctionWorkerSettings): TCustomLEDFunctionWorker; virtual;
protected protected
function CreateWorker(ASettings: ILEDFunctionWorkerSettings): ILEDFunctionWorker; override;
{ ILEDMultiStateFunction } { ILEDMultiStateFunction }
function GetEnumerator: ILEDStateEnumerator; virtual; function GetEnumerator: ILEDStateEnumerator; virtual;
public public
@ -67,9 +75,9 @@ type
property Observers: TInterfaceList read FObservers; property Observers: TInterfaceList read FObservers;
property States: TInterfaceList read FStates; property States: TInterfaceList read FStates;
protected protected
{ IObservable } { ILEDFunctionWorker }
procedure Attach(AObserver: IObserver); virtual; procedure Attach(AObserver: ILEDFunctionObserver); virtual;
procedure Detach(AObserver: IObserver); virtual; procedure Detach(AObserver: ILEDFunctionObserver); virtual;
function GetCurrentState: ILEDStateWorker; virtual; abstract; function GetCurrentState: ILEDStateWorker; virtual; abstract;
public public
@ -147,6 +155,18 @@ begin
end; end;
function TCustomMultiStateLEDFunction.CreateWorker(ASettings: ILEDFunctionWorkerSettings): ILEDFunctionWorker;
begin
Result := DoCreateWorker(ASettings);
end;
function TCustomMultiStateLEDFunction.DoCreateWorker(ASettings: ILEDFunctionWorkerSettings): TCustomLEDFunctionWorker;
begin
Result := GetWorkerClass.Create(Self, ASettings);
end;
{ TCustomLEDFunctionWorker } { TCustomLEDFunctionWorker }
constructor TCustomLEDFunctionWorker.Create; constructor TCustomLEDFunctionWorker.Create;
begin begin
@ -174,16 +194,16 @@ begin
end; end;
procedure TCustomLEDFunctionWorker.Attach(AObserver: IObserver); procedure TCustomLEDFunctionWorker.Attach(AObserver: ILEDFunctionObserver);
begin begin
{ TInterfaceList is thread-safe } { TInterfaceList is thread-safe }
Observers.Add(AObserver as IObserver); Observers.Add(AObserver as ILEDFunctionObserver);
end; end;
procedure TCustomLEDFunctionWorker.Detach(AObserver: IObserver); procedure TCustomLEDFunctionWorker.Detach(AObserver: ILEDFunctionObserver);
begin begin
Observers.Remove(AObserver as IObserver); Observers.Remove(AObserver as ILEDFunctionObserver);
end; end;
@ -225,7 +245,7 @@ var
begin begin
for observer in Observers do for observer in Observers do
(observer as IObserver).Update(Self); (observer as ILEDFunctionObserver).ObserveUpdate(Self);
end; end;

View File

@ -3,8 +3,7 @@ unit LEDFunctionIntf;
interface interface
uses uses
LEDColorIntf, LEDColorIntf,
LEDStateIntf, LEDStateIntf;
ObserverIntf;
type type
@ -40,8 +39,17 @@ type
end; end;
ILEDFunctionWorker = interface(IObservable) ILEDFunctionObserver = interface
['{B78415C9-9F64-4AF1-8983-BACE2B7225EF}']
procedure ObserveUpdate(Sender: ILEDFunctionWorker);
end;
ILEDFunctionWorker = interface
['{5EF3230D-B52F-4BD6-8AD3-F3A035F155B1}'] ['{5EF3230D-B52F-4BD6-8AD3-F3A035F155B1}']
procedure Attach(AObserver: ILEDFunctionObserver);
procedure Detach(AObserver: ILEDFunctionObserver);
function GetCurrentState: ILEDStateWorker; function GetCurrentState: ILEDStateWorker;
end; end;