UNPKG

homebridge-xbox-tv

Version:

Homebridge plugin to control Xbox game consoles.

328 lines (313 loc) • 12.5 kB
import { LocalApi } from '../constants.js'; class Packets { constructor(structure) { this.structure = structure; const types = { flags(length, value) { const packet = { value: value, length: length, pack(packetStructure) { return packetStructure.writeBytes(setFlags(this.value)); }, unpack(packetStructure) { return readFlags(packetStructure.readBytes(this.length)); } } return packet; }, bytes(length, value) { const packet = { value: value, length: length, pack(packetStructure) { return packetStructure.writeBytes(this.value); }, unpack(packetStructure) { return packetStructure.readBytes(length); } } return packet; }, uInt16(value) { const packet = { value: value, pack(packetStructure) { return packetStructure.writeUInt16(this.value); }, unpack(packetStructure) { return packetStructure.readUInt16(); } } return packet; }, uInt32(value) { const packet = { value: value, pack(packetStructure) { return packetStructure.writeUInt32(this.value); }, unpack(packetStructure) { return packetStructure.readUInt32(); } } return packet; }, sInt32(value) { const packet = { value: value, pack(packetStructure) { return packetStructure.writeInt32(this.value); }, unpack(packetStructure) { return packetStructure.readInt32(); } } return packet; }, uInt64(length, value) { const packet = { value: value, length: length, pack(packetStructure) { return packetStructure.writeBytes(this.value); }, unpack(packetStructure) { return packetStructure.readBytes(length); } } return packet; }, sgString(value) { const packet = { value: value, pack(packetStructure) { return packetStructure.writeSGString(this.value); }, unpack(packetStructure) { return packetStructure.readSGString().toString(); } } return packet; }, sgArray(structure, value) { const packet = { value: value, structure: structure, pack(packetStructure) { packetStructure.writeUInt16(this.value.length); let arrayStructure = packets[this.structure]; for (const index in this.value) { for (const name in arrayStructure) { arrayStructure[name].value = this.value[index][name] packetStructure = arrayStructure[name].pack(packetStructure); } } return packetStructure; }, unpack(packetStructure) { const arrayCount = packetStructure.readUInt16(); const array = []; for (let i = 0; i < arrayCount; i++) { const arrayStructure = packets[this.structure]; const item = {}; for (const name in arrayStructure) { item[name] = arrayStructure[name].unpack(packetStructure); } array.push(item); } return array; } } return packet; }, sgList(structure, value) { const packet = { value: value, structure: structure, pack(packetStructure) { packetStructure.writeUInt32(this.value.length); const arrayStructure = packets[this.structure]; for (const item of this.value) { for (const name in arrayStructure) { arrayStructure[name].value = item[name]; packetStructure = arrayStructure[name].pack(packetStructure); } } return packetStructure; }, unpack(packetStructure) { const arrayCount = packetStructure.readUInt32(); const array = []; for (let i = 0; i < arrayCount; i++) { const arrayStructure = packets[this.structure]; const item = {}; for (const name in arrayStructure) { item[name] = arrayStructure[name].unpack(packetStructure); } array.push(item); } return array; } }; return packet; }, mapper(map, item) { const packet = { item: item, value: false, pack(packetStructure) { return item.pack(packetStructure); }, unpack(packetStructure) { return map[item.unpack(packetStructure)]; } }; return packet; } }; const packets = { powerOn: { liveId: types.sgString(), }, json: { json: types.sgString('{}') }, discoveryRequest: { flags: types.uInt32('0'), clientType: types.uInt16('3'), minVersion: types.uInt16('0'), maxVersion: types.uInt16('2') }, discoveryResponse: { flags: types.uInt32('0'), clientType: types.uInt16('0'), name: types.sgString(), uuid: types.sgString(), lastError: types.uInt32('0'), certificateLength: types.uInt16('0'), certificate: types.bytes() }, connectRequest: { uuid: types.bytes(16, ''), publicKeyType: types.uInt16('0'), publicKey: types.bytes(64, ''), iv: types.bytes(16, ''), payloadProtected: types.bytes() }, connectResponse: { iv: types.bytes(16, ''), payloadProtected: types.bytes() }, connectRequestProtected: { userHash: types.sgString(''), jwt: types.sgString(''), connectRequestNum: types.uInt32('0'), connectRequestGroupStart: types.uInt32('0'), connectRequestGroupEnd: types.uInt32('1') }, connectResponseProtected: { connectResult: types.uInt16('1'), pairingState: types.uInt16('2'), participantId: types.uInt32('0') }, localJoin: { clientType: types.uInt16('3'), nativeWidth: types.uInt16('1080'), nativeHeight: types.uInt16('1920'), dpiX: types.uInt16('96'), dpiY: types.uInt16('96'), deviceCapabilities: types.uInt64(8, Buffer.from('ffffffffffffffff', 'hex')), clientVersion: types.uInt32('15'), osMajorVersion: types.uInt32('6'), osMinorVersion: types.uInt32('2'), displayName: types.sgString('Xbox-TV'), }, channelStartRequest: { channelRequestId: types.uInt32('0'), titleId: types.uInt32('0'), service: types.bytes(16, ''), activityId: types.uInt32('0'), }, channelStartResponse: { channelRequestId: types.uInt32('0'), channelTargetId: types.uInt64(8, ''), result: types.uInt32('0'), }, acknowledge: { lowWatermark: types.uInt32('0'), processedList: types.sgList('processedList', []), rejectedList: types.sgList('rejectedList', []), }, processedList: { id: types.uInt32('0'), }, rejectedList: { id: types.uInt32('0'), }, consoleStatus: { liveTvProvider: types.uInt32('0'), majorVersion: types.uInt32('0'), minorVersion: types.uInt32('0'), buildNumber: types.uInt32('0'), locale: types.sgString('en-US'), activeTitles: types.sgArray('activeTitle') }, activeTitle: { flags: types.bytes(2), titleId: types.uInt32('0'), productId: types.bytes(16, ''), sandboxId: types.bytes(16, ''), aumId: types.sgString('') }, recordGameDvr: { startTimeDelta: types.sInt32('0'), endTimeDelta: types.sInt32('0'), }, gamepad: { timestamp: types.uInt64(8, ''), buttons: types.uInt16('0'), leftTrigger: types.uInt32('0'), rightTrigger: types.uInt32('0'), leftThumbstickX: types.uInt32('0'), leftThumbstickY: types.uInt32('0'), rightThumbstickX: types.uInt32('0'), rightThumbstickY: types.uInt32('0'), }, mediaState: { titleId: types.uInt32('0'), aumId: types.sgString(), assetId: types.sgString(), mediaType: types.mapper(LocalApi.Media.Types, types.uInt16('0')), soundLevel: types.mapper(LocalApi.Media.SoundLevel, types.uInt16('0')), enabledCommands: types.uInt32('0'), playbackStatus: types.mapper(LocalApi.Media.PlaybackState, types.uInt16('0')), rate: types.uInt32('0'), position: types.uInt64(8, ''), mediaStart: types.uInt64(8, ''), mediaEnd: types.uInt64(8, ''), minSeek: types.uInt64(8, ''), maxSeek: types.uInt64(8, ''), metadata: types.sgArray('mediaStateList', []), }, mediaStateList: { name: types.sgString(), value: types.sgString(), }, mediaCommand: { requestId: types.uInt64(8, ''), titleId: types.uInt32('0'), command: types.uInt32('0'), }, powerOff: { liveId: types.sgString(''), }, disconnect: { reason: types.uInt32('1'), errorCode: types.uInt32('0') } }; return packets; }; }; export default Packets;