1
0
mirror of synced 2024-09-28 13:06:09 +00:00
G940LEDControl/G940LEDControl/Units/FSXLEDStateProvider.pas

743 lines
26 KiB
ObjectPascal

unit FSXLEDStateProvider;
interface
uses
Classes,
Messages,
SyncObjs,
Windows,
LEDFunctionMap,
LEDStateConsumer,
LEDStateProvider,
SimConnect;
const
{ Note: do not change these values, the config demands it! }
FUNCTION_FSX_GEAR = FUNCTION_PROVIDER_OFFSET + 1;
FUNCTION_FSX_LANDINGLIGHTS = FUNCTION_PROVIDER_OFFSET + 2;
FUNCTION_FSX_INSTRUMENTLIGHTS = FUNCTION_PROVIDER_OFFSET + 3;
FUNCTION_FSX_PARKINGBRAKE = FUNCTION_PROVIDER_OFFSET + 4;
FUNCTION_FSX_ENGINE = FUNCTION_PROVIDER_OFFSET + 5;
FUNCTION_FSX_EXITDOOR = FUNCTION_PROVIDER_OFFSET + 6;
FUNCTION_FSX_STROBELIGHTS = FUNCTION_PROVIDER_OFFSET + 7;
FUNCTION_FSX_NAVLIGHTS = FUNCTION_PROVIDER_OFFSET + 8;
FUNCTION_FSX_BEACONLIGHTS = FUNCTION_PROVIDER_OFFSET + 9;
FUNCTION_FSX_FLAPS = FUNCTION_PROVIDER_OFFSET + 10;
FUNCTION_FSX_BATTERYMASTER = FUNCTION_PROVIDER_OFFSET + 11;
FUNCTION_FSX_AVIONICSMASTER = FUNCTION_PROVIDER_OFFSET + 12;
FUNCTION_FSX_SPOILERS = FUNCTION_PROVIDER_OFFSET + 13;
FUNCTION_FSX_PRESSURIZATIONDUMPSWITCH = FUNCTION_PROVIDER_OFFSET + 14;
FUNCTION_FSX_ENGINEANTIICE = FUNCTION_PROVIDER_OFFSET + 15;
FUNCTION_FSX_AUTOPILOT = FUNCTION_PROVIDER_OFFSET + 16;
FUNCTION_FSX_FUELPUMP = FUNCTION_PROVIDER_OFFSET + 17;
FUNCTION_FSX_TAILHOOK = FUNCTION_PROVIDER_OFFSET + 18;
FUNCTION_FSX_AUTOPILOT_AMBER = FUNCTION_PROVIDER_OFFSET + 19;
FUNCTION_FSX_AUTOPILOT_HEADING = FUNCTION_PROVIDER_OFFSET + 20;
FUNCTION_FSX_AUTOPILOT_APPROACH = FUNCTION_PROVIDER_OFFSET + 21;
FUNCTION_FSX_AUTOPILOT_BACKCOURSE = FUNCTION_PROVIDER_OFFSET + 22;
FUNCTION_FSX_AUTOPILOT_ALTITUDE = FUNCTION_PROVIDER_OFFSET + 23;
FUNCTION_FSX_AUTOPILOT_NAV = FUNCTION_PROVIDER_OFFSET + 24;
FUNCTION_FSX_TAXILIGHTS = FUNCTION_PROVIDER_OFFSET + 25;
FUNCTION_FSX_RECOGNITIONLIGHTS = FUNCTION_PROVIDER_OFFSET + 26;
FUNCTION_FSX_DEICE = FUNCTION_PROVIDER_OFFSET + 27;
type
TFSXLEDStateProvider = class(TLEDStateProvider)
private
FSimConnectHandle: THandle;
FDefinitions: TList;
// FLastDown: Boolean;
protected
function GetProcessMessagesInterval: Integer; override;
procedure UpdateMap;
procedure HandleDispatch(AData: PSimConnectRecv);
procedure HandleGearData(AData: Pointer);
procedure HandleLightsData(AData: Pointer);
procedure HandleParkingBrakeData(AData: Pointer);
procedure HandleEngineData(AData: Pointer);
procedure HandleExitDoorData(AData: Pointer);
procedure HandleFlapsData(AData: Pointer);
procedure HandleSwitchesData(AData: Pointer);
procedure HandleAntiIceData(AData: Pointer);
procedure AddVariable(ADefineID: Cardinal; ADatumName, AUnitsName: string;
ADatumType: SIMCONNECT_DATAType = SIMCONNECT_DATAType_FLOAT64;
AEpsilon: Single = 0; ADatumID: DWORD = SIMCONNECT_UNUSED);
procedure AddDefinition(ADefinition: Cardinal);
procedure ClearDefinitions;
procedure SetFSXLightState(AStates: Cardinal; AMask, AFunction: Integer);
property SimConnectHandle: THandle read FSimConnectHandle;
public
class procedure EnumFunctions(AConsumer: IFunctionConsumer); override;
constructor Create(AConsumer: ILEDStateConsumer); override;
destructor Destroy; override;
procedure Initialize; override;
procedure Finalize; override;
procedure ProcessMessages; override;
end;
implementation
uses
ComObj,
Math,
SysUtils;
const
APPNAME = 'G940 LED Control';
MAX_ENGINES = 4;
DEFINITION_GEAR = 1;
DEFINITION_LIGHTS = 2;
DEFINITION_INSTRUMENTLIGHTS = 3;
DEFINITION_PARKINGBRAKE = 4;
DEFINITION_ENGINE = 5;
DEFINITION_THROTTLE = 6;
DEFINITION_EXITDOOR = 7;
DEFINITION_FLAPSSPOILERS = 8;
DEFINITION_SWITCHES = 9;
DEFINITION_ANTIICE = 10;
// EVENT_ZOOM = 10;
FSX_UNIT_PERCENT = 'percent';
FSX_UNIT_MASK = 'mask';
FSX_UNIT_BOOL = 'bool';
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;
type
TThrottleData = packed record
NumberOfEngines: Integer;
ThrottleLeverPos: array[1..MAX_ENGINES] of Double;
end;
{ TFSXLEDStateProvider }
class procedure TFSXLEDStateProvider.EnumFunctions(AConsumer: IFunctionConsumer);
begin
inherited;
AConsumer.SetCategory('Dynamic');
// AConsumer.AddFunction(FUNCTION_FSX_FUELPUMP, 'Fuel boost pump');
AConsumer.AddFunction(FUNCTION_FSX_AUTOPILOT, 'Auto pilot (main)');
AConsumer.AddFunction(FUNCTION_FSX_AUTOPILOT_ALTITUDE, 'Auto pilot - Altitude');
AConsumer.AddFunction(FUNCTION_FSX_AUTOPILOT_AMBER, 'Auto pilot (main - off / amber)');
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_BEACONLIGHTS, 'Beacon lights');
AConsumer.AddFunction(FUNCTION_FSX_DEICE, 'De-ice');
AConsumer.AddFunction(FUNCTION_FSX_ENGINE, 'Engine');
AConsumer.AddFunction(FUNCTION_FSX_ENGINEANTIICE, 'Engine anti-ice');
AConsumer.AddFunction(FUNCTION_FSX_EXITDOOR, 'Exit door');
AConsumer.AddFunction(FUNCTION_FSX_FLAPS, 'Flaps');
AConsumer.AddFunction(FUNCTION_FSX_GEAR, 'Landing gear');
AConsumer.AddFunction(FUNCTION_FSX_INSTRUMENTLIGHTS, 'Instrument lights');
AConsumer.AddFunction(FUNCTION_FSX_LANDINGLIGHTS, 'Landing lights');
AConsumer.AddFunction(FUNCTION_FSX_NAVLIGHTS, 'Nav lights');
AConsumer.AddFunction(FUNCTION_FSX_PARKINGBRAKE, 'Parking brake');
AConsumer.AddFunction(FUNCTION_FSX_PRESSURIZATIONDUMPSWITCH, 'Pressurization dump switch');
AConsumer.AddFunction(FUNCTION_FSX_RECOGNITIONLIGHTS, 'Recognition lights');
AConsumer.AddFunction(FUNCTION_FSX_SPOILERS, 'Spoilers (air brake)');
AConsumer.AddFunction(FUNCTION_FSX_STROBELIGHTS, 'Strobe lights');
AConsumer.AddFunction(FUNCTION_FSX_TAILHOOK, 'Tail hook');
AConsumer.AddFunction(FUNCTION_FSX_TAXILIGHTS, 'Taxi lights');
end;
constructor TFSXLEDStateProvider.Create(AConsumer: ILEDStateConsumer);
begin
inherited;
FDefinitions := TList.Create;
end;
destructor TFSXLEDStateProvider.Destroy;
begin
FreeAndNil(FDefinitions);
inherited;
end;
procedure TFSXLEDStateProvider.Initialize;
begin
inherited;
if not InitSimConnect then
raise EInitializeError.Create('SimConnect.dll could not be loaded');
if SimConnect_Open(FSimConnectHandle, APPNAME, 0, 0, 0, 0) <> S_OK then
raise EInitializeError.Create('Connection to Flight Simulator could not be established. Is it running?');
UpdateMap;
// SimConnect_MapClientEventToSimEvent(SimConnectHandle, EVENT_ZOOM, 'VIEW_ZOOM_SET');
end;
procedure TFSXLEDStateProvider.Finalize;
begin
inherited;
ClearDefinitions;
if SimConnectHandle <> 0 then
begin
SimConnect_Close(SimConnectHandle);
FSimConnectHandle := 0;
end;
end;
procedure TFSXLEDStateProvider.ProcessMessages;
var
data: PSimConnectRecv;
dataSize: Cardinal;
// down: Boolean;
// level: Integer;
// state: Integer;
begin
inherited;
while SimConnect_GetNextDispatch(SimConnectHandle, data, dataSize) = S_OK do
HandleDispatch(data);
{
state := GetKeyState(VK_CONTROL);
down := ((state and $8000) <> 0);
if down <> FLastDown then
begin
if down then
level := 4 * 64
else
level := 26;
SimConnect_TransmitClientEvent(SimConnectHandle, 0, EVENT_ZOOM, level, SIMCONNECT_GROUP_PRIORITY_STANDARD, SIMCONNECT_EVENT_FLAG_GROUPID_IS_PRIORITY);
FLastDown := down;
end;
}
end;
procedure TFSXLEDStateProvider.UpdateMap;
var
engineIndex: Integer;
begin
ClearDefinitions;
{ Gear }
if Consumer.FunctionMap.HasFunction(FUNCTION_FSX_GEAR) then
begin
AddVariable(DEFINITION_GEAR, 'IS GEAR RETRACTABLE', FSX_UNIT_BOOL, SIMCONNECT_DATAType_INT32);
AddVariable(DEFINITION_GEAR, 'GEAR TOTAL PCT EXTENDED', FSX_UNIT_PERCENT, SIMCONNECT_DATAType_FLOAT64);
AddVariable(DEFINITION_GEAR, 'GEAR DAMAGE BY SPEED', FSX_UNIT_BOOL, SIMCONNECT_DATAType_INT32);
AddVariable(DEFINITION_GEAR, 'GEAR SPEED EXCEEDED', FSX_UNIT_BOOL, SIMCONNECT_DATAType_INT32);
AddDefinition(DEFINITION_GEAR);
end;
{ Lights }
if Consumer.FunctionMap.HasFunction([FUNCTION_FSX_LANDINGLIGHTS, FUNCTION_FSX_INSTRUMENTLIGHTS,
FUNCTION_FSX_STROBELIGHTS, FUNCTION_FSX_NAVLIGHTS,
FUNCTION_FSX_BEACONLIGHTS, FUNCTION_FSX_TAXILIGHTS,
FUNCTION_FSX_RECOGNITIONLIGHTS]) then
begin
AddVariable(DEFINITION_LIGHTS, 'LIGHT ON STATES', FSX_UNIT_MASK, SIMCONNECT_DATATYPE_INT32);
AddDefinition(DEFINITION_LIGHTS);
end;
{ Parking brake }
if Consumer.FunctionMap.HasFunction(FUNCTION_FSX_PARKINGBRAKE) then
begin
AddVariable(DEFINITION_PARKINGBRAKE, 'BRAKE PARKING INDICATOR', FSX_UNIT_BOOL, SIMCONNECT_DATATYPE_INT32);
AddDefinition(DEFINITION_PARKINGBRAKE);
end;
{ Engine }
if Consumer.FunctionMap.HasFunction(FUNCTION_FSX_ENGINE) then
begin
AddVariable(DEFINITION_ENGINE, 'NUMBER OF ENGINES', FSX_UNIT_NUMBER, SIMCONNECT_DATAType_INT32);
for engineIndex := 1 to MAX_ENGINES do
AddVariable(DEFINITION_ENGINE, Format('GENERAL ENG COMBUSTION:%d', [engineIndex]), FSX_UNIT_BOOL, SIMCONNECT_DATAType_INT32);
for engineIndex := 1 to MAX_ENGINES do
AddVariable(DEFINITION_ENGINE, Format('ENG FAILED:%d', [engineIndex]), FSX_UNIT_BOOL, SIMCONNECT_DATAType_INT32);
for engineIndex := 1 to MAX_ENGINES do
AddVariable(DEFINITION_ENGINE, Format('ENG ON FIRE:%d', [engineIndex]), FSX_UNIT_BOOL, SIMCONNECT_DATAType_INT32);
AddDefinition(DEFINITION_ENGINE);
end;
{ Exit door }
if Consumer.FunctionMap.HasFunction(FUNCTION_FSX_EXITDOOR) or
Consumer.FunctionMap.HasFunction(FUNCTION_FSX_TAILHOOK) then
begin
AddVariable(DEFINITION_EXITDOOR, 'CANOPY OPEN', FSX_UNIT_PERCENT, SIMCONNECT_DATAType_FLOAT64);
AddVariable(DEFINITION_EXITDOOR, 'TAILHOOK POSITION', FSX_UNIT_PERCENT, SIMCONNECT_DATAType_FLOAT64);
AddDefinition(DEFINITION_EXITDOOR);
end;
{ Flaps & spoilers }
if Consumer.FunctionMap.HasFunction([FUNCTION_FSX_FLAPS, FUNCTION_FSX_SPOILERS]) then
begin
AddVariable(DEFINITION_FLAPSSPOILERS, 'FLAPS AVAILABLE', FSX_UNIT_BOOL, SIMCONNECT_DATAType_INT32);
AddVariable(DEFINITION_FLAPSSPOILERS, 'FLAPS HANDLE PERCENT', FSX_UNIT_PERCENT, SIMCONNECT_DATAType_FLOAT64);
AddVariable(DEFINITION_FLAPSSPOILERS, 'SPOILER AVAILABLE', FSX_UNIT_BOOL, SIMCONNECT_DATAType_INT32);
AddVariable(DEFINITION_FLAPSSPOILERS, 'SPOILERS HANDLE POSITION', FSX_UNIT_PERCENT, SIMCONNECT_DATAType_FLOAT64);
AddDefinition(DEFINITION_FLAPSSPOILERS);
end;
{ Master switches }
if Consumer.FunctionMap.HasFunction([FUNCTION_FSX_BATTERYMASTER, FUNCTION_FSX_AVIONICSMASTER,
FUNCTION_FSX_PRESSURIZATIONDUMPSWITCH,
FUNCTION_FSX_AUTOPILOT, FUNCTION_FSX_FUELPUMP,
FUNCTION_FSX_AUTOPILOT_AMBER, FUNCTION_FSX_AUTOPILOT_HEADING,
FUNCTION_FSX_AUTOPILOT_APPROACH, FUNCTION_FSX_AUTOPILOT_BACKCOURSE,
FUNCTION_FSX_AUTOPILOT_ALTITUDE, FUNCTION_FSX_AUTOPILOT_NAV]) then
begin
AddVariable(DEFINITION_SWITCHES, 'AVIONICS MASTER SWITCH', FSX_UNIT_BOOL, SIMCONNECT_DATAType_INT32);
AddVariable(DEFINITION_SWITCHES, 'ELECTRICAL MASTER BATTERY', FSX_UNIT_BOOL, SIMCONNECT_DATAType_INT32);
AddVariable(DEFINITION_SWITCHES, 'PRESSURIZATION DUMP SWITCH', FSX_UNIT_BOOL, SIMCONNECT_DATAType_INT32);
AddVariable(DEFINITION_SWITCHES, 'AUTOPILOT AVAILABLE', FSX_UNIT_BOOL, SIMCONNECT_DATAType_INT32);
AddVariable(DEFINITION_SWITCHES, 'AUTOPILOT MASTER', FSX_UNIT_BOOL, SIMCONNECT_DATAType_INT32);
// AddVariable(DEFINITION_SWITCHES, 'fuel pump?', FSX_UNIT_BOOL, SIMCONNECT_DATAType_INT32);
AddVariable(DEFINITION_SWITCHES, 'AUTOPILOT HEADING LOCK', FSX_UNIT_BOOL, SIMCONNECT_DATAType_INT32);
AddVariable(DEFINITION_SWITCHES, 'AUTOPILOT APPROACH HOLD', FSX_UNIT_BOOL, SIMCONNECT_DATAType_INT32);
AddVariable(DEFINITION_SWITCHES, 'AUTOPILOT BACKCOURSE HOLD', FSX_UNIT_BOOL, SIMCONNECT_DATAType_INT32);
AddVariable(DEFINITION_SWITCHES, 'AUTOPILOT ALTITUDE LOCK', FSX_UNIT_BOOL, SIMCONNECT_DATAType_INT32);
AddVariable(DEFINITION_SWITCHES, 'AUTOPILOT NAV1 LOCK', FSX_UNIT_BOOL, SIMCONNECT_DATAType_INT32);
AddDefinition(DEFINITION_SWITCHES);
end;
{ Anti-ice }
if Consumer.FunctionMap.HasFunction([FUNCTION_FSX_ENGINEANTIICE, FUNCTION_FSX_DEICE]) then
begin
AddVariable(DEFINITION_ANTIICE, 'NUMBER OF ENGINES', FSX_UNIT_NUMBER, SIMCONNECT_DATAType_INT32);
// for engineIndex := 1 to MAX_ENGINES do
// AddVariable(DEFINITION_ANTIICE, Format('GENERAL ENG ANTI ICE POSITION:%d', [engineIndex]), FSX_UNIT_BOOL, SIMCONNECT_DATAType_INT32);
//
// for engineIndex := 1 to MAX_ENGINES do
// AddVariable(DEFINITION_ANTIICE, Format('PROP DEICE SWITCH:%d', [engineIndex]), FSX_UNIT_BOOL, SIMCONNECT_DATAType_INT32);
for engineIndex := 1 to MAX_ENGINES do
AddVariable(DEFINITION_ANTIICE, Format('ENG ANTI ICE:%d', [engineIndex]), FSX_UNIT_BOOL, SIMCONNECT_DATAType_INT32);
AddVariable(DEFINITION_ANTIICE, 'STRUCTURAL DEICE SWITCH', FSX_UNIT_BOOL, SIMCONNECT_DATAType_INT32);
AddDefinition(DEFINITION_ANTIICE);
end;
{ Throttle }
{
AddVariable(DEFINITION_THROTTLE, FSX_VARIABLE_NUMBEROFENGINES, FSX_UNIT_NUMBER, SIMCONNECT_DATAType_INT32);
for engineIndex := 1 to MAX_ENGINES do
AddVariable(DEFINITION_THROTTLE, Format(FSX_VARIABLE_ENGTHROTTLELEVERPOS, [engineIndex]), FSX_UNIT_PERCENT);
AddDefinition(DEFINITION_THROTTLE);
}
end;
procedure TFSXLEDStateProvider.SetFSXLightState(AStates: Cardinal; AMask: Integer; AFunction: Integer);
begin
if (AStates and AMask) <> 0 then
Consumer.SetStateByFunction(AFunction, lsGreen)
else
Consumer.SetStateByFunction(AFunction, lsRed);
end;
procedure TFSXLEDStateProvider.HandleDispatch(AData: PSimConnectRecv);
var
simObjectData: PSimConnectRecvSimObjectData;
data: Pointer;
// throttleData: PThrottleData;
begin
case SIMCONNECT_RECV_ID(AData^.dwID) of
SIMCONNECT_RECV_ID_SIMOBJECT_DATA:
begin
simObjectData := PSimConnectRecvSimObjectData(AData);
data := @simObjectData^.dwData;
case simObjectData^.dwRequestID of
DEFINITION_GEAR: HandleGearData(data);
DEFINITION_LIGHTS: HandleLightsData(data);
DEFINITION_PARKINGBRAKE: HandleParkingBrakeData(data);
DEFINITION_ENGINE: HandleEngineData(data);
DEFINITION_EXITDOOR: HandleExitDoorData(data);
DEFINITION_FLAPSSPOILERS: HandleFlapsData(data);
DEFINITION_SWITCHES: HandleSwitchesData(data);
DEFINITION_ANTIICE: HandleAntiIceData(data);
{
DEFINITION_THROTTLE:
begin
throttleData := @simObjectData^.dwData;
if throttleData^.NumberOfEngines > 2 then
begin
if (throttleData^.ThrottleLeverPos[4] <> throttleData^.ThrottleLeverPos[1]) or
(throttleData^.ThrottleLeverPos[3] <> throttleData^.ThrottleLeverPos[2]) then
begin
throttleData^.ThrottleLeverPos[4] := throttleData^.ThrottleLeverPos[1];
throttleData^.ThrottleLeverPos[3] := throttleData^.ThrottleLeverPos[2];
SimConnect_SetDataOnSimObject(SimConnectHandle, DEFINITION_THROTTLE, SIMCONNECT_OBJECT_ID_USER,
0, 0, SizeOf(throttleData^), throttleData);
end;
end;
end;
}
end;
end;
SIMCONNECT_RECV_ID_QUIT:
Terminate;
end;
end;
procedure TFSXLEDStateProvider.HandleGearData(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
Consumer.SetStateByFunction(FUNCTION_FSX_GEAR, lsError)
else if gearData^.SpeedExceeded <> 0 then
Consumer.SetStateByFunction(FUNCTION_FSX_GEAR, lsWarning)
else if gearData^.IsGearRetractable <> 0 then
begin
case Trunc(gearData ^.TotalPctExtended * 100) of
0: Consumer.SetStateByFunction(FUNCTION_FSX_GEAR, lsRed);
95..100: Consumer.SetStateByFunction(FUNCTION_FSX_GEAR, lsGreen);
else Consumer.SetStateByFunction(FUNCTION_FSX_GEAR, lsAmber);
end;
end else
Consumer.SetStateByFunction(FUNCTION_FSX_GEAR, lsOff);
end;
procedure TFSXLEDStateProvider.HandleLightsData(AData: Pointer);
var
state: Cardinal;
begin
state := PCardinal(AData)^;
SetFSXLightState(state, FSX_LIGHTON_LANDING, FUNCTION_FSX_LANDINGLIGHTS);
SetFSXLightState(state, FSX_LIGHTON_PANEL, FUNCTION_FSX_INSTRUMENTLIGHTS);
SetFSXLightState(state, FSX_LIGHTON_BEACON, FUNCTION_FSX_BEACONLIGHTS);
SetFSXLightState(state, FSX_LIGHTON_NAV, FUNCTION_FSX_NAVLIGHTS);
SetFSXLightState(state, FSX_LIGHTON_STROBE, FUNCTION_FSX_STROBELIGHTS);
SetFSXLightState(state, FSX_LIGHTON_TAXI, FUNCTION_FSX_TAXILIGHTS);
SetFSXLightState(state, FSX_LIGHTON_RECOGNITION, FUNCTION_FSX_RECOGNITIONLIGHTS);
end;
procedure TFSXLEDStateProvider.HandleParkingBrakeData(AData: Pointer);
begin
if PCardinal(AData)^ <> 0 then
Consumer.SetStateByFunction(FUNCTION_FSX_PARKINGBRAKE, lsRed)
else
Consumer.SetStateByFunction(FUNCTION_FSX_PARKINGBRAKE, lsGreen);
end;
procedure TFSXLEDStateProvider.HandleEngineData(AData: Pointer);
type
PEngineData = ^TEngineData;
TEngineData = packed record
NumberOfEngines: Integer;
Combustion: array[1..MAX_ENGINES] of Integer;
Failed: array[1..MAX_ENGINES] of Integer;
OnFire: array[1..MAX_ENGINES] of Integer;
end;
var
engineData: PEngineData;
engineIndex: Integer;
state: TLEDState;
begin
engineData := AData;
if engineData^.NumberOfEngines > 0 then
begin
state := lsGreen;
for engineIndex := 1 to Min(engineData^.NumberOfEngines, MAX_ENGINES) do
begin
if engineData^.OnFire[engineIndex] <> 0 then
begin
state := lsError;
break;
end else if engineData^.Failed[engineIndex] <> 0 then
state := lsWarning
else if (engineData^.Combustion[engineIndex] = 0) and
(state = lsGreen) then
state := lsRed;
end;
Consumer.SetStateByFunction(FUNCTION_FSX_ENGINE, state);
end else
Consumer.SetStateByFunction(FUNCTION_FSX_ENGINE, lsOff);
end;
procedure TFSXLEDStateProvider.HandleExitDoorData(AData: Pointer);
type
PExitDoorData = ^TExitDoorData;
TExitDoorData = packed record
PercentOpen: Double;
TailHookPercent: Double;
end;
var
exitDoorData: PExitDoorData;
begin
exitDoorData := AData;
case Trunc(exitDoorData^.PercentOpen) of
0: Consumer.SetStateByFunction(FUNCTION_FSX_EXITDOOR, lsGreen);
95..100: Consumer.SetStateByFunction(FUNCTION_FSX_EXITDOOR, lsRed);
else Consumer.SetStateByFunction(FUNCTION_FSX_EXITDOOR, lsAmber);
end;
case Trunc(exitDoorData^.TailHookPercent) of
0: Consumer.SetStateByFunction(FUNCTION_FSX_TAILHOOK, lsGreen);
95..100: Consumer.SetStateByFunction(FUNCTION_FSX_TAILHOOK, lsRed);
else Consumer.SetStateByFunction(FUNCTION_FSX_TAILHOOK, lsAmber);
end;
end;
procedure TFSXLEDStateProvider.HandleFlapsData(AData: Pointer);
type
PFlapsData = ^TFlapsData;
TFlapsData = packed record
FlapsAvailable: Cardinal;
FlapsHandlePercent: Double;
SpoilersAvailable: Cardinal;
SpoilersHandlePercent: Double;
end;
var
flapsData: PFlapsData;
begin
flapsData := AData;
if flapsData^.FlapsAvailable <> 0 then
begin
case Trunc(flapsData^.FlapsHandlePercent) of
0: Consumer.SetStateByFunction(FUNCTION_FSX_FLAPS, lsGreen);
95..100: Consumer.SetStateByFunction(FUNCTION_FSX_FLAPS, lsRed);
else Consumer.SetStateByFunction(FUNCTION_FSX_FLAPS, lsAmber);
end;
end else
Consumer.SetStateByFunction(FUNCTION_FSX_FLAPS, lsOff);
if flapsData^.SpoilersAvailable <> 0 then
begin
case Trunc(flapsData^.SpoilersHandlePercent) of
0: Consumer.SetStateByFunction(FUNCTION_FSX_SPOILERS, lsGreen);
95..100: Consumer.SetStateByFunction(FUNCTION_FSX_SPOILERS, lsRed);
else Consumer.SetStateByFunction(FUNCTION_FSX_SPOILERS, lsAmber);
end;
end else
Consumer.SetStateByFunction(FUNCTION_FSX_SPOILERS, lsOff);
end;
procedure TFSXLEDStateProvider.HandleSwitchesData(AData: Pointer);
const
ONOFF_STATE: array[Boolean] of TLEDState = (lsRed, lsGreen);
AMBER_ONOFF_STATE: array[Boolean] of TLEDState = (lsOff, lsAmber);
type
PSwitchesData = ^TSwitchesData;
TSwitchesData = packed record
AvionicsSwitch: Cardinal;
BatterySwitch: Cardinal;
PressurizationDumpSwitch: Cardinal;
AutoPilotAvailable: Cardinal;
AutoPilotMaster: Cardinal;
AutoPilotHeading: Cardinal;
AutoPilotApproach: Cardinal;
AutoPilotBackcourse: Cardinal;
AutoPilotAltitude: Cardinal;
AutoPilotNav: Cardinal;
end;
var
switchesData: PSwitchesData;
begin
switchesData := AData;
Consumer.SetStateByFunction(FUNCTION_FSX_AVIONICSMASTER, ONOFF_STATE[switchesData^.AvionicsSwitch <> 0]);
Consumer.SetStateByFunction(FUNCTION_FSX_BATTERYMASTER, ONOFF_STATE[switchesData^.BatterySwitch <> 0]);
Consumer.SetStateByFunction(FUNCTION_FSX_PRESSURIZATIONDUMPSWITCH, ONOFF_STATE[switchesData^.PressurizationDumpSwitch <> 0]);
if switchesData^.AutoPilotAvailable <> 0 then
begin
Consumer.SetStateByFunction(FUNCTION_FSX_AUTOPILOT, ONOFF_STATE[switchesData^.AutoPilotMaster <> 0]);
Consumer.SetStateByFunction(FUNCTION_FSX_AUTOPILOT_AMBER, AMBER_ONOFF_STATE[switchesData^.AutoPilotMaster <> 0]);
Consumer.SetStateByFunction(FUNCTION_FSX_AUTOPILOT_HEADING, AMBER_ONOFF_STATE[switchesData^.AutoPilotHeading <> 0]);
Consumer.SetStateByFunction(FUNCTION_FSX_AUTOPILOT_APPROACH, AMBER_ONOFF_STATE[switchesData^.AutoPilotApproach <> 0]);
Consumer.SetStateByFunction(FUNCTION_FSX_AUTOPILOT_BACKCOURSE, AMBER_ONOFF_STATE[switchesData^.AutoPilotBackcourse <> 0]);
Consumer.SetStateByFunction(FUNCTION_FSX_AUTOPILOT_ALTITUDE, AMBER_ONOFF_STATE[switchesData^.AutoPilotAltitude <> 0]);
Consumer.SetStateByFunction(FUNCTION_FSX_AUTOPILOT_NAV, AMBER_ONOFF_STATE[switchesData^.AutoPilotNav <> 0]);
end else
begin
Consumer.SetStateByFunction(FUNCTION_FSX_AUTOPILOT, lsOff);
Consumer.SetStateByFunction(FUNCTION_FSX_AUTOPILOT_AMBER, lsOff);
Consumer.SetStateByFunction(FUNCTION_FSX_AUTOPILOT_HEADING, lsOff);
Consumer.SetStateByFunction(FUNCTION_FSX_AUTOPILOT_APPROACH, lsOff);
Consumer.SetStateByFunction(FUNCTION_FSX_AUTOPILOT_BACKCOURSE, lsOff);
Consumer.SetStateByFunction(FUNCTION_FSX_AUTOPILOT_ALTITUDE, lsOff);
Consumer.SetStateByFunction(FUNCTION_FSX_AUTOPILOT_NAV, lsOff);
end;
end;
procedure TFSXLEDStateProvider.HandleAntiIceData(AData: Pointer);
function EngineHasBoolean(AArray: array of Integer; ANumberOfEngines: Integer): Boolean;
var
engineIndex: Integer;
begin
Result := False;
for engineIndex := 1 to Max(ANumberOfEngines, MAX_ENGINES) do
if AArray[engineIndex] <> 0 then
begin
Result := True;
break;
end;
end;
const
ONOFF_STATE: array[Boolean] of TLEDState = (lsRed, lsGreen);
type
PAntiIceData = ^TAntiIceData;
TAntiIceData = packed record
NumberOfEngines: Integer;
// GeneralEngineAntiIce: array[1..MAX_ENGINES] of Integer;
// PropDeIce: array[1..MAX_ENGINES] of Integer;
EngineAntiIce: array[1..MAX_ENGINES] of Integer;
StructuralAntiIce: Integer;
end;
var
antiIceData: PAntiIceData;
begin
antiIceData := AData;
Consumer.SetStateByFunction(FUNCTION_FSX_DEICE, ONOFF_STATE[antiIceData^.StructuralAntiIce <> 0]);
Consumer.SetStateByFunction(FUNCTION_FSX_ENGINEANTIICE, ONOFF_STATE[EngineHasBoolean(antiIceData^.EngineAntiIce, antiIceData^.NumberOfEngines)]);
end;
procedure TFSXLEDStateProvider.AddDefinition(ADefinition: Cardinal);
begin
FDefinitions.Add(Pointer(ADefinition));
SimConnect_RequestDataOnSimObject(SimConnectHandle,
ADefinition,
ADefinition,
SIMCONNECT_OBJECT_ID_USER,
SIMCONNECT_PERIOD_SIM_FRAME,
SIMCONNECT_DATA_REQUEST_FLAG_CHANGED);
end;
procedure TFSXLEDStateProvider.AddVariable(ADefineID: Cardinal; ADatumName, AUnitsName: string;
ADatumType: SIMCONNECT_DATAType; AEpsilon: Single;
ADatumID: DWORD);
begin
SimConnect_AddToDataDefinition(SimConnectHandle, ADefineID, AnsiString(ADatumName), AnsiString(AUnitsName), ADatumType, AEpsilon, ADatumID);
end;
procedure TFSXLEDStateProvider.ClearDefinitions;
var
definition: Pointer;
begin
if SimConnectHandle <> 0 then
begin
for definition in FDefinitions do
SimConnect_ClearDataDefinition(SimConnectHandle, Cardinal(definition));
end;
FDefinitions.Clear;
end;
function TFSXLEDStateProvider.GetProcessMessagesInterval: Integer;
begin
Result := 50;
end;
end.