Skip to content

Commit

Permalink
Add new input event APIs from SU 13 (needs testing)
Browse files Browse the repository at this point in the history
Issue #86
  • Loading branch information
EvenAR committed Nov 14, 2023
1 parent 9789814 commit 7ed01ea
Show file tree
Hide file tree
Showing 12 changed files with 280 additions and 0 deletions.
51 changes: 51 additions & 0 deletions samples/typescript/inputEvents.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import { open, Protocol } from '../../dist';

/**
* Collects information about all available input events for the aircraft and prints them
*/
open('My app', Protocol.KittyHawk)
.then(({ recvOpen, handle }) => {
console.log('Connected: ', recvOpen);

let allInputEvents: {
inputEventName: string;
inputEventIdHash: string;
params?: string;
}[] = [];

handle.on('inputEventsList', recvEnumerateInputEvents => {
recvEnumerateInputEvents.inputEventDescriptors.forEach(e => {
allInputEvents.push({
inputEventName: e.name,
inputEventIdHash: e.inputEventIdHash.toString(),
});
handle.enumerateInputEventParams(e.inputEventIdHash);
});
});

handle.on('enumerateInputEventParams', recvEnumerateInputEventParams => {
// Update the list with the received value
allInputEvents = allInputEvents.map(inputEvent => {
if (
inputEvent.inputEventIdHash ===
recvEnumerateInputEventParams.inputEventIdHash.toString()
) {
return { ...inputEvent, params: recvEnumerateInputEventParams.value };
} else {
return inputEvent;
}
});

// Finally, when no input events are missing the params value, print the list
if (allInputEvents.filter(ev => ev.params === undefined).length === 0) {
console.log(allInputEvents);
}
});

handle.on('exception', ex => console.log('Exception', ex));

handle.enumerateInputEvents(0 /* request-id */);
})
.catch(error => {
console.log('Failed to connect', error);
});
12 changes: 12 additions & 0 deletions src/RawBuffer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,13 +71,25 @@ class RawBuffer {
return this.buffer.readInt64().toNumber();
}

readUint64(): Long {
return this.buffer.readUint64();
}

/** @deprecated use readInt64() instead */
readLong = this.readInt64;

writeInt64(value: number) {
this.buffer.writeInt64(value);
}

writeUint32(value: number, offset?: number) {
this.buffer.writeUint64(value, offset);
}

writeUint64(value: Long, offset?: number) {
this.buffer.writeUint64(value, offset);
}

/** @deprecated use writeInt64() instead */
writeLong = this.writeInt64;

Expand Down
96 changes: 96 additions & 0 deletions src/SimConnectConnection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,10 @@ import {
} from './Types';
import Timeout = NodeJS.Timeout;
import { RecvControllersList } from './recv/RecvControllersList';
import { RecvEnumerateInputEvents } from './recv/RecvEnumerateInputEvents';
import { RecvGetInputEvent } from './recv/RecvGetInputEvent';
import { RecvSubscribeInputEvent } from './recv/RecvSubscribeInputEvent';
import { RecvEnumerateInputEventParams } from './recv/RecvEnumerateInputEventParams';

type OpenPacketData = {
major: number;
Expand Down Expand Up @@ -131,6 +135,12 @@ interface SimConnectRecvEvents {
facilityMinimalList: (recvFacilityMinimalList: RecvFacilityMinimalList) => void;
jetwayData: (recvJetwayData: RecvJetwayData) => void;
controllersList: (recvControllersList: RecvControllersList) => void;
inputEventsList: (recvEnumerateInputEvents: RecvEnumerateInputEvents) => void;
getInputEvent: (recvGetInputEvent: RecvGetInputEvent) => void;
subscribeInputEvent: (recvSubscribeInputEvent: RecvSubscribeInputEvent) => void;
enumerateInputEventParams: (
recvEnumerateInputEventParams: RecvEnumerateInputEventParams
) => void;
}

type ConnectionOptions =
Expand Down Expand Up @@ -1526,6 +1536,78 @@ class SimConnectConnection extends EventEmitter {
);
}

// TODO: implement 0x4e: executeAction(dataRequestID: number, actionID: string, values: RawBuffer)

/**
*
* @returns sendId of packet (can be used to identify packet when exception event occurs)
*/
enumerateInputEvents(dataRequestID: number): number {
if (this._ourProtocol < Protocol.KittyHawk) throw Error(SimConnectError.BadVersion);

const packet = this._beginPacket(0x4f).putInt32(dataRequestID);
return this._buildAndSend(packet);
}

/**
*
* @returns sendId of packet (can be used to identify packet when exception event occurs)
*/
getInputEvent(dataRequestID: number, inputEventHashID: Long): number {
if (this._ourProtocol < Protocol.KittyHawk) throw Error(SimConnectError.BadVersion);

const packet = this._beginPacket(0x50).putInt32(dataRequestID).putUint64(inputEventHashID);
return this._buildAndSend(packet);
}

/**
*
* @returns sendId of packet (can be used to identify packet when exception event occurs)
*/
setInputEvent(inputEventHashID: Long, value: number | string): number {
if (this._ourProtocol < Protocol.KittyHawk) throw Error(SimConnectError.BadVersion);

const packet = this._beginPacket(0x51).putUint64(inputEventHashID);

if (typeof value === 'string') {
packet.putInt32(value.length).putString(value);
} else {
packet.putInt32(4).putFloat32(value);
}

return this._buildAndSend(packet);
}

/**
*
* @returns sendId of packet (can be used to identify packet when exception event occurs)
*/
subscribeInputEvent(inputEventHashID: Long): number {
if (this._ourProtocol < Protocol.KittyHawk) throw Error(SimConnectError.BadVersion);

return this._buildAndSend(this._beginPacket(0x52).putUint64(inputEventHashID));
}

/**
*
* @returns sendId of packet (can be used to identify packet when exception event occurs)
*/
unsubscribeInputEvent(inputEventHashID: Long): number {
if (this._ourProtocol < Protocol.KittyHawk) throw Error(SimConnectError.BadVersion);

return this._buildAndSend(this._beginPacket(0x53).putUint64(inputEventHashID));
}

/**
*
* @returns sendId of packet (can be used to identify packet when exception event occurs)
*/
enumerateInputEventParams(inputEventHashID: Long): number {
if (this._ourProtocol < Protocol.KittyHawk) throw Error(SimConnectError.BadVersion);

return this._buildAndSend(this._beginPacket(0x54).putUint64(inputEventHashID));
}

close() {
if (this._openTimeout !== null) {
clearTimeout(this._openTimeout);
Expand Down Expand Up @@ -1657,6 +1739,20 @@ class SimConnectConnection extends EventEmitter {
case RecvID.ID_CONTROLLERS_LIST:
this.emit('controllersList', new RecvControllersList(data));
break;
case RecvID.ID_ACTION_CALLBACK:
break;
case RecvID.ID_ENUMERATE_INPUT_EVENTS:
this.emit('inputEventsList', new RecvEnumerateInputEvents(data));
break;
case RecvID.ID_GET_INPUT_EVENT:
this.emit('getInputEvent', new RecvGetInputEvent(data));
break;
case RecvID.ID_SUBSCRIBE_INPUT_EVENT:
this.emit('subscribeInputEvent', new RecvSubscribeInputEvent(data));
break;
case RecvID.ID_ENUMERATE_INPUT_EVENT_PARAMS:
this.emit('enumerateInputEventParams', new RecvEnumerateInputEventParams(data));
break;
}
}

Expand Down
10 changes: 10 additions & 0 deletions src/SimConnectPacketBuilder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,16 @@ export class SimConnectPacketBuilder {
return this;
}

putUint32(value: number, offset?: number) {
this.packetContent.writeUint32(value, offset);
return this;
}

putUint64(value: Long, offset?: number) {
this.packetContent.writeUint64(value, offset);
return this;
}

putByte(value: number) {
this.packetContent.writeByte(value);
return this;
Expand Down
5 changes: 5 additions & 0 deletions src/SimConnectSocket.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,11 @@ enum RecvID {
ID_FACILITY_MINIMAL_LIST,
ID_JETWAY_DATA,
ID_CONTROLLERS_LIST,
ID_ACTION_CALLBACK,
ID_ENUMERATE_INPUT_EVENTS,
ID_GET_INPUT_EVENT,
ID_SUBSCRIBE_INPUT_EVENT,
ID_ENUMERATE_INPUT_EVENT_PARAMS,
}

interface SimConnectMessage {
Expand Down
16 changes: 16 additions & 0 deletions src/datastructures/InputEventDescriptor.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { InputEventType } from '../enums/InputEventType';
import { RawBuffer } from '../RawBuffer';

export class InputEventDescriptor {
name: string;

inputEventIdHash: Long;

type: InputEventType;

constructor(data: RawBuffer) {
this.name = data.readString64();
this.inputEventIdHash = data.readUint64();
this.type = data.readUint32() as InputEventType;
}
}
4 changes: 4 additions & 0 deletions src/enums/InputEventType.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export const enum InputEventType {
DOUBLE,
STRING,
}
5 changes: 5 additions & 0 deletions src/enums/SimConnectException.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,11 @@ export enum SimConnectException {
OBJECT_ATC,
OBJECT_SCHEDULE,
JETWAY_DATA,
ACTION_NOT_FOUND,
NOT_AN_ACTION,
INCORRECT_ACTION_PARAMS,
GET_INPUT_EVENT_FAILED,
SET_INPUT_EVENT_FAILED,
}

module.exports = {
Expand Down
12 changes: 12 additions & 0 deletions src/recv/RecvEnumerateInputEventParams.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { RawBuffer } from '../RawBuffer';

export class RecvEnumerateInputEventParams {
inputEventIdHash: Long;

value: string;

constructor(data: RawBuffer) {
this.inputEventIdHash = data.readUint64();
this.value = data.readStringV();
}
}
16 changes: 16 additions & 0 deletions src/recv/RecvEnumerateInputEvents.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { RecvListTemplate } from './RecvListTemplate';
import { RawBuffer } from '../RawBuffer';
import { InputEventDescriptor } from '../datastructures/InputEventDescriptor';

export class RecvEnumerateInputEvents extends RecvListTemplate {
inputEventDescriptors: InputEventDescriptor[] = [];

constructor(data: RawBuffer) {
super(data);

this.inputEventDescriptors = [];
for (let i = 0; i < this.arraySize; i++) {
this.inputEventDescriptors.push(new InputEventDescriptor(data));
}
}
}
27 changes: 27 additions & 0 deletions src/recv/RecvGetInputEvent.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { RawBuffer } from '../RawBuffer';
import { DataRequestId } from '../Types';
import { InputEventType } from '../enums/InputEventType';

export class RecvGetInputEvent {
requestID: DataRequestId;

type: InputEventType;

value: number | string;

constructor(data: RawBuffer) {
this.requestID = data.readInt32();
this.type = data.readUint32();

switch (this.type) {
case InputEventType.STRING:
this.value = data.readString256();
break;
case InputEventType.DOUBLE:
this.value = data.readFloat64();
break;
default:
throw Error(`Unknown input event type: ${this.type}`);
}
}
}
26 changes: 26 additions & 0 deletions src/recv/RecvSubscribeInputEvent.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { RawBuffer } from '../RawBuffer';
import { InputEventType } from '../enums/InputEventType';

export class RecvSubscribeInputEvent {
inputEventIdHash: Long;

type: InputEventType;

value: number | string;

constructor(data: RawBuffer) {
this.inputEventIdHash = data.readUint64();
this.type = data.readUint32();

switch (this.type) {
case InputEventType.STRING:
this.value = data.readString256();
break;
case InputEventType.DOUBLE:
this.value = data.readFloat64();
break;
default:
throw Error(`Unknown input event type: ${this.type}`);
}
}
}

0 comments on commit 7ed01ea

Please sign in to comment.