From d1e99aa6c5db81231b4273b5e1118739da0e24bc Mon Sep 17 00:00:00 2001 From: Julian Waller Date: Mon, 7 Oct 2019 19:50:28 +0100 Subject: [PATCH 01/68] wip: enable strict tsconfig --- config/tsconfig.strict.json | 26 +-- src/__tests__/index.spec.ts | 7 - src/atem.ts | 155 ++++++--------- src/commands/AbstractCommand.ts | 53 +++++- src/commands/Audio/AudioMixerInputCommand.ts | 34 +++- src/commands/Audio/AudioMixerMasterCommand.ts | 24 ++- src/commands/AuxSourceCommand.ts | 36 +++- .../DataTransfer/DataTransferAckCommand.ts | 16 +- .../DataTransferCompleteCommand.ts | 16 +- .../DataTransfer/DataTransferDataCommand.ts | 20 +- .../DataTransferDownloadRequestCommand.ts | 2 +- .../DataTransfer/DataTransferErrorCommand.ts | 18 +- .../DataTransferFileDescriptionCommand.ts | 2 +- .../DataTransferUploadContinueCommand.ts | 16 +- .../DataTransferUploadRequestCommand.ts | 2 +- .../DataTransfer/LockObtainedCommand.ts | 16 +- src/commands/DataTransfer/LockStateCommand.ts | 26 ++- .../DeviceProfile/productIdentifierCommand.ts | 16 +- .../DeviceProfile/superSourceConfigCommand.ts | 16 +- src/commands/DeviceProfile/topologyCommand.ts | 16 +- src/commands/DeviceProfile/versionCommand.ts | 16 +- .../DownstreamKey/DownstreamKeyAutoCommand.ts | 2 +- .../DownstreamKeyCutSourceCommand.ts | 2 +- .../DownstreamKeyFillSourceCommand.ts | 2 +- .../DownstreamKeyGeneralCommand.ts | 2 +- .../DownstreamKey/DownstreamKeyMaskCommand.ts | 2 +- .../DownstreamKeyOnAirCommand.ts | 2 +- .../DownstreamKeyPropertiesCommand.ts | 22 ++- .../DownstreamKey/DownstreamKeyRateCommand.ts | 2 +- .../DownstreamKeySourcesCommand.ts | 22 ++- .../DownstreamKeyStateCommand.ts | 48 +++-- .../DownstreamKey/DownstreamKeyTieCommand.ts | 2 +- src/commands/InitCompleteCommand.ts | 9 +- src/commands/Inputs/InputPropertiesCommand.ts | 36 +++- src/commands/Macro/MacroActionCommand.ts | 2 +- src/commands/Macro/MacroPropertiesCommand.ts | 27 ++- .../Macro/MacroRecordingStatusCommand.ts | 19 +- src/commands/Macro/MacroRunStatusCommand.ts | 19 +- .../Media/MediaPlayerSourceCommand.ts | 40 ++-- .../Media/MediaPlayerStatusCommand.ts | 35 +++- .../Media/MediaPoolClearClipCommand.ts | 2 +- .../Media/MediaPoolClearStillCommand.ts | 2 +- .../Media/MediaPoolClipDescription.ts | 21 +- .../Media/MediaPoolFrameDescription.ts | 26 ++- src/commands/Media/MediaPoolSetClipCommand.ts | 2 +- .../MixEffects/AutoTransitionCommand.ts | 2 +- src/commands/MixEffects/CutCommand.ts | 2 +- .../FadeToBlack/FadeToBlackAutoCommand.ts | 2 +- .../FadeToBlack/FadeToBlackRateCommand.ts | 34 +++- .../FadeToBlack/FadeToBlackStateCommand.ts | 21 +- .../Key/MixEffectKeyChromaCommand.ts | 53 ++++-- .../Key/MixEffectKeyCutSourceSetCommand.ts | 2 +- .../MixEffects/Key/MixEffectKeyDVECommand.ts | 95 ++++++---- .../Key/MixEffectKeyFillSourceSetCommand.ts | 2 +- .../Key/MixEffectKeyFlyKeyframeGetCommand.ts | 32 +++- .../MixEffectKeyFlyPropertiesGetCommand.ts | 26 ++- .../MixEffects/Key/MixEffectKeyLumaCommand.ts | 49 +++-- .../Key/MixEffectKeyMaskSetCommand.ts | 2 +- .../Key/MixEffectKeyOnAirCommand.ts | 43 +++-- .../Key/MixEffectKeyPatternCommand.ts | 58 ++++-- .../Key/MixEffectKeyPropertiesGetCommand.ts | 30 ++- .../Key/MixEffectKeyTypeSetCommand.ts | 2 +- .../MixEffects/PreviewInputCommand.ts | 43 +++-- .../MixEffects/ProgramInputCommand.ts | 44 +++-- .../Transition/TransitionDVECommand.ts | 50 +++-- .../Transition/TransitionDipCommand.ts | 39 ++-- .../Transition/TransitionMixCommand.ts | 38 ++-- .../Transition/TransitionPositionCommand.ts | 47 +++-- .../Transition/TransitionPreviewCommand.ts | 41 ++-- .../Transition/TransitionPropertiesCommand.ts | 40 ++-- .../Transition/TransitionStingerCommand.ts | 50 +++-- .../Transition/TransitionWipeCommand.ts | 52 +++-- src/commands/PowerStatusCommand.ts | 16 +- .../Settings/MultiViewerSourceCommand.ts | 48 +++-- src/commands/Settings/VideoMode.ts | 36 ++-- .../SuperSourceBoxParametersCommand.ts | 62 +++--- .../SuperSourcePropertiesCommand.ts | 179 ++++++++++-------- src/commands/__tests__/data-v7.2.json | 20 +- src/commands/__tests__/util.ts | 18 +- src/dataTransfer/dataLock.ts | 15 +- src/dataTransfer/dataTransfer.ts | 33 +++- src/dataTransfer/dataTransferAudio.ts | 10 +- src/dataTransfer/dataTransferClip.ts | 13 +- src/dataTransfer/dataTransferFrame.ts | 30 ++- src/dataTransfer/dataTransferStill.ts | 12 +- src/dataTransfer/index.ts | 48 +---- src/enums/index.ts | 3 +- src/lib/atemCommandParser.ts | 16 +- src/lib/atemSocket.ts | 8 +- src/lib/atemSocketChild.ts | 4 +- src/state/info.ts | 5 - src/state/macro.ts | 13 ++ src/state/media.ts | 6 +- src/state/settings.ts | 6 +- src/state/video/index.ts | 109 +++++++---- 95 files changed, 1575 insertions(+), 915 deletions(-) diff --git a/config/tsconfig.strict.json b/config/tsconfig.strict.json index 7d976bd40..1b9ab37b3 100644 --- a/config/tsconfig.strict.json +++ b/config/tsconfig.strict.json @@ -1,12 +1,16 @@ { - "compilerOptions": { - "strictNullChecks": true, - "forceConsistentCasingInFileNames": true, - "noFallthroughCasesInSwitch": true, - "noImplicitAny" : true, - "noImplicitReturns": true, - "noImplicitThis": true, - "noUnusedLocals": true, - "noUnusedParameters": true - } -} + "compilerOptions": { + "strict": true, + "alwaysStrict": false, + "strictNullChecks": true, + "strictPropertyInitialization": false, + "strictFunctionTypes": true, + "forceConsistentCasingInFileNames": true, + "noFallthroughCasesInSwitch": true, + "noImplicitAny": true, + "noImplicitReturns": true, + "noImplicitThis": true, + "noUnusedLocals": true, + "noUnusedParameters": true + } +} \ No newline at end of file diff --git a/src/__tests__/index.spec.ts b/src/__tests__/index.spec.ts index fc714db05..7153f628b 100644 --- a/src/__tests__/index.spec.ts +++ b/src/__tests__/index.spec.ts @@ -1,5 +1,4 @@ import { Atem, Enums } from '../index' -import { ProtocolVersion } from '../enums' function cleanupAtem (atem: Atem) { const atem2 = atem as any @@ -41,7 +40,6 @@ test('setSuperSourceProperties - 7.2', async () => { }, 2) expect(conn.sendCommand).toHaveBeenCalledTimes(1) expect(conn.sendCommand).toHaveBeenNthCalledWith(1, { - rawName: 'CSSc', flag: 12, properties: { artOption: 0, @@ -64,8 +62,6 @@ test('setSuperSourceProperties - 8.0', async () => { }, 2) expect(conn.sendCommand).toHaveBeenCalledTimes(1) expect(conn.sendCommand).toHaveBeenNthCalledWith(1, { - rawName: 'CSSc', - minimumVersion: ProtocolVersion.V8_0, ssrcId: 2, flag: 12, properties: { @@ -89,7 +85,6 @@ test('setSuperSourceBorder - 7.2', async () => { }, 2) expect(conn.sendCommand).toHaveBeenCalledTimes(1) expect(conn.sendCommand).toHaveBeenNthCalledWith(1, { - rawName: 'CSSc', flag: 139264, properties: { borderBevelSoftness: 12, @@ -112,8 +107,6 @@ test('setSuperSourceBorder - 8.0', async () => { }, 2) expect(conn.sendCommand).toHaveBeenCalledTimes(1) expect(conn.sendCommand).toHaveBeenNthCalledWith(1, { - rawName: 'CSBd', - minimumVersion: ProtocolVersion.V8_0, ssrcId: 2, flag: 1088, properties: { diff --git a/src/atem.ts b/src/atem.ts index d6d3b0c47..8d2715f95 100644 --- a/src/atem.ts +++ b/src/atem.ts @@ -4,7 +4,7 @@ import { AtemSocket } from './lib/atemSocket' import AbstractCommand from './commands/AbstractCommand' import * as Commands from './commands' import * as DataTransferCommands from './commands/DataTransfer' -import { MediaPlayer } from './state/media' +import { MediaPlayer, MediaPlayerSource } from './state/media' import { MultiViewerSourceState } from './state/settings' import { DipTransitionSettings, @@ -110,105 +110,89 @@ export class Atem extends EventEmitter { }) } - changeProgramInput (input: number, me = 0) { - const command = new Commands.ProgramInputCommand() - command.mixEffect = me - command.updateProps({ source: input }) + changeProgramInput (input: number, me: number = 0) { + const command = new Commands.ProgramInputCommand(me, input) return this.sendCommand(command) } - changePreviewInput (input: number, me = 0) { - const command = new Commands.PreviewInputCommand() - command.mixEffect = me - command.updateProps({ source: input }) + changePreviewInput (input: number, me: number = 0) { + const command = new Commands.PreviewInputCommand(me, input) return this.sendCommand(command) } - cut (me = 0) { + cut (me: number = 0) { const command = new Commands.CutCommand() command.mixEffect = me return this.sendCommand(command) } - autoTransition (me = 0) { + autoTransition (me: number = 0) { const command = new Commands.AutoTransitionCommand() command.mixEffect = me return this.sendCommand(command) } - fadeToBlack (me = 0) { + fadeToBlack (me: number = 0) { const command = new Commands.FadeToBlackAutoCommand() command.mixEffect = me return this.sendCommand(command) } - autoDownstreamKey (key = 0, isTowardsOnAir?: boolean) { + autoDownstreamKey (key: number = 0, isTowardsOnAir?: boolean) { const command = new Commands.DownstreamKeyAutoCommand() command.downstreamKeyerId = key command.updateProps({ isTowardsOnAir }) return this.sendCommand(command) } - setDipTransitionSettings (newProps: Partial, me = 0) { - const command = new Commands.TransitionDipCommand() - command.mixEffect = me + setDipTransitionSettings (newProps: Partial, me: number = 0) { + const command = new Commands.TransitionDipCommand(me) command.updateProps(newProps) return this.sendCommand(command) } - setDVETransitionSettings (newProps: Partial, me = 1) { - const command = new Commands.TransitionDVECommand() - command.mixEffect = me + setDVETransitionSettings (newProps: Partial, me: number = 0) { + const command = new Commands.TransitionDVECommand(me) command.updateProps(newProps) return this.sendCommand(command) } - setMixTransitionSettings (newProps: Partial, me = 0) { - const command = new Commands.TransitionMixCommand() - command.mixEffect = me + setMixTransitionSettings (newProps: Partial, me: number = 0) { + const command = new Commands.TransitionMixCommand(me) command.updateProps(newProps) return this.sendCommand(command) } - setTransitionPosition (position: number, me = 0) { - const command = new Commands.TransitionPositionCommand() - command.mixEffect = me - command.updateProps({ handlePosition: position }) + setTransitionPosition (position: number, me: number = 0) { + const command = new Commands.TransitionPositionCommand(me, position) return this.sendCommand(command) } - previewTransition (on: boolean, me = 0) { - const command = new Commands.PreviewTransitionCommand() - command.mixEffect = me - command.updateProps({ preview: on }) + previewTransition (on: boolean, me: number = 0) { + const command = new Commands.PreviewTransitionCommand(me, on) return this.sendCommand(command) } - setTransitionStyle (newProps: Partial, me = 0) { - const command = new Commands.TransitionPropertiesCommand() - command.mixEffect = me + setTransitionStyle (newProps: Partial, me: number = 0) { + const command = new Commands.TransitionPropertiesCommand(me) command.updateProps(newProps) return this.sendCommand(command) } - setStingerTransitionSettings (newProps: Partial, me = 0) { - const command = new Commands.TransitionStingerCommand() - command.mixEffect = me + setStingerTransitionSettings (newProps: Partial, me: number = 0) { + const command = new Commands.TransitionStingerCommand(me) command.updateProps(newProps) return this.sendCommand(command) } - setWipeTransitionSettings (newProps: Partial, me = 0) { - const command = new Commands.TransitionWipeCommand() - command.mixEffect = me + setWipeTransitionSettings (newProps: Partial, me: number = 0) { + const command = new Commands.TransitionWipeCommand(me) command.updateProps(newProps) return this.sendCommand(command) } - setAuxSource (source: number, bus = 0) { - const command = new Commands.AuxSourceCommand() - command.auxBus = bus - command.updateProps({ source }) + setAuxSource (source: number, bus: number = 0) { + const command = new Commands.AuxSourceCommand(bus, source) return this.sendCommand(command) } @@ -304,22 +288,19 @@ export class Atem extends EventEmitter { } setMultiViewerSource (newProps: Partial, mv = 0) { - const command = new Commands.MultiViewerSourceCommand() - command.multiViewerId = mv + const command = new Commands.MultiViewerSourceCommand(mv) command.updateProps(newProps) return this.sendCommand(command) } - setMediaPlayerSettings (newProps: Partial, player = 0) { - const command = new Commands.MediaPlayerStatusCommand() - command.mediaPlayerId = player + setMediaPlayerSettings (newProps: Partial, player: number = 0) { + const command = new Commands.MediaPlayerStatusCommand(player) command.updateProps(newProps) return this.sendCommand(command) } - setMediaPlayerSource (newProps: Partial<{ sourceType: Enums.MediaSourceType, stillIndex: number, clipIndex: number }>, player = 0) { - const command = new Commands.MediaPlayerSourceCommand() - command.mediaPlayerId = player + setMediaPlayerSource (newProps: Partial, player: number = 0) { + const command = new Commands.MediaPlayerSourceCommand(player) command.updateProps(newProps) return this.sendCommand(command) } @@ -342,18 +323,15 @@ export class Atem extends EventEmitter { return this.sendCommand(command) } - setSuperSourceBoxSettings (newProps: Partial, box = 0, ssrcId = 0) { - const command = new Commands.SuperSourceBoxParametersCommand() - command.ssrcId = ssrcId - command.boxId = box + setSuperSourceBoxSettings (newProps: Partial, box: number = 0, ssrcId: number = 0) { + const command = new Commands.SuperSourceBoxParametersCommand(ssrcId, box) command.updateProps(newProps) return this.sendCommand(command) } - setSuperSourceProperties (newProps: Partial, ssrcId = 0) { + setSuperSourceProperties (newProps: Partial, ssrcId: number = 0) { if (this.state.info.apiVersion >= Enums.ProtocolVersion.V8_0) { - const command = new Commands.SuperSourcePropertiesV8Command() - command.ssrcId = ssrcId + const command = new Commands.SuperSourcePropertiesV8Command(ssrcId) command.updateProps(newProps) return this.sendCommand(command) } else { @@ -363,10 +341,9 @@ export class Atem extends EventEmitter { } } - setSuperSourceBorder (newProps: Partial, ssrcId = 0) { + setSuperSourceBorder (newProps: Partial, ssrcId: number = 0) { if (this.state.info.apiVersion >= Enums.ProtocolVersion.V8_0) { - const command = new Commands.SuperSourceBorderCommand() - command.ssrcId = ssrcId + const command = new Commands.SuperSourceBorderCommand(ssrcId) command.updateProps(newProps) return this.sendCommand(command) } else { @@ -376,22 +353,19 @@ export class Atem extends EventEmitter { } } - setInputSettings (newProps: Partial, input = 0) { - const command = new Commands.InputPropertiesCommand() - command.inputId = input + setInputSettings (newProps: Partial, input: number = 0) { + const command = new Commands.InputPropertiesCommand(input) command.updateProps(newProps) return this.sendCommand(command) } - setUpstreamKeyerChromaSettings (newProps: Partial, me = 0, keyer = 0) { - const command = new Commands.MixEffectKeyChromaCommand() - command.mixEffect = me - command.upstreamKeyerId = keyer + setUpstreamKeyerChromaSettings (newProps: Partial, me: number = 0, keyer: number = 0) { + const command = new Commands.MixEffectKeyChromaCommand(me, keyer) command.updateProps(newProps) return this.sendCommand(command) } - setUpstreamKeyerCutSource (cutSource: number, me = 0, keyer = 0) { + setUpstreamKeyerCutSource (cutSource: number, me: number = 0, keyer: number = 0) { const command = new Commands.MixEffectKeyCutSourceSetCommand() command.mixEffect = me command.upstreamKeyerId = keyer @@ -399,7 +373,7 @@ export class Atem extends EventEmitter { return this.sendCommand(command) } - setUpstreamKeyerFillSource (fillSource: number, me = 0, keyer = 0) { + setUpstreamKeyerFillSource (fillSource: number, me: number = 0, keyer: number = 0) { const command = new Commands.MixEffectKeyFillSourceSetCommand() command.mixEffect = me command.upstreamKeyerId = keyer @@ -407,23 +381,19 @@ export class Atem extends EventEmitter { return this.sendCommand(command) } - setUpstreamKeyerDVESettings (newProps: Partial, me = 0, keyer = 0) { - const command = new Commands.MixEffectKeyDVECommand() - command.mixEffect = me - command.upstreamKeyerId = keyer + setUpstreamKeyerDVESettings (newProps: Partial, me: number = 0, keyer: number = 0) { + const command = new Commands.MixEffectKeyDVECommand(me, keyer) command.updateProps(newProps) return this.sendCommand(command) } - setUpstreamKeyerLumaSettings (newProps: Partial, me = 0, keyer = 0) { - const command = new Commands.MixEffectKeyLumaCommand() - command.mixEffect = me - command.upstreamKeyerId = keyer + setUpstreamKeyerLumaSettings (newProps: Partial, me: number = 0, keyer: number = 0) { + const command = new Commands.MixEffectKeyLumaCommand(me, keyer) command.updateProps(newProps) return this.sendCommand(command) } - setUpstreamKeyerMaskSettings (newProps: Partial, me = 0, keyer = 0) { + setUpstreamKeyerMaskSettings (newProps: Partial, me: number = 0, keyer: number = 0) { const command = new Commands.MixEffectKeyMaskSetCommand() command.mixEffect = me command.upstreamKeyerId = keyer @@ -431,23 +401,18 @@ export class Atem extends EventEmitter { return this.sendCommand(command) } - setUpstreamKeyerPatternSettings (newProps: Partial, me = 0, keyer = 0) { - const command = new Commands.MixEffectKeyPatternCommand() - command.mixEffect = me - command.upstreamKeyerId = keyer + setUpstreamKeyerPatternSettings (newProps: Partial, me: number = 0, keyer: number = 0) { + const command = new Commands.MixEffectKeyPatternCommand(me, keyer) command.updateProps(newProps) return this.sendCommand(command) } - setUpstreamKeyerOnAir (onAir: boolean, me = 0, keyer = 0) { - const command = new Commands.MixEffectKeyOnAirCommand() - command.mixEffect = me - command.upstreamKeyerId = keyer - command.updateProps({ onAir }) + setUpstreamKeyerOnAir (onAir: boolean, me: number = 0, keyer: number = 0) { + const command = new Commands.MixEffectKeyOnAirCommand(me, keyer, onAir) return this.sendCommand(command) } - setUpstreamKeyerType (newProps: Partial, me = 0, keyer = 0) { + setUpstreamKeyerType (newProps: Partial, me: number = 0, keyer: number = 0) { const command = new Commands.MixEffectKeyTypeSetCommand() command.mixEffect = me command.upstreamKeyerId = keyer @@ -487,29 +452,25 @@ export class Atem extends EventEmitter { } setAudioMixerInputMixOption (index: number, mixOption: Enums.AudioMixOption) { - const command = new Commands.AudioMixerInputCommand() - command.index = index + const command = new Commands.AudioMixerInputCommand(index) command.updateProps({ mixOption }) return this.sendCommand(command) } setAudioMixerInputGain (index: number, gain: number) { - const command = new Commands.AudioMixerInputCommand() - command.index = index + const command = new Commands.AudioMixerInputCommand(index) command.updateProps({ gain }) return this.sendCommand(command) } setAudioMixerInputBalance (index: number, balance: number) { - const command = new Commands.AudioMixerInputCommand() - command.index = index + const command = new Commands.AudioMixerInputCommand(index) command.updateProps({ balance }) return this.sendCommand(command) } setAudioMixerInputProps (index: number, props: Partial) { - const command = new Commands.AudioMixerInputCommand() - command.index = index + const command = new Commands.AudioMixerInputCommand(index) command.updateProps(props) return this.sendCommand(command) } diff --git a/src/commands/AbstractCommand.ts b/src/commands/AbstractCommand.ts index 74a0da6f2..271940ec3 100644 --- a/src/commands/AbstractCommand.ts +++ b/src/commands/AbstractCommand.ts @@ -1,19 +1,24 @@ import { AtemState } from '../state' import { ProtocolVersion } from '../enums' + export default abstract class AbstractCommand { - static MaskFlags?: { [key: string]: number } - abstract rawName: string + static readonly MaskFlags?: { [key: string]: number } + static readonly minimumVersion?: ProtocolVersion + + // static abstract rawName: string + + // abstract rawName: string packetId: number flag: number = 0 - minimumVersion?: ProtocolVersion + // minimumVersion?: ProtocolVersion resolve: (cmd: AbstractCommand) => void reject: (cmd: AbstractCommand) => void abstract properties: any - deserialize? (rawCommand: Buffer, version: ProtocolVersion): void + // deserialize? (rawCommand: Buffer, version: ProtocolVersion): void serialize? (version: ProtocolVersion): Buffer applyToState? (state: AtemState): string | string[] @@ -38,3 +43,43 @@ export default abstract class AbstractCommand { } } } + +export abstract class BasicWritableCommand extends AbstractCommand { + properties: T + + public serialize? (version: ProtocolVersion): Buffer +} + +export abstract class WritableCommand extends BasicWritableCommand> { + static readonly MaskFlags?: { [key: string]: number } + + flag: number + + constructor () { + super() + + this.flag = 0 + this.properties = {} + } + + public updateProps (newProps: Partial) { + this._updateProps(newProps) + } + + protected _updateProps (newProps: Object) { + this.properties = { + ...this.properties, + ...newProps + } + const maskFlags = (this.constructor as any).MaskFlags as { [key: string]: number } + + if (maskFlags) { + for (const key in newProps) { + if (key in maskFlags) { + this.flag = this.flag | maskFlags[key] + } + } + } + } + +} diff --git a/src/commands/Audio/AudioMixerInputCommand.ts b/src/commands/Audio/AudioMixerInputCommand.ts index 309055c25..f2c02a444 100644 --- a/src/commands/Audio/AudioMixerInputCommand.ts +++ b/src/commands/Audio/AudioMixerInputCommand.ts @@ -9,11 +9,17 @@ export class AudioMixerInputCommand extends AbstractCommand { gain: 1 << 1, balance: 1 << 2 } - rawName = 'CAMI' - mixEffect: number + static readonly rawName = 'CAMI' + readonly index: number properties: Partial - index: number + + constructor (index: number) { + super() + + this.index = index + this.properties = {} + } serialize () { const buffer = Buffer.alloc(12) @@ -27,21 +33,29 @@ export class AudioMixerInputCommand extends AbstractCommand { } export class AudioMixerInputUpdateCommand extends AbstractCommand { - rawName = 'AMIP' - mixEffect: number + static readonly rawName = 'AMIP' - properties: Partial - index: number + readonly index: number + readonly properties: Readonly - deserialize (rawCommand: Buffer) { - this.index = rawCommand.readUInt16BE(0) - this.properties = { + constructor (index: number, properties: AudioChannel) { + super() + + this.index = index + this.properties = properties + } + + static deserialize (rawCommand: Buffer): AudioMixerInputUpdateCommand { + const index = rawCommand.readUInt16BE(0) + const properties = { sourceType: rawCommand.readUInt8(2), portType: rawCommand.readUInt8(7), mixOption: rawCommand.readUInt8(8), gain: Util.UInt16BEToDecibel(rawCommand.readUInt16BE(10)), balance: Util.IntToBalance(rawCommand.readInt16BE(12)) } + + return new AudioMixerInputUpdateCommand(index, properties) } applyToState (state: AtemState) { diff --git a/src/commands/Audio/AudioMixerMasterCommand.ts b/src/commands/Audio/AudioMixerMasterCommand.ts index 43989f97c..595fc071c 100644 --- a/src/commands/Audio/AudioMixerMasterCommand.ts +++ b/src/commands/Audio/AudioMixerMasterCommand.ts @@ -9,10 +9,16 @@ export class AudioMixerMasterCommand extends AbstractCommand { balance: 1 << 1, followFadeToBlack: 1 << 2 } - rawName = 'CAMM' + static readonly rawName = 'CAMM' properties: Partial + constructor () { + super() + + this.properties = {} + } + serialize () { const buffer = Buffer.alloc(8) buffer.writeUInt8(this.flag, 0) @@ -24,16 +30,24 @@ export class AudioMixerMasterCommand extends AbstractCommand { } export class AudioMixerMasterUpdateCommand extends AbstractCommand { - rawName = 'AMMO' + static readonly rawName = 'AMMO' - properties: Partial + readonly properties: Readonly - deserialize (rawCommand: Buffer) { - this.properties = { + constructor (properties: AudioMasterChannel) { + super() + + this.properties = properties + } + + static deserialize (rawCommand: Buffer): AudioMixerMasterUpdateCommand { + const properties = { gain: Util.UInt16BEToDecibel(rawCommand.readUInt16BE(0)), balance: Util.IntToBalance(rawCommand.readInt16BE(2)), followFadeToBlack: rawCommand.readInt8(4) === 1 } + + return new AudioMixerMasterUpdateCommand(properties) } applyToState (state: AtemState) { diff --git a/src/commands/AuxSourceCommand.ts b/src/commands/AuxSourceCommand.ts index 3ffab76d5..b523aa0de 100644 --- a/src/commands/AuxSourceCommand.ts +++ b/src/commands/AuxSourceCommand.ts @@ -2,11 +2,19 @@ import AbstractCommand from './AbstractCommand' import { AtemState } from '../state' export class AuxSourceCommand extends AbstractCommand { - rawName = 'CAuS' - auxBus: number + static readonly rawName = 'CAuS' - properties: { + readonly auxBus: number + + readonly properties: Readonly<{ source: number + }> + + constructor (auxBus: number, source: number) { + super() + + this.auxBus = auxBus + this.properties = { source } } serialize () { @@ -19,18 +27,28 @@ export class AuxSourceCommand extends AbstractCommand { } export class AuxSourceUpdateCommand extends AbstractCommand { - rawName = 'AuxS' - auxBus: number + static readonly rawName = 'AuxS' + + readonly auxBus: number - properties: { + readonly properties: Readonly<{ source: number + }> + + constructor (auxBus: number, properties: AuxSourceUpdateCommand['properties']) { + super() + + this.auxBus = auxBus + this.properties = properties } - deserialize (rawCommand: Buffer) { - this.auxBus = rawCommand[0] - this.properties = { + static deserialize (rawCommand: Buffer): AuxSourceUpdateCommand { + const auxBus = rawCommand[0] + const properties = { source: rawCommand.readUInt16BE(2) } + + return new AuxSourceUpdateCommand(auxBus, properties) } applyToState (state: AtemState) { diff --git a/src/commands/DataTransfer/DataTransferAckCommand.ts b/src/commands/DataTransfer/DataTransferAckCommand.ts index 78c396934..853164a1f 100644 --- a/src/commands/DataTransfer/DataTransferAckCommand.ts +++ b/src/commands/DataTransfer/DataTransferAckCommand.ts @@ -1,17 +1,25 @@ import AbstractCommand from '../AbstractCommand' export class DataTransferAckCommand extends AbstractCommand { - rawName = 'FTUA' + static readonly rawName = 'FTUA' - properties: { + readonly properties: Readonly<{ transferId: number, transferIndex: number + }> + + constructor (properties: DataTransferAckCommand['properties']) { + super() + + this.properties = properties } - deserialize (rawCommand: Buffer) { - this.properties = { + static deserialize (rawCommand: Buffer): DataTransferAckCommand { + const properties = { transferId: rawCommand.readUInt16BE(0), transferIndex: rawCommand.readUInt8(2) } + + return new DataTransferAckCommand(properties) } } diff --git a/src/commands/DataTransfer/DataTransferCompleteCommand.ts b/src/commands/DataTransfer/DataTransferCompleteCommand.ts index 632ca6e23..23525305a 100644 --- a/src/commands/DataTransfer/DataTransferCompleteCommand.ts +++ b/src/commands/DataTransfer/DataTransferCompleteCommand.ts @@ -1,15 +1,23 @@ import AbstractCommand from '../AbstractCommand' export class DataTransferCompleteCommand extends AbstractCommand { - rawName = 'FTDC' + static readonly rawName = 'FTDC' - properties: { + readonly properties: Readonly<{ transferId: number + }> + + constructor (properties: DataTransferCompleteCommand['properties']) { + super() + + this.properties = properties } - deserialize (rawCommand: Buffer) { - this.properties = { + static deserialize (rawCommand: Buffer): DataTransferCompleteCommand { + const properties = { transferId: rawCommand.readUInt16BE(0) } + + return new DataTransferCompleteCommand(properties) } } diff --git a/src/commands/DataTransfer/DataTransferDataCommand.ts b/src/commands/DataTransfer/DataTransferDataCommand.ts index 479631352..0c34041ae 100644 --- a/src/commands/DataTransfer/DataTransferDataCommand.ts +++ b/src/commands/DataTransfer/DataTransferDataCommand.ts @@ -1,28 +1,34 @@ import AbstractCommand from '../AbstractCommand' export class DataTransferDataCommand extends AbstractCommand { - rawName = 'FTDa' + static readonly rawName = 'FTDa' - properties: { + readonly properties: Readonly<{ transferId: number, - size: number, body: Buffer + }> + + constructor (properties: DataTransferDataCommand['properties']) { + super() + + this.properties = properties } serialize () { - this.properties.size = this.properties.body.length const buffer = Buffer.alloc(4) buffer.writeUInt16BE(this.properties.transferId, 0) - buffer.writeUInt16BE(this.properties.size, 2) + buffer.writeUInt16BE(this.properties.body.length, 2) return Buffer.concat([ buffer, this.properties.body ]) } - deserialize (rawCommand: Buffer) { - this.properties = { + static deserialize (rawCommand: Buffer): DataTransferDataCommand { + const properties = { transferId: rawCommand.readUInt16BE(0), size: rawCommand.readUInt16BE(2), body: rawCommand.slice(4, 4 + rawCommand.readUInt16BE(2)) } + + return new DataTransferDataCommand(properties) } } diff --git a/src/commands/DataTransfer/DataTransferDownloadRequestCommand.ts b/src/commands/DataTransfer/DataTransferDownloadRequestCommand.ts index 81dd5eae4..6ec6f4a16 100644 --- a/src/commands/DataTransfer/DataTransferDownloadRequestCommand.ts +++ b/src/commands/DataTransfer/DataTransferDownloadRequestCommand.ts @@ -1,7 +1,7 @@ import AbstractCommand from '../AbstractCommand' export class DataTransferDownloadRequestCommand extends AbstractCommand { - rawName = 'FTSU' + static readonly rawName = 'FTSU' properties: { transferId: number, diff --git a/src/commands/DataTransfer/DataTransferErrorCommand.ts b/src/commands/DataTransfer/DataTransferErrorCommand.ts index 80ceb6c9c..b04151ccf 100644 --- a/src/commands/DataTransfer/DataTransferErrorCommand.ts +++ b/src/commands/DataTransfer/DataTransferErrorCommand.ts @@ -1,17 +1,25 @@ import AbstractCommand from '../AbstractCommand' export class DataTransferErrorCommand extends AbstractCommand { - rawName = 'FTDE' + static readonly rawName = 'FTDE' - properties: { - transferId: number, + readonly properties: Readonly<{ + transferId: number errorCode: number + }> + + constructor (properties: DataTransferErrorCommand['properties']) { + super() + + this.properties = properties } - deserialize (rawCommand: Buffer) { - this.properties = { + static deserialize (rawCommand: Buffer): DataTransferErrorCommand { + const properties = { transferId: rawCommand.readUInt16BE(0), errorCode: rawCommand.readUInt8(2) } + + return new DataTransferErrorCommand(properties) } } diff --git a/src/commands/DataTransfer/DataTransferFileDescriptionCommand.ts b/src/commands/DataTransfer/DataTransferFileDescriptionCommand.ts index 3ed118506..6e16508ad 100644 --- a/src/commands/DataTransfer/DataTransferFileDescriptionCommand.ts +++ b/src/commands/DataTransfer/DataTransferFileDescriptionCommand.ts @@ -1,7 +1,7 @@ import AbstractCommand from '../AbstractCommand' export class DataTransferFileDescriptionCommand extends AbstractCommand { - rawName = 'FTFD' + static readonly rawName = 'FTFD' properties: { transferId: number, diff --git a/src/commands/DataTransfer/DataTransferUploadContinueCommand.ts b/src/commands/DataTransfer/DataTransferUploadContinueCommand.ts index 237f72980..b10b91248 100644 --- a/src/commands/DataTransfer/DataTransferUploadContinueCommand.ts +++ b/src/commands/DataTransfer/DataTransferUploadContinueCommand.ts @@ -1,19 +1,27 @@ import AbstractCommand from '../AbstractCommand' export class DataTransferUploadContinueCommand extends AbstractCommand { - rawName = 'FTCD' + static readonly rawName = 'FTCD' - properties: { + readonly properties: Readonly<{ transferId: number, chunkSize: number, chunkCount: number + }> + + constructor (properties: DataTransferUploadContinueCommand['properties']) { + super() + + this.properties = properties } - deserialize (rawCommand: Buffer) { - this.properties = { + static deserialize (rawCommand: Buffer) { + const properties = { transferId: rawCommand.readUInt16BE(0), chunkSize: rawCommand.readUInt16BE(6), chunkCount: rawCommand.readUInt16BE(8) } + + return new DataTransferUploadContinueCommand(properties) } } diff --git a/src/commands/DataTransfer/DataTransferUploadRequestCommand.ts b/src/commands/DataTransfer/DataTransferUploadRequestCommand.ts index e51986e64..342061f7d 100644 --- a/src/commands/DataTransfer/DataTransferUploadRequestCommand.ts +++ b/src/commands/DataTransfer/DataTransferUploadRequestCommand.ts @@ -2,7 +2,7 @@ import AbstractCommand from '../AbstractCommand' import { Enums } from '../..' export class DataTransferUploadRequestCommand extends AbstractCommand { - rawName = 'FTSD' + static readonly rawName = 'FTSD' properties: { transferId: number, diff --git a/src/commands/DataTransfer/LockObtainedCommand.ts b/src/commands/DataTransfer/LockObtainedCommand.ts index 39f599d0d..6612b6619 100644 --- a/src/commands/DataTransfer/LockObtainedCommand.ts +++ b/src/commands/DataTransfer/LockObtainedCommand.ts @@ -1,15 +1,23 @@ import AbstractCommand from '../AbstractCommand' export class LockObtainedCommand extends AbstractCommand { - rawName = 'LKOB' + static readonly rawName = 'LKOB' - properties: { + readonly properties: Readonly<{ index: number + }> + + constructor (properties: LockObtainedCommand['properties']) { + super() + + this.properties = properties } - deserialize (rawCommand: Buffer) { - this.properties = { + static deserialize (rawCommand: Buffer) { + const properties = { index: rawCommand.readUInt16BE(0) } + + return new LockObtainedCommand(properties) } } diff --git a/src/commands/DataTransfer/LockStateCommand.ts b/src/commands/DataTransfer/LockStateCommand.ts index a259af2fe..94d4e4d5e 100644 --- a/src/commands/DataTransfer/LockStateCommand.ts +++ b/src/commands/DataTransfer/LockStateCommand.ts @@ -1,11 +1,17 @@ import AbstractCommand from '../AbstractCommand' export class LockStateCommand extends AbstractCommand { - rawName = 'LOCK' + static readonly rawName = 'LOCK' - properties: { + readonly properties: Readonly<{ index: number, locked: boolean + }> + + constructor (index: number, locked: boolean) { + super() + + this.properties = { index, locked } } serialize () { @@ -17,17 +23,25 @@ export class LockStateCommand extends AbstractCommand { } export class LockStateUpdateCommand extends AbstractCommand { - rawName = 'LKST' + static readonly rawName = 'LKST' - properties: { + readonly properties: Readonly<{ index: number, locked: boolean + }> + + constructor (properties: LockStateUpdateCommand['properties']) { + super() + + this.properties = properties } - deserialize (rawCommand: Buffer) { - this.properties = { + static deserialize (rawCommand: Buffer) { + const properties = { index: rawCommand.readUInt16BE(0), locked: rawCommand[2] === 1 } + + return new LockStateUpdateCommand(properties) } } diff --git a/src/commands/DeviceProfile/productIdentifierCommand.ts b/src/commands/DeviceProfile/productIdentifierCommand.ts index e7ba51fe6..42b323930 100644 --- a/src/commands/DeviceProfile/productIdentifierCommand.ts +++ b/src/commands/DeviceProfile/productIdentifierCommand.ts @@ -4,18 +4,26 @@ import { Util } from '../../lib/atemUtil' import { Enums } from '../..' export class ProductIdentifierCommand extends AbstractCommand { - rawName = '_pin' + static readonly rawName = '_pin' - properties: { + readonly properties: Readonly<{ deviceName: string model: number + }> + + constructor (properties: ProductIdentifierCommand['properties']) { + super() + + this.properties = properties } - deserialize (rawCommand: Buffer) { - this.properties = { + static deserialize (rawCommand: Buffer) { + const properties = { deviceName: Util.bufToNullTerminatedString(rawCommand, 0, 40), model: Util.parseEnum(rawCommand[40], Enums.Model) } + + return new ProductIdentifierCommand(properties) } applyToState (state: AtemState) { diff --git a/src/commands/DeviceProfile/superSourceConfigCommand.ts b/src/commands/DeviceProfile/superSourceConfigCommand.ts index 31f34330d..fad02e19f 100644 --- a/src/commands/DeviceProfile/superSourceConfigCommand.ts +++ b/src/commands/DeviceProfile/superSourceConfigCommand.ts @@ -3,16 +3,24 @@ import { AtemState } from '../../state' import { Util } from '../..' export class SuperSourceConfigCommand extends AbstractCommand { - rawName = '_SSC' + static readonly rawName = '_SSC' - properties: { + readonly properties: Readonly<{ superSourceBoxes: number + }> + + constructor (properties: SuperSourceConfigCommand['properties']) { + super() + + this.properties = properties } - deserialize (rawCommand: Buffer) { - this.properties = { + static deserialize (rawCommand: Buffer) { + const properties = { superSourceBoxes: Util.parseNumberBetween(rawCommand[0], 0, 4) } + + return new SuperSourceConfigCommand(properties) } applyToState (state: AtemState) { diff --git a/src/commands/DeviceProfile/topologyCommand.ts b/src/commands/DeviceProfile/topologyCommand.ts index 362ba9ab1..da7d6835d 100644 --- a/src/commands/DeviceProfile/topologyCommand.ts +++ b/src/commands/DeviceProfile/topologyCommand.ts @@ -3,12 +3,18 @@ import { AtemState } from '../../state' import { AtemCapabilites } from '../../state/info' export class TopologyCommand extends AbstractCommand { - rawName = '_top' + static readonly rawName = '_top' - properties: AtemCapabilites + readonly properties: Readonly - deserialize (rawCommand: Buffer) { - this.properties = { + constructor (properties: AtemCapabilites) { + super() + + this.properties = properties + } + + static deserialize (rawCommand: Buffer) { + const properties = { MEs: rawCommand[0], sources: rawCommand[1], colorGenerators: rawCommand[2], @@ -23,6 +29,8 @@ export class TopologyCommand extends AbstractCommand { superSources: rawCommand[10], talkbackOverSDI: rawCommand[13] } + + return new TopologyCommand(properties) } applyToState (state: AtemState) { diff --git a/src/commands/DeviceProfile/versionCommand.ts b/src/commands/DeviceProfile/versionCommand.ts index 10ca63f6c..48db307ac 100644 --- a/src/commands/DeviceProfile/versionCommand.ts +++ b/src/commands/DeviceProfile/versionCommand.ts @@ -3,16 +3,24 @@ import { AtemState } from '../../state' import { ProtocolVersion } from '../../enums' export class VersionCommand extends AbstractCommand { - rawName = '_ver' + static readonly rawName = '_ver' - properties: { + readonly properties: Readonly<{ version: ProtocolVersion + }> + + constructor (properties: VersionCommand['properties']) { + super() + + this.properties = properties } - deserialize (rawCommand: Buffer) { - this.properties = { + static deserialize (rawCommand: Buffer) { + const properties = { version: rawCommand.readUInt32BE(0) } + + return new VersionCommand(properties) } applyToState (state: AtemState) { diff --git a/src/commands/DownstreamKey/DownstreamKeyAutoCommand.ts b/src/commands/DownstreamKey/DownstreamKeyAutoCommand.ts index f75a3be57..c2d763e17 100644 --- a/src/commands/DownstreamKey/DownstreamKeyAutoCommand.ts +++ b/src/commands/DownstreamKey/DownstreamKeyAutoCommand.ts @@ -2,7 +2,7 @@ import AbstractCommand from '../AbstractCommand' import { ProtocolVersion } from '../../enums' export class DownstreamKeyAutoCommand extends AbstractCommand { - rawName = 'DDsA' + static readonly rawName = 'DDsA' downstreamKeyerId: number MaskFlags = { diff --git a/src/commands/DownstreamKey/DownstreamKeyCutSourceCommand.ts b/src/commands/DownstreamKey/DownstreamKeyCutSourceCommand.ts index 833cca9b9..c4ab0c2f8 100644 --- a/src/commands/DownstreamKey/DownstreamKeyCutSourceCommand.ts +++ b/src/commands/DownstreamKey/DownstreamKeyCutSourceCommand.ts @@ -1,7 +1,7 @@ import AbstractCommand from '../AbstractCommand' export class DownstreamKeyCutSourceCommand extends AbstractCommand { - rawName = 'CDsC' + static readonly rawName = 'CDsC' downstreamKeyerId: number properties: { input: number diff --git a/src/commands/DownstreamKey/DownstreamKeyFillSourceCommand.ts b/src/commands/DownstreamKey/DownstreamKeyFillSourceCommand.ts index d9a338355..e13f56ec4 100644 --- a/src/commands/DownstreamKey/DownstreamKeyFillSourceCommand.ts +++ b/src/commands/DownstreamKey/DownstreamKeyFillSourceCommand.ts @@ -1,7 +1,7 @@ import AbstractCommand from '../AbstractCommand' export class DownstreamKeyFillSourceCommand extends AbstractCommand { - rawName = 'CDsF' + static readonly rawName = 'CDsF' downstreamKeyerId: number properties: { input: number diff --git a/src/commands/DownstreamKey/DownstreamKeyGeneralCommand.ts b/src/commands/DownstreamKey/DownstreamKeyGeneralCommand.ts index 6139be234..cfc0ce0b7 100644 --- a/src/commands/DownstreamKey/DownstreamKeyGeneralCommand.ts +++ b/src/commands/DownstreamKey/DownstreamKeyGeneralCommand.ts @@ -9,7 +9,7 @@ export class DownstreamKeyGeneralCommand extends AbstractCommand { invert: 1 << 3 } - rawName = 'CDsG' + static readonly rawName = 'CDsG' downstreamKeyerId: number properties: DownstreamKeyerGeneral diff --git a/src/commands/DownstreamKey/DownstreamKeyMaskCommand.ts b/src/commands/DownstreamKey/DownstreamKeyMaskCommand.ts index 3b51b2a0b..77a651911 100644 --- a/src/commands/DownstreamKey/DownstreamKeyMaskCommand.ts +++ b/src/commands/DownstreamKey/DownstreamKeyMaskCommand.ts @@ -10,7 +10,7 @@ export class DownstreamKeyMaskCommand extends AbstractCommand { right: 1 << 4 } - rawName = 'CDsM' + static readonly rawName = 'CDsM' downstreamKeyerId: number properties: DownstreamKeyerMask diff --git a/src/commands/DownstreamKey/DownstreamKeyOnAirCommand.ts b/src/commands/DownstreamKey/DownstreamKeyOnAirCommand.ts index 29ad695a7..e885e725c 100644 --- a/src/commands/DownstreamKey/DownstreamKeyOnAirCommand.ts +++ b/src/commands/DownstreamKey/DownstreamKeyOnAirCommand.ts @@ -1,7 +1,7 @@ import AbstractCommand from '../AbstractCommand' export class DownstreamKeyOnAirCommand extends AbstractCommand { - rawName = 'CDsL' + static readonly rawName = 'CDsL' downstreamKeyerId: number properties: { diff --git a/src/commands/DownstreamKey/DownstreamKeyPropertiesCommand.ts b/src/commands/DownstreamKey/DownstreamKeyPropertiesCommand.ts index 2735a2e2b..dbd8953a2 100644 --- a/src/commands/DownstreamKey/DownstreamKeyPropertiesCommand.ts +++ b/src/commands/DownstreamKey/DownstreamKeyPropertiesCommand.ts @@ -4,13 +4,21 @@ import { DownstreamKeyerProperties } from '../../state/video/downstreamKeyers' import { Util } from '../..' export class DownstreamKeyPropertiesCommand extends AbstractCommand { - rawName = 'DskP' - downstreamKeyerId: number - properties: DownstreamKeyerProperties + static readonly rawName = 'DskP' - deserialize (rawCommand: Buffer) { - this.downstreamKeyerId = rawCommand[0] - this.properties = { + readonly downstreamKeyerId: number + readonly properties: Readonly + + constructor (downstreamKeyerId: number, properties: DownstreamKeyerProperties) { + super() + + this.downstreamKeyerId = downstreamKeyerId + this.properties = properties + } + + static deserialize (rawCommand: Buffer) { + const downstreamKeyerId = rawCommand[0] + const properties = { tie: rawCommand[1] === 1, rate: Util.parseNumberBetween(rawCommand[2], 0, 300), @@ -27,6 +35,8 @@ export class DownstreamKeyPropertiesCommand extends AbstractCommand { right: Util.parseNumberBetween(rawCommand.readInt16BE(16), -16000, 16000) } } + + return new DownstreamKeyPropertiesCommand(downstreamKeyerId, properties) } applyToState (state: AtemState) { diff --git a/src/commands/DownstreamKey/DownstreamKeyRateCommand.ts b/src/commands/DownstreamKey/DownstreamKeyRateCommand.ts index fc9ba9ce4..dcee2553b 100644 --- a/src/commands/DownstreamKey/DownstreamKeyRateCommand.ts +++ b/src/commands/DownstreamKey/DownstreamKeyRateCommand.ts @@ -1,7 +1,7 @@ import AbstractCommand from '../AbstractCommand' export class DownstreamKeyRateCommand extends AbstractCommand { - rawName = 'CDsR' + static readonly rawName = 'CDsR' downstreamKeyerId: number properties: { rate: number diff --git a/src/commands/DownstreamKey/DownstreamKeySourcesCommand.ts b/src/commands/DownstreamKey/DownstreamKeySourcesCommand.ts index 00b047496..4dc4c0811 100644 --- a/src/commands/DownstreamKey/DownstreamKeySourcesCommand.ts +++ b/src/commands/DownstreamKey/DownstreamKeySourcesCommand.ts @@ -3,19 +3,29 @@ import { AtemState } from '../../state' import { Util } from '../..' export class DownstreamKeySourcesCommand extends AbstractCommand { - rawName = 'DskB' - downstreamKeyerId: number - properties: { + static readonly rawName = 'DskB' + + readonly downstreamKeyerId: number + readonly properties: Readonly<{ fillSource: number, cutSource: number + }> + + constructor (downstreamKeyerId: number, properties: DownstreamKeySourcesCommand['properties']) { + super() + + this.downstreamKeyerId = downstreamKeyerId + this.properties = properties } - deserialize (rawCommand: Buffer) { - this.downstreamKeyerId = Util.parseNumberBetween(rawCommand[0], 0, 3), - this.properties = { + static deserialize (rawCommand: Buffer) { + const downstreamKeyerId = Util.parseNumberBetween(rawCommand[0], 0, 3) + const properties = { fillSource: rawCommand.readUInt16BE(2), cutSource: rawCommand.readUInt16BE(4) } + + return new DownstreamKeySourcesCommand(downstreamKeyerId, properties) } applyToState (state: AtemState) { diff --git a/src/commands/DownstreamKey/DownstreamKeyStateCommand.ts b/src/commands/DownstreamKey/DownstreamKeyStateCommand.ts index 57f505b8a..57ffaaa59 100644 --- a/src/commands/DownstreamKey/DownstreamKeyStateCommand.ts +++ b/src/commands/DownstreamKey/DownstreamKeyStateCommand.ts @@ -5,24 +5,33 @@ import { Util } from '../..' import { ProtocolVersion } from '../../enums' export class DownstreamKeyStateCommand extends AbstractCommand { - rawName = 'DskS' - downstreamKeyerId: number + static readonly rawName = 'DskS' - properties: DownstreamKeyerBase + readonly downstreamKeyerId: number + readonly properties: Readonly - deserialize (rawCommand: Buffer) { - this.downstreamKeyerId = Util.parseNumberBetween(rawCommand[0], 0, 3) - this.properties = { + constructor (downstreamKeyerId: number, properties: DownstreamKeyerBase) { + super() + + this.downstreamKeyerId = downstreamKeyerId + this.properties = properties + } + + static deserialize (rawCommand: Buffer) { + const downstreamKeyerId = Util.parseNumberBetween(rawCommand[0], 0, 3) + const properties = { onAir: rawCommand[1] === 1, inTransition: rawCommand[2] === 1, isAuto: rawCommand[3] === 1, remainingFrames: rawCommand[4] } + + return new DownstreamKeyStateCommand(downstreamKeyerId, properties) } applyToState (state: AtemState) { state.video.downstreamKeyers[this.downstreamKeyerId] = { - ...state.video.downstreamKeyers[this.downstreamKeyerId], + ...state.video.getDownstreamKeyer(this.downstreamKeyerId), ...this.properties } return `video.downstreamKeyers.${this.downstreamKeyerId}` @@ -30,26 +39,35 @@ export class DownstreamKeyStateCommand extends AbstractCommand { } export class DownstreamKeyStateV8Command extends AbstractCommand { - rawName = 'DskS' - downstreamKeyerId: number - minimumVersion = ProtocolVersion.V8_0_1 + static readonly rawName = 'DskS' + static readonly minimumVersion = ProtocolVersion.V8_0_1 - properties: DownstreamKeyerBase + readonly downstreamKeyerId: number + readonly properties: Readonly - deserialize (rawCommand: Buffer) { - this.downstreamKeyerId = Util.parseNumberBetween(rawCommand[0], 0, 3) - this.properties = { + constructor (downstreamKeyerId: number, properties: DownstreamKeyerBase) { + super() + + this.downstreamKeyerId = downstreamKeyerId + this.properties = properties + } + + static deserialize (rawCommand: Buffer) { + const downstreamKeyerId = Util.parseNumberBetween(rawCommand[0], 0, 3) + const properties = { onAir: rawCommand[1] === 1, inTransition: rawCommand[2] === 1, isAuto: rawCommand[3] === 1, isTowardsOnAir: rawCommand[4] === 1, remainingFrames: rawCommand[5] } + + return new DownstreamKeyStateV8Command(downstreamKeyerId, properties) } applyToState (state: AtemState) { state.video.downstreamKeyers[this.downstreamKeyerId] = { - ...state.video.downstreamKeyers[this.downstreamKeyerId], + ...state.video.getDownstreamKeyer(this.downstreamKeyerId), ...this.properties } return `video.downstreamKeyers.${this.downstreamKeyerId}` diff --git a/src/commands/DownstreamKey/DownstreamKeyTieCommand.ts b/src/commands/DownstreamKey/DownstreamKeyTieCommand.ts index 15d5ee4cc..c81ed5d58 100644 --- a/src/commands/DownstreamKey/DownstreamKeyTieCommand.ts +++ b/src/commands/DownstreamKey/DownstreamKeyTieCommand.ts @@ -1,7 +1,7 @@ import AbstractCommand from '../AbstractCommand' export class DownstreamKeyTieCommand extends AbstractCommand { - rawName = 'CDsT' + static readonly rawName = 'CDsT' downstreamKeyerId: number properties: { diff --git a/src/commands/InitCompleteCommand.ts b/src/commands/InitCompleteCommand.ts index d99295d4e..83dac0cd5 100644 --- a/src/commands/InitCompleteCommand.ts +++ b/src/commands/InitCompleteCommand.ts @@ -1,15 +1,14 @@ import AbstractCommand from './AbstractCommand' export class InitCompleteCommand extends AbstractCommand { - rawName = 'InCm' - properties: null + static readonly rawName = 'InCm' + readonly properties: null = null - deserialize () { - // + static deserialize () { + return new InitCompleteCommand() } applyToState () { - // return `info` } } diff --git a/src/commands/Inputs/InputPropertiesCommand.ts b/src/commands/Inputs/InputPropertiesCommand.ts index 7cadee33e..04a895554 100644 --- a/src/commands/Inputs/InputPropertiesCommand.ts +++ b/src/commands/Inputs/InputPropertiesCommand.ts @@ -11,10 +11,17 @@ export class InputPropertiesCommand extends AbstractCommand { isExternal: 1 << 2 } - rawName = 'CInL' - inputId: number + static readonly rawName = 'CInL' - properties: InputChannel + readonly inputId: number + properties: Partial + + constructor (inputId: number) { + super() + + this.inputId = inputId + this.properties = {} + } updateProps (newProps: Partial) { this._updateProps(newProps) @@ -26,19 +33,26 @@ export class InputPropertiesCommand extends AbstractCommand { buffer.writeUInt16BE(this.inputId, 2) buffer.write(this.properties.longName || '', 4) buffer.write(this.properties.shortName || '', 24) - buffer.writeUInt16BE(this.properties.externalPortType, 28) + buffer.writeUInt16BE(this.properties.externalPortType || 0, 28) return buffer } } export class InputPropertiesUpdateCommand extends AbstractCommand { - rawName = 'InPr' - inputId: number + static readonly rawName = 'InPr' - properties: InputChannel + readonly inputId: number + readonly properties: Readonly - deserialize (rawCommand: Buffer) { - this.inputId = rawCommand.readUInt16BE(0) + constructor (inputId: number, properties: InputChannel) { + super() + + this.inputId = inputId + this.properties = properties + } + + static deserialize (rawCommand: Buffer) { + const inputId = rawCommand.readUInt16BE(0) const externalPortsMask = rawCommand[29] const externalPorts: ExternalPortType[] = [] @@ -58,7 +72,7 @@ export class InputPropertiesUpdateCommand extends AbstractCommand { externalPorts.push(ExternalPortType.SVideo) } - this.properties = { + const properties = { inputId: rawCommand.readUInt16BE(0), longName: Util.bufToNullTerminatedString(rawCommand, 2, 20), shortName: Util.bufToNullTerminatedString(rawCommand, 22, 4), @@ -69,6 +83,8 @@ export class InputPropertiesUpdateCommand extends AbstractCommand { sourceAvailability: rawCommand.readUInt8(34), meAvailability: rawCommand.readUInt8(35) } + + return new InputPropertiesUpdateCommand(inputId, properties) } applyToState (state: AtemState) { diff --git a/src/commands/Macro/MacroActionCommand.ts b/src/commands/Macro/MacroActionCommand.ts index fa8f2aff7..58cdcd5ab 100644 --- a/src/commands/Macro/MacroActionCommand.ts +++ b/src/commands/Macro/MacroActionCommand.ts @@ -2,7 +2,7 @@ import AbstractCommand from '../AbstractCommand' import { MacroAction } from '../../enums' export class MacroActionCommand extends AbstractCommand { - rawName = 'MAct' + static readonly rawName = 'MAct' index: number properties: { diff --git a/src/commands/Macro/MacroPropertiesCommand.ts b/src/commands/Macro/MacroPropertiesCommand.ts index 3b50985ce..3c4f49389 100644 --- a/src/commands/Macro/MacroPropertiesCommand.ts +++ b/src/commands/Macro/MacroPropertiesCommand.ts @@ -4,30 +4,39 @@ import { MacroPropertiesState } from '../../state/macro' import { Util } from '../../lib/atemUtil' export class MacroPropertiesCommand extends AbstractCommand { - rawName = 'MPrp' + static readonly rawName = 'MPrp' - macroIndexID: number - properties: MacroPropertiesState + readonly macroIndexID: number + readonly properties: MacroPropertiesState - deserialize (rawCommand: Buffer) { - this.macroIndexID = rawCommand.readUInt16BE(0) + constructor (macroIndexID: number, properties: MacroPropertiesState) { + super() + + this.macroIndexID = macroIndexID + this.properties = properties + } + + static deserialize (rawCommand: Buffer): MacroPropertiesCommand { + const macroIndexID = rawCommand.readUInt16BE(0) const nameLen = rawCommand.readUInt16BE(4) const descLen = rawCommand.readUInt16BE(6) - this.properties = { + const properties = { description: '', isUsed: Boolean(rawCommand[2] & 1 << 0), - macroIndex: this.macroIndexID, + macroIndex: macroIndexID, name: '' } if (descLen > 0) { - this.properties.description = Util.bufToNullTerminatedString(rawCommand, (8 + nameLen), descLen) + properties.description = Util.bufToNullTerminatedString(rawCommand, (8 + nameLen), descLen) } if (nameLen > 0) { - this.properties.name = Util.bufToNullTerminatedString(rawCommand, 8, nameLen) + properties.name = Util.bufToNullTerminatedString(rawCommand, 8, nameLen) } + + return new MacroPropertiesCommand(macroIndexID, properties) } applyToState (state: AtemState) { diff --git a/src/commands/Macro/MacroRecordingStatusCommand.ts b/src/commands/Macro/MacroRecordingStatusCommand.ts index bf9bd4998..3b4a1f99a 100644 --- a/src/commands/Macro/MacroRecordingStatusCommand.ts +++ b/src/commands/Macro/MacroRecordingStatusCommand.ts @@ -3,18 +3,23 @@ import { AtemState } from '../../state' import { MacroRecorderState } from '../../state/macro' export class MacroRecordingStatusCommand extends AbstractCommand { - rawName = 'MRcS' + static readonly rawName = 'MRcS' - macroIndexID: number - properties: MacroRecorderState + readonly properties: Readonly - deserialize (rawCommand: Buffer) { - this.macroIndexID = rawCommand.readUInt16BE(2) + constructor (properties: MacroRecorderState) { + super() - this.properties = { + this.properties = properties + } + + static deserialize (rawCommand: Buffer) { + const properties = { isRecording: Boolean(rawCommand[0] & 1 << 0), - macroIndex: this.macroIndexID + macroIndex: rawCommand.readUInt16BE(2) } + + return new MacroRecordingStatusCommand(properties) } applyToState (state: AtemState) { diff --git a/src/commands/Macro/MacroRunStatusCommand.ts b/src/commands/Macro/MacroRunStatusCommand.ts index 522e61cda..f2d4779e3 100644 --- a/src/commands/Macro/MacroRunStatusCommand.ts +++ b/src/commands/Macro/MacroRunStatusCommand.ts @@ -3,20 +3,25 @@ import { AtemState } from '../../state' import { MacroPlayerState } from '../../state/macro' export class MacroRunStatusCommand extends AbstractCommand { - rawName = 'MRPr' + static readonly rawName = 'MRPr' - macroIndexID: number - properties: MacroPlayerState + readonly properties: Readonly - deserialize (rawCommand: Buffer) { - this.macroIndexID = rawCommand.readUInt16BE(2) + constructor (properties: MacroPlayerState) { + super() - this.properties = { + this.properties = properties + } + + static deserialize (rawCommand: Buffer) { + const properties = { isRunning: Boolean(rawCommand[0] & 1 << 0), isWaiting: Boolean(rawCommand[0] & 1 << 1), loop: Boolean(rawCommand[1] & 1 << 0), - macroIndex: this.macroIndexID + macroIndex: rawCommand.readUInt16BE(2) } + + return new MacroRunStatusCommand(properties) } applyToState (state: AtemState) { diff --git a/src/commands/Media/MediaPlayerSourceCommand.ts b/src/commands/Media/MediaPlayerSourceCommand.ts index d67160356..ed9674bfe 100644 --- a/src/commands/Media/MediaPlayerSourceCommand.ts +++ b/src/commands/Media/MediaPlayerSourceCommand.ts @@ -9,10 +9,17 @@ export class MediaPlayerSourceCommand extends AbstractCommand { clipIndex: 1 << 2 } - rawName = 'MPSS' - mediaPlayerId: number + static readonly rawName = 'MPSS' - properties: MediaPlayerSource + readonly mediaPlayerId: number + properties: Partial + + constructor (mediaPlayerId: number) { + super() + + this.mediaPlayerId = mediaPlayerId + this.properties = {} + } updateProps (newProps: Partial) { this._updateProps(newProps) @@ -22,26 +29,35 @@ export class MediaPlayerSourceCommand extends AbstractCommand { const buffer = Buffer.alloc(8) buffer.writeUInt8(this.flag, 0) buffer.writeUInt8(this.mediaPlayerId, 1) - buffer.writeUInt8(this.properties.sourceType, 2) - buffer.writeUInt8(this.properties.clipIndex, 3) - buffer.writeUInt8(this.properties.stillIndex, 4) + buffer.writeUInt8(this.properties.sourceType || 0, 2) + buffer.writeUInt8(this.properties.stillIndex || 0, 3) + buffer.writeUInt8(this.properties.clipIndex || 0, 4) return buffer } } export class MediaPlayerSourceUpdateCommand extends AbstractCommand { - rawName = 'MPCE' - mediaPlayerId: number + static readonly rawName = 'MPCE' + + readonly mediaPlayerId: number + readonly properties: Readonly - properties: MediaPlayerSource + constructor (mediaPlayerId: number, properties: MediaPlayerSource) { + super() - deserialize (rawCommand: Buffer) { - this.mediaPlayerId = rawCommand[0] - this.properties = { + this.mediaPlayerId = mediaPlayerId + this.properties = properties + } + + static deserialize (rawCommand: Buffer) { + const mediaPlayerId = rawCommand[0] + const properties = { sourceType: rawCommand[1], clipIndex: rawCommand[2], stillIndex: rawCommand[3] } + + return new MediaPlayerSourceUpdateCommand(mediaPlayerId, properties) } applyToState (state: AtemState) { diff --git a/src/commands/Media/MediaPlayerStatusCommand.ts b/src/commands/Media/MediaPlayerStatusCommand.ts index e4aff4e51..1028ba0d1 100644 --- a/src/commands/Media/MediaPlayerStatusCommand.ts +++ b/src/commands/Media/MediaPlayerStatusCommand.ts @@ -10,11 +10,17 @@ export class MediaPlayerStatusCommand extends AbstractCommand { atBeginning: 1 << 2, frame: 1 << 3 } + static readonly rawName = 'SCPS' - rawName = 'SCPS' - mediaPlayerId: number + readonly mediaPlayerId: number + properties: Partial - properties: MediaPlayer + constructor (mediaPlayerId: number) { + super() + + this.mediaPlayerId = mediaPlayerId + this.properties = {} + } updateProps (newProps: Partial) { this._updateProps(newProps) @@ -27,25 +33,34 @@ export class MediaPlayerStatusCommand extends AbstractCommand { buffer.writeUInt8(this.properties.playing ? 1 : 0, 2) buffer.writeUInt8(this.properties.loop ? 1 : 0, 3) buffer.writeUInt8(this.properties.atBeginning ? 1 : 0, 4) - buffer.writeUInt16BE(this.properties.clipFrame, 6) + buffer.writeUInt16BE(this.properties.clipFrame || 0, 6) return buffer } } export class MediaPlayerStatusUpdateCommand extends AbstractCommand { - rawName = 'RCPS' - mediaPlayerId: number + static readonly rawName = 'RCPS' + + readonly mediaPlayerId: number + readonly properties: Readonly - properties: MediaPlayer + constructor (mediaPlayerId: number, properties: MediaPlayer) { + super() - deserialize (rawCommand: Buffer) { - this.mediaPlayerId = Util.parseNumberBetween(rawCommand[0], 0, 3) - this.properties = { + this.mediaPlayerId = mediaPlayerId + this.properties = properties + } + + static deserialize (rawCommand: Buffer) { + const mediaPlayerId = Util.parseNumberBetween(rawCommand[0], 0, 3) + const properties = { playing: rawCommand[1] === 1, loop: rawCommand[2] === 1, atBeginning: rawCommand[3] === 1, clipFrame: rawCommand[4] << 8 | (rawCommand[5]) } + + return new MediaPlayerStatusUpdateCommand(mediaPlayerId, properties) } applyToState (state: AtemState) { diff --git a/src/commands/Media/MediaPoolClearClipCommand.ts b/src/commands/Media/MediaPoolClearClipCommand.ts index ce6269aaa..aba397a47 100644 --- a/src/commands/Media/MediaPoolClearClipCommand.ts +++ b/src/commands/Media/MediaPoolClearClipCommand.ts @@ -1,7 +1,7 @@ import AbstractCommand from '../AbstractCommand' export class MediaPoolClearClipCommand extends AbstractCommand { - rawName = 'CMPC' + static readonly rawName = 'CMPC' properties: { index: number diff --git a/src/commands/Media/MediaPoolClearStillCommand.ts b/src/commands/Media/MediaPoolClearStillCommand.ts index 62301c261..9be2ec96e 100644 --- a/src/commands/Media/MediaPoolClearStillCommand.ts +++ b/src/commands/Media/MediaPoolClearStillCommand.ts @@ -1,7 +1,7 @@ import AbstractCommand from '../AbstractCommand' export class MediaPoolClearStillCommand extends AbstractCommand { - rawName = 'CSTL' + static readonly rawName = 'CSTL' properties: { index: number diff --git a/src/commands/Media/MediaPoolClipDescription.ts b/src/commands/Media/MediaPoolClipDescription.ts index ccc4d3cd9..f2929c83c 100644 --- a/src/commands/Media/MediaPoolClipDescription.ts +++ b/src/commands/Media/MediaPoolClipDescription.ts @@ -4,19 +4,28 @@ import AbstractCommand from '../AbstractCommand' import { Util } from '../../lib/atemUtil' export class MediaPoolClipDescriptionCommand extends AbstractCommand { - rawName = 'MPCS' + static readonly rawName = 'MPCS' - mediaPool: number - properties: ClipBank + readonly mediaPool: number + readonly properties: Readonly - deserialize (rawCommand: Buffer) { - this.mediaPool = rawCommand[0] - this.properties = { + constructor (mediaPool: number, properties: ClipBank) { + super() + + this.mediaPool = mediaPool + this.properties = properties + } + + static deserialize (rawCommand: Buffer) { + const mediaPool = rawCommand[0] + const properties = { isUsed: rawCommand[1] === 1, name: Util.bufToNullTerminatedString(rawCommand, 2, 64), frameCount: rawCommand.readUInt16BE(66), frames: [] } + + return new MediaPoolClipDescriptionCommand(mediaPool, properties) } applyToState (state: AtemState) { diff --git a/src/commands/Media/MediaPoolFrameDescription.ts b/src/commands/Media/MediaPoolFrameDescription.ts index 2f3ab0b57..4d9bbf35e 100644 --- a/src/commands/Media/MediaPoolFrameDescription.ts +++ b/src/commands/Media/MediaPoolFrameDescription.ts @@ -4,20 +4,30 @@ import AbstractCommand from '../AbstractCommand' import { Util } from '../../lib/atemUtil' export class MediaPoolFrameDescriptionCommand extends AbstractCommand { - rawName = 'MPfe' + static readonly rawName = 'MPfe' - mediaPool: number - frameIndex: number - properties: StillFrame + readonly mediaPool: number + readonly frameIndex: number + readonly properties: Readonly - deserialize (rawCommand: Buffer) { - this.mediaPool = rawCommand[0] - this.frameIndex = rawCommand.readUInt16BE(2) - this.properties = { + constructor (mediaPool: number, frameIndex: number,properties: StillFrame) { + super() + + this.mediaPool = mediaPool + this.frameIndex = frameIndex + this.properties = properties + } + + static deserialize (rawCommand: Buffer) { + const mediaPool = rawCommand[0] + const frameIndex = rawCommand.readUInt16BE(2) + const properties = { isUsed: rawCommand[4] === 1, hash: Util.bufToBase64String(rawCommand, 5, 16), fileName: Util.bufToNullTerminatedString(rawCommand, 24, rawCommand[23]) } + + return new MediaPoolFrameDescriptionCommand(mediaPool, frameIndex, properties) } applyToState (state: AtemState) { diff --git a/src/commands/Media/MediaPoolSetClipCommand.ts b/src/commands/Media/MediaPoolSetClipCommand.ts index 6ccc4b2e7..f7fae040e 100644 --- a/src/commands/Media/MediaPoolSetClipCommand.ts +++ b/src/commands/Media/MediaPoolSetClipCommand.ts @@ -1,7 +1,7 @@ import AbstractCommand from '../AbstractCommand' export class MediaPoolSetClipCommand extends AbstractCommand { - rawName = 'SMPC' + static readonly rawName = 'SMPC' properties: { index: number, diff --git a/src/commands/MixEffects/AutoTransitionCommand.ts b/src/commands/MixEffects/AutoTransitionCommand.ts index 4749c36f8..c4fb7878a 100644 --- a/src/commands/MixEffects/AutoTransitionCommand.ts +++ b/src/commands/MixEffects/AutoTransitionCommand.ts @@ -1,7 +1,7 @@ import AbstractCommand from '../AbstractCommand' export class AutoTransitionCommand extends AbstractCommand { - rawName = 'DAut' + static readonly rawName = 'DAut' mixEffect: number properties: null diff --git a/src/commands/MixEffects/CutCommand.ts b/src/commands/MixEffects/CutCommand.ts index 3675b073c..236a20d57 100644 --- a/src/commands/MixEffects/CutCommand.ts +++ b/src/commands/MixEffects/CutCommand.ts @@ -1,7 +1,7 @@ import AbstractCommand from '../AbstractCommand' export class CutCommand extends AbstractCommand { - rawName = 'DCut' + static readonly rawName = 'DCut' mixEffect: number properties: null diff --git a/src/commands/MixEffects/FadeToBlack/FadeToBlackAutoCommand.ts b/src/commands/MixEffects/FadeToBlack/FadeToBlackAutoCommand.ts index 1c7b88e6b..3dd41d3b9 100644 --- a/src/commands/MixEffects/FadeToBlack/FadeToBlackAutoCommand.ts +++ b/src/commands/MixEffects/FadeToBlack/FadeToBlackAutoCommand.ts @@ -1,7 +1,7 @@ import AbstractCommand from '../../AbstractCommand' export class FadeToBlackAutoCommand extends AbstractCommand { - rawName = 'FtbA' + static readonly rawName = 'FtbA' mixEffect: number properties: {} diff --git a/src/commands/MixEffects/FadeToBlack/FadeToBlackRateCommand.ts b/src/commands/MixEffects/FadeToBlack/FadeToBlackRateCommand.ts index 8378f857c..596b636e8 100644 --- a/src/commands/MixEffects/FadeToBlack/FadeToBlackRateCommand.ts +++ b/src/commands/MixEffects/FadeToBlack/FadeToBlackRateCommand.ts @@ -3,11 +3,18 @@ import { AtemState } from '../../../state' import { Util } from '../../..' export class FadeToBlackRateCommand extends AbstractCommand { - rawName = 'FtbC' - mixEffect: number + static readonly rawName = 'FtbC' - properties: { + readonly mixEffect: number + readonly properties: Readonly<{ rate: number + }> + + constructor (mixEffect: number, rate: number) { + super() + + this.mixEffect = mixEffect + this.properties = { rate } } serialize () { @@ -20,18 +27,27 @@ export class FadeToBlackRateCommand extends AbstractCommand { } export class FadeToBlackRateUpdateCommand extends AbstractCommand { - rawName = 'FtbP' - mixEffect: number + static readonly rawName = 'FtbP' - properties: { + readonly mixEffect: number + readonly properties: Readonly<{ rate: number + }> + + constructor (mixEffect: number, properties: FadeToBlackRateUpdateCommand['properties']) { + super() + + this.mixEffect = mixEffect + this.properties = properties } - deserialize (rawCommand: Buffer) { - this.mixEffect = Util.parseNumberBetween(rawCommand[0], 0, 3) - this.properties = { + static deserialize (rawCommand: Buffer) { + const mixEffect = Util.parseNumberBetween(rawCommand[0], 0, 3) + const properties = { rate: rawCommand.readUInt8(1) } + + return new FadeToBlackRateUpdateCommand(mixEffect, properties) } applyToState (state: AtemState) { diff --git a/src/commands/MixEffects/FadeToBlack/FadeToBlackStateCommand.ts b/src/commands/MixEffects/FadeToBlack/FadeToBlackStateCommand.ts index e30d53886..4a70f544f 100644 --- a/src/commands/MixEffects/FadeToBlack/FadeToBlackStateCommand.ts +++ b/src/commands/MixEffects/FadeToBlack/FadeToBlackStateCommand.ts @@ -3,22 +3,31 @@ import { AtemState } from '../../../state' import { Util } from '../../..' export class FadeToBlackStateCommand extends AbstractCommand { - rawName = 'FtbS' - mixEffect: number + static readonly rawName = 'FtbS' - properties: { + readonly mixEffect: number + readonly properties: Readonly<{ isFullyBlack: boolean inTransition: boolean remainingFrames: number + }> + + constructor (mixEffect: number, properties: FadeToBlackStateCommand['properties']) { + super() + + this.mixEffect = mixEffect + this.properties = properties } - deserialize (rawCommand: Buffer) { - this.mixEffect = Util.parseNumberBetween(rawCommand[0], 0, 3) - this.properties = { + static deserialize (rawCommand: Buffer) { + const mixEffect = Util.parseNumberBetween(rawCommand[0], 0, 3) + const properties = { isFullyBlack: rawCommand.readUInt8(1) === 1, inTransition: rawCommand.readUInt8(2) === 1, remainingFrames: Util.parseNumberBetween(rawCommand.readUInt8(3), 0, 250) } + + return new FadeToBlackStateCommand(mixEffect, properties) } applyToState (state: AtemState) { diff --git a/src/commands/MixEffects/Key/MixEffectKeyChromaCommand.ts b/src/commands/MixEffects/Key/MixEffectKeyChromaCommand.ts index 5e4e13e0d..320b4f237 100644 --- a/src/commands/MixEffects/Key/MixEffectKeyChromaCommand.ts +++ b/src/commands/MixEffects/Key/MixEffectKeyChromaCommand.ts @@ -11,11 +11,19 @@ export class MixEffectKeyChromaCommand extends AbstractCommand { lift: 1 << 3, narrow: 1 << 4 } + static readonly rawName = 'CKCk' - rawName = 'CKCk' - mixEffect: number - upstreamKeyerId: number - properties: UpstreamKeyerChromaSettings + readonly mixEffect: number + readonly upstreamKeyerId: number + properties: Partial + + constructor (mixEffect: number, upstreamKeyerId: number) { + super() + + this.mixEffect = mixEffect + this.upstreamKeyerId = upstreamKeyerId + this.properties = {} + } serialize () { const buffer = Buffer.alloc(16) @@ -23,10 +31,10 @@ export class MixEffectKeyChromaCommand extends AbstractCommand { buffer.writeUInt8(this.mixEffect, 1) buffer.writeUInt8(this.upstreamKeyerId, 2) - buffer.writeUInt16BE(this.properties.hue, 4) - buffer.writeUInt16BE(this.properties.gain, 6) - buffer.writeUInt16BE(this.properties.ySuppress, 8) - buffer.writeUInt16BE(this.properties.lift, 10) + buffer.writeUInt16BE(this.properties.hue || 0, 4) + buffer.writeUInt16BE(this.properties.gain || 0, 6) + buffer.writeUInt16BE(this.properties.ySuppress || 0, 8) + buffer.writeUInt16BE(this.properties.lift || 0, 10) buffer.writeUInt8(this.properties.narrow ? 1 : 0, 12) return buffer @@ -34,21 +42,32 @@ export class MixEffectKeyChromaCommand extends AbstractCommand { } export class MixEffectKeyChromaUpdateCommand extends AbstractCommand { - rawName = 'KeCk' - mixEffect: number - upstreamKeyerId: number - properties: UpstreamKeyerChromaSettings - - deserialize (rawCommand: Buffer) { - this.mixEffect = Util.parseNumberBetween(rawCommand[0], 0, 3) - this.upstreamKeyerId = Util.parseNumberBetween(rawCommand[1], 0, 3) - this.properties = { + static readonly rawName = 'KeCk' + + readonly mixEffect: number + readonly upstreamKeyerId: number + readonly properties: Readonly + + constructor (mixEffect: number, upstreamKeyerId: number, properties: UpstreamKeyerChromaSettings) { + super() + + this.mixEffect = mixEffect + this.upstreamKeyerId = upstreamKeyerId + this.properties = properties + } + + static deserialize (rawCommand: Buffer) { + const mixEffect = Util.parseNumberBetween(rawCommand[0], 0, 3) + const upstreamKeyerId = Util.parseNumberBetween(rawCommand[1], 0, 3) + const properties = { hue: Util.parseNumberBetween(rawCommand.readUInt16BE(2), 0, 3599), gain: Util.parseNumberBetween(rawCommand.readUInt16BE(4), 0, 1000), ySuppress: Util.parseNumberBetween(rawCommand.readUInt16BE(6), 0, 1000), lift: Util.parseNumberBetween(rawCommand.readUInt16BE(8), 0, 1000), narrow: rawCommand[10] === 1 } + + return new MixEffectKeyChromaUpdateCommand(mixEffect, upstreamKeyerId, properties) } applyToState (state: AtemState) { diff --git a/src/commands/MixEffects/Key/MixEffectKeyCutSourceSetCommand.ts b/src/commands/MixEffects/Key/MixEffectKeyCutSourceSetCommand.ts index 85d338e0b..4f8c1bcfe 100644 --- a/src/commands/MixEffects/Key/MixEffectKeyCutSourceSetCommand.ts +++ b/src/commands/MixEffects/Key/MixEffectKeyCutSourceSetCommand.ts @@ -1,7 +1,7 @@ import AbstractCommand from '../../AbstractCommand' export class MixEffectKeyCutSourceSetCommand extends AbstractCommand { - rawName = 'CKeC' + static readonly rawName = 'CKeC' mixEffect: number upstreamKeyerId: number properties: { diff --git a/src/commands/MixEffects/Key/MixEffectKeyDVECommand.ts b/src/commands/MixEffects/Key/MixEffectKeyDVECommand.ts index 4da20db1e..52566b848 100644 --- a/src/commands/MixEffects/Key/MixEffectKeyDVECommand.ts +++ b/src/commands/MixEffects/Key/MixEffectKeyDVECommand.ts @@ -32,11 +32,19 @@ export class MixEffectKeyDVECommand extends AbstractCommand { maskRight: 1 << 24, rate: 1 << 25 } + static readonly rawName = 'CKDV' - rawName = 'CKDV' - mixEffect: number - upstreamKeyerId: number - properties: UpstreamKeyerDVESettings + readonly mixEffect: number + readonly upstreamKeyerId: number + properties: Partial + + constructor (mixEffect: number, upstreamKeyerId: number) { + super() + + this.mixEffect = mixEffect + this.upstreamKeyerId = upstreamKeyerId + this.properties = {} + } serialize () { const buffer = Buffer.alloc(64) @@ -44,52 +52,61 @@ export class MixEffectKeyDVECommand extends AbstractCommand { buffer.writeUInt8(this.mixEffect, 4) buffer.writeUInt8(this.upstreamKeyerId, 5) - buffer.writeUInt32BE(this.properties.sizeX, 8) - buffer.writeUInt32BE(this.properties.sizeY, 12) - buffer.writeInt32BE(this.properties.positionX, 16) - buffer.writeInt32BE(this.properties.positionY, 20) - buffer.writeInt32BE(this.properties.rotation, 24) + buffer.writeUInt32BE(this.properties.sizeX || 0, 8) + buffer.writeUInt32BE(this.properties.sizeY || 0, 12) + buffer.writeInt32BE(this.properties.positionX || 0, 16) + buffer.writeInt32BE(this.properties.positionY || 0, 20) + buffer.writeInt32BE(this.properties.rotation || 0, 24) buffer[28] = this.properties.borderEnabled ? 1 : 0 buffer[29] = this.properties.shadowEnabled ? 1 : 0 - buffer.writeUInt8(this.properties.borderBevel, 30) - buffer.writeUInt16BE(this.properties.borderOuterWidth, 32) - buffer.writeUInt16BE(this.properties.borderInnerWidth, 34) - buffer.writeUInt8(this.properties.borderOuterSoftness, 36) - buffer.writeUInt8(this.properties.borderInnerSoftness, 37) - buffer.writeUInt8(this.properties.borderBevelSoftness, 38) - buffer.writeUInt8(this.properties.borderBevelPosition, 39) - buffer.writeUInt8(this.properties.borderOpacity, 40) - - buffer.writeUInt16BE(this.properties.borderHue, 42) - buffer.writeUInt16BE(this.properties.borderSaturation, 44) - buffer.writeUInt16BE(this.properties.borderLuma, 46) - - buffer.writeUInt16BE(this.properties.lightSourceDirection, 48) - buffer.writeUInt8(this.properties.lightSourceAltitude, 50) + buffer.writeUInt8(this.properties.borderBevel || 0, 30) + buffer.writeUInt16BE(this.properties.borderOuterWidth || 0, 32) + buffer.writeUInt16BE(this.properties.borderInnerWidth || 0, 34) + buffer.writeUInt8(this.properties.borderOuterSoftness || 0, 36) + buffer.writeUInt8(this.properties.borderInnerSoftness || 0, 37) + buffer.writeUInt8(this.properties.borderBevelSoftness || 0, 38) + buffer.writeUInt8(this.properties.borderBevelPosition || 0, 39) + buffer.writeUInt8(this.properties.borderOpacity || 0, 40) + + buffer.writeUInt16BE(this.properties.borderHue || 0, 42) + buffer.writeUInt16BE(this.properties.borderSaturation || 0, 44) + buffer.writeUInt16BE(this.properties.borderLuma || 0, 46) + + buffer.writeUInt16BE(this.properties.lightSourceDirection || 0, 48) + buffer.writeUInt8(this.properties.lightSourceAltitude || 0, 50) buffer[51] = this.properties.maskEnabled ? 1 : 0 - buffer.writeUInt16BE(this.properties.maskTop, 52) - buffer.writeUInt16BE(this.properties.maskBottom, 54) - buffer.writeUInt16BE(this.properties.maskLeft, 56) - buffer.writeUInt16BE(this.properties.maskRight, 58) + buffer.writeUInt16BE(this.properties.maskTop || 0, 52) + buffer.writeUInt16BE(this.properties.maskBottom || 0, 54) + buffer.writeUInt16BE(this.properties.maskLeft || 0, 56) + buffer.writeUInt16BE(this.properties.maskRight || 0, 58) - buffer.writeUInt8(this.properties.rate, 60) + buffer.writeUInt8(this.properties.rate || 0, 60) return buffer } } export class MixEffectKeyDVEUpdateCommand extends AbstractCommand { - rawName = 'KeDV' - mixEffect: number - upstreamKeyerId: number - properties: UpstreamKeyerDVESettings - - deserialize (rawCommand: Buffer) { - this.mixEffect = Util.parseNumberBetween(rawCommand[0], 0, 3) - this.upstreamKeyerId = Util.parseNumberBetween(rawCommand[1], 0, 3) - this.properties = { + static readonly rawName = 'KeDV' + + readonly mixEffect: number + readonly upstreamKeyerId: number + readonly properties: Readonly + + constructor (mixEffect: number, upstreamKeyerId: number, properties: UpstreamKeyerDVESettings) { + super() + + this.mixEffect = mixEffect + this.upstreamKeyerId = upstreamKeyerId + this.properties = properties + } + + static deserialize (rawCommand: Buffer) { + const mixEffect = Util.parseNumberBetween(rawCommand[0], 0, 3) + const upstreamKeyerId = Util.parseNumberBetween(rawCommand[1], 0, 3) + const properties = { // Note: these are higher than the ui shows, but are within the range the atem can be set to sizeX: Util.parseNumberBetween(rawCommand.readUInt32BE(4), 0, Math.pow(2, 32) - 1), sizeY: Util.parseNumberBetween(rawCommand.readUInt32BE(8), 0, Math.pow(2, 32) - 1), @@ -124,6 +141,8 @@ export class MixEffectKeyDVEUpdateCommand extends AbstractCommand { rate: Util.parseNumberBetween(rawCommand.readUInt8(56), 0, 250) } + + return new MixEffectKeyDVEUpdateCommand(mixEffect, upstreamKeyerId, properties) } applyToState (state: AtemState) { diff --git a/src/commands/MixEffects/Key/MixEffectKeyFillSourceSetCommand.ts b/src/commands/MixEffects/Key/MixEffectKeyFillSourceSetCommand.ts index a91855959..0ad9cf8ef 100644 --- a/src/commands/MixEffects/Key/MixEffectKeyFillSourceSetCommand.ts +++ b/src/commands/MixEffects/Key/MixEffectKeyFillSourceSetCommand.ts @@ -1,7 +1,7 @@ import AbstractCommand from '../../AbstractCommand' export class MixEffectKeyFillSourceSetCommand extends AbstractCommand { - rawName = 'CKeF' + static readonly rawName = 'CKeF' mixEffect: number upstreamKeyerId: number properties: { diff --git a/src/commands/MixEffects/Key/MixEffectKeyFlyKeyframeGetCommand.ts b/src/commands/MixEffects/Key/MixEffectKeyFlyKeyframeGetCommand.ts index 653a16af6..b1347fa0e 100644 --- a/src/commands/MixEffects/Key/MixEffectKeyFlyKeyframeGetCommand.ts +++ b/src/commands/MixEffects/Key/MixEffectKeyFlyKeyframeGetCommand.ts @@ -4,16 +4,28 @@ import { UpstreamKeyerFlyKeyframe } from '../../../state/video/upstreamKeyers' import { Util } from '../../..' export class MixEffectKeyFlyKeyframeGetCommand extends AbstractCommand { - rawName = 'KKFP' - mixEffect: number - upstreamKeyerId: number - properties: UpstreamKeyerFlyKeyframe + static readonly rawName = 'KKFP' - deserialize (rawCommand: Buffer) { - this.mixEffect = Util.parseNumberBetween(rawCommand[0], 0, 3) - this.upstreamKeyerId = Util.parseNumberBetween(rawCommand[1], 0, 3) - this.properties = { - keyFrameId: Util.parseNumberBetween(rawCommand[2], 1, 2), + readonly mixEffect: number + readonly upstreamKeyerId: number + readonly keyFrameId: number + readonly properties: Readonly + + constructor (mixEffect: number, upstreamKeyerId: number, keyFrameId: number, properties: UpstreamKeyerFlyKeyframe) { + super() + + this.mixEffect = mixEffect + this.upstreamKeyerId = upstreamKeyerId + this.keyFrameId = keyFrameId + this.properties = properties + } + + static deserialize (rawCommand: Buffer) { + const mixEffect = Util.parseNumberBetween(rawCommand[0], 0, 3) + const upstreamKeyerId = Util.parseNumberBetween(rawCommand[1], 0, 3) + const keyFrameId = Util.parseNumberBetween(rawCommand[2], 1, 2) + const properties = { + keyFrameId: keyFrameId, // Note: these are higher than the ui shows, but are within the range the atem can be set to sizeX: Util.parseNumberBetween(rawCommand.readUInt32BE(4), 0, Math.pow(2, 32) - 1), @@ -44,6 +56,8 @@ export class MixEffectKeyFlyKeyframeGetCommand extends AbstractCommand { maskLeft: Util.parseNumberBetween(rawCommand.readInt16BE(48), -16000, 16000), maskRight: Util.parseNumberBetween(rawCommand.readInt16BE(50), -16000, 16000) } + + return new MixEffectKeyFlyKeyframeGetCommand(mixEffect, upstreamKeyerId, keyFrameId, properties) } applyToState (state: AtemState) { diff --git a/src/commands/MixEffects/Key/MixEffectKeyFlyPropertiesGetCommand.ts b/src/commands/MixEffects/Key/MixEffectKeyFlyPropertiesGetCommand.ts index a1d96e0cf..acfdece71 100644 --- a/src/commands/MixEffects/Key/MixEffectKeyFlyPropertiesGetCommand.ts +++ b/src/commands/MixEffects/Key/MixEffectKeyFlyPropertiesGetCommand.ts @@ -4,20 +4,30 @@ import { UpstreamKeyerFlySettings } from '../../../state/video/upstreamKeyers' import { Util } from '../../..' export class MixEffectKeyFlyPropertiesGetCommand extends AbstractCommand { - rawName = 'KeFS' - mixEffect: number - upstreamKeyerId: number - properties: UpstreamKeyerFlySettings + static readonly rawName = 'KeFS' - deserialize (rawCommand: Buffer) { - this.mixEffect = Util.parseNumberBetween(rawCommand[0], 0, 3) - this.upstreamKeyerId = Util.parseNumberBetween(rawCommand[1], 0, 3) - this.properties = { + readonly mixEffect: number + readonly upstreamKeyerId: number + readonly properties: Readonly + + constructor (mixEffect: number, upstreamKeyerId: number, properties: UpstreamKeyerFlySettings) { + super() + + this.mixEffect = mixEffect + this.upstreamKeyerId = upstreamKeyerId + this.properties = properties + } + + static deserialize (rawCommand: Buffer) { + const mixEffect = Util.parseNumberBetween(rawCommand[0], 0, 3) + const upstreamKeyerId = Util.parseNumberBetween(rawCommand[1], 0, 3) + const properties = { isASet: rawCommand[2] === 1, isBSet: rawCommand[3] === 1, isAtKeyFrame: rawCommand[6], runToInfiniteIndex: rawCommand[7] } + return new MixEffectKeyFlyPropertiesGetCommand(mixEffect, upstreamKeyerId, properties) } applyToState (state: AtemState) { diff --git a/src/commands/MixEffects/Key/MixEffectKeyLumaCommand.ts b/src/commands/MixEffects/Key/MixEffectKeyLumaCommand.ts index 09d547404..01545e21c 100644 --- a/src/commands/MixEffects/Key/MixEffectKeyLumaCommand.ts +++ b/src/commands/MixEffects/Key/MixEffectKeyLumaCommand.ts @@ -10,11 +10,19 @@ export class MixEffectKeyLumaCommand extends AbstractCommand { gain: 1 << 2, invert: 1 << 3 } + static readonly rawName = 'CKLm' - rawName = 'CKLm' - mixEffect: number - upstreamKeyerId: number - properties: UpstreamKeyerLumaSettings + readonly mixEffect: number + readonly upstreamKeyerId: number + properties: Partial + + constructor (mixEffect: number, upstreamKeyerId: number) { + super() + + this.mixEffect = mixEffect + this.upstreamKeyerId = upstreamKeyerId + this.properties = {} + } serialize () { const buffer = Buffer.alloc(12) @@ -23,8 +31,8 @@ export class MixEffectKeyLumaCommand extends AbstractCommand { buffer.writeUInt8(this.upstreamKeyerId, 2) buffer.writeUInt8(this.properties.preMultiplied ? 1 : 0, 3) - buffer.writeUInt16BE(this.properties.clip, 4) - buffer.writeUInt16BE(this.properties.gain, 6) + buffer.writeUInt16BE(this.properties.clip || 0, 4) + buffer.writeUInt16BE(this.properties.gain || 0, 6) buffer.writeUInt8(this.properties.invert ? 1 : 0, 8) return buffer @@ -32,20 +40,31 @@ export class MixEffectKeyLumaCommand extends AbstractCommand { } export class MixEffectKeyLumaUpdateCommand extends AbstractCommand { - rawName = 'KeLm' - mixEffect: number - upstreamKeyerId: number - properties: UpstreamKeyerLumaSettings - - deserialize (rawCommand: Buffer) { - this.mixEffect = Util.parseNumberBetween(rawCommand[0], 0, 3) - this.upstreamKeyerId = Util.parseNumberBetween(rawCommand[1], 0, 3) - this.properties = { + static readonly rawName = 'KeLm' + + readonly mixEffect: number + readonly upstreamKeyerId: number + readonly properties: Readonly + + constructor (mixEffect: number, upstreamKeyerId: number, properties: UpstreamKeyerLumaSettings) { + super() + + this.mixEffect = mixEffect + this.upstreamKeyerId = upstreamKeyerId + this.properties = properties + } + + static deserialize (rawCommand: Buffer) { + const mixEffect = Util.parseNumberBetween(rawCommand[0], 0, 3) + const upstreamKeyerId = Util.parseNumberBetween(rawCommand[1], 0, 3) + const properties = { preMultiplied: rawCommand[2] === 1, clip: Util.parseNumberBetween(rawCommand.readUInt16BE(4), 0, 1000), gain: Util.parseNumberBetween(rawCommand.readUInt16BE(6), 0, 1000), invert: rawCommand[8] === 1 } + + return new MixEffectKeyLumaUpdateCommand(mixEffect, upstreamKeyerId, properties) } applyToState (state: AtemState) { diff --git a/src/commands/MixEffects/Key/MixEffectKeyMaskSetCommand.ts b/src/commands/MixEffects/Key/MixEffectKeyMaskSetCommand.ts index 4df76c8fb..d83f3ce9e 100644 --- a/src/commands/MixEffects/Key/MixEffectKeyMaskSetCommand.ts +++ b/src/commands/MixEffects/Key/MixEffectKeyMaskSetCommand.ts @@ -10,7 +10,7 @@ export class MixEffectKeyMaskSetCommand extends AbstractCommand { maskRight: 1 << 4 } - rawName = 'CKMs' + static readonly rawName = 'CKMs' mixEffect: number upstreamKeyerId: number properties: UpstreamKeyerMaskSettings diff --git a/src/commands/MixEffects/Key/MixEffectKeyOnAirCommand.ts b/src/commands/MixEffects/Key/MixEffectKeyOnAirCommand.ts index 9d5edfdd8..5503a6aea 100644 --- a/src/commands/MixEffects/Key/MixEffectKeyOnAirCommand.ts +++ b/src/commands/MixEffects/Key/MixEffectKeyOnAirCommand.ts @@ -3,11 +3,20 @@ import { AtemState } from '../../../state' import { Util } from '../../..' export class MixEffectKeyOnAirCommand extends AbstractCommand { - rawName = 'CKOn' - mixEffect: number - upstreamKeyerId: number - properties: { + static readonly rawName = 'CKOn' + + readonly mixEffect: number + readonly upstreamKeyerId: number + readonly properties: Readonly<{ onAir: boolean + }> + + constructor (mixEffect: number, upstreamKeyerId: number, onAir: boolean) { + super() + + this.mixEffect = mixEffect + this.upstreamKeyerId = upstreamKeyerId + this.properties = { onAir } } serialize () { @@ -20,19 +29,29 @@ export class MixEffectKeyOnAirCommand extends AbstractCommand { } export class MixEffectKeyOnAirUpdateCommand extends AbstractCommand { - rawName = 'KeOn' - mixEffect: number - upstreamKeyerId: number - properties: { + static readonly rawName = 'KeOn' + + readonly mixEffect: number + readonly upstreamKeyerId: number + readonly properties: Readonly<{ onAir: boolean + }> + + constructor (mixEffect: number, upstreamKeyerId: number, properties: MixEffectKeyOnAirUpdateCommand['properties']) { + super() + + this.mixEffect = mixEffect + this.upstreamKeyerId = upstreamKeyerId + this.properties = properties } - deserialize (rawCommand: Buffer) { - this.mixEffect = Util.parseNumberBetween(rawCommand[0], 0, 3) - this.upstreamKeyerId = Util.parseNumberBetween(rawCommand[1], 0, 3) - this.properties = { + static deserialize (rawCommand: Buffer) { + const mixEffect = Util.parseNumberBetween(rawCommand[0], 0, 3) + const upstreamKeyerId = Util.parseNumberBetween(rawCommand[1], 0, 3) + const properties = { onAir: rawCommand[2] === 1 } + return new MixEffectKeyOnAirUpdateCommand(mixEffect, upstreamKeyerId, properties) } applyToState (state: AtemState) { diff --git a/src/commands/MixEffects/Key/MixEffectKeyPatternCommand.ts b/src/commands/MixEffects/Key/MixEffectKeyPatternCommand.ts index 9b605c7a4..c2b8e1b54 100644 --- a/src/commands/MixEffects/Key/MixEffectKeyPatternCommand.ts +++ b/src/commands/MixEffects/Key/MixEffectKeyPatternCommand.ts @@ -1,9 +1,9 @@ -import AbstractCommand from '../../AbstractCommand' +import AbstractCommand, { WritableCommand } from '../../AbstractCommand' import { AtemState } from '../../../state' import { UpstreamKeyerPatternSettings } from '../../../state/video/upstreamKeyers' import { Util, Enums } from '../../..' -export class MixEffectKeyPatternCommand extends AbstractCommand { +export class MixEffectKeyPatternCommand extends WritableCommand { static MaskFlags = { style: 1 << 0, size: 1 << 1, @@ -14,10 +14,17 @@ export class MixEffectKeyPatternCommand extends AbstractCommand { invert: 1 << 6 } - rawName = 'CKPt' - mixEffect: number - upstreamKeyerId: number - properties: UpstreamKeyerPatternSettings + static readonly rawName = 'CKPt' + + readonly mixEffect: number + readonly upstreamKeyerId: number + + constructor (mixEffect: number, upstreamKeyerId: number) { + super() + + this.mixEffect = mixEffect + this.upstreamKeyerId = upstreamKeyerId + } serialize () { const buffer = Buffer.alloc(16) @@ -25,12 +32,12 @@ export class MixEffectKeyPatternCommand extends AbstractCommand { buffer.writeUInt8(this.mixEffect, 1) buffer.writeUInt8(this.upstreamKeyerId, 2) - buffer.writeUInt8(this.properties.style, 3) - buffer.writeUInt16BE(this.properties.size, 4) - buffer.writeUInt16BE(this.properties.symmetry, 6) - buffer.writeUInt16BE(this.properties.softness, 8) - buffer.writeUInt16BE(this.properties.positionX, 10) - buffer.writeUInt16BE(this.properties.positionY, 12) + buffer.writeUInt8(this.properties.style || 0, 3) + buffer.writeUInt16BE(this.properties.size || 0, 4) + buffer.writeUInt16BE(this.properties.symmetry || 0, 6) + buffer.writeUInt16BE(this.properties.softness || 0, 8) + buffer.writeUInt16BE(this.properties.positionX || 0, 10) + buffer.writeUInt16BE(this.properties.positionY || 0, 12) buffer.writeUInt8(this.properties.invert ? 1 : 0, 14) return buffer @@ -38,15 +45,24 @@ export class MixEffectKeyPatternCommand extends AbstractCommand { } export class MixEffectKeyUpdateCommand extends AbstractCommand { - rawName = 'KePt' - mixEffect: number - upstreamKeyerId: number - properties: UpstreamKeyerPatternSettings + static readonly rawName = 'KePt' + + readonly mixEffect: number + readonly upstreamKeyerId: number + readonly properties: Readonly - deserialize (rawCommand: Buffer) { - this.mixEffect = Util.parseNumberBetween(rawCommand[0], 0, 3) - this.upstreamKeyerId = Util.parseNumberBetween(rawCommand[1], 0, 3) - this.properties = { + constructor (mixEffect: number, upstreamKeyerId: number, properties: UpstreamKeyerPatternSettings) { + super() + + this.mixEffect = mixEffect + this.upstreamKeyerId = upstreamKeyerId + this.properties = properties + } + + static deserialize (rawCommand: Buffer): MixEffectKeyUpdateCommand { + const mixEffect = Util.parseNumberBetween(rawCommand[0], 0, 3) + const upstreamKeyerId = Util.parseNumberBetween(rawCommand[1], 0, 3) + const properties = { style: Util.parseEnum(rawCommand[2], Enums.Pattern), size: Util.parseNumberBetween(rawCommand.readUInt16BE(4), 0, 10000), symmetry: Util.parseNumberBetween(rawCommand.readUInt16BE(6), 0, 10000), @@ -55,6 +71,8 @@ export class MixEffectKeyUpdateCommand extends AbstractCommand { positionY: Util.parseNumberBetween(rawCommand.readUInt16BE(12), 0, 10000), invert: rawCommand[14] === 1 } + + return new MixEffectKeyUpdateCommand(mixEffect, upstreamKeyerId, properties) } applyToState (state: AtemState) { diff --git a/src/commands/MixEffects/Key/MixEffectKeyPropertiesGetCommand.ts b/src/commands/MixEffects/Key/MixEffectKeyPropertiesGetCommand.ts index f1115ab67..7adf164b5 100644 --- a/src/commands/MixEffects/Key/MixEffectKeyPropertiesGetCommand.ts +++ b/src/commands/MixEffects/Key/MixEffectKeyPropertiesGetCommand.ts @@ -4,13 +4,21 @@ import { UpstreamKeyerBase } from '../../../state/video/upstreamKeyers' import { Util, Enums } from '../../..' export class MixEffectKeyPropertiesGetCommand extends AbstractCommand { - rawName = 'KeBP' - mixEffect: number - properties: UpstreamKeyerBase + static readonly rawName = 'KeBP' - deserialize (rawCommand: Buffer) { - this.mixEffect = Util.parseNumberBetween(rawCommand[0], 0, 3) - this.properties = { + readonly mixEffect: number + readonly properties: Readonly + + constructor (mixEffect: number, properties: UpstreamKeyerBase) { + super() + + this.mixEffect = mixEffect + this.properties = properties + } + + static deserialize (rawCommand: Buffer): MixEffectKeyPropertiesGetCommand { + const mixEffect = Util.parseNumberBetween(rawCommand[0], 0, 3) + const properties = { upstreamKeyerId: Util.parseNumberBetween(rawCommand[1], 0, 3), mixEffectKeyType: Util.parseEnum(rawCommand[2], Enums.MixEffectKeyType), flyEnabled: rawCommand[5] === 1, @@ -22,14 +30,16 @@ export class MixEffectKeyPropertiesGetCommand extends AbstractCommand { maskLeft: Util.parseNumberBetween(rawCommand.readInt16BE(16), -16000, 16000), maskRight: Util.parseNumberBetween(rawCommand.readInt16BE(18), -16000, 16000) } + + return new MixEffectKeyPropertiesGetCommand(mixEffect, properties) } applyToState (state: AtemState) { const mixEffect = state.video.getMe(this.mixEffect) - Object.assign( - mixEffect.upstreamKeyers[this.properties.upstreamKeyerId], - this.properties - ) + mixEffect.upstreamKeyers[this.properties.upstreamKeyerId] = { + ...mixEffect.upstreamKeyers[this.properties.upstreamKeyerId], + ...this.properties + } return `video.ME.${this.mixEffect}.upstreamKeyers.${this.properties.upstreamKeyerId}` } } diff --git a/src/commands/MixEffects/Key/MixEffectKeyTypeSetCommand.ts b/src/commands/MixEffects/Key/MixEffectKeyTypeSetCommand.ts index f959bc2a3..71a1fcadb 100644 --- a/src/commands/MixEffects/Key/MixEffectKeyTypeSetCommand.ts +++ b/src/commands/MixEffects/Key/MixEffectKeyTypeSetCommand.ts @@ -7,7 +7,7 @@ export class MixEffectKeyTypeSetCommand extends AbstractCommand { flyEnabled: 1 << 1 } - rawName = 'CKTp' + static readonly rawName = 'CKTp' mixEffect: number upstreamKeyerId: number properties: UpstreamKeyerTypeSettings diff --git a/src/commands/MixEffects/PreviewInputCommand.ts b/src/commands/MixEffects/PreviewInputCommand.ts index b9f9b16d1..4594f0aba 100644 --- a/src/commands/MixEffects/PreviewInputCommand.ts +++ b/src/commands/MixEffects/PreviewInputCommand.ts @@ -1,13 +1,23 @@ -import AbstractCommand from '../AbstractCommand' +import AbstractCommand, { BasicWritableCommand } from '../AbstractCommand' import { AtemState } from '../../state' import { Util } from '../..' -export class PreviewInputCommand extends AbstractCommand { - rawName = 'CPvI' - mixEffect: number +export interface InputSource { + source: number +} + +export class PreviewInputCommand extends BasicWritableCommand { + static readonly rawName = 'CPvI' + + readonly mixEffect: number - properties: { - source: number + constructor (mixEffect: number, source: number) { + super() + + this.mixEffect = mixEffect + this.properties = { + source + } } serialize () { @@ -19,18 +29,25 @@ export class PreviewInputCommand extends AbstractCommand { } export class PreviewInputUpdateCommand extends AbstractCommand { - rawName = 'PrvI' - mixEffect: number + static readonly rawName = 'PrvI' + readonly mixEffect: number + + readonly properties: Readonly + + constructor (mixEffect: number, properties: InputSource) { + super() - properties: { - source: number + this.mixEffect = mixEffect + this.properties = properties } - deserialize (rawCommand: Buffer) { - this.mixEffect = Util.parseNumberBetween(rawCommand[0], 0, 3) - this.properties = { + static deserialize (rawCommand: Buffer): PreviewInputUpdateCommand { + const mixEffect = Util.parseNumberBetween(rawCommand[0], 0, 3) + const properties = { source: rawCommand.readUInt16BE(2) } + + return new PreviewInputUpdateCommand(mixEffect, properties) } applyToState (state: AtemState) { diff --git a/src/commands/MixEffects/ProgramInputCommand.ts b/src/commands/MixEffects/ProgramInputCommand.ts index 191cd0b92..a5560c4b5 100644 --- a/src/commands/MixEffects/ProgramInputCommand.ts +++ b/src/commands/MixEffects/ProgramInputCommand.ts @@ -1,13 +1,23 @@ -import AbstractCommand from '../AbstractCommand' +import AbstractCommand, { BasicWritableCommand } from '../AbstractCommand' import { AtemState } from '../../state' import { Util } from '../..' -export class ProgramInputCommand extends AbstractCommand { - rawName = 'CPgI' - mixEffect: number +export interface InputSource { + source: number +} + +export class ProgramInputCommand extends BasicWritableCommand { + static readonly rawName = 'CPgI' + + readonly mixEffect: number - properties: { - source: number + constructor (mixEffect: number, source: number) { + super() + + this.mixEffect = mixEffect + this.properties = { + source + } } serialize () { @@ -19,18 +29,26 @@ export class ProgramInputCommand extends AbstractCommand { } export class ProgramInputUpdateCommand extends AbstractCommand { - rawName = 'PrgI' - mixEffect: number + static readonly rawName = 'PrgI' + readonly mixEffect: number - properties: { - source: number + readonly properties: Readonly + + constructor (mixEffect: number, properties: InputSource) { + super() + + this.mixEffect = mixEffect + this.properties = properties } - deserialize (rawCommand: Buffer) { - this.mixEffect = Util.parseNumberBetween(rawCommand[0], 0, 3) - this.properties = { + + static deserialize (rawCommand: Buffer): ProgramInputUpdateCommand { + const mixEffect = Util.parseNumberBetween(rawCommand[0], 0, 3) + const properties = { source: rawCommand.readUInt16BE(2) } + + return new ProgramInputUpdateCommand(mixEffect, properties) } applyToState (state: AtemState) { diff --git a/src/commands/MixEffects/Transition/TransitionDVECommand.ts b/src/commands/MixEffects/Transition/TransitionDVECommand.ts index f16d7596c..56264d128 100644 --- a/src/commands/MixEffects/Transition/TransitionDVECommand.ts +++ b/src/commands/MixEffects/Transition/TransitionDVECommand.ts @@ -1,9 +1,9 @@ -import AbstractCommand from '../../AbstractCommand' +import AbstractCommand, { WritableCommand } from '../../AbstractCommand' import { AtemState } from '../../../state' import { DVETransitionSettings } from '../../../state/video' import { Util, Enums } from '../../..' -export class TransitionDVECommand extends AbstractCommand { +export class TransitionDVECommand extends WritableCommand { static MaskFlags = { rate: 1 << 0, logoRate: 1 << 1, @@ -19,13 +19,14 @@ export class TransitionDVECommand extends AbstractCommand { flipFlop: 1 << 11 } - rawName = 'CTDv' - mixEffect: number + static readonly rawName = 'CTDv' - properties: DVETransitionSettings + readonly mixEffect: number - updateProps (newProps: Partial) { - this._updateProps(newProps) + constructor (mixEffect: number) { + super() + + this.mixEffect = mixEffect } serialize () { @@ -33,17 +34,17 @@ export class TransitionDVECommand extends AbstractCommand { buffer.writeUInt16BE(this.flag, 0) buffer.writeUInt8(this.mixEffect, 2) - buffer.writeUInt8(this.properties.rate, 3) - buffer.writeUInt8(this.properties.logoRate, 4) - buffer.writeUInt8(this.properties.style, 5) + buffer.writeUInt8(this.properties.rate || 0, 3) + buffer.writeUInt8(this.properties.logoRate || 0, 4) + buffer.writeUInt8(this.properties.style || 0, 5) - buffer.writeUInt16BE(this.properties.fillSource, 6) - buffer.writeUInt16BE(this.properties.keySource, 8) + buffer.writeUInt16BE(this.properties.fillSource || 0, 6) + buffer.writeUInt16BE(this.properties.keySource || 0, 8) buffer.writeUInt8(this.properties.enableKey ? 1 : 0, 10) buffer.writeUInt8(this.properties.preMultiplied ? 1 : 0, 11) - buffer.writeUInt16BE(this.properties.clip, 12) - buffer.writeUInt16BE(this.properties.gain, 14) + buffer.writeUInt16BE(this.properties.clip || 0, 12) + buffer.writeUInt16BE(this.properties.gain || 0, 14) buffer.writeUInt8(this.properties.invertKey ? 1 : 0, 16) buffer.writeUInt8(this.properties.reverse ? 1 : 0, 17) buffer.writeUInt8(this.properties.flipFlop ? 1 : 0, 18) @@ -53,14 +54,21 @@ export class TransitionDVECommand extends AbstractCommand { } export class TransitionDVEUpdateCommand extends AbstractCommand { - rawName = 'TDvP' - mixEffect: number + static readonly rawName = 'TDvP' + + readonly mixEffect: number + readonly properties: Readonly - properties: DVETransitionSettings + constructor (mixEffect: number, properties: DVETransitionSettings) { + super() - deserialize (rawCommand: Buffer) { - this.mixEffect = Util.parseNumberBetween(rawCommand[0], 0, 3) - this.properties = { + this.mixEffect = mixEffect + this.properties = properties + } + + static deserialize (rawCommand: Buffer): TransitionDVEUpdateCommand { + const mixEffect = Util.parseNumberBetween(rawCommand[0], 0, 3) + const properties = { rate: Util.parseNumberBetween(rawCommand[1], 1, 250), logoRate: Util.parseNumberBetween(rawCommand[2], 1, 250), style: Util.parseEnum(rawCommand[3], Enums.DVEEffect), @@ -75,6 +83,8 @@ export class TransitionDVEUpdateCommand extends AbstractCommand { reverse: rawCommand[15] === 1, flipFlop: rawCommand[16] === 1 } + + return new TransitionDVEUpdateCommand(mixEffect, properties) } applyToState (state: AtemState) { diff --git a/src/commands/MixEffects/Transition/TransitionDipCommand.ts b/src/commands/MixEffects/Transition/TransitionDipCommand.ts index 074da8bac..550faaa35 100644 --- a/src/commands/MixEffects/Transition/TransitionDipCommand.ts +++ b/src/commands/MixEffects/Transition/TransitionDipCommand.ts @@ -1,45 +1,54 @@ -import AbstractCommand from '../../AbstractCommand' +import AbstractCommand, { WritableCommand } from '../../AbstractCommand' import { AtemState } from '../../../state' import { DipTransitionSettings } from '../../../state/video' import { Util } from '../../..' -export class TransitionDipCommand extends AbstractCommand { +export class TransitionDipCommand extends WritableCommand { static MaskFlags = { rate: 1 << 0, input: 1 << 1 } + static readonly rawName = 'CTDp' - rawName = 'CTDp' - mixEffect: number + readonly mixEffect: number - properties: DipTransitionSettings + constructor (mixEffect: number) { + super() - updateProps (newProps: Partial) { - this._updateProps(newProps) + this.mixEffect = mixEffect } serialize () { const buffer = Buffer.alloc(8) buffer.writeUInt8(this.flag, 0) buffer.writeUInt8(this.mixEffect, 1) - buffer.writeUInt8(this.properties.rate, 2) - buffer.writeUInt16BE(this.properties.input, 4) + buffer.writeUInt8(this.properties.rate || 0, 2) + buffer.writeUInt16BE(this.properties.input || 0, 4) return buffer } } export class TransitionDipUpdateCommand extends AbstractCommand { - rawName = 'TDpP' - mixEffect: number + static readonly rawName = 'TDpP' - properties: DipTransitionSettings + readonly mixEffect: number + readonly properties: Readonly - deserialize (rawCommand: Buffer) { - this.mixEffect = Util.parseNumberBetween(rawCommand[0], 0, 3) - this.properties = { + constructor (mixEffect: number, properties: DipTransitionSettings) { + super() + + this.mixEffect = mixEffect + this.properties = properties + } + + static deserialize (rawCommand: Buffer): TransitionDipUpdateCommand { + const mixEffect = Util.parseNumberBetween(rawCommand[0], 0, 3) + const properties = { rate: Util.parseNumberBetween(rawCommand[1], 0, 250), input: rawCommand[2] << 8 | (rawCommand[3] & 0xFF) } + + return new TransitionDipUpdateCommand(mixEffect, properties) } applyToState (state: AtemState) { diff --git a/src/commands/MixEffects/Transition/TransitionMixCommand.ts b/src/commands/MixEffects/Transition/TransitionMixCommand.ts index 5bb618b87..e1261ea35 100644 --- a/src/commands/MixEffects/Transition/TransitionMixCommand.ts +++ b/src/commands/MixEffects/Transition/TransitionMixCommand.ts @@ -1,37 +1,47 @@ -import AbstractCommand from '../../AbstractCommand' +import AbstractCommand, { WritableCommand } from '../../AbstractCommand' import { AtemState } from '../../../state' import { MixTransitionSettings } from '../../../state/video' import { Util } from '../../..' -export class TransitionMixCommand extends AbstractCommand { - rawName = 'CTMx' - mixEffect: number +export class TransitionMixCommand extends WritableCommand { + static readonly rawName = 'CTMx' - properties: MixTransitionSettings + readonly mixEffect: number - updateProps (newProps: Partial) { - this._updateProps(newProps) + constructor (mixEffect: number) { + super() + + this.mixEffect = mixEffect } serialize () { const buffer = Buffer.alloc(4) buffer.writeUInt8(this.mixEffect, 0) - buffer.writeUInt8(this.properties.rate, 1) + buffer.writeUInt8(this.properties.rate || 0, 1) return buffer } } export class TransitionMixUpdateCommand extends AbstractCommand { - rawName = 'TMxP' - mixEffect: number + static readonly rawName = 'TMxP' + + readonly mixEffect: number + readonly properties: Readonly - properties: MixTransitionSettings + constructor (mixEffect: number, properties: MixTransitionSettings) { + super() - deserialize (rawCommand: Buffer) { - this.mixEffect = Util.parseNumberBetween(rawCommand[0], 0, 3) - this.properties = { + this.mixEffect = mixEffect + this.properties = properties + } + + static deserialize (rawCommand: Buffer): TransitionMixUpdateCommand { + const mixEffect = Util.parseNumberBetween(rawCommand[0], 0, 3) + const properties = { rate: Util.parseNumberBetween(rawCommand[1], 1, 250) } + + return new TransitionMixUpdateCommand(mixEffect, properties) } applyToState (state: AtemState) { diff --git a/src/commands/MixEffects/Transition/TransitionPositionCommand.ts b/src/commands/MixEffects/Transition/TransitionPositionCommand.ts index 1f7a7d08d..a6ebbd60e 100644 --- a/src/commands/MixEffects/Transition/TransitionPositionCommand.ts +++ b/src/commands/MixEffects/Transition/TransitionPositionCommand.ts @@ -1,15 +1,21 @@ -import AbstractCommand from '../../AbstractCommand' +import AbstractCommand, { BasicWritableCommand } from '../../AbstractCommand' import { AtemState } from '../../../state' import { Util } from '../../..' -export class TransitionPositionCommand extends AbstractCommand { - rawName = 'CTPs' - mixEffect: number +export interface HandlePositionProps { + handlePosition: number // 0...10000 +} - properties: { - readonly inTransition: boolean - readonly remainingFrames: number // 0...250 - handlePosition: number // 0...10000 +export class TransitionPositionCommand extends BasicWritableCommand { + static readonly rawName = 'CTPs' + + readonly mixEffect: number + + constructor (mixEffect: number, handlePosition: number) { + super() + + this.mixEffect = mixEffect + this.properties = { handlePosition } } serialize () { @@ -21,22 +27,31 @@ export class TransitionPositionCommand extends AbstractCommand { } export class TransitionPositionUpdateCommand extends AbstractCommand { - rawName = 'TrPs' - mixEffect: number + static readonly rawName = 'TrPs' - properties: { - readonly inTransition: boolean - readonly remainingFrames: number // 0...250 + readonly mixEffect: number + readonly properties: Readonly<{ + inTransition: boolean + remainingFrames: number // 0...250 handlePosition: number // 0...10000 + }> + + constructor (mixEffect: number, properties: TransitionPositionUpdateCommand['properties']) { + super() + + this.mixEffect = mixEffect + this.properties = properties } - deserialize (rawCommand: Buffer) { - this.mixEffect = Util.parseNumberBetween(rawCommand[0], 0, 3) - this.properties = { + static deserialize (rawCommand: Buffer): TransitionPositionUpdateCommand { + const mixEffect = Util.parseNumberBetween(rawCommand[0], 0, 3) + const properties = { inTransition: rawCommand[1] === 1, remainingFrames: Util.parseNumberBetween(rawCommand[2], 0, 250), handlePosition: Util.parseNumberBetween(rawCommand.readUInt16BE(4), 0, 10000) } + + return new TransitionPositionUpdateCommand(mixEffect, properties) } applyToState (state: AtemState) { diff --git a/src/commands/MixEffects/Transition/TransitionPreviewCommand.ts b/src/commands/MixEffects/Transition/TransitionPreviewCommand.ts index 818c25626..8d3f93c87 100644 --- a/src/commands/MixEffects/Transition/TransitionPreviewCommand.ts +++ b/src/commands/MixEffects/Transition/TransitionPreviewCommand.ts @@ -1,13 +1,21 @@ -import AbstractCommand from '../../AbstractCommand' +import AbstractCommand, { BasicWritableCommand } from '../../AbstractCommand' import { AtemState } from '../../../state' import { Util } from '../../..' -export class PreviewTransitionCommand extends AbstractCommand { - rawName = 'CTPr' - mixEffect: number +export interface PreviewProps { + preview: boolean +} + +export class PreviewTransitionCommand extends BasicWritableCommand { + static readonly rawName = 'CTPr' + + readonly mixEffect: number + + constructor (mixEffect: number, preview: boolean) { + super() - properties: { - preview: boolean + this.mixEffect = mixEffect + this.properties = { preview } } serialize () { @@ -19,18 +27,25 @@ export class PreviewTransitionCommand extends AbstractCommand { } export class PreviewTransitionUpdateCommand extends AbstractCommand { - rawName = 'TrPr' - mixEffect: number + static readonly rawName = 'TrPr' - properties: { - preview: boolean + readonly mixEffect: number + readonly properties: Readonly + + constructor (mixEffect: number, properties: PreviewProps) { + super() + + this.mixEffect = mixEffect + this.properties = properties } - deserialize (rawCommand: Buffer) { - this.mixEffect = Util.parseNumberBetween(rawCommand[0], 0, 3) - this.properties = { + static deserialize (rawCommand: Buffer): PreviewTransitionUpdateCommand { + const mixEffect = Util.parseNumberBetween(rawCommand[0], 0, 3) + const properties = { preview: rawCommand[1] === 1 } + + return new PreviewTransitionUpdateCommand(mixEffect, properties) } applyToState (state: AtemState) { diff --git a/src/commands/MixEffects/Transition/TransitionPropertiesCommand.ts b/src/commands/MixEffects/Transition/TransitionPropertiesCommand.ts index 32ab81fb3..ce300be18 100644 --- a/src/commands/MixEffects/Transition/TransitionPropertiesCommand.ts +++ b/src/commands/MixEffects/Transition/TransitionPropertiesCommand.ts @@ -1,21 +1,22 @@ -import AbstractCommand from '../../AbstractCommand' +import AbstractCommand, { WritableCommand } from '../../AbstractCommand' import { AtemState } from '../../../state' import { TransitionProperties } from '../../../state/video' import { Util, Enums } from '../../..' -export class TransitionPropertiesCommand extends AbstractCommand { +export class TransitionPropertiesCommand extends WritableCommand { static MaskFlags = { style: 1 << 0, selection: 1 << 1 } - rawName = 'CTTp' - mixEffect: number + static readonly rawName = 'CTTp' - properties: TransitionProperties + readonly mixEffect: number - updateProps (newProps: Partial) { - this._updateProps(newProps) + constructor (mixEffect: number) { + super() + + this.mixEffect = mixEffect } serialize () { @@ -23,27 +24,36 @@ export class TransitionPropertiesCommand extends AbstractCommand { buffer.writeUInt8(this.flag, 0) buffer.writeUInt8(this.mixEffect, 1) - buffer.writeUInt8(this.properties.style, 2) - buffer.writeUInt8(this.properties.selection, 3) + buffer.writeUInt8(this.properties.style || 0, 2) + buffer.writeUInt8(this.properties.selection || 0, 3) return buffer } } export class TransitionPropertiesUpdateCommand extends AbstractCommand { - rawName = 'TrSS' - mixEffect: number + static readonly rawName = 'TrSS' + + readonly mixEffect: number + readonly properties: Readonly - properties: TransitionProperties + constructor (mixEffect: number, properties: TransitionProperties) { + super() - deserialize (rawCommand: Buffer) { - this.mixEffect = Util.parseNumberBetween(rawCommand[0], 0, 3) - this.properties = { + this.mixEffect = mixEffect + this.properties = properties + } + + static deserialize (rawCommand: Buffer): TransitionPropertiesUpdateCommand { + const mixEffect = Util.parseNumberBetween(rawCommand[0], 0, 3) + const properties = { style: Util.parseEnum(rawCommand[1], Enums.TransitionStyle),// rawCommand[1], selection: rawCommand[2], nextStyle: Util.parseEnum(rawCommand[3], Enums.TransitionStyle), nextSelection: rawCommand[4] } + + return new TransitionPropertiesUpdateCommand(mixEffect, properties) } applyToState (state: AtemState) { diff --git a/src/commands/MixEffects/Transition/TransitionStingerCommand.ts b/src/commands/MixEffects/Transition/TransitionStingerCommand.ts index d6fa203c5..6772e0680 100644 --- a/src/commands/MixEffects/Transition/TransitionStingerCommand.ts +++ b/src/commands/MixEffects/Transition/TransitionStingerCommand.ts @@ -1,9 +1,9 @@ -import AbstractCommand from '../../AbstractCommand' +import AbstractCommand, { WritableCommand } from '../../AbstractCommand' import { AtemState } from '../../../state' import { StingerTransitionSettings } from '../../../state/video' import { Util } from '../../..' -export class TransitionStingerCommand extends AbstractCommand { +export class TransitionStingerCommand extends WritableCommand { static MaskFlags = { source: 1 << 0, preMultipliedKey: 1 << 1, @@ -16,13 +16,14 @@ export class TransitionStingerCommand extends AbstractCommand { mixRate: 1 << 8 } - rawName = 'CTSt' - mixEffect: number + static readonly rawName = 'CTSt' - properties: StingerTransitionSettings + readonly mixEffect: number - updateProps (newProps: Partial) { - this._updateProps(newProps) + constructor (mixEffect: number) { + super() + + this.mixEffect = mixEffect } serialize () { @@ -30,31 +31,38 @@ export class TransitionStingerCommand extends AbstractCommand { buffer.writeUInt16BE(this.flag, 0) buffer.writeUInt8(this.mixEffect, 2) - buffer.writeUInt8(this.properties.source, 3) + buffer.writeUInt8(this.properties.source || 0, 3) buffer.writeUInt8(this.properties.preMultipliedKey ? 1 : 0, 4) - buffer.writeUInt16BE(this.properties.clip, 6) - buffer.writeUInt16BE(this.properties.gain, 8) + buffer.writeUInt16BE(this.properties.clip || 0, 6) + buffer.writeUInt16BE(this.properties.gain || 0, 8) buffer.writeUInt8(this.properties.invert ? 1 : 0, 10) - buffer.writeUInt16BE(this.properties.preroll, 12) - buffer.writeUInt16BE(this.properties.clipDuration, 14) - buffer.writeUInt16BE(this.properties.triggerPoint, 16) - buffer.writeUInt16BE(this.properties.mixRate, 18) + buffer.writeUInt16BE(this.properties.preroll || 0, 12) + buffer.writeUInt16BE(this.properties.clipDuration || 0, 14) + buffer.writeUInt16BE(this.properties.triggerPoint || 0, 16) + buffer.writeUInt16BE(this.properties.mixRate || 0, 18) return buffer } } export class TransitionStingerUpdateCommand extends AbstractCommand { - rawName = 'TStP' - mixEffect: number + static readonly rawName = 'TStP' + + readonly mixEffect: number + readonly properties: Readonly - properties: StingerTransitionSettings + constructor (mixEffect: number, properties: StingerTransitionSettings) { + super() - deserialize (rawCommand: Buffer) { - this.mixEffect = Util.parseNumberBetween(rawCommand[0], 0, 3) - this.properties = { + this.mixEffect = mixEffect + this.properties = properties + } + + static deserialize (rawCommand: Buffer): TransitionStingerUpdateCommand { + const mixEffect = Util.parseNumberBetween(rawCommand[0], 0, 3) + const properties = { source: rawCommand[1], preMultipliedKey: rawCommand[2] === 1, @@ -67,6 +75,8 @@ export class TransitionStingerUpdateCommand extends AbstractCommand { triggerPoint: rawCommand[14] << 8 | rawCommand[15], mixRate: rawCommand[16] << 8 | rawCommand[17] } + + return new TransitionStingerUpdateCommand(mixEffect, properties) } applyToState (state: AtemState) { diff --git a/src/commands/MixEffects/Transition/TransitionWipeCommand.ts b/src/commands/MixEffects/Transition/TransitionWipeCommand.ts index 721f3c740..85da8212d 100644 --- a/src/commands/MixEffects/Transition/TransitionWipeCommand.ts +++ b/src/commands/MixEffects/Transition/TransitionWipeCommand.ts @@ -1,9 +1,9 @@ -import AbstractCommand from '../../AbstractCommand' +import AbstractCommand, { WritableCommand } from '../../AbstractCommand' import { AtemState } from '../../../state' import { WipeTransitionSettings } from '../../../state/video' import { Util, Enums } from '../../..' -export class TransitionWipeCommand extends AbstractCommand { +export class TransitionWipeCommand extends WritableCommand { static MaskFlags = { rate: 1 << 0, pattern: 1 << 1, @@ -17,13 +17,14 @@ export class TransitionWipeCommand extends AbstractCommand { flipFlop: 1 << 9 } - rawName = 'CTWp' - mixEffect: number + static readonly rawName = 'CTWp' - properties: WipeTransitionSettings + readonly mixEffect: number - updateProps (newProps: Partial) { - this._updateProps(newProps) + constructor (mixEffect: number) { + super() + + this.mixEffect = mixEffect } serialize () { @@ -31,16 +32,16 @@ export class TransitionWipeCommand extends AbstractCommand { buffer.writeUInt16BE(this.flag, 0) buffer.writeUInt8(this.mixEffect, 2) - buffer.writeUInt8(this.properties.rate, 3) - buffer.writeUInt8(this.properties.pattern, 4) + buffer.writeUInt8(this.properties.rate || 0, 3) + buffer.writeUInt8(this.properties.pattern || 0, 4) - buffer.writeUInt16BE(this.properties.borderWidth, 6) - buffer.writeUInt16BE(this.properties.borderInput, 8) - buffer.writeUInt16BE(this.properties.symmetry, 10) + buffer.writeUInt16BE(this.properties.borderWidth || 0, 6) + buffer.writeUInt16BE(this.properties.borderInput || 0, 8) + buffer.writeUInt16BE(this.properties.symmetry || 0, 10) - buffer.writeUInt16BE(this.properties.borderSoftness, 12) - buffer.writeUInt16BE(this.properties.xPosition, 14) - buffer.writeUInt16BE(this.properties.yPosition, 16) + buffer.writeUInt16BE(this.properties.borderSoftness || 0, 12) + buffer.writeUInt16BE(this.properties.xPosition || 0, 14) + buffer.writeUInt16BE(this.properties.yPosition || 0, 16) buffer.writeUInt8(this.properties.reverseDirection ? 1 : 0, 18) buffer.writeUInt8(this.properties.flipFlop ? 1 : 0, 19) @@ -49,14 +50,21 @@ export class TransitionWipeCommand extends AbstractCommand { } export class TransitionWipeUpdateCommand extends AbstractCommand { - rawName = 'TWpP' - mixEffect: number + static readonly rawName = 'TWpP' + + readonly mixEffect: number + readonly properties: Readonly - properties: WipeTransitionSettings + constructor (mixEffect: number, properties: WipeTransitionSettings) { + super() - deserialize (rawCommand: Buffer) { - this.mixEffect = Util.parseNumberBetween(rawCommand[0], 0, 3) - this.properties = { + this.mixEffect = mixEffect + this.properties = properties + } + + static deserialize (rawCommand: Buffer): TransitionWipeUpdateCommand { + const mixEffect = Util.parseNumberBetween(rawCommand[0], 0, 3) + const properties = { rate: Util.parseNumberBetween(rawCommand[1], 1, 250), pattern: Util.parseEnum(rawCommand[2], Enums.Pattern), borderWidth: Util.parseNumberBetween(rawCommand.readUInt16BE(4), 0, 10000), @@ -68,6 +76,8 @@ export class TransitionWipeUpdateCommand extends AbstractCommand { reverseDirection: rawCommand[16] === 1, flipFlop: rawCommand[17] === 1 } + + return new TransitionWipeUpdateCommand(mixEffect, properties) } applyToState (state: AtemState) { diff --git a/src/commands/PowerStatusCommand.ts b/src/commands/PowerStatusCommand.ts index 73ae417e2..7d3079b70 100644 --- a/src/commands/PowerStatusCommand.ts +++ b/src/commands/PowerStatusCommand.ts @@ -7,15 +7,23 @@ import { AtemState } from '../state' * Broadcast Studio have 2 power supplies. All other models have 1. */ export class PowerStatusCommand extends AbstractCommand { - rawName = 'Powr' + static readonly rawName = 'Powr' - properties: boolean[] + readonly properties: Readonly - deserialize (rawCommand: Buffer) { - this.properties = [ + constructor (properties: boolean[]) { + super() + + this.properties = properties + } + + static deserialize (rawCommand: Buffer): PowerStatusCommand { + const properties = [ Boolean(rawCommand[0] & 1 << 0), Boolean(rawCommand[0] & 1 << 1) ] + + return new PowerStatusCommand(properties) } applyToState (state: AtemState) { diff --git a/src/commands/Settings/MultiViewerSourceCommand.ts b/src/commands/Settings/MultiViewerSourceCommand.ts index a7416b226..e339557c5 100644 --- a/src/commands/Settings/MultiViewerSourceCommand.ts +++ b/src/commands/Settings/MultiViewerSourceCommand.ts @@ -1,51 +1,57 @@ -import AbstractCommand from '../AbstractCommand' +import AbstractCommand, { WritableCommand } from '../AbstractCommand' import { AtemState } from '../../state' import { MultiViewerSourceState } from '../../state/settings' -export class MultiViewerSourceCommand extends AbstractCommand { - rawName = 'CMvI' - multiViewerId: number - index: number +export class MultiViewerSourceCommand extends WritableCommand { + static readonly rawName = 'CMvI' - properties: MultiViewerSourceState + readonly multiViewerId: number - updateProps (newProps: Partial) { - this._updateProps(newProps) + constructor (multiviewerId: number) { + super() + + this.multiViewerId = multiviewerId } serialize () { const buffer = Buffer.alloc(4) buffer.writeUInt8(this.multiViewerId, 0) - buffer.writeUInt8(this.properties.windowIndex, 1) - buffer.writeUInt16BE(this.properties.source, 2) + buffer.writeUInt8(this.properties.windowIndex || 0, 1) + buffer.writeUInt16BE(this.properties.source || 0, 2) return buffer } } export class MultiViewerSourceUpdateCommand extends AbstractCommand { - rawName = 'MvIn' - multiViewerId: number - index: number + static readonly rawName = 'MvIn' + + readonly multiViewerId: number + readonly properties: Readonly - properties: MultiViewerSourceState + constructor (multiviewerId: number, properties: MultiViewerSourceState) { + super() - deserialize (rawCommand: Buffer) { - this.index = rawCommand.readUInt8(1) - this.multiViewerId = rawCommand.readUInt8(0) + this.multiViewerId = multiviewerId + this.properties = properties + } - this.properties = { + static deserialize (rawCommand: Buffer): MultiViewerSourceUpdateCommand { + const multiViewerId = rawCommand.readUInt8(0) + const properties = { source: rawCommand.readUInt16BE(2), windowIndex: rawCommand.readUInt8(1) } + + return new MultiViewerSourceUpdateCommand(multiViewerId, properties) } applyToState (state: AtemState) { const multiviewer = state.settings.getMultiViewer(this.multiViewerId) - multiviewer.windows[this.index] = { - ...multiviewer.windows[this.index], + multiviewer.windows[this.properties.windowIndex] = { + ...multiviewer.windows[this.properties.windowIndex], ...this.properties } - return `settings.multiViewers.${this.multiViewerId}.windows.${this.index}` + return `settings.multiViewers.${this.multiViewerId}.windows.${this.properties.windowIndex}` } } diff --git a/src/commands/Settings/VideoMode.ts b/src/commands/Settings/VideoMode.ts index 4f3c35b47..f741dae9a 100644 --- a/src/commands/Settings/VideoMode.ts +++ b/src/commands/Settings/VideoMode.ts @@ -1,13 +1,20 @@ -import AbstractCommand from '../AbstractCommand' +import AbstractCommand, { BasicWritableCommand } from '../AbstractCommand' import { AtemState } from '../../state' import { Enums } from '../..' -export class VideoModeCommand extends AbstractCommand { - rawName = 'CVdM' - auxBus: number +export interface VideoModeProps { + mode: Enums.VideoMode +} + +export class VideoModeCommand extends BasicWritableCommand { + static readonly rawName = 'CVdM' + + constructor (mode: Enums.VideoMode) { + super() - properties: { - mode: Enums.VideoMode + this.properties = { + mode + } } serialize () { @@ -18,19 +25,22 @@ export class VideoModeCommand extends AbstractCommand { } export class VideoModeUpdateCommand extends AbstractCommand { - rawName = 'VidM' - auxBus: number + static readonly rawName = 'VidM' - properties: { - mode: Enums.VideoMode - } + readonly properties: Readonly + + constructor (mode: Enums.VideoMode) { + super() - deserialize (rawCommand: Buffer) { this.properties = { - mode: rawCommand[0] + mode } } + static deserialize (rawCommand: Buffer): VideoModeUpdateCommand { + return new VideoModeUpdateCommand(rawCommand[0]) + } + applyToState (state: AtemState) { state.settings.videoMode = this.properties.mode return `settings.videoMode` diff --git a/src/commands/SuperSource/SuperSourceBoxParametersCommand.ts b/src/commands/SuperSource/SuperSourceBoxParametersCommand.ts index 2c76e75d2..1837dc51a 100644 --- a/src/commands/SuperSource/SuperSourceBoxParametersCommand.ts +++ b/src/commands/SuperSource/SuperSourceBoxParametersCommand.ts @@ -18,10 +18,19 @@ export class SuperSourceBoxParametersCommand extends AbstractCommand { cropRight: 1 << 9 } - rawName = 'CSBP' - ssrcId: number - boxId: number - properties: SuperSourceBox + static readonly rawName = 'CSBP' + + readonly ssrcId: number + readonly boxId: number + properties: Partial + + constructor (ssrcId: number, boxId: number) { + super() + + this.ssrcId = ssrcId + this.boxId = boxId + this.properties = {} + } updateProps (newProps: Partial) { this._updateProps(newProps) @@ -40,37 +49,44 @@ export class SuperSourceBoxParametersCommand extends AbstractCommand { buffer.writeUInt8(this.properties.enabled ? 1 : 0, i + 3) if (i === 1) i++ // Needs to be 2 byte aligned now - buffer.writeUInt16BE(this.properties.source, i + 4) - buffer.writeInt16BE(this.properties.x, i + 6) - buffer.writeInt16BE(this.properties.y, i + 8) - buffer.writeUInt16BE(this.properties.size, i + 10) + buffer.writeUInt16BE(this.properties.source || 0, i + 4) + buffer.writeInt16BE(this.properties.x || 0, i + 6) + buffer.writeInt16BE(this.properties.y || 0, i + 8) + buffer.writeUInt16BE(this.properties.size || 0, i + 10) buffer.writeUInt8(this.properties.cropped ? 1 : 0, i + 12) - buffer.writeUInt16BE(this.properties.cropTop, i + 14) - buffer.writeUInt16BE(this.properties.cropBottom, i + 16) - buffer.writeUInt16BE(this.properties.cropLeft, i + 18) - buffer.writeUInt16BE(this.properties.cropRight, i + 20) + buffer.writeUInt16BE(this.properties.cropTop || 0, i + 14) + buffer.writeUInt16BE(this.properties.cropBottom || 0, i + 16) + buffer.writeUInt16BE(this.properties.cropLeft || 0, i + 18) + buffer.writeUInt16BE(this.properties.cropRight || 0, i + 20) return buffer } } export class SuperSourceBoxParametersUpdateCommand extends AbstractCommand { + static readonly rawName = 'SSBP' - rawName = 'SSBP' - ssrcId: number - boxId: number - properties: SuperSourceBox + readonly ssrcId: number + readonly boxId: number + readonly properties: Readonly - deserialize (rawCommand: Buffer, version: ProtocolVersion) { + constructor (ssrcId: number, boxId: number, properties: SuperSourceBox) { + super() + + this.ssrcId = ssrcId + this.boxId = boxId + this.properties = properties + } + + static deserialize (rawCommand: Buffer, version: ProtocolVersion): SuperSourceBoxParametersUpdateCommand { + let ssrcId = 0 let i = 0 if (version >= ProtocolVersion.V8_0) { i = 2 - this.ssrcId = rawCommand.readUInt8(0) - } else { - this.ssrcId = 0 + ssrcId = rawCommand.readUInt8(0) } - this.boxId = rawCommand.readUInt8(i > 0 ? 1 : 0) - this.properties = { + const boxId = rawCommand.readUInt8(i > 0 ? 1 : 0) + const properties = { enabled: rawCommand[i > 0 ? 2 : 1] === 1, source: rawCommand.readUInt16BE(i + 2), x: Util.parseNumberBetween(rawCommand.readInt16BE(i + 4), -4800, 4800), @@ -82,6 +98,8 @@ export class SuperSourceBoxParametersUpdateCommand extends AbstractCommand { cropLeft: Util.parseNumberBetween(rawCommand.readUInt16BE(i + 16), 0, 32000), cropRight: Util.parseNumberBetween(rawCommand.readUInt16BE(i + 18), 0, 32000) } + + return new SuperSourceBoxParametersUpdateCommand(ssrcId, boxId, properties) } applyToState (state: AtemState) { diff --git a/src/commands/SuperSource/SuperSourcePropertiesCommand.ts b/src/commands/SuperSource/SuperSourcePropertiesCommand.ts index ea789d041..ad18adf97 100644 --- a/src/commands/SuperSource/SuperSourcePropertiesCommand.ts +++ b/src/commands/SuperSource/SuperSourcePropertiesCommand.ts @@ -1,10 +1,10 @@ -import AbstractCommand from '../AbstractCommand' +import AbstractCommand, { WritableCommand } from '../AbstractCommand' import { AtemState } from '../../state' import { SuperSourceProperties, SuperSourceBorder, SuperSource } from '../../state/video' import { Util, Enums } from '../..' import { ProtocolVersion } from '../../enums' -export class SuperSourcePropertiesCommand extends AbstractCommand { +export class SuperSourcePropertiesCommand extends WritableCommand { static MaskFlags = { artFillSource: 1 << 0, artCutSource: 1 << 1, @@ -28,45 +28,43 @@ export class SuperSourcePropertiesCommand extends AbstractCommand { borderLightSourceDirection: 1 << 18, borderLightSourceAltitude: 1 << 19 } + static readonly rawName = 'CSSc' - rawName = 'CSSc' - properties: SuperSourceProperties & SuperSourceBorder - - updateProps (newProps: Partial) { - this._updateProps(newProps) + constructor () { + super() } serialize () { const buffer = Buffer.alloc(36) buffer.writeUInt32BE(this.flag, 0) - buffer.writeUInt16BE(this.properties.artFillSource, 4) - buffer.writeUInt16BE(this.properties.artCutSource, 6) - buffer.writeUInt8(this.properties.artOption, 8) + buffer.writeUInt16BE(this.properties.artFillSource || 0, 4) + buffer.writeUInt16BE(this.properties.artCutSource || 0, 6) + buffer.writeUInt8(this.properties.artOption || 0, 8) buffer.writeUInt8(this.properties.artPreMultiplied ? 1 : 0, 9) - buffer.writeUInt16BE(this.properties.artClip, 10) - buffer.writeUInt16BE(this.properties.artGain, 12) + buffer.writeUInt16BE(this.properties.artClip || 0, 10) + buffer.writeUInt16BE(this.properties.artGain || 0, 12) buffer.writeUInt8(this.properties.artInvertKey ? 1 : 0, 14) buffer.writeUInt8(this.properties.borderEnabled ? 1 : 0, 15) - buffer.writeUInt8(this.properties.borderBevel, 16) - buffer.writeUInt16BE(this.properties.borderOuterWidth, 18) - buffer.writeUInt16BE(this.properties.borderInnerWidth, 20) - buffer.writeUInt8(this.properties.borderOuterSoftness, 22) - buffer.writeUInt8(this.properties.borderInnerSoftness, 23) - buffer.writeUInt8(this.properties.borderBevelSoftness, 24) - buffer.writeUInt8(this.properties.borderBevelPosition, 25) - buffer.writeUInt16BE(this.properties.borderHue, 26) - buffer.writeUInt16BE(this.properties.borderSaturation, 28) - buffer.writeUInt16BE(this.properties.borderLuma, 30) - buffer.writeUInt16BE(this.properties.borderLightSourceDirection, 32) - buffer.writeUInt8(this.properties.borderLightSourceAltitude, 34) + buffer.writeUInt8(this.properties.borderBevel || 0, 16) + buffer.writeUInt16BE(this.properties.borderOuterWidth || 0, 18) + buffer.writeUInt16BE(this.properties.borderInnerWidth || 0, 20) + buffer.writeUInt8(this.properties.borderOuterSoftness || 0, 22) + buffer.writeUInt8(this.properties.borderInnerSoftness || 0, 23) + buffer.writeUInt8(this.properties.borderBevelSoftness || 0, 24) + buffer.writeUInt8(this.properties.borderBevelPosition || 0, 25) + buffer.writeUInt16BE(this.properties.borderHue || 0, 26) + buffer.writeUInt16BE(this.properties.borderSaturation || 0, 28) + buffer.writeUInt16BE(this.properties.borderLuma || 0, 30) + buffer.writeUInt16BE(this.properties.borderLightSourceDirection || 0, 32) + buffer.writeUInt8(this.properties.borderLightSourceAltitude || 0, 34) return buffer } } -export class SuperSourcePropertiesV8Command extends AbstractCommand { +export class SuperSourcePropertiesV8Command extends WritableCommand { static MaskFlags = { artFillSource: 1 << 0, artCutSource: 1 << 1, @@ -77,13 +75,15 @@ export class SuperSourcePropertiesV8Command extends AbstractCommand { artInvertKey: 1 << 6 } - rawName = 'CSSc' - minimumVersion = ProtocolVersion.V8_0 - ssrcId: number - properties: SuperSourceProperties + static readonly rawName = 'CSSc' + static readonly minimumVersion = ProtocolVersion.V8_0 + + readonly ssrcId: number + + constructor (ssrcId: number) { + super() - updateProps (newProps: Partial) { - this._updateProps(newProps) + this.ssrcId = ssrcId } serialize () { @@ -92,19 +92,19 @@ export class SuperSourcePropertiesV8Command extends AbstractCommand { buffer.writeUInt8(this.flag, 0) buffer.writeUInt8(this.ssrcId, 1) - buffer.writeUInt16BE(this.properties.artFillSource, 2) - buffer.writeUInt16BE(this.properties.artCutSource, 4) - buffer.writeUInt8(this.properties.artOption, 6) + buffer.writeUInt16BE(this.properties.artFillSource || 0, 2) + buffer.writeUInt16BE(this.properties.artCutSource || 0, 4) + buffer.writeUInt8(this.properties.artOption || 0, 6) buffer.writeUInt8(this.properties.artPreMultiplied ? 1 : 0, 7) - buffer.writeUInt16BE(this.properties.artClip, 8) - buffer.writeUInt16BE(this.properties.artGain, 10) + buffer.writeUInt16BE(this.properties.artClip || 0, 8) + buffer.writeUInt16BE(this.properties.artGain || 0, 10) buffer.writeUInt8(this.properties.artInvertKey ? 1 : 0, 12) return buffer } } -export class SuperSourceBorderCommand extends AbstractCommand { +export class SuperSourceBorderCommand extends WritableCommand { static MaskFlags = { borderEnabled: 1 << 0, borderBevel: 1 << 1, @@ -121,13 +121,15 @@ export class SuperSourceBorderCommand extends AbstractCommand { borderLightSourceAltitude: 1 << 12 } - rawName = 'CSBd' - minimumVersion = ProtocolVersion.V8_0 - ssrcId: number - properties: SuperSourceBorder + static readonly rawName = 'CSBd' + static readonly minimumVersion = ProtocolVersion.V8_0 - updateProps (newProps: Partial) { - this._updateProps(newProps) + readonly ssrcId: number + + constructor (ssrcId: number) { + super() + + this.ssrcId = ssrcId } serialize () { @@ -137,29 +139,36 @@ export class SuperSourceBorderCommand extends AbstractCommand { buffer.writeUInt8(this.ssrcId, 2) buffer.writeUInt8(this.properties.borderEnabled ? 1 : 0, 3) - buffer.writeUInt8(this.properties.borderBevel, 4) - buffer.writeUInt16BE(this.properties.borderOuterWidth, 6) - buffer.writeUInt16BE(this.properties.borderInnerWidth, 8) - buffer.writeUInt8(this.properties.borderOuterSoftness, 10) - buffer.writeUInt8(this.properties.borderInnerSoftness, 11) - buffer.writeUInt8(this.properties.borderBevelSoftness, 12) - buffer.writeUInt8(this.properties.borderBevelPosition, 13) - buffer.writeUInt16BE(this.properties.borderHue, 14) - buffer.writeUInt16BE(this.properties.borderSaturation, 16) - buffer.writeUInt16BE(this.properties.borderLuma, 18) - buffer.writeUInt16BE(this.properties.borderLightSourceDirection, 20) - buffer.writeUInt8(this.properties.borderLightSourceAltitude, 22) + buffer.writeUInt8(this.properties.borderBevel || 0, 4) + buffer.writeUInt16BE(this.properties.borderOuterWidth || 0, 6) + buffer.writeUInt16BE(this.properties.borderInnerWidth || 0, 8) + buffer.writeUInt8(this.properties.borderOuterSoftness || 0, 10) + buffer.writeUInt8(this.properties.borderInnerSoftness || 0, 11) + buffer.writeUInt8(this.properties.borderBevelSoftness || 0, 12) + buffer.writeUInt8(this.properties.borderBevelPosition || 0, 13) + buffer.writeUInt16BE(this.properties.borderHue || 0, 14) + buffer.writeUInt16BE(this.properties.borderSaturation || 0, 16) + buffer.writeUInt16BE(this.properties.borderLuma || 0, 18) + buffer.writeUInt16BE(this.properties.borderLightSourceDirection || 0, 20) + buffer.writeUInt8(this.properties.borderLightSourceAltitude || 0, 22) return buffer } } export class SuperSourcePropertiesUpdateCommand extends AbstractCommand { - rawName = 'SSrc' + static readonly rawName = 'SSrc' + properties: Pick - deserialize (rawCommand: Buffer) { - this.properties = { + constructor (properties: SuperSourcePropertiesUpdateCommand['properties']) { + super() + + this.properties = properties + } + + static deserialize (rawCommand: Buffer): SuperSourcePropertiesUpdateCommand { + const properties = { properties: { artFillSource: rawCommand.readUInt16BE(0), artCutSource: rawCommand.readUInt16BE(2), @@ -186,6 +195,8 @@ export class SuperSourcePropertiesUpdateCommand extends AbstractCommand { borderLightSourceAltitude: Util.parseNumberBetween(rawCommand.readUInt8(30), 0, 100) } } + + return new SuperSourcePropertiesUpdateCommand(properties) } applyToState (state: AtemState) { @@ -204,14 +215,22 @@ export class SuperSourcePropertiesUpdateCommand extends AbstractCommand { } export class SuperSourcePropertiesUpdateV8Command extends AbstractCommand { - rawName = 'SSrc' - minimumVersion = ProtocolVersion.V8_0 - ssrcId: number - properties: SuperSourceProperties - - deserialize (rawCommand: Buffer) { - this.ssrcId = rawCommand.readUInt8(0) - this.properties = { + static readonly rawName = 'SSrc' + static readonly minimumVersion = ProtocolVersion.V8_0 + + readonly ssrcId: number + readonly properties: Readonly + + constructor (ssrcId: number, properties: SuperSourceProperties) { + super() + + this.ssrcId = ssrcId + this.properties = properties + } + + static deserialize (rawCommand: Buffer): SuperSourcePropertiesUpdateV8Command { + const ssrcId = rawCommand.readUInt8(0) + const properties = { artFillSource: rawCommand.readUInt16BE(2), artCutSource: rawCommand.readUInt16BE(4), artOption: Util.parseEnum(rawCommand.readUInt8(6), Enums.SuperSourceArtOption), @@ -220,6 +239,8 @@ export class SuperSourcePropertiesUpdateV8Command extends AbstractCommand { artGain: Util.parseNumberBetween(rawCommand.readUInt16BE(10), 0, 1000), artInvertKey: rawCommand[12] === 1 } + + return new SuperSourcePropertiesUpdateV8Command(ssrcId, properties) } applyToState (state: AtemState) { @@ -232,14 +253,22 @@ export class SuperSourcePropertiesUpdateV8Command extends AbstractCommand { } export class SuperSourceBorderUpdateCommand extends AbstractCommand { - rawName = 'SSBd' - minimumVersion = ProtocolVersion.V8_0 - ssrcId: number - properties: SuperSourceBorder - - deserialize (rawCommand: Buffer) { - this.ssrcId = rawCommand.readUInt8(0) - this.properties = { + static readonly rawName = 'SSBd' + static readonly minimumVersion = ProtocolVersion.V8_0 + + readonly ssrcId: number + readonly properties: Readonly + + constructor (ssrcId: number, properties: SuperSourceBorder) { + super() + + this.ssrcId = ssrcId + this.properties = properties + } + + static deserialize (rawCommand: Buffer) { + const ssrcId = rawCommand.readUInt8(0) + const properties = { borderEnabled: rawCommand[1] === 1, borderBevel: Util.parseEnum(rawCommand.readUInt8(2), Enums.BorderBevel), borderOuterWidth: Util.parseNumberBetween(rawCommand.readUInt16BE(4), 0, 1600), @@ -254,6 +283,8 @@ export class SuperSourceBorderUpdateCommand extends AbstractCommand { borderLightSourceDirection: Util.parseNumberBetween(rawCommand.readUInt16BE(18), 0, 3599), borderLightSourceAltitude: Util.parseNumberBetween(rawCommand.readUInt8(20), 0, 100) } + + return new SuperSourceBorderUpdateCommand(ssrcId, properties) } applyToState (state: AtemState) { diff --git a/src/commands/__tests__/data-v7.2.json b/src/commands/__tests__/data-v7.2.json index 5a323f283..5ad18cdfb 100644 --- a/src/commands/__tests__/data-v7.2.json +++ b/src/commands/__tests__/data-v7.2.json @@ -8521,7 +8521,7 @@ }, { "name": "MPSS", - "bytes": "00-10-00-00-4D-50-53-53-02-03-02-37-7F-00-00-00", + "bytes": "00-10-00-00-4D-50-53-53-02-03-02-7F-37-00-00-00", "command": { "Mask": 2, "Index": 3, @@ -8532,7 +8532,7 @@ }, { "name": "MPSS", - "bytes": "00-10-00-00-4D-50-53-53-01-02-02-E0-1C-00-00-00", + "bytes": "00-10-00-00-4D-50-53-53-01-02-02-1C-E0-00-00-00", "command": { "Mask": 1, "Index": 2, @@ -8543,7 +8543,7 @@ }, { "name": "MPSS", - "bytes": "00-10-00-00-4D-50-53-53-02-03-02-24-52-00-00-00", + "bytes": "00-10-00-00-4D-50-53-53-02-03-02-52-24-00-00-00", "command": { "Mask": 2, "Index": 3, @@ -8554,7 +8554,7 @@ }, { "name": "MPSS", - "bytes": "00-10-00-00-4D-50-53-53-01-03-01-2E-1B-00-00-00", + "bytes": "00-10-00-00-4D-50-53-53-01-03-01-1B-2E-00-00-00", "command": { "Mask": 1, "Index": 3, @@ -8565,7 +8565,7 @@ }, { "name": "MPSS", - "bytes": "00-10-00-00-4D-50-53-53-02-02-02-C0-47-00-00-00", + "bytes": "00-10-00-00-4D-50-53-53-02-02-02-47-C0-00-00-00", "command": { "Mask": 2, "Index": 2, @@ -8576,7 +8576,7 @@ }, { "name": "MPSS", - "bytes": "00-10-00-00-4D-50-53-53-01-01-01-17-A2-00-00-00", + "bytes": "00-10-00-00-4D-50-53-53-01-01-01-A2-17-00-00-00", "command": { "Mask": 1, "Index": 1, @@ -8587,7 +8587,7 @@ }, { "name": "MPSS", - "bytes": "00-10-00-00-4D-50-53-53-01-00-02-0D-D8-00-00-00", + "bytes": "00-10-00-00-4D-50-53-53-01-00-02-D8-0D-00-00-00", "command": { "Mask": 1, "Index": 0, @@ -8598,7 +8598,7 @@ }, { "name": "MPSS", - "bytes": "00-10-00-00-4D-50-53-53-02-03-01-58-BF-00-00-00", + "bytes": "00-10-00-00-4D-50-53-53-02-03-01-BF-58-00-00-00", "command": { "Mask": 2, "Index": 3, @@ -8609,7 +8609,7 @@ }, { "name": "MPSS", - "bytes": "00-10-00-00-4D-50-53-53-04-01-02-B0-8F-00-00-00", + "bytes": "00-10-00-00-4D-50-53-53-04-01-02-8F-B0-00-00-00", "command": { "Mask": 4, "Index": 1, @@ -8620,7 +8620,7 @@ }, { "name": "MPSS", - "bytes": "00-10-00-00-4D-50-53-53-01-03-02-95-F9-00-00-00", + "bytes": "00-10-00-00-4D-50-53-53-01-03-02-F9-95-00-00-00", "command": { "Mask": 1, "Index": 3, diff --git a/src/commands/__tests__/util.ts b/src/commands/__tests__/util.ts index 90917923a..d2278e042 100644 --- a/src/commands/__tests__/util.ts +++ b/src/commands/__tests__/util.ts @@ -1,5 +1,6 @@ import { CommandParser } from '../../lib/atemCommandParser' import { ProtocolVersion } from '../../enums' +import { AbstractCommand } from '..'; export type CommandTestConverterSet = { [key: string]: CommandTestConverter } export interface CommandTestConverter { @@ -15,11 +16,11 @@ export interface TestCase { } export function runTestForCommand (commandParser: CommandParser, commandConverters: CommandTestConverterSet, i: number, testCase: TestCase, allowUnknown?: boolean) { - const cmd = commandParser.commandFromRawName(testCase.name) - if (!cmd && allowUnknown) return + const cmdConstructor = commandParser.commandFromRawName(testCase.name) + if (!cmdConstructor && allowUnknown) return let matchedCase = false - if (cmd) { + if (cmdConstructor) { const buffer = Buffer.from(testCase.bytes.replace(/-/g, ''), 'hex') const length = buffer.readUInt16BE(0) const name = buffer.toString('ascii', 4, 8) @@ -38,14 +39,13 @@ export function runTestForCommand (commandParser: CommandParser, commandConverte mutatedCommand = converter.customMutate(mutatedCommand) } - if (typeof cmd.deserialize === 'function') { + if (typeof cmdConstructor.deserialize === 'function') { matchedCase = true test(`Test #${i}: ${testCase.name} - Deserialize`, () => { - cmd.deserialize!(buffer.slice(0, length).slice(8), commandParser.version) + const cmd: AbstractCommand = cmdConstructor.deserialize!(buffer.slice(0, length).slice(8), commandParser.version) delete cmd.flag // Anything deserialized will never have flags - delete cmd.rawName - delete (cmd as any).rawCommand + // delete (cmd as any).rawCommand if (converter) { for (const key in cmd) { @@ -61,6 +61,7 @@ export function runTestForCommand (commandParser: CommandParser, commandConverte }) } + const cmd: AbstractCommand = new cmdConstructor() // TODO - params if (typeof cmd.serialize === 'function') { matchedCase = true test(`Test #${i}: ${testCase.name} - Serialize`, () => { @@ -112,8 +113,7 @@ export function ensureAllCommandsCovered (commandParser: CommandParser, testCase let knownNames: string[] = [] for (const name of Object.keys(commandParser.commands)) { for (const cmd of commandParser.commands[name]) { - const inst = new cmd() - if ((expectUndefined && !inst.minimumVersion) || inst.minimumVersion === commandParser.version) { + if ((expectUndefined && !cmd.minimumVersion) || cmd.minimumVersion === commandParser.version) { knownNames.push(name) } } diff --git a/src/dataTransfer/dataLock.ts b/src/dataTransfer/dataLock.ts index f3f06b617..00fe62bbd 100644 --- a/src/dataTransfer/dataLock.ts +++ b/src/dataTransfer/dataLock.ts @@ -60,7 +60,7 @@ export default class DataLock { transferFinished () { if (this.transfer && this.transfer.state === Enums.TransferState.Finished) { - this.transfer.finish(this.transfer) + this.transfer.resolvePromise(this.transfer) } if (this.queue.length > 0) { @@ -100,21 +100,12 @@ export default class DataLock { } _getLock () { - const command = new Commands.LockStateCommand() - command.updateProps({ - index: this.storeId, - locked: true - }) - + const command = new Commands.LockStateCommand(this.storeId, true) this.commandQueue.push(command) } _releaseLock () { - const command = new Commands.LockStateCommand() - command.updateProps({ - index: this.storeId, - locked: false - }) + const command = new Commands.LockStateCommand(this.storeId, false) this.commandQueue.push(command) } } diff --git a/src/dataTransfer/dataTransfer.ts b/src/dataTransfer/dataTransfer.ts index 3f20c3075..ceb7d5ea4 100644 --- a/src/dataTransfer/dataTransfer.ts +++ b/src/dataTransfer/dataTransfer.ts @@ -1,15 +1,38 @@ import { Commands, Enums } from '..' export default abstract class DataTransfer { - startedAt: Date state: Enums.TransferState = Enums.TransferState.Queued - transferId: number - storeId: number + readonly transferId: number + readonly storeId: number commandQueue: Array - finish: (transfer: DataTransfer) => void - fail: (error: Error) => void + private readonly completionPromise: Promise + resolvePromise: (value?: DataTransfer | PromiseLike | undefined) => void + rejectPromise: (reason?: any) => void + + constructor (transferId: number, storeId: number) { + this.transferId = transferId + this.storeId = storeId + + // Make typescript happy + // tslint:disable-next-line: no-empty + this.resolvePromise = () => {} + // tslint:disable-next-line: no-empty + this.rejectPromise = () => {} + + this.completionPromise = new Promise((resolve, reject) => { + this.resolvePromise = resolve + this.rejectPromise = reject + }) + } + + get promise () { + return this.completionPromise + } + + fail(..._args: any[]): void{} // TODO remove + abstract start (): void abstract handleCommand (command: Commands.AbstractCommand): void diff --git a/src/dataTransfer/dataTransferAudio.ts b/src/dataTransfer/dataTransferAudio.ts index 45a7b628a..59a0fab75 100644 --- a/src/dataTransfer/dataTransferAudio.ts +++ b/src/dataTransfer/dataTransferAudio.ts @@ -3,7 +3,13 @@ import { Commands, Enums } from '..' import DataTransferFrame from './dataTransferFrame' export default class DataTransferAudio extends DataTransferFrame { - description: { name: string } + readonly name: string + + constructor (transferId: number, storeId: number, data: Buffer, name: string) { + super(transferId, storeId, 0, data) + + this.name = name + } start () { const command = new Commands.DataTransferUploadRequestCommand() @@ -19,7 +25,7 @@ export default class DataTransferAudio extends DataTransferFrame { sendDescription () { const command = new Commands.DataTransferFileDescriptionCommand() - command.updateProps({ ...this.description, fileHash: this.hash, transferId: this.transferId }) + command.updateProps({ name: this.name, fileHash: this.hash, transferId: this.transferId }) this.commandQueue.push(command) } } diff --git a/src/dataTransfer/dataTransferClip.ts b/src/dataTransfer/dataTransferClip.ts index 64ba8dfae..eaaee4537 100644 --- a/src/dataTransfer/dataTransferClip.ts +++ b/src/dataTransfer/dataTransferClip.ts @@ -4,10 +4,17 @@ import DataTransfer from './dataTransfer' import DataTransferFrame from './dataTransferFrame' export default class DataTransferClip extends DataTransfer { - clipIndex: number // 0 or 1 + readonly clipIndex: number // 0 or 1 frames: Array = [] curFrame = 0 - description: { name: string } + readonly name: string + + constructor (clipIndex: number, name: string) { + super(0, 1 + clipIndex) + + this.clipIndex = clipIndex + this.name = name + } start () { const clearMediaCommand = new Commands.MediaPoolClearClipCommand() @@ -31,7 +38,7 @@ export default class DataTransferClip extends DataTransfer { const command = new Commands.MediaPoolSetClipCommand() command.updateProps({ index: this.clipIndex, - name: this.description.name, + name: this.name, frames: this.frames.length }) this.commandQueue.push(command) diff --git a/src/dataTransfer/dataTransferFrame.ts b/src/dataTransfer/dataTransferFrame.ts index 30ccaf5eb..23cd9b4f9 100644 --- a/src/dataTransfer/dataTransferFrame.ts +++ b/src/dataTransfer/dataTransferFrame.ts @@ -4,13 +4,21 @@ import * as crypto from 'crypto' import DataTransfer from './dataTransfer' export default class DataTransferFrame extends DataTransfer { - frameId: number - hash: string + readonly frameId: number + readonly hash: string + readonly data: Buffer - lastSent: Date - data: Buffer + lastSent?: Date _sent = 0 + constructor (transferId: number, storeId: number, frameId: number, data: Buffer) { + super(transferId, storeId) + + this.frameId = frameId + this.data = data + this.hash = this.data ? crypto.createHash('md5').update(this.data).digest().toString() : '' + } + start () { const command = new Commands.DataTransferUploadRequestCommand() command.updateProps({ @@ -18,15 +26,12 @@ export default class DataTransferFrame extends DataTransfer { transferStoreId: this.storeId, transferIndex: this.frameId, size: this.data.length, - mode: Enums.TransferMode.Write + mode: Enums.TransferMode.TEST }) this.commandQueue.push(command) } sendDescription () { - if (!this.hash) { - this.setHash() - } const command = new Commands.DataTransferFileDescriptionCommand() command.updateProps({ fileHash: this.hash, transferId: this.transferId }) this.commandQueue.push(command) @@ -57,8 +62,7 @@ export default class DataTransferFrame extends DataTransfer { for (let i = 0; i < chunkCount; i++) { if (this._sent > this.data.length) return - const command = new Commands.DataTransferDataCommand() - command.updateProps({ + const command = new Commands.DataTransferDataCommand({ transferId: this.transferId, body: this.data.slice(this._sent, this._sent + chunkSize) }) @@ -66,10 +70,4 @@ export default class DataTransferFrame extends DataTransfer { this._sent += chunkSize } } - - setHash () { - if (this.data) { - this.hash = crypto.createHash('md5').update(this.data).digest().toString() - } - } } diff --git a/src/dataTransfer/dataTransferStill.ts b/src/dataTransfer/dataTransferStill.ts index 4aa663f1a..487e3e6f9 100644 --- a/src/dataTransfer/dataTransferStill.ts +++ b/src/dataTransfer/dataTransferStill.ts @@ -3,11 +3,19 @@ import { Commands } from '..' import DataTransferFrame from './dataTransferFrame' export default class DataTransferStill extends DataTransferFrame { - description: { name: string, description: string } + readonly name: string + readonly description: string + + constructor (transferId: number, frameId: number, data: Buffer, name: string, description: string) { + super(transferId, 0xffff, frameId, data) + + this.name = name + this.description = description + } sendDescription () { const command = new Commands.DataTransferFileDescriptionCommand() - command.updateProps({ ...this.description, fileHash: this.hash, transferId: this.transferId }) + command.updateProps({ description: this.description, name: this.name, fileHash: this.hash, transferId: this.transferId }) this.commandQueue.push(command) } } diff --git a/src/dataTransfer/index.ts b/src/dataTransfer/index.ts index 873ff6c41..35f92d4a6 100644 --- a/src/dataTransfer/index.ts +++ b/src/dataTransfer/index.ts @@ -1,5 +1,4 @@ import { Commands, Enums } from '..' -import * as crypto from 'crypto' import DataLock from './dataLock' import DataTransferFrame from './dataTransferFrame' @@ -89,46 +88,23 @@ export class DataTransferManager { } uploadStill (index: number, data: Buffer, name: string, description: string) { - const transfer = new DataTransferStill() - const ps = new Promise((resolve, reject) => { - transfer.finish = resolve - transfer.fail = reject - }) - + const transfer = new DataTransferStill(this.transferIndex++, index, data, name, description) transfer.commandQueue = this.commandQueue - transfer.transferId = this.transferIndex++ - transfer.storeId = 0 - transfer.frameId = index - transfer.data = data - transfer.hash = crypto.createHash('md5').update(data).digest().toString() - transfer.description = { name, description } this.stillsLock.enqueue(transfer) - return ps + return transfer.promise } uploadClip (index: number, data: Array, name: string) { - const transfer = new DataTransferClip() - const ps = new Promise((resolve, reject) => { - transfer.finish = resolve - transfer.fail = reject - }) - + const transfer = new DataTransferClip(1 + index, name) transfer.commandQueue = this.commandQueue - transfer.storeId = 1 + index - transfer.clipIndex = index - transfer.description = { name } for (const frameId in data) { const frame = data[frameId] - const frameTransfer = new DataTransferFrame() + const frameTransfer = new DataTransferFrame(this.transferIndex++, 1 + index, Number(frameId), frame) frameTransfer.commandQueue = this.commandQueue - frameTransfer.transferId = this.transferIndex++ - frameTransfer.storeId = 1 + index - frameTransfer.frameId = Number(frameId) - frameTransfer.data = frame // frameTransfer.hash = crypto.createHash('md5').update(frame).digest().toString() transfer.frames.push(frameTransfer) @@ -136,26 +112,16 @@ export class DataTransferManager { [ this.clip1Lock, this.clip2Lock ][index].enqueue(transfer) - return ps + return transfer.promise } uploadAudio (index: number, data: Buffer, name: string) { - const transfer = new DataTransferAudio() - const ps = new Promise((resolve, reject) => { - transfer.finish = resolve - transfer.fail = reject - }) - + const transfer = new DataTransferAudio(this.transferIndex++, 1 + index, data, name) transfer.commandQueue = this.commandQueue - transfer.transferId = this.transferIndex++ - transfer.storeId = 1 + index - transfer.description = { name } - transfer.data = data - transfer.hash = crypto.createHash('md5').update(data).digest().toString() ;[ this.clip1Lock, this.clip2Lock ][index].enqueue(transfer) - return ps + return transfer.promise } } diff --git a/src/enums/index.ts b/src/enums/index.ts index 63ffdbc20..e3b785309 100644 --- a/src/enums/index.ts +++ b/src/enums/index.ts @@ -213,7 +213,8 @@ export enum TransferMode { NoOp, Write, Clear, - WriteAudio = 256 + WriteAudio = 256, + TEST = 0x0201 } export enum StoragePool { diff --git a/src/lib/atemCommandParser.ts b/src/lib/atemCommandParser.ts index 4df57d760..9ba0cbe9d 100644 --- a/src/lib/atemCommandParser.ts +++ b/src/lib/atemCommandParser.ts @@ -1,8 +1,7 @@ import * as Commands from '../commands' -import AbstractCommand from '../commands/AbstractCommand' import { ProtocolVersion } from '../enums' -type CommandConstructor = new () => AbstractCommand +type CommandConstructor = any export class CommandParser { commands: {[key: string]: Array} = {} version: ProtocolVersion = ProtocolVersion.V7_2 // Default to the minimum supported @@ -10,8 +9,8 @@ export class CommandParser { constructor () { for (const cmd in Commands) { try { - const cmdConstructor = (Commands as any)[cmd] as CommandConstructor - const rawName = new cmdConstructor().rawName + const cmdConstructor = (Commands as any)[cmd] + const rawName = cmdConstructor.rawName if (rawName) { if (!this.commands[rawName]) this.commands[rawName] = [] this.commands[rawName].push(cmdConstructor) @@ -22,12 +21,9 @@ export class CommandParser { } } - commandFromRawName (name: string): AbstractCommand | undefined { - const commandsArray = this.commands[name] - if (commandsArray) { - // instantiate all commands in the array for access to the version prop: - const commands = commandsArray.map(cmd => new (cmd as any)()) - + commandFromRawName (name: string): CommandConstructor | undefined { + const commands = this.commands[name] + if (commands) { if (!this.version) { // edge case for the version command itself: return commands[0] } else { // now we should have a version defined diff --git a/src/lib/atemSocket.ts b/src/lib/atemSocket.ts index c61050d32..0dce1d707 100644 --- a/src/lib/atemSocket.ts +++ b/src/lib/atemSocket.ts @@ -83,7 +83,7 @@ export class AtemSocket extends EventEmitter { const payload = command.serialize(this._commandParser.version) const fullPayload = Buffer.alloc(payload.length + 8, 0) fullPayload.writeUInt16BE(fullPayload.length, 0) - fullPayload.write(command.rawName, 4, 4) + fullPayload.write((command.constructor as any).rawName, 4, 4) payload.copy(fullPayload, 8, 0) if (this._debug) this.log('PAYLOAD', fullPayload) @@ -177,10 +177,10 @@ export class AtemSocket extends EventEmitter { } // this.log('COMMAND', `${name}(${length})`, buffer.slice(0, length)) - const cmd = this._commandParser.commandFromRawName(name) - if (cmd && typeof cmd.deserialize === 'function') { + const cmdConstructor = this._commandParser.commandFromRawName(name) + if (cmdConstructor && typeof cmdConstructor.deserialize === 'function') { try { - cmd.deserialize(buffer.slice(0, length).slice(8), this._commandParser.version) + const cmd: AbstractCommand = cmdConstructor.deserialize(buffer.slice(0, length).slice(8), this._commandParser.version) cmd.packetId = packetId || -1 if (name === '_ver') { // init started diff --git a/src/lib/atemSocketChild.ts b/src/lib/atemSocketChild.ts index 1f6781409..ab1293a15 100644 --- a/src/lib/atemSocketChild.ts +++ b/src/lib/atemSocketChild.ts @@ -13,7 +13,7 @@ export class AtemSocketChild extends EventEmitter { private _localPacketId = 1 private _maxPacketID = (1 << 15) - 1 // Atem expects 15 not 16 bits before wrapping - private _sessionId: number + private _sessionId: number = 0 private _address: string private _port: number = 9910 @@ -32,7 +32,7 @@ export class AtemSocketChild extends EventEmitter { constructor (options: { address?: string, port?: number } = {}) { super() - this._address = options.address || this._address + this._address = options.address || '' this._port = options.port || this._port this._createSocket() } diff --git a/src/state/info.ts b/src/state/info.ts index 79945be19..38dd825ea 100644 --- a/src/state/info.ts +++ b/src/state/info.ts @@ -1,10 +1,5 @@ import { Model, ProtocolVersion } from '../enums' -export interface VersionProps { - readonly major: number - readonly minor: number -} - export interface AtemCapabilites { readonly MEs: number readonly sources: number diff --git a/src/state/macro.ts b/src/state/macro.ts index f0b77a6b4..21459fb82 100644 --- a/src/state/macro.ts +++ b/src/state/macro.ts @@ -21,4 +21,17 @@ export class MacroState { macroPlayer: MacroPlayerState macroRecorder: MacroRecorderState macroProperties: Array = [] + + constructor () { + this.macroPlayer = { + isRunning: false, + isWaiting: false, + loop: false, + macroIndex: 0 + } + this.macroRecorder = { + isRecording: false, + macroIndex: 0 + } + } } diff --git a/src/state/media.ts b/src/state/media.ts index f647a7626..ba5aa7732 100644 --- a/src/state/media.ts +++ b/src/state/media.ts @@ -19,15 +19,15 @@ export class MediaState { players: Array = [] } -export class StillFrame { +export interface StillFrame { isUsed: boolean hash: string fileName: string } -export class ClipBank { +export interface ClipBank { isUsed: boolean name: string frameCount: number - frames: Array = [] + frames: Array } diff --git a/src/state/settings.ts b/src/state/settings.ts index 8500106b7..3441fbea5 100644 --- a/src/state/settings.ts +++ b/src/state/settings.ts @@ -11,8 +11,6 @@ export interface MultiViewerWindowState extends MultiViewerSourceState { export class MultiViewer { index: number - layout: number - overlayOpacity: number windows: { [index: string]: MultiViewerWindowState } = {} constructor (index: number) { @@ -32,6 +30,10 @@ export class SettingsState { multiViewers: { [index: string]: MultiViewer } = {} videoMode: number + constructor () { + this.videoMode = 0 + } + getMultiViewer (index: number) { if (!this.multiViewers[index]) { this.multiViewers[index] = new MultiViewer(index) diff --git a/src/state/video/index.ts b/src/state/video/index.ts index 60955c97b..23b384fc1 100644 --- a/src/state/video/index.ts +++ b/src/state/video/index.ts @@ -85,32 +85,45 @@ export interface IMixEffect { export class MixEffect implements IMixEffect { index: number - programInput: number - previewInput: number - inTransition: boolean - transitionPreview: boolean - transitionPosition: number - transitionFramesLeft: number + programInput: number = 0 + previewInput: number = 0 + inTransition: boolean = false + transitionPreview: boolean = false + transitionPosition: number = 0 + transitionFramesLeft: number = 0 fadeToBlack: FadeToBlackProperties - numberOfKeyers: number - transitionProperties: TransitionProperties = {} as TransitionProperties - transitionSettings: TransitionSettings = {} as TransitionSettings + numberOfKeyers: number = 0 + transitionProperties: TransitionProperties + transitionSettings: TransitionSettings = {} as any upstreamKeyers: { [index: number]: USK.UpstreamKeyer } = [] constructor (index: number) { this.index = index + + this.fadeToBlack = { + isFullyBlack: false, + rate: 0, + inTransition: false, + remainingFrames: 0 + } + this.transitionProperties = { + style: Enum.TransitionStyle.MIX, + selection: 0, + nextStyle: Enum.TransitionStyle.MIX, + nextSelection: 0 + } } getUpstreamKeyer (index: number) { if (!this.upstreamKeyers[index]) { this.upstreamKeyers[index] = { - dveSettings: {} as USK.UpstreamKeyerDVESettings, - chromaSettings: {} as USK.UpstreamKeyerChromaSettings, - lumaSettings: {} as USK.UpstreamKeyerLumaSettings, - patternSettings: {} as USK.UpstreamKeyerPatternSettings, - flyKeyframes: [] as { [index: number]: USK.UpstreamKeyerFlyKeyframe }, - flyProperties: {} as USK.UpstreamKeyerFlySettings - } as USK.UpstreamKeyer + dveSettings: {} as any, + chromaSettings: {} as any, + lumaSettings: {} as any, + patternSettings: {} as any, + flyKeyframes: [], + flyProperties: {} as any + } as any } return this.upstreamKeyers[index] @@ -158,12 +171,37 @@ export interface SuperSourceBorder { export class SuperSource { index: number - boxes: { [index: string]: SuperSourceBox } = {} + boxes: { [index: string]: SuperSourceBox | undefined } = {} properties: SuperSourceProperties border: SuperSourceBorder constructor (index: number) { this.index = index + + this.properties = { + artFillSource: 0, + artCutSource: 0, + artOption: Enum.SuperSourceArtOption.Background, + artPreMultiplied: false, + artClip: 0, + artGain: 0, + artInvertKey: false + } + this.border = { + borderEnabled: false, + borderBevel: Enum.BorderBevel.None, + borderOuterWidth: 0, + borderInnerWidth: 0, + borderOuterSoftness: 0, + borderInnerSoftness: 0, + borderBevelSoftness: 0, + borderBevelPosition: 0, + borderHue: 0, + borderSaturation: 0, + borderLuma: 0, + borderLightSourceDirection: 0, + borderLightSourceAltitude: 0 + } } } @@ -175,32 +213,35 @@ export interface FadeToBlackProperties { } export class AtemVideoState { - ME: { [index: string]: MixEffect } = {} - downstreamKeyers: { [index: string]: DownstreamKeyer } = {} - auxilliaries: { [index: string]: number } = {} - superSources: { [index: string]: SuperSource } = {} - - getMe (index: number) { - if (!this.ME[index]) { - this.ME[index] = new MixEffect(index) + ME: { [index: string]: MixEffect | undefined } = {} + downstreamKeyers: { [index: string]: DownstreamKeyer | undefined } = {} + auxilliaries: { [index: string]: number | undefined } = {} + superSources: { [index: string]: SuperSource | undefined } = {} + + getMe (index: number): MixEffect { + let me = this.ME[index] + if (!me) { + me = this.ME[index] = new MixEffect(index) } - return this.ME[index] + return me } - getSuperSource (index: number) { - if (!this.superSources[index]) { - this.superSources[index] = new SuperSource(index) + getSuperSource (index: number): SuperSource { + let ssrc = this.superSources[index] + if (!ssrc) { + ssrc = this.superSources[index] = new SuperSource(index) } - return this.superSources[index] + return ssrc } - getDownstreamKeyer (index: number) { - if (!this.downstreamKeyers[index]) { - this.downstreamKeyers[index] = {} as DownstreamKeyer + getDownstreamKeyer (index: number): DownstreamKeyer { + let dsk = this.downstreamKeyers[index] + if (!dsk) { + dsk = this.downstreamKeyers[index] = {} as DownstreamKeyer } - return this.downstreamKeyers[index] + return dsk } } From e9a4c2f6be402c9bec8a2e783c509fc80364b72b Mon Sep 17 00:00:00 2001 From: Julian Waller Date: Mon, 7 Oct 2019 21:20:20 +0100 Subject: [PATCH 02/68] wip: replace AbstractCommand with better typed abstract classes --- config/tsconfig.strict.json | 3 +- src/atem.ts | 150 +++++++----------- src/commands/AbstractCommand.ts | 85 ---------- src/commands/Audio/AudioMixerInputCommand.ts | 11 +- src/commands/Audio/AudioMixerMasterCommand.ts | 22 +-- src/commands/AuxSourceCommand.ts | 26 ++- src/commands/CommandBase.ts | 70 ++++++++ .../DataTransfer/DataTransferAckCommand.ts | 25 ++- .../DataTransferCompleteCommand.ts | 19 +-- .../DataTransfer/DataTransferDataCommand.ts | 25 ++- .../DataTransferDownloadRequestCommand.ts | 16 +- .../DataTransfer/DataTransferErrorCommand.ts | 25 ++- .../DataTransferFileDescriptionCommand.ts | 18 +-- .../DataTransferUploadContinueCommand.ts | 27 ++-- .../DataTransferUploadRequestCommand.ts | 20 +-- .../DataTransfer/LockObtainedCommand.ts | 25 ++- src/commands/DataTransfer/LockStateCommand.ts | 36 ++--- .../DeviceProfile/productIdentifierCommand.ts | 20 +-- .../DeviceProfile/superSourceConfigCommand.ts | 12 +- src/commands/DeviceProfile/topologyCommand.ts | 12 +- src/commands/DeviceProfile/versionCommand.ts | 20 +-- .../DownstreamKey/DownstreamKeyAutoCommand.ts | 20 ++- .../DownstreamKeyCutSourceCommand.ts | 18 +-- .../DownstreamKeyFillSourceCommand.ts | 18 +-- .../DownstreamKeyGeneralCommand.ts | 22 +-- .../DownstreamKey/DownstreamKeyMaskCommand.ts | 26 +-- .../DownstreamKeyOnAirCommand.ts | 13 +- .../DownstreamKeyPropertiesCommand.ts | 8 +- .../DownstreamKey/DownstreamKeyRateCommand.ts | 18 +-- .../DownstreamKeySourcesCommand.ts | 14 +- .../DownstreamKeyStateCommand.ts | 14 +- .../DownstreamKey/DownstreamKeyTieCommand.ts | 13 +- src/commands/InitCompleteCommand.ts | 9 +- src/commands/Inputs/InputPropertiesCommand.ts | 15 +- src/commands/Macro/MacroActionCommand.ts | 13 +- src/commands/Macro/MacroPropertiesCommand.ts | 8 +- .../Macro/MacroRecordingStatusCommand.ts | 12 +- src/commands/Macro/MacroRunStatusCommand.ts | 12 +- .../Media/MediaPlayerSourceCommand.ts | 16 +- .../Media/MediaPlayerStatusCommand.ts | 16 +- .../Media/MediaPoolClearClipCommand.ts | 12 +- .../Media/MediaPoolClearStillCommand.ts | 12 +- .../Media/MediaPoolClipDescription.ts | 8 +- .../Media/MediaPoolFrameDescription.ts | 10 +- src/commands/Media/MediaPoolSetClipCommand.ts | 16 +- .../MixEffects/AutoTransitionCommand.ts | 13 +- src/commands/MixEffects/CutCommand.ts | 13 +- .../FadeToBlack/FadeToBlackAutoCommand.ts | 13 +- .../FadeToBlack/FadeToBlackRateCommand.ts | 25 +-- .../FadeToBlack/FadeToBlackStateCommand.ts | 20 +-- .../Key/MixEffectKeyChromaCommand.ts | 12 +- .../Key/MixEffectKeyCutSourceSetCommand.ts | 17 +- .../MixEffects/Key/MixEffectKeyDVECommand.ts | 11 +- .../Key/MixEffectKeyFillSourceSetCommand.ts | 17 +- .../Key/MixEffectKeyFlyKeyframeGetCommand.ts | 8 +- .../MixEffectKeyFlyPropertiesGetCommand.ts | 8 +- .../MixEffects/Key/MixEffectKeyLumaCommand.ts | 12 +- .../Key/MixEffectKeyMaskSetCommand.ts | 25 +-- .../Key/MixEffectKeyOnAirCommand.ts | 18 +-- .../Key/MixEffectKeyPatternCommand.ts | 8 +- .../Key/MixEffectKeyPropertiesGetCommand.ts | 8 +- .../Key/MixEffectKeyTypeSetCommand.ts | 19 ++- .../MixEffects/PreviewInputCommand.ts | 15 +- .../MixEffects/ProgramInputCommand.ts | 16 +- .../Transition/TransitionDVECommand.ts | 8 +- .../Transition/TransitionDipCommand.ts | 8 +- .../Transition/TransitionMixCommand.ts | 8 +- .../Transition/TransitionPositionCommand.ts | 22 ++- .../Transition/TransitionPreviewCommand.ts | 11 +- .../Transition/TransitionPropertiesCommand.ts | 8 +- .../Transition/TransitionStingerCommand.ts | 8 +- .../Transition/TransitionWipeCommand.ts | 8 +- src/commands/PowerStatusCommand.ts | 12 +- .../Settings/MultiViewerSourceCommand.ts | 8 +- src/commands/Settings/VideoMode.ts | 18 +-- .../SuperSourceBoxParametersCommand.ts | 16 +- .../SuperSourcePropertiesCommand.ts | 24 +-- src/commands/__tests__/util.ts | 17 +- src/commands/index.ts | 4 +- src/dataTransfer/dataLock.ts | 4 +- src/dataTransfer/dataTransfer.ts | 6 +- src/dataTransfer/dataTransferClip.ts | 4 +- src/dataTransfer/dataTransferFrame.ts | 8 +- src/dataTransfer/index.ts | 7 +- src/lib/atemSocket.ts | 10 +- src/state/video/index.ts | 2 +- 86 files changed, 631 insertions(+), 878 deletions(-) delete mode 100644 src/commands/AbstractCommand.ts create mode 100644 src/commands/CommandBase.ts diff --git a/config/tsconfig.strict.json b/config/tsconfig.strict.json index 1b9ab37b3..35e6f3cc4 100644 --- a/config/tsconfig.strict.json +++ b/config/tsconfig.strict.json @@ -2,8 +2,7 @@ "compilerOptions": { "strict": true, "alwaysStrict": false, - "strictNullChecks": true, - "strictPropertyInitialization": false, + "strictPropertyInitialization": true, "strictFunctionTypes": true, "forceConsistentCasingInFileNames": true, "noFallthroughCasesInSwitch": true, diff --git a/src/atem.ts b/src/atem.ts index 8d2715f95..1c493e8d2 100644 --- a/src/atem.ts +++ b/src/atem.ts @@ -1,7 +1,7 @@ import { EventEmitter } from 'events' import { AtemState } from './state' import { AtemSocket } from './lib/atemSocket' -import AbstractCommand from './commands/AbstractCommand' +import { ISerializableCommand, IDeserializedCommand } from './commands/CommandBase' import * as Commands from './commands' import * as DataTransferCommands from './commands/DataTransfer' import { MediaPlayer, MediaPlayerSource } from './state/media' @@ -25,7 +25,7 @@ import { Util } from './lib/atemUtil' import * as Enums from './enums' import { AudioChannel, AudioMasterChannel } from './state/audio' import exitHook = require('exit-hook') -import { isArray } from 'util' +import { isArray, isFunction } from 'util' export interface AtemOptions { address?: string, @@ -41,12 +41,11 @@ export class Atem extends EventEmitter { AUDIO_GAIN_RATE = 65381 - event: EventEmitter - state: AtemState + private _state: AtemState private socket: AtemSocket private dataTransferManager: DT.DataTransferManager private _log: (...args: any[]) => void - private _sentQueue: {[packetId: string]: AbstractCommand } = {} + private _sentQueue: {[packetId: string]: ISerializableCommand } = {} on: ((event: 'error', listener: (message: any) => void) => this) & ((event: 'connected', listener: () => void) => this) & @@ -57,12 +56,12 @@ export class Atem extends EventEmitter { super() if (options) { this.DEBUG = options.debug === undefined ? false : options.debug - this._log = options.externalLog || function (...args: any[]): void { - console.log(...args) - } + } + this._log = (options && options.externalLog) || function (...args: any[]): void { + console.log(...args) } - this.state = new AtemState() + this._state = new AtemState() this.socket = new AtemSocket({ debug: this.DEBUG, log: this._log, @@ -70,7 +69,7 @@ export class Atem extends EventEmitter { port: (options || {}).port }) this.dataTransferManager = new DT.DataTransferManager( - (command: AbstractCommand) => this.sendCommand(command) + (command: ISerializableCommand) => this.sendCommand(command) ) // When the parent process begins exiting, remove the listeners on our child process. @@ -82,7 +81,7 @@ export class Atem extends EventEmitter { } }) - this.socket.on('receivedStateChange', (command: AbstractCommand) => this._mutateState(command)) + this.socket.on('receivedStateChange', (command: IDeserializedCommand) => this._mutateState(command)) this.socket.on(Enums.IPCMessageType.CommandAcknowledged, ({ trackingId }: {trackingId: number}) => this._resolveCommand(trackingId)) this.socket.on(Enums.IPCMessageType.CommandTimeout, ({ trackingId }: {trackingId: number}) => this._rejectCommand(trackingId)) this.socket.on('error', (e) => this.emit('error', e)) @@ -90,6 +89,10 @@ export class Atem extends EventEmitter { this.socket.on('disconnect', () => this.emit('disconnected')) } + get state (): Readonly { + return this._state + } + connect (address: string, port?: number) { return this.socket.connect(address, port) } @@ -100,7 +103,7 @@ export class Atem extends EventEmitter { }) } - sendCommand (command: AbstractCommand): Promise { + sendCommand (command: ISerializableCommand): Promise { const nextPacketId = this.socket.nextPacketId this._sentQueue[nextPacketId] = command return new Promise((resolve, reject) => { @@ -121,26 +124,22 @@ export class Atem extends EventEmitter { } cut (me: number = 0) { - const command = new Commands.CutCommand() - command.mixEffect = me + const command = new Commands.CutCommand(me) return this.sendCommand(command) } autoTransition (me: number = 0) { - const command = new Commands.AutoTransitionCommand() - command.mixEffect = me + const command = new Commands.AutoTransitionCommand(me) return this.sendCommand(command) } fadeToBlack (me: number = 0) { - const command = new Commands.FadeToBlackAutoCommand() - command.mixEffect = me + const command = new Commands.FadeToBlackAutoCommand(me) return this.sendCommand(command) } autoDownstreamKey (key: number = 0, isTowardsOnAir?: boolean) { - const command = new Commands.DownstreamKeyAutoCommand() - command.downstreamKeyerId = key + const command = new Commands.DownstreamKeyAutoCommand(key) command.updateProps({ isTowardsOnAir }) return this.sendCommand(command) } @@ -196,94 +195,70 @@ export class Atem extends EventEmitter { return this.sendCommand(command) } - setDownstreamKeyTie (tie: boolean, key = 0) { - const command = new Commands.DownstreamKeyTieCommand() - command.downstreamKeyerId = key - command.updateProps({ tie }) + setDownstreamKeyTie (tie: boolean, key: number = 0) { + const command = new Commands.DownstreamKeyTieCommand(key, tie) return this.sendCommand(command) } - setDownstreamKeyOnAir (onAir: boolean, key = 0) { - const command = new Commands.DownstreamKeyOnAirCommand() - command.downstreamKeyerId = key - command.updateProps({ onAir }) + setDownstreamKeyOnAir (onAir: boolean, key: number = 0) { + const command = new Commands.DownstreamKeyOnAirCommand(key, onAir) return this.sendCommand(command) } - setDownstreamKeyCutSource (input: number, key = 0) { - const command = new Commands.DownstreamKeyCutSourceCommand() - command.downstreamKeyerId = key - command.updateProps({ input }) + setDownstreamKeyCutSource (input: number, key: number = 0) { + const command = new Commands.DownstreamKeyCutSourceCommand(key, input) return this.sendCommand(command) } - setDownstreamKeyFillSource (input: number, key = 0) { - const command = new Commands.DownstreamKeyFillSourceCommand() - command.downstreamKeyerId = key - command.updateProps({ input }) + setDownstreamKeyFillSource (input: number, key: number = 0) { + const command = new Commands.DownstreamKeyFillSourceCommand(key, input) return this.sendCommand(command) } - setDownstreamKeyGeneralProperties (props: Partial, key = 0) { - const command = new Commands.DownstreamKeyGeneralCommand() - command.downstreamKeyerId = key + setDownstreamKeyGeneralProperties (props: Partial, key: number = 0) { + const command = new Commands.DownstreamKeyGeneralCommand(key) command.updateProps(props) return this.sendCommand(command) } - setDownstreamKeyMaskSettings (props: Partial, key = 0) { - const command = new Commands.DownstreamKeyMaskCommand() - command.downstreamKeyerId = key + setDownstreamKeyMaskSettings (props: Partial, key: number = 0) { + const command = new Commands.DownstreamKeyMaskCommand(key) command.updateProps(props) return this.sendCommand(command) } - setDownstreamKeyRate (rate: number, key = 0) { - const command = new Commands.DownstreamKeyRateCommand() - command.downstreamKeyerId = key - command.updateProps({ rate }) + setDownstreamKeyRate (rate: number, key: number = 0) { + const command = new Commands.DownstreamKeyRateCommand(key, rate) return this.sendCommand(command) } macroContinue () { - const command = new Commands.MacroActionCommand() - command.index = 0 - command.updateProps({ action: Enums.MacroAction.Continue }) + const command = new Commands.MacroActionCommand(0, Enums.MacroAction.Continue) return this.sendCommand(command) } macroDelete (index = 0) { - const command = new Commands.MacroActionCommand() - command.index = index - command.updateProps({ action: Enums.MacroAction.Delete }) + const command = new Commands.MacroActionCommand(index, Enums.MacroAction.Delete) return this.sendCommand(command) } macroInsertUserWait () { - const command = new Commands.MacroActionCommand() - command.index = 0 - command.updateProps({ action: Enums.MacroAction.InsertUserWait }) + const command = new Commands.MacroActionCommand(0, Enums.MacroAction.InsertUserWait) return this.sendCommand(command) } - macroRun (index = 0) { - const command = new Commands.MacroActionCommand() - command.index = index - command.updateProps({ action: Enums.MacroAction.Run }) + macroRun (index: number = 0) { + const command = new Commands.MacroActionCommand(index, Enums.MacroAction.Run) return this.sendCommand(command) } macroStop () { - const command = new Commands.MacroActionCommand() - command.index = 0 - command.updateProps({ action: Enums.MacroAction.Stop }) + const command = new Commands.MacroActionCommand(0, Enums.MacroAction.Stop) return this.sendCommand(command) } macroStopRecord () { - const command = new Commands.MacroActionCommand() - command.index = 0 - command.updateProps({ action: Enums.MacroAction.StopRecord }) + const command = new Commands.MacroActionCommand(0, Enums.MacroAction.StopRecord) return this.sendCommand(command) } @@ -305,21 +280,18 @@ export class Atem extends EventEmitter { return this.sendCommand(command) } - setMediaClip (index: number, name: string, frames = 1) { - const command = new Commands.MediaPoolSetClipCommand() - command.updateProps({ index, name, frames }) + setMediaClip (index: number, name: string, frames: number = 1) { + const command = new Commands.MediaPoolSetClipCommand({ index, name, frames }) return this.sendCommand(command) } clearMediaPoolClip (clipId: number) { - const command = new Commands.MediaPoolClearClipCommand() - command.updateProps({ index: clipId }) + const command = new Commands.MediaPoolClearClipCommand(clipId) return this.sendCommand(command) } clearMediaPoolStill (stillId: number) { - const command = new Commands.MediaPoolClearStillCommand() - command.updateProps({ index: stillId }) + const command = new Commands.MediaPoolClearStillCommand(stillId) return this.sendCommand(command) } @@ -330,7 +302,7 @@ export class Atem extends EventEmitter { } setSuperSourceProperties (newProps: Partial, ssrcId: number = 0) { - if (this.state.info.apiVersion >= Enums.ProtocolVersion.V8_0) { + if (this._state.info.apiVersion >= Enums.ProtocolVersion.V8_0) { const command = new Commands.SuperSourcePropertiesV8Command(ssrcId) command.updateProps(newProps) return this.sendCommand(command) @@ -342,7 +314,7 @@ export class Atem extends EventEmitter { } setSuperSourceBorder (newProps: Partial, ssrcId: number = 0) { - if (this.state.info.apiVersion >= Enums.ProtocolVersion.V8_0) { + if (this._state.info.apiVersion >= Enums.ProtocolVersion.V8_0) { const command = new Commands.SuperSourceBorderCommand(ssrcId) command.updateProps(newProps) return this.sendCommand(command) @@ -366,18 +338,12 @@ export class Atem extends EventEmitter { } setUpstreamKeyerCutSource (cutSource: number, me: number = 0, keyer: number = 0) { - const command = new Commands.MixEffectKeyCutSourceSetCommand() - command.mixEffect = me - command.upstreamKeyerId = keyer - command.updateProps({ cutSource }) + const command = new Commands.MixEffectKeyCutSourceSetCommand(me, keyer, cutSource) return this.sendCommand(command) } setUpstreamKeyerFillSource (fillSource: number, me: number = 0, keyer: number = 0) { - const command = new Commands.MixEffectKeyFillSourceSetCommand() - command.mixEffect = me - command.upstreamKeyerId = keyer - command.updateProps({ fillSource }) + const command = new Commands.MixEffectKeyFillSourceSetCommand(me, keyer, fillSource) return this.sendCommand(command) } @@ -394,9 +360,7 @@ export class Atem extends EventEmitter { } setUpstreamKeyerMaskSettings (newProps: Partial, me: number = 0, keyer: number = 0) { - const command = new Commands.MixEffectKeyMaskSetCommand() - command.mixEffect = me - command.upstreamKeyerId = keyer + const command = new Commands.MixEffectKeyMaskSetCommand(me, keyer) command.updateProps(newProps) return this.sendCommand(command) } @@ -413,15 +377,13 @@ export class Atem extends EventEmitter { } setUpstreamKeyerType (newProps: Partial, me: number = 0, keyer: number = 0) { - const command = new Commands.MixEffectKeyTypeSetCommand() - command.mixEffect = me - command.upstreamKeyerId = keyer + const command = new Commands.MixEffectKeyTypeSetCommand(me, keyer) command.updateProps(newProps) return this.sendCommand(command) } uploadStill (index: number, data: Buffer, name: string, description: string) { - const resolution = Util.getResolution(this.state.settings.videoMode) + const resolution = Util.getResolution(this._state.settings.videoMode) return this.dataTransferManager.uploadStill( index, Util.convertRGBAToYUV422(resolution[0], resolution[1], data), @@ -431,7 +393,7 @@ export class Atem extends EventEmitter { } uploadClip (index: number, frames: Array, name: string) { - const resolution = Util.getResolution(this.state.settings.videoMode) + const resolution = Util.getResolution(this._state.settings.videoMode) const data: Array = [] for (const frame of frames) { data.push(Util.convertRGBAToYUV422(resolution[0], resolution[1], frame)) @@ -487,13 +449,13 @@ export class Atem extends EventEmitter { return this.sendCommand(command) } - private _mutateState (command: AbstractCommand) { - if (typeof command.applyToState === 'function') { - let changePaths = command.applyToState(this.state) + private _mutateState (command: IDeserializedCommand) { + if (isFunction(command.applyToState)) { + let changePaths = command.applyToState(this._state) if (!isArray(changePaths)) { changePaths = [ changePaths ] } - changePaths.forEach(path => this.emit('stateChanged', this.state, path)) + changePaths.forEach(path => this.emit('stateChanged', this._state, path)) } for (const commandName in DataTransferCommands) { if (command.constructor.name === commandName) { diff --git a/src/commands/AbstractCommand.ts b/src/commands/AbstractCommand.ts deleted file mode 100644 index 271940ec3..000000000 --- a/src/commands/AbstractCommand.ts +++ /dev/null @@ -1,85 +0,0 @@ -import { AtemState } from '../state' -import { ProtocolVersion } from '../enums' - - -export default abstract class AbstractCommand { - static readonly MaskFlags?: { [key: string]: number } - static readonly minimumVersion?: ProtocolVersion - - // static abstract rawName: string - - // abstract rawName: string - packetId: number - flag: number = 0 - // minimumVersion?: ProtocolVersion - - resolve: (cmd: AbstractCommand) => void - reject: (cmd: AbstractCommand) => void - - abstract properties: any - - // deserialize? (rawCommand: Buffer, version: ProtocolVersion): void - serialize? (version: ProtocolVersion): Buffer - - applyToState? (state: AtemState): string | string[] - - updateProps (newProps: object) { - this._updateProps(newProps) - } - - protected _updateProps (newProps: Object) { - this.properties = { - ...this.properties, - ...newProps - } - const maskFlags = (this.constructor as any).MaskFlags as { [key: string]: number } - - if (maskFlags) { - for (const key in newProps) { - if (key in maskFlags) { - this.flag = this.flag | maskFlags[key] - } - } - } - } -} - -export abstract class BasicWritableCommand extends AbstractCommand { - properties: T - - public serialize? (version: ProtocolVersion): Buffer -} - -export abstract class WritableCommand extends BasicWritableCommand> { - static readonly MaskFlags?: { [key: string]: number } - - flag: number - - constructor () { - super() - - this.flag = 0 - this.properties = {} - } - - public updateProps (newProps: Partial) { - this._updateProps(newProps) - } - - protected _updateProps (newProps: Object) { - this.properties = { - ...this.properties, - ...newProps - } - const maskFlags = (this.constructor as any).MaskFlags as { [key: string]: number } - - if (maskFlags) { - for (const key in newProps) { - if (key in maskFlags) { - this.flag = this.flag | maskFlags[key] - } - } - } - } - -} diff --git a/src/commands/Audio/AudioMixerInputCommand.ts b/src/commands/Audio/AudioMixerInputCommand.ts index f2c02a444..fcac110fd 100644 --- a/src/commands/Audio/AudioMixerInputCommand.ts +++ b/src/commands/Audio/AudioMixerInputCommand.ts @@ -1,9 +1,9 @@ -import AbstractCommand from '../AbstractCommand' import { AtemState } from '../../state' import { Util } from '../..' import { AudioChannel } from '../../state/audio' +import { WritableCommand, DeserializedCommand } from '../CommandBase' -export class AudioMixerInputCommand extends AbstractCommand { +export class AudioMixerInputCommand extends WritableCommand { static MaskFlags = { mixOption: 1 << 0, gain: 1 << 1, @@ -12,7 +12,6 @@ export class AudioMixerInputCommand extends AbstractCommand { static readonly rawName = 'CAMI' readonly index: number - properties: Partial constructor (index: number) { super() @@ -32,17 +31,15 @@ export class AudioMixerInputCommand extends AbstractCommand { } } -export class AudioMixerInputUpdateCommand extends AbstractCommand { +export class AudioMixerInputUpdateCommand extends DeserializedCommand { static readonly rawName = 'AMIP' readonly index: number - readonly properties: Readonly constructor (index: number, properties: AudioChannel) { - super() + super(properties) this.index = index - this.properties = properties } static deserialize (rawCommand: Buffer): AudioMixerInputUpdateCommand { diff --git a/src/commands/Audio/AudioMixerMasterCommand.ts b/src/commands/Audio/AudioMixerMasterCommand.ts index 595fc071c..13e66e669 100644 --- a/src/commands/Audio/AudioMixerMasterCommand.ts +++ b/src/commands/Audio/AudioMixerMasterCommand.ts @@ -1,9 +1,9 @@ -import AbstractCommand from '../AbstractCommand' +import { WritableCommand, DeserializedCommand } from '../CommandBase' import { AtemState } from '../../state' import { Util } from '../..' import { AudioMasterChannel } from '../../state/audio' -export class AudioMixerMasterCommand extends AbstractCommand { +export class AudioMixerMasterCommand extends WritableCommand { static MaskFlags = { gain: 1 << 0, balance: 1 << 1, @@ -11,14 +11,6 @@ export class AudioMixerMasterCommand extends AbstractCommand { } static readonly rawName = 'CAMM' - properties: Partial - - constructor () { - super() - - this.properties = {} - } - serialize () { const buffer = Buffer.alloc(8) buffer.writeUInt8(this.flag, 0) @@ -29,17 +21,9 @@ export class AudioMixerMasterCommand extends AbstractCommand { } } -export class AudioMixerMasterUpdateCommand extends AbstractCommand { +export class AudioMixerMasterUpdateCommand extends DeserializedCommand { static readonly rawName = 'AMMO' - readonly properties: Readonly - - constructor (properties: AudioMasterChannel) { - super() - - this.properties = properties - } - static deserialize (rawCommand: Buffer): AudioMixerMasterUpdateCommand { const properties = { gain: Util.UInt16BEToDecibel(rawCommand.readUInt16BE(0)), diff --git a/src/commands/AuxSourceCommand.ts b/src/commands/AuxSourceCommand.ts index b523aa0de..293792def 100644 --- a/src/commands/AuxSourceCommand.ts +++ b/src/commands/AuxSourceCommand.ts @@ -1,20 +1,19 @@ -import AbstractCommand from './AbstractCommand' +import { BasicWritableCommand, DeserializedCommand } from './CommandBase' import { AtemState } from '../state' -export class AuxSourceCommand extends AbstractCommand { +export interface AuxSourceProps { + source: number +} + +export class AuxSourceCommand extends BasicWritableCommand { static readonly rawName = 'CAuS' readonly auxBus: number - readonly properties: Readonly<{ - source: number - }> - constructor (auxBus: number, source: number) { - super() + super({ source }) this.auxBus = auxBus - this.properties = { source } } serialize () { @@ -26,20 +25,15 @@ export class AuxSourceCommand extends AbstractCommand { } } -export class AuxSourceUpdateCommand extends AbstractCommand { +export class AuxSourceUpdateCommand extends DeserializedCommand { static readonly rawName = 'AuxS' readonly auxBus: number - readonly properties: Readonly<{ - source: number - }> - - constructor (auxBus: number, properties: AuxSourceUpdateCommand['properties']) { - super() + constructor (auxBus: number, properties: AuxSourceProps) { + super(properties) this.auxBus = auxBus - this.properties = properties } static deserialize (rawCommand: Buffer): AuxSourceUpdateCommand { diff --git a/src/commands/CommandBase.ts b/src/commands/CommandBase.ts new file mode 100644 index 000000000..3ed99372e --- /dev/null +++ b/src/commands/CommandBase.ts @@ -0,0 +1,70 @@ +import { AtemState } from '../state' +import { ProtocolVersion } from '../enums' + +export interface IDeserializedCommand { + properties: any + + applyToState (state: AtemState): string | string[] +} + +export abstract class DeserializedCommand implements IDeserializedCommand { + static readonly minimumVersion?: ProtocolVersion + + readonly properties: Readonly + + constructor (properties: T) { + this.properties = properties + } + + abstract applyToState (state: AtemState): string | string[] +} + +export interface ISerializableCommand { + serialize (version: ProtocolVersion): Buffer +} + +export abstract class BasicWritableCommand implements ISerializableCommand { + static readonly MaskFlags?: { [key: string]: number } + static readonly minimumVersion?: ProtocolVersion + + properties: T + + constructor (properties: T) { + this.properties = properties + } + + abstract serialize (version: ProtocolVersion): Buffer +} + +export abstract class WritableCommand extends BasicWritableCommand> { + static readonly MaskFlags?: { [key: string]: number } + + flag: number + + constructor () { + super({}) + + this.flag = 0 + } + + public updateProps (newProps: Partial) { + this._updateProps(newProps) + } + + protected _updateProps (newProps: Object) { + this.properties = { + ...this.properties, + ...newProps + } + const maskFlags = (this.constructor as any).MaskFlags as { [key: string]: number } + + if (maskFlags) { + for (const key in newProps) { + if (key in maskFlags) { + this.flag = this.flag | maskFlags[key] + } + } + } + } + +} diff --git a/src/commands/DataTransfer/DataTransferAckCommand.ts b/src/commands/DataTransfer/DataTransferAckCommand.ts index 853164a1f..bd6dd5da6 100644 --- a/src/commands/DataTransfer/DataTransferAckCommand.ts +++ b/src/commands/DataTransfer/DataTransferAckCommand.ts @@ -1,18 +1,12 @@ -import AbstractCommand from '../AbstractCommand' +import { DeserializedCommand } from '../CommandBase' -export class DataTransferAckCommand extends AbstractCommand { - static readonly rawName = 'FTUA' - - readonly properties: Readonly<{ - transferId: number, - transferIndex: number - }> - - constructor (properties: DataTransferAckCommand['properties']) { - super() +export interface DataTransferAckProps { + transferId: number + transferIndex: number +} - this.properties = properties - } +export class DataTransferAckCommand extends DeserializedCommand { + static readonly rawName = 'FTUA' static deserialize (rawCommand: Buffer): DataTransferAckCommand { const properties = { @@ -22,4 +16,9 @@ export class DataTransferAckCommand extends AbstractCommand { return new DataTransferAckCommand(properties) } + + applyToState (): string[] { + // Nothing to do + return [] + } } diff --git a/src/commands/DataTransfer/DataTransferCompleteCommand.ts b/src/commands/DataTransfer/DataTransferCompleteCommand.ts index 23525305a..720122611 100644 --- a/src/commands/DataTransfer/DataTransferCompleteCommand.ts +++ b/src/commands/DataTransfer/DataTransferCompleteCommand.ts @@ -1,18 +1,8 @@ -import AbstractCommand from '../AbstractCommand' +import { DeserializedCommand } from '../CommandBase' -export class DataTransferCompleteCommand extends AbstractCommand { +export class DataTransferCompleteCommand extends DeserializedCommand<{ transferId: number }> { static readonly rawName = 'FTDC' - readonly properties: Readonly<{ - transferId: number - }> - - constructor (properties: DataTransferCompleteCommand['properties']) { - super() - - this.properties = properties - } - static deserialize (rawCommand: Buffer): DataTransferCompleteCommand { const properties = { transferId: rawCommand.readUInt16BE(0) @@ -20,4 +10,9 @@ export class DataTransferCompleteCommand extends AbstractCommand { return new DataTransferCompleteCommand(properties) } + + applyToState (): string[] { + // Nothing to do + return [] + } } diff --git a/src/commands/DataTransfer/DataTransferDataCommand.ts b/src/commands/DataTransfer/DataTransferDataCommand.ts index 0c34041ae..c2e23194d 100644 --- a/src/commands/DataTransfer/DataTransferDataCommand.ts +++ b/src/commands/DataTransfer/DataTransferDataCommand.ts @@ -1,18 +1,12 @@ -import AbstractCommand from '../AbstractCommand' +import { BasicWritableCommand, IDeserializedCommand } from '../CommandBase' -export class DataTransferDataCommand extends AbstractCommand { - static readonly rawName = 'FTDa' - - readonly properties: Readonly<{ - transferId: number, - body: Buffer - }> - - constructor (properties: DataTransferDataCommand['properties']) { - super() +export interface DataTransferDataProps { + transferId: number + body: Buffer +} - this.properties = properties - } +export class DataTransferDataCommand extends BasicWritableCommand implements IDeserializedCommand { + static readonly rawName = 'FTDa' serialize () { const buffer = Buffer.alloc(4) @@ -31,4 +25,9 @@ export class DataTransferDataCommand extends AbstractCommand { return new DataTransferDataCommand(properties) } + + applyToState (): string[] { + // Nothing to do + return [] + } } diff --git a/src/commands/DataTransfer/DataTransferDownloadRequestCommand.ts b/src/commands/DataTransfer/DataTransferDownloadRequestCommand.ts index 6ec6f4a16..77eb00600 100644 --- a/src/commands/DataTransfer/DataTransferDownloadRequestCommand.ts +++ b/src/commands/DataTransfer/DataTransferDownloadRequestCommand.ts @@ -1,13 +1,13 @@ -import AbstractCommand from '../AbstractCommand' +import { BasicWritableCommand } from '../CommandBase' -export class DataTransferDownloadRequestCommand extends AbstractCommand { - static readonly rawName = 'FTSU' +export interface DataTransferDownloadRequestProps { + transferId: number + transferStoreId: number + transferIndex: number +} - properties: { - transferId: number, - transferStoreId: number, - transferIndex: number - } +export class DataTransferDownloadRequestCommand extends BasicWritableCommand { + static readonly rawName = 'FTSU' serialize () { const buffer = Buffer.alloc(12) diff --git a/src/commands/DataTransfer/DataTransferErrorCommand.ts b/src/commands/DataTransfer/DataTransferErrorCommand.ts index b04151ccf..a59c07fd4 100644 --- a/src/commands/DataTransfer/DataTransferErrorCommand.ts +++ b/src/commands/DataTransfer/DataTransferErrorCommand.ts @@ -1,18 +1,12 @@ -import AbstractCommand from '../AbstractCommand' +import { DeserializedCommand } from '../CommandBase' -export class DataTransferErrorCommand extends AbstractCommand { - static readonly rawName = 'FTDE' - - readonly properties: Readonly<{ - transferId: number - errorCode: number - }> - - constructor (properties: DataTransferErrorCommand['properties']) { - super() +export interface DataTransferErrorProps { + transferId: number + errorCode: number +} - this.properties = properties - } +export class DataTransferErrorCommand extends DeserializedCommand { + static readonly rawName = 'FTDE' static deserialize (rawCommand: Buffer): DataTransferErrorCommand { const properties = { @@ -22,4 +16,9 @@ export class DataTransferErrorCommand extends AbstractCommand { return new DataTransferErrorCommand(properties) } + + applyToState (): string[] { + // Nothing to do + return [] + } } diff --git a/src/commands/DataTransfer/DataTransferFileDescriptionCommand.ts b/src/commands/DataTransfer/DataTransferFileDescriptionCommand.ts index 6e16508ad..6dca9b3f6 100644 --- a/src/commands/DataTransfer/DataTransferFileDescriptionCommand.ts +++ b/src/commands/DataTransfer/DataTransferFileDescriptionCommand.ts @@ -1,14 +1,14 @@ -import AbstractCommand from '../AbstractCommand' +import { BasicWritableCommand } from '../CommandBase' -export class DataTransferFileDescriptionCommand extends AbstractCommand { - static readonly rawName = 'FTFD' +export interface DataTransferFileDescriptionProps { + transferId: number + name?: string + description?: string + fileHash: string +} - properties: { - transferId: number, - name: string, - description: string, - fileHash: string - } +export class DataTransferFileDescriptionCommand extends BasicWritableCommand { + static readonly rawName = 'FTFD' serialize () { const buffer = Buffer.alloc(212) diff --git a/src/commands/DataTransfer/DataTransferUploadContinueCommand.ts b/src/commands/DataTransfer/DataTransferUploadContinueCommand.ts index b10b91248..5f6d7e065 100644 --- a/src/commands/DataTransfer/DataTransferUploadContinueCommand.ts +++ b/src/commands/DataTransfer/DataTransferUploadContinueCommand.ts @@ -1,19 +1,13 @@ -import AbstractCommand from '../AbstractCommand' +import { DeserializedCommand } from '../CommandBase' -export class DataTransferUploadContinueCommand extends AbstractCommand { - static readonly rawName = 'FTCD' - - readonly properties: Readonly<{ - transferId: number, - chunkSize: number, - chunkCount: number - }> - - constructor (properties: DataTransferUploadContinueCommand['properties']) { - super() +export interface DataTransferUploadContinueProps { + transferId: number + chunkSize: number + chunkCount: number +} - this.properties = properties - } +export class DataTransferUploadContinueCommand extends DeserializedCommand { + static readonly rawName = 'FTCD' static deserialize (rawCommand: Buffer) { const properties = { @@ -24,4 +18,9 @@ export class DataTransferUploadContinueCommand extends AbstractCommand { return new DataTransferUploadContinueCommand(properties) } + + applyToState (): string[] { + // Nothing to do + return [] + } } diff --git a/src/commands/DataTransfer/DataTransferUploadRequestCommand.ts b/src/commands/DataTransfer/DataTransferUploadRequestCommand.ts index 342061f7d..5ea959794 100644 --- a/src/commands/DataTransfer/DataTransferUploadRequestCommand.ts +++ b/src/commands/DataTransfer/DataTransferUploadRequestCommand.ts @@ -1,16 +1,16 @@ -import AbstractCommand from '../AbstractCommand' +import { BasicWritableCommand } from '../CommandBase' import { Enums } from '../..' -export class DataTransferUploadRequestCommand extends AbstractCommand { - static readonly rawName = 'FTSD' +export interface DataTransferUploadRequestProps { + transferId: number + transferStoreId: number + transferIndex: number + size: number + mode: Enums.TransferMode +} - properties: { - transferId: number, - transferStoreId: number, - transferIndex: number, - size: number, - mode: Enums.TransferMode - } +export class DataTransferUploadRequestCommand extends BasicWritableCommand { + static readonly rawName = 'FTSD' serialize () { const buffer = Buffer.alloc(16) diff --git a/src/commands/DataTransfer/LockObtainedCommand.ts b/src/commands/DataTransfer/LockObtainedCommand.ts index 6612b6619..11318677f 100644 --- a/src/commands/DataTransfer/LockObtainedCommand.ts +++ b/src/commands/DataTransfer/LockObtainedCommand.ts @@ -1,23 +1,20 @@ -import AbstractCommand from '../AbstractCommand' +import { DeserializedCommand } from '../CommandBase' -export class LockObtainedCommand extends AbstractCommand { +export class LockObtainedCommand extends DeserializedCommand<{ index: number }> { static readonly rawName = 'LKOB' - readonly properties: Readonly<{ - index: number - }> - - constructor (properties: LockObtainedCommand['properties']) { - super() - - this.properties = properties + constructor (index: number) { + super({ index }) } static deserialize (rawCommand: Buffer) { - const properties = { - index: rawCommand.readUInt16BE(0) - } + const index = rawCommand.readUInt16BE(0) + + return new LockObtainedCommand(index) + } - return new LockObtainedCommand(properties) + applyToState (): string[] { + // nothing to do + return [] } } diff --git a/src/commands/DataTransfer/LockStateCommand.ts b/src/commands/DataTransfer/LockStateCommand.ts index 94d4e4d5e..4b28081a4 100644 --- a/src/commands/DataTransfer/LockStateCommand.ts +++ b/src/commands/DataTransfer/LockStateCommand.ts @@ -1,17 +1,15 @@ -import AbstractCommand from '../AbstractCommand' +import { BasicWritableCommand, DeserializedCommand } from '../CommandBase' -export class LockStateCommand extends AbstractCommand { - static readonly rawName = 'LOCK' +export interface LockStateProps { + index: number + locked: boolean +} - readonly properties: Readonly<{ - index: number, - locked: boolean - }> +export class LockStateCommand extends BasicWritableCommand { + static readonly rawName = 'LOCK' constructor (index: number, locked: boolean) { - super() - - this.properties = { index, locked } + super({ index, locked }) } serialize () { @@ -22,20 +20,9 @@ export class LockStateCommand extends AbstractCommand { } } -export class LockStateUpdateCommand extends AbstractCommand { +export class LockStateUpdateCommand extends DeserializedCommand { static readonly rawName = 'LKST' - readonly properties: Readonly<{ - index: number, - locked: boolean - }> - - constructor (properties: LockStateUpdateCommand['properties']) { - super() - - this.properties = properties - } - static deserialize (rawCommand: Buffer) { const properties = { index: rawCommand.readUInt16BE(0), @@ -44,4 +31,9 @@ export class LockStateUpdateCommand extends AbstractCommand { return new LockStateUpdateCommand(properties) } + + applyToState (): string | string[] { + // Nothing to do + return [] + } } diff --git a/src/commands/DeviceProfile/productIdentifierCommand.ts b/src/commands/DeviceProfile/productIdentifierCommand.ts index 42b323930..0041f06a5 100644 --- a/src/commands/DeviceProfile/productIdentifierCommand.ts +++ b/src/commands/DeviceProfile/productIdentifierCommand.ts @@ -1,25 +1,15 @@ -import AbstractCommand from '../AbstractCommand' +import { DeserializedCommand } from '../CommandBase' import { AtemState } from '../../state' import { Util } from '../../lib/atemUtil' import { Enums } from '../..' +import { DeviceInfo } from '../../state/info' -export class ProductIdentifierCommand extends AbstractCommand { +export class ProductIdentifierCommand extends DeserializedCommand> { static readonly rawName = '_pin' - readonly properties: Readonly<{ - deviceName: string - model: number - }> - - constructor (properties: ProductIdentifierCommand['properties']) { - super() - - this.properties = properties - } - static deserialize (rawCommand: Buffer) { const properties = { - deviceName: Util.bufToNullTerminatedString(rawCommand, 0, 40), + productIdentifier: Util.bufToNullTerminatedString(rawCommand, 0, 40), model: Util.parseEnum(rawCommand[40], Enums.Model) } @@ -27,7 +17,7 @@ export class ProductIdentifierCommand extends AbstractCommand { } applyToState (state: AtemState) { - state.info.productIdentifier = this.properties.deviceName + state.info.productIdentifier = this.properties.productIdentifier state.info.model = this.properties.model // Model specific features that aren't specified by the protocol diff --git a/src/commands/DeviceProfile/superSourceConfigCommand.ts b/src/commands/DeviceProfile/superSourceConfigCommand.ts index fad02e19f..1f1dfef42 100644 --- a/src/commands/DeviceProfile/superSourceConfigCommand.ts +++ b/src/commands/DeviceProfile/superSourceConfigCommand.ts @@ -1,18 +1,12 @@ -import AbstractCommand from '../AbstractCommand' +import { DeserializedCommand } from '../CommandBase' import { AtemState } from '../../state' import { Util } from '../..' -export class SuperSourceConfigCommand extends AbstractCommand { +export class SuperSourceConfigCommand extends DeserializedCommand<{ superSourceBoxes: number }> { static readonly rawName = '_SSC' - readonly properties: Readonly<{ - superSourceBoxes: number - }> - constructor (properties: SuperSourceConfigCommand['properties']) { - super() - - this.properties = properties + super(properties) } static deserialize (rawCommand: Buffer) { diff --git a/src/commands/DeviceProfile/topologyCommand.ts b/src/commands/DeviceProfile/topologyCommand.ts index da7d6835d..15c1d2eb0 100644 --- a/src/commands/DeviceProfile/topologyCommand.ts +++ b/src/commands/DeviceProfile/topologyCommand.ts @@ -1,18 +1,10 @@ -import AbstractCommand from '../AbstractCommand' +import { DeserializedCommand } from '../CommandBase' import { AtemState } from '../../state' import { AtemCapabilites } from '../../state/info' -export class TopologyCommand extends AbstractCommand { +export class TopologyCommand extends DeserializedCommand { static readonly rawName = '_top' - readonly properties: Readonly - - constructor (properties: AtemCapabilites) { - super() - - this.properties = properties - } - static deserialize (rawCommand: Buffer) { const properties = { MEs: rawCommand[0], diff --git a/src/commands/DeviceProfile/versionCommand.ts b/src/commands/DeviceProfile/versionCommand.ts index 48db307ac..e32c1ba47 100644 --- a/src/commands/DeviceProfile/versionCommand.ts +++ b/src/commands/DeviceProfile/versionCommand.ts @@ -1,26 +1,18 @@ -import AbstractCommand from '../AbstractCommand' +import { DeserializedCommand } from '../CommandBase' import { AtemState } from '../../state' import { ProtocolVersion } from '../../enums' -export class VersionCommand extends AbstractCommand { +export class VersionCommand extends DeserializedCommand<{ version: ProtocolVersion }> { static readonly rawName = '_ver' - readonly properties: Readonly<{ - version: ProtocolVersion - }> - - constructor (properties: VersionCommand['properties']) { - super() - - this.properties = properties + constructor (version: ProtocolVersion) { + super({ version }) } static deserialize (rawCommand: Buffer) { - const properties = { - version: rawCommand.readUInt32BE(0) - } + const version = rawCommand.readUInt32BE(0) - return new VersionCommand(properties) + return new VersionCommand(version) } applyToState (state: AtemState) { diff --git a/src/commands/DownstreamKey/DownstreamKeyAutoCommand.ts b/src/commands/DownstreamKey/DownstreamKeyAutoCommand.ts index c2d763e17..cd55ce41c 100644 --- a/src/commands/DownstreamKey/DownstreamKeyAutoCommand.ts +++ b/src/commands/DownstreamKey/DownstreamKeyAutoCommand.ts @@ -1,20 +1,18 @@ -import AbstractCommand from '../AbstractCommand' +import { WritableCommand } from '../CommandBase' import { ProtocolVersion } from '../../enums' -export class DownstreamKeyAutoCommand extends AbstractCommand { - static readonly rawName = 'DDsA' - downstreamKeyerId: number - - MaskFlags = { +export class DownstreamKeyAutoCommand extends WritableCommand<{ isTowardsOnAir: boolean }> { + static readonly MaskFlags = { isTowardsOnAir: 1 } + static readonly rawName = 'DDsA' - properties: { - isTowardsOnAir?: boolean - } + readonly downstreamKeyerId: number + + constructor (downstreamKeyerId: number) { + super() - updateProps (newProps: Partial) { - this._updateProps(newProps) + this.downstreamKeyerId = downstreamKeyerId } serialize (version: ProtocolVersion) { diff --git a/src/commands/DownstreamKey/DownstreamKeyCutSourceCommand.ts b/src/commands/DownstreamKey/DownstreamKeyCutSourceCommand.ts index c4ab0c2f8..fa70dbf0f 100644 --- a/src/commands/DownstreamKey/DownstreamKeyCutSourceCommand.ts +++ b/src/commands/DownstreamKey/DownstreamKeyCutSourceCommand.ts @@ -1,10 +1,14 @@ -import AbstractCommand from '../AbstractCommand' +import { BasicWritableCommand } from '../CommandBase' -export class DownstreamKeyCutSourceCommand extends AbstractCommand { +export class DownstreamKeyCutSourceCommand extends BasicWritableCommand<{ input: number }> { static readonly rawName = 'CDsC' - downstreamKeyerId: number - properties: { - input: number + + readonly downstreamKeyerId: number + + constructor (downstreamKeyerId: number, input: number) { + super({ input }) + + this.downstreamKeyerId = downstreamKeyerId } serialize () { @@ -13,8 +17,4 @@ export class DownstreamKeyCutSourceCommand extends AbstractCommand { buffer.writeUInt16BE(this.properties.input, 2) return buffer } - - updateProps (newProps: { input: number }) { - this._updateProps(newProps) - } } diff --git a/src/commands/DownstreamKey/DownstreamKeyFillSourceCommand.ts b/src/commands/DownstreamKey/DownstreamKeyFillSourceCommand.ts index e13f56ec4..ccec1427d 100644 --- a/src/commands/DownstreamKey/DownstreamKeyFillSourceCommand.ts +++ b/src/commands/DownstreamKey/DownstreamKeyFillSourceCommand.ts @@ -1,10 +1,14 @@ -import AbstractCommand from '../AbstractCommand' +import { BasicWritableCommand } from '../CommandBase' -export class DownstreamKeyFillSourceCommand extends AbstractCommand { +export class DownstreamKeyFillSourceCommand extends BasicWritableCommand<{ input: number }> { static readonly rawName = 'CDsF' - downstreamKeyerId: number - properties: { - input: number + + readonly downstreamKeyerId: number + + constructor (downstreamKeyerId: number, input: number) { + super({ input }) + + this.downstreamKeyerId = downstreamKeyerId } serialize () { @@ -13,8 +17,4 @@ export class DownstreamKeyFillSourceCommand extends AbstractCommand { buffer.writeUInt16BE(this.properties.input, 2) return buffer } - - updateProps (newProps: { input: number }) { - this._updateProps(newProps) - } } diff --git a/src/commands/DownstreamKey/DownstreamKeyGeneralCommand.ts b/src/commands/DownstreamKey/DownstreamKeyGeneralCommand.ts index cfc0ce0b7..c0fa783eb 100644 --- a/src/commands/DownstreamKey/DownstreamKeyGeneralCommand.ts +++ b/src/commands/DownstreamKey/DownstreamKeyGeneralCommand.ts @@ -1,7 +1,7 @@ -import AbstractCommand from '../AbstractCommand' +import { WritableCommand } from '../CommandBase' import { DownstreamKeyerGeneral } from '../../state/video/downstreamKeyers' -export class DownstreamKeyGeneralCommand extends AbstractCommand { +export class DownstreamKeyGeneralCommand extends WritableCommand { static MaskFlags = { preMultiply: 1 << 0, clip: 1 << 1, @@ -10,21 +10,23 @@ export class DownstreamKeyGeneralCommand extends AbstractCommand { } static readonly rawName = 'CDsG' - downstreamKeyerId: number - properties: DownstreamKeyerGeneral + + readonly downstreamKeyerId: number + + constructor (downstreamKeyerId: number) { + super() + + this.downstreamKeyerId = downstreamKeyerId + } serialize () { const buffer = Buffer.alloc(12) buffer.writeUInt8(this.flag, 0) buffer.writeUInt8(this.downstreamKeyerId, 1) buffer.writeUInt8(this.properties.preMultiply ? 1 : 0, 2) - buffer.writeInt16BE(this.properties.clip, 4) - buffer.writeInt16BE(this.properties.gain, 6) + buffer.writeInt16BE(this.properties.clip || 0, 4) + buffer.writeInt16BE(this.properties.gain || 0, 6) buffer.writeUInt8(this.properties.invert ? 1 : 0, 8) return buffer } - - updateProps (newProps: Partial) { - this._updateProps(newProps) - } } diff --git a/src/commands/DownstreamKey/DownstreamKeyMaskCommand.ts b/src/commands/DownstreamKey/DownstreamKeyMaskCommand.ts index 77a651911..24941ccd9 100644 --- a/src/commands/DownstreamKey/DownstreamKeyMaskCommand.ts +++ b/src/commands/DownstreamKey/DownstreamKeyMaskCommand.ts @@ -1,7 +1,7 @@ -import AbstractCommand from '../AbstractCommand' +import { WritableCommand } from '../CommandBase' import { DownstreamKeyerMask } from '../../state/video/downstreamKeyers' -export class DownstreamKeyMaskCommand extends AbstractCommand { +export class DownstreamKeyMaskCommand extends WritableCommand { static MaskFlags = { enabled: 1 << 0, top: 1 << 1, @@ -11,8 +11,14 @@ export class DownstreamKeyMaskCommand extends AbstractCommand { } static readonly rawName = 'CDsM' - downstreamKeyerId: number - properties: DownstreamKeyerMask + + readonly downstreamKeyerId: number + + constructor (downstreamKeyerId: number) { + super() + + this.downstreamKeyerId = downstreamKeyerId + } serialize () { const buffer = Buffer.alloc(12) @@ -20,14 +26,10 @@ export class DownstreamKeyMaskCommand extends AbstractCommand { buffer.writeUInt8(this.downstreamKeyerId, 1) buffer.writeUInt8(this.properties.enabled ? 1 : 0, 2) - buffer.writeInt16BE(this.properties.top, 4) - buffer.writeInt16BE(this.properties.bottom, 6) - buffer.writeInt16BE(this.properties.left, 8) - buffer.writeInt16BE(this.properties.right, 10) + buffer.writeInt16BE(this.properties.top || 0, 4) + buffer.writeInt16BE(this.properties.bottom || 0, 6) + buffer.writeInt16BE(this.properties.left || 0, 8) + buffer.writeInt16BE(this.properties.right || 0, 10) return buffer } - - updateProps (newProps: Partial) { - this._updateProps(newProps) - } } diff --git a/src/commands/DownstreamKey/DownstreamKeyOnAirCommand.ts b/src/commands/DownstreamKey/DownstreamKeyOnAirCommand.ts index e885e725c..09e62b360 100644 --- a/src/commands/DownstreamKey/DownstreamKeyOnAirCommand.ts +++ b/src/commands/DownstreamKey/DownstreamKeyOnAirCommand.ts @@ -1,11 +1,14 @@ -import AbstractCommand from '../AbstractCommand' +import { BasicWritableCommand } from '../CommandBase' -export class DownstreamKeyOnAirCommand extends AbstractCommand { +export class DownstreamKeyOnAirCommand extends BasicWritableCommand<{ onAir: boolean }> { static readonly rawName = 'CDsL' - downstreamKeyerId: number - properties: { - onAir: boolean + readonly downstreamKeyerId: number + + constructor (downstreamKeyerId: number, onAir: boolean) { + super({ onAir }) + + this.downstreamKeyerId = downstreamKeyerId } serialize () { diff --git a/src/commands/DownstreamKey/DownstreamKeyPropertiesCommand.ts b/src/commands/DownstreamKey/DownstreamKeyPropertiesCommand.ts index dbd8953a2..1a2755271 100644 --- a/src/commands/DownstreamKey/DownstreamKeyPropertiesCommand.ts +++ b/src/commands/DownstreamKey/DownstreamKeyPropertiesCommand.ts @@ -1,19 +1,17 @@ -import AbstractCommand from '../AbstractCommand' +import { DeserializedCommand } from '../CommandBase' import { AtemState } from '../../state' import { DownstreamKeyerProperties } from '../../state/video/downstreamKeyers' import { Util } from '../..' -export class DownstreamKeyPropertiesCommand extends AbstractCommand { +export class DownstreamKeyPropertiesCommand extends DeserializedCommand { static readonly rawName = 'DskP' readonly downstreamKeyerId: number - readonly properties: Readonly constructor (downstreamKeyerId: number, properties: DownstreamKeyerProperties) { - super() + super(properties) this.downstreamKeyerId = downstreamKeyerId - this.properties = properties } static deserialize (rawCommand: Buffer) { diff --git a/src/commands/DownstreamKey/DownstreamKeyRateCommand.ts b/src/commands/DownstreamKey/DownstreamKeyRateCommand.ts index dcee2553b..a0ecaa72c 100644 --- a/src/commands/DownstreamKey/DownstreamKeyRateCommand.ts +++ b/src/commands/DownstreamKey/DownstreamKeyRateCommand.ts @@ -1,10 +1,14 @@ -import AbstractCommand from '../AbstractCommand' +import { BasicWritableCommand } from '../CommandBase' -export class DownstreamKeyRateCommand extends AbstractCommand { +export class DownstreamKeyRateCommand extends BasicWritableCommand<{ rate: number }> { static readonly rawName = 'CDsR' - downstreamKeyerId: number - properties: { - rate: number + + readonly downstreamKeyerId: number + + constructor (downstreamKeyerId: number, rate: number) { + super({ rate }) + + this.downstreamKeyerId = downstreamKeyerId } serialize () { @@ -13,8 +17,4 @@ export class DownstreamKeyRateCommand extends AbstractCommand { buffer.writeUInt8(this.properties.rate, 1) return buffer } - - updateProps (newProps: { rate: number }) { - this._updateProps(newProps) - } } diff --git a/src/commands/DownstreamKey/DownstreamKeySourcesCommand.ts b/src/commands/DownstreamKey/DownstreamKeySourcesCommand.ts index 4dc4c0811..d053f84d3 100644 --- a/src/commands/DownstreamKey/DownstreamKeySourcesCommand.ts +++ b/src/commands/DownstreamKey/DownstreamKeySourcesCommand.ts @@ -1,21 +1,17 @@ -import AbstractCommand from '../AbstractCommand' +import { DeserializedCommand } from '../CommandBase' import { AtemState } from '../../state' import { Util } from '../..' +import { DownstreamKeyer } from '../../state/video/downstreamKeyers' -export class DownstreamKeySourcesCommand extends AbstractCommand { +export class DownstreamKeySourcesCommand extends DeserializedCommand { static readonly rawName = 'DskB' readonly downstreamKeyerId: number - readonly properties: Readonly<{ - fillSource: number, - cutSource: number - }> - constructor (downstreamKeyerId: number, properties: DownstreamKeySourcesCommand['properties']) { - super() + constructor (downstreamKeyerId: number, properties: DownstreamKeyer['sources']) { + super(properties) this.downstreamKeyerId = downstreamKeyerId - this.properties = properties } static deserialize (rawCommand: Buffer) { diff --git a/src/commands/DownstreamKey/DownstreamKeyStateCommand.ts b/src/commands/DownstreamKey/DownstreamKeyStateCommand.ts index 57ffaaa59..6d803b2a1 100644 --- a/src/commands/DownstreamKey/DownstreamKeyStateCommand.ts +++ b/src/commands/DownstreamKey/DownstreamKeyStateCommand.ts @@ -1,20 +1,18 @@ -import AbstractCommand from '../AbstractCommand' +import { DeserializedCommand } from '../CommandBase' import { AtemState } from '../../state' import { DownstreamKeyerBase } from '../../state/video/downstreamKeyers' import { Util } from '../..' import { ProtocolVersion } from '../../enums' -export class DownstreamKeyStateCommand extends AbstractCommand { +export class DownstreamKeyStateCommand extends DeserializedCommand { static readonly rawName = 'DskS' readonly downstreamKeyerId: number - readonly properties: Readonly constructor (downstreamKeyerId: number, properties: DownstreamKeyerBase) { - super() + super(properties) this.downstreamKeyerId = downstreamKeyerId - this.properties = properties } static deserialize (rawCommand: Buffer) { @@ -38,18 +36,16 @@ export class DownstreamKeyStateCommand extends AbstractCommand { } } -export class DownstreamKeyStateV8Command extends AbstractCommand { +export class DownstreamKeyStateV8Command extends DeserializedCommand { static readonly rawName = 'DskS' static readonly minimumVersion = ProtocolVersion.V8_0_1 readonly downstreamKeyerId: number - readonly properties: Readonly constructor (downstreamKeyerId: number, properties: DownstreamKeyerBase) { - super() + super(properties) this.downstreamKeyerId = downstreamKeyerId - this.properties = properties } static deserialize (rawCommand: Buffer) { diff --git a/src/commands/DownstreamKey/DownstreamKeyTieCommand.ts b/src/commands/DownstreamKey/DownstreamKeyTieCommand.ts index c81ed5d58..1bf2ca9ac 100644 --- a/src/commands/DownstreamKey/DownstreamKeyTieCommand.ts +++ b/src/commands/DownstreamKey/DownstreamKeyTieCommand.ts @@ -1,11 +1,14 @@ -import AbstractCommand from '../AbstractCommand' +import { BasicWritableCommand } from '../CommandBase' -export class DownstreamKeyTieCommand extends AbstractCommand { +export class DownstreamKeyTieCommand extends BasicWritableCommand<{ tie: boolean }> { static readonly rawName = 'CDsT' - downstreamKeyerId: number - properties: { - tie: boolean + readonly downstreamKeyerId: number + + constructor (downstreamKeyerId: number, tie: boolean) { + super({ tie }) + + this.downstreamKeyerId = downstreamKeyerId } serialize () { diff --git a/src/commands/InitCompleteCommand.ts b/src/commands/InitCompleteCommand.ts index 83dac0cd5..2a4dd0080 100644 --- a/src/commands/InitCompleteCommand.ts +++ b/src/commands/InitCompleteCommand.ts @@ -1,8 +1,11 @@ -import AbstractCommand from './AbstractCommand' +import { DeserializedCommand } from './CommandBase' -export class InitCompleteCommand extends AbstractCommand { +export class InitCompleteCommand extends DeserializedCommand { static readonly rawName = 'InCm' - readonly properties: null = null + + constructor () { + super(null) + } static deserialize () { return new InitCompleteCommand() diff --git a/src/commands/Inputs/InputPropertiesCommand.ts b/src/commands/Inputs/InputPropertiesCommand.ts index 04a895554..0cbb694df 100644 --- a/src/commands/Inputs/InputPropertiesCommand.ts +++ b/src/commands/Inputs/InputPropertiesCommand.ts @@ -1,10 +1,10 @@ -import AbstractCommand from '../AbstractCommand' +import { WritableCommand, DeserializedCommand } from '../CommandBase' import { AtemState } from '../../state' import { InputChannel } from '../../state/input' import { ExternalPorts, ExternalPortType } from '../../enums' import { Util } from '../../lib/atemUtil' -export class InputPropertiesCommand extends AbstractCommand { +export class InputPropertiesCommand extends WritableCommand { static MaskFlags = { longName: 1 << 0, shortName: 1 << 1, @@ -14,7 +14,6 @@ export class InputPropertiesCommand extends AbstractCommand { static readonly rawName = 'CInL' readonly inputId: number - properties: Partial constructor (inputId: number) { super() @@ -23,10 +22,6 @@ export class InputPropertiesCommand extends AbstractCommand { this.properties = {} } - updateProps (newProps: Partial) { - this._updateProps(newProps) - } - serialize () { const buffer = Buffer.alloc(32) buffer.writeUInt8(this.flag, 0) @@ -38,17 +33,15 @@ export class InputPropertiesCommand extends AbstractCommand { } } -export class InputPropertiesUpdateCommand extends AbstractCommand { +export class InputPropertiesUpdateCommand extends DeserializedCommand { static readonly rawName = 'InPr' readonly inputId: number - readonly properties: Readonly constructor (inputId: number, properties: InputChannel) { - super() + super(properties) this.inputId = inputId - this.properties = properties } static deserialize (rawCommand: Buffer) { diff --git a/src/commands/Macro/MacroActionCommand.ts b/src/commands/Macro/MacroActionCommand.ts index 58cdcd5ab..2aa8f9fd4 100644 --- a/src/commands/Macro/MacroActionCommand.ts +++ b/src/commands/Macro/MacroActionCommand.ts @@ -1,12 +1,15 @@ -import AbstractCommand from '../AbstractCommand' +import { BasicWritableCommand } from '../CommandBase' import { MacroAction } from '../../enums' -export class MacroActionCommand extends AbstractCommand { +export class MacroActionCommand extends BasicWritableCommand<{ action: MacroAction }> { static readonly rawName = 'MAct' - index: number - properties: { - action: MacroAction + readonly index: number + + constructor (index: number, action: MacroAction) { + super({ action }) + + this.index = index } serialize () { diff --git a/src/commands/Macro/MacroPropertiesCommand.ts b/src/commands/Macro/MacroPropertiesCommand.ts index 3c4f49389..5801924bc 100644 --- a/src/commands/Macro/MacroPropertiesCommand.ts +++ b/src/commands/Macro/MacroPropertiesCommand.ts @@ -1,19 +1,17 @@ -import AbstractCommand from '../AbstractCommand' +import { DeserializedCommand } from '../CommandBase' import { AtemState } from '../../state' import { MacroPropertiesState } from '../../state/macro' import { Util } from '../../lib/atemUtil' -export class MacroPropertiesCommand extends AbstractCommand { +export class MacroPropertiesCommand extends DeserializedCommand { static readonly rawName = 'MPrp' readonly macroIndexID: number - readonly properties: MacroPropertiesState constructor (macroIndexID: number, properties: MacroPropertiesState) { - super() + super(properties) this.macroIndexID = macroIndexID - this.properties = properties } static deserialize (rawCommand: Buffer): MacroPropertiesCommand { diff --git a/src/commands/Macro/MacroRecordingStatusCommand.ts b/src/commands/Macro/MacroRecordingStatusCommand.ts index 3b4a1f99a..151a95f02 100644 --- a/src/commands/Macro/MacroRecordingStatusCommand.ts +++ b/src/commands/Macro/MacroRecordingStatusCommand.ts @@ -1,18 +1,10 @@ -import AbstractCommand from '../AbstractCommand' +import { DeserializedCommand } from '../CommandBase' import { AtemState } from '../../state' import { MacroRecorderState } from '../../state/macro' -export class MacroRecordingStatusCommand extends AbstractCommand { +export class MacroRecordingStatusCommand extends DeserializedCommand { static readonly rawName = 'MRcS' - readonly properties: Readonly - - constructor (properties: MacroRecorderState) { - super() - - this.properties = properties - } - static deserialize (rawCommand: Buffer) { const properties = { isRecording: Boolean(rawCommand[0] & 1 << 0), diff --git a/src/commands/Macro/MacroRunStatusCommand.ts b/src/commands/Macro/MacroRunStatusCommand.ts index f2d4779e3..8490b206c 100644 --- a/src/commands/Macro/MacroRunStatusCommand.ts +++ b/src/commands/Macro/MacroRunStatusCommand.ts @@ -1,18 +1,10 @@ -import AbstractCommand from '../AbstractCommand' +import { DeserializedCommand } from '../CommandBase' import { AtemState } from '../../state' import { MacroPlayerState } from '../../state/macro' -export class MacroRunStatusCommand extends AbstractCommand { +export class MacroRunStatusCommand extends DeserializedCommand { static readonly rawName = 'MRPr' - readonly properties: Readonly - - constructor (properties: MacroPlayerState) { - super() - - this.properties = properties - } - static deserialize (rawCommand: Buffer) { const properties = { isRunning: Boolean(rawCommand[0] & 1 << 0), diff --git a/src/commands/Media/MediaPlayerSourceCommand.ts b/src/commands/Media/MediaPlayerSourceCommand.ts index ed9674bfe..24e80f356 100644 --- a/src/commands/Media/MediaPlayerSourceCommand.ts +++ b/src/commands/Media/MediaPlayerSourceCommand.ts @@ -1,8 +1,8 @@ import { AtemState } from '../../state' import { MediaPlayerSource } from '../../state/media' -import AbstractCommand from '../AbstractCommand' +import { WritableCommand, DeserializedCommand } from '../CommandBase' -export class MediaPlayerSourceCommand extends AbstractCommand { +export class MediaPlayerSourceCommand extends WritableCommand { static MaskFlags = { sourceType: 1 << 0, stillIndex: 1 << 1, @@ -12,17 +12,11 @@ export class MediaPlayerSourceCommand extends AbstractCommand { static readonly rawName = 'MPSS' readonly mediaPlayerId: number - properties: Partial constructor (mediaPlayerId: number) { super() this.mediaPlayerId = mediaPlayerId - this.properties = {} - } - - updateProps (newProps: Partial) { - this._updateProps(newProps) } serialize () { @@ -36,17 +30,15 @@ export class MediaPlayerSourceCommand extends AbstractCommand { } } -export class MediaPlayerSourceUpdateCommand extends AbstractCommand { +export class MediaPlayerSourceUpdateCommand extends DeserializedCommand { static readonly rawName = 'MPCE' readonly mediaPlayerId: number - readonly properties: Readonly constructor (mediaPlayerId: number, properties: MediaPlayerSource) { - super() + super(properties) this.mediaPlayerId = mediaPlayerId - this.properties = properties } static deserialize (rawCommand: Buffer) { diff --git a/src/commands/Media/MediaPlayerStatusCommand.ts b/src/commands/Media/MediaPlayerStatusCommand.ts index 1028ba0d1..ee81c7645 100644 --- a/src/commands/Media/MediaPlayerStatusCommand.ts +++ b/src/commands/Media/MediaPlayerStatusCommand.ts @@ -1,9 +1,9 @@ import { AtemState } from '../../state' import { MediaPlayer } from '../../state/media' -import AbstractCommand from '../AbstractCommand' +import { WritableCommand, DeserializedCommand } from '../CommandBase' import { Util } from '../../lib/atemUtil' -export class MediaPlayerStatusCommand extends AbstractCommand { +export class MediaPlayerStatusCommand extends WritableCommand { static MaskFlags = { playing: 1 << 0, loop: 1 << 1, @@ -13,17 +13,11 @@ export class MediaPlayerStatusCommand extends AbstractCommand { static readonly rawName = 'SCPS' readonly mediaPlayerId: number - properties: Partial constructor (mediaPlayerId: number) { super() this.mediaPlayerId = mediaPlayerId - this.properties = {} - } - - updateProps (newProps: Partial) { - this._updateProps(newProps) } serialize () { @@ -38,17 +32,15 @@ export class MediaPlayerStatusCommand extends AbstractCommand { } } -export class MediaPlayerStatusUpdateCommand extends AbstractCommand { +export class MediaPlayerStatusUpdateCommand extends DeserializedCommand { static readonly rawName = 'RCPS' readonly mediaPlayerId: number - readonly properties: Readonly constructor (mediaPlayerId: number, properties: MediaPlayer) { - super() + super(properties) this.mediaPlayerId = mediaPlayerId - this.properties = properties } static deserialize (rawCommand: Buffer) { diff --git a/src/commands/Media/MediaPoolClearClipCommand.ts b/src/commands/Media/MediaPoolClearClipCommand.ts index aba397a47..a1c8f0e73 100644 --- a/src/commands/Media/MediaPoolClearClipCommand.ts +++ b/src/commands/Media/MediaPoolClearClipCommand.ts @@ -1,10 +1,10 @@ -import AbstractCommand from '../AbstractCommand' +import { BasicWritableCommand } from '../CommandBase' -export class MediaPoolClearClipCommand extends AbstractCommand { +export class MediaPoolClearClipCommand extends BasicWritableCommand<{ index: number }> { static readonly rawName = 'CMPC' - properties: { - index: number + constructor (index: number) { + super({ index }) } serialize () { @@ -12,8 +12,4 @@ export class MediaPoolClearClipCommand extends AbstractCommand { buffer.writeUInt8(this.properties.index, 0) return buffer } - - updateProps (props: { index: number }) { - this._updateProps(props) - } } diff --git a/src/commands/Media/MediaPoolClearStillCommand.ts b/src/commands/Media/MediaPoolClearStillCommand.ts index 9be2ec96e..d0a22bd56 100644 --- a/src/commands/Media/MediaPoolClearStillCommand.ts +++ b/src/commands/Media/MediaPoolClearStillCommand.ts @@ -1,10 +1,10 @@ -import AbstractCommand from '../AbstractCommand' +import { BasicWritableCommand } from '../CommandBase' -export class MediaPoolClearStillCommand extends AbstractCommand { +export class MediaPoolClearStillCommand extends BasicWritableCommand<{ index: number }> { static readonly rawName = 'CSTL' - properties: { - index: number + constructor (index: number) { + super({ index }) } serialize () { @@ -12,8 +12,4 @@ export class MediaPoolClearStillCommand extends AbstractCommand { buffer.writeUInt8(this.properties.index, 0) return buffer } - - updateProps (props: { index: number }) { - this._updateProps(props) - } } diff --git a/src/commands/Media/MediaPoolClipDescription.ts b/src/commands/Media/MediaPoolClipDescription.ts index f2929c83c..6e534964b 100644 --- a/src/commands/Media/MediaPoolClipDescription.ts +++ b/src/commands/Media/MediaPoolClipDescription.ts @@ -1,19 +1,17 @@ import { AtemState } from '../../state' import { ClipBank } from '../../state/media' -import AbstractCommand from '../AbstractCommand' +import { DeserializedCommand } from '../CommandBase' import { Util } from '../../lib/atemUtil' -export class MediaPoolClipDescriptionCommand extends AbstractCommand { +export class MediaPoolClipDescriptionCommand extends DeserializedCommand { static readonly rawName = 'MPCS' readonly mediaPool: number - readonly properties: Readonly constructor (mediaPool: number, properties: ClipBank) { - super() + super(properties) this.mediaPool = mediaPool - this.properties = properties } static deserialize (rawCommand: Buffer) { diff --git a/src/commands/Media/MediaPoolFrameDescription.ts b/src/commands/Media/MediaPoolFrameDescription.ts index 4d9bbf35e..36bbf7633 100644 --- a/src/commands/Media/MediaPoolFrameDescription.ts +++ b/src/commands/Media/MediaPoolFrameDescription.ts @@ -1,21 +1,19 @@ import { AtemState } from '../../state' import { StillFrame } from '../../state/media' -import AbstractCommand from '../AbstractCommand' +import { DeserializedCommand } from '../CommandBase' import { Util } from '../../lib/atemUtil' -export class MediaPoolFrameDescriptionCommand extends AbstractCommand { +export class MediaPoolFrameDescriptionCommand extends DeserializedCommand { static readonly rawName = 'MPfe' readonly mediaPool: number readonly frameIndex: number - readonly properties: Readonly - constructor (mediaPool: number, frameIndex: number,properties: StillFrame) { - super() + constructor (mediaPool: number, frameIndex: number, properties: StillFrame) { + super(properties) this.mediaPool = mediaPool this.frameIndex = frameIndex - this.properties = properties } static deserialize (rawCommand: Buffer) { diff --git a/src/commands/Media/MediaPoolSetClipCommand.ts b/src/commands/Media/MediaPoolSetClipCommand.ts index f7fae040e..13a0f18f1 100644 --- a/src/commands/Media/MediaPoolSetClipCommand.ts +++ b/src/commands/Media/MediaPoolSetClipCommand.ts @@ -1,13 +1,13 @@ -import AbstractCommand from '../AbstractCommand' +import { BasicWritableCommand } from '../CommandBase' -export class MediaPoolSetClipCommand extends AbstractCommand { - static readonly rawName = 'SMPC' +export interface MediaPoolSetClipProps { + index: number, + name: string, + frames: number +} - properties: { - index: number, - name: string, - frames: number - } +export class MediaPoolSetClipCommand extends BasicWritableCommand { + static readonly rawName = 'SMPC' serialize () { const buffer = Buffer.alloc(68) diff --git a/src/commands/MixEffects/AutoTransitionCommand.ts b/src/commands/MixEffects/AutoTransitionCommand.ts index c4fb7878a..3a08e4196 100644 --- a/src/commands/MixEffects/AutoTransitionCommand.ts +++ b/src/commands/MixEffects/AutoTransitionCommand.ts @@ -1,10 +1,15 @@ -import AbstractCommand from '../AbstractCommand' +import { BasicWritableCommand } from '../CommandBase' -export class AutoTransitionCommand extends AbstractCommand { +export class AutoTransitionCommand extends BasicWritableCommand { static readonly rawName = 'DAut' - mixEffect: number - properties: null + readonly mixEffect: number + + constructor (mixEffect: number) { + super(null) + + this.mixEffect = mixEffect + } serialize () { const buffer = Buffer.alloc(4) diff --git a/src/commands/MixEffects/CutCommand.ts b/src/commands/MixEffects/CutCommand.ts index 236a20d57..1ba62cf91 100644 --- a/src/commands/MixEffects/CutCommand.ts +++ b/src/commands/MixEffects/CutCommand.ts @@ -1,10 +1,15 @@ -import AbstractCommand from '../AbstractCommand' +import { BasicWritableCommand } from '../CommandBase' -export class CutCommand extends AbstractCommand { +export class CutCommand extends BasicWritableCommand { static readonly rawName = 'DCut' - mixEffect: number - properties: null + readonly mixEffect: number + + constructor (mixEffect: number) { + super(null) + + this.mixEffect = mixEffect + } serialize () { const buffer = Buffer.alloc(4) diff --git a/src/commands/MixEffects/FadeToBlack/FadeToBlackAutoCommand.ts b/src/commands/MixEffects/FadeToBlack/FadeToBlackAutoCommand.ts index 3dd41d3b9..5d2fe0cf8 100644 --- a/src/commands/MixEffects/FadeToBlack/FadeToBlackAutoCommand.ts +++ b/src/commands/MixEffects/FadeToBlack/FadeToBlackAutoCommand.ts @@ -1,10 +1,15 @@ -import AbstractCommand from '../../AbstractCommand' +import { BasicWritableCommand } from '../../CommandBase' -export class FadeToBlackAutoCommand extends AbstractCommand { +export class FadeToBlackAutoCommand extends BasicWritableCommand { static readonly rawName = 'FtbA' - mixEffect: number - properties: {} + readonly mixEffect: number + + constructor (mixEffect: number) { + super(null) + + this.mixEffect = mixEffect + } serialize () { const buffer = Buffer.alloc(4) diff --git a/src/commands/MixEffects/FadeToBlack/FadeToBlackRateCommand.ts b/src/commands/MixEffects/FadeToBlack/FadeToBlackRateCommand.ts index 596b636e8..8d2d11497 100644 --- a/src/commands/MixEffects/FadeToBlack/FadeToBlackRateCommand.ts +++ b/src/commands/MixEffects/FadeToBlack/FadeToBlackRateCommand.ts @@ -1,17 +1,14 @@ -import AbstractCommand from '../../AbstractCommand' +import { BasicWritableCommand, DeserializedCommand } from '../../CommandBase' import { AtemState } from '../../../state' import { Util } from '../../..' -export class FadeToBlackRateCommand extends AbstractCommand { +export class FadeToBlackRateCommand extends BasicWritableCommand<{ rate: number }> { static readonly rawName = 'FtbC' readonly mixEffect: number - readonly properties: Readonly<{ - rate: number - }> constructor (mixEffect: number, rate: number) { - super() + super({ rate }) this.mixEffect = mixEffect this.properties = { rate } @@ -26,28 +23,22 @@ export class FadeToBlackRateCommand extends AbstractCommand { } } -export class FadeToBlackRateUpdateCommand extends AbstractCommand { +export class FadeToBlackRateUpdateCommand extends DeserializedCommand<{ rate: number }> { static readonly rawName = 'FtbP' readonly mixEffect: number - readonly properties: Readonly<{ - rate: number - }> - constructor (mixEffect: number, properties: FadeToBlackRateUpdateCommand['properties']) { - super() + constructor (mixEffect: number, rate: number) { + super({ rate }) this.mixEffect = mixEffect - this.properties = properties } static deserialize (rawCommand: Buffer) { const mixEffect = Util.parseNumberBetween(rawCommand[0], 0, 3) - const properties = { - rate: rawCommand.readUInt8(1) - } + const rate = rawCommand.readUInt8(1) - return new FadeToBlackRateUpdateCommand(mixEffect, properties) + return new FadeToBlackRateUpdateCommand(mixEffect, rate) } applyToState (state: AtemState) { diff --git a/src/commands/MixEffects/FadeToBlack/FadeToBlackStateCommand.ts b/src/commands/MixEffects/FadeToBlack/FadeToBlackStateCommand.ts index 4a70f544f..6a45a4528 100644 --- a/src/commands/MixEffects/FadeToBlack/FadeToBlackStateCommand.ts +++ b/src/commands/MixEffects/FadeToBlack/FadeToBlackStateCommand.ts @@ -1,22 +1,22 @@ -import AbstractCommand from '../../AbstractCommand' +import { DeserializedCommand } from '../../CommandBase' import { AtemState } from '../../../state' import { Util } from '../../..' -export class FadeToBlackStateCommand extends AbstractCommand { +export interface FadeToBlackProps { + isFullyBlack: boolean + inTransition: boolean + remainingFrames: number +} + +export class FadeToBlackStateCommand extends DeserializedCommand { static readonly rawName = 'FtbS' readonly mixEffect: number - readonly properties: Readonly<{ - isFullyBlack: boolean - inTransition: boolean - remainingFrames: number - }> - constructor (mixEffect: number, properties: FadeToBlackStateCommand['properties']) { - super() + constructor (mixEffect: number, properties: FadeToBlackProps) { + super(properties) this.mixEffect = mixEffect - this.properties = properties } static deserialize (rawCommand: Buffer) { diff --git a/src/commands/MixEffects/Key/MixEffectKeyChromaCommand.ts b/src/commands/MixEffects/Key/MixEffectKeyChromaCommand.ts index 320b4f237..64c8e34fc 100644 --- a/src/commands/MixEffects/Key/MixEffectKeyChromaCommand.ts +++ b/src/commands/MixEffects/Key/MixEffectKeyChromaCommand.ts @@ -1,9 +1,9 @@ -import AbstractCommand from '../../AbstractCommand' +import { WritableCommand, DeserializedCommand } from '../../CommandBase' import { AtemState } from '../../../state' import { UpstreamKeyerChromaSettings } from '../../../state/video/upstreamKeyers' import { Util } from '../../..' -export class MixEffectKeyChromaCommand extends AbstractCommand { +export class MixEffectKeyChromaCommand extends WritableCommand { static MaskFlags = { hue: 1 << 0, gain: 1 << 1, @@ -15,14 +15,12 @@ export class MixEffectKeyChromaCommand extends AbstractCommand { readonly mixEffect: number readonly upstreamKeyerId: number - properties: Partial constructor (mixEffect: number, upstreamKeyerId: number) { super() this.mixEffect = mixEffect this.upstreamKeyerId = upstreamKeyerId - this.properties = {} } serialize () { @@ -41,19 +39,17 @@ export class MixEffectKeyChromaCommand extends AbstractCommand { } } -export class MixEffectKeyChromaUpdateCommand extends AbstractCommand { +export class MixEffectKeyChromaUpdateCommand extends DeserializedCommand { static readonly rawName = 'KeCk' readonly mixEffect: number readonly upstreamKeyerId: number - readonly properties: Readonly constructor (mixEffect: number, upstreamKeyerId: number, properties: UpstreamKeyerChromaSettings) { - super() + super(properties) this.mixEffect = mixEffect this.upstreamKeyerId = upstreamKeyerId - this.properties = properties } static deserialize (rawCommand: Buffer) { diff --git a/src/commands/MixEffects/Key/MixEffectKeyCutSourceSetCommand.ts b/src/commands/MixEffects/Key/MixEffectKeyCutSourceSetCommand.ts index 4f8c1bcfe..a44d4a6f0 100644 --- a/src/commands/MixEffects/Key/MixEffectKeyCutSourceSetCommand.ts +++ b/src/commands/MixEffects/Key/MixEffectKeyCutSourceSetCommand.ts @@ -1,11 +1,16 @@ -import AbstractCommand from '../../AbstractCommand' +import { BasicWritableCommand } from '../../CommandBase' -export class MixEffectKeyCutSourceSetCommand extends AbstractCommand { +export class MixEffectKeyCutSourceSetCommand extends BasicWritableCommand<{ cutSource: number }> { static readonly rawName = 'CKeC' - mixEffect: number - upstreamKeyerId: number - properties: { - cutSource: number + + readonly mixEffect: number + readonly upstreamKeyerId: number + + constructor (mixEffect: number, upstreamKeyerId: number, cutSource: number) { + super({ cutSource }) + + this.mixEffect = mixEffect + this.upstreamKeyerId = upstreamKeyerId } serialize () { diff --git a/src/commands/MixEffects/Key/MixEffectKeyDVECommand.ts b/src/commands/MixEffects/Key/MixEffectKeyDVECommand.ts index 52566b848..360ebb54d 100644 --- a/src/commands/MixEffects/Key/MixEffectKeyDVECommand.ts +++ b/src/commands/MixEffects/Key/MixEffectKeyDVECommand.ts @@ -1,9 +1,9 @@ -import AbstractCommand from '../../AbstractCommand' +import { WritableCommand, DeserializedCommand } from '../../CommandBase' import { AtemState } from '../../../state' import { UpstreamKeyerDVESettings } from '../../../state/video/upstreamKeyers' import { Util, Enums } from '../../..' -export class MixEffectKeyDVECommand extends AbstractCommand { +export class MixEffectKeyDVECommand extends WritableCommand { static MaskFlags = { sizeX: 1 << 0, sizeY: 1 << 1, @@ -36,7 +36,6 @@ export class MixEffectKeyDVECommand extends AbstractCommand { readonly mixEffect: number readonly upstreamKeyerId: number - properties: Partial constructor (mixEffect: number, upstreamKeyerId: number) { super() @@ -88,19 +87,17 @@ export class MixEffectKeyDVECommand extends AbstractCommand { } } -export class MixEffectKeyDVEUpdateCommand extends AbstractCommand { +export class MixEffectKeyDVEUpdateCommand extends DeserializedCommand { static readonly rawName = 'KeDV' readonly mixEffect: number readonly upstreamKeyerId: number - readonly properties: Readonly constructor (mixEffect: number, upstreamKeyerId: number, properties: UpstreamKeyerDVESettings) { - super() + super(properties) this.mixEffect = mixEffect this.upstreamKeyerId = upstreamKeyerId - this.properties = properties } static deserialize (rawCommand: Buffer) { diff --git a/src/commands/MixEffects/Key/MixEffectKeyFillSourceSetCommand.ts b/src/commands/MixEffects/Key/MixEffectKeyFillSourceSetCommand.ts index 0ad9cf8ef..b9a59ff9a 100644 --- a/src/commands/MixEffects/Key/MixEffectKeyFillSourceSetCommand.ts +++ b/src/commands/MixEffects/Key/MixEffectKeyFillSourceSetCommand.ts @@ -1,11 +1,16 @@ -import AbstractCommand from '../../AbstractCommand' +import { BasicWritableCommand } from '../../CommandBase' -export class MixEffectKeyFillSourceSetCommand extends AbstractCommand { +export class MixEffectKeyFillSourceSetCommand extends BasicWritableCommand<{ fillSource: number }> { static readonly rawName = 'CKeF' - mixEffect: number - upstreamKeyerId: number - properties: { - fillSource: number + + readonly mixEffect: number + readonly upstreamKeyerId: number + + constructor (mixEffect: number, upstreamKeyerId: number, fillSource: number) { + super({ fillSource }) + + this.mixEffect = mixEffect + this.upstreamKeyerId = upstreamKeyerId } serialize () { diff --git a/src/commands/MixEffects/Key/MixEffectKeyFlyKeyframeGetCommand.ts b/src/commands/MixEffects/Key/MixEffectKeyFlyKeyframeGetCommand.ts index b1347fa0e..1574254c1 100644 --- a/src/commands/MixEffects/Key/MixEffectKeyFlyKeyframeGetCommand.ts +++ b/src/commands/MixEffects/Key/MixEffectKeyFlyKeyframeGetCommand.ts @@ -1,23 +1,21 @@ -import AbstractCommand from '../../AbstractCommand' +import { DeserializedCommand } from '../../CommandBase' import { AtemState } from '../../../state' import { UpstreamKeyerFlyKeyframe } from '../../../state/video/upstreamKeyers' import { Util } from '../../..' -export class MixEffectKeyFlyKeyframeGetCommand extends AbstractCommand { +export class MixEffectKeyFlyKeyframeGetCommand extends DeserializedCommand { static readonly rawName = 'KKFP' readonly mixEffect: number readonly upstreamKeyerId: number readonly keyFrameId: number - readonly properties: Readonly constructor (mixEffect: number, upstreamKeyerId: number, keyFrameId: number, properties: UpstreamKeyerFlyKeyframe) { - super() + super(properties) this.mixEffect = mixEffect this.upstreamKeyerId = upstreamKeyerId this.keyFrameId = keyFrameId - this.properties = properties } static deserialize (rawCommand: Buffer) { diff --git a/src/commands/MixEffects/Key/MixEffectKeyFlyPropertiesGetCommand.ts b/src/commands/MixEffects/Key/MixEffectKeyFlyPropertiesGetCommand.ts index acfdece71..6b60167da 100644 --- a/src/commands/MixEffects/Key/MixEffectKeyFlyPropertiesGetCommand.ts +++ b/src/commands/MixEffects/Key/MixEffectKeyFlyPropertiesGetCommand.ts @@ -1,21 +1,19 @@ -import AbstractCommand from '../../AbstractCommand' +import { DeserializedCommand } from '../../CommandBase' import { AtemState } from '../../../state' import { UpstreamKeyerFlySettings } from '../../../state/video/upstreamKeyers' import { Util } from '../../..' -export class MixEffectKeyFlyPropertiesGetCommand extends AbstractCommand { +export class MixEffectKeyFlyPropertiesGetCommand extends DeserializedCommand { static readonly rawName = 'KeFS' readonly mixEffect: number readonly upstreamKeyerId: number - readonly properties: Readonly constructor (mixEffect: number, upstreamKeyerId: number, properties: UpstreamKeyerFlySettings) { - super() + super(properties) this.mixEffect = mixEffect this.upstreamKeyerId = upstreamKeyerId - this.properties = properties } static deserialize (rawCommand: Buffer) { diff --git a/src/commands/MixEffects/Key/MixEffectKeyLumaCommand.ts b/src/commands/MixEffects/Key/MixEffectKeyLumaCommand.ts index 01545e21c..ef54a139a 100644 --- a/src/commands/MixEffects/Key/MixEffectKeyLumaCommand.ts +++ b/src/commands/MixEffects/Key/MixEffectKeyLumaCommand.ts @@ -1,9 +1,9 @@ -import AbstractCommand from '../../AbstractCommand' +import { WritableCommand, DeserializedCommand } from '../../CommandBase' import { AtemState } from '../../../state' import { UpstreamKeyerLumaSettings } from '../../../state/video/upstreamKeyers' import { Util } from '../../..' -export class MixEffectKeyLumaCommand extends AbstractCommand { +export class MixEffectKeyLumaCommand extends WritableCommand { static MaskFlags = { preMultiplied: 1 << 0, clip: 1 << 1, @@ -14,14 +14,12 @@ export class MixEffectKeyLumaCommand extends AbstractCommand { readonly mixEffect: number readonly upstreamKeyerId: number - properties: Partial constructor (mixEffect: number, upstreamKeyerId: number) { super() this.mixEffect = mixEffect this.upstreamKeyerId = upstreamKeyerId - this.properties = {} } serialize () { @@ -39,19 +37,17 @@ export class MixEffectKeyLumaCommand extends AbstractCommand { } } -export class MixEffectKeyLumaUpdateCommand extends AbstractCommand { +export class MixEffectKeyLumaUpdateCommand extends DeserializedCommand { static readonly rawName = 'KeLm' readonly mixEffect: number readonly upstreamKeyerId: number - readonly properties: Readonly constructor (mixEffect: number, upstreamKeyerId: number, properties: UpstreamKeyerLumaSettings) { - super() + super(properties) this.mixEffect = mixEffect this.upstreamKeyerId = upstreamKeyerId - this.properties = properties } static deserialize (rawCommand: Buffer) { diff --git a/src/commands/MixEffects/Key/MixEffectKeyMaskSetCommand.ts b/src/commands/MixEffects/Key/MixEffectKeyMaskSetCommand.ts index d83f3ce9e..7679a2cc9 100644 --- a/src/commands/MixEffects/Key/MixEffectKeyMaskSetCommand.ts +++ b/src/commands/MixEffects/Key/MixEffectKeyMaskSetCommand.ts @@ -1,7 +1,7 @@ -import AbstractCommand from '../../AbstractCommand' +import { WritableCommand } from '../../CommandBase' import { UpstreamKeyerMaskSettings } from '../../../state/video/upstreamKeyers' -export class MixEffectKeyMaskSetCommand extends AbstractCommand { +export class MixEffectKeyMaskSetCommand extends WritableCommand { static MaskFlags = { maskEnabled: 1 << 0, maskTop: 1 << 1, @@ -11,9 +11,16 @@ export class MixEffectKeyMaskSetCommand extends AbstractCommand { } static readonly rawName = 'CKMs' - mixEffect: number - upstreamKeyerId: number - properties: UpstreamKeyerMaskSettings + + readonly mixEffect: number + readonly upstreamKeyerId: number + + constructor (mixEffect: number, upstreamKeyerId: number) { + super() + + this.mixEffect = mixEffect + this.upstreamKeyerId = upstreamKeyerId + } serialize () { const buffer = Buffer.alloc(12) @@ -22,10 +29,10 @@ export class MixEffectKeyMaskSetCommand extends AbstractCommand { buffer.writeUInt8(this.upstreamKeyerId, 2) buffer.writeUInt8(this.properties.maskEnabled ? 1 : 0, 3) - buffer.writeInt16BE(this.properties.maskTop, 4) - buffer.writeInt16BE(this.properties.maskBottom, 6) - buffer.writeInt16BE(this.properties.maskLeft, 8) - buffer.writeInt16BE(this.properties.maskRight, 10) + buffer.writeInt16BE(this.properties.maskTop || 0, 4) + buffer.writeInt16BE(this.properties.maskBottom || 0, 6) + buffer.writeInt16BE(this.properties.maskLeft || 0, 8) + buffer.writeInt16BE(this.properties.maskRight || 0, 10) return buffer } diff --git a/src/commands/MixEffects/Key/MixEffectKeyOnAirCommand.ts b/src/commands/MixEffects/Key/MixEffectKeyOnAirCommand.ts index 5503a6aea..7b035bee1 100644 --- a/src/commands/MixEffects/Key/MixEffectKeyOnAirCommand.ts +++ b/src/commands/MixEffects/Key/MixEffectKeyOnAirCommand.ts @@ -1,22 +1,18 @@ -import AbstractCommand from '../../AbstractCommand' +import { BasicWritableCommand, DeserializedCommand } from '../../CommandBase' import { AtemState } from '../../../state' import { Util } from '../../..' -export class MixEffectKeyOnAirCommand extends AbstractCommand { +export class MixEffectKeyOnAirCommand extends BasicWritableCommand<{ onAir: boolean}> { static readonly rawName = 'CKOn' readonly mixEffect: number readonly upstreamKeyerId: number - readonly properties: Readonly<{ - onAir: boolean - }> constructor (mixEffect: number, upstreamKeyerId: number, onAir: boolean) { - super() + super({ onAir }) this.mixEffect = mixEffect this.upstreamKeyerId = upstreamKeyerId - this.properties = { onAir } } serialize () { @@ -28,21 +24,17 @@ export class MixEffectKeyOnAirCommand extends AbstractCommand { } } -export class MixEffectKeyOnAirUpdateCommand extends AbstractCommand { +export class MixEffectKeyOnAirUpdateCommand extends DeserializedCommand<{onAir: boolean}> { static readonly rawName = 'KeOn' readonly mixEffect: number readonly upstreamKeyerId: number - readonly properties: Readonly<{ - onAir: boolean - }> constructor (mixEffect: number, upstreamKeyerId: number, properties: MixEffectKeyOnAirUpdateCommand['properties']) { - super() + super(properties) this.mixEffect = mixEffect this.upstreamKeyerId = upstreamKeyerId - this.properties = properties } static deserialize (rawCommand: Buffer) { diff --git a/src/commands/MixEffects/Key/MixEffectKeyPatternCommand.ts b/src/commands/MixEffects/Key/MixEffectKeyPatternCommand.ts index c2b8e1b54..9ab0dfd83 100644 --- a/src/commands/MixEffects/Key/MixEffectKeyPatternCommand.ts +++ b/src/commands/MixEffects/Key/MixEffectKeyPatternCommand.ts @@ -1,4 +1,4 @@ -import AbstractCommand, { WritableCommand } from '../../AbstractCommand' +import { WritableCommand, DeserializedCommand } from '../../CommandBase' import { AtemState } from '../../../state' import { UpstreamKeyerPatternSettings } from '../../../state/video/upstreamKeyers' import { Util, Enums } from '../../..' @@ -44,19 +44,17 @@ export class MixEffectKeyPatternCommand extends WritableCommand { static readonly rawName = 'KePt' readonly mixEffect: number readonly upstreamKeyerId: number - readonly properties: Readonly constructor (mixEffect: number, upstreamKeyerId: number, properties: UpstreamKeyerPatternSettings) { - super() + super(properties) this.mixEffect = mixEffect this.upstreamKeyerId = upstreamKeyerId - this.properties = properties } static deserialize (rawCommand: Buffer): MixEffectKeyUpdateCommand { diff --git a/src/commands/MixEffects/Key/MixEffectKeyPropertiesGetCommand.ts b/src/commands/MixEffects/Key/MixEffectKeyPropertiesGetCommand.ts index 7adf164b5..6e4337dc6 100644 --- a/src/commands/MixEffects/Key/MixEffectKeyPropertiesGetCommand.ts +++ b/src/commands/MixEffects/Key/MixEffectKeyPropertiesGetCommand.ts @@ -1,19 +1,17 @@ -import AbstractCommand from '../../AbstractCommand' +import { DeserializedCommand } from '../../CommandBase' import { AtemState } from '../../../state' import { UpstreamKeyerBase } from '../../../state/video/upstreamKeyers' import { Util, Enums } from '../../..' -export class MixEffectKeyPropertiesGetCommand extends AbstractCommand { +export class MixEffectKeyPropertiesGetCommand extends DeserializedCommand { static readonly rawName = 'KeBP' readonly mixEffect: number - readonly properties: Readonly constructor (mixEffect: number, properties: UpstreamKeyerBase) { - super() + super(properties) this.mixEffect = mixEffect - this.properties = properties } static deserialize (rawCommand: Buffer): MixEffectKeyPropertiesGetCommand { diff --git a/src/commands/MixEffects/Key/MixEffectKeyTypeSetCommand.ts b/src/commands/MixEffects/Key/MixEffectKeyTypeSetCommand.ts index 71a1fcadb..9f0296f9b 100644 --- a/src/commands/MixEffects/Key/MixEffectKeyTypeSetCommand.ts +++ b/src/commands/MixEffects/Key/MixEffectKeyTypeSetCommand.ts @@ -1,16 +1,23 @@ -import AbstractCommand from '../../AbstractCommand' +import { WritableCommand } from '../../CommandBase' import { UpstreamKeyerTypeSettings } from '../../../state/video/upstreamKeyers' -export class MixEffectKeyTypeSetCommand extends AbstractCommand { +export class MixEffectKeyTypeSetCommand extends WritableCommand { static MaskFlags = { keyType: 1 << 0, flyEnabled: 1 << 1 } static readonly rawName = 'CKTp' - mixEffect: number - upstreamKeyerId: number - properties: UpstreamKeyerTypeSettings + + readonly mixEffect: number + readonly upstreamKeyerId: number + + constructor (mixEffect: number, upstreamKeyerId: number) { + super() + + this.mixEffect = mixEffect + this.upstreamKeyerId = upstreamKeyerId + } serialize () { const buffer = Buffer.alloc(8) @@ -18,7 +25,7 @@ export class MixEffectKeyTypeSetCommand extends AbstractCommand { buffer.writeUInt8(this.mixEffect, 1) buffer.writeUInt8(this.upstreamKeyerId, 2) - buffer.writeUInt8(this.properties.keyType, 3) + buffer.writeUInt8(this.properties.keyType || 0, 3) buffer.writeUInt8(this.properties.flyEnabled ? 1 : 0, 4) return buffer diff --git a/src/commands/MixEffects/PreviewInputCommand.ts b/src/commands/MixEffects/PreviewInputCommand.ts index 4594f0aba..4d9a58956 100644 --- a/src/commands/MixEffects/PreviewInputCommand.ts +++ b/src/commands/MixEffects/PreviewInputCommand.ts @@ -1,4 +1,4 @@ -import AbstractCommand, { BasicWritableCommand } from '../AbstractCommand' +import { BasicWritableCommand, DeserializedCommand } from '../CommandBase' import { AtemState } from '../../state' import { Util } from '../..' @@ -12,12 +12,9 @@ export class PreviewInputCommand extends BasicWritableCommand { readonly mixEffect: number constructor (mixEffect: number, source: number) { - super() + super({ source }) this.mixEffect = mixEffect - this.properties = { - source - } } serialize () { @@ -28,17 +25,15 @@ export class PreviewInputCommand extends BasicWritableCommand { } } -export class PreviewInputUpdateCommand extends AbstractCommand { +export class PreviewInputUpdateCommand extends DeserializedCommand { static readonly rawName = 'PrvI' - readonly mixEffect: number - readonly properties: Readonly + readonly mixEffect: number constructor (mixEffect: number, properties: InputSource) { - super() + super(properties) this.mixEffect = mixEffect - this.properties = properties } static deserialize (rawCommand: Buffer): PreviewInputUpdateCommand { diff --git a/src/commands/MixEffects/ProgramInputCommand.ts b/src/commands/MixEffects/ProgramInputCommand.ts index a5560c4b5..85a408a41 100644 --- a/src/commands/MixEffects/ProgramInputCommand.ts +++ b/src/commands/MixEffects/ProgramInputCommand.ts @@ -1,4 +1,4 @@ -import AbstractCommand, { BasicWritableCommand } from '../AbstractCommand' +import { BasicWritableCommand, DeserializedCommand } from '../CommandBase' import { AtemState } from '../../state' import { Util } from '../..' @@ -12,12 +12,9 @@ export class ProgramInputCommand extends BasicWritableCommand { readonly mixEffect: number constructor (mixEffect: number, source: number) { - super() + super({ source }) this.mixEffect = mixEffect - this.properties = { - source - } } serialize () { @@ -28,20 +25,17 @@ export class ProgramInputCommand extends BasicWritableCommand { } } -export class ProgramInputUpdateCommand extends AbstractCommand { +export class ProgramInputUpdateCommand extends DeserializedCommand { static readonly rawName = 'PrgI' - readonly mixEffect: number - readonly properties: Readonly + readonly mixEffect: number constructor (mixEffect: number, properties: InputSource) { - super() + super(properties) this.mixEffect = mixEffect - this.properties = properties } - static deserialize (rawCommand: Buffer): ProgramInputUpdateCommand { const mixEffect = Util.parseNumberBetween(rawCommand[0], 0, 3) const properties = { diff --git a/src/commands/MixEffects/Transition/TransitionDVECommand.ts b/src/commands/MixEffects/Transition/TransitionDVECommand.ts index 56264d128..87fbe7c34 100644 --- a/src/commands/MixEffects/Transition/TransitionDVECommand.ts +++ b/src/commands/MixEffects/Transition/TransitionDVECommand.ts @@ -1,4 +1,4 @@ -import AbstractCommand, { WritableCommand } from '../../AbstractCommand' +import { WritableCommand, DeserializedCommand } from '../../CommandBase' import { AtemState } from '../../../state' import { DVETransitionSettings } from '../../../state/video' import { Util, Enums } from '../../..' @@ -53,17 +53,15 @@ export class TransitionDVECommand extends WritableCommand } } -export class TransitionDVEUpdateCommand extends AbstractCommand { +export class TransitionDVEUpdateCommand extends DeserializedCommand { static readonly rawName = 'TDvP' readonly mixEffect: number - readonly properties: Readonly constructor (mixEffect: number, properties: DVETransitionSettings) { - super() + super(properties) this.mixEffect = mixEffect - this.properties = properties } static deserialize (rawCommand: Buffer): TransitionDVEUpdateCommand { diff --git a/src/commands/MixEffects/Transition/TransitionDipCommand.ts b/src/commands/MixEffects/Transition/TransitionDipCommand.ts index 550faaa35..b6a0979ed 100644 --- a/src/commands/MixEffects/Transition/TransitionDipCommand.ts +++ b/src/commands/MixEffects/Transition/TransitionDipCommand.ts @@ -1,4 +1,4 @@ -import AbstractCommand, { WritableCommand } from '../../AbstractCommand' +import { WritableCommand, DeserializedCommand } from '../../CommandBase' import { AtemState } from '../../../state' import { DipTransitionSettings } from '../../../state/video' import { Util } from '../../..' @@ -28,17 +28,15 @@ export class TransitionDipCommand extends WritableCommand } } -export class TransitionDipUpdateCommand extends AbstractCommand { +export class TransitionDipUpdateCommand extends DeserializedCommand { static readonly rawName = 'TDpP' readonly mixEffect: number - readonly properties: Readonly constructor (mixEffect: number, properties: DipTransitionSettings) { - super() + super(properties) this.mixEffect = mixEffect - this.properties = properties } static deserialize (rawCommand: Buffer): TransitionDipUpdateCommand { diff --git a/src/commands/MixEffects/Transition/TransitionMixCommand.ts b/src/commands/MixEffects/Transition/TransitionMixCommand.ts index e1261ea35..3655c6b74 100644 --- a/src/commands/MixEffects/Transition/TransitionMixCommand.ts +++ b/src/commands/MixEffects/Transition/TransitionMixCommand.ts @@ -1,4 +1,4 @@ -import AbstractCommand, { WritableCommand } from '../../AbstractCommand' +import { WritableCommand, DeserializedCommand } from '../../CommandBase' import { AtemState } from '../../../state' import { MixTransitionSettings } from '../../../state/video' import { Util } from '../../..' @@ -22,17 +22,15 @@ export class TransitionMixCommand extends WritableCommand } } -export class TransitionMixUpdateCommand extends AbstractCommand { +export class TransitionMixUpdateCommand extends DeserializedCommand { static readonly rawName = 'TMxP' readonly mixEffect: number - readonly properties: Readonly constructor (mixEffect: number, properties: MixTransitionSettings) { - super() + super(properties) this.mixEffect = mixEffect - this.properties = properties } static deserialize (rawCommand: Buffer): TransitionMixUpdateCommand { diff --git a/src/commands/MixEffects/Transition/TransitionPositionCommand.ts b/src/commands/MixEffects/Transition/TransitionPositionCommand.ts index a6ebbd60e..17ab830b9 100644 --- a/src/commands/MixEffects/Transition/TransitionPositionCommand.ts +++ b/src/commands/MixEffects/Transition/TransitionPositionCommand.ts @@ -1,4 +1,4 @@ -import AbstractCommand, { BasicWritableCommand } from '../../AbstractCommand' +import { BasicWritableCommand, DeserializedCommand } from '../../CommandBase' import { AtemState } from '../../../state' import { Util } from '../../..' @@ -12,10 +12,9 @@ export class TransitionPositionCommand extends BasicWritableCommand { static readonly rawName = 'TrPs' readonly mixEffect: number - readonly properties: Readonly<{ - inTransition: boolean - remainingFrames: number // 0...250 - handlePosition: number // 0...10000 - }> - constructor (mixEffect: number, properties: TransitionPositionUpdateCommand['properties']) { - super() + constructor (mixEffect: number, properties: TransitionPositionProps) { + super(properties) this.mixEffect = mixEffect - this.properties = properties } static deserialize (rawCommand: Buffer): TransitionPositionUpdateCommand { diff --git a/src/commands/MixEffects/Transition/TransitionPreviewCommand.ts b/src/commands/MixEffects/Transition/TransitionPreviewCommand.ts index 8d3f93c87..b9bc7ea08 100644 --- a/src/commands/MixEffects/Transition/TransitionPreviewCommand.ts +++ b/src/commands/MixEffects/Transition/TransitionPreviewCommand.ts @@ -1,4 +1,4 @@ -import AbstractCommand, { BasicWritableCommand } from '../../AbstractCommand' +import { BasicWritableCommand, DeserializedCommand } from '../../CommandBase' import { AtemState } from '../../../state' import { Util } from '../../..' @@ -12,10 +12,9 @@ export class PreviewTransitionCommand extends BasicWritableCommand readonly mixEffect: number constructor (mixEffect: number, preview: boolean) { - super() + super({ preview }) this.mixEffect = mixEffect - this.properties = { preview } } serialize () { @@ -26,17 +25,15 @@ export class PreviewTransitionCommand extends BasicWritableCommand } } -export class PreviewTransitionUpdateCommand extends AbstractCommand { +export class PreviewTransitionUpdateCommand extends DeserializedCommand { static readonly rawName = 'TrPr' readonly mixEffect: number - readonly properties: Readonly constructor (mixEffect: number, properties: PreviewProps) { - super() + super(properties) this.mixEffect = mixEffect - this.properties = properties } static deserialize (rawCommand: Buffer): PreviewTransitionUpdateCommand { diff --git a/src/commands/MixEffects/Transition/TransitionPropertiesCommand.ts b/src/commands/MixEffects/Transition/TransitionPropertiesCommand.ts index ce300be18..6cf4bf3b6 100644 --- a/src/commands/MixEffects/Transition/TransitionPropertiesCommand.ts +++ b/src/commands/MixEffects/Transition/TransitionPropertiesCommand.ts @@ -1,4 +1,4 @@ -import AbstractCommand, { WritableCommand } from '../../AbstractCommand' +import { WritableCommand, DeserializedCommand } from '../../CommandBase' import { AtemState } from '../../../state' import { TransitionProperties } from '../../../state/video' import { Util, Enums } from '../../..' @@ -31,17 +31,15 @@ export class TransitionPropertiesCommand extends WritableCommand { static readonly rawName = 'TrSS' readonly mixEffect: number - readonly properties: Readonly constructor (mixEffect: number, properties: TransitionProperties) { - super() + super(properties) this.mixEffect = mixEffect - this.properties = properties } static deserialize (rawCommand: Buffer): TransitionPropertiesUpdateCommand { diff --git a/src/commands/MixEffects/Transition/TransitionStingerCommand.ts b/src/commands/MixEffects/Transition/TransitionStingerCommand.ts index 6772e0680..b71ee26b0 100644 --- a/src/commands/MixEffects/Transition/TransitionStingerCommand.ts +++ b/src/commands/MixEffects/Transition/TransitionStingerCommand.ts @@ -1,4 +1,4 @@ -import AbstractCommand, { WritableCommand } from '../../AbstractCommand' +import { WritableCommand, DeserializedCommand } from '../../CommandBase' import { AtemState } from '../../../state' import { StingerTransitionSettings } from '../../../state/video' import { Util } from '../../..' @@ -47,17 +47,15 @@ export class TransitionStingerCommand extends WritableCommand { static readonly rawName = 'TStP' readonly mixEffect: number - readonly properties: Readonly constructor (mixEffect: number, properties: StingerTransitionSettings) { - super() + super(properties) this.mixEffect = mixEffect - this.properties = properties } static deserialize (rawCommand: Buffer): TransitionStingerUpdateCommand { diff --git a/src/commands/MixEffects/Transition/TransitionWipeCommand.ts b/src/commands/MixEffects/Transition/TransitionWipeCommand.ts index 85da8212d..846cd5885 100644 --- a/src/commands/MixEffects/Transition/TransitionWipeCommand.ts +++ b/src/commands/MixEffects/Transition/TransitionWipeCommand.ts @@ -1,4 +1,4 @@ -import AbstractCommand, { WritableCommand } from '../../AbstractCommand' +import { WritableCommand, DeserializedCommand } from '../../CommandBase' import { AtemState } from '../../../state' import { WipeTransitionSettings } from '../../../state/video' import { Util, Enums } from '../../..' @@ -49,17 +49,15 @@ export class TransitionWipeCommand extends WritableCommand { static readonly rawName = 'TWpP' readonly mixEffect: number - readonly properties: Readonly constructor (mixEffect: number, properties: WipeTransitionSettings) { - super() + super(properties) this.mixEffect = mixEffect - this.properties = properties } static deserialize (rawCommand: Buffer): TransitionWipeUpdateCommand { diff --git a/src/commands/PowerStatusCommand.ts b/src/commands/PowerStatusCommand.ts index 7d3079b70..f426eb598 100644 --- a/src/commands/PowerStatusCommand.ts +++ b/src/commands/PowerStatusCommand.ts @@ -1,4 +1,4 @@ -import AbstractCommand from './AbstractCommand' +import { DeserializedCommand } from './CommandBase' import { AtemState } from '../state' /** @@ -6,17 +6,9 @@ import { AtemState } from '../state' * DeviceProfile/productIdentifierCommand.ts the 2ME, 2ME 4K and the * Broadcast Studio have 2 power supplies. All other models have 1. */ -export class PowerStatusCommand extends AbstractCommand { +export class PowerStatusCommand extends DeserializedCommand { static readonly rawName = 'Powr' - readonly properties: Readonly - - constructor (properties: boolean[]) { - super() - - this.properties = properties - } - static deserialize (rawCommand: Buffer): PowerStatusCommand { const properties = [ Boolean(rawCommand[0] & 1 << 0), diff --git a/src/commands/Settings/MultiViewerSourceCommand.ts b/src/commands/Settings/MultiViewerSourceCommand.ts index e339557c5..ce5821721 100644 --- a/src/commands/Settings/MultiViewerSourceCommand.ts +++ b/src/commands/Settings/MultiViewerSourceCommand.ts @@ -1,4 +1,4 @@ -import AbstractCommand, { WritableCommand } from '../AbstractCommand' +import { WritableCommand, DeserializedCommand } from '../CommandBase' import { AtemState } from '../../state' import { MultiViewerSourceState } from '../../state/settings' @@ -22,17 +22,15 @@ export class MultiViewerSourceCommand extends WritableCommand { static readonly rawName = 'MvIn' readonly multiViewerId: number - readonly properties: Readonly constructor (multiviewerId: number, properties: MultiViewerSourceState) { - super() + super(properties) this.multiViewerId = multiviewerId - this.properties = properties } static deserialize (rawCommand: Buffer): MultiViewerSourceUpdateCommand { diff --git a/src/commands/Settings/VideoMode.ts b/src/commands/Settings/VideoMode.ts index f741dae9a..5d7cb40c0 100644 --- a/src/commands/Settings/VideoMode.ts +++ b/src/commands/Settings/VideoMode.ts @@ -1,4 +1,4 @@ -import AbstractCommand, { BasicWritableCommand } from '../AbstractCommand' +import { BasicWritableCommand, DeserializedCommand } from '../CommandBase' import { AtemState } from '../../state' import { Enums } from '../..' @@ -10,11 +10,7 @@ export class VideoModeCommand extends BasicWritableCommand { static readonly rawName = 'CVdM' constructor (mode: Enums.VideoMode) { - super() - - this.properties = { - mode - } + super({ mode }) } serialize () { @@ -24,17 +20,11 @@ export class VideoModeCommand extends BasicWritableCommand { } } -export class VideoModeUpdateCommand extends AbstractCommand { +export class VideoModeUpdateCommand extends DeserializedCommand { static readonly rawName = 'VidM' - readonly properties: Readonly - constructor (mode: Enums.VideoMode) { - super() - - this.properties = { - mode - } + super({ mode }) } static deserialize (rawCommand: Buffer): VideoModeUpdateCommand { diff --git a/src/commands/SuperSource/SuperSourceBoxParametersCommand.ts b/src/commands/SuperSource/SuperSourceBoxParametersCommand.ts index 1837dc51a..135c4e424 100644 --- a/src/commands/SuperSource/SuperSourceBoxParametersCommand.ts +++ b/src/commands/SuperSource/SuperSourceBoxParametersCommand.ts @@ -1,10 +1,10 @@ -import AbstractCommand from '../AbstractCommand' +import { WritableCommand, DeserializedCommand } from '../CommandBase' import { AtemState } from '../../state' import { SuperSourceBox } from '../../state/video' import { Util } from '../..' import { ProtocolVersion } from '../../enums' -export class SuperSourceBoxParametersCommand extends AbstractCommand { +export class SuperSourceBoxParametersCommand extends WritableCommand { static MaskFlags = { enabled: 1 << 0, source: 1 << 1, @@ -22,18 +22,12 @@ export class SuperSourceBoxParametersCommand extends AbstractCommand { readonly ssrcId: number readonly boxId: number - properties: Partial constructor (ssrcId: number, boxId: number) { super() this.ssrcId = ssrcId this.boxId = boxId - this.properties = {} - } - - updateProps (newProps: Partial) { - this._updateProps(newProps) } serialize (version: ProtocolVersion) { @@ -62,19 +56,17 @@ export class SuperSourceBoxParametersCommand extends AbstractCommand { } } -export class SuperSourceBoxParametersUpdateCommand extends AbstractCommand { +export class SuperSourceBoxParametersUpdateCommand extends DeserializedCommand { static readonly rawName = 'SSBP' readonly ssrcId: number readonly boxId: number - readonly properties: Readonly constructor (ssrcId: number, boxId: number, properties: SuperSourceBox) { - super() + super(properties) this.ssrcId = ssrcId this.boxId = boxId - this.properties = properties } static deserialize (rawCommand: Buffer, version: ProtocolVersion): SuperSourceBoxParametersUpdateCommand { diff --git a/src/commands/SuperSource/SuperSourcePropertiesCommand.ts b/src/commands/SuperSource/SuperSourcePropertiesCommand.ts index ad18adf97..334e71b11 100644 --- a/src/commands/SuperSource/SuperSourcePropertiesCommand.ts +++ b/src/commands/SuperSource/SuperSourcePropertiesCommand.ts @@ -1,4 +1,4 @@ -import AbstractCommand, { WritableCommand } from '../AbstractCommand' +import { WritableCommand, DeserializedCommand } from '../CommandBase' import { AtemState } from '../../state' import { SuperSourceProperties, SuperSourceBorder, SuperSource } from '../../state/video' import { Util, Enums } from '../..' @@ -156,17 +156,9 @@ export class SuperSourceBorderCommand extends WritableCommand } } -export class SuperSourcePropertiesUpdateCommand extends AbstractCommand { +export class SuperSourcePropertiesUpdateCommand extends DeserializedCommand> { static readonly rawName = 'SSrc' - properties: Pick - - constructor (properties: SuperSourcePropertiesUpdateCommand['properties']) { - super() - - this.properties = properties - } - static deserialize (rawCommand: Buffer): SuperSourcePropertiesUpdateCommand { const properties = { properties: { @@ -214,18 +206,16 @@ export class SuperSourcePropertiesUpdateCommand extends AbstractCommand { } } -export class SuperSourcePropertiesUpdateV8Command extends AbstractCommand { +export class SuperSourcePropertiesUpdateV8Command extends DeserializedCommand { static readonly rawName = 'SSrc' static readonly minimumVersion = ProtocolVersion.V8_0 readonly ssrcId: number - readonly properties: Readonly constructor (ssrcId: number, properties: SuperSourceProperties) { - super() + super(properties) this.ssrcId = ssrcId - this.properties = properties } static deserialize (rawCommand: Buffer): SuperSourcePropertiesUpdateV8Command { @@ -252,18 +242,16 @@ export class SuperSourcePropertiesUpdateV8Command extends AbstractCommand { } } -export class SuperSourceBorderUpdateCommand extends AbstractCommand { +export class SuperSourceBorderUpdateCommand extends DeserializedCommand { static readonly rawName = 'SSBd' static readonly minimumVersion = ProtocolVersion.V8_0 readonly ssrcId: number - readonly properties: Readonly constructor (ssrcId: number, properties: SuperSourceBorder) { - super() + super(properties) this.ssrcId = ssrcId - this.properties = properties } static deserialize (rawCommand: Buffer) { diff --git a/src/commands/__tests__/util.ts b/src/commands/__tests__/util.ts index d2278e042..1426c7e12 100644 --- a/src/commands/__tests__/util.ts +++ b/src/commands/__tests__/util.ts @@ -1,6 +1,7 @@ import { CommandParser } from '../../lib/atemCommandParser' import { ProtocolVersion } from '../../enums' -import { AbstractCommand } from '..'; +import { IDeserializedCommand, ISerializableCommand } from '../CommandBase' +import { isFunction } from 'util' export type CommandTestConverterSet = { [key: string]: CommandTestConverter } export interface CommandTestConverter { @@ -42,9 +43,9 @@ export function runTestForCommand (commandParser: CommandParser, commandConverte if (typeof cmdConstructor.deserialize === 'function') { matchedCase = true test(`Test #${i}: ${testCase.name} - Deserialize`, () => { - const cmd: AbstractCommand = cmdConstructor.deserialize!(buffer.slice(0, length).slice(8), commandParser.version) + const cmd: IDeserializedCommand = cmdConstructor.deserialize(buffer.slice(0, length).slice(8), commandParser.version) - delete cmd.flag // Anything deserialized will never have flags + // delete cmd.flag // Anything deserialized will never have flags // delete (cmd as any).rawCommand if (converter) { @@ -61,8 +62,8 @@ export function runTestForCommand (commandParser: CommandParser, commandConverte }) } - const cmd: AbstractCommand = new cmdConstructor() // TODO - params - if (typeof cmd.serialize === 'function') { + const cmd: ISerializableCommand = new cmdConstructor() // TODO - params + if (isFunction(cmd.serialize)) { matchedCase = true test(`Test #${i}: ${testCase.name} - Serialize`, () => { if (converter) { @@ -74,11 +75,11 @@ export function runTestForCommand (commandParser: CommandParser, commandConverte } if (mutatedCommand.mask !== undefined) { - cmd.flag = mutatedCommand.mask + (cmd as any).flag = mutatedCommand.mask delete mutatedCommand.mask } - cmd.properties = mutatedCommand + (cmd as any).properties = mutatedCommand const hexStr = (buf: Buffer) => { const str = buf.toString('hex') @@ -90,7 +91,7 @@ export function runTestForCommand (commandParser: CommandParser, commandConverte return str2.substring(0, str2.length - 1) } - const encodedBytes = cmd.serialize!(commandParser.version) + const encodedBytes = cmd.serialize(commandParser.version) // console.log(hexStr(buffer.slice(4))) expect(length).toEqual(encodedBytes.length + 8) expect(hexStr(buffer.slice(8))).toEqual(hexStr(encodedBytes)) diff --git a/src/commands/index.ts b/src/commands/index.ts index a5613fbed..1cd04ec2d 100644 --- a/src/commands/index.ts +++ b/src/commands/index.ts @@ -1,5 +1,3 @@ -import AbstractCommand from './AbstractCommand' - export * from './Audio' export * from './DataTransfer' export * from './DeviceProfile' @@ -11,7 +9,7 @@ export * from './MixEffects' export * from './Settings' export * from './SuperSource' -export { AbstractCommand } +export * from './CommandBase' export * from './AuxSourceCommand' export * from './InitCompleteCommand' export * from './PowerStatusCommand' diff --git a/src/dataTransfer/dataLock.ts b/src/dataTransfer/dataLock.ts index 00fe62bbd..9f8b288b1 100644 --- a/src/dataTransfer/dataLock.ts +++ b/src/dataTransfer/dataLock.ts @@ -9,9 +9,9 @@ export default class DataLock { transfer: DataTransfer | undefined queue: Array = [] - commandQueue: Array = [] + commandQueue: Array = [] - constructor (storeId: number, commandQueue: Array) { + constructor (storeId: number, commandQueue: Array) { this.storeId = storeId this.commandQueue = commandQueue } diff --git a/src/dataTransfer/dataTransfer.ts b/src/dataTransfer/dataTransfer.ts index ceb7d5ea4..ed3b4ff19 100644 --- a/src/dataTransfer/dataTransfer.ts +++ b/src/dataTransfer/dataTransfer.ts @@ -5,7 +5,7 @@ export default abstract class DataTransfer { readonly transferId: number readonly storeId: number - commandQueue: Array + commandQueue: Array private readonly completionPromise: Promise resolvePromise: (value?: DataTransfer | PromiseLike | undefined) => void @@ -31,10 +31,10 @@ export default abstract class DataTransfer { return this.completionPromise } - fail(..._args: any[]): void{} // TODO remove + fail (..._args: any[]): void {} // TODO remove abstract start (): void - abstract handleCommand (command: Commands.AbstractCommand): void + abstract handleCommand (command: Commands.IDeserializedCommand): void abstract gotLock (): void } diff --git a/src/dataTransfer/dataTransferClip.ts b/src/dataTransfer/dataTransferClip.ts index eaaee4537..f3ff196fd 100644 --- a/src/dataTransfer/dataTransferClip.ts +++ b/src/dataTransfer/dataTransferClip.ts @@ -17,7 +17,7 @@ export default class DataTransferClip extends DataTransfer { } start () { - const clearMediaCommand = new Commands.MediaPoolClearClipCommand() + const clearMediaCommand = new Commands.MediaPoolClearClipCommand(this.clipIndex) clearMediaCommand.updateProps({ index: this.clipIndex }) @@ -26,7 +26,7 @@ export default class DataTransferClip extends DataTransfer { this.frames[this.curFrame].start() } - handleCommand (command: Commands.AbstractCommand) { + handleCommand (command: Commands.IDeserializedCommand) { this.frames[this.curFrame].handleCommand(command) if (this.state !== Enums.TransferState.Transferring) this.state = Enums.TransferState.Transferring if (this.frames[this.curFrame].state === Enums.TransferState.Finished) { diff --git a/src/dataTransfer/dataTransferFrame.ts b/src/dataTransfer/dataTransferFrame.ts index 23cd9b4f9..2520d0743 100644 --- a/src/dataTransfer/dataTransferFrame.ts +++ b/src/dataTransfer/dataTransferFrame.ts @@ -20,8 +20,7 @@ export default class DataTransferFrame extends DataTransfer { } start () { - const command = new Commands.DataTransferUploadRequestCommand() - command.updateProps({ + const command = new Commands.DataTransferUploadRequestCommand({ transferId: this.transferId, transferStoreId: this.storeId, transferIndex: this.frameId, @@ -32,12 +31,11 @@ export default class DataTransferFrame extends DataTransfer { } sendDescription () { - const command = new Commands.DataTransferFileDescriptionCommand() - command.updateProps({ fileHash: this.hash, transferId: this.transferId }) + const command = new Commands.DataTransferFileDescriptionCommand({ fileHash: this.hash, transferId: this.transferId }) this.commandQueue.push(command) } - handleCommand (command: Commands.AbstractCommand) { + handleCommand (command: Commands.IDeserializedCommand) { if (command.constructor.name === Commands.DataTransferUploadContinueCommand.name) { if (this.state === Enums.TransferState.Locked) { this.state = Enums.TransferState.Transferring diff --git a/src/dataTransfer/index.ts b/src/dataTransfer/index.ts index 35f92d4a6..854020ba4 100644 --- a/src/dataTransfer/index.ts +++ b/src/dataTransfer/index.ts @@ -5,11 +5,12 @@ import DataTransferFrame from './dataTransferFrame' import DataTransferStill from './dataTransferStill' import DataTransferClip from './dataTransferClip' import DataTransferAudio from './dataTransferAudio' +import { ISerializableCommand } from '../commands/CommandBase' const MAX_PACKETS_TO_SEND_PER_TICK = 10 export class DataTransferManager { - readonly commandQueue: Array = [] + readonly commandQueue: Array = [] readonly stillsLock = new DataLock(0, this.commandQueue) readonly clip1Lock = new DataLock(1, this.commandQueue) @@ -19,7 +20,7 @@ export class DataTransferManager { transferIndex = 0 - constructor (sendCommand: (command: Commands.AbstractCommand) => Promise) { + constructor (sendCommand: (command: ISerializableCommand) => Promise) { this.interval = setInterval(() => { if (this.commandQueue.length <= 0) { return @@ -36,7 +37,7 @@ export class DataTransferManager { clearInterval(this.interval) } - handleCommand (command: Commands.AbstractCommand) { + handleCommand (command: Commands.IDeserializedCommand) { const allLocks = [ this.stillsLock, this.clip1Lock, this.clip2Lock ] // try to establish the associated DataLock: diff --git a/src/lib/atemSocket.ts b/src/lib/atemSocket.ts index 0dce1d707..beac179d3 100644 --- a/src/lib/atemSocket.ts +++ b/src/lib/atemSocket.ts @@ -2,11 +2,11 @@ import { ChildProcess, fork } from 'child_process' import { EventEmitter } from 'events' import * as path from 'path' import { CommandParser } from './atemCommandParser' -import AbstractCommand from '../commands/AbstractCommand' import { IPCMessageType } from '../enums' import exitHook = require('exit-hook') import { Util } from './atemUtil' -import { VersionCommand } from '../commands' +import { VersionCommand, ISerializableCommand, IDeserializedCommand } from '../commands' +import { isFunction } from 'util' export class AtemSocket extends EventEmitter { private _debug = false @@ -75,8 +75,8 @@ export class AtemSocket extends EventEmitter { return ++this._localPacketId } - public _sendCommand (command: AbstractCommand, trackingId: number) { - if (typeof command.serialize !== 'function') { + public _sendCommand (command: ISerializableCommand, trackingId: number) { + if (isFunction(command.serialize)) { return Promise.reject(new Error('Command is not serializable')) } @@ -180,7 +180,7 @@ export class AtemSocket extends EventEmitter { const cmdConstructor = this._commandParser.commandFromRawName(name) if (cmdConstructor && typeof cmdConstructor.deserialize === 'function') { try { - const cmd: AbstractCommand = cmdConstructor.deserialize(buffer.slice(0, length).slice(8), this._commandParser.version) + const cmd: IDeserializedCommand = cmdConstructor.deserialize(buffer.slice(0, length).slice(8), this._commandParser.version) cmd.packetId = packetId || -1 if (name === '_ver') { // init started diff --git a/src/state/video/index.ts b/src/state/video/index.ts index 23b384fc1..c1317d9e2 100644 --- a/src/state/video/index.ts +++ b/src/state/video/index.ts @@ -94,7 +94,7 @@ export class MixEffect implements IMixEffect { fadeToBlack: FadeToBlackProperties numberOfKeyers: number = 0 transitionProperties: TransitionProperties - transitionSettings: TransitionSettings = {} as any + transitionSettings: TransitionSettings = {} as any upstreamKeyers: { [index: number]: USK.UpstreamKeyer } = [] constructor (index: number) { From 6c5ec03d56f2f1856c68c870e7ed577198782502 Mon Sep 17 00:00:00 2001 From: Julian Waller Date: Mon, 7 Oct 2019 22:35:06 +0100 Subject: [PATCH 03/68] fix some bad typings --- src/atem.ts | 33 +++++--- src/commands/Audio/AudioMixerInputCommand.ts | 1 - .../FadeToBlack/FadeToBlackRateCommand.ts | 3 + .../FadeToBlack/FadeToBlackStateCommand.ts | 1 + .../Key/MixEffectKeyPropertiesGetCommand.ts | 2 +- .../MixEffects/ProgramInputCommand.ts | 5 +- src/commands/__tests__/index.spec.ts | 2 +- src/dataTransfer/dataLock.ts | 81 +++++++++---------- src/dataTransfer/dataTransfer.ts | 10 +-- src/dataTransfer/dataTransferAudio.ts | 13 ++- src/dataTransfer/dataTransferClip.ts | 31 +++---- src/dataTransfer/dataTransferFrame.ts | 32 +++++--- src/dataTransfer/dataTransferStill.ts | 6 +- src/dataTransfer/index.ts | 36 ++++----- src/lib/atemSocket.ts | 12 +-- src/lib/atemSocketChild.ts | 24 ++++-- src/lib/atemUtil.ts | 1 + src/state/audio.ts | 19 ++--- src/state/info.ts | 12 +-- src/state/settings.ts | 25 +++--- src/state/video/downstreamKeyers.ts | 4 +- src/state/video/index.ts | 69 ++++++++-------- src/state/video/upstreamKeyers.ts | 17 ++-- 23 files changed, 213 insertions(+), 226 deletions(-) diff --git a/src/atem.ts b/src/atem.ts index 1c493e8d2..0a42445da 100644 --- a/src/atem.ts +++ b/src/atem.ts @@ -34,6 +34,12 @@ export interface AtemOptions { externalLog?: (arg0?: any,arg1?: any,arg2?: any,arg3?: any) => void } +interface SentCommand { + command: ISerializableCommand + resolve: (cmd: ISerializableCommand) => void + reject: (cmd: ISerializableCommand) => void +} + export class Atem extends EventEmitter { DEFAULT_PORT = 9910 RECONNECT_INTERVAL = 5000 @@ -45,12 +51,9 @@ export class Atem extends EventEmitter { private socket: AtemSocket private dataTransferManager: DT.DataTransferManager private _log: (...args: any[]) => void - private _sentQueue: {[packetId: string]: ISerializableCommand } = {} + private _sentQueue: {[packetId: string]: SentCommand } = {} - on: ((event: 'error', listener: (message: any) => void) => this) & - ((event: 'connected', listener: () => void) => this) & - ((event: 'disconnected', listener: () => void) => this) & - ((event: 'stateChanged', listener: (state: AtemState, path: string) => void) => this) + on!: ((event: 'error', listener: (message: any) => void) => this) & ((event: 'connected', listener: () => void) => this) & ((event: 'disconnected', listener: () => void) => this) & ((event: 'stateChanged', listener: (state: AtemState, path: string) => void) => this) constructor (options?: AtemOptions) { super() @@ -103,12 +106,14 @@ export class Atem extends EventEmitter { }) } - sendCommand (command: ISerializableCommand): Promise { + sendCommand (command: ISerializableCommand): Promise { const nextPacketId = this.socket.nextPacketId - this._sentQueue[nextPacketId] = command return new Promise((resolve, reject) => { - command.resolve = resolve - command.reject = reject + this._sentQueue[nextPacketId] = { + command, + resolve, + reject + } this.socket._sendCommand(command, nextPacketId).catch(reject) }) } @@ -465,15 +470,17 @@ export class Atem extends EventEmitter { } private _resolveCommand (trackingId: number) { - if (this._sentQueue[trackingId]) { - this._sentQueue[trackingId].resolve(this._sentQueue[trackingId]) + const sent = this._sentQueue[trackingId] + if (sent) { + sent.resolve(sent.command) delete this._sentQueue[trackingId] } } private _rejectCommand (trackingId: number) { - if (this._sentQueue[trackingId]) { - this._sentQueue[trackingId].reject(this._sentQueue[trackingId]) + const sent = this._sentQueue[trackingId] + if (sent) { + sent.reject(sent.command) delete this._sentQueue[trackingId] } } diff --git a/src/commands/Audio/AudioMixerInputCommand.ts b/src/commands/Audio/AudioMixerInputCommand.ts index fcac110fd..72103ffe4 100644 --- a/src/commands/Audio/AudioMixerInputCommand.ts +++ b/src/commands/Audio/AudioMixerInputCommand.ts @@ -56,7 +56,6 @@ export class AudioMixerInputUpdateCommand extends DeserializedCommand { static readonly rawName = 'CPgI' diff --git a/src/commands/__tests__/index.spec.ts b/src/commands/__tests__/index.spec.ts index cd3eff7a6..78f1cc5aa 100644 --- a/src/commands/__tests__/index.spec.ts +++ b/src/commands/__tests__/index.spec.ts @@ -20,7 +20,7 @@ const commandConverters: CommandTestConverterSet = { '_pin': { idAliases: {}, propertyAliases: { - 'name': (val: any) => ({ val, name: 'deviceName' }) + 'name': (val: any) => ({ val, name: 'productIdentifier' }) } }, 'SSBP': { diff --git a/src/dataTransfer/dataLock.ts b/src/dataTransfer/dataLock.ts index 9f8b288b1..468b16cd9 100644 --- a/src/dataTransfer/dataLock.ts +++ b/src/dataTransfer/dataLock.ts @@ -4,82 +4,83 @@ import DataTransfer from './dataTransfer' import DataTransferClip from './dataTransferClip' export default class DataLock { - storeId: number - state: number - transfer: DataTransfer | undefined - queue: Array = [] + private storeId: number + private isLocked: boolean + private taskQueue: Array = [] - commandQueue: Array = [] + public activeTransfer: DataTransfer | undefined - constructor (storeId: number, commandQueue: Array) { + private queueCommand: (cmd: Commands.ISerializableCommand) => void + + constructor (storeId: number, queueCommand: (cmd: Commands.ISerializableCommand) => void) { this.storeId = storeId - this.commandQueue = commandQueue + this.queueCommand = queueCommand + this.isLocked = false } enqueue (transfer: DataTransfer) { - this.queue.push(transfer) - if (!this.transfer) { + this.taskQueue.push(transfer) + if (!this.activeTransfer) { this.dequeueAndRun() } } - dequeueAndRun () { - if ((this.transfer === undefined || this.transfer.state === Enums.TransferState.Finished) && this.queue.length > 0) { - this.transfer = this.queue.shift() + private dequeueAndRun () { + if ((this.activeTransfer === undefined || this.activeTransfer.state === Enums.TransferState.Finished) && this.taskQueue.length > 0) { + this.activeTransfer = this.taskQueue.shift() - if (this.state === 1) { + if (this.isLocked) { this.lockObtained() } else { - this._getLock() + this.queueCommand(new Commands.LockStateCommand(this.storeId, true)) } - } else if (this.transfer) { - this.transfer.fail(new Error('Tried to run next transfer, but one was still in-progress')) } } lockObtained () { - this.state = 1 - if (this.transfer && this.transfer.state === Enums.TransferState.Queued) { - this.transfer.gotLock() + this.isLocked = true + if (this.activeTransfer && this.activeTransfer.state === Enums.TransferState.Queued) { + this.activeTransfer.gotLock().forEach(cmd => this.queueCommand(cmd)) } } lostLock () { - this.state = 0 - if (this.transfer && this.transfer.state !== Enums.TransferState.Finished) { + this.isLocked = false + if (this.activeTransfer && this.activeTransfer.state !== Enums.TransferState.Finished) { // @todo: dequeue any old commands - this.transfer.fail(new Error('Lost lock mid-transfer')) + this.activeTransfer.rejectPromise(new Error('Lost lock mid-transfer')) } - this.transfer = undefined + this.activeTransfer = undefined this.dequeueAndRun() } updateLock (locked: boolean) { - this.state = locked ? 1 : 0 + this.isLocked = locked } transferFinished () { - if (this.transfer && this.transfer.state === Enums.TransferState.Finished) { - this.transfer.resolvePromise(this.transfer) + if (this.activeTransfer && this.activeTransfer.state === Enums.TransferState.Finished) { + this.activeTransfer.resolvePromise(this.activeTransfer) + this.activeTransfer = undefined } - if (this.queue.length > 0) { + if (this.taskQueue.length > 0) { this.dequeueAndRun() } else { // unlock - this._releaseLock() + this.queueCommand(new Commands.LockStateCommand(this.storeId, false)) } } transferErrored (code: number) { - if (this.transfer) { + if (this.activeTransfer) { switch (code) { case 1: // Probably means "retry". - if (this.transfer instanceof DataTransferClip) { + if (this.activeTransfer instanceof DataTransferClip) { // Retry the last frame. - this.transfer.frames[this.transfer.curFrame].start() + this.activeTransfer.frames[this.activeTransfer.curFrame].start().forEach(cmd => this.queueCommand(cmd)) } else { // Retry the entire transfer. - this.transfer.start() + this.activeTransfer.start().forEach(cmd => this.queueCommand(cmd)) } break case 2: // Unknown. @@ -89,23 +90,13 @@ export default class DataLock { default: // Abort the transfer. // @todo: dequeue any old commands - this.transfer.fail(new Error(`Code ${code}`)) - this.transfer = undefined + this.activeTransfer.rejectPromise(new Error(`Code ${code}`)) + this.activeTransfer = undefined this.dequeueAndRun() } } else { - this.transfer = undefined + this.activeTransfer = undefined this.dequeueAndRun() } } - - _getLock () { - const command = new Commands.LockStateCommand(this.storeId, true) - this.commandQueue.push(command) - } - - _releaseLock () { - const command = new Commands.LockStateCommand(this.storeId, false) - this.commandQueue.push(command) - } } diff --git a/src/dataTransfer/dataTransfer.ts b/src/dataTransfer/dataTransfer.ts index ed3b4ff19..3b8696561 100644 --- a/src/dataTransfer/dataTransfer.ts +++ b/src/dataTransfer/dataTransfer.ts @@ -5,7 +5,7 @@ export default abstract class DataTransfer { readonly transferId: number readonly storeId: number - commandQueue: Array + // commandQueue: Array private readonly completionPromise: Promise resolvePromise: (value?: DataTransfer | PromiseLike | undefined) => void @@ -31,10 +31,8 @@ export default abstract class DataTransfer { return this.completionPromise } - fail (..._args: any[]): void {} // TODO remove + abstract start (): Commands.ISerializableCommand[] - abstract start (): void - - abstract handleCommand (command: Commands.IDeserializedCommand): void - abstract gotLock (): void + abstract handleCommand (command: Commands.IDeserializedCommand): Commands.ISerializableCommand[] + abstract gotLock (): Commands.ISerializableCommand[] } diff --git a/src/dataTransfer/dataTransferAudio.ts b/src/dataTransfer/dataTransferAudio.ts index 59a0fab75..9c8f0000a 100644 --- a/src/dataTransfer/dataTransferAudio.ts +++ b/src/dataTransfer/dataTransferAudio.ts @@ -11,21 +11,18 @@ export default class DataTransferAudio extends DataTransferFrame { this.name = name } - start () { - const command = new Commands.DataTransferUploadRequestCommand() - command.updateProps({ + public start () { + const command = new Commands.DataTransferUploadRequestCommand({ transferId: this.transferId, transferStoreId: this.storeId, transferIndex: 0, size: this.data.length, mode: Enums.TransferMode.WriteAudio }) - this.commandQueue.push(command) + return [ command ] } - sendDescription () { - const command = new Commands.DataTransferFileDescriptionCommand() - command.updateProps({ name: this.name, fileHash: this.hash, transferId: this.transferId }) - this.commandQueue.push(command) + public sendDescription (): Commands.ISerializableCommand { + return new Commands.DataTransferFileDescriptionCommand({ name: this.name, fileHash: this.hash, transferId: this.transferId }) } } diff --git a/src/dataTransfer/dataTransferClip.ts b/src/dataTransfer/dataTransferClip.ts index f3ff196fd..6829c1e43 100644 --- a/src/dataTransfer/dataTransferClip.ts +++ b/src/dataTransfer/dataTransferClip.ts @@ -16,43 +16,44 @@ export default class DataTransferClip extends DataTransfer { this.name = name } - start () { - const clearMediaCommand = new Commands.MediaPoolClearClipCommand(this.clipIndex) - clearMediaCommand.updateProps({ - index: this.clipIndex - }) - this.commandQueue.push(clearMediaCommand) + public start () { + const commands: Commands.ISerializableCommand[] = [] + commands.push(new Commands.MediaPoolClearClipCommand(this.clipIndex)) this.frames[this.curFrame].state = Enums.TransferState.Locked - this.frames[this.curFrame].start() + commands.push(...this.frames[this.curFrame].start()) + return commands } - handleCommand (command: Commands.IDeserializedCommand) { - this.frames[this.curFrame].handleCommand(command) + public handleCommand (command: Commands.IDeserializedCommand): Commands.ISerializableCommand[] { + const commands: Commands.ISerializableCommand[] = [] + + commands.push(...this.frames[this.curFrame].handleCommand(command)) if (this.state !== Enums.TransferState.Transferring) this.state = Enums.TransferState.Transferring if (this.frames[this.curFrame].state === Enums.TransferState.Finished) { this.curFrame++ if (this.curFrame < this.frames.length) { this.frames[this.curFrame].state = Enums.TransferState.Locked - this.frames[this.curFrame].start() + commands.push(...this.frames[this.curFrame].start()) } else { - const command = new Commands.MediaPoolSetClipCommand() - command.updateProps({ + const command = new Commands.MediaPoolSetClipCommand({ index: this.clipIndex, name: this.name, frames: this.frames.length }) - this.commandQueue.push(command) + commands.push(command) this.state = Enums.TransferState.Finished } } + + return commands } get transferId () { return this.frames[this.curFrame].transferId } - gotLock () { + public gotLock (): Commands.ISerializableCommand[] { this.state = Enums.TransferState.Locked - this.start() + return this.start() } } diff --git a/src/dataTransfer/dataTransferFrame.ts b/src/dataTransfer/dataTransferFrame.ts index 2520d0743..d36343523 100644 --- a/src/dataTransfer/dataTransferFrame.ts +++ b/src/dataTransfer/dataTransferFrame.ts @@ -19,7 +19,7 @@ export default class DataTransferFrame extends DataTransfer { this.hash = this.data ? crypto.createHash('md5').update(this.data).digest().toString() : '' } - start () { + public start () { const command = new Commands.DataTransferUploadRequestCommand({ transferId: this.transferId, transferStoreId: this.storeId, @@ -27,45 +27,51 @@ export default class DataTransferFrame extends DataTransfer { size: this.data.length, mode: Enums.TransferMode.TEST }) - this.commandQueue.push(command) + return [ command ] } - sendDescription () { - const command = new Commands.DataTransferFileDescriptionCommand({ fileHash: this.hash, transferId: this.transferId }) - this.commandQueue.push(command) + public sendDescription (): Commands.ISerializableCommand { + return new Commands.DataTransferFileDescriptionCommand({ fileHash: this.hash, transferId: this.transferId }) } - handleCommand (command: Commands.IDeserializedCommand) { + public handleCommand (command: Commands.IDeserializedCommand): Commands.ISerializableCommand[] { + const commands: Commands.ISerializableCommand[] = [] if (command.constructor.name === Commands.DataTransferUploadContinueCommand.name) { if (this.state === Enums.TransferState.Locked) { this.state = Enums.TransferState.Transferring - this.sendDescription() + commands.push(this.sendDescription()) } - this.queueCommand(command.properties.chunkCount, command.properties.chunkSize) + commands.push(...this.queueCommand(command.properties.chunkCount, command.properties.chunkSize)) } else if (command.constructor.name === Commands.DataTransferCompleteCommand.name) { if (this.state === Enums.TransferState.Transferring) { this.state = Enums.TransferState.Finished } } + + return commands } - gotLock () { + public gotLock () { this.state = Enums.TransferState.Locked - this.start() + return this.start() } - queueCommand (chunkCount: number, chunkSize: number) { + private queueCommand (chunkCount: number, chunkSize: number): Commands.ISerializableCommand[] { + const commands: Commands.ISerializableCommand[] = [] + chunkSize += -4 this.lastSent = new Date() for (let i = 0; i < chunkCount; i++) { - if (this._sent > this.data.length) return + if (this._sent > this.data.length) break const command = new Commands.DataTransferDataCommand({ transferId: this.transferId, body: this.data.slice(this._sent, this._sent + chunkSize) }) - this.commandQueue.push(command) + commands.push(command) this._sent += chunkSize } + + return commands } } diff --git a/src/dataTransfer/dataTransferStill.ts b/src/dataTransfer/dataTransferStill.ts index 487e3e6f9..646320698 100644 --- a/src/dataTransfer/dataTransferStill.ts +++ b/src/dataTransfer/dataTransferStill.ts @@ -13,9 +13,7 @@ export default class DataTransferStill extends DataTransferFrame { this.description = description } - sendDescription () { - const command = new Commands.DataTransferFileDescriptionCommand() - command.updateProps({ description: this.description, name: this.name, fileHash: this.hash, transferId: this.transferId }) - this.commandQueue.push(command) + public sendDescription (): Commands.ISerializableCommand { + return new Commands.DataTransferFileDescriptionCommand({ description: this.description, name: this.name, fileHash: this.hash, transferId: this.transferId }) } } diff --git a/src/dataTransfer/index.ts b/src/dataTransfer/index.ts index 854020ba4..70c63b3e3 100644 --- a/src/dataTransfer/index.ts +++ b/src/dataTransfer/index.ts @@ -12,9 +12,11 @@ const MAX_PACKETS_TO_SEND_PER_TICK = 10 export class DataTransferManager { readonly commandQueue: Array = [] - readonly stillsLock = new DataLock(0, this.commandQueue) - readonly clip1Lock = new DataLock(1, this.commandQueue) - readonly clip2Lock = new DataLock(2, this.commandQueue) + readonly stillsLock = new DataLock(0, cmd => this.commandQueue.push(cmd)) + readonly clipLocks = [ + new DataLock(1, cmd => this.commandQueue.push(cmd)), + new DataLock(2, cmd => this.commandQueue.push(cmd)) + ] readonly interval: NodeJS.Timer @@ -38,7 +40,7 @@ export class DataTransferManager { } handleCommand (command: Commands.IDeserializedCommand) { - const allLocks = [ this.stillsLock, this.clip1Lock, this.clip2Lock ] + const allLocks = [ this.stillsLock, ...this.clipLocks ] // try to establish the associated DataLock: let lock: DataLock | undefined @@ -48,17 +50,17 @@ export class DataTransferManager { lock = this.stillsLock break case 1 : - lock = this.clip1Lock + lock = this.clipLocks[0] break case 2 : - lock = this.clip2Lock + lock = this.clipLocks[1] break } } else if (command.properties.storeId) { lock = allLocks[command.properties.storeId] } else if (command.properties.transferId !== undefined || command.properties.transferIndex !== undefined) { for (const _lock of allLocks) { - if (_lock.transfer && (_lock.transfer.transferId === command.properties.transferId || _lock.transfer.transferId === command.properties.transferIndex)) { + if (_lock.activeTransfer && (_lock.activeTransfer.transferId === command.properties.transferId || _lock.activeTransfer.transferId === command.properties.transferIndex)) { lock = _lock } } @@ -80,9 +82,9 @@ export class DataTransferManager { if (command.constructor.name === Commands.DataTransferErrorCommand.name) { lock.transferErrored(command.properties.errorCode) } - if (lock.transfer) { - lock.transfer.handleCommand(command) - if (lock.transfer.state === Enums.TransferState.Finished) { + if (lock.activeTransfer) { + lock.activeTransfer.handleCommand(command).forEach(cmd => this.commandQueue.push(cmd)) + if (lock.activeTransfer.state === Enums.TransferState.Finished) { lock.transferFinished() } } @@ -90,7 +92,7 @@ export class DataTransferManager { uploadStill (index: number, data: Buffer, name: string, description: string) { const transfer = new DataTransferStill(this.transferIndex++, index, data, name, description) - transfer.commandQueue = this.commandQueue + // transfer.commandQueue = this.commandQueue this.stillsLock.enqueue(transfer) @@ -99,28 +101,22 @@ export class DataTransferManager { uploadClip (index: number, data: Array, name: string) { const transfer = new DataTransferClip(1 + index, name) - transfer.commandQueue = this.commandQueue for (const frameId in data) { - const frame = data[frameId] - const frameTransfer = new DataTransferFrame(this.transferIndex++, 1 + index, Number(frameId), frame) - - frameTransfer.commandQueue = this.commandQueue - // frameTransfer.hash = crypto.createHash('md5').update(frame).digest().toString() + const frameTransfer = new DataTransferFrame(this.transferIndex++, 1 + index, Number(frameId), data[frameId]) transfer.frames.push(frameTransfer) } - [ this.clip1Lock, this.clip2Lock ][index].enqueue(transfer) + this.clipLocks[index].enqueue(transfer) return transfer.promise } uploadAudio (index: number, data: Buffer, name: string) { const transfer = new DataTransferAudio(this.transferIndex++, 1 + index, data, name) - transfer.commandQueue = this.commandQueue - ;[ this.clip1Lock, this.clip2Lock ][index].enqueue(transfer) + this.clipLocks[index].enqueue(transfer) return transfer.promise } diff --git a/src/lib/atemSocket.ts b/src/lib/atemSocket.ts index beac179d3..b6cb116e9 100644 --- a/src/lib/atemSocket.ts +++ b/src/lib/atemSocket.ts @@ -17,13 +17,14 @@ export class AtemSocket extends EventEmitter { private _socketProcess: ChildProcess | null private _commandParser: CommandParser = new CommandParser() - constructor (options: { address?: string, port?: number, debug?: boolean, log?: (args1: any, args2?: any, args3?: any) => void }) { + constructor (options: { address?: string, port?: number, debug?: boolean, log?: (...args: any[]) => void }) { super() - this._address = options.address || this._address + this._address = options.address || '' this._port = options.port || this._port this._debug = options.debug || false this.log = options.log || this.log + this._socketProcess = null this._createSocketProcess() // When the parent process begins exiting, remove the listeners on our child process. @@ -160,7 +161,7 @@ export class AtemSocket extends EventEmitter { this.emit(IPCMessageType.CommandTimeout, message.payload) break case IPCMessageType.InboundCommand: - this._parseCommand(Buffer.from(payload.packet.data), payload.remotePacketId) + this._parseCommand(Buffer.from(payload.packet.data)) break case IPCMessageType.Disconnect: this.emit(IPCMessageType.Disconnect) @@ -168,7 +169,7 @@ export class AtemSocket extends EventEmitter { } } - private _parseCommand (buffer: Buffer, packetId?: number) { + private _parseCommand (buffer: Buffer) { const length = buffer.readUInt16BE(0) const name = buffer.toString('ascii', 4, 8) @@ -181,7 +182,6 @@ export class AtemSocket extends EventEmitter { if (cmdConstructor && typeof cmdConstructor.deserialize === 'function') { try { const cmd: IDeserializedCommand = cmdConstructor.deserialize(buffer.slice(0, length).slice(8), this._commandParser.version) - cmd.packetId = packetId || -1 if (name === '_ver') { // init started const verCmd = cmd as VersionCommand @@ -195,7 +195,7 @@ export class AtemSocket extends EventEmitter { } if (buffer.length > length) { - this._parseCommand(buffer.slice(length), packetId) + this._parseCommand(buffer.slice(length)) } } } diff --git a/src/lib/atemSocketChild.ts b/src/lib/atemSocketChild.ts index ab1293a15..40cad1898 100644 --- a/src/lib/atemSocketChild.ts +++ b/src/lib/atemSocketChild.ts @@ -9,7 +9,7 @@ export class AtemSocketChild extends EventEmitter { private _connectionState = ConnectionState.Closed private _debug = false private _reconnectTimer: NodeJS.Timer | undefined - private _retransmitTimer: NodeJS.Timer + private _retransmitTimer: NodeJS.Timer | undefined private _localPacketId = 1 private _maxPacketID = (1 << 15) - 1 // Atem expects 15 not 16 bits before wrapping @@ -34,7 +34,7 @@ export class AtemSocketChild extends EventEmitter { super() this._address = options.address || '' this._port = options.port || this._port - this._createSocket() + this._socket = this._createSocket() } public connect (address?: string, port?: number) { @@ -55,7 +55,9 @@ export class AtemSocketChild extends EventEmitter { }, this._reconnectInterval) } // Check for retransmits every 10 milliseconds - this._retransmitTimer = setInterval(() => this._checkForRetransmit(), 10) + if (!this._retransmitTimer) { + this._retransmitTimer = setInterval(() => this._checkForRetransmit(), 10) + } if (address) { this._address = address @@ -78,8 +80,14 @@ export class AtemSocketChild extends EventEmitter { resolve() } }).then(() => { - clearInterval(this._retransmitTimer) - clearInterval(this._reconnectTimer as NodeJS.Timer) + if (this._retransmitTimer) { + clearInterval(this._retransmitTimer) + this._retransmitTimer = undefined + } + if (this._reconnectTimer) { + clearInterval(this._reconnectTimer) + this._reconnectTimer = undefined + } this._reconnectTimer = undefined this._connectionState = ConnectionState.Closed @@ -88,8 +96,8 @@ export class AtemSocketChild extends EventEmitter { }) } - public log (...args: any[]): void { - const payload = format.apply(format, args) + public log (fmt: string, ...args: any[]): void { + const payload = format(fmt, ...args) this.emit(IPCMessageType.Log, payload) } @@ -122,6 +130,8 @@ export class AtemSocketChild extends EventEmitter { this._socket = createSocket('udp4') this._socket.bind() this._socket.on('message', (packet, rinfo) => this._receivePacket(packet, rinfo)) + + return this._socket } private _receivePacket (packet: Buffer, rinfo: any) { diff --git a/src/lib/atemUtil.ts b/src/lib/atemUtil.ts index 8485f030d..2fb556a80 100644 --- a/src/lib/atemUtil.ts +++ b/src/lib/atemUtil.ts @@ -170,6 +170,7 @@ export namespace Util { const HD = [1280, 720] const FHD = [1920, 1080] const UHD = [3840, 2160] + // TODO - add 8k options const enumToResolution = [ NTSC, PAL, NTSC, PAL, diff --git a/src/state/audio.ts b/src/state/audio.ts index e4a193d2e..d08203cb4 100644 --- a/src/state/audio.ts +++ b/src/state/audio.ts @@ -1,6 +1,6 @@ import { AudioSourceType, ExternalPortType, AudioMixOption } from '../enums' -export class AudioChannel { +export interface AudioChannel { sourceType: AudioSourceType portType: ExternalPortType mixOption: AudioMixOption @@ -10,7 +10,7 @@ export class AudioChannel { balance: number } -export class AudioMasterChannel { +export interface AudioMasterChannel { /** Gain in decibel, -Infinity to +6dB */ gain: number /** Balance, -50 to +50 */ @@ -19,15 +19,8 @@ export class AudioMasterChannel { } export class AtemAudioState { - numberOfChannels: number - hasMonitor: boolean - channels: Array = [] - master: AudioMasterChannel = new AudioMasterChannel() - - getChannel (index: number) { - if (!this.channels[index]) { - this.channels[index] = new AudioChannel() - } - return this.channels[index] - } + numberOfChannels?: number + hasMonitor?: boolean + channels: Array = [] + master?: AudioMasterChannel } diff --git a/src/state/info.ts b/src/state/info.ts index 38dd825ea..1f89834d9 100644 --- a/src/state/info.ts +++ b/src/state/info.ts @@ -17,10 +17,10 @@ export interface AtemCapabilites { } export class DeviceInfo { - apiVersion: ProtocolVersion - capabilities: AtemCapabilites - model: Model - productIdentifier: string - superSourceBoxes: number - power: boolean[] + apiVersion: ProtocolVersion = 0 + capabilities?: AtemCapabilites + model: Model = Model.Unknown + productIdentifier?: string + superSourceBoxes?: number + power: boolean[] = [] } diff --git a/src/state/settings.ts b/src/state/settings.ts index 3441fbea5..e94176030 100644 --- a/src/state/settings.ts +++ b/src/state/settings.ts @@ -4,41 +4,34 @@ export interface MultiViewerSourceState { } export interface MultiViewerWindowState extends MultiViewerSourceState { - safeTitle: boolean - audioMeter: boolean + safeTitle?: boolean + audioMeter?: boolean // TODO - supports safeTitle & audioMeter? } export class MultiViewer { index: number - windows: { [index: string]: MultiViewerWindowState } = {} + windows: { [index: string]: MultiViewerWindowState | undefined } = {} constructor (index: number) { this.index = index } - - getWindow (index: number) { - if (!this.windows[index]) { - this.windows[index] = {} as MultiViewerWindowState - } - - return this.windows[index] - } } export class SettingsState { - multiViewers: { [index: string]: MultiViewer } = {} + multiViewers: { [index: string]: MultiViewer | undefined } = {} videoMode: number constructor () { this.videoMode = 0 } - getMultiViewer (index: number) { - if (!this.multiViewers[index]) { - this.multiViewers[index] = new MultiViewer(index) + getMultiViewer (index: number): MultiViewer { + const multiViewer = this.multiViewers[index] + if (!multiViewer) { + return this.multiViewers[index] = new MultiViewer(index) } - return this.multiViewers[index] + return multiViewer } } diff --git a/src/state/video/downstreamKeyers.ts b/src/state/video/downstreamKeyers.ts index 56fb85365..7df7a0e5c 100644 --- a/src/state/video/downstreamKeyers.ts +++ b/src/state/video/downstreamKeyers.ts @@ -7,11 +7,11 @@ export interface DownstreamKeyerBase { } export interface DownstreamKeyer extends DownstreamKeyerBase { - sources: { + sources?: { fillSource: number, cutSource: number } - properties: DownstreamKeyerProperties + properties?: DownstreamKeyerProperties } export interface DownstreamKeyerGeneral { diff --git a/src/state/video/index.ts b/src/state/video/index.ts index c1317d9e2..aeacb7b73 100644 --- a/src/state/video/index.ts +++ b/src/state/video/index.ts @@ -62,11 +62,11 @@ export interface TransitionProperties { } export interface TransitionSettings { - dip: DipTransitionSettings - DVE: DVETransitionSettings - mix: MixTransitionSettings - stinger: StingerTransitionSettings - wipe: WipeTransitionSettings + dip?: DipTransitionSettings + DVE?: DVETransitionSettings + mix?: MixTransitionSettings + stinger?: StingerTransitionSettings + wipe?: WipeTransitionSettings } export interface IMixEffect { @@ -76,11 +76,11 @@ export interface IMixEffect { transitionPreview: boolean transitionPosition: number transitionFramesLeft: number - fadeToBlack: FadeToBlackProperties + fadeToBlack?: FadeToBlackProperties numberOfKeyers: number transitionProperties: TransitionProperties - transitionSettings: TransitionSettings, - upstreamKeyers: { [index: number]: USK.UpstreamKeyer } + transitionSettings: TransitionSettings + upstreamKeyers: { [index: number]: USK.UpstreamKeyer | undefined } } export class MixEffect implements IMixEffect { @@ -91,21 +91,15 @@ export class MixEffect implements IMixEffect { transitionPreview: boolean = false transitionPosition: number = 0 transitionFramesLeft: number = 0 - fadeToBlack: FadeToBlackProperties + fadeToBlack?: FadeToBlackProperties numberOfKeyers: number = 0 transitionProperties: TransitionProperties - transitionSettings: TransitionSettings = {} as any - upstreamKeyers: { [index: number]: USK.UpstreamKeyer } = [] + transitionSettings: TransitionSettings = {} + upstreamKeyers: { [index: number]: USK.UpstreamKeyer | undefined } = [] constructor (index: number) { this.index = index - this.fadeToBlack = { - isFullyBlack: false, - rate: 0, - inTransition: false, - remainingFrames: 0 - } this.transitionProperties = { style: Enum.TransitionStyle.MIX, selection: 0, @@ -114,19 +108,21 @@ export class MixEffect implements IMixEffect { } } - getUpstreamKeyer (index: number) { - if (!this.upstreamKeyers[index]) { - this.upstreamKeyers[index] = { - dveSettings: {} as any, - chromaSettings: {} as any, - lumaSettings: {} as any, - patternSettings: {} as any, - flyKeyframes: [], - flyProperties: {} as any - } as any + getUpstreamKeyer (index: number): USK.UpstreamKeyer { + const usk = this.upstreamKeyers[index] + if (!usk) { + return this.upstreamKeyers[index] = { + upstreamKeyerId: index, + mixEffectKeyType: 0, + cutSource: 0, + fillSource: 0, + onAir: false, + flyEnabled: false, + flyKeyframes: [] + } } - return this.upstreamKeyers[index] + return usk } } @@ -219,27 +215,32 @@ export class AtemVideoState { superSources: { [index: string]: SuperSource | undefined } = {} getMe (index: number): MixEffect { - let me = this.ME[index] + const me = this.ME[index] if (!me) { - me = this.ME[index] = new MixEffect(index) + return this.ME[index] = new MixEffect(index) } return me } getSuperSource (index: number): SuperSource { - let ssrc = this.superSources[index] + const ssrc = this.superSources[index] if (!ssrc) { - ssrc = this.superSources[index] = new SuperSource(index) + return this.superSources[index] = new SuperSource(index) } return ssrc } getDownstreamKeyer (index: number): DownstreamKeyer { - let dsk = this.downstreamKeyers[index] + const dsk = this.downstreamKeyers[index] if (!dsk) { - dsk = this.downstreamKeyers[index] = {} as DownstreamKeyer + return this.downstreamKeyers[index] = { + isAuto: false, + remainingFrames: 0, + onAir: false, + inTransition: false + } } return dsk diff --git a/src/state/video/upstreamKeyers.ts b/src/state/video/upstreamKeyers.ts index 3a32f4bb3..b990b82e7 100644 --- a/src/state/video/upstreamKeyers.ts +++ b/src/state/video/upstreamKeyers.ts @@ -6,11 +6,6 @@ export interface UpstreamKeyerBase { flyEnabled: boolean, fillSource: number, cutSource: number, - maskEnabled: boolean, - maskTop: number, - maskBottom: number, - maskLeft: number, - maskRight: number, } export interface UpstreamKeyerMaskSettings { @@ -93,11 +88,11 @@ export interface UpstreamKeyerTypeSettings { } export interface UpstreamKeyer extends UpstreamKeyerBase { - dveSettings: UpstreamKeyerDVESettings, - chromaSettings: UpstreamKeyerChromaSettings, - lumaSettings: UpstreamKeyerLumaSettings, - patternSettings: UpstreamKeyerPatternSettings, - flyKeyframes: Array, - flyProperties: UpstreamKeyerFlySettings, + dveSettings?: UpstreamKeyerDVESettings, + chromaSettings?: UpstreamKeyerChromaSettings, + lumaSettings?: UpstreamKeyerLumaSettings, + patternSettings?: UpstreamKeyerPatternSettings, + flyKeyframes: Array, + flyProperties?: UpstreamKeyerFlySettings, onAir: boolean } From e681623db01636c5b7b60a2d4d17f93417e3fa7f Mon Sep 17 00:00:00 2001 From: Julian Waller Date: Tue, 22 Oct 2019 01:17:59 +0100 Subject: [PATCH 04/68] feat: some changes for atem-state --- .../Media/MediaPlayerSourceCommand.ts | 2 +- .../Media/MediaPlayerStatusCommand.ts | 2 +- .../Media/MediaPoolClipDescription.ts | 14 ++- .../Media/MediaPoolFrameDescription.ts | 4 +- .../Key/MixEffectKeyTypeSetCommand.ts | 2 +- .../SuperSourcePropertiesCommand.ts | 17 ++-- src/lib/atemUtil.ts | 27 +++--- src/state/media.ts | 45 +++++++++- src/state/video/downstreamKeyers.ts | 10 ++- src/state/video/index.ts | 85 +++++++++---------- src/state/video/upstreamKeyers.ts | 14 ++- 11 files changed, 124 insertions(+), 98 deletions(-) diff --git a/src/commands/Media/MediaPlayerSourceCommand.ts b/src/commands/Media/MediaPlayerSourceCommand.ts index 24e80f356..d686f4e20 100644 --- a/src/commands/Media/MediaPlayerSourceCommand.ts +++ b/src/commands/Media/MediaPlayerSourceCommand.ts @@ -54,7 +54,7 @@ export class MediaPlayerSourceUpdateCommand extends DeserializedCommand { +export class MediaPoolClipDescriptionCommand extends DeserializedCommand> { static readonly rawName = 'MPCS' readonly mediaPool: number - constructor (mediaPool: number, properties: ClipBank) { + constructor (mediaPool: number, properties: Omit) { super(properties) this.mediaPool = mediaPool @@ -19,19 +19,17 @@ export class MediaPoolClipDescriptionCommand extends DeserializedCommand } } -export class SuperSourcePropertiesUpdateCommand extends DeserializedCommand> { +export class SuperSourcePropertiesUpdateCommand extends DeserializedCommand<{ properties: SuperSourceProperties, border: SuperSourceBorder }> { static readonly rawName = 'SSrc' static deserialize (rawCommand: Buffer): SuperSourcePropertiesUpdateCommand { @@ -193,12 +193,8 @@ export class SuperSourcePropertiesUpdateCommand extends DeserializedCommand { - const array = [] - for (const val of Buffer.from(str).values()) { - array.push(val) - } - return array + return Array.from(Buffer.from(str).values()) } export function bufToBase64String (buffer: Buffer, start: number, length: number): string { @@ -24,13 +20,18 @@ export namespace Util { } export function parseNumberBetween (num: number, min: number, max: number): number { - if (num > max) throw Error(`Number too big: ${num} > ${max}`) - else if (num < min) throw Error(`Number too small: ${num} < ${min}`) + if (num > max) { + throw Error(`Number too big: ${num} > ${max}`) + } else if (num < min) { + throw Error(`Number too small: ${num} < ${min}`) + } return num } export function parseEnum (value: G, type: any): G { - if (!type[value]) throw Error(`Value ${value} is not a valid option in enum`) + if (!type[value]) { + throw Error(`Value ${value} is not a valid option in enum`) + } return value } @@ -128,8 +129,7 @@ export namespace Util { const KGoKRi = KG / KRi * HalfCbCrRange const buffer = Buffer.alloc(width * height * 4) - let i = 0 - while (i < width * height * 4) { + for (let i = 0; i < width * height * 4; i += 8) { const r1 = data[i + 0] const g1 = data[i + 1] const b1 = data[i + 2] @@ -151,6 +151,7 @@ export namespace Util { const y2 = Math.round(y16b) >> 6 const v2 = Math.round(cr16) >> 6 + // TODO - rewrite using buffer.writeUIntLE/writeUIntBE? buffer[i + 0] = a1 >> 4 buffer[i + 1] = ((a1 & 0x0f) << 4) | (u1 >> 6) buffer[i + 2] = ((u1 & 0x3f) << 2) | (y1 >> 8) @@ -159,7 +160,6 @@ export namespace Util { buffer[i + 5] = ((a2 & 0x0f) << 4) | (v2 >> 6) buffer[i + 6] = ((v2 & 0x3f) << 2) | (y2 >> 8) buffer[i + 7] = y2 & 0xff - i = i + 8 } return buffer } @@ -197,10 +197,9 @@ export namespace Util { const buffer = Buffer.from(wav.data.samples) const buffer2 = Buffer.alloc(buffer.length) for (let i = 0; i < buffer.length; i += 3) { + // TODO - is this the correct way around? (only matters for readability) // 24bit samples, change endian - buffer2[i] = buffer[i + 2] - buffer2[i + 1] = buffer[i + 1] - buffer2[i + 2] = buffer[i] + buffer2.writeUIntLE(buffer.readUIntBE(i, 3), i, 3) } return buffer2 diff --git a/src/state/media.ts b/src/state/media.ts index ba5aa7732..6ae9349c2 100644 --- a/src/state/media.ts +++ b/src/state/media.ts @@ -13,10 +13,47 @@ export interface MediaPlayerSource { stillIndex: number } +export type MediaPlayerState = MediaPlayer & MediaPlayerSource + export class MediaState { - stillPool: Array = [] - clipPool: Array = [] - players: Array = [] + stillPool: Array = [] + clipPool: Array = [] + players: Array = [] + + getMediaPlayer (index: number, dontCreate?: boolean): MediaPlayerState { + let player = this.players[index] + if (!player) { + player = { + playing: false, + loop: false, + atBeginning: false, + clipFrame: 0, + sourceType: Enums.MediaSourceType.Clip, + clipIndex: 0, + stillIndex: 0 + } + + if (!dontCreate) { + this.players[index] = player + } + } + + return player + } + + getClip (index: number): ClipBank { + const clip = this.clipPool[index] + if (!clip) { + return this.clipPool[index] = { + isUsed: false, + name: '', + frameCount: 0, + frames: [] + } + } + + return clip + } } export interface StillFrame { @@ -29,5 +66,5 @@ export interface ClipBank { isUsed: boolean name: string frameCount: number - frames: Array + frames: Array } diff --git a/src/state/video/downstreamKeyers.ts b/src/state/video/downstreamKeyers.ts index 7df7a0e5c..6f3d396de 100644 --- a/src/state/video/downstreamKeyers.ts +++ b/src/state/video/downstreamKeyers.ts @@ -7,10 +7,7 @@ export interface DownstreamKeyerBase { } export interface DownstreamKeyer extends DownstreamKeyerBase { - sources?: { - fillSource: number, - cutSource: number - } + sources?: DownstreamKeyerSources properties?: DownstreamKeyerProperties } @@ -34,3 +31,8 @@ export interface DownstreamKeyerProperties extends DownstreamKeyerGeneral { rate: number mask: DownstreamKeyerMask } + +export interface DownstreamKeyerSources { + fillSource: number + cutSource: number +} diff --git a/src/state/video/index.ts b/src/state/video/index.ts index aeacb7b73..0298e3f92 100644 --- a/src/state/video/index.ts +++ b/src/state/video/index.ts @@ -80,7 +80,7 @@ export interface IMixEffect { numberOfKeyers: number transitionProperties: TransitionProperties transitionSettings: TransitionSettings - upstreamKeyers: { [index: number]: USK.UpstreamKeyer | undefined } + upstreamKeyers: Array } export class MixEffect implements IMixEffect { @@ -95,7 +95,7 @@ export class MixEffect implements IMixEffect { numberOfKeyers: number = 0 transitionProperties: TransitionProperties transitionSettings: TransitionSettings = {} - upstreamKeyers: { [index: number]: USK.UpstreamKeyer | undefined } = [] + upstreamKeyers: Array = [] constructor (index: number) { this.index = index @@ -108,10 +108,10 @@ export class MixEffect implements IMixEffect { } } - getUpstreamKeyer (index: number): USK.UpstreamKeyer { - const usk = this.upstreamKeyers[index] + getUpstreamKeyer (index: number, dontCreate?: boolean): USK.UpstreamKeyer { + let usk = this.upstreamKeyers[index] if (!usk) { - return this.upstreamKeyers[index] = { + usk = { upstreamKeyerId: index, mixEffectKeyType: 0, cutSource: 0, @@ -120,6 +120,10 @@ export class MixEffect implements IMixEffect { flyEnabled: false, flyKeyframes: [] } + + if (!dontCreate) { + this.upstreamKeyers[index] = usk + } } return usk @@ -167,37 +171,16 @@ export interface SuperSourceBorder { export class SuperSource { index: number - boxes: { [index: string]: SuperSourceBox | undefined } = {} - properties: SuperSourceProperties - border: SuperSourceBorder + boxes: [SuperSourceBox | undefined, SuperSourceBox | undefined, SuperSourceBox | undefined, SuperSourceBox | undefined] + properties?: SuperSourceProperties + border?: SuperSourceBorder constructor (index: number) { this.index = index - this.properties = { - artFillSource: 0, - artCutSource: 0, - artOption: Enum.SuperSourceArtOption.Background, - artPreMultiplied: false, - artClip: 0, - artGain: 0, - artInvertKey: false - } - this.border = { - borderEnabled: false, - borderBevel: Enum.BorderBevel.None, - borderOuterWidth: 0, - borderInnerWidth: 0, - borderOuterSoftness: 0, - borderInnerSoftness: 0, - borderBevelSoftness: 0, - borderBevelPosition: 0, - borderHue: 0, - borderSaturation: 0, - borderLuma: 0, - borderLightSourceDirection: 0, - borderLightSourceAltitude: 0 - } + this.boxes = [ + undefined, undefined, undefined, undefined + ] } } @@ -209,38 +192,50 @@ export interface FadeToBlackProperties { } export class AtemVideoState { - ME: { [index: string]: MixEffect | undefined } = {} - downstreamKeyers: { [index: string]: DownstreamKeyer | undefined } = {} - auxilliaries: { [index: string]: number | undefined } = {} - superSources: { [index: string]: SuperSource | undefined } = {} + ME: Array = [] + downstreamKeyers: Array = [] + auxilliaries: Array = [] + superSources: Array = [] - getMe (index: number): MixEffect { - const me = this.ME[index] + getMe (index: number, dontCreate?: boolean): MixEffect { + let me = this.ME[index] if (!me) { - return this.ME[index] = new MixEffect(index) + me = new MixEffect(index) + + if (!dontCreate) { + this.ME[index] = me + } } return me } - getSuperSource (index: number): SuperSource { - const ssrc = this.superSources[index] + getSuperSource (index: number, dontCreate?: boolean): SuperSource { + let ssrc = this.superSources[index] if (!ssrc) { - return this.superSources[index] = new SuperSource(index) + ssrc = new SuperSource(index) + + if (!dontCreate) { + this.superSources[index] = ssrc + } } return ssrc } - getDownstreamKeyer (index: number): DownstreamKeyer { - const dsk = this.downstreamKeyers[index] + getDownstreamKeyer (index: number, dontCreate?: boolean): DownstreamKeyer { + let dsk = this.downstreamKeyers[index] if (!dsk) { - return this.downstreamKeyers[index] = { + dsk = { isAuto: false, remainingFrames: 0, onAir: false, inTransition: false } + + if (!dontCreate) { + this.downstreamKeyers[index] = dsk + } } return dsk diff --git a/src/state/video/upstreamKeyers.ts b/src/state/video/upstreamKeyers.ts index b990b82e7..3d0ed63e8 100644 --- a/src/state/video/upstreamKeyers.ts +++ b/src/state/video/upstreamKeyers.ts @@ -1,13 +1,16 @@ import * as Enum from '../../enums' -export interface UpstreamKeyerBase { +export interface UpstreamKeyerBase extends UpstreamKeyerTypeSettings { readonly upstreamKeyerId: number, - mixEffectKeyType: number, - flyEnabled: boolean, fillSource: number, cutSource: number, } +export interface UpstreamKeyerTypeSettings { + mixEffectKeyType: Enum.MixEffectKeyType, + flyEnabled: boolean +} + export interface UpstreamKeyerMaskSettings { maskEnabled: boolean, maskTop: number, @@ -82,11 +85,6 @@ export interface UpstreamKeyerFlySettings { readonly runToInfiniteIndex: number } -export interface UpstreamKeyerTypeSettings { - keyType: Enum.MixEffectKeyType, - flyEnabled: boolean -} - export interface UpstreamKeyer extends UpstreamKeyerBase { dveSettings?: UpstreamKeyerDVESettings, chromaSettings?: UpstreamKeyerChromaSettings, From 416a5205603c94120253394c421b7a00af89f981 Mon Sep 17 00:00:00 2001 From: Julian Waller Date: Tue, 22 Oct 2019 10:26:16 +0100 Subject: [PATCH 05/68] fix: TransitionMixCommand using wrong base class --- src/atem.ts | 5 ++--- .../MixEffects/Transition/TransitionMixCommand.ts | 8 ++++---- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/src/atem.ts b/src/atem.ts index 0a42445da..bf5079209 100644 --- a/src/atem.ts +++ b/src/atem.ts @@ -161,9 +161,8 @@ export class Atem extends EventEmitter { return this.sendCommand(command) } - setMixTransitionSettings (newProps: Partial, me: number = 0) { - const command = new Commands.TransitionMixCommand(me) - command.updateProps(newProps) + setMixTransitionSettings (newProps: Pick, me: number = 0) { + const command = new Commands.TransitionMixCommand(me, newProps.rate) return this.sendCommand(command) } diff --git a/src/commands/MixEffects/Transition/TransitionMixCommand.ts b/src/commands/MixEffects/Transition/TransitionMixCommand.ts index 3655c6b74..f6ea8fb2e 100644 --- a/src/commands/MixEffects/Transition/TransitionMixCommand.ts +++ b/src/commands/MixEffects/Transition/TransitionMixCommand.ts @@ -1,15 +1,15 @@ -import { WritableCommand, DeserializedCommand } from '../../CommandBase' +import { DeserializedCommand, BasicWritableCommand } from '../../CommandBase' import { AtemState } from '../../../state' import { MixTransitionSettings } from '../../../state/video' import { Util } from '../../..' -export class TransitionMixCommand extends WritableCommand { +export class TransitionMixCommand extends BasicWritableCommand { static readonly rawName = 'CTMx' readonly mixEffect: number - constructor (mixEffect: number) { - super() + constructor (mixEffect: number, rate: number) { + super({ rate }) this.mixEffect = mixEffect } From 7d48ff6d73ba40f6697e147b962a3f21714e6a4c Mon Sep 17 00:00:00 2001 From: Julian Waller Date: Tue, 22 Oct 2019 11:57:32 +0100 Subject: [PATCH 06/68] feat: updateProps only updates the valid properties (according to the mask). Returns true if anything was changed --- src/__tests__/index.spec.ts | 8 +++---- src/commands/Audio/AudioMixerInputCommand.ts | 1 - src/commands/CommandBase.ts | 24 +++++++++++-------- src/commands/Inputs/InputPropertiesCommand.ts | 1 - .../Media/MediaPlayerStatusCommand.ts | 2 +- .../FadeToBlack/FadeToBlackRateCommand.ts | 1 - .../MixEffects/Key/MixEffectKeyDVECommand.ts | 1 - .../Key/MixEffectKeyTypeSetCommand.ts | 2 +- src/commands/__tests__/index.spec.ts | 10 ++++---- 9 files changed, 24 insertions(+), 26 deletions(-) diff --git a/src/__tests__/index.spec.ts b/src/__tests__/index.spec.ts index 7153f628b..966334d6d 100644 --- a/src/__tests__/index.spec.ts +++ b/src/__tests__/index.spec.ts @@ -41,7 +41,7 @@ test('setSuperSourceProperties - 7.2', async () => { expect(conn.sendCommand).toHaveBeenCalledTimes(1) expect(conn.sendCommand).toHaveBeenNthCalledWith(1, { flag: 12, - properties: { + _properties: { artOption: 0, artPreMultiplied: true } @@ -64,7 +64,7 @@ test('setSuperSourceProperties - 8.0', async () => { expect(conn.sendCommand).toHaveBeenNthCalledWith(1, { ssrcId: 2, flag: 12, - properties: { + _properties: { artOption: 0, artPreMultiplied: true } @@ -86,7 +86,7 @@ test('setSuperSourceBorder - 7.2', async () => { expect(conn.sendCommand).toHaveBeenCalledTimes(1) expect(conn.sendCommand).toHaveBeenNthCalledWith(1, { flag: 139264, - properties: { + _properties: { borderBevelSoftness: 12, borderLuma: 3 } @@ -109,7 +109,7 @@ test('setSuperSourceBorder - 8.0', async () => { expect(conn.sendCommand).toHaveBeenNthCalledWith(1, { ssrcId: 2, flag: 1088, - properties: { + _properties: { borderBevelSoftness: 12, borderLuma: 3 } diff --git a/src/commands/Audio/AudioMixerInputCommand.ts b/src/commands/Audio/AudioMixerInputCommand.ts index 72103ffe4..3f5328150 100644 --- a/src/commands/Audio/AudioMixerInputCommand.ts +++ b/src/commands/Audio/AudioMixerInputCommand.ts @@ -17,7 +17,6 @@ export class AudioMixerInputCommand extends WritableCommand { super() this.index = index - this.properties = {} } serialize () { diff --git a/src/commands/CommandBase.ts b/src/commands/CommandBase.ts index 3ed99372e..55fef4b10 100644 --- a/src/commands/CommandBase.ts +++ b/src/commands/CommandBase.ts @@ -27,10 +27,14 @@ export abstract class BasicWritableCommand implements ISerializableCommand { static readonly MaskFlags?: { [key: string]: number } static readonly minimumVersion?: ProtocolVersion - properties: T + protected _properties: T + + public get properties (): Readonly { + return this._properties + } constructor (properties: T) { - this.properties = properties + this._properties = properties } abstract serialize (version: ProtocolVersion): Buffer @@ -47,24 +51,24 @@ export abstract class WritableCommand extends BasicWritableCommand this.flag = 0 } - public updateProps (newProps: Partial) { - this._updateProps(newProps) + public updateProps (newProps: Partial): boolean { + return this._updateProps(newProps) } - protected _updateProps (newProps: Object) { - this.properties = { - ...this.properties, - ...newProps - } + protected _updateProps (newProps: { [key: string]: any }): boolean { const maskFlags = (this.constructor as any).MaskFlags as { [key: string]: number } - + let hasChanges = false if (maskFlags) { for (const key in newProps) { + const key2 = key as keyof T if (key in maskFlags) { this.flag = this.flag | maskFlags[key] + this._properties[key2] = newProps[key] + hasChanges = true } } } + return hasChanges } } diff --git a/src/commands/Inputs/InputPropertiesCommand.ts b/src/commands/Inputs/InputPropertiesCommand.ts index 0cbb694df..7f30876a3 100644 --- a/src/commands/Inputs/InputPropertiesCommand.ts +++ b/src/commands/Inputs/InputPropertiesCommand.ts @@ -19,7 +19,6 @@ export class InputPropertiesCommand extends WritableCommand { super() this.inputId = inputId - this.properties = {} } serialize () { diff --git a/src/commands/Media/MediaPlayerStatusCommand.ts b/src/commands/Media/MediaPlayerStatusCommand.ts index 187833498..91f5ec943 100644 --- a/src/commands/Media/MediaPlayerStatusCommand.ts +++ b/src/commands/Media/MediaPlayerStatusCommand.ts @@ -8,7 +8,7 @@ export class MediaPlayerStatusCommand extends WritableCommand { playing: 1 << 0, loop: 1 << 1, atBeginning: 1 << 2, - frame: 1 << 3 + clipFrame: 1 << 3 } static readonly rawName = 'SCPS' diff --git a/src/commands/MixEffects/FadeToBlack/FadeToBlackRateCommand.ts b/src/commands/MixEffects/FadeToBlack/FadeToBlackRateCommand.ts index 937440f94..d82232bfb 100644 --- a/src/commands/MixEffects/FadeToBlack/FadeToBlackRateCommand.ts +++ b/src/commands/MixEffects/FadeToBlack/FadeToBlackRateCommand.ts @@ -11,7 +11,6 @@ export class FadeToBlackRateCommand extends BasicWritableCommand<{ rate: number super({ rate }) this.mixEffect = mixEffect - this.properties = { rate } } serialize () { diff --git a/src/commands/MixEffects/Key/MixEffectKeyDVECommand.ts b/src/commands/MixEffects/Key/MixEffectKeyDVECommand.ts index 360ebb54d..683270017 100644 --- a/src/commands/MixEffects/Key/MixEffectKeyDVECommand.ts +++ b/src/commands/MixEffects/Key/MixEffectKeyDVECommand.ts @@ -42,7 +42,6 @@ export class MixEffectKeyDVECommand extends WritableCommand { static MaskFlags = { - keyType: 1 << 0, + mixEffectKeyType: 1 << 0, flyEnabled: 1 << 1 } diff --git a/src/commands/__tests__/index.spec.ts b/src/commands/__tests__/index.spec.ts index 78f1cc5aa..5f723e18f 100644 --- a/src/commands/__tests__/index.spec.ts +++ b/src/commands/__tests__/index.spec.ts @@ -340,7 +340,9 @@ const commandConverters: CommandTestConverterSet = { 'mixEffect': 'mixEffectIndex', 'upstreamKeyerId': 'keyerIndex' }, - propertyAliases: {} + propertyAliases: { + 'keyType': (v: number) => ({ val: v, name: 'mixEffectKeyType' }) + } }, 'KeOn': { idAliases: { @@ -644,11 +646,7 @@ const commandConverters: CommandTestConverterSet = { idAliases: { 'mediaPool': 'index' }, - propertyAliases: {}, - customMutate: (obj: any) => { - obj.frames = [] - return obj - } + propertyAliases: {} }, 'SMPC': { idAliases: { From bf688baa8ee5128d9d50f4fe48789053ebfb7c51 Mon Sep 17 00:00:00 2001 From: Julian Waller Date: Tue, 22 Oct 2019 11:57:55 +0100 Subject: [PATCH 07/68] feat: add test to ensure all serialized properties are covered by MaskFlags (when appropriate) --- src/commands/Inputs/InputPropertiesCommand.ts | 2 +- src/commands/__tests__/util.ts | 11 ++++++++++- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/src/commands/Inputs/InputPropertiesCommand.ts b/src/commands/Inputs/InputPropertiesCommand.ts index 7f30876a3..31dd9714e 100644 --- a/src/commands/Inputs/InputPropertiesCommand.ts +++ b/src/commands/Inputs/InputPropertiesCommand.ts @@ -8,7 +8,7 @@ export class InputPropertiesCommand extends WritableCommand { static MaskFlags = { longName: 1 << 0, shortName: 1 << 1, - isExternal: 1 << 2 + externalPortType: 1 << 2 } static readonly rawName = 'CInL' diff --git a/src/commands/__tests__/util.ts b/src/commands/__tests__/util.ts index 1426c7e12..c93772148 100644 --- a/src/commands/__tests__/util.ts +++ b/src/commands/__tests__/util.ts @@ -79,7 +79,16 @@ export function runTestForCommand (commandParser: CommandParser, commandConverte delete mutatedCommand.mask } - (cmd as any).properties = mutatedCommand + (cmd as any)._properties = mutatedCommand + + // Ensure all properties appear in the mask + const maskProps = (cmd as any).constructor.MaskFlags + if (maskProps) { + for (const key of Object.keys(mutatedCommand)) { + expect(maskProps).toHaveProperty(key) + // expect(maskProps[key]).not.toBeUndefined() + } + } const hexStr = (buf: Buffer) => { const str = buf.toString('hex') From 3b762487b44a5f8f95f2e78246fd004e2b89a1c6 Mon Sep 17 00:00:00 2001 From: Julian Waller Date: Fri, 29 Nov 2019 18:51:58 +0000 Subject: [PATCH 08/68] fix: failing tests --- src/__tests__/tally/chain-me2-pgm-state.json | 50 ++++---- src/__tests__/tally/chain-me2-pvw-state.json | 50 ++++---- src/__tests__/tally/dsk-active-state.json | 50 ++++---- src/__tests__/tally/dsk-in-auto-state.json | 50 ++++---- src/__tests__/tally/mid-dip-state.json | 50 ++++---- .../tally/mid-preview-trans-state.json | 50 ++++---- src/__tests__/tally/mid-trans-dve-state.json | 50 ++++---- ...mid-trans-dve-with-fill-and-key-state.json | 50 ++++---- .../tally/mid-trans-dve-with-fill-state.json | 50 ++++---- .../tally/mid-trans-sting-state.json | 50 ++++---- .../tally/mid-wipe-no-border-state.json | 50 ++++---- .../tally/mid-wipe-with-border-state.json | 50 ++++---- src/__tests__/tally/preview-trans-state.json | 50 ++++---- src/__tests__/tally/ssrc-state.json | 50 ++++---- src/__tests__/tally/ssrc2-state.json | 50 ++++---- .../tally/upstream-keyers-state.json | 50 ++++---- src/__tests__/util.ts | 15 +-- src/commands/TallyBySourceCommand.ts | 19 ++- src/commands/__tests__/util.ts | 3 +- src/dataTransfer/dataTransferFrame.ts | 2 +- src/enums/index.ts | 3 +- src/lib/atemSocket.ts | 3 +- src/lib/tally.ts | 112 +++++++++++------- tsconfig.build.json | 2 +- 24 files changed, 486 insertions(+), 473 deletions(-) diff --git a/src/__tests__/tally/chain-me2-pgm-state.json b/src/__tests__/tally/chain-me2-pgm-state.json index ba5d42dfb..c5669d91c 100644 --- a/src/__tests__/tally/chain-me2-pgm-state.json +++ b/src/__tests__/tally/chain-me2-pgm-state.json @@ -1,7 +1,7 @@ { "video": { - "ME": { - "0": { + "ME": [ + { "transitionProperties": { "style": 0, "selection": 1, @@ -314,7 +314,7 @@ "remainingFrames": 25 } }, - "1": { + { "transitionProperties": { "style": 0, "selection": 3, @@ -627,9 +627,9 @@ "remainingFrames": 25 } } - }, - "downstreamKeyers": { - "0": { + ], + "downstreamKeyers": [ + { "sources": { "fillSource": 13, "cutSource": 14 @@ -655,7 +655,7 @@ "isTowardsOnAir": true, "remainingFrames": 250 }, - "1": { + { "sources": { "fillSource": 15, "cutSource": 16 @@ -681,19 +681,19 @@ "isTowardsOnAir": true, "remainingFrames": 25 } - }, - "auxilliaries": { - "0": 3020, - "1": 0, - "2": 6000, - "3": 0, - "4": 6000, - "5": 7001 - }, - "superSources": { - "0": { - "boxes": { - "0": { + ], + "auxilliaries": [ + 3020, + 0, + 6000, + 0, + 6000, + 7001 + ], + "superSources": [ + { + "boxes": [ + { "enabled": true, "source": 3, "x": -1600, @@ -705,7 +705,7 @@ "cropLeft": 3200, "cropRight": 631 }, - "1": { + { "enabled": false, "source": 2, "x": 800, @@ -717,7 +717,7 @@ "cropLeft": 0, "cropRight": 0 }, - "2": { + { "enabled": true, "source": 1, "x": -800, @@ -729,7 +729,7 @@ "cropLeft": 0, "cropRight": 0 }, - "3": { + { "enabled": false, "source": 4, "x": 800, @@ -741,7 +741,7 @@ "cropLeft": 0, "cropRight": 0 } - }, + ], "index": 0, "properties": { "artFillSource": 3010, @@ -768,7 +768,7 @@ "borderLightSourceAltitude": 25 } } - } + ] }, "inputs": { "0": { diff --git a/src/__tests__/tally/chain-me2-pvw-state.json b/src/__tests__/tally/chain-me2-pvw-state.json index a5e512847..46bf36f2f 100644 --- a/src/__tests__/tally/chain-me2-pvw-state.json +++ b/src/__tests__/tally/chain-me2-pvw-state.json @@ -1,7 +1,7 @@ { "video": { - "ME": { - "0": { + "ME": [ + { "transitionProperties": { "style": 0, "selection": 1, @@ -314,7 +314,7 @@ "remainingFrames": 25 } }, - "1": { + { "transitionProperties": { "style": 0, "selection": 3, @@ -627,9 +627,9 @@ "remainingFrames": 25 } } - }, - "downstreamKeyers": { - "0": { + ], + "downstreamKeyers": [ + { "sources": { "fillSource": 13, "cutSource": 14 @@ -655,7 +655,7 @@ "isTowardsOnAir": true, "remainingFrames": 250 }, - "1": { + { "sources": { "fillSource": 15, "cutSource": 16 @@ -681,19 +681,19 @@ "isTowardsOnAir": true, "remainingFrames": 25 } - }, - "auxilliaries": { - "0": 3020, - "1": 0, - "2": 6000, - "3": 0, - "4": 6000, - "5": 7001 - }, - "superSources": { - "0": { - "boxes": { - "0": { + ], + "auxilliaries": [ + 3020, + 0, + 6000, + 0, + 6000, + 7001 + ], + "superSources": [ + { + "boxes": [ + { "enabled": true, "source": 3, "x": -1600, @@ -705,7 +705,7 @@ "cropLeft": 3200, "cropRight": 631 }, - "1": { + { "enabled": false, "source": 2, "x": 800, @@ -717,7 +717,7 @@ "cropLeft": 0, "cropRight": 0 }, - "2": { + { "enabled": true, "source": 1, "x": -800, @@ -729,7 +729,7 @@ "cropLeft": 0, "cropRight": 0 }, - "3": { + { "enabled": false, "source": 4, "x": 800, @@ -741,7 +741,7 @@ "cropLeft": 0, "cropRight": 0 } - }, + ], "index": 0, "properties": { "artFillSource": 3010, @@ -768,7 +768,7 @@ "borderLightSourceAltitude": 25 } } - } + ] }, "inputs": { "0": { diff --git a/src/__tests__/tally/dsk-active-state.json b/src/__tests__/tally/dsk-active-state.json index 2b0861f82..77f65acea 100644 --- a/src/__tests__/tally/dsk-active-state.json +++ b/src/__tests__/tally/dsk-active-state.json @@ -1,7 +1,7 @@ { "video": { - "ME": { - "0": { + "ME": [ + { "transitionProperties": { "style": 0, "selection": 1, @@ -314,7 +314,7 @@ "remainingFrames": 25 } }, - "1": { + { "transitionProperties": { "style": 0, "selection": 1, @@ -627,9 +627,9 @@ "remainingFrames": 25 } } - }, - "downstreamKeyers": { - "0": { + ], + "downstreamKeyers": [ + { "sources": { "fillSource": 13, "cutSource": 14 @@ -655,7 +655,7 @@ "isTowardsOnAir": false, "remainingFrames": 25 }, - "1": { + { "sources": { "fillSource": 15, "cutSource": 16 @@ -681,19 +681,19 @@ "isTowardsOnAir": true, "remainingFrames": 25 } - }, - "auxilliaries": { - "0": 3020, - "1": 0, - "2": 6000, - "3": 0, - "4": 6000, - "5": 7001 - }, - "superSources": { - "0": { - "boxes": { - "0": { + ], + "auxilliaries": [ + 3020, + 0, + 6000, + 0, + 6000, + 7001 + ], + "superSources": [ + { + "boxes": [ + { "enabled": true, "source": 3, "x": -1600, @@ -705,7 +705,7 @@ "cropLeft": 3200, "cropRight": 631 }, - "1": { + { "enabled": true, "source": 0, "x": 800, @@ -717,7 +717,7 @@ "cropLeft": 0, "cropRight": 0 }, - "2": { + { "enabled": true, "source": 0, "x": -800, @@ -729,7 +729,7 @@ "cropLeft": 0, "cropRight": 0 }, - "3": { + { "enabled": true, "source": 0, "x": 800, @@ -741,7 +741,7 @@ "cropLeft": 0, "cropRight": 0 } - }, + ], "index": 0, "properties": { "artFillSource": 3010, @@ -768,7 +768,7 @@ "borderLightSourceAltitude": 25 } } - } + ] }, "inputs": { "0": { diff --git a/src/__tests__/tally/dsk-in-auto-state.json b/src/__tests__/tally/dsk-in-auto-state.json index 26707a51a..1a8be9350 100644 --- a/src/__tests__/tally/dsk-in-auto-state.json +++ b/src/__tests__/tally/dsk-in-auto-state.json @@ -1,7 +1,7 @@ { "video": { - "ME": { - "0": { + "ME": [ + { "transitionProperties": { "style": 0, "selection": 1, @@ -314,7 +314,7 @@ "remainingFrames": 25 } }, - "1": { + { "transitionProperties": { "style": 0, "selection": 1, @@ -627,9 +627,9 @@ "remainingFrames": 25 } } - }, - "downstreamKeyers": { - "0": { + ], + "downstreamKeyers": [ + { "sources": { "fillSource": 13, "cutSource": 14 @@ -655,7 +655,7 @@ "isTowardsOnAir": true, "remainingFrames": 201 }, - "1": { + { "sources": { "fillSource": 15, "cutSource": 16 @@ -681,19 +681,19 @@ "isTowardsOnAir": true, "remainingFrames": 25 } - }, - "auxilliaries": { - "0": 3020, - "1": 0, - "2": 6000, - "3": 0, - "4": 6000, - "5": 7001 - }, - "superSources": { - "0": { - "boxes": { - "0": { + ], + "auxilliaries": [ + 3020, + 0, + 6000, + 0, + 6000, + 7001 + ], + "superSources": [ + { + "boxes": [ + { "enabled": true, "source": 3, "x": -1600, @@ -705,7 +705,7 @@ "cropLeft": 3200, "cropRight": 631 }, - "1": { + { "enabled": false, "source": 2, "x": 800, @@ -717,7 +717,7 @@ "cropLeft": 0, "cropRight": 0 }, - "2": { + { "enabled": true, "source": 1, "x": -800, @@ -729,7 +729,7 @@ "cropLeft": 0, "cropRight": 0 }, - "3": { + { "enabled": false, "source": 4, "x": 800, @@ -741,7 +741,7 @@ "cropLeft": 0, "cropRight": 0 } - }, + ], "index": 0, "properties": { "artFillSource": 3010, @@ -768,7 +768,7 @@ "borderLightSourceAltitude": 25 } } - } + ] }, "inputs": { "0": { diff --git a/src/__tests__/tally/mid-dip-state.json b/src/__tests__/tally/mid-dip-state.json index 7999d38ba..60d412293 100644 --- a/src/__tests__/tally/mid-dip-state.json +++ b/src/__tests__/tally/mid-dip-state.json @@ -1,7 +1,7 @@ { "video": { - "ME": { - "0": { + "ME": [ + { "transitionProperties": { "style": 1, "selection": 1, @@ -314,7 +314,7 @@ "remainingFrames": 25 } }, - "1": { + { "transitionProperties": { "style": 0, "selection": 1, @@ -627,9 +627,9 @@ "remainingFrames": 25 } } - }, - "downstreamKeyers": { - "0": { + ], + "downstreamKeyers": [ + { "sources": { "fillSource": 13, "cutSource": 14 @@ -655,7 +655,7 @@ "isTowardsOnAir": true, "remainingFrames": 250 }, - "1": { + { "sources": { "fillSource": 15, "cutSource": 16 @@ -681,19 +681,19 @@ "isTowardsOnAir": true, "remainingFrames": 25 } - }, - "auxilliaries": { - "0": 3020, - "1": 0, - "2": 6000, - "3": 0, - "4": 6000, - "5": 7001 - }, - "superSources": { - "0": { - "boxes": { - "0": { + ], + "auxilliaries": [ + 3020, + 0, + 6000, + 0, + 6000, + 7001 + ], + "superSources": [ + { + "boxes": [ + { "enabled": true, "source": 3, "x": -1600, @@ -705,7 +705,7 @@ "cropLeft": 3200, "cropRight": 631 }, - "1": { + { "enabled": false, "source": 2, "x": 800, @@ -717,7 +717,7 @@ "cropLeft": 0, "cropRight": 0 }, - "2": { + { "enabled": true, "source": 1, "x": -800, @@ -729,7 +729,7 @@ "cropLeft": 0, "cropRight": 0 }, - "3": { + { "enabled": false, "source": 4, "x": 800, @@ -741,7 +741,7 @@ "cropLeft": 0, "cropRight": 0 } - }, + ], "index": 0, "properties": { "artFillSource": 3010, @@ -768,7 +768,7 @@ "borderLightSourceAltitude": 25 } } - } + ] }, "inputs": { "0": { diff --git a/src/__tests__/tally/mid-preview-trans-state.json b/src/__tests__/tally/mid-preview-trans-state.json index b821a3ea4..5960662f1 100644 --- a/src/__tests__/tally/mid-preview-trans-state.json +++ b/src/__tests__/tally/mid-preview-trans-state.json @@ -1,7 +1,7 @@ { "video": { - "ME": { - "0": { + "ME": [ + { "transitionProperties": { "style": 0, "selection": 3, @@ -314,7 +314,7 @@ "remainingFrames": 25 } }, - "1": { + { "transitionProperties": { "style": 0, "selection": 1, @@ -627,9 +627,9 @@ "remainingFrames": 25 } } - }, - "downstreamKeyers": { - "0": { + ], + "downstreamKeyers": [ + { "sources": { "fillSource": 13, "cutSource": 14 @@ -655,7 +655,7 @@ "isTowardsOnAir": true, "remainingFrames": 250 }, - "1": { + { "sources": { "fillSource": 15, "cutSource": 16 @@ -681,19 +681,19 @@ "isTowardsOnAir": true, "remainingFrames": 25 } - }, - "auxilliaries": { - "0": 3020, - "1": 0, - "2": 6000, - "3": 0, - "4": 6000, - "5": 7001 - }, - "superSources": { - "0": { - "boxes": { - "0": { + ], + "auxilliaries": [ + 3020, + 0, + 6000, + 0, + 6000, + 7001 + ], + "superSources": [ + { + "boxes": [ + { "enabled": true, "source": 3, "x": -1600, @@ -705,7 +705,7 @@ "cropLeft": 3200, "cropRight": 631 }, - "1": { + { "enabled": false, "source": 2, "x": 800, @@ -717,7 +717,7 @@ "cropLeft": 0, "cropRight": 0 }, - "2": { + { "enabled": true, "source": 1, "x": -800, @@ -729,7 +729,7 @@ "cropLeft": 0, "cropRight": 0 }, - "3": { + { "enabled": false, "source": 4, "x": 800, @@ -741,7 +741,7 @@ "cropLeft": 0, "cropRight": 0 } - }, + ], "index": 0, "properties": { "artFillSource": 3010, @@ -768,7 +768,7 @@ "borderLightSourceAltitude": 25 } } - } + ] }, "inputs": { "0": { diff --git a/src/__tests__/tally/mid-trans-dve-state.json b/src/__tests__/tally/mid-trans-dve-state.json index fb63c962d..d6f089356 100644 --- a/src/__tests__/tally/mid-trans-dve-state.json +++ b/src/__tests__/tally/mid-trans-dve-state.json @@ -1,7 +1,7 @@ { "video": { - "ME": { - "0": { + "ME": [ + { "transitionProperties": { "style": 3, "selection": 1, @@ -314,7 +314,7 @@ "remainingFrames": 25 } }, - "1": { + { "transitionProperties": { "style": 0, "selection": 1, @@ -627,9 +627,9 @@ "remainingFrames": 25 } } - }, - "downstreamKeyers": { - "0": { + ], + "downstreamKeyers": [ + { "sources": { "fillSource": 13, "cutSource": 14 @@ -655,7 +655,7 @@ "isTowardsOnAir": true, "remainingFrames": 250 }, - "1": { + { "sources": { "fillSource": 15, "cutSource": 16 @@ -681,19 +681,19 @@ "isTowardsOnAir": true, "remainingFrames": 25 } - }, - "auxilliaries": { - "0": 3020, - "1": 0, - "2": 6000, - "3": 0, - "4": 6000, - "5": 7001 - }, - "superSources": { - "0": { - "boxes": { - "0": { + ], + "auxilliaries": [ + 3020, + 0, + 6000, + 0, + 6000, + 7001 + ], + "superSources": [ + { + "boxes": [ + { "enabled": true, "source": 3, "x": -1600, @@ -705,7 +705,7 @@ "cropLeft": 3200, "cropRight": 631 }, - "1": { + { "enabled": false, "source": 2, "x": 800, @@ -717,7 +717,7 @@ "cropLeft": 0, "cropRight": 0 }, - "2": { + { "enabled": true, "source": 1, "x": -800, @@ -729,7 +729,7 @@ "cropLeft": 0, "cropRight": 0 }, - "3": { + { "enabled": false, "source": 4, "x": 800, @@ -741,7 +741,7 @@ "cropLeft": 0, "cropRight": 0 } - }, + ], "index": 0, "properties": { "artFillSource": 3010, @@ -768,7 +768,7 @@ "borderLightSourceAltitude": 25 } } - } + ] }, "inputs": { "0": { diff --git a/src/__tests__/tally/mid-trans-dve-with-fill-and-key-state.json b/src/__tests__/tally/mid-trans-dve-with-fill-and-key-state.json index d8b69d174..e8bf98beb 100644 --- a/src/__tests__/tally/mid-trans-dve-with-fill-and-key-state.json +++ b/src/__tests__/tally/mid-trans-dve-with-fill-and-key-state.json @@ -1,7 +1,7 @@ { "video": { - "ME": { - "0": { + "ME": [ + { "transitionProperties": { "style": 3, "selection": 1, @@ -314,7 +314,7 @@ "remainingFrames": 25 } }, - "1": { + { "transitionProperties": { "style": 0, "selection": 1, @@ -627,9 +627,9 @@ "remainingFrames": 25 } } - }, - "downstreamKeyers": { - "0": { + ], + "downstreamKeyers": [ + { "sources": { "fillSource": 13, "cutSource": 14 @@ -655,7 +655,7 @@ "isTowardsOnAir": true, "remainingFrames": 250 }, - "1": { + { "sources": { "fillSource": 15, "cutSource": 16 @@ -681,19 +681,19 @@ "isTowardsOnAir": true, "remainingFrames": 25 } - }, - "auxilliaries": { - "0": 3020, - "1": 0, - "2": 6000, - "3": 0, - "4": 6000, - "5": 7001 - }, - "superSources": { - "0": { - "boxes": { - "0": { + ], + "auxilliaries": [ + 3020, + 0, + 6000, + 0, + 6000, + 7001 + ], + "superSources": [ + { + "boxes": [ + { "enabled": true, "source": 3, "x": -1600, @@ -705,7 +705,7 @@ "cropLeft": 3200, "cropRight": 631 }, - "1": { + { "enabled": false, "source": 2, "x": 800, @@ -717,7 +717,7 @@ "cropLeft": 0, "cropRight": 0 }, - "2": { + { "enabled": true, "source": 1, "x": -800, @@ -729,7 +729,7 @@ "cropLeft": 0, "cropRight": 0 }, - "3": { + { "enabled": false, "source": 4, "x": 800, @@ -741,7 +741,7 @@ "cropLeft": 0, "cropRight": 0 } - }, + ], "index": 0, "properties": { "artFillSource": 3010, @@ -768,7 +768,7 @@ "borderLightSourceAltitude": 25 } } - } + ] }, "inputs": { "0": { diff --git a/src/__tests__/tally/mid-trans-dve-with-fill-state.json b/src/__tests__/tally/mid-trans-dve-with-fill-state.json index 6f08402fa..3cc8745fa 100644 --- a/src/__tests__/tally/mid-trans-dve-with-fill-state.json +++ b/src/__tests__/tally/mid-trans-dve-with-fill-state.json @@ -1,7 +1,7 @@ { "video": { - "ME": { - "0": { + "ME": [ + { "transitionProperties": { "style": 3, "selection": 1, @@ -314,7 +314,7 @@ "remainingFrames": 25 } }, - "1": { + { "transitionProperties": { "style": 0, "selection": 1, @@ -627,9 +627,9 @@ "remainingFrames": 25 } } - }, - "downstreamKeyers": { - "0": { + ], + "downstreamKeyers": [ + { "sources": { "fillSource": 13, "cutSource": 14 @@ -655,7 +655,7 @@ "isTowardsOnAir": true, "remainingFrames": 250 }, - "1": { + { "sources": { "fillSource": 15, "cutSource": 16 @@ -681,19 +681,19 @@ "isTowardsOnAir": true, "remainingFrames": 25 } - }, - "auxilliaries": { - "0": 3020, - "1": 0, - "2": 6000, - "3": 0, - "4": 6000, - "5": 7001 - }, - "superSources": { - "0": { - "boxes": { - "0": { + ], + "auxilliaries": [ + 3020, + 0, + 6000, + 0, + 6000, + 7001 + ], + "superSources": [ + { + "boxes": [ + { "enabled": true, "source": 3, "x": -1600, @@ -705,7 +705,7 @@ "cropLeft": 3200, "cropRight": 631 }, - "1": { + { "enabled": false, "source": 2, "x": 800, @@ -717,7 +717,7 @@ "cropLeft": 0, "cropRight": 0 }, - "2": { + { "enabled": true, "source": 1, "x": -800, @@ -729,7 +729,7 @@ "cropLeft": 0, "cropRight": 0 }, - "3": { + { "enabled": false, "source": 4, "x": 800, @@ -741,7 +741,7 @@ "cropLeft": 0, "cropRight": 0 } - }, + ], "index": 0, "properties": { "artFillSource": 3010, @@ -768,7 +768,7 @@ "borderLightSourceAltitude": 25 } } - } + ] }, "inputs": { "0": { diff --git a/src/__tests__/tally/mid-trans-sting-state.json b/src/__tests__/tally/mid-trans-sting-state.json index 26eda5da0..54367e55e 100644 --- a/src/__tests__/tally/mid-trans-sting-state.json +++ b/src/__tests__/tally/mid-trans-sting-state.json @@ -1,7 +1,7 @@ { "video": { - "ME": { - "0": { + "ME": [ + { "transitionProperties": { "style": 4, "selection": 1, @@ -314,7 +314,7 @@ "remainingFrames": 25 } }, - "1": { + { "transitionProperties": { "style": 0, "selection": 1, @@ -627,9 +627,9 @@ "remainingFrames": 25 } } - }, - "downstreamKeyers": { - "0": { + ], + "downstreamKeyers": [ + { "sources": { "fillSource": 13, "cutSource": 14 @@ -655,7 +655,7 @@ "isTowardsOnAir": true, "remainingFrames": 250 }, - "1": { + { "sources": { "fillSource": 15, "cutSource": 16 @@ -681,19 +681,19 @@ "isTowardsOnAir": true, "remainingFrames": 25 } - }, - "auxilliaries": { - "0": 3020, - "1": 0, - "2": 6000, - "3": 0, - "4": 6000, - "5": 7001 - }, - "superSources": { - "0": { - "boxes": { - "0": { + ], + "auxilliaries": [ + 3020, + 0, + 6000, + 0, + 6000, + 7001 + ], + "superSources": [ + { + "boxes": [ + { "enabled": true, "source": 3, "x": -1600, @@ -705,7 +705,7 @@ "cropLeft": 3200, "cropRight": 631 }, - "1": { + { "enabled": false, "source": 2, "x": 800, @@ -717,7 +717,7 @@ "cropLeft": 0, "cropRight": 0 }, - "2": { + { "enabled": true, "source": 1, "x": -800, @@ -729,7 +729,7 @@ "cropLeft": 0, "cropRight": 0 }, - "3": { + { "enabled": false, "source": 4, "x": 800, @@ -741,7 +741,7 @@ "cropLeft": 0, "cropRight": 0 } - }, + ], "index": 0, "properties": { "artFillSource": 3010, @@ -768,7 +768,7 @@ "borderLightSourceAltitude": 25 } } - } + ] }, "inputs": { "0": { diff --git a/src/__tests__/tally/mid-wipe-no-border-state.json b/src/__tests__/tally/mid-wipe-no-border-state.json index e1c2afa0b..63e9eb732 100644 --- a/src/__tests__/tally/mid-wipe-no-border-state.json +++ b/src/__tests__/tally/mid-wipe-no-border-state.json @@ -1,7 +1,7 @@ { "video": { - "ME": { - "0": { + "ME": [ + { "transitionProperties": { "style": 2, "selection": 1, @@ -314,7 +314,7 @@ "remainingFrames": 25 } }, - "1": { + { "transitionProperties": { "style": 0, "selection": 1, @@ -627,9 +627,9 @@ "remainingFrames": 25 } } - }, - "downstreamKeyers": { - "0": { + ], + "downstreamKeyers": [ + { "sources": { "fillSource": 13, "cutSource": 14 @@ -655,7 +655,7 @@ "isTowardsOnAir": true, "remainingFrames": 250 }, - "1": { + { "sources": { "fillSource": 15, "cutSource": 16 @@ -681,19 +681,19 @@ "isTowardsOnAir": true, "remainingFrames": 25 } - }, - "auxilliaries": { - "0": 3020, - "1": 0, - "2": 6000, - "3": 0, - "4": 6000, - "5": 7001 - }, - "superSources": { - "0": { - "boxes": { - "0": { + ], + "auxilliaries": [ + 3020, + 0, + 6000, + 0, + 6000, + 7001 + ], + "superSources": [ + { + "boxes": [ + { "enabled": true, "source": 3, "x": -1600, @@ -705,7 +705,7 @@ "cropLeft": 3200, "cropRight": 631 }, - "1": { + { "enabled": false, "source": 2, "x": 800, @@ -717,7 +717,7 @@ "cropLeft": 0, "cropRight": 0 }, - "2": { + { "enabled": true, "source": 1, "x": -800, @@ -729,7 +729,7 @@ "cropLeft": 0, "cropRight": 0 }, - "3": { + { "enabled": false, "source": 4, "x": 800, @@ -741,7 +741,7 @@ "cropLeft": 0, "cropRight": 0 } - }, + ], "index": 0, "properties": { "artFillSource": 3010, @@ -768,7 +768,7 @@ "borderLightSourceAltitude": 25 } } - } + ] }, "inputs": { "0": { diff --git a/src/__tests__/tally/mid-wipe-with-border-state.json b/src/__tests__/tally/mid-wipe-with-border-state.json index 99ff3d3c6..94d74430f 100644 --- a/src/__tests__/tally/mid-wipe-with-border-state.json +++ b/src/__tests__/tally/mid-wipe-with-border-state.json @@ -1,7 +1,7 @@ { "video": { - "ME": { - "0": { + "ME": [ + { "transitionProperties": { "style": 2, "selection": 1, @@ -314,7 +314,7 @@ "remainingFrames": 25 } }, - "1": { + { "transitionProperties": { "style": 0, "selection": 1, @@ -627,9 +627,9 @@ "remainingFrames": 25 } } - }, - "downstreamKeyers": { - "0": { + ], + "downstreamKeyers": [ + { "sources": { "fillSource": 13, "cutSource": 14 @@ -655,7 +655,7 @@ "isTowardsOnAir": true, "remainingFrames": 250 }, - "1": { + { "sources": { "fillSource": 15, "cutSource": 16 @@ -681,19 +681,19 @@ "isTowardsOnAir": true, "remainingFrames": 25 } - }, - "auxilliaries": { - "0": 3020, - "1": 0, - "2": 6000, - "3": 0, - "4": 6000, - "5": 7001 - }, - "superSources": { - "0": { - "boxes": { - "0": { + ], + "auxilliaries": [ + 3020, + 0, + 6000, + 0, + 6000, + 7001 + ], + "superSources": [ + { + "boxes": [ + { "enabled": true, "source": 3, "x": -1600, @@ -705,7 +705,7 @@ "cropLeft": 3200, "cropRight": 631 }, - "1": { + { "enabled": false, "source": 2, "x": 800, @@ -717,7 +717,7 @@ "cropLeft": 0, "cropRight": 0 }, - "2": { + { "enabled": true, "source": 1, "x": -800, @@ -729,7 +729,7 @@ "cropLeft": 0, "cropRight": 0 }, - "3": { + { "enabled": false, "source": 4, "x": 800, @@ -741,7 +741,7 @@ "cropLeft": 0, "cropRight": 0 } - }, + ], "index": 0, "properties": { "artFillSource": 3010, @@ -768,7 +768,7 @@ "borderLightSourceAltitude": 25 } } - } + ] }, "inputs": { "0": { diff --git a/src/__tests__/tally/preview-trans-state.json b/src/__tests__/tally/preview-trans-state.json index 411ec905a..c6f0b4001 100644 --- a/src/__tests__/tally/preview-trans-state.json +++ b/src/__tests__/tally/preview-trans-state.json @@ -1,7 +1,7 @@ { "video": { - "ME": { - "0": { + "ME": [ + { "transitionProperties": { "style": 0, "selection": 3, @@ -314,7 +314,7 @@ "remainingFrames": 25 } }, - "1": { + { "transitionProperties": { "style": 0, "selection": 1, @@ -627,9 +627,9 @@ "remainingFrames": 25 } } - }, - "downstreamKeyers": { - "0": { + ], + "downstreamKeyers": [ + { "sources": { "fillSource": 13, "cutSource": 14 @@ -655,7 +655,7 @@ "isTowardsOnAir": true, "remainingFrames": 250 }, - "1": { + { "sources": { "fillSource": 15, "cutSource": 16 @@ -681,19 +681,19 @@ "isTowardsOnAir": true, "remainingFrames": 25 } - }, - "auxilliaries": { - "0": 3020, - "1": 0, - "2": 6000, - "3": 0, - "4": 6000, - "5": 7001 - }, - "superSources": { - "0": { - "boxes": { - "0": { + ], + "auxilliaries": [ + 3020, + 0, + 6000, + 0, + 6000, + 7001 + ], + "superSources": [ + { + "boxes": [ + { "enabled": true, "source": 3, "x": -1600, @@ -705,7 +705,7 @@ "cropLeft": 3200, "cropRight": 631 }, - "1": { + { "enabled": false, "source": 2, "x": 800, @@ -717,7 +717,7 @@ "cropLeft": 0, "cropRight": 0 }, - "2": { + { "enabled": true, "source": 1, "x": -800, @@ -729,7 +729,7 @@ "cropLeft": 0, "cropRight": 0 }, - "3": { + { "enabled": false, "source": 4, "x": 800, @@ -741,7 +741,7 @@ "cropLeft": 0, "cropRight": 0 } - }, + ], "index": 0, "properties": { "artFillSource": 3010, @@ -768,7 +768,7 @@ "borderLightSourceAltitude": 25 } } - } + ] }, "inputs": { "0": { diff --git a/src/__tests__/tally/ssrc-state.json b/src/__tests__/tally/ssrc-state.json index f2d03fd6e..6c2c2e459 100644 --- a/src/__tests__/tally/ssrc-state.json +++ b/src/__tests__/tally/ssrc-state.json @@ -1,7 +1,7 @@ { "video": { - "ME": { - "0": { + "ME": [ + { "transitionProperties": { "style": 0, "selection": 1, @@ -314,7 +314,7 @@ "remainingFrames": 25 } }, - "1": { + { "transitionProperties": { "style": 0, "selection": 1, @@ -627,9 +627,9 @@ "remainingFrames": 25 } } - }, - "downstreamKeyers": { - "0": { + ], + "downstreamKeyers": [ + { "sources": { "fillSource": 13, "cutSource": 14 @@ -655,7 +655,7 @@ "isTowardsOnAir": true, "remainingFrames": 25 }, - "1": { + { "sources": { "fillSource": 15, "cutSource": 16 @@ -681,19 +681,19 @@ "isTowardsOnAir": true, "remainingFrames": 25 } - }, - "auxilliaries": { - "0": 3020, - "1": 0, - "2": 6000, - "3": 0, - "4": 6000, - "5": 7001 - }, - "superSources": { - "0": { - "boxes": { - "0": { + ], + "auxilliaries": [ + 3020, + 0, + 6000, + 0, + 6000, + 7001 + ], + "superSources": [ + { + "boxes": [ + { "enabled": true, "source": 3, "x": -1600, @@ -705,7 +705,7 @@ "cropLeft": 3200, "cropRight": 631 }, - "1": { + { "enabled": false, "source": 2, "x": 800, @@ -717,7 +717,7 @@ "cropLeft": 0, "cropRight": 0 }, - "2": { + { "enabled": true, "source": 1, "x": -800, @@ -729,7 +729,7 @@ "cropLeft": 0, "cropRight": 0 }, - "3": { + { "enabled": false, "source": 4, "x": 800, @@ -741,7 +741,7 @@ "cropLeft": 0, "cropRight": 0 } - }, + ], "index": 0, "properties": { "artFillSource": 3010, @@ -768,7 +768,7 @@ "borderLightSourceAltitude": 25 } } - } + ] }, "inputs": { "0": { diff --git a/src/__tests__/tally/ssrc2-state.json b/src/__tests__/tally/ssrc2-state.json index 3cedc0464..e52697635 100644 --- a/src/__tests__/tally/ssrc2-state.json +++ b/src/__tests__/tally/ssrc2-state.json @@ -1,7 +1,7 @@ { "video": { - "ME": { - "0": { + "ME": [ + { "transitionProperties": { "style": 0, "selection": 1, @@ -314,7 +314,7 @@ "remainingFrames": 25 } }, - "1": { + { "transitionProperties": { "style": 0, "selection": 1, @@ -627,9 +627,9 @@ "remainingFrames": 25 } } - }, - "downstreamKeyers": { - "0": { + ], + "downstreamKeyers": [ + { "sources": { "fillSource": 13, "cutSource": 14 @@ -655,7 +655,7 @@ "isTowardsOnAir": true, "remainingFrames": 250 }, - "1": { + { "sources": { "fillSource": 15, "cutSource": 16 @@ -681,19 +681,19 @@ "isTowardsOnAir": true, "remainingFrames": 25 } - }, - "auxilliaries": { - "0": 3020, - "1": 0, - "2": 6000, - "3": 0, - "4": 6000, - "5": 7001 - }, - "superSources": { - "0": { - "boxes": { - "0": { + ], + "auxilliaries": [ + 3020, + 0, + 6000, + 0, + 6000, + 7001 + ], + "superSources": [ + { + "boxes": [ + { "enabled": true, "source": 3, "x": -1600, @@ -705,7 +705,7 @@ "cropLeft": 3200, "cropRight": 631 }, - "1": { + { "enabled": false, "source": 2, "x": 800, @@ -717,7 +717,7 @@ "cropLeft": 0, "cropRight": 0 }, - "2": { + { "enabled": true, "source": 1, "x": -800, @@ -729,7 +729,7 @@ "cropLeft": 0, "cropRight": 0 }, - "3": { + { "enabled": false, "source": 4, "x": 800, @@ -741,7 +741,7 @@ "cropLeft": 0, "cropRight": 0 } - }, + ], "index": 0, "properties": { "artFillSource": 3010, @@ -768,7 +768,7 @@ "borderLightSourceAltitude": 25 } } - } + ] }, "inputs": { "0": { diff --git a/src/__tests__/tally/upstream-keyers-state.json b/src/__tests__/tally/upstream-keyers-state.json index 02a2712c9..17190d6db 100644 --- a/src/__tests__/tally/upstream-keyers-state.json +++ b/src/__tests__/tally/upstream-keyers-state.json @@ -1,7 +1,7 @@ { "video": { - "ME": { - "0": { + "ME": [ + { "transitionProperties": { "style": 0, "selection": 5, @@ -314,7 +314,7 @@ "remainingFrames": 25 } }, - "1": { + { "transitionProperties": { "style": 0, "selection": 1, @@ -627,9 +627,9 @@ "remainingFrames": 25 } } - }, - "downstreamKeyers": { - "0": { + ], + "downstreamKeyers": [ + { "sources": { "fillSource": 13, "cutSource": 14 @@ -655,7 +655,7 @@ "isTowardsOnAir": true, "remainingFrames": 25 }, - "1": { + { "sources": { "fillSource": 15, "cutSource": 16 @@ -681,19 +681,19 @@ "isTowardsOnAir": true, "remainingFrames": 25 } - }, - "auxilliaries": { - "0": 3020, - "1": 0, - "2": 6000, - "3": 0, - "4": 6000, - "5": 7001 - }, - "superSources": { - "0": { - "boxes": { - "0": { + ], + "auxilliaries": [ + 3020, + 0, + 6000, + 0, + 6000, + 7001 + ], + "superSources": [ + { + "boxes": [ + { "enabled": true, "source": 3, "x": -1600, @@ -705,7 +705,7 @@ "cropLeft": 3200, "cropRight": 631 }, - "1": { + { "enabled": false, "source": 2, "x": 800, @@ -717,7 +717,7 @@ "cropLeft": 0, "cropRight": 0 }, - "2": { + { "enabled": true, "source": 1, "x": -800, @@ -729,7 +729,7 @@ "cropLeft": 0, "cropRight": 0 }, - "3": { + { "enabled": false, "source": 4, "x": 800, @@ -741,7 +741,7 @@ "cropLeft": 0, "cropRight": 0 } - }, + ], "index": 0, "properties": { "artFillSource": 3010, @@ -768,7 +768,7 @@ "borderLightSourceAltitude": 25 } } - } + ] }, "inputs": { "0": { diff --git a/src/__tests__/util.ts b/src/__tests__/util.ts index cfc24d2d1..ad7a644e6 100644 --- a/src/__tests__/util.ts +++ b/src/__tests__/util.ts @@ -1,25 +1,20 @@ import { plainToClass } from 'class-transformer' import { AtemState } from '..' -import { AtemAudioState, AudioChannel, AudioMasterChannel } from '../state/audio' +import { AtemAudioState } from '../state/audio' import { AtemVideoState, MixEffect, SuperSource } from '../state/video' function parseAudio (rawState: AtemAudioState) { const state = plainToClass(AtemAudioState, rawState) - state.master = plainToClass(AudioMasterChannel, state.master) - state.channels = state.channels.map(ch => plainToClass(AudioChannel, ch)) + state.master = state.master + state.channels = state.channels.map(ch => ch) return state } function parseVideo (rawState: AtemVideoState) { const state = plainToClass(AtemVideoState, rawState) - Object.keys(state.ME).map(id => { - state.ME[id] = plainToClass(MixEffect, state.ME[id]) - }) - Object.keys(state.superSources).map(id => { - state.superSources[id] = plainToClass(SuperSource, state.superSources[id]) - }) - + state.ME = state.ME.map(me => plainToClass(MixEffect, me)) + state.superSources = state.superSources.map(ssrc => plainToClass(SuperSource, ssrc)) return state } diff --git a/src/commands/TallyBySourceCommand.ts b/src/commands/TallyBySourceCommand.ts index 3754ca396..f40d006de 100644 --- a/src/commands/TallyBySourceCommand.ts +++ b/src/commands/TallyBySourceCommand.ts @@ -1,18 +1,17 @@ -import AbstractCommand from './AbstractCommand' +import { DeserializedCommand } from './CommandBase' import { AtemState } from '../state' -export class TallyBySourceCommand extends AbstractCommand { - rawName = 'TlSr' - auxBus: number +export interface TallyBySourceProps { + [source: number]: { program: boolean, preview: boolean } | undefined +} - properties: { - [source: number]: { program: boolean, preview: boolean } | undefined - } +export class TallyBySourceCommand extends DeserializedCommand { + static readonly rawName = 'TlSr' - deserialize (rawCommand: Buffer) { + static deserialize (rawCommand: Buffer) { const sourceCount = rawCommand.readUInt16BE(0) - const sources: TallyBySourceCommand['properties'] = {} + const sources: TallyBySourceProps = {} for (let i = 0; i < sourceCount; i++) { const source = rawCommand.readUInt16BE(2 + (i * 3)) const value = rawCommand.readUInt8(4 + (i * 3)) @@ -22,7 +21,7 @@ export class TallyBySourceCommand extends AbstractCommand { } } - this.properties = sources + return new TallyBySourceCommand(sources) } applyToState (_state: AtemState) { diff --git a/src/commands/__tests__/util.ts b/src/commands/__tests__/util.ts index cbd4ef9ab..d667c8d94 100644 --- a/src/commands/__tests__/util.ts +++ b/src/commands/__tests__/util.ts @@ -1,7 +1,6 @@ import { CommandParser } from '../../lib/atemCommandParser' import { ProtocolVersion } from '../../enums' import { IDeserializedCommand, ISerializableCommand } from '../CommandBase' -import { isFunction } from 'util' export type CommandTestConverterSet = { [key: string]: CommandTestConverter } export interface CommandTestConverter { @@ -63,7 +62,7 @@ export function runTestForCommand (commandParser: CommandParser, commandConverte } const cmd: ISerializableCommand = new cmdConstructor() // TODO - params - if (isFunction(cmd.serialize)) { + if (typeof (cmd as any).serialize === 'function') { matchedCase = true test(`Test #${i}: ${testCase.name} - Serialize`, () => { if (converter) { diff --git a/src/dataTransfer/dataTransferFrame.ts b/src/dataTransfer/dataTransferFrame.ts index d36343523..88094237f 100644 --- a/src/dataTransfer/dataTransferFrame.ts +++ b/src/dataTransfer/dataTransferFrame.ts @@ -25,7 +25,7 @@ export default class DataTransferFrame extends DataTransfer { transferStoreId: this.storeId, transferIndex: this.frameId, size: this.data.length, - mode: Enums.TransferMode.TEST + mode: Enums.TransferMode.Write }) return [ command ] } diff --git a/src/enums/index.ts b/src/enums/index.ts index e3b785309..63ffdbc20 100644 --- a/src/enums/index.ts +++ b/src/enums/index.ts @@ -213,8 +213,7 @@ export enum TransferMode { NoOp, Write, Clear, - WriteAudio = 256, - TEST = 0x0201 + WriteAudio = 256 } export enum StoragePool { diff --git a/src/lib/atemSocket.ts b/src/lib/atemSocket.ts index b6cb116e9..a1bb0da7d 100644 --- a/src/lib/atemSocket.ts +++ b/src/lib/atemSocket.ts @@ -6,7 +6,6 @@ import { IPCMessageType } from '../enums' import exitHook = require('exit-hook') import { Util } from './atemUtil' import { VersionCommand, ISerializableCommand, IDeserializedCommand } from '../commands' -import { isFunction } from 'util' export class AtemSocket extends EventEmitter { private _debug = false @@ -77,7 +76,7 @@ export class AtemSocket extends EventEmitter { } public _sendCommand (command: ISerializableCommand, trackingId: number) { - if (isFunction(command.serialize)) { + if (typeof (command as any).serialize !== 'function') { return Promise.reject(new Error('Command is not serializable')) } diff --git a/src/lib/tally.ts b/src/lib/tally.ts index 38ef1a057..4b4f39bf5 100644 --- a/src/lib/tally.ts +++ b/src/lib/tally.ts @@ -36,15 +36,17 @@ export function listVisibleInputs (mode: 'program' | 'preview', state: AtemState case Enums.InternalPortType.SuperSource: const ssrcId = inputId - 6000 const ssrc = state.video.getSuperSource(ssrcId) - Object.values(ssrc.boxes).forEach(box => { - if (box.enabled) { + ssrc.boxes.forEach(box => { + if (box && box.enabled) { inputs.add(box.source) } }) - inputs.add(ssrc.properties.artFillSource) - if (ssrc.properties.artOption === Enums.SuperSourceArtOption.Foreground) { - inputs.add(ssrc.properties.artCutSource) + if (ssrc.properties) { + inputs.add(ssrc.properties.artFillSource) + if (ssrc.properties.artOption === Enums.SuperSourceArtOption.Foreground) { + inputs.add(ssrc.properties.artCutSource) + } } break case Enums.InternalPortType.MEOutput: @@ -83,49 +85,63 @@ function _calcActiveMeInputs (mode: 'program' | 'preview', state: AtemState, meI } // Upstream Keyers - Object.values(meRef.upstreamKeyers).filter(usk => { - const keyerMask = 1 << (usk.upstreamKeyerId + 1) - const isPartOfTransition = meRef.transitionProperties.selection & keyerMask - if (mode === 'program') { // TODO - verify these conditions - if (meRef.inTransition) { - return usk.onAir || isPartOfTransition + meRef.upstreamKeyers.filter(usk => { + if (usk) { + const keyerMask = 1 << (usk.upstreamKeyerId + 1) + const isPartOfTransition = meRef.transitionProperties.selection & keyerMask + if (mode === 'program') { // TODO - verify these conditions + if (meRef.inTransition) { + return usk.onAir || isPartOfTransition + } + + return usk.onAir } - return usk.onAir + return (isPartOfTransition && !usk.onAir) || (usk.onAir && !isPartOfTransition) + } else { + return false } - - return (isPartOfTransition && !usk.onAir) || (usk.onAir && !isPartOfTransition) }).forEach(usk => { - inputs.add(usk.fillSource) + if (usk) { + inputs.add(usk.fillSource) - // This is the only USK type that actually uses the cutSource. - if (usk.mixEffectKeyType === Enums.MixEffectKeyType.Luma) { - inputs.add(usk.cutSource) + // This is the only USK type that actually uses the cutSource. + if (usk.mixEffectKeyType === Enums.MixEffectKeyType.Luma) { + inputs.add(usk.cutSource) + } } }) // DSKs only show up on ME 1, // so we only add them if that's the ME we are currently processing. if (meId === 0) { - Object.values(state.video.downstreamKeyers).filter(dsk => { - if (mode === 'program') { - return dsk.onAir || dsk.inTransition - } + state.video.downstreamKeyers.filter(dsk => { + if (dsk) { + if (mode === 'program') { + return dsk.onAir || dsk.inTransition + } - if (!dsk.properties) { - // Data isn't hydrated yet, we'll get 'em next time. + if (!dsk.properties) { + // Data isn't hydrated yet, we'll get 'em next time. + return false + } + + return dsk.properties.tie && !dsk.onAir + } else { return false } - - return dsk.properties.tie && !dsk.onAir }).forEach(dsk => { - inputs.add(dsk.sources.fillSource) - inputs.add(dsk.sources.cutSource) + if (dsk && dsk.sources) { + inputs.add(dsk.sources.fillSource) + inputs.add(dsk.sources.cutSource) + } }) } // Compute what sources are currently participating in a transition. - if ((meRef.inTransition && mode === 'program') || (mode === 'preview' && meRef.transitionPreview && meRef.transitionPosition > 0)) { + const isTransitionInProgram = mode === 'program' && meRef.inTransition + const isTransitionInPreview = mode === 'preview' && meRef.transitionPreview && meRef.transitionPosition > 0 + if (isTransitionInProgram || isTransitionInPreview) { if (meRef.transitionProperties.selection & 1) { // Includes background inputs.add(meRef.previewInput) } @@ -134,33 +150,39 @@ function _calcActiveMeInputs (mode: 'program' | 'preview', state: AtemState, meI // on the transition style being used, so we handle each separately. switch (meRef.transitionProperties.style) { case Enums.TransitionStyle.DIP: - inputs.add(meRef.transitionSettings.dip.input) + if (meRef.transitionSettings.dip) { + inputs.add(meRef.transitionSettings.dip.input) + } break case Enums.TransitionStyle.DVE: - switch (meRef.transitionSettings.DVE.style) { - case Enums.DVEEffect.GraphicCCWSpin: - case Enums.DVEEffect.GraphicCWSpin: - case Enums.DVEEffect.GraphicLogoWipe: { - inputs.add(meRef.transitionSettings.DVE.fillSource) - if (meRef.transitionSettings.DVE.enableKey) { - inputs.add(meRef.transitionSettings.DVE.keySource) + if (meRef.transitionSettings.DVE) { + switch (meRef.transitionSettings.DVE.style) { + case Enums.DVEEffect.GraphicCCWSpin: + case Enums.DVEEffect.GraphicCWSpin: + case Enums.DVEEffect.GraphicLogoWipe: { + inputs.add(meRef.transitionSettings.DVE.fillSource) + if (meRef.transitionSettings.DVE.enableKey) { + inputs.add(meRef.transitionSettings.DVE.keySource) + } + break + // Anything not Graphic* do not use the sources } - break - // Anything not Graphic* do not use the sources } } break case Enums.TransitionStyle.WIPE: - if (meRef.transitionSettings.wipe.borderWidth > 0) { + if (meRef.transitionSettings.wipe && meRef.transitionSettings.wipe.borderWidth > 0) { inputs.add(meRef.transitionSettings.wipe.borderInput) } break case Enums.TransitionStyle.STING: - const mediaPlayerIndex = meRef.transitionSettings.stinger.source - const fillInputId = 3000 + (mediaPlayerIndex * 10) - const keyInputId = fillInputId + 1 - inputs.add(fillInputId) - inputs.add(keyInputId) + if (meRef.transitionSettings.stinger) { + const mediaPlayerIndex = meRef.transitionSettings.stinger.source + const fillInputId = 3000 + (mediaPlayerIndex * 10) + const keyInputId = fillInputId + 1 + inputs.add(fillInputId) + inputs.add(keyInputId) + } break default: // Do nothing. diff --git a/tsconfig.build.json b/tsconfig.build.json index e2d66b1ec..f748c9454 100644 --- a/tsconfig.build.json +++ b/tsconfig.build.json @@ -2,6 +2,6 @@ "extends": "./config/tsconfig.base", "exclude": [ "node_modules/**", - "src/**/__tests__/*.ts" + "src/**/__tests__/*" ] } \ No newline at end of file From 458666bea507b5e33bdec411c9fbf77faf5b430a Mon Sep 17 00:00:00 2001 From: Julian Waller Date: Fri, 29 Nov 2019 20:34:45 +0000 Subject: [PATCH 09/68] wip: fix: still media uploading --- examples/upload.ts | 64 + src/atem.ts | 8 +- src/dataTransfer/__tests__/index.spec.ts | 128 + .../__tests__/upload-still-sequence.json | 59974 ++++++++++++++++ src/dataTransfer/dataLock.ts | 2 + src/dataTransfer/dataTransferClip.ts | 5 +- src/dataTransfer/dataTransferStill.ts | 6 +- src/dataTransfer/index.ts | 102 +- src/lib/atemSocket.ts | 2 +- src/lib/atemSocketChild.ts | 11 +- 10 files changed, 60236 insertions(+), 66 deletions(-) create mode 100644 examples/upload.ts create mode 100644 src/dataTransfer/__tests__/index.spec.ts create mode 100644 src/dataTransfer/__tests__/upload-still-sequence.json diff --git a/examples/upload.ts b/examples/upload.ts new file mode 100644 index 000000000..7a2a09298 --- /dev/null +++ b/examples/upload.ts @@ -0,0 +1,64 @@ +import { Atem } from '../dist' +import * as fs from 'fs' + +const file = fs.readFileSync('./stress/amsterdam.rgba') +// const file = fs.readFileSync('./testframe.rgba') + +if (process.argv.length < 3) { + console.error('Expected ip address as parameter') + process.exit(1) +} +const IP = process.argv[2] + +const MAX_POOL = 20 +let upload = 0 +let t = Date.now() + +async function uploadNext () { + // if (upload >= MAX_POOL) { + // return + // } + // console.log('item ', upload) + t = Date.now() + conn.uploadStill(upload % MAX_POOL, file, 'contemplation..', '') + // conn.uploadStill(upload, file, 'TEST FRAME', '') + .then(async (_res) => { + console.log(`Uploaded still #${upload} in ${Date.now() - t}ms at 1080p`) + // console.log('queue len', conn.dataTransferManager.commandQueue.length) + // console.log(conn.state.media.stillPool) + upload++ + // if (upload % 2 === 0) { + // await reconnect() + // console.log('reconnected') + // } + setTimeout(() => uploadNext(), 0) + // uploadNext() + }, (e) => { + console.log('e', e) + // console.log('retry') + // setTimeout(() => uploadNext(), 0) + }) +} + +// async function uploadInf () { +// while (true) { +// if (upload > 0) console.log(`Uploaded ${upload} in ${Date.now() - t}, is ${(Date.now() - t) / upload} at 720p`) +// await conn.dataTransferManager.uploadStill(upload % MAX_POOL, file, 'TEST FRAME ' + upload, '').catch((e) => console.log('e', e)) +// upload++ +// } +// } + +let conn = new Atem({ debug: false }) +conn.on('error', console.log) +conn.on('disconnected', () => { + console.log('Connection lost') + process.exit(0) +}) +conn.connect(IP) +conn.once('connected', () => { + console.log(`connected in ${Date.now() - t}ms`) + t = Date.now() + uploadNext() + // console.log(conn.state.media) + +}) diff --git a/src/atem.ts b/src/atem.ts index 6de3e0032..3ff35f54e 100644 --- a/src/atem.ts +++ b/src/atem.ts @@ -75,16 +75,16 @@ export class Atem extends EventEmitter { address: (options || {}).address, port: (options || {}).port }) - this.dataTransferManager = new DT.DataTransferManager( - (command: ISerializableCommand) => this.sendCommand(command) - ) + this.dataTransferManager = new DT.DataTransferManager() + this.socket.on('connect', () => this.dataTransferManager.startCommandSending((command: ISerializableCommand) => this.sendCommand(command))) + this.socket.on('disconnect', () => this.dataTransferManager.stopCommandSending()) // When the parent process begins exiting, remove the listeners on our child process. // We do this to avoid throwing an error when the child process exits // as a natural part of the parent process exiting. exitHook(() => { if (this.dataTransferManager) { - this.dataTransferManager.stop() + this.dataTransferManager.stopCommandSending() } }) diff --git a/src/dataTransfer/__tests__/index.spec.ts b/src/dataTransfer/__tests__/index.spec.ts new file mode 100644 index 000000000..fcbaf0d46 --- /dev/null +++ b/src/dataTransfer/__tests__/index.spec.ts @@ -0,0 +1,128 @@ +import * as DataTransferCommands from '../../commands/DataTransfer' +import { readFileSync } from 'fs' +import * as path from 'path' +import { DataTransferManager } from '..' + +function specToCommandClass (spec: any) { + for (const commandName in DataTransferCommands) { + if (spec.name === commandName) { + const cmdCons = (DataTransferCommands as any)[commandName] + const cmd = new cmdCons(spec.properties) + cmd.properties = spec.properties + return cmd + } + } + return undefined +} + +function mangleCommand (cmd: any, dir: string) { + const props = { ...cmd.properties } + Object.keys(props).forEach(k => { + if (Buffer.isBuffer(props[k])) { + const buf = props[k] as Buffer + props[k] = { bufferLength: buf.length } + } + }) + return { + name: cmd.constructor.name, + properties: props, + direction: dir + } +} + +function runDataTransferTest (spec: any) { + const manager = new DataTransferManager() + manager.startCommandSending(cmd => { + const expectedCmd = spec.shift() + const gotCmd = mangleCommand(cmd, 'send') + expect(expectedCmd).toEqual(gotCmd) + + while (spec.length > 0) { + if (spec[0].direction !== 'recv') break + const nextCmd = spec.shift() + const nextCmd2 = specToCommandClass(nextCmd) + if (!nextCmd2) throw new Error(`Failed specToCommandClass ${nextCmd.name}`) + manager.handleCommand(nextCmd2) + } + + return Promise.resolve(cmd) + }) + return manager +} + +test('Test Still upload', async () => { + const spec: any[] = JSON.parse(readFileSync(path.join(__dirname, './upload-still-sequence.json')).toString()) + + const newBuffer = Buffer.alloc(1920 * 1080 * 4, 0) + + const manager = runDataTransferTest(spec) + await manager.uploadStill(0, newBuffer, 'some still', '') + + await new Promise(resolve => setTimeout(resolve, 1000)) + + // Nothing should be left by this point + expect(spec).toHaveLength(0) +}) + +// function cleanupAtem (atem: Atem) { +// const atem2 = atem as any +// atem2.dataTransferManager.stop() + +// const sock = atem2.socket._socketProcess +// sock.removeAllListeners() +// sock.kill() +// } + +// test('TMP: Generate DataTransferSpec', async () => { +// const newBuffer = Buffer.alloc(1920 * 1080 * 4, 0) + +// const nb = new Atem({ debug: false }) +// try { +// nb.on('error', () => null) + +// await new Promise(resolve => { +// nb.on('connected', resolve) +// nb.connect('10.42.13.99') +// }) + +// const commands: any[] = [] + +// const procCmd = (cmd: AbstractCommand, dir: string) => { +// const props = { ...cmd.properties } +// Object.keys(props).forEach(k => { +// if (Buffer.isBuffer(props[k])) { +// const buf = props[k] as Buffer +// props[k] = { bufferLength: buf.length } +// } +// }) +// return { +// name: cmd.constructor.name, +// properties: props, +// direction: dir +// } +// } + +// const transfer = new DataTransferManager(cmd => { +// commands.push(procCmd(cmd, 'send')) +// return nb.sendCommand(cmd) +// }) +// nb.on('receivedCommand', cmd => { +// commands.push(procCmd(cmd, 'recv')) +// transfer.handleCommand(cmd) +// }) + +// await transfer.uploadStill(0, newBuffer, 'some still', '') + +// await new Promise(resolve => setTimeout(resolve, 1000)) + +// // console.log(JSON.stringify({ +// // sent: sentCommands, +// // received: receivedCommands +// // })) +// writeFileSync('upload.json', JSON.stringify(commands, undefined, '\t')) + +// expect(nb).toBeTruthy() +// } finally { +// cleanupAtem(nb) +// } +// }) diff --git a/src/dataTransfer/__tests__/upload-still-sequence.json b/src/dataTransfer/__tests__/upload-still-sequence.json new file mode 100644 index 000000000..bd3408bc0 --- /dev/null +++ b/src/dataTransfer/__tests__/upload-still-sequence.json @@ -0,0 +1,59974 @@ +[ + { + "name": "LockStateCommand", + "properties": { + "index": 0, + "locked": true + }, + "direction": "send" + }, + { + "name": "LockObtainedCommand", + "properties": { + "index": 0 + }, + "direction": "recv" + }, + { + "name": "DataTransferUploadRequestCommand", + "properties": { + "transferId": 0, + "transferStoreId": 0, + "transferIndex": 0, + "size": 8294400, + "mode": 1 + }, + "direction": "send" + }, + { + "name": "LockStateUpdateCommand", + "properties": { + "index": 0, + "locked": true + }, + "direction": "recv" + }, + { + "name": "DataTransferUploadContinueCommand", + "properties": { + "transferId": 0, + "chunkSize": 1396, + "chunkCount": 216 + }, + "direction": "recv" + }, + { + "name": "DataTransferFileDescriptionCommand", + "properties": { + "name": "some still", + "description": "", + "fileHash": "\u0016V�������\u0016�\u0000��\u0010�", + "transferId": 0 + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferUploadContinueCommand", + "properties": { + "transferId": 0, + "chunkSize": 1396, + "chunkCount": 149 + }, + "direction": "recv" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferUploadContinueCommand", + "properties": { + "transferId": 0, + "chunkSize": 1396, + "chunkCount": 184 + }, + "direction": "recv" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferUploadContinueCommand", + "properties": { + "transferId": 0, + "chunkSize": 1396, + "chunkCount": 166 + }, + "direction": "recv" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferUploadContinueCommand", + "properties": { + "transferId": 0, + "chunkSize": 1396, + "chunkCount": 171 + }, + "direction": "recv" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferUploadContinueCommand", + "properties": { + "transferId": 0, + "chunkSize": 1396, + "chunkCount": 166 + }, + "direction": "recv" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferUploadContinueCommand", + "properties": { + "transferId": 0, + "chunkSize": 1396, + "chunkCount": 164 + }, + "direction": "recv" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferUploadContinueCommand", + "properties": { + "transferId": 0, + "chunkSize": 1396, + "chunkCount": 169 + }, + "direction": "recv" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferUploadContinueCommand", + "properties": { + "transferId": 0, + "chunkSize": 1396, + "chunkCount": 185 + }, + "direction": "recv" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferUploadContinueCommand", + "properties": { + "transferId": 0, + "chunkSize": 1396, + "chunkCount": 153 + }, + "direction": "recv" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferUploadContinueCommand", + "properties": { + "transferId": 0, + "chunkSize": 1396, + "chunkCount": 202 + }, + "direction": "recv" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferUploadContinueCommand", + "properties": { + "transferId": 0, + "chunkSize": 1396, + "chunkCount": 184 + }, + "direction": "recv" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferUploadContinueCommand", + "properties": { + "transferId": 0, + "chunkSize": 1396, + "chunkCount": 216 + }, + "direction": "recv" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferUploadContinueCommand", + "properties": { + "transferId": 0, + "chunkSize": 1396, + "chunkCount": 190 + }, + "direction": "recv" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferUploadContinueCommand", + "properties": { + "transferId": 0, + "chunkSize": 1396, + "chunkCount": 120 + }, + "direction": "recv" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferUploadContinueCommand", + "properties": { + "transferId": 0, + "chunkSize": 1396, + "chunkCount": 190 + }, + "direction": "recv" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferUploadContinueCommand", + "properties": { + "transferId": 0, + "chunkSize": 1396, + "chunkCount": 190 + }, + "direction": "recv" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferUploadContinueCommand", + "properties": { + "transferId": 0, + "chunkSize": 1396, + "chunkCount": 165 + }, + "direction": "recv" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferUploadContinueCommand", + "properties": { + "transferId": 0, + "chunkSize": 1396, + "chunkCount": 179 + }, + "direction": "recv" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferUploadContinueCommand", + "properties": { + "transferId": 0, + "chunkSize": 1396, + "chunkCount": 216 + }, + "direction": "recv" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferUploadContinueCommand", + "properties": { + "transferId": 0, + "chunkSize": 1396, + "chunkCount": 165 + }, + "direction": "recv" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferUploadContinueCommand", + "properties": { + "transferId": 0, + "chunkSize": 1396, + "chunkCount": 112 + }, + "direction": "recv" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferUploadContinueCommand", + "properties": { + "transferId": 0, + "chunkSize": 1396, + "chunkCount": 131 + }, + "direction": "recv" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferUploadContinueCommand", + "properties": { + "transferId": 0, + "chunkSize": 1396, + "chunkCount": 158 + }, + "direction": "recv" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferUploadContinueCommand", + "properties": { + "transferId": 0, + "chunkSize": 1396, + "chunkCount": 180 + }, + "direction": "recv" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferUploadContinueCommand", + "properties": { + "transferId": 0, + "chunkSize": 1396, + "chunkCount": 194 + }, + "direction": "recv" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferUploadContinueCommand", + "properties": { + "transferId": 0, + "chunkSize": 1396, + "chunkCount": 159 + }, + "direction": "recv" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferUploadContinueCommand", + "properties": { + "transferId": 0, + "chunkSize": 1396, + "chunkCount": 121 + }, + "direction": "recv" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferUploadContinueCommand", + "properties": { + "transferId": 0, + "chunkSize": 1396, + "chunkCount": 110 + }, + "direction": "recv" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferUploadContinueCommand", + "properties": { + "transferId": 0, + "chunkSize": 1396, + "chunkCount": 194 + }, + "direction": "recv" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferUploadContinueCommand", + "properties": { + "transferId": 0, + "chunkSize": 1396, + "chunkCount": 185 + }, + "direction": "recv" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferUploadContinueCommand", + "properties": { + "transferId": 0, + "chunkSize": 1396, + "chunkCount": 216 + }, + "direction": "recv" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferUploadContinueCommand", + "properties": { + "transferId": 0, + "chunkSize": 1396, + "chunkCount": 163 + }, + "direction": "recv" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferUploadContinueCommand", + "properties": { + "transferId": 0, + "chunkSize": 1396, + "chunkCount": 197 + }, + "direction": "recv" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferUploadContinueCommand", + "properties": { + "transferId": 0, + "chunkSize": 1396, + "chunkCount": 203 + }, + "direction": "recv" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 1392 + } + }, + "direction": "send" + }, + { + "name": "DataTransferDataCommand", + "properties": { + "transferId": 0, + "body": { + "bufferLength": 864 + } + }, + "direction": "send" + }, + { + "name": "DataTransferCompleteCommand", + "properties": { + "transferId": 0 + }, + "direction": "recv" + }, + { + "name": "LockStateCommand", + "properties": { + "index": 0, + "locked": false + }, + "direction": "send" + }, + { + "name": "LockStateUpdateCommand", + "properties": { + "index": 0, + "locked": false + }, + "direction": "recv" + } +] \ No newline at end of file diff --git a/src/dataTransfer/dataLock.ts b/src/dataTransfer/dataLock.ts index 468b16cd9..21f67f101 100644 --- a/src/dataTransfer/dataLock.ts +++ b/src/dataTransfer/dataLock.ts @@ -23,6 +23,8 @@ export default class DataLock { if (!this.activeTransfer) { this.dequeueAndRun() } + + return transfer.promise } private dequeueAndRun () { diff --git a/src/dataTransfer/dataTransferClip.ts b/src/dataTransfer/dataTransferClip.ts index 6829c1e43..0a7e2f387 100644 --- a/src/dataTransfer/dataTransferClip.ts +++ b/src/dataTransfer/dataTransferClip.ts @@ -5,15 +5,16 @@ import DataTransferFrame from './dataTransferFrame' export default class DataTransferClip extends DataTransfer { readonly clipIndex: number // 0 or 1 - frames: Array = [] + readonly frames: Array curFrame = 0 readonly name: string - constructor (clipIndex: number, name: string) { + constructor (clipIndex: number, name: string, frames: Array) { super(0, 1 + clipIndex) this.clipIndex = clipIndex this.name = name + this.frames = frames } public start () { diff --git a/src/dataTransfer/dataTransferStill.ts b/src/dataTransfer/dataTransferStill.ts index 646320698..ed7aadf49 100644 --- a/src/dataTransfer/dataTransferStill.ts +++ b/src/dataTransfer/dataTransferStill.ts @@ -3,11 +3,11 @@ import { Commands } from '..' import DataTransferFrame from './dataTransferFrame' export default class DataTransferStill extends DataTransferFrame { - readonly name: string - readonly description: string + private readonly name: string + private readonly description: string constructor (transferId: number, frameId: number, data: Buffer, name: string, description: string) { - super(transferId, 0xffff, frameId, data) + super(transferId, 0, frameId, data) this.name = name this.description = description diff --git a/src/dataTransfer/index.ts b/src/dataTransfer/index.ts index 70c63b3e3..6fbd3bba4 100644 --- a/src/dataTransfer/index.ts +++ b/src/dataTransfer/index.ts @@ -10,53 +10,50 @@ import { ISerializableCommand } from '../commands/CommandBase' const MAX_PACKETS_TO_SEND_PER_TICK = 10 export class DataTransferManager { - readonly commandQueue: Array = [] + private readonly commandQueue: Array = [] - readonly stillsLock = new DataLock(0, cmd => this.commandQueue.push(cmd)) - readonly clipLocks = [ + private readonly stillsLock = new DataLock(0, cmd => this.commandQueue.push(cmd)) + private readonly clipLocks = [ new DataLock(1, cmd => this.commandQueue.push(cmd)), new DataLock(2, cmd => this.commandQueue.push(cmd)) ] - readonly interval: NodeJS.Timer + private interval: NodeJS.Timer | undefined - transferIndex = 0 + private transferIndex: number = 0 - constructor (sendCommand: (command: ISerializableCommand) => Promise) { - this.interval = setInterval(() => { - if (this.commandQueue.length <= 0) { - return - } + public startCommandSending (sendCommand: (command: ISerializableCommand) => Promise) { + if (!this.interval) { + // New connection means a new queue + this.commandQueue.splice(0, this.commandQueue.length) - const commandsToSend = this.commandQueue.splice(0, MAX_PACKETS_TO_SEND_PER_TICK) - commandsToSend.forEach(command => { - sendCommand(command).catch(() => { /* discard error */ }) - }) - }, 0) - } + this.interval = setInterval(() => { + if (this.commandQueue.length <= 0) { + return + } - stop () { - clearInterval(this.interval) + const commandsToSend = this.commandQueue.splice(0, MAX_PACKETS_TO_SEND_PER_TICK) + commandsToSend.forEach(command => { + sendCommand(command).catch(() => { /* discard error */ }) + }) + }, 0) // TODO - should this be done slower? + } + } + public stopCommandSending () { + if (this.interval) { + clearInterval(this.interval) + this.interval = undefined + } } - handleCommand (command: Commands.IDeserializedCommand) { + public handleCommand (command: Commands.IDeserializedCommand) { const allLocks = [ this.stillsLock, ...this.clipLocks ] // try to establish the associated DataLock: let lock: DataLock | undefined if (command.constructor.name === Commands.LockObtainedCommand.name || command.constructor.name === Commands.LockStateUpdateCommand.name) { - switch (command.properties.index) { - case 0 : - lock = this.stillsLock - break - case 1 : - lock = this.clipLocks[0] - break - case 2 : - lock = this.clipLocks[1] - break - } - } else if (command.properties.storeId) { + lock = allLocks[command.properties.index] + } else if (typeof command.properties.storeId === 'number') { lock = allLocks[command.properties.storeId] } else if (command.properties.transferId !== undefined || command.properties.transferIndex !== undefined) { for (const _lock of allLocks) { @@ -69,6 +66,8 @@ export class DataTransferManager { console.log('UNKNOWN COMMAND:', command) return } + + // console.log('CMD', command.constructor.name) if (!lock) return // handle actual command @@ -90,35 +89,30 @@ export class DataTransferManager { } } - uploadStill (index: number, data: Buffer, name: string, description: string) { + public uploadStill (index: number, data: Buffer, name: string, description: string) { const transfer = new DataTransferStill(this.transferIndex++, index, data, name, description) - // transfer.commandQueue = this.commandQueue - - this.stillsLock.enqueue(transfer) - - return transfer.promise + return this.stillsLock.enqueue(transfer) } - uploadClip (index: number, data: Array, name: string) { - const transfer = new DataTransferClip(1 + index, name) - - for (const frameId in data) { - const frameTransfer = new DataTransferFrame(this.transferIndex++, 1 + index, Number(frameId), data[frameId]) - - transfer.frames.push(frameTransfer) - } - - this.clipLocks[index].enqueue(transfer) - - return transfer.promise + public async uploadClip (index: number, data: Array, name: string) { + const frames = data.map((frame, id) => new DataTransferFrame(this.transferIndex++, 1 + index, id, frame)) + const transfer = new DataTransferClip(1 + index, name, frames) + const lock = await this.getClipLock(index) + return lock.enqueue(transfer) } - uploadAudio (index: number, data: Buffer, name: string) { + public async uploadAudio (index: number, data: Buffer, name: string) { const transfer = new DataTransferAudio(this.transferIndex++, 1 + index, data, name) - - this.clipLocks[index].enqueue(transfer) - - return transfer.promise + const lock = await this.getClipLock(index) + return lock.enqueue(transfer) } + private async getClipLock (index: number) { + const lock = this.clipLocks[index] + if (lock) { + return lock + } else { + throw new Error('Invalid clip id') + } + } } diff --git a/src/lib/atemSocket.ts b/src/lib/atemSocket.ts index a1bb0da7d..0070af297 100644 --- a/src/lib/atemSocket.ts +++ b/src/lib/atemSocket.ts @@ -86,7 +86,7 @@ export class AtemSocket extends EventEmitter { fullPayload.write((command.constructor as any).rawName, 4, 4) payload.copy(fullPayload, 8, 0) - if (this._debug) this.log('PAYLOAD', fullPayload) + if (this._debug) this.log('PAYLOAD', command.constructor.name, fullPayload) return this._sendSubprocessMessage({ cmd: IPCMessageType.OutboundCommand, diff --git a/src/lib/atemSocketChild.ts b/src/lib/atemSocketChild.ts index 40cad1898..53a339e5c 100644 --- a/src/lib/atemSocketChild.ts +++ b/src/lib/atemSocketChild.ts @@ -235,13 +235,20 @@ export class AtemSocketChild extends EventEmitter { sentPacket.lastSent = Date.now() sentPacket.resent++ - this.log('RESEND: ', sentPacket) + this.log('Resending', sentPacket.packetId) + if (this._debug) { + this.log('RESEND: ', sentPacket) + } this._sendPacket(sentPacket.packet) retransmitFromPacketId = sentPacket.packetId } else { this.emit(IPCMessageType.CommandTimeout, sentPacket.packetId, sentPacket.trackingId) this._inFlight.splice(this._inFlight.indexOf(sentPacket), 1) - this.log('TIMED OUT: ', sentPacket.packet) + + this.log('Timed out: ', sentPacket.packetId) + if (this._debug) { + this.log('TIMED OUT: ', sentPacket.packet) + } // @todo: we should probably break up the connection here. } } From 42a99c92dda698d75fab5036909be2e9225a9a28 Mon Sep 17 00:00:00 2001 From: Julian Waller Date: Sat, 30 Nov 2019 23:06:57 +0000 Subject: [PATCH 10/68] feat: some tidying of socket-child and parsing of previously unknown PacketFlag --- examples/upload.ts | 31 ++- jest.config.js | 1 + package.json | 4 + src/atem.ts | 6 +- src/enums/index.ts | 4 +- src/lib/__mocks__/dgram.ts | 69 +++++ src/lib/__tests__/socket-child.spec.ts | 334 +++++++++++++++++++++++++ src/lib/atemSocket.ts | 10 +- src/lib/atemSocketChild.ts | 230 +++++++++-------- src/lib/atemUtil.ts | 6 - src/socket-child.ts | 2 +- tsconfig.build.json | 3 +- yarn.lock | 120 ++++++--- 13 files changed, 667 insertions(+), 153 deletions(-) create mode 100644 src/lib/__mocks__/dgram.ts create mode 100644 src/lib/__tests__/socket-child.spec.ts diff --git a/examples/upload.ts b/examples/upload.ts index 7a2a09298..561b30c45 100644 --- a/examples/upload.ts +++ b/examples/upload.ts @@ -10,17 +10,20 @@ if (process.argv.length < 3) { } const IP = process.argv[2] -const MAX_POOL = 20 let upload = 0 let t = Date.now() +const conn = new Atem({ debug: false }) + +let stuckTimeout: any = null + async function uploadNext () { // if (upload >= MAX_POOL) { // return // } // console.log('item ', upload) t = Date.now() - conn.uploadStill(upload % MAX_POOL, file, 'contemplation..', '') + conn.uploadStill(upload % conn.state.media.stillPool.length, file, 'contemplation..', '') // conn.uploadStill(upload, file, 'TEST FRAME', '') .then(async (_res) => { console.log(`Uploaded still #${upload} in ${Date.now() - t}ms at 1080p`) @@ -31,10 +34,33 @@ async function uploadNext () { // await reconnect() // console.log('reconnected') // } + + if (stuckTimeout) { + clearTimeout(stuckTimeout) + } + stuckTimeout = setTimeout(() => { + console.log('') + console.log('UPLOAD GOT STUCK') + console.log('') + console.log('') + // console.log(JSON.stringify(conn.state, undefined, 4)) + console.log('') + const dt = (conn as any).dataTransferManager + // console.log(JSON.stringify({ + // stills: dt.stillsLock, + // clips: dt.clipLocks + // }, undefined, 4)) + fs.writeFileSync('upload-stuck', JSON.stringify({ + stills: dt.stillsLock, + clips: dt.clipLocks + }, undefined, 4)) + }, 20000) + setTimeout(() => uploadNext(), 0) // uploadNext() }, (e) => { console.log('e', e) + setTimeout(() => uploadNext(), 500) // console.log('retry') // setTimeout(() => uploadNext(), 0) }) @@ -48,7 +74,6 @@ async function uploadNext () { // } // } -let conn = new Atem({ debug: false }) conn.on('error', console.log) conn.on('disconnected', () => { console.log('Connection lost') diff --git a/jest.config.js b/jest.config.js index 1c92c973b..3dca92d4d 100644 --- a/jest.config.js +++ b/jest.config.js @@ -14,6 +14,7 @@ module.exports = { testMatch: [ '**/__tests__/**/*.spec.(ts|js)' ], + setupFilesAfterEnv: ["jest-extended"], testEnvironment: 'node', coverageThreshold: { global: { diff --git a/package.json b/package.json index f020988ea..c2eb5d8ac 100644 --- a/package.json +++ b/package.json @@ -79,13 +79,16 @@ ], "devDependencies": { "@types/jest": "^24.0.11", + "@types/lolex": "^5.1.0", "@types/node": "^12.7.12", "class-transformer": "^0.2.3", "codecov": "^3.2.0", "gh-pages": "^2.0.1", "jest": "^24.8.0", + "jest-extended": "^0.11.2", "jest-haste-map": "^24.0.0", "jest-resolve": "^24.1.0", + "lolex": "^5.1.1", "mkdirp": "^0.5.1", "node-license-validator": "^1.3.0", "npm-scripts-info": "0.3.9", @@ -94,6 +97,7 @@ "standard-version": "^7.0.0", "trash-cli": "^3.0.0", "ts-jest": "^24.0.2", + "ts-node": "^8.5.4", "tslint": "^5.17.0", "tslint-config-security": "^1.16.0", "tslint-config-standard": "8.0.1", diff --git a/src/atem.ts b/src/atem.ts index 3ff35f54e..22a9e6bda 100644 --- a/src/atem.ts +++ b/src/atem.ts @@ -114,14 +114,14 @@ export class Atem extends EventEmitter { } sendCommand (command: ISerializableCommand): Promise { - const nextPacketId = this.socket.nextPacketId + const commandTrackingId = this.socket.nextCommandTrackingId return new Promise((resolve, reject) => { - this._sentQueue[nextPacketId] = { + this._sentQueue[commandTrackingId] = { command, resolve, reject } - this.socket._sendCommand(command, nextPacketId).catch(reject) + this.socket._sendCommand(command, commandTrackingId).catch(reject) }) } diff --git a/src/enums/index.ts b/src/enums/index.ts index 63ffdbc20..bd40f3fa7 100644 --- a/src/enums/index.ts +++ b/src/enums/index.ts @@ -42,8 +42,8 @@ export enum ConnectionState { export enum PacketFlag { AckRequest = 0x01, Connect = 0x02, - Repeat = 0x04, - Error = 0x08, + IsRetransmit = 0x04, + RetransmitRequest = 0x08, AckReply = 0x10 } diff --git a/src/lib/__mocks__/dgram.ts b/src/lib/__mocks__/dgram.ts new file mode 100644 index 000000000..cb821ebae --- /dev/null +++ b/src/lib/__mocks__/dgram.ts @@ -0,0 +1,69 @@ +import { EventEmitter } from 'events' +import { SocketType, RemoteInfo } from 'dgram' +import 'jest-extended' + +export class Socket extends EventEmitter { + public isOpen: boolean = false + + public expectedAddress?: string + public expectedPort?: number + + constructor () { + super() + } + + public sendImpl?: (msg: Buffer) => void + + public emitMessage (msg: Buffer) { + expect(Buffer.isBuffer(msg)).toBeTruthy() + + const rinfo: RemoteInfo = { + address: this.expectedAddress || '127.0.0.1', + port: this.expectedPort || 9910, + family: 'IPv4', + size: msg.length + } + this.emit('message', msg, rinfo) + } + + public bind (port?: number, address?: string, callback?: () => void): void { + expect(port).toBeUndefined() + expect(address).toBeUndefined() + expect(callback).toBeUndefined() + + this.isOpen = true + } + + public send (msg: string | Uint8Array, offset: number, length: number, port: number, address?: string, callback?: (error: Error | null, bytes: number) => void): void { + expect(Buffer.isBuffer(msg)).toBeTruthy() + expect(offset).toBeNumber() + expect(length).toBeNumber() + expect(port).toBeNumber() + expect(address).toBeString() + expect(callback).toBeUndefined() + + if (this.expectedAddress) { + expect(address).toEqual(this.expectedAddress) + } + if (this.expectedPort) { + expect(port).toEqual(this.expectedPort) + } + + if (this.sendImpl) { + this.sendImpl(msg as Buffer) + } + } + + public close (cb?: Function) { + this.isOpen = false + // TODO - optional delay? + if (cb) cb() + } +} + +export function createSocket (type: SocketType, callback?: (msg: Buffer, rinfo: RemoteInfo) => void): Socket { + expect(type).toEqual('udp4') + expect(callback).toBeUndefined() + + return new Socket() +} diff --git a/src/lib/__tests__/socket-child.spec.ts b/src/lib/__tests__/socket-child.spec.ts new file mode 100644 index 000000000..db2c1fa07 --- /dev/null +++ b/src/lib/__tests__/socket-child.spec.ts @@ -0,0 +1,334 @@ +jest.mock('dgram') +import { Socket } from '../__mocks__/dgram' +import { AtemSocketChild } from '../atemSocketChild' +import { Util } from '../..' +import * as lolex from 'lolex' +import { ConnectionState, PacketFlag, IPCMessageType } from '../../enums' + +const ADDRESS = '127.0.0.1' + +function getSocket (child: AtemSocketChild) { + const socket = (child as any)._socket as Socket + expect(socket).toBeTruthy() + expect(socket.isOpen).toBeTruthy() + socket.expectedAddress = ADDRESS + socket.expectedPort = 9910 + + return socket +} +function getState (child: AtemSocketChild) { + return (child as any)._connectionState as ConnectionState +} +function fakeConnect (child: AtemSocketChild) { + const child2 = child as any + child2._connectionState = ConnectionState.Established + child2._address = '127.0.0.1' +} + +describe('SocketChild', () => { + let clock: lolex.InstalledClock + beforeEach(() => { + clock = lolex.install() + }) + afterEach(() => { + clock.uninstall() + }) + + test('Establish connection', async () => { + const child = new AtemSocketChild() + try { + const socket = getSocket(child) + + let receivedPacket = false + socket.sendImpl = (msg: Buffer) => { + if (!receivedPacket) { + expect(msg).toEqual(Util.COMMAND_CONNECT_HELLO) + receivedPacket = true + } else { + // Shouldnt get any other sends + expect(false).toBeTruthy() + } + } + + expect(getState(child)).toEqual(ConnectionState.Closed) + child.connect(ADDRESS) + + // Ensure everything has ticked through + clock.tick(20) + + // Confirm something was sent + expect(receivedPacket).toBeTruthy() + expect(getState(child)).toEqual(ConnectionState.SynSent) + + receivedPacket = false + socket.sendImpl = (msg: Buffer) => { + if (!receivedPacket) { + expect(msg).toEqual(Buffer.from([ + 0x80, 0x0C, 0x53, 0x1B, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00 + ])) + receivedPacket = true + } else { + // Shouldnt get any other sends + expect(false).toBeTruthy() + } + } + + // Now get the connection established + socket.emitMessage(Buffer.from([ + 0x10, 0x14, // Length & Type + 0x53, 0x1b, // Session Id + 0x00, 0x00, // Not acking + 0x00, 0x00, // Not asking for retransmit + 0x00, 0xd1, // 'Client pkt id' Not sure why this + 0x00, 0x00, // Packet Id + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // Unknown Payload + ])) + + // Ensure everything has ticked through + clock.tick(20) + + // Confirm something was sent + expect(receivedPacket).toBeTruthy() + expect(getState(child)).toEqual(ConnectionState.Established) + + } finally { + if (child) { + // Try and cleanup any timers + await child.disconnect() + } + } + }) + + function genAckRequestMessage (pktId: number, extraLength?: number) { + const buffer = Buffer.from([ + 0x08, 0x0c + (extraLength || 0), // Length & Type + 0x53, 0x1b, // Session Id + 0x00, 0x00, // Not acking + 0x00, 0x00, // Not asking for retransmit + 0x00, 0x00, // 'Client pkt id' Not needed + 0x00, 0x00 // Packet Id + ]) + buffer.writeUInt16BE(pktId, 10) // Packet Id + + return buffer + } + + test('Ack - delayed', async () => { + const child = new AtemSocketChild() + try { + fakeConnect(child) + const socket = getSocket(child) + + const acked: number[] = [] + let gotUnknown = false + socket.sendImpl = (msg: Buffer) => { + const opcode = msg.readUInt8(0) >> 3 + if (opcode & PacketFlag.AckReply) { + acked.push(msg.readUInt16BE(4)) + } else { + gotUnknown = true + // Shouldnt get any other sends + expect(false).toBeTruthy() + } + } + + socket.emitMessage(genAckRequestMessage(1)) + + // Nothing should have been sent immediately + expect(acked).toEqual([]) + expect(gotUnknown).toBeFalse() + + // Still nothing sent + clock.tick(4) + expect(acked).toEqual([]) + expect(gotUnknown).toBeFalse() + + // Should be an ack a little later + clock.tick(10) + expect(acked).toEqual([1]) + expect(gotUnknown).toBeFalse() + + } finally { + if (child) { + // Try and cleanup any timers + await child.disconnect() + } + } + }) + + test('Ack - bulk', async () => { + const child = new AtemSocketChild() + try { + fakeConnect(child) + const socket = getSocket(child) + + let acked: number[] = [] + let gotUnknown = false + socket.sendImpl = (msg: Buffer) => { + const opcode = msg.readUInt8(0) >> 3 + if (opcode & PacketFlag.AckReply) { + acked.push(msg.readUInt16BE(4)) + } else { + gotUnknown = true + // Shouldnt get any other sends + expect(false).toBeTruthy() + } + } + + for (let i = 1; i <= 15; i++) { + socket.emitMessage(genAckRequestMessage(i)) + } + + // Nothing should have been sent yet + clock.tick(4) + expect(acked).toEqual([]) + expect(gotUnknown).toBeFalse() + + // One more will trigger an ack + socket.emitMessage(genAckRequestMessage(16)) + expect(acked).toEqual([16]) + expect(gotUnknown).toBeFalse() + acked = [] + + // Nothing more should be acked + clock.tick(10) + expect(acked).toEqual([]) + expect(gotUnknown).toBeFalse() + + } finally { + if (child) { + // Try and cleanup any timers + await child.disconnect() + } + } + }) + + test('Inbound commands', async () => { + const child = new AtemSocketChild() + try { + fakeConnect(child) + const socket = getSocket(child) + + let gotUnknown = false + socket.sendImpl = (_msg: Buffer) => { + gotUnknown = true + // Shouldnt get any other sends + expect(false).toBeTruthy() + } + + let gotCmds: number[] = [] + child.on(IPCMessageType.InboundCommand, buf => gotCmds.push(buf.length)) + + // Nothing + socket.emitMessage(genAckRequestMessage(1)) + expect(gotCmds).toEqual([]) + expect(gotUnknown).toBeFalse() + + // Some payload + const buffer = Buffer.concat([genAckRequestMessage(2, 1), Buffer.from([0])]) + socket.emitMessage(buffer) + expect(gotCmds).toEqual([1]) + expect(gotUnknown).toBeFalse() + gotCmds = [] + + // Repeated should not re-emit + socket.emitMessage(buffer) + expect(gotCmds).toEqual([]) + expect(gotUnknown).toBeFalse() + + // Previous should not re-emit + socket.emitMessage(Buffer.concat([genAckRequestMessage(1, 1), Buffer.from([0])])) + expect(gotCmds).toEqual([]) + expect(gotUnknown).toBeFalse() + + // Another payload + socket.emitMessage(Buffer.concat([genAckRequestMessage(3, 1), Buffer.from([0])])) + expect(gotCmds).toEqual([1]) + expect(gotUnknown).toBeFalse() + gotCmds = [] + + } finally { + if (child) { + // Try and cleanup any timers + await child.disconnect() + } + } + }) + + test('Inbound commands - around wrap', async () => { + const child = new AtemSocketChild() + try { + fakeConnect(child) + const socket = getSocket(child) + ; (child as any)._lastReceivedPacketId = 32766 // 32767 is max + + let gotUnknown = false + socket.sendImpl = (_msg: Buffer) => { + gotUnknown = true + // Shouldnt get any other sends + expect(false).toBeTruthy() + } + + let gotCmds: number[] = [] + child.on(IPCMessageType.InboundCommand, buf => gotCmds.push(buf.length)) + + // Nothing + socket.emitMessage(Buffer.concat([genAckRequestMessage(32766, 1), Buffer.from([0])])) + expect(gotCmds).toEqual([]) + expect(gotUnknown).toBeFalse() + + // Some payload + const lastBuffer = Buffer.concat([genAckRequestMessage(32767, 1), Buffer.from([0])]) + socket.emitMessage(lastBuffer) + expect(gotCmds).toEqual([1]) + expect(gotUnknown).toBeFalse() + gotCmds = [] + + // Should not re-emit + socket.emitMessage(lastBuffer) + expect(gotCmds).toEqual([]) + expect(gotUnknown).toBeFalse() + gotCmds = [] + + // Now it has wrapped + const firstBuffer = Buffer.concat([genAckRequestMessage(0, 1), Buffer.from([0])]) + socket.emitMessage(firstBuffer) + expect(gotCmds).toEqual([1]) + expect(gotUnknown).toBeFalse() + gotCmds = [] + + // Next buffer + socket.emitMessage(Buffer.concat([genAckRequestMessage(1, 1), Buffer.from([0])])) + expect(gotCmds).toEqual([1]) + expect(gotUnknown).toBeFalse() + gotCmds = [] + + // Should not re-emit + socket.emitMessage(firstBuffer) + expect(gotCmds).toEqual([]) + expect(gotUnknown).toBeFalse() + gotCmds = [] + + // Retransmit of lastBuffer is not uncommon, it should not re-emit + socket.emitMessage(lastBuffer) + expect(gotCmds).toEqual([]) + expect(gotUnknown).toBeFalse() + gotCmds = [] + + // Ensure that the first buffer still does not re-emit + socket.emitMessage(firstBuffer) + expect(gotCmds).toEqual([]) + expect(gotUnknown).toBeFalse() + gotCmds = [] + + } finally { + if (child) { + // Try and cleanup any timers + await child.disconnect() + } + } + }) + +}) diff --git a/src/lib/atemSocket.ts b/src/lib/atemSocket.ts index 0070af297..47a84e031 100644 --- a/src/lib/atemSocket.ts +++ b/src/lib/atemSocket.ts @@ -9,7 +9,7 @@ import { VersionCommand, ISerializableCommand, IDeserializedCommand } from '../c export class AtemSocket extends EventEmitter { private _debug = false - private _localPacketId = 0 + private _nextCommandTrackingId = 0 private _address: string private _port: number = 9910 private _shouldConnect = false @@ -68,11 +68,11 @@ export class AtemSocket extends EventEmitter { // Will be re-assigned by the top-level ATEM class. } - get nextPacketId (): number { - if (this._localPacketId >= Number.MAX_SAFE_INTEGER) { - this._localPacketId = 0 + get nextCommandTrackingId (): number { + if (this._nextCommandTrackingId >= Number.MAX_SAFE_INTEGER) { + this._nextCommandTrackingId = 0 } - return ++this._localPacketId + return ++this._nextCommandTrackingId } public _sendCommand (command: ISerializableCommand, trackingId: number) { diff --git a/src/lib/atemSocketChild.ts b/src/lib/atemSocketChild.ts index 53a339e5c..7f2c049ba 100644 --- a/src/lib/atemSocketChild.ts +++ b/src/lib/atemSocketChild.ts @@ -1,35 +1,57 @@ -import { createSocket, Socket } from 'dgram' +import { createSocket, Socket, RemoteInfo } from 'dgram' import { EventEmitter } from 'events' -import { format } from 'util' import { Util } from './atemUtil' import { ConnectionState, IPCMessageType, PacketFlag } from '../enums' import * as NanoTimer from 'nanotimer' +const IN_FLIGHT_TIMEOUT = 30 // ms +const RECONNECT_INTERVAL = 5000 // ms +const MAX_PACKET_RETRIES = 5 +const MAX_PACKET_ID = (1 << 15) - 1 // Atem expects 15 not 16 bits before wrapping +const MAX_PACKET_PER_ACK = 16 + +interface InFlightPacket { + readonly packetId: number + readonly trackingId: number + readonly payload: Buffer + lastSent: number + resent: number +} + export class AtemSocketChild extends EventEmitter { + private readonly _debug = false + private _connectionState = ConnectionState.Closed - private _debug = false private _reconnectTimer: NodeJS.Timer | undefined private _retransmitTimer: NodeJS.Timer | undefined - private _localPacketId = 1 - private _maxPacketID = (1 << 15) - 1 // Atem expects 15 not 16 bits before wrapping + private _nextSendPacketId = 1 private _sessionId: number = 0 private _address: string private _port: number = 9910 private _socket: Socket - private _reconnectInterval = 5000 - private _inFlightTimeout = 30 - private _maxRetries = 5 private _lastReceivedAt: number = Date.now() - private _lastReceivedPacketId = 0 - private _inFlight: Array<{packetId: number, trackingId: number, lastSent: number, packet: Buffer, resent: number}> = [] - private _ackTimer = new NanoTimer() - private _hasTimeout = false - private _receivedWithoutAck = 0 + private _lastReceivedPacketId: number = 0 + private readonly _inFlight: InFlightPacket[] = [] + private readonly _ackTimer = new NanoTimer() + private _ackTimerRunning = false + private _receivedWithoutAck: number = 0 private _lastAcked = 0 + public on!: ((event: IPCMessageType.Disconnect, listener: () => void) => this) & + ((event: IPCMessageType.Log, listener: (payload: string) => void) => this) & + ((event: IPCMessageType.InboundCommand, listener: (payload: Buffer, packetId: number) => void) => this) & + ((event: IPCMessageType.CommandAcknowledged, listener: (packetId: number, trackingId: number) => void) => this) & + ((event: IPCMessageType.CommandTimeout, listener: (packetId: number, trackingId: number) => void) => this) + + public emit!: ((event: IPCMessageType.Disconnect) => boolean) & + ((event: IPCMessageType.Log, payload: string) => boolean) & + ((event: IPCMessageType.InboundCommand, payload: Buffer, packetId: number) => boolean) & + ((event: IPCMessageType.CommandAcknowledged, packetId: number, trackingId: number) => boolean) & + ((event: IPCMessageType.CommandTimeout, packetId: number, trackingId: number) => boolean) + constructor (options: { address?: string, port?: number } = {}) { super() this._address = options.address || '' @@ -37,22 +59,22 @@ export class AtemSocketChild extends EventEmitter { this._socket = this._createSocket() } - public connect (address?: string, port?: number) { + public connect (address?: string, port?: number): void { if (!this._reconnectTimer) { this._reconnectTimer = setInterval(() => { - if (this._lastReceivedAt + this._reconnectInterval > Date.now()) return + if (this._lastReceivedAt + RECONNECT_INTERVAL > Date.now()) return if (this._connectionState === ConnectionState.Established) { this._connectionState = ConnectionState.Closed - this.emit(IPCMessageType.Disconnect, null, null) + this.emit(IPCMessageType.Disconnect) } - this._localPacketId = 1 + this._nextSendPacketId = 1 this._sessionId = 0 this.log('reconnect') if (this._address && this._port) { this._sendPacket(Util.COMMAND_CONNECT_HELLO) this._connectionState = ConnectionState.SynSent } - }, this._reconnectInterval) + }, RECONNECT_INTERVAL) } // Check for retransmits every 10 milliseconds if (!this._retransmitTimer) { @@ -70,60 +92,56 @@ export class AtemSocketChild extends EventEmitter { this._connectionState = ConnectionState.SynSent } - public disconnect () { + public disconnect (): Promise { + // Stop timers, as they just cause pointless work now. + if (this._retransmitTimer) { + clearInterval(this._retransmitTimer) + this._retransmitTimer = undefined + } + if (this._reconnectTimer) { + clearInterval(this._reconnectTimer) + this._reconnectTimer = undefined + } + return new Promise((resolve) => { - if (this._connectionState === ConnectionState.Established) { - this._socket.close(() => { - resolve() - }) - } else { + try { + this._socket.close(() => resolve()) + } catch (e) { resolve() } }).then(() => { - if (this._retransmitTimer) { - clearInterval(this._retransmitTimer) - this._retransmitTimer = undefined - } - if (this._reconnectTimer) { - clearInterval(this._reconnectTimer) - this._reconnectTimer = undefined - } - this._reconnectTimer = undefined - this._connectionState = ConnectionState.Closed this._createSocket() this.emit(IPCMessageType.Disconnect) }) } - public log (fmt: string, ...args: any[]): void { - const payload = format(fmt, ...args) + public log (payload: string): void { this.emit(IPCMessageType.Log, payload) } - get nextPacketId (): number { - return this._localPacketId - } + public sendCommand (payload: Buffer, trackingId: number): void { + const packetId = this._nextSendPacketId++ + if (this._nextSendPacketId > MAX_PACKET_ID) this._nextSendPacketId = 0 - public _sendCommand (serializedCommand: Buffer, trackingId: number) { - const payload = serializedCommand - if (this._debug) this.log('PAYLOAD', payload) + const opcode = PacketFlag.AckRequest << 11 + + if (this._debug) this.log(`SEND ${payload}`) const buffer = Buffer.alloc(12 + payload.length, 0) - buffer.writeUInt16BE(0x0800 | payload.length + 12, 0) // Opcode & Length + buffer.writeUInt16BE(opcode | (payload.length + 12), 0) // Opcode & Length buffer.writeUInt16BE(this._sessionId, 2) - buffer.writeUInt16BE(this._localPacketId, 10) + buffer.writeUInt16BE(packetId, 10) payload.copy(buffer, 12) this._sendPacket(buffer) this._inFlight.push({ - packetId: this._localPacketId, + packetId, trackingId, lastSent: Date.now(), - packet: buffer, - resent: 0 }) - this._localPacketId++ - if (this._maxPacketID < this._localPacketId) this._localPacketId = 0 + payload: buffer, + resent: 0 + }) } private _createSocket () { @@ -134,94 +152,100 @@ export class AtemSocketChild extends EventEmitter { return this._socket } - private _receivePacket (packet: Buffer, rinfo: any) { - if (this._debug) this.log('RECV ', packet) + private _receivePacket (packet: Buffer, rinfo: RemoteInfo) { + if (this._debug) this.log(`RECV ${packet}`) this._lastReceivedAt = Date.now() - const length = ((packet[0] & 0x07) << 8) | packet[1] + const length = packet.readUInt16BE(0) & 0x07ff if (length !== rinfo.size) return - const flags = packet[0] >> 3 - // this._sessionId = [packet[2], packet[3]] - this._sessionId = packet[2] << 8 | packet[3] - const remotePacketId = packet[10] << 8 | packet[11] + const flags = packet.readUInt8(0) >> 3 + this._sessionId = packet.readUInt16BE(2) + const remotePacketId = packet.readUInt16BE(10) // Send hello answer packet when receive connect flags - if (flags & PacketFlag.Connect && !(flags & PacketFlag.Repeat)) { - this._sendPacket(Util.COMMAND_CONNECT_HELLO_ANSWER) + if (flags & PacketFlag.Connect) { + this._connectionState = ConnectionState.Established + this._sendAck(remotePacketId) + this._lastReceivedPacketId = remotePacketId + return } - // Parse commands, Emit 'stateChanged' event after parse - if (flags & PacketFlag.AckRequest) { - if (this._connectionState === ConnectionState.Established) { - if (remotePacketId === (this._lastReceivedPacketId + 1) % this._maxPacketID) { - this._attemptAck(remotePacketId) + if (this._connectionState === ConnectionState.Established) { + // Device asked for retransmit + if (flags & PacketFlag.RetransmitRequest) { + const fromPacketId = packet.readUInt16BE(6) + this.log(`Retransmit request: ${fromPacketId}`) + + // TODO + } + + // Got a packet that needs an ack + if (flags & PacketFlag.AckRequest) { + // Check if it next in the sequence + if (remotePacketId === (this._lastReceivedPacketId + 1) % (MAX_PACKET_ID + 1)) { // TODO - tidy this + this._sendOrQueueAck(remotePacketId) this._lastReceivedPacketId = remotePacketId - } else { - return + + // It might have commands + if (length > 12) { + this.emit(IPCMessageType.InboundCommand, packet.slice(12), remotePacketId) + } } } - if (length > 12) { - this.emit(IPCMessageType.InboundCommand, packet.slice(12), remotePacketId) - } - } - - // Send ping packet, Emit 'connect' event after receive all stats - if (flags & PacketFlag.AckRequest && length === 12 && this._connectionState === ConnectionState.SynSent) { - this._connectionState = ConnectionState.Established - this._sendAck(remotePacketId) - this._lastReceivedPacketId = remotePacketId - } - // Device ack'ed our command - if (flags & PacketFlag.AckReply && this._connectionState === ConnectionState.Established) { - const ackPacketId = packet[4] << 8 | packet[5] - this._lastAcked = ackPacketId - for (const i in this._inFlight) { - if (ackPacketId >= this._inFlight[i].packetId || this._localPacketId < this._inFlight[i].packetId) { - this.emit(IPCMessageType.CommandAcknowledged, this._inFlight[i].packetId, this._inFlight[i].trackingId) - this._inFlight.splice(Number(i), 1) + // Device ack'ed our packet + if (flags & PacketFlag.AckReply) { + const ackPacketId = packet.readUInt16BE(4) + this._lastAcked = ackPacketId + for (const i in this._inFlight) { + // TODO - this doesnt wrap well... + if (ackPacketId >= this._inFlight[i].packetId || this._nextSendPacketId < this._inFlight[i].packetId) { + this.emit(IPCMessageType.CommandAcknowledged, this._inFlight[i].packetId, this._inFlight[i].trackingId) + this._inFlight.splice(Number(i), 1) + } } } } } private _sendPacket (packet: Buffer) { - if (this._debug) this.log('SEND ', packet) + if (this._debug) this.log(`SEND ${packet}`) this._socket.send(packet, 0, packet.length, this._port, this._address) } - private _attemptAck (packetId: number) { + private _sendOrQueueAck (packetId: number) { this._lastReceivedPacketId = packetId this._receivedWithoutAck++ - if (this._receivedWithoutAck === 16) { + if (this._receivedWithoutAck >= MAX_PACKET_PER_ACK) { this._receivedWithoutAck = 0 - this._hasTimeout = false + this._ackTimerRunning = false this._ackTimer.clearTimeout() this._sendAck(this._lastReceivedPacketId) - } else if (!this._hasTimeout) { - this._hasTimeout = true + } else if (!this._ackTimerRunning) { + this._ackTimerRunning = true // timeout for 5 ms (syntax for nanotimer says m) this._ackTimer.setTimeout(() => { this._receivedWithoutAck = 0 - this._hasTimeout = false + this._ackTimerRunning = false this._sendAck(this._lastReceivedPacketId) }, [], '5m') } } private _sendAck (packetId: number) { - const buffer = Buffer.alloc(12, 0) - buffer.writeUInt16BE(0x800C, 0) // Opcode & Length + const opcode = PacketFlag.AckReply << 11 + const length = 12 + const buffer = Buffer.alloc(length, 0) + buffer.writeUInt16BE(opcode | length, 0) buffer.writeUInt16BE(this._sessionId, 2) buffer.writeUInt16BE(packetId, 4) - buffer.writeUInt8(0x41, 9) this._sendPacket(buffer) } private _checkForRetransmit () { let retransmitFromPacketId: number | undefined for (const sentPacket of this._inFlight) { - if (sentPacket.packetId <= this._lastAcked || sentPacket.packetId > this._localPacketId) { + if (sentPacket.packetId <= this._lastAcked || sentPacket.packetId > this._nextSendPacketId) { this.emit(IPCMessageType.CommandAcknowledged, sentPacket.packetId, sentPacket.trackingId) this._inFlight.splice(this._inFlight.indexOf(sentPacket), 1) continue @@ -229,25 +253,25 @@ export class AtemSocketChild extends EventEmitter { if (retransmitFromPacketId && sentPacket.packetId > retransmitFromPacketId) { sentPacket.lastSent = Date.now() sentPacket.resent++ - this._sendPacket(sentPacket.packet) - } else if (sentPacket && sentPacket.lastSent + this._inFlightTimeout < Date.now()) { - if (sentPacket.resent <= this._maxRetries && sentPacket.packetId < this.nextPacketId) { + this._sendPacket(sentPacket.payload) + } else if (sentPacket && sentPacket.lastSent + IN_FLIGHT_TIMEOUT < Date.now()) { + if (sentPacket.resent <= MAX_PACKET_RETRIES && sentPacket.packetId < this._nextSendPacketId) { sentPacket.lastSent = Date.now() sentPacket.resent++ - this.log('Resending', sentPacket.packetId) + this.log(`Resending ${sentPacket.packetId}`) if (this._debug) { - this.log('RESEND: ', sentPacket) + this.log(`RESEND: ${sentPacket}`) } - this._sendPacket(sentPacket.packet) + this._sendPacket(sentPacket.payload) retransmitFromPacketId = sentPacket.packetId } else { this.emit(IPCMessageType.CommandTimeout, sentPacket.packetId, sentPacket.trackingId) this._inFlight.splice(this._inFlight.indexOf(sentPacket), 1) - this.log('Timed out: ', sentPacket.packetId) + this.log(`Timed out: ${sentPacket.packetId}`) if (this._debug) { - this.log('TIMED OUT: ', sentPacket.packet) + this.log(`TIMED OUT: ${sentPacket}`) } // @todo: we should probably break up the connection here. } diff --git a/src/lib/atemUtil.ts b/src/lib/atemUtil.ts index db7b468d6..3424bb886 100644 --- a/src/lib/atemUtil.ts +++ b/src/lib/atemUtil.ts @@ -97,12 +97,6 @@ export namespace Util { 0x00, 0x00, 0x00, 0x00 ]) - export const COMMAND_CONNECT_HELLO_ANSWER = Buffer.from([ - 0x80, 0x0C, 0x53, 0xAB, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x03, 0x00, 0x00 - ]) - /** * @todo: BALTE - 2018-5-24: * Create util functions that handle proper colour spaces in UHD. diff --git a/src/socket-child.ts b/src/socket-child.ts index e963963f8..5834d4195 100644 --- a/src/socket-child.ts +++ b/src/socket-child.ts @@ -21,7 +21,7 @@ process.on('message', message => { singleton.disconnect().catch(() => { /* discard error */ }) break case IPCMessageType.OutboundCommand: - singleton._sendCommand(Buffer.from(payload.data.data), payload.trackingId) + singleton.sendCommand(Buffer.from(payload.data.data), payload.trackingId) break } }) diff --git a/tsconfig.build.json b/tsconfig.build.json index f748c9454..3cffa14c3 100644 --- a/tsconfig.build.json +++ b/tsconfig.build.json @@ -2,6 +2,7 @@ "extends": "./config/tsconfig.base", "exclude": [ "node_modules/**", - "src/**/__tests__/*" + "src/**/__tests__/*", + "src/**/__mocks__/*" ] } \ No newline at end of file diff --git a/yarn.lock b/yarn.lock index b8b6fa87b..703f1416e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -375,15 +375,20 @@ dependencies: jest-diff "^24.3.0" +"@types/lolex@^5.1.0": + version "5.1.0" + resolved "https://registry.yarnpkg.com/@types/lolex/-/lolex-5.1.0.tgz#11b4c4756c007306d0feeaf2f08f88350c635d2b" + integrity sha512-hCQ2dOEQUw1LwofdIpMMGGqENd5p5ANzvcTe1nXTjcQL84r7tcLXFJlBgi0Ggz0f7BLmE2epf0C5Q07iq2gV0g== + "@types/minimatch@3.0.3": version "3.0.3" resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-3.0.3.tgz#3dca0e3f33b200fc7d1139c0cd96c1268cadfd9d" integrity sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA== "@types/node@^12.7.12": - version "12.12.12" - resolved "https://registry.yarnpkg.com/@types/node/-/node-12.12.12.tgz#529bc3e73dbb35dd9e90b0a1c83606a9d3264bdb" - integrity sha512-MGuvYJrPU0HUwqF7LqvIj50RZUX23Z+m583KBygKYUZLlZ88n6w28XRNJRJgsHukLEnLz6w6SvxZoLgbr5wLqQ== + version "12.12.14" + resolved "https://registry.yarnpkg.com/@types/node/-/node-12.12.14.tgz#1c1d6e3c75dba466e0326948d56e8bd72a1903d2" + integrity sha512-u/SJDyXwuihpwjXy7hOOghagLEV1KdAST6syfnOk6QZAMzZuWZqXy5aYYZbh8Jdpd4escVFP0MvftHNDb9pruA== "@types/retry@^0.12.0": version "0.12.0" @@ -444,9 +449,9 @@ acorn@^5.5.3: integrity sha512-T/zvzYRfbVojPWahDsE5evJdHb3oJoQfFbsrKM7w5Zcs++Tr257tia3BmMP8XYVjp1S9RZXQMh7gao96BlqZOw== acorn@^6.0.1: - version "6.3.0" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.3.0.tgz#0087509119ffa4fc0a0041d1e93a417e68cb856e" - integrity sha512-/czfa8BwS88b9gWQVhc8eknunSA2DoJpJyTQkhheIf5E48u1N0R4q/YxxsAeqRrmK9TQ/uYfgLDfZo91UlANIA== + version "6.4.0" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.4.0.tgz#b659d2ffbafa24baf5db1cdbb2c94a983ecd2784" + integrity sha512-gac8OEcQ2Li1dxIEWGZzsp2BitJxwkwcOm0zHAJLcPJaVvm58FRnk6RkuLRpU1EujipU2ZFODv2P9DLMfnV8mw== agent-base@^4.3.0: version "4.3.0" @@ -538,6 +543,11 @@ are-we-there-yet@~1.1.2: delegates "^1.0.0" readable-stream "^2.0.6" +arg@^4.1.0: + version "4.1.2" + resolved "https://registry.yarnpkg.com/arg/-/arg-4.1.2.tgz#e70c90579e02c63d80e3ad4e31d8bfdb8bd50064" + integrity sha512-+ytCkGcBtHZ3V2r2Z06AncYO8jz46UEamcspGoU8lHcEbpn6J77QK0vdWvChsclg/tM5XIJC5tnjmPp7Eq6Obg== + argparse@^1.0.7: version "1.0.10" resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" @@ -657,9 +667,9 @@ aws-sign2@~0.7.0: integrity sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg= aws4@^1.8.0: - version "1.8.0" - resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.8.0.tgz#f0e003d9ca9e7f59c7a508945d7b2ef9a04a542f" - integrity sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ== + version "1.9.0" + resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.9.0.tgz#24390e6ad61386b0a747265754d2a17219de862c" + integrity sha512-Uvq6hVe90D0B2WEnUqtdgY1bATGz3mw33nH9Y+dmA+w5DHvUmBgkr5rM/KCHpCsiFNRUfokW/szpPPgMK2hm4A== babel-jest@^24.9.0: version "24.9.0" @@ -1584,22 +1594,22 @@ error-ex@^1.2.0, error-ex@^1.3.1: is-arrayish "^0.2.1" es-abstract@^1.5.1: - version "1.16.0" - resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.16.0.tgz#d3a26dc9c3283ac9750dca569586e976d9dcc06d" - integrity sha512-xdQnfykZ9JMEiasTAJZJdMWCQ1Vm00NBw79/AWi7ELfZuuPCSOMDZbT9mkOfSctVtfhb+sAAzrm+j//GjjLHLg== + version "1.16.2" + resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.16.2.tgz#4e874331645e9925edef141e74fc4bd144669d34" + integrity sha512-jYo/J8XU2emLXl3OLwfwtuFfuF2w6DYPs+xy9ZfVyPkDcrauu6LYrw/q2TyCtrbc/KUdCiC5e9UajRhgNkVopA== dependencies: - es-to-primitive "^1.2.0" + es-to-primitive "^1.2.1" function-bind "^1.1.1" has "^1.0.3" - has-symbols "^1.0.0" + has-symbols "^1.0.1" is-callable "^1.1.4" is-regex "^1.0.4" - object-inspect "^1.6.0" + object-inspect "^1.7.0" object-keys "^1.1.1" string.prototype.trimleft "^2.1.0" string.prototype.trimright "^2.1.0" -es-to-primitive@^1.2.0: +es-to-primitive@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.2.1.tgz#e55cd4c9cdc188bcefb03b366c736323fc5c898a" integrity sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA== @@ -1727,7 +1737,7 @@ expand-brackets@^2.1.4: snapdragon "^0.8.1" to-regex "^3.0.1" -expect@^24.9.0: +expect@^24.1.0, expect@^24.9.0: version "24.9.0" resolved "https://registry.yarnpkg.com/expect/-/expect-24.9.0.tgz#b75165b4817074fa4a157794f46fe9f1ba15b6ca" integrity sha512-wvVAx8XIol3Z5m9zvZXiyZOQ+sRJqNTIm6sGjdWlaZIeupQGO3WbYI+15D/AmEwZywL6wtJkbAbJtzkOfBuR0Q== @@ -2198,7 +2208,7 @@ has-flag@^3.0.0: resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0= -has-symbols@^1.0.0, has-symbols@^1.0.1: +has-symbols@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.1.tgz#9f5214758a44196c406d9bd76cebf81ec2dd31e8" integrity sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg== @@ -2790,6 +2800,20 @@ jest-environment-node@^24.9.0: jest-mock "^24.9.0" jest-util "^24.9.0" +jest-extended@^0.11.2: + version "0.11.2" + resolved "https://registry.yarnpkg.com/jest-extended/-/jest-extended-0.11.2.tgz#924f4a6b4c946133faf9ec8fba865de9790f4116" + integrity sha512-gwNMXrAPN0IY5L7VXWfSlC2aGo0KHIsGGcW+lTHYpedt5SJksEvBgMxs29iNikiNOz+cqAZY1s/+kYK0jlj4Jw== + dependencies: + expect "^24.1.0" + jest-get-type "^22.4.3" + jest-matcher-utils "^22.0.0" + +jest-get-type@^22.4.3: + version "22.4.3" + resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-22.4.3.tgz#e3a8504d8479342dd4420236b322869f18900ce4" + integrity sha512-/jsz0Y+V29w1chdXVygEKSz2nBoHoYqNShPe+QgxSNjAuP1i8+k4LbQNrfoliKej0P45sivkSCh7yiD6ubHS3w== + jest-get-type@^24.9.0: version "24.9.0" resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-24.9.0.tgz#1684a0c8a50f2e4901b6644ae861f579eed2ef0e" @@ -2844,6 +2868,15 @@ jest-leak-detector@^24.9.0: jest-get-type "^24.9.0" pretty-format "^24.9.0" +jest-matcher-utils@^22.0.0: + version "22.4.3" + resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-22.4.3.tgz#4632fe428ebc73ebc194d3c7b65d37b161f710ff" + integrity sha512-lsEHVaTnKzdAPR5t4B6OcxXo9Vy4K+kRRbG5gtddY8lBEC+Mlpvm1CJcsMESRjzUhzkz568exMV1hTB76nAKbA== + dependencies: + chalk "^2.0.1" + jest-get-type "^22.4.3" + pretty-format "^22.4.3" + jest-matcher-utils@^24.9.0: version "24.9.0" resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-24.9.0.tgz#f5b3661d5e628dffe6dd65251dfdae0e87c3a073" @@ -3308,6 +3341,11 @@ lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.15: resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548" integrity sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A== +lolex@^5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/lolex/-/lolex-5.1.1.tgz#9587144854511d27940ee5e113dcb7de9b0fd666" + integrity sha512-dEwHz1CJ8DsdgfpiimgQQEhEJYOEiJ69a0s4aJDNHajaTqOJuF34vBAWVa/sS0V8aQvt72p+KgQ3pRmEVJM+iA== + loose-envify@^1.0.0: version "1.4.0" resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf" @@ -3368,7 +3406,7 @@ make-dir@^3.0.0: dependencies: semver "^6.0.0" -make-error@1.x: +make-error@1.x, make-error@^1.1.1: version "1.3.5" resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.5.tgz#efe4e81f6db28cadd605c70f29c831b58ef776c8" integrity sha512-c3sIjNUow0+8swNwVpqoH4YCShKNFkMaw6oH1mNS2haDZQqkeZFlHS3dhoeEbKKmJB4vXpJucU6oH75aDYeE9g== @@ -3841,7 +3879,7 @@ object-copy@^0.1.0: define-property "^0.2.5" kind-of "^3.0.3" -object-inspect@^1.6.0: +object-inspect@^1.7.0: version "1.7.0" resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.7.0.tgz#f4f6bd181ad77f006b5ece60bd0b6f398ff74a67" integrity sha512-a7pEHdh1xKIAgTySUGgLMx/xwDZskN1Ud6egYYN3EdRW4ZMPNEDUTF+hwy2LUC+Bl+SyLXANnwz/jyh/qutKUw== @@ -4194,6 +4232,14 @@ prepend-http@^2.0.0: resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-2.0.0.tgz#e92434bfa5ea8c19f41cdfd401d741a3c819d897" integrity sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc= +pretty-format@^22.4.3: + version "22.4.3" + resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-22.4.3.tgz#f873d780839a9c02e9664c8a082e9ee79eaac16f" + integrity sha512-S4oT9/sT6MN7/3COoOy+ZJeA92VmOnveLHgrwBE3Z1W5N9S2A1QGNYiE1z75DAENbJrXXUb+OWXhpJcg05QKQQ== + dependencies: + ansi-regex "^3.0.0" + ansi-styles "^3.2.0" + pretty-format@^24.9.0: version "24.9.0" resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-24.9.0.tgz#12fac31b37019a4eea3c11aa9a959eb7628aa7c9" @@ -4228,9 +4274,9 @@ pseudomap@^1.0.2: integrity sha1-8FKijacOYYkX7wqKw0wa5aaChrM= psl@^1.1.24, psl@^1.1.28: - version "1.4.0" - resolved "https://registry.yarnpkg.com/psl/-/psl-1.4.0.tgz#5dd26156cdb69fa1fdb8ab1991667d3f80ced7c2" - integrity sha512-HZzqCGPecFLyoRj5HLfuDSKYTJkAfB5thKBIkRHtGjWwY7p1dAyveIbXIq4tO0KYfDF2tHqPUgY9SDnGm00uFw== + version "1.5.0" + resolved "https://registry.yarnpkg.com/psl/-/psl-1.5.0.tgz#47fd1292def7fdb1e138cd78afa8814cebcf7b13" + integrity sha512-4vqUjKi2huMu1OJiLhi3jN6jeeKvMZdI1tYgi/njW5zV52jNLgSAZSdN16m9bJFe61/cT8ulmw4qFitV9QRsEA== pump@^3.0.0: version "3.0.0" @@ -4538,9 +4584,9 @@ resolve@1.1.7: integrity sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs= resolve@1.x, resolve@^1.1.6, resolve@^1.10.0, resolve@^1.3.2: - version "1.12.2" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.12.2.tgz#08b12496d9aa8659c75f534a8f05f0d892fff594" - integrity sha512-cAVTI2VLHWYsGOirfeYVVQ7ZDejtQ9fp4YhYckWDEkFfqbVjaT11iM8k6xSAfGFMM+gDpZjMnFssPu8we+mqFw== + version "1.13.1" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.13.1.tgz#be0aa4c06acd53083505abb35f4d66932ab35d16" + integrity sha512-CxqObCX8K8YtAhOBRg+lrcdn+LK+WYOS8tSjqSFbjtrI5PnS63QPhZl4+yKfrU9tdsbMu9Anr/amegT87M9Z6w== dependencies: path-parse "^1.0.6" @@ -5287,6 +5333,17 @@ ts-jest@^24.0.2: semver "^5.5" yargs-parser "10.x" +ts-node@^8.5.4: + version "8.5.4" + resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-8.5.4.tgz#a152add11fa19c221d0b48962c210cf467262ab2" + integrity sha512-izbVCRV68EasEPQ8MSIGBNK9dc/4sYJJKYA+IarMQct1RtEot6Xp0bXuClsbUSnKpg50ho+aOAx8en5c+y4OFw== + dependencies: + arg "^4.1.0" + diff "^4.0.1" + make-error "^1.1.1" + source-map-support "^0.5.6" + yn "^3.0.0" + tslib@1.9.0: version "1.9.0" resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.9.0.tgz#e37a86fda8cbbaf23a057f473c9f4dc64e5fc2e8" @@ -5427,9 +5484,9 @@ typescript@~3.6.4: integrity sha512-unoCll1+l+YK4i4F8f22TaNVPRHcD9PA3yCuZ8g5e0qGqlVlJ/8FSateOLLSagn+Yg5+ZwuPkL8LFUc0Jcvksg== uglify-js@^3.1.4: - version "3.6.9" - resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.6.9.tgz#85d353edb6ddfb62a9d798f36e91792249320611" - integrity sha512-pcnnhaoG6RtrvHJ1dFncAe8Od6Nuy30oaJ82ts6//sGSXOP5UjBMEthiProjXmMNHOfd93sqlkztifFMcb+4yw== + version "3.7.1" + resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.7.1.tgz#35c7de17971a4aa7689cd2eae0a5b39bb838c0c5" + integrity sha512-pnOF7jY82wdIhATVn87uUY/FHU+MDUdPLkmGFvGoclQmeu229eTkbG5gjGGBi3R7UuYYSEeYXY/TTY5j2aym2g== dependencies: commander "~2.20.3" source-map "~0.6.1" @@ -5854,3 +5911,8 @@ yargs@~1.2.6: integrity sha1-nHtKgv1dWVsr8Xq23MQxNUMv40s= dependencies: minimist "^0.1.0" + +yn@^3.0.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/yn/-/yn-3.1.1.tgz#1e87401a09d767c1d5eab26a6e4c185182d2eb50" + integrity sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q== From b261ee2dbd563e1b8e88b89c499a3f547508b989 Mon Sep 17 00:00:00 2001 From: Julian Waller Date: Sun, 1 Dec 2019 13:23:36 +0000 Subject: [PATCH 11/68] fix: incorrectly handling acks for sent packets around the wrap point --- src/lib/__tests__/socket-child.spec.ts | 179 +++++++++++++++++++++++++ src/lib/atemSocketChild.ts | 47 ++++--- 2 files changed, 205 insertions(+), 21 deletions(-) diff --git a/src/lib/__tests__/socket-child.spec.ts b/src/lib/__tests__/socket-child.spec.ts index db2c1fa07..e1e5a79bb 100644 --- a/src/lib/__tests__/socket-child.spec.ts +++ b/src/lib/__tests__/socket-child.spec.ts @@ -19,6 +19,9 @@ function getSocket (child: AtemSocketChild) { function getState (child: AtemSocketChild) { return (child as any)._connectionState as ConnectionState } +function getInflightIds (child: AtemSocketChild) { + return (child as any)._inFlight.map((p: any) => p.packetId) +} function fakeConnect (child: AtemSocketChild) { const child2 = child as any child2._connectionState = ConnectionState.Established @@ -331,4 +334,180 @@ describe('SocketChild', () => { } }) + test('SendCommand', async () => { + const child = new AtemSocketChild() + try { + fakeConnect(child) + const socket = getSocket(child) + + ;(child as any)._nextSendPacketId = 123 + + let received: Array<{id: number, payload: Buffer}> = [] + socket.sendImpl = (msg: Buffer) => { + const opcode = msg.readUInt8(0) >> 3 + expect(opcode).toEqual(PacketFlag.AckRequest) + + received.push({ + id: msg.readUInt16BE(10), + payload: msg.slice(12) + }) + } + + // Send something + const buf1 = Buffer.from([0, 1, 2]) + child.sendCommand(buf1, 1) + expect(received).toEqual([{ + id: 123, + payload: buf1 + }]) + received = [] + expect(getInflightIds(child)).toEqual([123]) + + // Send another + child.sendCommand(buf1, 1) + expect(received).toEqual([{ + id: 124, + payload: buf1 + }]) + received = [] + expect(getInflightIds(child)).toEqual([123, 124 ]) + + } finally { + if (child) { + // Try and cleanup any timers + await child.disconnect() + } + } + }) + + function genAckCommandMessage (pktId: number) { + const buffer = Buffer.from([ + 0x80, 0x0c, // Length & Type + 0x53, 0x1b, // Session Id + 0x00, 0x00, // Acking - set after + 0x00, 0x00, // Not asking for retransmit + 0x00, 0x00, // 'Client pkt id' Not needed + 0x00, 0x00 // No Packet Id + ]) + buffer.writeUInt16BE(pktId, 4) // Acked Id + + return buffer + } + + test('SendCommand - acks', async () => { + const child = new AtemSocketChild() + try { + fakeConnect(child) + const socket = getSocket(child) + + ;(child as any)._nextSendPacketId = 123 + + let received: number[] = [] + socket.sendImpl = (msg: Buffer) => { + const opcode = msg.readUInt8(0) >> 3 + expect(opcode).toEqual(PacketFlag.AckRequest) + + received.push(msg.readUInt16BE(10)) + } + + let acked: Array<{packetId: number, trackingId: number}> = [] + child.on(IPCMessageType.CommandAcknowledged, (packetId, trackingId) => acked.push({ packetId, trackingId })) + + // Send some stuff + const buf1 = Buffer.from([0, 1, 2]) + child.sendCommand(buf1, 5) + child.sendCommand(buf1, 6) + child.sendCommand(buf1, 7) + child.sendCommand(buf1, 8) + child.sendCommand(buf1, 9) + child.sendCommand(buf1, 10) + expect(received).toEqual([123, 124, 125, 126, 127, 128]) + received = [] + expect(getInflightIds(child)).toEqual([123, 124, 125, 126, 127, 128]) + expect(acked).toEqual([]) + + // Ack a couple + socket.emitMessage(genAckCommandMessage(125)) + expect(getInflightIds(child)).toEqual([126, 127, 128]) + expect(acked).toEqual([ + { packetId: 123, trackingId: 5 }, + { packetId: 124, trackingId: 6 }, + { packetId: 125, trackingId: 7 } + ]) + acked = [] + + // Another ack + socket.emitMessage(genAckCommandMessage(126)) + expect(getInflightIds(child)).toEqual([127, 128]) + expect(acked).toEqual([ + { packetId: 126, trackingId: 8 } + ]) + + } finally { + if (child) { + // Try and cleanup any timers + await child.disconnect() + } + } + }) + + test('SendCommand - acks wrap', async () => { + const child = new AtemSocketChild() + try { + fakeConnect(child) + const socket = getSocket(child) + + ;(child as any)._nextSendPacketId = 32764 // 32767 is max + + let received: number[] = [] + socket.sendImpl = (msg: Buffer) => { + const opcode = msg.readUInt8(0) >> 3 + expect(opcode).toEqual(PacketFlag.AckRequest) + + received.push(msg.readUInt16BE(10)) + } + + let acked: Array<{packetId: number, trackingId: number}> = [] + child.on(IPCMessageType.CommandAcknowledged, (packetId, trackingId) => acked.push({ packetId, trackingId })) + + // Send some stuff + const buf1 = Buffer.from([0, 1, 2]) + child.sendCommand(buf1, 5) // 32764 + child.sendCommand(buf1, 6) // 32765 + child.sendCommand(buf1, 7) // 32766 + child.sendCommand(buf1, 8) // 32767 + child.sendCommand(buf1, 9) // 0 + child.sendCommand(buf1, 10)// 1 + expect(received).toEqual([32764, 32765, 32766, 32767, 0, 1]) + received = [] + expect(getInflightIds(child)).toEqual([32764, 32765, 32766, 32767, 0, 1]) + expect(acked).toEqual([]) + + // TODO - and the remainder of this is very very broken.. + // Ack a couple + socket.emitMessage(genAckCommandMessage(32766)) + expect(getInflightIds(child)).toEqual([32767, 0, 1]) + expect(acked).toEqual([ + { packetId: 32764, trackingId: 5 }, + { packetId: 32765, trackingId: 6 }, + { packetId: 32766, trackingId: 7 } + ]) + acked = [] + + // Another ack + socket.emitMessage(genAckCommandMessage(0)) + expect(getInflightIds(child)).toEqual([1]) + expect(acked).toEqual([ + { packetId: 32767, trackingId: 8 }, + { packetId: 0, trackingId: 9 } + ]) + + } finally { + if (child) { + // Try and cleanup any timers + await child.disconnect() + } + } + }) + }) diff --git a/src/lib/atemSocketChild.ts b/src/lib/atemSocketChild.ts index 7f2c049ba..e3a4c8c2e 100644 --- a/src/lib/atemSocketChild.ts +++ b/src/lib/atemSocketChild.ts @@ -7,7 +7,7 @@ import * as NanoTimer from 'nanotimer' const IN_FLIGHT_TIMEOUT = 30 // ms const RECONNECT_INTERVAL = 5000 // ms const MAX_PACKET_RETRIES = 5 -const MAX_PACKET_ID = (1 << 15) - 1 // Atem expects 15 not 16 bits before wrapping +const MAX_PACKET_ID = (1 << 15) // Atem expects 15 not 16 bits before wrapping const MAX_PACKET_PER_ACK = 16 interface InFlightPacket { @@ -34,11 +34,10 @@ export class AtemSocketChild extends EventEmitter { private _lastReceivedAt: number = Date.now() private _lastReceivedPacketId: number = 0 - private readonly _inFlight: InFlightPacket[] = [] + private _inFlight: InFlightPacket[] = [] private readonly _ackTimer = new NanoTimer() private _ackTimerRunning = false private _receivedWithoutAck: number = 0 - private _lastAcked = 0 public on!: ((event: IPCMessageType.Disconnect, listener: () => void) => this) & ((event: IPCMessageType.Log, listener: (payload: string) => void) => this) & @@ -122,7 +121,7 @@ export class AtemSocketChild extends EventEmitter { public sendCommand (payload: Buffer, trackingId: number): void { const packetId = this._nextSendPacketId++ - if (this._nextSendPacketId > MAX_PACKET_ID) this._nextSendPacketId = 0 + if (this._nextSendPacketId >= MAX_PACKET_ID) this._nextSendPacketId = 0 const opcode = PacketFlag.AckRequest << 11 @@ -152,6 +151,14 @@ export class AtemSocketChild extends EventEmitter { return this._socket } + private _isPacketCoveredByAck (ackId: number, packetId: number) { + const tolerance = MAX_PACKET_ID / 2 + const pktIsShortlyBefore = packetId < ackId && packetId + tolerance > ackId + const pktIsShortlyAfter = packetId > ackId && packetId < ackId + tolerance + const pktIsBeforeWrap = packetId > ackId + tolerance + return packetId === ackId || ((pktIsShortlyBefore || pktIsBeforeWrap) && !pktIsShortlyAfter) + } + private _receivePacket (packet: Buffer, rinfo: RemoteInfo) { if (this._debug) this.log(`RECV ${packet}`) this._lastReceivedAt = Date.now() @@ -165,8 +172,8 @@ export class AtemSocketChild extends EventEmitter { // Send hello answer packet when receive connect flags if (flags & PacketFlag.Connect) { this._connectionState = ConnectionState.Established - this._sendAck(remotePacketId) this._lastReceivedPacketId = remotePacketId + this._sendAck(remotePacketId) return } @@ -182,28 +189,32 @@ export class AtemSocketChild extends EventEmitter { // Got a packet that needs an ack if (flags & PacketFlag.AckRequest) { // Check if it next in the sequence - if (remotePacketId === (this._lastReceivedPacketId + 1) % (MAX_PACKET_ID + 1)) { // TODO - tidy this - this._sendOrQueueAck(remotePacketId) + if (remotePacketId === (this._lastReceivedPacketId + 1) % MAX_PACKET_ID) { this._lastReceivedPacketId = remotePacketId + this._sendOrQueueAck() // It might have commands if (length > 12) { this.emit(IPCMessageType.InboundCommand, packet.slice(12), remotePacketId) } + } else if (this._isPacketCoveredByAck(this._lastReceivedPacketId, remotePacketId)) { + // We got a retransmit of something we have already acked, so reack it + this._sendOrQueueAck() } } // Device ack'ed our packet if (flags & PacketFlag.AckReply) { const ackPacketId = packet.readUInt16BE(4) - this._lastAcked = ackPacketId - for (const i in this._inFlight) { - // TODO - this doesnt wrap well... - if (ackPacketId >= this._inFlight[i].packetId || this._nextSendPacketId < this._inFlight[i].packetId) { - this.emit(IPCMessageType.CommandAcknowledged, this._inFlight[i].packetId, this._inFlight[i].trackingId) - this._inFlight.splice(Number(i), 1) + this._inFlight = this._inFlight.filter(pkt => { + if (this._isPacketCoveredByAck(ackPacketId, pkt.packetId)) { + this.emit(IPCMessageType.CommandAcknowledged, pkt.packetId, pkt.trackingId) + return false + } else { + // Not acked yet + return true } - } + }) } } } @@ -213,8 +224,7 @@ export class AtemSocketChild extends EventEmitter { this._socket.send(packet, 0, packet.length, this._port, this._address) } - private _sendOrQueueAck (packetId: number) { - this._lastReceivedPacketId = packetId + private _sendOrQueueAck () { this._receivedWithoutAck++ if (this._receivedWithoutAck >= MAX_PACKET_PER_ACK) { this._receivedWithoutAck = 0 @@ -245,11 +255,6 @@ export class AtemSocketChild extends EventEmitter { private _checkForRetransmit () { let retransmitFromPacketId: number | undefined for (const sentPacket of this._inFlight) { - if (sentPacket.packetId <= this._lastAcked || sentPacket.packetId > this._nextSendPacketId) { - this.emit(IPCMessageType.CommandAcknowledged, sentPacket.packetId, sentPacket.trackingId) - this._inFlight.splice(this._inFlight.indexOf(sentPacket), 1) - continue - } if (retransmitFromPacketId && sentPacket.packetId > retransmitFromPacketId) { sentPacket.lastSent = Date.now() sentPacket.resent++ From 14dda0b9509d55a209193f4a3f54367d0b7c29a4 Mon Sep 17 00:00:00 2001 From: Julian Waller Date: Sun, 1 Dec 2019 17:37:57 +0000 Subject: [PATCH 12/68] feat: unlock media pool as part of transfer. this avoids race conditions when doing multiple uploads --- src/dataTransfer/dataLock.ts | 22 +++++++++------------- src/dataTransfer/index.ts | 13 ++++++++++--- 2 files changed, 19 insertions(+), 16 deletions(-) diff --git a/src/dataTransfer/dataLock.ts b/src/dataTransfer/dataLock.ts index 21f67f101..0730a4a05 100644 --- a/src/dataTransfer/dataLock.ts +++ b/src/dataTransfer/dataLock.ts @@ -48,10 +48,15 @@ export default class DataLock { lostLock () { this.isLocked = false - if (this.activeTransfer && this.activeTransfer.state !== Enums.TransferState.Finished) { - // @todo: dequeue any old commands - this.activeTransfer.rejectPromise(new Error('Lost lock mid-transfer')) + if (this.activeTransfer) { + if (this.activeTransfer.state === Enums.TransferState.Finished) { + this.activeTransfer.resolvePromise(this.activeTransfer) + } else { + // @todo: dequeue any old commands + this.activeTransfer.rejectPromise(new Error('Lost lock mid-transfer')) + } } + this.activeTransfer = undefined this.dequeueAndRun() } @@ -61,16 +66,7 @@ export default class DataLock { } transferFinished () { - if (this.activeTransfer && this.activeTransfer.state === Enums.TransferState.Finished) { - this.activeTransfer.resolvePromise(this.activeTransfer) - this.activeTransfer = undefined - } - - if (this.taskQueue.length > 0) { - this.dequeueAndRun() - } else { // unlock - this.queueCommand(new Commands.LockStateCommand(this.storeId, false)) - } + this.queueCommand(new Commands.LockStateCommand(this.storeId, false)) } transferErrored (code: number) { diff --git a/src/dataTransfer/index.ts b/src/dataTransfer/index.ts index 6fbd3bba4..224d36ad3 100644 --- a/src/dataTransfer/index.ts +++ b/src/dataTransfer/index.ts @@ -12,7 +12,10 @@ const MAX_PACKETS_TO_SEND_PER_TICK = 10 export class DataTransferManager { private readonly commandQueue: Array = [] - private readonly stillsLock = new DataLock(0, cmd => this.commandQueue.push(cmd)) + private readonly stillsLock = new DataLock(0, cmd => { + // console.log('SEND', cmd.constructor.name) + this.commandQueue.push(cmd) + }) private readonly clipLocks = [ new DataLock(1, cmd => this.commandQueue.push(cmd)), new DataLock(2, cmd => this.commandQueue.push(cmd)) @@ -75,8 +78,12 @@ export class DataTransferManager { lock.lockObtained() } if (command.constructor.name === Commands.LockStateUpdateCommand.name) { - if (!command.properties.locked) lock.lostLock() - else lock.updateLock(command.properties.locked) + const transferFinished = lock.activeTransfer && lock.activeTransfer.state === Enums.TransferState.Finished + if (!command.properties.locked || transferFinished) { + lock.lostLock() + } else { + lock.updateLock(command.properties.locked) + } } if (command.constructor.name === Commands.DataTransferErrorCommand.name) { lock.transferErrored(command.properties.errorCode) From b26293a337a94746af454831f4c8e3cc47f2e6ec Mon Sep 17 00:00:00 2001 From: Julian Waller Date: Sun, 1 Dec 2019 17:44:05 +0000 Subject: [PATCH 13/68] fix: tslint member-access rule --- src/atem.ts | 132 +++++++++--------- src/commands/Audio/AudioMixerInputCommand.ts | 16 +-- src/commands/Audio/AudioMixerMasterCommand.ts | 12 +- src/commands/AuxSourceCommand.ts | 14 +- src/commands/CommandBase.ts | 16 +-- .../DataTransfer/DataTransferAckCommand.ts | 6 +- .../DataTransferCompleteCommand.ts | 6 +- .../DataTransfer/DataTransferDataCommand.ts | 8 +- .../DataTransferDownloadRequestCommand.ts | 4 +- .../DataTransfer/DataTransferErrorCommand.ts | 6 +- .../DataTransferFileDescriptionCommand.ts | 4 +- .../DataTransferUploadContinueCommand.ts | 6 +- .../DataTransferUploadRequestCommand.ts | 4 +- .../DataTransfer/LockObtainedCommand.ts | 6 +- src/commands/DataTransfer/LockStateCommand.ts | 10 +- .../DeviceProfile/productIdentifierCommand.ts | 6 +- .../DeviceProfile/superSourceConfigCommand.ts | 8 +- src/commands/DeviceProfile/topologyCommand.ts | 6 +- src/commands/DeviceProfile/versionCommand.ts | 6 +- .../DownstreamKey/DownstreamKeyAutoCommand.ts | 8 +- .../DownstreamKeyCutSourceCommand.ts | 6 +- .../DownstreamKeyFillSourceCommand.ts | 6 +- .../DownstreamKeyGeneralCommand.ts | 8 +- .../DownstreamKey/DownstreamKeyMaskCommand.ts | 8 +- .../DownstreamKeyOnAirCommand.ts | 6 +- .../DownstreamKeyPropertiesCommand.ts | 8 +- .../DownstreamKey/DownstreamKeyRateCommand.ts | 6 +- .../DownstreamKeySourcesCommand.ts | 8 +- .../DownstreamKeyStateCommand.ts | 18 +-- .../DownstreamKey/DownstreamKeyTieCommand.ts | 6 +- src/commands/InitCompleteCommand.ts | 6 +- src/commands/Inputs/InputPropertiesCommand.ts | 16 +-- src/commands/Macro/MacroActionCommand.ts | 6 +- src/commands/Macro/MacroPropertiesCommand.ts | 8 +- .../Macro/MacroRecordingStatusCommand.ts | 6 +- src/commands/Macro/MacroRunStatusCommand.ts | 6 +- .../Media/MediaPlayerSourceCommand.ts | 16 +-- .../Media/MediaPlayerStatusCommand.ts | 16 +-- .../Media/MediaPoolClearClipCommand.ts | 4 +- .../Media/MediaPoolClearStillCommand.ts | 4 +- .../Media/MediaPoolClipDescription.ts | 8 +- .../Media/MediaPoolFrameDescription.ts | 10 +- src/commands/Media/MediaPoolSetClipCommand.ts | 4 +- .../MixEffects/AutoTransitionCommand.ts | 6 +- src/commands/MixEffects/CutCommand.ts | 6 +- .../FadeToBlack/FadeToBlackAutoCommand.ts | 6 +- .../FadeToBlack/FadeToBlackRateCommand.ts | 14 +- .../FadeToBlack/FadeToBlackStateCommand.ts | 8 +- .../Key/MixEffectKeyChromaCommand.ts | 20 +-- .../Key/MixEffectKeyCutSourceSetCommand.ts | 8 +- .../MixEffects/Key/MixEffectKeyDVECommand.ts | 20 +-- .../Key/MixEffectKeyFillSourceSetCommand.ts | 8 +- .../Key/MixEffectKeyFlyKeyframeGetCommand.ts | 12 +- .../MixEffectKeyFlyPropertiesGetCommand.ts | 10 +- .../MixEffects/Key/MixEffectKeyLumaCommand.ts | 20 +-- .../Key/MixEffectKeyMaskSetCommand.ts | 10 +- .../Key/MixEffectKeyOnAirCommand.ts | 18 +-- .../Key/MixEffectKeyPatternCommand.ts | 20 +-- .../Key/MixEffectKeyPropertiesGetCommand.ts | 8 +- .../Key/MixEffectKeyTypeSetCommand.ts | 10 +- .../MixEffects/PreviewInputCommand.ts | 14 +- .../MixEffects/ProgramInputCommand.ts | 14 +- .../Transition/TransitionDVECommand.ts | 16 +-- .../Transition/TransitionDipCommand.ts | 16 +-- .../Transition/TransitionMixCommand.ts | 14 +- .../Transition/TransitionPositionCommand.ts | 14 +- .../Transition/TransitionPreviewCommand.ts | 14 +- .../Transition/TransitionPropertiesCommand.ts | 16 +-- .../Transition/TransitionStingerCommand.ts | 16 +-- .../Transition/TransitionWipeCommand.ts | 16 +-- src/commands/PowerStatusCommand.ts | 6 +- .../Settings/MultiViewerSourceCommand.ts | 14 +- src/commands/Settings/VideoMode.ts | 10 +- .../SuperSourceBoxParametersCommand.ts | 20 +-- .../SuperSourcePropertiesCommand.ts | 52 +++---- src/commands/TallyBySourceCommand.ts | 6 +- src/dataTransfer/dataLock.ts | 12 +- src/dataTransfer/dataTransfer.ts | 16 +-- src/dataTransfer/dataTransferAudio.ts | 2 +- src/dataTransfer/dataTransferClip.ts | 8 +- src/dataTransfer/dataTransferFrame.ts | 10 +- src/lib/atemCommandParser.ts | 6 +- src/state/audio.ts | 10 +- src/state/index.ts | 14 +- src/state/info.ts | 12 +- src/state/macro.ts | 6 +- src/state/media.ts | 10 +- src/state/settings.ts | 10 +- src/state/video/index.ts | 48 +++---- src/state/video/upstreamKeyers.ts | 2 +- tslint.json | 3 +- 91 files changed, 553 insertions(+), 552 deletions(-) diff --git a/src/atem.ts b/src/atem.ts index 22a9e6bda..50e5073e0 100644 --- a/src/atem.ts +++ b/src/atem.ts @@ -41,11 +41,11 @@ interface SentCommand { } export class Atem extends EventEmitter { - DEFAULT_PORT = 9910 - RECONNECT_INTERVAL = 5000 - DEBUG = false + public DEFAULT_PORT = 9910 + public RECONNECT_INTERVAL = 5000 + public DEBUG = false - AUDIO_GAIN_RATE = 65381 + public AUDIO_GAIN_RATE = 65381 private _state: AtemState private socket: AtemSocket @@ -53,7 +53,7 @@ export class Atem extends EventEmitter { private _log: (...args: any[]) => void private _sentQueue: {[packetId: string]: SentCommand } = {} - on!: ((event: 'error', listener: (message: any) => void) => this) & + public on!: ((event: 'error', listener: (message: any) => void) => this) & ((event: 'connected', listener: () => void) => this) & ((event: 'disconnected', listener: () => void) => this) & ((event: 'stateChanged', listener: (state: AtemState, path: string) => void) => this) & @@ -103,17 +103,17 @@ export class Atem extends EventEmitter { return this._state } - connect (address: string, port?: number) { + public connect (address: string, port?: number) { return this.socket.connect(address, port) } - disconnect (): Promise { + public disconnect (): Promise { return new Promise((resolve, reject) => { this.socket.disconnect().then(() => resolve()).catch(reject) }) } - sendCommand (command: ISerializableCommand): Promise { + public sendCommand (command: ISerializableCommand): Promise { const commandTrackingId = this.socket.nextCommandTrackingId return new Promise((resolve, reject) => { this._sentQueue[commandTrackingId] = { @@ -125,199 +125,199 @@ export class Atem extends EventEmitter { }) } - changeProgramInput (input: number, me: number = 0) { + public changeProgramInput (input: number, me: number = 0) { const command = new Commands.ProgramInputCommand(me, input) return this.sendCommand(command) } - changePreviewInput (input: number, me: number = 0) { + public changePreviewInput (input: number, me: number = 0) { const command = new Commands.PreviewInputCommand(me, input) return this.sendCommand(command) } - cut (me: number = 0) { + public cut (me: number = 0) { const command = new Commands.CutCommand(me) return this.sendCommand(command) } - autoTransition (me: number = 0) { + public autoTransition (me: number = 0) { const command = new Commands.AutoTransitionCommand(me) return this.sendCommand(command) } - fadeToBlack (me: number = 0) { + public fadeToBlack (me: number = 0) { const command = new Commands.FadeToBlackAutoCommand(me) return this.sendCommand(command) } - setFadeToBlackRate (rate: number, me: number = 0) { + public setFadeToBlackRate (rate: number, me: number = 0) { const command = new Commands.FadeToBlackRateCommand(me, rate) return this.sendCommand(command) } - autoDownstreamKey (key: number = 0, isTowardsOnAir?: boolean) { + public autoDownstreamKey (key: number = 0, isTowardsOnAir?: boolean) { const command = new Commands.DownstreamKeyAutoCommand(key) command.updateProps({ isTowardsOnAir }) return this.sendCommand(command) } - setDipTransitionSettings (newProps: Partial, me: number = 0) { + public setDipTransitionSettings (newProps: Partial, me: number = 0) { const command = new Commands.TransitionDipCommand(me) command.updateProps(newProps) return this.sendCommand(command) } - setDVETransitionSettings (newProps: Partial, me: number = 0) { + public setDVETransitionSettings (newProps: Partial, me: number = 0) { const command = new Commands.TransitionDVECommand(me) command.updateProps(newProps) return this.sendCommand(command) } - setMixTransitionSettings (newProps: Pick, me: number = 0) { + public setMixTransitionSettings (newProps: Pick, me: number = 0) { const command = new Commands.TransitionMixCommand(me, newProps.rate) return this.sendCommand(command) } - setTransitionPosition (position: number, me: number = 0) { + public setTransitionPosition (position: number, me: number = 0) { const command = new Commands.TransitionPositionCommand(me, position) return this.sendCommand(command) } - previewTransition (on: boolean, me: number = 0) { + public previewTransition (on: boolean, me: number = 0) { const command = new Commands.PreviewTransitionCommand(me, on) return this.sendCommand(command) } - setTransitionStyle (newProps: Partial, me: number = 0) { + public setTransitionStyle (newProps: Partial, me: number = 0) { const command = new Commands.TransitionPropertiesCommand(me) command.updateProps(newProps) return this.sendCommand(command) } - setStingerTransitionSettings (newProps: Partial, me: number = 0) { + public setStingerTransitionSettings (newProps: Partial, me: number = 0) { const command = new Commands.TransitionStingerCommand(me) command.updateProps(newProps) return this.sendCommand(command) } - setWipeTransitionSettings (newProps: Partial, me: number = 0) { + public setWipeTransitionSettings (newProps: Partial, me: number = 0) { const command = new Commands.TransitionWipeCommand(me) command.updateProps(newProps) return this.sendCommand(command) } - setAuxSource (source: number, bus: number = 0) { + public setAuxSource (source: number, bus: number = 0) { const command = new Commands.AuxSourceCommand(bus, source) return this.sendCommand(command) } - setDownstreamKeyTie (tie: boolean, key: number = 0) { + public setDownstreamKeyTie (tie: boolean, key: number = 0) { const command = new Commands.DownstreamKeyTieCommand(key, tie) return this.sendCommand(command) } - setDownstreamKeyOnAir (onAir: boolean, key: number = 0) { + public setDownstreamKeyOnAir (onAir: boolean, key: number = 0) { const command = new Commands.DownstreamKeyOnAirCommand(key, onAir) return this.sendCommand(command) } - setDownstreamKeyCutSource (input: number, key: number = 0) { + public setDownstreamKeyCutSource (input: number, key: number = 0) { const command = new Commands.DownstreamKeyCutSourceCommand(key, input) return this.sendCommand(command) } - setDownstreamKeyFillSource (input: number, key: number = 0) { + public setDownstreamKeyFillSource (input: number, key: number = 0) { const command = new Commands.DownstreamKeyFillSourceCommand(key, input) return this.sendCommand(command) } - setDownstreamKeyGeneralProperties (props: Partial, key: number = 0) { + public setDownstreamKeyGeneralProperties (props: Partial, key: number = 0) { const command = new Commands.DownstreamKeyGeneralCommand(key) command.updateProps(props) return this.sendCommand(command) } - setDownstreamKeyMaskSettings (props: Partial, key: number = 0) { + public setDownstreamKeyMaskSettings (props: Partial, key: number = 0) { const command = new Commands.DownstreamKeyMaskCommand(key) command.updateProps(props) return this.sendCommand(command) } - setDownstreamKeyRate (rate: number, key: number = 0) { + public setDownstreamKeyRate (rate: number, key: number = 0) { const command = new Commands.DownstreamKeyRateCommand(key, rate) return this.sendCommand(command) } - macroContinue () { + public macroContinue () { const command = new Commands.MacroActionCommand(0, Enums.MacroAction.Continue) return this.sendCommand(command) } - macroDelete (index = 0) { + public macroDelete (index = 0) { const command = new Commands.MacroActionCommand(index, Enums.MacroAction.Delete) return this.sendCommand(command) } - macroInsertUserWait () { + public macroInsertUserWait () { const command = new Commands.MacroActionCommand(0, Enums.MacroAction.InsertUserWait) return this.sendCommand(command) } - macroRun (index: number = 0) { + public macroRun (index: number = 0) { const command = new Commands.MacroActionCommand(index, Enums.MacroAction.Run) return this.sendCommand(command) } - macroStop () { + public macroStop () { const command = new Commands.MacroActionCommand(0, Enums.MacroAction.Stop) return this.sendCommand(command) } - macroStopRecord () { + public macroStopRecord () { const command = new Commands.MacroActionCommand(0, Enums.MacroAction.StopRecord) return this.sendCommand(command) } - setMultiViewerSource (newProps: Partial, mv = 0) { + public setMultiViewerSource (newProps: Partial, mv = 0) { const command = new Commands.MultiViewerSourceCommand(mv) command.updateProps(newProps) return this.sendCommand(command) } - setMediaPlayerSettings (newProps: Partial, player: number = 0) { + public setMediaPlayerSettings (newProps: Partial, player: number = 0) { const command = new Commands.MediaPlayerStatusCommand(player) command.updateProps(newProps) return this.sendCommand(command) } - setMediaPlayerSource (newProps: Partial, player: number = 0) { + public setMediaPlayerSource (newProps: Partial, player: number = 0) { const command = new Commands.MediaPlayerSourceCommand(player) command.updateProps(newProps) return this.sendCommand(command) } - setMediaClip (index: number, name: string, frames: number = 1) { + public setMediaClip (index: number, name: string, frames: number = 1) { const command = new Commands.MediaPoolSetClipCommand({ index, name, frames }) return this.sendCommand(command) } - clearMediaPoolClip (clipId: number) { + public clearMediaPoolClip (clipId: number) { const command = new Commands.MediaPoolClearClipCommand(clipId) return this.sendCommand(command) } - clearMediaPoolStill (stillId: number) { + public clearMediaPoolStill (stillId: number) { const command = new Commands.MediaPoolClearStillCommand(stillId) return this.sendCommand(command) } - setSuperSourceBoxSettings (newProps: Partial, box: number = 0, ssrcId: number = 0) { + public setSuperSourceBoxSettings (newProps: Partial, box: number = 0, ssrcId: number = 0) { const command = new Commands.SuperSourceBoxParametersCommand(ssrcId, box) command.updateProps(newProps) return this.sendCommand(command) } - setSuperSourceProperties (newProps: Partial, ssrcId: number = 0) { + public setSuperSourceProperties (newProps: Partial, ssrcId: number = 0) { if (this._state.info.apiVersion >= Enums.ProtocolVersion.V8_0) { const command = new Commands.SuperSourcePropertiesV8Command(ssrcId) command.updateProps(newProps) @@ -329,7 +329,7 @@ export class Atem extends EventEmitter { } } - setSuperSourceBorder (newProps: Partial, ssrcId: number = 0) { + public setSuperSourceBorder (newProps: Partial, ssrcId: number = 0) { if (this._state.info.apiVersion >= Enums.ProtocolVersion.V8_0) { const command = new Commands.SuperSourceBorderCommand(ssrcId) command.updateProps(newProps) @@ -341,64 +341,64 @@ export class Atem extends EventEmitter { } } - setInputSettings (newProps: Partial, input: number = 0) { + public setInputSettings (newProps: Partial, input: number = 0) { const command = new Commands.InputPropertiesCommand(input) command.updateProps(newProps) return this.sendCommand(command) } - setUpstreamKeyerChromaSettings (newProps: Partial, me: number = 0, keyer: number = 0) { + public setUpstreamKeyerChromaSettings (newProps: Partial, me: number = 0, keyer: number = 0) { const command = new Commands.MixEffectKeyChromaCommand(me, keyer) command.updateProps(newProps) return this.sendCommand(command) } - setUpstreamKeyerCutSource (cutSource: number, me: number = 0, keyer: number = 0) { + public setUpstreamKeyerCutSource (cutSource: number, me: number = 0, keyer: number = 0) { const command = new Commands.MixEffectKeyCutSourceSetCommand(me, keyer, cutSource) return this.sendCommand(command) } - setUpstreamKeyerFillSource (fillSource: number, me: number = 0, keyer: number = 0) { + public setUpstreamKeyerFillSource (fillSource: number, me: number = 0, keyer: number = 0) { const command = new Commands.MixEffectKeyFillSourceSetCommand(me, keyer, fillSource) return this.sendCommand(command) } - setUpstreamKeyerDVESettings (newProps: Partial, me: number = 0, keyer: number = 0) { + public setUpstreamKeyerDVESettings (newProps: Partial, me: number = 0, keyer: number = 0) { const command = new Commands.MixEffectKeyDVECommand(me, keyer) command.updateProps(newProps) return this.sendCommand(command) } - setUpstreamKeyerLumaSettings (newProps: Partial, me: number = 0, keyer: number = 0) { + public setUpstreamKeyerLumaSettings (newProps: Partial, me: number = 0, keyer: number = 0) { const command = new Commands.MixEffectKeyLumaCommand(me, keyer) command.updateProps(newProps) return this.sendCommand(command) } - setUpstreamKeyerMaskSettings (newProps: Partial, me: number = 0, keyer: number = 0) { + public setUpstreamKeyerMaskSettings (newProps: Partial, me: number = 0, keyer: number = 0) { const command = new Commands.MixEffectKeyMaskSetCommand(me, keyer) command.updateProps(newProps) return this.sendCommand(command) } - setUpstreamKeyerPatternSettings (newProps: Partial, me: number = 0, keyer: number = 0) { + public setUpstreamKeyerPatternSettings (newProps: Partial, me: number = 0, keyer: number = 0) { const command = new Commands.MixEffectKeyPatternCommand(me, keyer) command.updateProps(newProps) return this.sendCommand(command) } - setUpstreamKeyerOnAir (onAir: boolean, me: number = 0, keyer: number = 0) { + public setUpstreamKeyerOnAir (onAir: boolean, me: number = 0, keyer: number = 0) { const command = new Commands.MixEffectKeyOnAirCommand(me, keyer, onAir) return this.sendCommand(command) } - setUpstreamKeyerType (newProps: Partial, me: number = 0, keyer: number = 0) { + public setUpstreamKeyerType (newProps: Partial, me: number = 0, keyer: number = 0) { const command = new Commands.MixEffectKeyTypeSetCommand(me, keyer) command.updateProps(newProps) return this.sendCommand(command) } - uploadStill (index: number, data: Buffer, name: string, description: string) { + public uploadStill (index: number, data: Buffer, name: string, description: string) { const resolution = Util.getResolution(this._state.settings.videoMode) return this.dataTransferManager.uploadStill( index, @@ -408,7 +408,7 @@ export class Atem extends EventEmitter { ) } - uploadClip (index: number, frames: Array, name: string) { + public uploadClip (index: number, frames: Array, name: string) { const resolution = Util.getResolution(this._state.settings.videoMode) const data: Array = [] for (const frame of frames) { @@ -421,7 +421,7 @@ export class Atem extends EventEmitter { ) } - uploadAudio (index: number, data: Buffer, name: string) { + public uploadAudio (index: number, data: Buffer, name: string) { return this.dataTransferManager.uploadAudio( index, Util.convertWAVToRaw(data), @@ -429,43 +429,43 @@ export class Atem extends EventEmitter { ) } - setAudioMixerInputMixOption (index: number, mixOption: Enums.AudioMixOption) { + public setAudioMixerInputMixOption (index: number, mixOption: Enums.AudioMixOption) { const command = new Commands.AudioMixerInputCommand(index) command.updateProps({ mixOption }) return this.sendCommand(command) } - setAudioMixerInputGain (index: number, gain: number) { + public setAudioMixerInputGain (index: number, gain: number) { const command = new Commands.AudioMixerInputCommand(index) command.updateProps({ gain }) return this.sendCommand(command) } - setAudioMixerInputBalance (index: number, balance: number) { + public setAudioMixerInputBalance (index: number, balance: number) { const command = new Commands.AudioMixerInputCommand(index) command.updateProps({ balance }) return this.sendCommand(command) } - setAudioMixerInputProps (index: number, props: Partial) { + public setAudioMixerInputProps (index: number, props: Partial) { const command = new Commands.AudioMixerInputCommand(index) command.updateProps(props) return this.sendCommand(command) } - setAudioMixerMasterGain (gain: number) { + public setAudioMixerMasterGain (gain: number) { const command = new Commands.AudioMixerMasterCommand() command.updateProps({ gain }) return this.sendCommand(command) } - setAudioMixerMasterProps (props: Partial) { + public setAudioMixerMasterProps (props: Partial) { const command = new Commands.AudioMixerMasterCommand() command.updateProps(props) return this.sendCommand(command) } - listVisibleInputs (mode: 'program' | 'preview', me = 0): number[] { + public listVisibleInputs (mode: 'program' | 'preview', me = 0): number[] { return listVisibleInputs(mode, this.state, me) } diff --git a/src/commands/Audio/AudioMixerInputCommand.ts b/src/commands/Audio/AudioMixerInputCommand.ts index 3f5328150..47be256ec 100644 --- a/src/commands/Audio/AudioMixerInputCommand.ts +++ b/src/commands/Audio/AudioMixerInputCommand.ts @@ -4,14 +4,14 @@ import { AudioChannel } from '../../state/audio' import { WritableCommand, DeserializedCommand } from '../CommandBase' export class AudioMixerInputCommand extends WritableCommand { - static MaskFlags = { + public static MaskFlags = { mixOption: 1 << 0, gain: 1 << 1, balance: 1 << 2 } - static readonly rawName = 'CAMI' + public static readonly rawName = 'CAMI' - readonly index: number + public readonly index: number constructor (index: number) { super() @@ -19,7 +19,7 @@ export class AudioMixerInputCommand extends WritableCommand { this.index = index } - serialize () { + public serialize () { const buffer = Buffer.alloc(12) buffer.writeUInt8(this.flag, 0) buffer.writeUInt16BE(this.index, 2) @@ -31,9 +31,9 @@ export class AudioMixerInputCommand extends WritableCommand { } export class AudioMixerInputUpdateCommand extends DeserializedCommand { - static readonly rawName = 'AMIP' + public static readonly rawName = 'AMIP' - readonly index: number + public readonly index: number constructor (index: number, properties: AudioChannel) { super(properties) @@ -41,7 +41,7 @@ export class AudioMixerInputUpdateCommand extends DeserializedCommand { - static MaskFlags = { + public static MaskFlags = { gain: 1 << 0, balance: 1 << 1, followFadeToBlack: 1 << 2 } - static readonly rawName = 'CAMM' + public static readonly rawName = 'CAMM' - serialize () { + public serialize () { const buffer = Buffer.alloc(8) buffer.writeUInt8(this.flag, 0) buffer.writeUInt16BE(Util.DecibelToUInt16BE(this.properties.gain || 0), 2) @@ -22,9 +22,9 @@ export class AudioMixerMasterCommand extends WritableCommand } export class AudioMixerMasterUpdateCommand extends DeserializedCommand { - static readonly rawName = 'AMMO' + public static readonly rawName = 'AMMO' - static deserialize (rawCommand: Buffer): AudioMixerMasterUpdateCommand { + public static deserialize (rawCommand: Buffer): AudioMixerMasterUpdateCommand { const properties = { gain: Util.UInt16BEToDecibel(rawCommand.readUInt16BE(0)), balance: Util.IntToBalance(rawCommand.readInt16BE(2)), @@ -34,7 +34,7 @@ export class AudioMixerMasterUpdateCommand extends DeserializedCommand { - static readonly rawName = 'CAuS' + public static readonly rawName = 'CAuS' - readonly auxBus: number + public readonly auxBus: number constructor (auxBus: number, source: number) { super({ source }) @@ -16,7 +16,7 @@ export class AuxSourceCommand extends BasicWritableCommand { this.auxBus = auxBus } - serialize () { + public serialize () { const buffer = Buffer.alloc(4) buffer.writeUInt8(0x01, 0) buffer.writeUInt8(this.auxBus, 1) @@ -26,9 +26,9 @@ export class AuxSourceCommand extends BasicWritableCommand { } export class AuxSourceUpdateCommand extends DeserializedCommand { - static readonly rawName = 'AuxS' + public static readonly rawName = 'AuxS' - readonly auxBus: number + public readonly auxBus: number constructor (auxBus: number, properties: AuxSourceProps) { super(properties) @@ -36,7 +36,7 @@ export class AuxSourceUpdateCommand extends DeserializedCommand this.auxBus = auxBus } - static deserialize (rawCommand: Buffer): AuxSourceUpdateCommand { + public static deserialize (rawCommand: Buffer): AuxSourceUpdateCommand { const auxBus = rawCommand[0] const properties = { source: rawCommand.readUInt16BE(2) @@ -45,7 +45,7 @@ export class AuxSourceUpdateCommand extends DeserializedCommand return new AuxSourceUpdateCommand(auxBus, properties) } - applyToState (state: AtemState) { + public applyToState (state: AtemState) { state.video.auxilliaries[this.auxBus] = this.properties.source return `video.auxilliaries.${this.auxBus}` } diff --git a/src/commands/CommandBase.ts b/src/commands/CommandBase.ts index 55fef4b10..33abae2a6 100644 --- a/src/commands/CommandBase.ts +++ b/src/commands/CommandBase.ts @@ -8,15 +8,15 @@ export interface IDeserializedCommand { } export abstract class DeserializedCommand implements IDeserializedCommand { - static readonly minimumVersion?: ProtocolVersion + public static readonly minimumVersion?: ProtocolVersion - readonly properties: Readonly + public readonly properties: Readonly constructor (properties: T) { this.properties = properties } - abstract applyToState (state: AtemState): string | string[] + public abstract applyToState (state: AtemState): string | string[] } export interface ISerializableCommand { @@ -24,8 +24,8 @@ export interface ISerializableCommand { } export abstract class BasicWritableCommand implements ISerializableCommand { - static readonly MaskFlags?: { [key: string]: number } - static readonly minimumVersion?: ProtocolVersion + public static readonly MaskFlags?: { [key: string]: number } + public static readonly minimumVersion?: ProtocolVersion protected _properties: T @@ -37,13 +37,13 @@ export abstract class BasicWritableCommand implements ISerializableCommand { this._properties = properties } - abstract serialize (version: ProtocolVersion): Buffer + public abstract serialize (version: ProtocolVersion): Buffer } export abstract class WritableCommand extends BasicWritableCommand> { - static readonly MaskFlags?: { [key: string]: number } + public static readonly MaskFlags?: { [key: string]: number } - flag: number + public flag: number constructor () { super({}) diff --git a/src/commands/DataTransfer/DataTransferAckCommand.ts b/src/commands/DataTransfer/DataTransferAckCommand.ts index bd6dd5da6..dab7423b2 100644 --- a/src/commands/DataTransfer/DataTransferAckCommand.ts +++ b/src/commands/DataTransfer/DataTransferAckCommand.ts @@ -6,9 +6,9 @@ export interface DataTransferAckProps { } export class DataTransferAckCommand extends DeserializedCommand { - static readonly rawName = 'FTUA' + public static readonly rawName = 'FTUA' - static deserialize (rawCommand: Buffer): DataTransferAckCommand { + public static deserialize (rawCommand: Buffer): DataTransferAckCommand { const properties = { transferId: rawCommand.readUInt16BE(0), transferIndex: rawCommand.readUInt8(2) @@ -17,7 +17,7 @@ export class DataTransferAckCommand extends DeserializedCommand { - static readonly rawName = 'FTDC' + public static readonly rawName = 'FTDC' - static deserialize (rawCommand: Buffer): DataTransferCompleteCommand { + public static deserialize (rawCommand: Buffer): DataTransferCompleteCommand { const properties = { transferId: rawCommand.readUInt16BE(0) } @@ -11,7 +11,7 @@ export class DataTransferCompleteCommand extends DeserializedCommand<{ transferI return new DataTransferCompleteCommand(properties) } - applyToState (): string[] { + public applyToState (): string[] { // Nothing to do return [] } diff --git a/src/commands/DataTransfer/DataTransferDataCommand.ts b/src/commands/DataTransfer/DataTransferDataCommand.ts index c2e23194d..77c970877 100644 --- a/src/commands/DataTransfer/DataTransferDataCommand.ts +++ b/src/commands/DataTransfer/DataTransferDataCommand.ts @@ -6,9 +6,9 @@ export interface DataTransferDataProps { } export class DataTransferDataCommand extends BasicWritableCommand implements IDeserializedCommand { - static readonly rawName = 'FTDa' + public static readonly rawName = 'FTDa' - serialize () { + public serialize () { const buffer = Buffer.alloc(4) buffer.writeUInt16BE(this.properties.transferId, 0) buffer.writeUInt16BE(this.properties.body.length, 2) @@ -16,7 +16,7 @@ export class DataTransferDataCommand extends BasicWritableCommand { - static readonly rawName = 'FTSU' + public static readonly rawName = 'FTSU' - serialize () { + public serialize () { const buffer = Buffer.alloc(12) buffer.writeUInt16BE(this.properties.transferId, 0) buffer.writeUInt16BE(this.properties.transferStoreId, 2) diff --git a/src/commands/DataTransfer/DataTransferErrorCommand.ts b/src/commands/DataTransfer/DataTransferErrorCommand.ts index a59c07fd4..bcb4fd279 100644 --- a/src/commands/DataTransfer/DataTransferErrorCommand.ts +++ b/src/commands/DataTransfer/DataTransferErrorCommand.ts @@ -6,9 +6,9 @@ export interface DataTransferErrorProps { } export class DataTransferErrorCommand extends DeserializedCommand { - static readonly rawName = 'FTDE' + public static readonly rawName = 'FTDE' - static deserialize (rawCommand: Buffer): DataTransferErrorCommand { + public static deserialize (rawCommand: Buffer): DataTransferErrorCommand { const properties = { transferId: rawCommand.readUInt16BE(0), errorCode: rawCommand.readUInt8(2) @@ -17,7 +17,7 @@ export class DataTransferErrorCommand extends DeserializedCommand { - static readonly rawName = 'FTFD' + public static readonly rawName = 'FTFD' - serialize () { + public serialize () { const buffer = Buffer.alloc(212) buffer.writeUInt16BE(this.properties.transferId, 0) if (this.properties.name) buffer.write(this.properties.name, 2, 64) diff --git a/src/commands/DataTransfer/DataTransferUploadContinueCommand.ts b/src/commands/DataTransfer/DataTransferUploadContinueCommand.ts index 5f6d7e065..42130f056 100644 --- a/src/commands/DataTransfer/DataTransferUploadContinueCommand.ts +++ b/src/commands/DataTransfer/DataTransferUploadContinueCommand.ts @@ -7,9 +7,9 @@ export interface DataTransferUploadContinueProps { } export class DataTransferUploadContinueCommand extends DeserializedCommand { - static readonly rawName = 'FTCD' + public static readonly rawName = 'FTCD' - static deserialize (rawCommand: Buffer) { + public static deserialize (rawCommand: Buffer) { const properties = { transferId: rawCommand.readUInt16BE(0), chunkSize: rawCommand.readUInt16BE(6), @@ -19,7 +19,7 @@ export class DataTransferUploadContinueCommand extends DeserializedCommand { - static readonly rawName = 'FTSD' + public static readonly rawName = 'FTSD' - serialize () { + public serialize () { const buffer = Buffer.alloc(16) buffer.writeUInt16BE(this.properties.transferId, 0) buffer.writeUInt16BE(this.properties.transferStoreId, 2) diff --git a/src/commands/DataTransfer/LockObtainedCommand.ts b/src/commands/DataTransfer/LockObtainedCommand.ts index 11318677f..476f185a2 100644 --- a/src/commands/DataTransfer/LockObtainedCommand.ts +++ b/src/commands/DataTransfer/LockObtainedCommand.ts @@ -1,19 +1,19 @@ import { DeserializedCommand } from '../CommandBase' export class LockObtainedCommand extends DeserializedCommand<{ index: number }> { - static readonly rawName = 'LKOB' + public static readonly rawName = 'LKOB' constructor (index: number) { super({ index }) } - static deserialize (rawCommand: Buffer) { + public static deserialize (rawCommand: Buffer) { const index = rawCommand.readUInt16BE(0) return new LockObtainedCommand(index) } - applyToState (): string[] { + public applyToState (): string[] { // nothing to do return [] } diff --git a/src/commands/DataTransfer/LockStateCommand.ts b/src/commands/DataTransfer/LockStateCommand.ts index 4b28081a4..6369954ee 100644 --- a/src/commands/DataTransfer/LockStateCommand.ts +++ b/src/commands/DataTransfer/LockStateCommand.ts @@ -6,13 +6,13 @@ export interface LockStateProps { } export class LockStateCommand extends BasicWritableCommand { - static readonly rawName = 'LOCK' + public static readonly rawName = 'LOCK' constructor (index: number, locked: boolean) { super({ index, locked }) } - serialize () { + public serialize () { const buffer = Buffer.alloc(4) buffer.writeUInt16BE(this.properties.index, 0) buffer[2] = this.properties.locked ? 1 : 0 @@ -21,9 +21,9 @@ export class LockStateCommand extends BasicWritableCommand { } export class LockStateUpdateCommand extends DeserializedCommand { - static readonly rawName = 'LKST' + public static readonly rawName = 'LKST' - static deserialize (rawCommand: Buffer) { + public static deserialize (rawCommand: Buffer) { const properties = { index: rawCommand.readUInt16BE(0), locked: rawCommand[2] === 1 @@ -32,7 +32,7 @@ export class LockStateUpdateCommand extends DeserializedCommand return new LockStateUpdateCommand(properties) } - applyToState (): string | string[] { + public applyToState (): string | string[] { // Nothing to do return [] } diff --git a/src/commands/DeviceProfile/productIdentifierCommand.ts b/src/commands/DeviceProfile/productIdentifierCommand.ts index 90b364e08..ecc2f7c98 100644 --- a/src/commands/DeviceProfile/productIdentifierCommand.ts +++ b/src/commands/DeviceProfile/productIdentifierCommand.ts @@ -5,9 +5,9 @@ import { Enums } from '../..' import { DeviceInfo } from '../../state/info' export class ProductIdentifierCommand extends DeserializedCommand> { - static readonly rawName = '_pin' + public static readonly rawName = '_pin' - static deserialize (rawCommand: Buffer) { + public static deserialize (rawCommand: Buffer) { const properties = { productIdentifier: Util.bufToNullTerminatedString(rawCommand, 0, 40), model: rawCommand[40] @@ -16,7 +16,7 @@ export class ProductIdentifierCommand extends DeserializedCommand { - static readonly rawName = '_SSC' + public static readonly rawName = '_SSC' - readonly ssrcId: number + public readonly ssrcId: number constructor (ssrcId: number, properties: SuperSourceInfo) { super(properties) @@ -14,7 +14,7 @@ export class SuperSourceConfigCommand extends DeserializedCommand= ProtocolVersion.V8_0) { return new SuperSourceConfigCommand(rawCommand[0], { boxCount: rawCommand[2] }) } else { @@ -22,7 +22,7 @@ export class SuperSourceConfigCommand extends DeserializedCommand { - static readonly rawName = '_top' + public static readonly rawName = '_top' - static deserialize (rawCommand: Buffer) { + public static deserialize (rawCommand: Buffer) { const properties = { MEs: rawCommand[0], sources: rawCommand[1], @@ -25,7 +25,7 @@ export class TopologyCommand extends DeserializedCommand { return new TopologyCommand(properties) } - applyToState (state: AtemState) { + public applyToState (state: AtemState) { state.info.capabilities = { ...state.info.capabilities, ...this.properties diff --git a/src/commands/DeviceProfile/versionCommand.ts b/src/commands/DeviceProfile/versionCommand.ts index e32c1ba47..ebcb35861 100644 --- a/src/commands/DeviceProfile/versionCommand.ts +++ b/src/commands/DeviceProfile/versionCommand.ts @@ -3,19 +3,19 @@ import { AtemState } from '../../state' import { ProtocolVersion } from '../../enums' export class VersionCommand extends DeserializedCommand<{ version: ProtocolVersion }> { - static readonly rawName = '_ver' + public static readonly rawName = '_ver' constructor (version: ProtocolVersion) { super({ version }) } - static deserialize (rawCommand: Buffer) { + public static deserialize (rawCommand: Buffer) { const version = rawCommand.readUInt32BE(0) return new VersionCommand(version) } - applyToState (state: AtemState) { + public applyToState (state: AtemState) { state.info.apiVersion = this.properties.version return `info.apiVersion` } diff --git a/src/commands/DownstreamKey/DownstreamKeyAutoCommand.ts b/src/commands/DownstreamKey/DownstreamKeyAutoCommand.ts index cd55ce41c..c68e55a83 100644 --- a/src/commands/DownstreamKey/DownstreamKeyAutoCommand.ts +++ b/src/commands/DownstreamKey/DownstreamKeyAutoCommand.ts @@ -2,12 +2,12 @@ import { WritableCommand } from '../CommandBase' import { ProtocolVersion } from '../../enums' export class DownstreamKeyAutoCommand extends WritableCommand<{ isTowardsOnAir: boolean }> { - static readonly MaskFlags = { + public static readonly MaskFlags = { isTowardsOnAir: 1 } - static readonly rawName = 'DDsA' + public static readonly rawName = 'DDsA' - readonly downstreamKeyerId: number + public readonly downstreamKeyerId: number constructor (downstreamKeyerId: number) { super() @@ -15,7 +15,7 @@ export class DownstreamKeyAutoCommand extends WritableCommand<{ isTowardsOnAir: this.downstreamKeyerId = downstreamKeyerId } - serialize (version: ProtocolVersion) { + public serialize (version: ProtocolVersion) { const buffer = Buffer.alloc(4) if (version >= ProtocolVersion.V8_0_1) { diff --git a/src/commands/DownstreamKey/DownstreamKeyCutSourceCommand.ts b/src/commands/DownstreamKey/DownstreamKeyCutSourceCommand.ts index fa70dbf0f..e6d5236e9 100644 --- a/src/commands/DownstreamKey/DownstreamKeyCutSourceCommand.ts +++ b/src/commands/DownstreamKey/DownstreamKeyCutSourceCommand.ts @@ -1,9 +1,9 @@ import { BasicWritableCommand } from '../CommandBase' export class DownstreamKeyCutSourceCommand extends BasicWritableCommand<{ input: number }> { - static readonly rawName = 'CDsC' + public static readonly rawName = 'CDsC' - readonly downstreamKeyerId: number + public readonly downstreamKeyerId: number constructor (downstreamKeyerId: number, input: number) { super({ input }) @@ -11,7 +11,7 @@ export class DownstreamKeyCutSourceCommand extends BasicWritableCommand<{ input: this.downstreamKeyerId = downstreamKeyerId } - serialize () { + public serialize () { const buffer = Buffer.alloc(4) buffer.writeUInt8(this.downstreamKeyerId, 0) buffer.writeUInt16BE(this.properties.input, 2) diff --git a/src/commands/DownstreamKey/DownstreamKeyFillSourceCommand.ts b/src/commands/DownstreamKey/DownstreamKeyFillSourceCommand.ts index ccec1427d..74afce779 100644 --- a/src/commands/DownstreamKey/DownstreamKeyFillSourceCommand.ts +++ b/src/commands/DownstreamKey/DownstreamKeyFillSourceCommand.ts @@ -1,9 +1,9 @@ import { BasicWritableCommand } from '../CommandBase' export class DownstreamKeyFillSourceCommand extends BasicWritableCommand<{ input: number }> { - static readonly rawName = 'CDsF' + public static readonly rawName = 'CDsF' - readonly downstreamKeyerId: number + public readonly downstreamKeyerId: number constructor (downstreamKeyerId: number, input: number) { super({ input }) @@ -11,7 +11,7 @@ export class DownstreamKeyFillSourceCommand extends BasicWritableCommand<{ input this.downstreamKeyerId = downstreamKeyerId } - serialize () { + public serialize () { const buffer = Buffer.alloc(4) buffer.writeUInt8(this.downstreamKeyerId, 0) buffer.writeUInt16BE(this.properties.input, 2) diff --git a/src/commands/DownstreamKey/DownstreamKeyGeneralCommand.ts b/src/commands/DownstreamKey/DownstreamKeyGeneralCommand.ts index c0fa783eb..0fb2e9eeb 100644 --- a/src/commands/DownstreamKey/DownstreamKeyGeneralCommand.ts +++ b/src/commands/DownstreamKey/DownstreamKeyGeneralCommand.ts @@ -2,16 +2,16 @@ import { WritableCommand } from '../CommandBase' import { DownstreamKeyerGeneral } from '../../state/video/downstreamKeyers' export class DownstreamKeyGeneralCommand extends WritableCommand { - static MaskFlags = { + public static MaskFlags = { preMultiply: 1 << 0, clip: 1 << 1, gain: 1 << 2, invert: 1 << 3 } - static readonly rawName = 'CDsG' + public static readonly rawName = 'CDsG' - readonly downstreamKeyerId: number + public readonly downstreamKeyerId: number constructor (downstreamKeyerId: number) { super() @@ -19,7 +19,7 @@ export class DownstreamKeyGeneralCommand extends WritableCommand { - static MaskFlags = { + public static MaskFlags = { enabled: 1 << 0, top: 1 << 1, bottom: 1 << 2, @@ -10,9 +10,9 @@ export class DownstreamKeyMaskCommand extends WritableCommand { - static readonly rawName = 'CDsL' + public static readonly rawName = 'CDsL' - readonly downstreamKeyerId: number + public readonly downstreamKeyerId: number constructor (downstreamKeyerId: number, onAir: boolean) { super({ onAir }) @@ -11,7 +11,7 @@ export class DownstreamKeyOnAirCommand extends BasicWritableCommand<{ onAir: boo this.downstreamKeyerId = downstreamKeyerId } - serialize () { + public serialize () { const buffer = Buffer.alloc(4) buffer.writeUInt8(this.downstreamKeyerId, 0) buffer.writeUInt8(this.properties.onAir ? 1 : 0, 1) diff --git a/src/commands/DownstreamKey/DownstreamKeyPropertiesCommand.ts b/src/commands/DownstreamKey/DownstreamKeyPropertiesCommand.ts index 1a2755271..e5387d23a 100644 --- a/src/commands/DownstreamKey/DownstreamKeyPropertiesCommand.ts +++ b/src/commands/DownstreamKey/DownstreamKeyPropertiesCommand.ts @@ -4,9 +4,9 @@ import { DownstreamKeyerProperties } from '../../state/video/downstreamKeyers' import { Util } from '../..' export class DownstreamKeyPropertiesCommand extends DeserializedCommand { - static readonly rawName = 'DskP' + public static readonly rawName = 'DskP' - readonly downstreamKeyerId: number + public readonly downstreamKeyerId: number constructor (downstreamKeyerId: number, properties: DownstreamKeyerProperties) { super(properties) @@ -14,7 +14,7 @@ export class DownstreamKeyPropertiesCommand extends DeserializedCommand { - static readonly rawName = 'CDsR' + public static readonly rawName = 'CDsR' - readonly downstreamKeyerId: number + public readonly downstreamKeyerId: number constructor (downstreamKeyerId: number, rate: number) { super({ rate }) @@ -11,7 +11,7 @@ export class DownstreamKeyRateCommand extends BasicWritableCommand<{ rate: numbe this.downstreamKeyerId = downstreamKeyerId } - serialize () { + public serialize () { const buffer = Buffer.alloc(4) buffer.writeUInt8(this.downstreamKeyerId, 0) buffer.writeUInt8(this.properties.rate, 1) diff --git a/src/commands/DownstreamKey/DownstreamKeySourcesCommand.ts b/src/commands/DownstreamKey/DownstreamKeySourcesCommand.ts index d053f84d3..b8d0edf18 100644 --- a/src/commands/DownstreamKey/DownstreamKeySourcesCommand.ts +++ b/src/commands/DownstreamKey/DownstreamKeySourcesCommand.ts @@ -4,9 +4,9 @@ import { Util } from '../..' import { DownstreamKeyer } from '../../state/video/downstreamKeyers' export class DownstreamKeySourcesCommand extends DeserializedCommand { - static readonly rawName = 'DskB' + public static readonly rawName = 'DskB' - readonly downstreamKeyerId: number + public readonly downstreamKeyerId: number constructor (downstreamKeyerId: number, properties: DownstreamKeyer['sources']) { super(properties) @@ -14,7 +14,7 @@ export class DownstreamKeySourcesCommand extends DeserializedCommand { - static readonly rawName = 'DskS' + public static readonly rawName = 'DskS' - readonly downstreamKeyerId: number + public readonly downstreamKeyerId: number constructor (downstreamKeyerId: number, properties: DownstreamKeyerBase) { super(properties) @@ -15,7 +15,7 @@ export class DownstreamKeyStateCommand extends DeserializedCommand { - static readonly rawName = 'DskS' - static readonly minimumVersion = ProtocolVersion.V8_0_1 + public static readonly rawName = 'DskS' + public static readonly minimumVersion = ProtocolVersion.V8_0_1 - readonly downstreamKeyerId: number + public readonly downstreamKeyerId: number constructor (downstreamKeyerId: number, properties: DownstreamKeyerBase) { super(properties) @@ -48,7 +48,7 @@ export class DownstreamKeyStateV8Command extends DeserializedCommand { - static readonly rawName = 'CDsT' + public static readonly rawName = 'CDsT' - readonly downstreamKeyerId: number + public readonly downstreamKeyerId: number constructor (downstreamKeyerId: number, tie: boolean) { super({ tie }) @@ -11,7 +11,7 @@ export class DownstreamKeyTieCommand extends BasicWritableCommand<{ tie: boolean this.downstreamKeyerId = downstreamKeyerId } - serialize () { + public serialize () { const buffer = Buffer.alloc(4) buffer.writeUInt8(this.downstreamKeyerId, 0) buffer.writeUInt8(this.properties.tie ? 1 : 0, 1) diff --git a/src/commands/InitCompleteCommand.ts b/src/commands/InitCompleteCommand.ts index 2a4dd0080..58190558d 100644 --- a/src/commands/InitCompleteCommand.ts +++ b/src/commands/InitCompleteCommand.ts @@ -1,17 +1,17 @@ import { DeserializedCommand } from './CommandBase' export class InitCompleteCommand extends DeserializedCommand { - static readonly rawName = 'InCm' + public static readonly rawName = 'InCm' constructor () { super(null) } - static deserialize () { + public static deserialize () { return new InitCompleteCommand() } - applyToState () { + public applyToState () { return `info` } } diff --git a/src/commands/Inputs/InputPropertiesCommand.ts b/src/commands/Inputs/InputPropertiesCommand.ts index 31dd9714e..64f1a6632 100644 --- a/src/commands/Inputs/InputPropertiesCommand.ts +++ b/src/commands/Inputs/InputPropertiesCommand.ts @@ -5,15 +5,15 @@ import { ExternalPorts, ExternalPortType } from '../../enums' import { Util } from '../../lib/atemUtil' export class InputPropertiesCommand extends WritableCommand { - static MaskFlags = { + public static MaskFlags = { longName: 1 << 0, shortName: 1 << 1, externalPortType: 1 << 2 } - static readonly rawName = 'CInL' + public static readonly rawName = 'CInL' - readonly inputId: number + public readonly inputId: number constructor (inputId: number) { super() @@ -21,7 +21,7 @@ export class InputPropertiesCommand extends WritableCommand { this.inputId = inputId } - serialize () { + public serialize () { const buffer = Buffer.alloc(32) buffer.writeUInt8(this.flag, 0) buffer.writeUInt16BE(this.inputId, 2) @@ -33,9 +33,9 @@ export class InputPropertiesCommand extends WritableCommand { } export class InputPropertiesUpdateCommand extends DeserializedCommand { - static readonly rawName = 'InPr' + public static readonly rawName = 'InPr' - readonly inputId: number + public readonly inputId: number constructor (inputId: number, properties: InputChannel) { super(properties) @@ -43,7 +43,7 @@ export class InputPropertiesUpdateCommand extends DeserializedCommand { - static readonly rawName = 'MAct' + public static readonly rawName = 'MAct' - readonly index: number + public readonly index: number constructor (index: number, action: MacroAction) { super({ action }) @@ -12,7 +12,7 @@ export class MacroActionCommand extends BasicWritableCommand<{ action: MacroActi this.index = index } - serialize () { + public serialize () { const buffer = Buffer.alloc(4) buffer.writeUInt8(this.properties.action, 2) switch (this.properties.action) { diff --git a/src/commands/Macro/MacroPropertiesCommand.ts b/src/commands/Macro/MacroPropertiesCommand.ts index 5801924bc..cc05c66de 100644 --- a/src/commands/Macro/MacroPropertiesCommand.ts +++ b/src/commands/Macro/MacroPropertiesCommand.ts @@ -4,9 +4,9 @@ import { MacroPropertiesState } from '../../state/macro' import { Util } from '../../lib/atemUtil' export class MacroPropertiesCommand extends DeserializedCommand { - static readonly rawName = 'MPrp' + public static readonly rawName = 'MPrp' - readonly macroIndexID: number + public readonly macroIndexID: number constructor (macroIndexID: number, properties: MacroPropertiesState) { super(properties) @@ -14,7 +14,7 @@ export class MacroPropertiesCommand extends DeserializedCommand { - static readonly rawName = 'MRcS' + public static readonly rawName = 'MRcS' - static deserialize (rawCommand: Buffer) { + public static deserialize (rawCommand: Buffer) { const properties = { isRecording: Boolean(rawCommand[0] & 1 << 0), macroIndex: rawCommand.readUInt16BE(2) @@ -14,7 +14,7 @@ export class MacroRecordingStatusCommand extends DeserializedCommand { - static readonly rawName = 'MRPr' + public static readonly rawName = 'MRPr' - static deserialize (rawCommand: Buffer) { + public static deserialize (rawCommand: Buffer) { const properties = { isRunning: Boolean(rawCommand[0] & 1 << 0), isWaiting: Boolean(rawCommand[0] & 1 << 1), @@ -16,7 +16,7 @@ export class MacroRunStatusCommand extends DeserializedCommand return new MacroRunStatusCommand(properties) } - applyToState (state: AtemState) { + public applyToState (state: AtemState) { state.macro.macroPlayer = { ...state.macro.macroPlayer, ...this.properties diff --git a/src/commands/Media/MediaPlayerSourceCommand.ts b/src/commands/Media/MediaPlayerSourceCommand.ts index 130002274..7c53ae1c2 100644 --- a/src/commands/Media/MediaPlayerSourceCommand.ts +++ b/src/commands/Media/MediaPlayerSourceCommand.ts @@ -3,15 +3,15 @@ import { MediaPlayerSource } from '../../state/media' import { WritableCommand, DeserializedCommand } from '../CommandBase' export class MediaPlayerSourceCommand extends WritableCommand { - static MaskFlags = { + public static MaskFlags = { sourceType: 1 << 0, stillIndex: 1 << 1, clipIndex: 1 << 2 } - static readonly rawName = 'MPSS' + public static readonly rawName = 'MPSS' - readonly mediaPlayerId: number + public readonly mediaPlayerId: number constructor (mediaPlayerId: number) { super() @@ -19,7 +19,7 @@ export class MediaPlayerSourceCommand extends WritableCommand this.mediaPlayerId = mediaPlayerId } - serialize () { + public serialize () { const buffer = Buffer.alloc(8) buffer.writeUInt8(this.flag, 0) buffer.writeUInt8(this.mediaPlayerId, 1) @@ -31,9 +31,9 @@ export class MediaPlayerSourceCommand extends WritableCommand } export class MediaPlayerSourceUpdateCommand extends DeserializedCommand { - static readonly rawName = 'MPCE' + public static readonly rawName = 'MPCE' - readonly mediaPlayerId: number + public readonly mediaPlayerId: number constructor (mediaPlayerId: number, properties: MediaPlayerSource) { super(properties) @@ -41,7 +41,7 @@ export class MediaPlayerSourceUpdateCommand extends DeserializedCommand { - static MaskFlags = { + public static MaskFlags = { playing: 1 << 0, loop: 1 << 1, atBeginning: 1 << 2, clipFrame: 1 << 3 } - static readonly rawName = 'SCPS' + public static readonly rawName = 'SCPS' - readonly mediaPlayerId: number + public readonly mediaPlayerId: number constructor (mediaPlayerId: number) { super() @@ -20,7 +20,7 @@ export class MediaPlayerStatusCommand extends WritableCommand { this.mediaPlayerId = mediaPlayerId } - serialize () { + public serialize () { const buffer = Buffer.alloc(8) buffer.writeUInt8(this.flag, 0) buffer.writeUInt8(this.mediaPlayerId, 1) @@ -33,9 +33,9 @@ export class MediaPlayerStatusCommand extends WritableCommand { } export class MediaPlayerStatusUpdateCommand extends DeserializedCommand { - static readonly rawName = 'RCPS' + public static readonly rawName = 'RCPS' - readonly mediaPlayerId: number + public readonly mediaPlayerId: number constructor (mediaPlayerId: number, properties: MediaPlayer) { super(properties) @@ -43,7 +43,7 @@ export class MediaPlayerStatusUpdateCommand extends DeserializedCommand { - static readonly rawName = 'CMPC' + public static readonly rawName = 'CMPC' constructor (index: number) { super({ index }) } - serialize () { + public serialize () { const buffer = Buffer.alloc(4) buffer.writeUInt8(this.properties.index, 0) return buffer diff --git a/src/commands/Media/MediaPoolClearStillCommand.ts b/src/commands/Media/MediaPoolClearStillCommand.ts index d0a22bd56..4f9b0fb8f 100644 --- a/src/commands/Media/MediaPoolClearStillCommand.ts +++ b/src/commands/Media/MediaPoolClearStillCommand.ts @@ -1,13 +1,13 @@ import { BasicWritableCommand } from '../CommandBase' export class MediaPoolClearStillCommand extends BasicWritableCommand<{ index: number }> { - static readonly rawName = 'CSTL' + public static readonly rawName = 'CSTL' constructor (index: number) { super({ index }) } - serialize () { + public serialize () { const buffer = Buffer.alloc(4) buffer.writeUInt8(this.properties.index, 0) return buffer diff --git a/src/commands/Media/MediaPoolClipDescription.ts b/src/commands/Media/MediaPoolClipDescription.ts index 9e516fe3e..69a48a57d 100644 --- a/src/commands/Media/MediaPoolClipDescription.ts +++ b/src/commands/Media/MediaPoolClipDescription.ts @@ -4,9 +4,9 @@ import { DeserializedCommand } from '../CommandBase' import { Util } from '../../lib/atemUtil' export class MediaPoolClipDescriptionCommand extends DeserializedCommand> { - static readonly rawName = 'MPCS' + public static readonly rawName = 'MPCS' - readonly mediaPool: number + public readonly mediaPool: number constructor (mediaPool: number, properties: Omit) { super(properties) @@ -14,7 +14,7 @@ export class MediaPoolClipDescriptionCommand extends DeserializedCommand { - static readonly rawName = 'MPfe' + public static readonly rawName = 'MPfe' - readonly mediaPool: number - readonly frameIndex: number + public readonly mediaPool: number + public readonly frameIndex: number constructor (mediaPool: number, frameIndex: number, properties: StillFrame) { super(properties) @@ -16,7 +16,7 @@ export class MediaPoolFrameDescriptionCommand extends DeserializedCommand { - static readonly rawName = 'SMPC' + public static readonly rawName = 'SMPC' - serialize () { + public serialize () { const buffer = Buffer.alloc(68) buffer.writeUInt8(3, 0) buffer.writeUInt8(this.properties.index, 1) diff --git a/src/commands/MixEffects/AutoTransitionCommand.ts b/src/commands/MixEffects/AutoTransitionCommand.ts index 3a08e4196..14596773a 100644 --- a/src/commands/MixEffects/AutoTransitionCommand.ts +++ b/src/commands/MixEffects/AutoTransitionCommand.ts @@ -1,9 +1,9 @@ import { BasicWritableCommand } from '../CommandBase' export class AutoTransitionCommand extends BasicWritableCommand { - static readonly rawName = 'DAut' + public static readonly rawName = 'DAut' - readonly mixEffect: number + public readonly mixEffect: number constructor (mixEffect: number) { super(null) @@ -11,7 +11,7 @@ export class AutoTransitionCommand extends BasicWritableCommand { this.mixEffect = mixEffect } - serialize () { + public serialize () { const buffer = Buffer.alloc(4) buffer.writeUInt8(this.mixEffect, 0) return buffer diff --git a/src/commands/MixEffects/CutCommand.ts b/src/commands/MixEffects/CutCommand.ts index 1ba62cf91..8a553ec62 100644 --- a/src/commands/MixEffects/CutCommand.ts +++ b/src/commands/MixEffects/CutCommand.ts @@ -1,9 +1,9 @@ import { BasicWritableCommand } from '../CommandBase' export class CutCommand extends BasicWritableCommand { - static readonly rawName = 'DCut' + public static readonly rawName = 'DCut' - readonly mixEffect: number + public readonly mixEffect: number constructor (mixEffect: number) { super(null) @@ -11,7 +11,7 @@ export class CutCommand extends BasicWritableCommand { this.mixEffect = mixEffect } - serialize () { + public serialize () { const buffer = Buffer.alloc(4) buffer.writeUInt8(this.mixEffect, 0) return buffer diff --git a/src/commands/MixEffects/FadeToBlack/FadeToBlackAutoCommand.ts b/src/commands/MixEffects/FadeToBlack/FadeToBlackAutoCommand.ts index 5d2fe0cf8..5501aa05b 100644 --- a/src/commands/MixEffects/FadeToBlack/FadeToBlackAutoCommand.ts +++ b/src/commands/MixEffects/FadeToBlack/FadeToBlackAutoCommand.ts @@ -1,9 +1,9 @@ import { BasicWritableCommand } from '../../CommandBase' export class FadeToBlackAutoCommand extends BasicWritableCommand { - static readonly rawName = 'FtbA' + public static readonly rawName = 'FtbA' - readonly mixEffect: number + public readonly mixEffect: number constructor (mixEffect: number) { super(null) @@ -11,7 +11,7 @@ export class FadeToBlackAutoCommand extends BasicWritableCommand { this.mixEffect = mixEffect } - serialize () { + public serialize () { const buffer = Buffer.alloc(4) buffer.writeUInt8(this.mixEffect, 0) return buffer diff --git a/src/commands/MixEffects/FadeToBlack/FadeToBlackRateCommand.ts b/src/commands/MixEffects/FadeToBlack/FadeToBlackRateCommand.ts index d82232bfb..4ddee644e 100644 --- a/src/commands/MixEffects/FadeToBlack/FadeToBlackRateCommand.ts +++ b/src/commands/MixEffects/FadeToBlack/FadeToBlackRateCommand.ts @@ -3,9 +3,9 @@ import { AtemState } from '../../../state' import { Util } from '../../..' export class FadeToBlackRateCommand extends BasicWritableCommand<{ rate: number }> { - static readonly rawName = 'FtbC' + public static readonly rawName = 'FtbC' - readonly mixEffect: number + public readonly mixEffect: number constructor (mixEffect: number, rate: number) { super({ rate }) @@ -13,7 +13,7 @@ export class FadeToBlackRateCommand extends BasicWritableCommand<{ rate: number this.mixEffect = mixEffect } - serialize () { + public serialize () { const buffer = Buffer.alloc(4) buffer.writeUInt8(1, 0) buffer.writeUInt8(this.mixEffect, 1) @@ -23,9 +23,9 @@ export class FadeToBlackRateCommand extends BasicWritableCommand<{ rate: number } export class FadeToBlackRateUpdateCommand extends DeserializedCommand<{ rate: number }> { - static readonly rawName = 'FtbP' + public static readonly rawName = 'FtbP' - readonly mixEffect: number + public readonly mixEffect: number constructor (mixEffect: number, rate: number) { super({ rate }) @@ -33,14 +33,14 @@ export class FadeToBlackRateUpdateCommand extends DeserializedCommand<{ rate: nu this.mixEffect = mixEffect } - static deserialize (rawCommand: Buffer) { + public static deserialize (rawCommand: Buffer) { const mixEffect = Util.parseNumberBetween(rawCommand[0], 0, 3) const rate = rawCommand.readUInt8(1) return new FadeToBlackRateUpdateCommand(mixEffect, rate) } - applyToState (state: AtemState) { + public applyToState (state: AtemState) { const mixEffect = state.video.getMe(this.mixEffect) mixEffect.fadeToBlack = { isFullyBlack: false, diff --git a/src/commands/MixEffects/FadeToBlack/FadeToBlackStateCommand.ts b/src/commands/MixEffects/FadeToBlack/FadeToBlackStateCommand.ts index 1d131c4b0..300cd59a7 100644 --- a/src/commands/MixEffects/FadeToBlack/FadeToBlackStateCommand.ts +++ b/src/commands/MixEffects/FadeToBlack/FadeToBlackStateCommand.ts @@ -9,9 +9,9 @@ export interface FadeToBlackProps { } export class FadeToBlackStateCommand extends DeserializedCommand { - static readonly rawName = 'FtbS' + public static readonly rawName = 'FtbS' - readonly mixEffect: number + public readonly mixEffect: number constructor (mixEffect: number, properties: FadeToBlackProps) { super(properties) @@ -19,7 +19,7 @@ export class FadeToBlackStateCommand extends DeserializedCommand { - static MaskFlags = { + public static MaskFlags = { hue: 1 << 0, gain: 1 << 1, ySuppress: 1 << 2, lift: 1 << 3, narrow: 1 << 4 } - static readonly rawName = 'CKCk' + public static readonly rawName = 'CKCk' - readonly mixEffect: number - readonly upstreamKeyerId: number + public readonly mixEffect: number + public readonly upstreamKeyerId: number constructor (mixEffect: number, upstreamKeyerId: number) { super() @@ -23,7 +23,7 @@ export class MixEffectKeyChromaCommand extends WritableCommand { - static readonly rawName = 'KeCk' + public static readonly rawName = 'KeCk' - readonly mixEffect: number - readonly upstreamKeyerId: number + public readonly mixEffect: number + public readonly upstreamKeyerId: number constructor (mixEffect: number, upstreamKeyerId: number, properties: UpstreamKeyerChromaSettings) { super(properties) @@ -52,7 +52,7 @@ export class MixEffectKeyChromaUpdateCommand extends DeserializedCommand { - static readonly rawName = 'CKeC' + public static readonly rawName = 'CKeC' - readonly mixEffect: number - readonly upstreamKeyerId: number + public readonly mixEffect: number + public readonly upstreamKeyerId: number constructor (mixEffect: number, upstreamKeyerId: number, cutSource: number) { super({ cutSource }) @@ -13,7 +13,7 @@ export class MixEffectKeyCutSourceSetCommand extends BasicWritableCommand<{ cutS this.upstreamKeyerId = upstreamKeyerId } - serialize () { + public serialize () { const buffer = Buffer.alloc(4) buffer.writeUInt8(this.mixEffect, 0) buffer.writeUInt8(this.upstreamKeyerId, 1) diff --git a/src/commands/MixEffects/Key/MixEffectKeyDVECommand.ts b/src/commands/MixEffects/Key/MixEffectKeyDVECommand.ts index 683270017..76474b9ba 100644 --- a/src/commands/MixEffects/Key/MixEffectKeyDVECommand.ts +++ b/src/commands/MixEffects/Key/MixEffectKeyDVECommand.ts @@ -4,7 +4,7 @@ import { UpstreamKeyerDVESettings } from '../../../state/video/upstreamKeyers' import { Util, Enums } from '../../..' export class MixEffectKeyDVECommand extends WritableCommand { - static MaskFlags = { + public static MaskFlags = { sizeX: 1 << 0, sizeY: 1 << 1, positionX: 1 << 2, @@ -32,10 +32,10 @@ export class MixEffectKeyDVECommand extends WritableCommand { - static readonly rawName = 'KeDV' + public static readonly rawName = 'KeDV' - readonly mixEffect: number - readonly upstreamKeyerId: number + public readonly mixEffect: number + public readonly upstreamKeyerId: number constructor (mixEffect: number, upstreamKeyerId: number, properties: UpstreamKeyerDVESettings) { super(properties) @@ -99,7 +99,7 @@ export class MixEffectKeyDVEUpdateCommand extends DeserializedCommand { - static readonly rawName = 'CKeF' + public static readonly rawName = 'CKeF' - readonly mixEffect: number - readonly upstreamKeyerId: number + public readonly mixEffect: number + public readonly upstreamKeyerId: number constructor (mixEffect: number, upstreamKeyerId: number, fillSource: number) { super({ fillSource }) @@ -13,7 +13,7 @@ export class MixEffectKeyFillSourceSetCommand extends BasicWritableCommand<{ fil this.upstreamKeyerId = upstreamKeyerId } - serialize () { + public serialize () { const buffer = Buffer.alloc(4) buffer.writeUInt8(this.mixEffect, 0) buffer.writeUInt8(this.upstreamKeyerId, 1) diff --git a/src/commands/MixEffects/Key/MixEffectKeyFlyKeyframeGetCommand.ts b/src/commands/MixEffects/Key/MixEffectKeyFlyKeyframeGetCommand.ts index 1574254c1..73e697956 100644 --- a/src/commands/MixEffects/Key/MixEffectKeyFlyKeyframeGetCommand.ts +++ b/src/commands/MixEffects/Key/MixEffectKeyFlyKeyframeGetCommand.ts @@ -4,11 +4,11 @@ import { UpstreamKeyerFlyKeyframe } from '../../../state/video/upstreamKeyers' import { Util } from '../../..' export class MixEffectKeyFlyKeyframeGetCommand extends DeserializedCommand { - static readonly rawName = 'KKFP' + public static readonly rawName = 'KKFP' - readonly mixEffect: number - readonly upstreamKeyerId: number - readonly keyFrameId: number + public readonly mixEffect: number + public readonly upstreamKeyerId: number + public readonly keyFrameId: number constructor (mixEffect: number, upstreamKeyerId: number, keyFrameId: number, properties: UpstreamKeyerFlyKeyframe) { super(properties) @@ -18,7 +18,7 @@ export class MixEffectKeyFlyKeyframeGetCommand extends DeserializedCommand { - static readonly rawName = 'KeFS' + public static readonly rawName = 'KeFS' - readonly mixEffect: number - readonly upstreamKeyerId: number + public readonly mixEffect: number + public readonly upstreamKeyerId: number constructor (mixEffect: number, upstreamKeyerId: number, properties: UpstreamKeyerFlySettings) { super(properties) @@ -16,7 +16,7 @@ export class MixEffectKeyFlyPropertiesGetCommand extends DeserializedCommand { - static MaskFlags = { + public static MaskFlags = { preMultiplied: 1 << 0, clip: 1 << 1, gain: 1 << 2, invert: 1 << 3 } - static readonly rawName = 'CKLm' + public static readonly rawName = 'CKLm' - readonly mixEffect: number - readonly upstreamKeyerId: number + public readonly mixEffect: number + public readonly upstreamKeyerId: number constructor (mixEffect: number, upstreamKeyerId: number) { super() @@ -22,7 +22,7 @@ export class MixEffectKeyLumaCommand extends WritableCommand { - static readonly rawName = 'KeLm' + public static readonly rawName = 'KeLm' - readonly mixEffect: number - readonly upstreamKeyerId: number + public readonly mixEffect: number + public readonly upstreamKeyerId: number constructor (mixEffect: number, upstreamKeyerId: number, properties: UpstreamKeyerLumaSettings) { super(properties) @@ -50,7 +50,7 @@ export class MixEffectKeyLumaUpdateCommand extends DeserializedCommand { - static MaskFlags = { + public static MaskFlags = { maskEnabled: 1 << 0, maskTop: 1 << 1, maskBottom: 1 << 2, @@ -10,10 +10,10 @@ export class MixEffectKeyMaskSetCommand extends WritableCommand { - static readonly rawName = 'CKOn' + public static readonly rawName = 'CKOn' - readonly mixEffect: number - readonly upstreamKeyerId: number + public readonly mixEffect: number + public readonly upstreamKeyerId: number constructor (mixEffect: number, upstreamKeyerId: number, onAir: boolean) { super({ onAir }) @@ -15,7 +15,7 @@ export class MixEffectKeyOnAirCommand extends BasicWritableCommand<{ onAir: bool this.upstreamKeyerId = upstreamKeyerId } - serialize () { + public serialize () { const buffer = Buffer.alloc(4) buffer.writeUInt8(this.mixEffect, 0) buffer.writeUInt8(this.upstreamKeyerId, 1) @@ -25,10 +25,10 @@ export class MixEffectKeyOnAirCommand extends BasicWritableCommand<{ onAir: bool } export class MixEffectKeyOnAirUpdateCommand extends DeserializedCommand<{onAir: boolean}> { - static readonly rawName = 'KeOn' + public static readonly rawName = 'KeOn' - readonly mixEffect: number - readonly upstreamKeyerId: number + public readonly mixEffect: number + public readonly upstreamKeyerId: number constructor (mixEffect: number, upstreamKeyerId: number, properties: MixEffectKeyOnAirUpdateCommand['properties']) { super(properties) @@ -37,7 +37,7 @@ export class MixEffectKeyOnAirUpdateCommand extends DeserializedCommand<{onAir: this.upstreamKeyerId = upstreamKeyerId } - static deserialize (rawCommand: Buffer) { + public static deserialize (rawCommand: Buffer) { const mixEffect = Util.parseNumberBetween(rawCommand[0], 0, 3) const upstreamKeyerId = Util.parseNumberBetween(rawCommand[1], 0, 3) const properties = { @@ -46,7 +46,7 @@ export class MixEffectKeyOnAirUpdateCommand extends DeserializedCommand<{onAir: return new MixEffectKeyOnAirUpdateCommand(mixEffect, upstreamKeyerId, properties) } - applyToState (state: AtemState) { + public applyToState (state: AtemState) { const mixEffect = state.video.getMe(this.mixEffect) const upstreamKeyer = mixEffect.getUpstreamKeyer(this.upstreamKeyerId) upstreamKeyer.onAir = this.properties.onAir diff --git a/src/commands/MixEffects/Key/MixEffectKeyPatternCommand.ts b/src/commands/MixEffects/Key/MixEffectKeyPatternCommand.ts index 9ab0dfd83..187fb6762 100644 --- a/src/commands/MixEffects/Key/MixEffectKeyPatternCommand.ts +++ b/src/commands/MixEffects/Key/MixEffectKeyPatternCommand.ts @@ -4,7 +4,7 @@ import { UpstreamKeyerPatternSettings } from '../../../state/video/upstreamKeyer import { Util, Enums } from '../../..' export class MixEffectKeyPatternCommand extends WritableCommand { - static MaskFlags = { + public static MaskFlags = { style: 1 << 0, size: 1 << 1, symmetry: 1 << 2, @@ -14,10 +14,10 @@ export class MixEffectKeyPatternCommand extends WritableCommand { - static readonly rawName = 'KePt' + public static readonly rawName = 'KePt' - readonly mixEffect: number - readonly upstreamKeyerId: number + public readonly mixEffect: number + public readonly upstreamKeyerId: number constructor (mixEffect: number, upstreamKeyerId: number, properties: UpstreamKeyerPatternSettings) { super(properties) @@ -57,7 +57,7 @@ export class MixEffectKeyUpdateCommand extends DeserializedCommand { - static readonly rawName = 'KeBP' + public static readonly rawName = 'KeBP' - readonly mixEffect: number + public readonly mixEffect: number constructor (mixEffect: number, properties: UpstreamKeyerBase) { super(properties) @@ -14,7 +14,7 @@ export class MixEffectKeyPropertiesGetCommand extends DeserializedCommand { - static MaskFlags = { + public static MaskFlags = { mixEffectKeyType: 1 << 0, flyEnabled: 1 << 1 } - static readonly rawName = 'CKTp' + public static readonly rawName = 'CKTp' - readonly mixEffect: number - readonly upstreamKeyerId: number + public readonly mixEffect: number + public readonly upstreamKeyerId: number constructor (mixEffect: number, upstreamKeyerId: number) { super() @@ -19,7 +19,7 @@ export class MixEffectKeyTypeSetCommand extends WritableCommand { - static readonly rawName = 'CPvI' + public static readonly rawName = 'CPvI' - readonly mixEffect: number + public readonly mixEffect: number constructor (mixEffect: number, source: number) { super({ source }) @@ -17,7 +17,7 @@ export class PreviewInputCommand extends BasicWritableCommand { this.mixEffect = mixEffect } - serialize () { + public serialize () { const buffer = Buffer.alloc(4) buffer.writeUInt8(this.mixEffect, 0) buffer.writeUInt16BE(this.properties.source, 2) @@ -26,9 +26,9 @@ export class PreviewInputCommand extends BasicWritableCommand { } export class PreviewInputUpdateCommand extends DeserializedCommand { - static readonly rawName = 'PrvI' + public static readonly rawName = 'PrvI' - readonly mixEffect: number + public readonly mixEffect: number constructor (mixEffect: number, properties: InputSource) { super(properties) @@ -36,7 +36,7 @@ export class PreviewInputUpdateCommand extends DeserializedCommand this.mixEffect = mixEffect } - static deserialize (rawCommand: Buffer): PreviewInputUpdateCommand { + public static deserialize (rawCommand: Buffer): PreviewInputUpdateCommand { const mixEffect = Util.parseNumberBetween(rawCommand[0], 0, 3) const properties = { source: rawCommand.readUInt16BE(2) @@ -45,7 +45,7 @@ export class PreviewInputUpdateCommand extends DeserializedCommand return new PreviewInputUpdateCommand(mixEffect, properties) } - applyToState (state: AtemState) { + public applyToState (state: AtemState) { const mixEffect = state.video.getMe(this.mixEffect) mixEffect.previewInput = this.properties.source return `video.ME.${this.mixEffect}.previewInput` diff --git a/src/commands/MixEffects/ProgramInputCommand.ts b/src/commands/MixEffects/ProgramInputCommand.ts index 2649b3bde..5a5bb7c9a 100644 --- a/src/commands/MixEffects/ProgramInputCommand.ts +++ b/src/commands/MixEffects/ProgramInputCommand.ts @@ -4,9 +4,9 @@ import { Util } from '../..' import { InputSource } from './PreviewInputCommand' export class ProgramInputCommand extends BasicWritableCommand { - static readonly rawName = 'CPgI' + public static readonly rawName = 'CPgI' - readonly mixEffect: number + public readonly mixEffect: number constructor (mixEffect: number, source: number) { super({ source }) @@ -14,7 +14,7 @@ export class ProgramInputCommand extends BasicWritableCommand { this.mixEffect = mixEffect } - serialize () { + public serialize () { const buffer = Buffer.alloc(4) buffer.writeUInt8(this.mixEffect, 0) buffer.writeUInt16BE(this.properties.source, 2) @@ -23,9 +23,9 @@ export class ProgramInputCommand extends BasicWritableCommand { } export class ProgramInputUpdateCommand extends DeserializedCommand { - static readonly rawName = 'PrgI' + public static readonly rawName = 'PrgI' - readonly mixEffect: number + public readonly mixEffect: number constructor (mixEffect: number, properties: InputSource) { super(properties) @@ -33,7 +33,7 @@ export class ProgramInputUpdateCommand extends DeserializedCommand this.mixEffect = mixEffect } - static deserialize (rawCommand: Buffer): ProgramInputUpdateCommand { + public static deserialize (rawCommand: Buffer): ProgramInputUpdateCommand { const mixEffect = Util.parseNumberBetween(rawCommand[0], 0, 3) const properties = { source: rawCommand.readUInt16BE(2) @@ -42,7 +42,7 @@ export class ProgramInputUpdateCommand extends DeserializedCommand return new ProgramInputUpdateCommand(mixEffect, properties) } - applyToState (state: AtemState) { + public applyToState (state: AtemState) { const mixEffect = state.video.getMe(this.mixEffect) mixEffect.programInput = this.properties.source return `video.ME.${this.mixEffect}.programInput` diff --git a/src/commands/MixEffects/Transition/TransitionDVECommand.ts b/src/commands/MixEffects/Transition/TransitionDVECommand.ts index 87fbe7c34..85511bfb5 100644 --- a/src/commands/MixEffects/Transition/TransitionDVECommand.ts +++ b/src/commands/MixEffects/Transition/TransitionDVECommand.ts @@ -4,7 +4,7 @@ import { DVETransitionSettings } from '../../../state/video' import { Util, Enums } from '../../..' export class TransitionDVECommand extends WritableCommand { - static MaskFlags = { + public static MaskFlags = { rate: 1 << 0, logoRate: 1 << 1, style: 1 << 2, @@ -19,9 +19,9 @@ export class TransitionDVECommand extends WritableCommand flipFlop: 1 << 11 } - static readonly rawName = 'CTDv' + public static readonly rawName = 'CTDv' - readonly mixEffect: number + public readonly mixEffect: number constructor (mixEffect: number) { super() @@ -29,7 +29,7 @@ export class TransitionDVECommand extends WritableCommand this.mixEffect = mixEffect } - serialize () { + public serialize () { const buffer = Buffer.alloc(20, 0) buffer.writeUInt16BE(this.flag, 0) @@ -54,9 +54,9 @@ export class TransitionDVECommand extends WritableCommand } export class TransitionDVEUpdateCommand extends DeserializedCommand { - static readonly rawName = 'TDvP' + public static readonly rawName = 'TDvP' - readonly mixEffect: number + public readonly mixEffect: number constructor (mixEffect: number, properties: DVETransitionSettings) { super(properties) @@ -64,7 +64,7 @@ export class TransitionDVEUpdateCommand extends DeserializedCommand { - static MaskFlags = { + public static MaskFlags = { rate: 1 << 0, input: 1 << 1 } - static readonly rawName = 'CTDp' + public static readonly rawName = 'CTDp' - readonly mixEffect: number + public readonly mixEffect: number constructor (mixEffect: number) { super() @@ -18,7 +18,7 @@ export class TransitionDipCommand extends WritableCommand this.mixEffect = mixEffect } - serialize () { + public serialize () { const buffer = Buffer.alloc(8) buffer.writeUInt8(this.flag, 0) buffer.writeUInt8(this.mixEffect, 1) @@ -29,9 +29,9 @@ export class TransitionDipCommand extends WritableCommand } export class TransitionDipUpdateCommand extends DeserializedCommand { - static readonly rawName = 'TDpP' + public static readonly rawName = 'TDpP' - readonly mixEffect: number + public readonly mixEffect: number constructor (mixEffect: number, properties: DipTransitionSettings) { super(properties) @@ -39,7 +39,7 @@ export class TransitionDipUpdateCommand extends DeserializedCommand { - static readonly rawName = 'CTMx' + public static readonly rawName = 'CTMx' - readonly mixEffect: number + public readonly mixEffect: number constructor (mixEffect: number, rate: number) { super({ rate }) @@ -14,7 +14,7 @@ export class TransitionMixCommand extends BasicWritableCommand { - static readonly rawName = 'TMxP' + public static readonly rawName = 'TMxP' - readonly mixEffect: number + public readonly mixEffect: number constructor (mixEffect: number, properties: MixTransitionSettings) { super(properties) @@ -33,7 +33,7 @@ export class TransitionMixUpdateCommand extends DeserializedCommand { - static readonly rawName = 'CTPs' + public static readonly rawName = 'CTPs' - readonly mixEffect: number + public readonly mixEffect: number constructor (mixEffect: number, handlePosition: number) { super({ handlePosition }) @@ -17,7 +17,7 @@ export class TransitionPositionCommand extends BasicWritableCommand { - static readonly rawName = 'TrPs' + public static readonly rawName = 'TrPs' - readonly mixEffect: number + public readonly mixEffect: number constructor (mixEffect: number, properties: TransitionPositionProps) { super(properties) @@ -41,7 +41,7 @@ export class TransitionPositionUpdateCommand extends DeserializedCommand { - static readonly rawName = 'CTPr' + public static readonly rawName = 'CTPr' - readonly mixEffect: number + public readonly mixEffect: number constructor (mixEffect: number, preview: boolean) { super({ preview }) @@ -17,7 +17,7 @@ export class PreviewTransitionCommand extends BasicWritableCommand this.mixEffect = mixEffect } - serialize () { + public serialize () { const buffer = Buffer.alloc(4) buffer.writeUInt8(this.mixEffect, 0) buffer.writeUInt8(this.properties.preview ? 1 : 0, 1) @@ -26,9 +26,9 @@ export class PreviewTransitionCommand extends BasicWritableCommand } export class PreviewTransitionUpdateCommand extends DeserializedCommand { - static readonly rawName = 'TrPr' + public static readonly rawName = 'TrPr' - readonly mixEffect: number + public readonly mixEffect: number constructor (mixEffect: number, properties: PreviewProps) { super(properties) @@ -36,7 +36,7 @@ export class PreviewTransitionUpdateCommand extends DeserializedCommand { - static MaskFlags = { + public static MaskFlags = { style: 1 << 0, selection: 1 << 1 } - static readonly rawName = 'CTTp' + public static readonly rawName = 'CTTp' - readonly mixEffect: number + public readonly mixEffect: number constructor (mixEffect: number) { super() @@ -19,7 +19,7 @@ export class TransitionPropertiesCommand extends WritableCommand { - static readonly rawName = 'TrSS' + public static readonly rawName = 'TrSS' - readonly mixEffect: number + public readonly mixEffect: number constructor (mixEffect: number, properties: TransitionProperties) { super(properties) @@ -42,7 +42,7 @@ export class TransitionPropertiesUpdateCommand extends DeserializedCommand(rawCommand[1], Enums.TransitionStyle),// rawCommand[1], @@ -54,7 +54,7 @@ export class TransitionPropertiesUpdateCommand extends DeserializedCommand { - static MaskFlags = { + public static MaskFlags = { source: 1 << 0, preMultipliedKey: 1 << 1, clip: 1 << 2, @@ -16,9 +16,9 @@ export class TransitionStingerCommand extends WritableCommand { - static readonly rawName = 'TStP' + public static readonly rawName = 'TStP' - readonly mixEffect: number + public readonly mixEffect: number constructor (mixEffect: number, properties: StingerTransitionSettings) { super(properties) @@ -58,7 +58,7 @@ export class TransitionStingerUpdateCommand extends DeserializedCommand { - static MaskFlags = { + public static MaskFlags = { rate: 1 << 0, pattern: 1 << 1, borderWidth: 1 << 2, @@ -17,9 +17,9 @@ export class TransitionWipeCommand extends WritableCommand { - static readonly rawName = 'TWpP' + public static readonly rawName = 'TWpP' - readonly mixEffect: number + public readonly mixEffect: number constructor (mixEffect: number, properties: WipeTransitionSettings) { super(properties) @@ -60,7 +60,7 @@ export class TransitionWipeUpdateCommand extends DeserializedCommand { - static readonly rawName = 'Powr' + public static readonly rawName = 'Powr' - static deserialize (rawCommand: Buffer): PowerStatusCommand { + public static deserialize (rawCommand: Buffer): PowerStatusCommand { const properties = [ Boolean(rawCommand[0] & 1 << 0), Boolean(rawCommand[0] & 1 << 1) @@ -18,7 +18,7 @@ export class PowerStatusCommand extends DeserializedCommand { return new PowerStatusCommand(properties) } - applyToState (state: AtemState) { + public applyToState (state: AtemState) { const count = state.info.power.length state.info.power = this.properties.slice(0, count) return `info.power` diff --git a/src/commands/Settings/MultiViewerSourceCommand.ts b/src/commands/Settings/MultiViewerSourceCommand.ts index ce5821721..54c37df67 100644 --- a/src/commands/Settings/MultiViewerSourceCommand.ts +++ b/src/commands/Settings/MultiViewerSourceCommand.ts @@ -3,9 +3,9 @@ import { AtemState } from '../../state' import { MultiViewerSourceState } from '../../state/settings' export class MultiViewerSourceCommand extends WritableCommand { - static readonly rawName = 'CMvI' + public static readonly rawName = 'CMvI' - readonly multiViewerId: number + public readonly multiViewerId: number constructor (multiviewerId: number) { super() @@ -13,7 +13,7 @@ export class MultiViewerSourceCommand extends WritableCommand { - static readonly rawName = 'MvIn' + public static readonly rawName = 'MvIn' - readonly multiViewerId: number + public readonly multiViewerId: number constructor (multiviewerId: number, properties: MultiViewerSourceState) { super(properties) @@ -33,7 +33,7 @@ export class MultiViewerSourceUpdateCommand extends DeserializedCommand { - static readonly rawName = 'CVdM' + public static readonly rawName = 'CVdM' constructor (mode: Enums.VideoMode) { super({ mode }) } - serialize () { + public serialize () { const buffer = Buffer.alloc(4) buffer.writeUInt8(this.properties.mode, 0) return buffer @@ -21,17 +21,17 @@ export class VideoModeCommand extends BasicWritableCommand { } export class VideoModeUpdateCommand extends DeserializedCommand { - static readonly rawName = 'VidM' + public static readonly rawName = 'VidM' constructor (mode: Enums.VideoMode) { super({ mode }) } - static deserialize (rawCommand: Buffer): VideoModeUpdateCommand { + public static deserialize (rawCommand: Buffer): VideoModeUpdateCommand { return new VideoModeUpdateCommand(rawCommand[0]) } - applyToState (state: AtemState) { + public applyToState (state: AtemState) { state.settings.videoMode = this.properties.mode return `settings.videoMode` } diff --git a/src/commands/SuperSource/SuperSourceBoxParametersCommand.ts b/src/commands/SuperSource/SuperSourceBoxParametersCommand.ts index 135c4e424..52cb6994c 100644 --- a/src/commands/SuperSource/SuperSourceBoxParametersCommand.ts +++ b/src/commands/SuperSource/SuperSourceBoxParametersCommand.ts @@ -5,7 +5,7 @@ import { Util } from '../..' import { ProtocolVersion } from '../../enums' export class SuperSourceBoxParametersCommand extends WritableCommand { - static MaskFlags = { + public static MaskFlags = { enabled: 1 << 0, source: 1 << 1, x: 1 << 2, @@ -18,10 +18,10 @@ export class SuperSourceBoxParametersCommand extends WritableCommand= ProtocolVersion.V8_0) { @@ -57,10 +57,10 @@ export class SuperSourceBoxParametersCommand extends WritableCommand { - static readonly rawName = 'SSBP' + public static readonly rawName = 'SSBP' - readonly ssrcId: number - readonly boxId: number + public readonly ssrcId: number + public readonly boxId: number constructor (ssrcId: number, boxId: number, properties: SuperSourceBox) { super(properties) @@ -69,7 +69,7 @@ export class SuperSourceBoxParametersUpdateCommand extends DeserializedCommand= ProtocolVersion.V8_0) { @@ -94,7 +94,7 @@ export class SuperSourceBoxParametersUpdateCommand extends DeserializedCommand { - static MaskFlags = { + public static MaskFlags = { artFillSource: 1 << 0, artCutSource: 1 << 1, artOption: 1 << 2, @@ -28,13 +28,13 @@ export class SuperSourcePropertiesCommand extends WritableCommand { - static MaskFlags = { + public static MaskFlags = { artFillSource: 1 << 0, artCutSource: 1 << 1, artOption: 1 << 2, @@ -75,10 +75,10 @@ export class SuperSourcePropertiesV8Command extends WritableCommand { - static MaskFlags = { + public static MaskFlags = { borderEnabled: 1 << 0, borderBevel: 1 << 1, borderOuterWidth: 1 << 2, @@ -121,10 +121,10 @@ export class SuperSourceBorderCommand extends WritableCommand borderLightSourceAltitude: 1 << 12 } - static readonly rawName = 'CSBd' - static readonly minimumVersion = ProtocolVersion.V8_0 + public static readonly rawName = 'CSBd' + public static readonly minimumVersion = ProtocolVersion.V8_0 - readonly ssrcId: number + public readonly ssrcId: number constructor (ssrcId: number) { super() @@ -132,7 +132,7 @@ export class SuperSourceBorderCommand extends WritableCommand this.ssrcId = ssrcId } - serialize () { + public serialize () { const buffer = Buffer.alloc(24) buffer.writeUInt16BE(this.flag, 0) @@ -157,9 +157,9 @@ export class SuperSourceBorderCommand extends WritableCommand } export class SuperSourcePropertiesUpdateCommand extends DeserializedCommand<{ properties: SuperSourceProperties, border: SuperSourceBorder }> { - static readonly rawName = 'SSrc' + public static readonly rawName = 'SSrc' - static deserialize (rawCommand: Buffer): SuperSourcePropertiesUpdateCommand { + public static deserialize (rawCommand: Buffer): SuperSourcePropertiesUpdateCommand { const properties = { properties: { artFillSource: rawCommand.readUInt16BE(0), @@ -191,7 +191,7 @@ export class SuperSourcePropertiesUpdateCommand extends DeserializedCommand<{ pr return new SuperSourcePropertiesUpdateCommand(properties) } - applyToState (state: AtemState) { + public applyToState (state: AtemState) { const supersource = state.video.getSuperSource(0) supersource.properties = this.properties.properties supersource.border = this.properties.border @@ -203,10 +203,10 @@ export class SuperSourcePropertiesUpdateCommand extends DeserializedCommand<{ pr } export class SuperSourcePropertiesUpdateV8Command extends DeserializedCommand { - static readonly rawName = 'SSrc' - static readonly minimumVersion = ProtocolVersion.V8_0 + public static readonly rawName = 'SSrc' + public static readonly minimumVersion = ProtocolVersion.V8_0 - readonly ssrcId: number + public readonly ssrcId: number constructor (ssrcId: number, properties: SuperSourceProperties) { super(properties) @@ -214,7 +214,7 @@ export class SuperSourcePropertiesUpdateV8Command extends DeserializedCommand { - static readonly rawName = 'SSBd' - static readonly minimumVersion = ProtocolVersion.V8_0 + public static readonly rawName = 'SSBd' + public static readonly minimumVersion = ProtocolVersion.V8_0 - readonly ssrcId: number + public readonly ssrcId: number constructor (ssrcId: number, properties: SuperSourceBorder) { super(properties) @@ -250,7 +250,7 @@ export class SuperSourceBorderUpdateCommand extends DeserializedCommand { - static readonly rawName = 'TlSr' + public static readonly rawName = 'TlSr' - static deserialize (rawCommand: Buffer) { + public static deserialize (rawCommand: Buffer) { const sourceCount = rawCommand.readUInt16BE(0) const sources: TallyBySourceProps = {} @@ -24,7 +24,7 @@ export class TallyBySourceCommand extends DeserializedCommand this.queueCommand(cmd)) } } - lostLock () { + public lostLock () { this.isLocked = false if (this.activeTransfer) { if (this.activeTransfer.state === Enums.TransferState.Finished) { @@ -61,15 +61,15 @@ export default class DataLock { this.dequeueAndRun() } - updateLock (locked: boolean) { + public updateLock (locked: boolean) { this.isLocked = locked } - transferFinished () { + public transferFinished () { this.queueCommand(new Commands.LockStateCommand(this.storeId, false)) } - transferErrored (code: number) { + public transferErrored (code: number) { if (this.activeTransfer) { switch (code) { case 1: // Probably means "retry". diff --git a/src/dataTransfer/dataTransfer.ts b/src/dataTransfer/dataTransfer.ts index 3b8696561..45982f7d0 100644 --- a/src/dataTransfer/dataTransfer.ts +++ b/src/dataTransfer/dataTransfer.ts @@ -1,15 +1,15 @@ import { Commands, Enums } from '..' export default abstract class DataTransfer { - state: Enums.TransferState = Enums.TransferState.Queued - readonly transferId: number - readonly storeId: number + public state: Enums.TransferState = Enums.TransferState.Queued + public readonly transferId: number + public readonly storeId: number // commandQueue: Array private readonly completionPromise: Promise - resolvePromise: (value?: DataTransfer | PromiseLike | undefined) => void - rejectPromise: (reason?: any) => void + public resolvePromise: (value?: DataTransfer | PromiseLike | undefined) => void + public rejectPromise: (reason?: any) => void constructor (transferId: number, storeId: number) { this.transferId = transferId @@ -31,8 +31,8 @@ export default abstract class DataTransfer { return this.completionPromise } - abstract start (): Commands.ISerializableCommand[] + public abstract start (): Commands.ISerializableCommand[] - abstract handleCommand (command: Commands.IDeserializedCommand): Commands.ISerializableCommand[] - abstract gotLock (): Commands.ISerializableCommand[] + public abstract handleCommand (command: Commands.IDeserializedCommand): Commands.ISerializableCommand[] + public abstract gotLock (): Commands.ISerializableCommand[] } diff --git a/src/dataTransfer/dataTransferAudio.ts b/src/dataTransfer/dataTransferAudio.ts index 9c8f0000a..e2403328f 100644 --- a/src/dataTransfer/dataTransferAudio.ts +++ b/src/dataTransfer/dataTransferAudio.ts @@ -3,7 +3,7 @@ import { Commands, Enums } from '..' import DataTransferFrame from './dataTransferFrame' export default class DataTransferAudio extends DataTransferFrame { - readonly name: string + public readonly name: string constructor (transferId: number, storeId: number, data: Buffer, name: string) { super(transferId, storeId, 0, data) diff --git a/src/dataTransfer/dataTransferClip.ts b/src/dataTransfer/dataTransferClip.ts index 0a7e2f387..44d8b2167 100644 --- a/src/dataTransfer/dataTransferClip.ts +++ b/src/dataTransfer/dataTransferClip.ts @@ -4,10 +4,10 @@ import DataTransfer from './dataTransfer' import DataTransferFrame from './dataTransferFrame' export default class DataTransferClip extends DataTransfer { - readonly clipIndex: number // 0 or 1 - readonly frames: Array - curFrame = 0 - readonly name: string + public readonly clipIndex: number // 0 or 1 + public readonly frames: Array + public readonly name: string + public curFrame = 0 constructor (clipIndex: number, name: string, frames: Array) { super(0, 1 + clipIndex) diff --git a/src/dataTransfer/dataTransferFrame.ts b/src/dataTransfer/dataTransferFrame.ts index 88094237f..a644f6590 100644 --- a/src/dataTransfer/dataTransferFrame.ts +++ b/src/dataTransfer/dataTransferFrame.ts @@ -4,12 +4,12 @@ import * as crypto from 'crypto' import DataTransfer from './dataTransfer' export default class DataTransferFrame extends DataTransfer { - readonly frameId: number - readonly hash: string - readonly data: Buffer + public readonly frameId: number + public readonly hash: string + public readonly data: Buffer - lastSent?: Date - _sent = 0 + private lastSent?: Date + private _sent = 0 constructor (transferId: number, storeId: number, frameId: number, data: Buffer) { super(transferId, storeId) diff --git a/src/lib/atemCommandParser.ts b/src/lib/atemCommandParser.ts index 9ba0cbe9d..28b6839d0 100644 --- a/src/lib/atemCommandParser.ts +++ b/src/lib/atemCommandParser.ts @@ -3,8 +3,8 @@ import { ProtocolVersion } from '../enums' type CommandConstructor = any export class CommandParser { - commands: {[key: string]: Array} = {} - version: ProtocolVersion = ProtocolVersion.V7_2 // Default to the minimum supported + public readonly commands: {[key: string]: Array} = {} + public version: ProtocolVersion = ProtocolVersion.V7_2 // Default to the minimum supported constructor () { for (const cmd in Commands) { @@ -21,7 +21,7 @@ export class CommandParser { } } - commandFromRawName (name: string): CommandConstructor | undefined { + public commandFromRawName (name: string): CommandConstructor | undefined { const commands = this.commands[name] if (commands) { if (!this.version) { // edge case for the version command itself: diff --git a/src/state/audio.ts b/src/state/audio.ts index d08203cb4..bcaf0b608 100644 --- a/src/state/audio.ts +++ b/src/state/audio.ts @@ -1,7 +1,7 @@ import { AudioSourceType, ExternalPortType, AudioMixOption } from '../enums' export interface AudioChannel { - sourceType: AudioSourceType + readonly sourceType: AudioSourceType portType: ExternalPortType mixOption: AudioMixOption /** Gain in decibel, -Infinity to +6dB */ @@ -19,8 +19,8 @@ export interface AudioMasterChannel { } export class AtemAudioState { - numberOfChannels?: number - hasMonitor?: boolean - channels: Array = [] - master?: AudioMasterChannel + public numberOfChannels?: number + public hasMonitor?: boolean + public channels: Array = [] + public master?: AudioMasterChannel } diff --git a/src/state/index.ts b/src/state/index.ts index f6caae3fe..10e809eac 100644 --- a/src/state/index.ts +++ b/src/state/index.ts @@ -7,11 +7,11 @@ import { MacroState } from './macro' import { SettingsState } from './settings' export class AtemState { - info = new DeviceInfo() - video: AtemVideoState = new AtemVideoState() - audio: AtemAudioState = new AtemAudioState() - media: MediaState = new MediaState() - inputs: Array = [] - macro: MacroState = new MacroState() - settings: SettingsState = new SettingsState() + public info = new DeviceInfo() + public video: AtemVideoState = new AtemVideoState() + public audio: AtemAudioState = new AtemAudioState() + public media: MediaState = new MediaState() + public inputs: Array = [] + public macro: MacroState = new MacroState() + public settings: SettingsState = new SettingsState() } diff --git a/src/state/info.ts b/src/state/info.ts index eb96d7644..7b055fc03 100644 --- a/src/state/info.ts +++ b/src/state/info.ts @@ -21,10 +21,10 @@ export interface SuperSourceInfo { } export class DeviceInfo { - apiVersion: ProtocolVersion = 0 - capabilities?: AtemCapabilites - model: Model = Model.Unknown - productIdentifier?: string - superSources: SuperSourceInfo[] = [] - power: boolean[] = [] + public apiVersion: ProtocolVersion = 0 + public capabilities?: AtemCapabilites + public model: Model = Model.Unknown + public productIdentifier?: string + public superSources: SuperSourceInfo[] = [] + public power: boolean[] = [] } diff --git a/src/state/macro.ts b/src/state/macro.ts index 21459fb82..3f63db28b 100644 --- a/src/state/macro.ts +++ b/src/state/macro.ts @@ -18,9 +18,9 @@ export interface MacroPropertiesState { } export class MacroState { - macroPlayer: MacroPlayerState - macroRecorder: MacroRecorderState - macroProperties: Array = [] + public readonly macroPlayer: MacroPlayerState + public readonly macroRecorder: MacroRecorderState + public readonly macroProperties: Array = [] constructor () { this.macroPlayer = { diff --git a/src/state/media.ts b/src/state/media.ts index 6ae9349c2..0dee9858d 100644 --- a/src/state/media.ts +++ b/src/state/media.ts @@ -16,11 +16,11 @@ export interface MediaPlayerSource { export type MediaPlayerState = MediaPlayer & MediaPlayerSource export class MediaState { - stillPool: Array = [] - clipPool: Array = [] - players: Array = [] + public readonly stillPool: Array = [] + public readonly clipPool: Array = [] + public readonly players: Array = [] - getMediaPlayer (index: number, dontCreate?: boolean): MediaPlayerState { + public getMediaPlayer (index: number, dontCreate?: boolean): MediaPlayerState { let player = this.players[index] if (!player) { player = { @@ -41,7 +41,7 @@ export class MediaState { return player } - getClip (index: number): ClipBank { + public getClip (index: number): ClipBank { const clip = this.clipPool[index] if (!clip) { return this.clipPool[index] = { diff --git a/src/state/settings.ts b/src/state/settings.ts index e94176030..e391ecc5e 100644 --- a/src/state/settings.ts +++ b/src/state/settings.ts @@ -10,8 +10,8 @@ export interface MultiViewerWindowState extends MultiViewerSourceState { } export class MultiViewer { - index: number - windows: { [index: string]: MultiViewerWindowState | undefined } = {} + public readonly index: number + public readonly windows: { [index: string]: MultiViewerWindowState | undefined } = {} constructor (index: number) { this.index = index @@ -19,14 +19,14 @@ export class MultiViewer { } export class SettingsState { - multiViewers: { [index: string]: MultiViewer | undefined } = {} - videoMode: number + public readonly multiViewers: { [index: string]: MultiViewer | undefined } = {} + public videoMode: number constructor () { this.videoMode = 0 } - getMultiViewer (index: number): MultiViewer { + public getMultiViewer (index: number): MultiViewer { const multiViewer = this.multiViewers[index] if (!multiViewer) { return this.multiViewers[index] = new MultiViewer(index) diff --git a/src/state/video/index.ts b/src/state/video/index.ts index 0298e3f92..baf1d49b5 100644 --- a/src/state/video/index.ts +++ b/src/state/video/index.ts @@ -84,18 +84,18 @@ export interface IMixEffect { } export class MixEffect implements IMixEffect { - index: number - programInput: number = 0 - previewInput: number = 0 - inTransition: boolean = false - transitionPreview: boolean = false - transitionPosition: number = 0 - transitionFramesLeft: number = 0 - fadeToBlack?: FadeToBlackProperties - numberOfKeyers: number = 0 - transitionProperties: TransitionProperties - transitionSettings: TransitionSettings = {} - upstreamKeyers: Array = [] + public readonly index: number + public programInput: number = 0 + public previewInput: number = 0 + public inTransition: boolean = false + public transitionPreview: boolean = false + public transitionPosition: number = 0 + public transitionFramesLeft: number = 0 + public fadeToBlack?: FadeToBlackProperties + public numberOfKeyers: number = 0 + public readonly transitionProperties: TransitionProperties + public readonly transitionSettings: TransitionSettings = {} + public readonly upstreamKeyers: Array = [] constructor (index: number) { this.index = index @@ -108,7 +108,7 @@ export class MixEffect implements IMixEffect { } } - getUpstreamKeyer (index: number, dontCreate?: boolean): USK.UpstreamKeyer { + public getUpstreamKeyer (index: number, dontCreate?: boolean): USK.UpstreamKeyer { let usk = this.upstreamKeyers[index] if (!usk) { usk = { @@ -170,10 +170,10 @@ export interface SuperSourceBorder { } export class SuperSource { - index: number - boxes: [SuperSourceBox | undefined, SuperSourceBox | undefined, SuperSourceBox | undefined, SuperSourceBox | undefined] - properties?: SuperSourceProperties - border?: SuperSourceBorder + public readonly index: number + public readonly boxes: [SuperSourceBox | undefined, SuperSourceBox | undefined, SuperSourceBox | undefined, SuperSourceBox | undefined] + public properties?: SuperSourceProperties + public border?: SuperSourceBorder constructor (index: number) { this.index = index @@ -192,12 +192,12 @@ export interface FadeToBlackProperties { } export class AtemVideoState { - ME: Array = [] - downstreamKeyers: Array = [] - auxilliaries: Array = [] - superSources: Array = [] + public readonly ME: Array = [] + public readonly downstreamKeyers: Array = [] + public readonly auxilliaries: Array = [] + public readonly superSources: Array = [] - getMe (index: number, dontCreate?: boolean): MixEffect { + public getMe (index: number, dontCreate?: boolean): MixEffect { let me = this.ME[index] if (!me) { me = new MixEffect(index) @@ -210,7 +210,7 @@ export class AtemVideoState { return me } - getSuperSource (index: number, dontCreate?: boolean): SuperSource { + public getSuperSource (index: number, dontCreate?: boolean): SuperSource { let ssrc = this.superSources[index] if (!ssrc) { ssrc = new SuperSource(index) @@ -223,7 +223,7 @@ export class AtemVideoState { return ssrc } - getDownstreamKeyer (index: number, dontCreate?: boolean): DownstreamKeyer { + public getDownstreamKeyer (index: number, dontCreate?: boolean): DownstreamKeyer { let dsk = this.downstreamKeyers[index] if (!dsk) { dsk = { diff --git a/src/state/video/upstreamKeyers.ts b/src/state/video/upstreamKeyers.ts index 3d0ed63e8..12e046995 100644 --- a/src/state/video/upstreamKeyers.ts +++ b/src/state/video/upstreamKeyers.ts @@ -50,7 +50,7 @@ export interface UpstreamKeyerDVESettings extends UpstreamKeyerDVEBase { } export interface UpstreamKeyerFlyKeyframe extends UpstreamKeyerDVEBase { - keyFrameId: number + readonly keyFrameId: number } export interface UpstreamKeyerChromaSettings { diff --git a/tslint.json b/tslint.json index 8193aca6b..341511530 100644 --- a/tslint.json +++ b/tslint.json @@ -8,6 +8,7 @@ "ter-indent": [true, "tab",{ "SwitchCase": 1 }], - "prefer-const": true + "prefer-const": true, + "member-access": true } } From cb255fb0294c28d0fea1ef9165574afc9738eb84 Mon Sep 17 00:00:00 2001 From: Julian Waller Date: Sun, 1 Dec 2019 18:18:59 +0000 Subject: [PATCH 14/68] fix: tidying --- .gitignore | 2 + examples/upload.ts | 52 +++++--------------------- src/__tests__/util.ts | 9 +++-- src/atem.ts | 23 ++++-------- src/dataTransfer/dataLock.ts | 1 + src/dataTransfer/dataTransferFrame.ts | 2 - src/enums/index.ts | 5 +-- src/lib/__mocks__/dgram.ts | 3 +- src/lib/__tests__/socket-child.spec.ts | 4 +- src/lib/atemSocket.ts | 3 +- src/lib/atemSocketChild.ts | 25 +++++++++---- src/state/macro.ts | 4 +- src/state/video/index.ts | 4 +- 13 files changed, 56 insertions(+), 81 deletions(-) diff --git a/.gitignore b/.gitignore index fa5f86d08..0e5b35441 100644 --- a/.gitignore +++ b/.gitignore @@ -14,3 +14,5 @@ wallaby.conf.js # JetBrains IDE project files /.idea + +testframe.rgba diff --git a/examples/upload.ts b/examples/upload.ts index 561b30c45..d3fc29082 100644 --- a/examples/upload.ts +++ b/examples/upload.ts @@ -1,8 +1,7 @@ import { Atem } from '../dist' import * as fs from 'fs' -const file = fs.readFileSync('./stress/amsterdam.rgba') -// const file = fs.readFileSync('./testframe.rgba') +const file = fs.readFileSync('./testframe.rgba') if (process.argv.length < 3) { console.error('Expected ip address as parameter') @@ -10,30 +9,19 @@ if (process.argv.length < 3) { } const IP = process.argv[2] -let upload = 0 -let t = Date.now() +let uploadNumber = 0 +let uploadStarted = Date.now() const conn = new Atem({ debug: false }) let stuckTimeout: any = null -async function uploadNext () { - // if (upload >= MAX_POOL) { - // return - // } - // console.log('item ', upload) - t = Date.now() - conn.uploadStill(upload % conn.state.media.stillPool.length, file, 'contemplation..', '') - // conn.uploadStill(upload, file, 'TEST FRAME', '') +function uploadNext () { + uploadStarted = Date.now() + conn.uploadStill(uploadNumber % conn.state.media.stillPool.length, file, 'contemplation..', '') .then(async (_res) => { - console.log(`Uploaded still #${upload} in ${Date.now() - t}ms at 1080p`) - // console.log('queue len', conn.dataTransferManager.commandQueue.length) - // console.log(conn.state.media.stillPool) - upload++ - // if (upload % 2 === 0) { - // await reconnect() - // console.log('reconnected') - // } + console.log(`Uploaded still #${uploadNumber} in ${Date.now() - uploadStarted}ms at 1080p`) + uploadNumber++ if (stuckTimeout) { clearTimeout(stuckTimeout) @@ -42,14 +30,8 @@ async function uploadNext () { console.log('') console.log('UPLOAD GOT STUCK') console.log('') - console.log('') - // console.log(JSON.stringify(conn.state, undefined, 4)) - console.log('') + const dt = (conn as any).dataTransferManager - // console.log(JSON.stringify({ - // stills: dt.stillsLock, - // clips: dt.clipLocks - // }, undefined, 4)) fs.writeFileSync('upload-stuck', JSON.stringify({ stills: dt.stillsLock, clips: dt.clipLocks @@ -57,23 +39,12 @@ async function uploadNext () { }, 20000) setTimeout(() => uploadNext(), 0) - // uploadNext() }, (e) => { console.log('e', e) setTimeout(() => uploadNext(), 500) - // console.log('retry') - // setTimeout(() => uploadNext(), 0) }) } -// async function uploadInf () { -// while (true) { -// if (upload > 0) console.log(`Uploaded ${upload} in ${Date.now() - t}, is ${(Date.now() - t) / upload} at 720p`) -// await conn.dataTransferManager.uploadStill(upload % MAX_POOL, file, 'TEST FRAME ' + upload, '').catch((e) => console.log('e', e)) -// upload++ -// } -// } - conn.on('error', console.log) conn.on('disconnected', () => { console.log('Connection lost') @@ -81,9 +52,6 @@ conn.on('disconnected', () => { }) conn.connect(IP) conn.once('connected', () => { - console.log(`connected in ${Date.now() - t}ms`) - t = Date.now() + console.log(`connected in ${Date.now() - uploadStarted}ms`) uploadNext() - // console.log(conn.state.media) - }) diff --git a/src/__tests__/util.ts b/src/__tests__/util.ts index ad7a644e6..3addca7fe 100644 --- a/src/__tests__/util.ts +++ b/src/__tests__/util.ts @@ -12,10 +12,11 @@ function parseAudio (rawState: AtemAudioState) { } function parseVideo (rawState: AtemVideoState) { - const state = plainToClass(AtemVideoState, rawState) - state.ME = state.ME.map(me => plainToClass(MixEffect, me)) - state.superSources = state.superSources.map(ssrc => plainToClass(SuperSource, ssrc)) - return state + return plainToClass(AtemVideoState, { + ...rawState, + ME: rawState.ME.map(me => plainToClass(MixEffect, me)), + superSources: rawState.superSources.map(ssrc => plainToClass(SuperSource, ssrc)) + }) } /** Note: This is incomplete, and should be filled in as needed */ diff --git a/src/atem.ts b/src/atem.ts index 50e5073e0..540516043 100644 --- a/src/atem.ts +++ b/src/atem.ts @@ -40,18 +40,14 @@ interface SentCommand { reject: (cmd: ISerializableCommand) => void } -export class Atem extends EventEmitter { - public DEFAULT_PORT = 9910 - public RECONNECT_INTERVAL = 5000 - public DEBUG = false - - public AUDIO_GAIN_RATE = 65381 +export const DEFAULT_PORT = 9910 - private _state: AtemState - private socket: AtemSocket - private dataTransferManager: DT.DataTransferManager - private _log: (...args: any[]) => void - private _sentQueue: {[packetId: string]: SentCommand } = {} +export class Atem extends EventEmitter { + private readonly socket: AtemSocket + private readonly _state: AtemState + private readonly dataTransferManager: DT.DataTransferManager + private readonly _log: (...args: any[]) => void + private readonly _sentQueue: {[packetId: string]: SentCommand } = {} public on!: ((event: 'error', listener: (message: any) => void) => this) & ((event: 'connected', listener: () => void) => this) & @@ -61,16 +57,13 @@ export class Atem extends EventEmitter { constructor (options?: AtemOptions) { super() - if (options) { - this.DEBUG = options.debug === undefined ? false : options.debug - } this._log = (options && options.externalLog) || function (...args: any[]): void { console.log(...args) } this._state = new AtemState() this.socket = new AtemSocket({ - debug: this.DEBUG, + debug: (options || {}).debug, log: this._log, address: (options || {}).address, port: (options || {}).port diff --git a/src/dataTransfer/dataLock.ts b/src/dataTransfer/dataLock.ts index 2e3813d33..2a2adf10a 100644 --- a/src/dataTransfer/dataLock.ts +++ b/src/dataTransfer/dataLock.ts @@ -32,6 +32,7 @@ export default class DataLock { this.activeTransfer = this.taskQueue.shift() if (this.isLocked) { + // TODO - this flow should never be hit this.lockObtained() } else { this.queueCommand(new Commands.LockStateCommand(this.storeId, true)) diff --git a/src/dataTransfer/dataTransferFrame.ts b/src/dataTransfer/dataTransferFrame.ts index a644f6590..7d86933db 100644 --- a/src/dataTransfer/dataTransferFrame.ts +++ b/src/dataTransfer/dataTransferFrame.ts @@ -8,7 +8,6 @@ export default class DataTransferFrame extends DataTransfer { public readonly hash: string public readonly data: Buffer - private lastSent?: Date private _sent = 0 constructor (transferId: number, storeId: number, frameId: number, data: Buffer) { @@ -60,7 +59,6 @@ export default class DataTransferFrame extends DataTransfer { const commands: Commands.ISerializableCommand[] = [] chunkSize += -4 - this.lastSent = new Date() for (let i = 0; i < chunkCount; i++) { if (this._sent > this.data.length) break diff --git a/src/enums/index.ts b/src/enums/index.ts index bd40f3fa7..afa43d174 100644 --- a/src/enums/index.ts +++ b/src/enums/index.ts @@ -33,10 +33,9 @@ export enum TallyState { } export enum ConnectionState { - None = 0x00, + Closed = 0x00, SynSent = 0x01, - Established = 0x02, - Closed = 0x03 + Established = 0x02 } export enum PacketFlag { diff --git a/src/lib/__mocks__/dgram.ts b/src/lib/__mocks__/dgram.ts index cb821ebae..424edbea4 100644 --- a/src/lib/__mocks__/dgram.ts +++ b/src/lib/__mocks__/dgram.ts @@ -1,6 +1,7 @@ import { EventEmitter } from 'events' import { SocketType, RemoteInfo } from 'dgram' import 'jest-extended' +import { DEFAULT_PORT } from '../../atem' export class Socket extends EventEmitter { public isOpen: boolean = false @@ -19,7 +20,7 @@ export class Socket extends EventEmitter { const rinfo: RemoteInfo = { address: this.expectedAddress || '127.0.0.1', - port: this.expectedPort || 9910, + port: this.expectedPort || DEFAULT_PORT, family: 'IPv4', size: msg.length } diff --git a/src/lib/__tests__/socket-child.spec.ts b/src/lib/__tests__/socket-child.spec.ts index e1e5a79bb..03630d674 100644 --- a/src/lib/__tests__/socket-child.spec.ts +++ b/src/lib/__tests__/socket-child.spec.ts @@ -4,6 +4,7 @@ import { AtemSocketChild } from '../atemSocketChild' import { Util } from '../..' import * as lolex from 'lolex' import { ConnectionState, PacketFlag, IPCMessageType } from '../../enums' +import { DEFAULT_PORT } from '../../atem' const ADDRESS = '127.0.0.1' @@ -12,7 +13,7 @@ function getSocket (child: AtemSocketChild) { expect(socket).toBeTruthy() expect(socket.isOpen).toBeTruthy() socket.expectedAddress = ADDRESS - socket.expectedPort = 9910 + socket.expectedPort = DEFAULT_PORT return socket } @@ -483,7 +484,6 @@ describe('SocketChild', () => { expect(getInflightIds(child)).toEqual([32764, 32765, 32766, 32767, 0, 1]) expect(acked).toEqual([]) - // TODO - and the remainder of this is very very broken.. // Ack a couple socket.emitMessage(genAckCommandMessage(32766)) expect(getInflightIds(child)).toEqual([32767, 0, 1]) diff --git a/src/lib/atemSocket.ts b/src/lib/atemSocket.ts index 47a84e031..65b470165 100644 --- a/src/lib/atemSocket.ts +++ b/src/lib/atemSocket.ts @@ -6,12 +6,13 @@ import { IPCMessageType } from '../enums' import exitHook = require('exit-hook') import { Util } from './atemUtil' import { VersionCommand, ISerializableCommand, IDeserializedCommand } from '../commands' +import { DEFAULT_PORT } from '../atem' export class AtemSocket extends EventEmitter { private _debug = false private _nextCommandTrackingId = 0 private _address: string - private _port: number = 9910 + private _port: number = DEFAULT_PORT private _shouldConnect = false private _socketProcess: ChildProcess | null private _commandParser: CommandParser = new CommandParser() diff --git a/src/lib/atemSocketChild.ts b/src/lib/atemSocketChild.ts index e3a4c8c2e..1b0f0a083 100644 --- a/src/lib/atemSocketChild.ts +++ b/src/lib/atemSocketChild.ts @@ -3,9 +3,11 @@ import { EventEmitter } from 'events' import { Util } from './atemUtil' import { ConnectionState, IPCMessageType, PacketFlag } from '../enums' import * as NanoTimer from 'nanotimer' +import { DEFAULT_PORT } from '../atem' const IN_FLIGHT_TIMEOUT = 30 // ms -const RECONNECT_INTERVAL = 5000 // ms +const CONNECTION_TIMEOUT = 5000 // ms +const CONNECTION_RETRY_INTERVAL = 1000 // ms const MAX_PACKET_RETRIES = 5 const MAX_PACKET_ID = (1 << 15) // Atem expects 15 not 16 bits before wrapping const MAX_PACKET_PER_ACK = 16 @@ -29,7 +31,7 @@ export class AtemSocketChild extends EventEmitter { private _sessionId: number = 0 private _address: string - private _port: number = 9910 + private _port: number = DEFAULT_PORT private _socket: Socket private _lastReceivedAt: number = Date.now() @@ -61,19 +63,28 @@ export class AtemSocketChild extends EventEmitter { public connect (address?: string, port?: number): void { if (!this._reconnectTimer) { this._reconnectTimer = setInterval(() => { - if (this._lastReceivedAt + RECONNECT_INTERVAL > Date.now()) return + if (this._lastReceivedAt + CONNECTION_TIMEOUT > Date.now()) { + // We heard from the atem recently + return + } + + // This includes a 'disconnect' if (this._connectionState === ConnectionState.Established) { this._connectionState = ConnectionState.Closed this.emit(IPCMessageType.Disconnect) } + + // Reset connection this._nextSendPacketId = 1 this._sessionId = 0 this.log('reconnect') + + // Try doing reconnect if (this._address && this._port) { this._sendPacket(Util.COMMAND_CONNECT_HELLO) this._connectionState = ConnectionState.SynSent } - }, RECONNECT_INTERVAL) + }, CONNECTION_RETRY_INTERVAL) } // Check for retransmits every 10 milliseconds if (!this._retransmitTimer) { @@ -183,7 +194,8 @@ export class AtemSocketChild extends EventEmitter { const fromPacketId = packet.readUInt16BE(6) this.log(`Retransmit request: ${fromPacketId}`) - // TODO + // TODO - enable and test this + // this._checkForRetransmit(fromPacketId) } // Got a packet that needs an ack @@ -252,8 +264,7 @@ export class AtemSocketChild extends EventEmitter { this._sendPacket(buffer) } - private _checkForRetransmit () { - let retransmitFromPacketId: number | undefined + private _checkForRetransmit (retransmitFromPacketId?: number) { for (const sentPacket of this._inFlight) { if (retransmitFromPacketId && sentPacket.packetId > retransmitFromPacketId) { sentPacket.lastSent = Date.now() diff --git a/src/state/macro.ts b/src/state/macro.ts index 3f63db28b..cfcbb59ed 100644 --- a/src/state/macro.ts +++ b/src/state/macro.ts @@ -18,8 +18,8 @@ export interface MacroPropertiesState { } export class MacroState { - public readonly macroPlayer: MacroPlayerState - public readonly macroRecorder: MacroRecorderState + public macroPlayer: MacroPlayerState + public macroRecorder: MacroRecorderState public readonly macroProperties: Array = [] constructor () { diff --git a/src/state/video/index.ts b/src/state/video/index.ts index baf1d49b5..5a44da1ff 100644 --- a/src/state/video/index.ts +++ b/src/state/video/index.ts @@ -93,8 +93,8 @@ export class MixEffect implements IMixEffect { public transitionFramesLeft: number = 0 public fadeToBlack?: FadeToBlackProperties public numberOfKeyers: number = 0 - public readonly transitionProperties: TransitionProperties - public readonly transitionSettings: TransitionSettings = {} + public transitionProperties: TransitionProperties + public transitionSettings: TransitionSettings = {} public readonly upstreamKeyers: Array = [] constructor (index: number) { From b136ac0f08f74efeb38e4a3854136336d9d252ad Mon Sep 17 00:00:00 2001 From: Julian Waller Date: Sun, 1 Dec 2019 20:01:57 +0000 Subject: [PATCH 15/68] fix: packet management incorrect if one times out --- src/__tests__/index.spec.ts | 2 +- src/lib/atemSocket.ts | 2 +- src/lib/atemSocketChild.ts | 10 +++++++--- src/lib/atemUtil.ts | 4 ---- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/__tests__/index.spec.ts b/src/__tests__/index.spec.ts index 966334d6d..9ed5b70cc 100644 --- a/src/__tests__/index.spec.ts +++ b/src/__tests__/index.spec.ts @@ -2,7 +2,7 @@ import { Atem, Enums } from '../index' function cleanupAtem (atem: Atem) { const atem2 = atem as any - atem2.dataTransferManager.stop() + atem2.dataTransferManager.stopCommandSending() const sock = atem2.socket._socketProcess sock.removeAllListeners() diff --git a/src/lib/atemSocket.ts b/src/lib/atemSocket.ts index 65b470165..331e38cdd 100644 --- a/src/lib/atemSocket.ts +++ b/src/lib/atemSocket.ts @@ -105,7 +105,7 @@ export class AtemSocket extends EventEmitter { this._socketProcess = null } - this._socketProcess = fork(path.resolve(__dirname, '../socket-child.js'), [], { + this._socketProcess = fork(path.resolve(__dirname, '../../dist/socket-child.js'), [], { silent: !this._debug, stdio: this._debug ? [0, 1, 2, 'ipc'] : undefined }) diff --git a/src/lib/atemSocketChild.ts b/src/lib/atemSocketChild.ts index 1b0f0a083..8df2b97c3 100644 --- a/src/lib/atemSocketChild.ts +++ b/src/lib/atemSocketChild.ts @@ -265,7 +265,7 @@ export class AtemSocketChild extends EventEmitter { } private _checkForRetransmit (retransmitFromPacketId?: number) { - for (const sentPacket of this._inFlight) { + this._inFlight = this._inFlight.filter(sentPacket => { if (retransmitFromPacketId && sentPacket.packetId > retransmitFromPacketId) { sentPacket.lastSent = Date.now() sentPacket.resent++ @@ -283,15 +283,19 @@ export class AtemSocketChild extends EventEmitter { retransmitFromPacketId = sentPacket.packetId } else { this.emit(IPCMessageType.CommandTimeout, sentPacket.packetId, sentPacket.trackingId) - this._inFlight.splice(this._inFlight.indexOf(sentPacket), 1) this.log(`Timed out: ${sentPacket.packetId}`) if (this._debug) { this.log(`TIMED OUT: ${sentPacket}`) } // @todo: we should probably break up the connection here. + + // Discard + return false } } - } + + return true + }) } } diff --git a/src/lib/atemUtil.ts b/src/lib/atemUtil.ts index 3424bb886..6534323c3 100644 --- a/src/lib/atemUtil.ts +++ b/src/lib/atemUtil.ts @@ -5,10 +5,6 @@ import { Enums } from '..' import WaveFile = require('wavefile') export namespace Util { - export function stringToBytes (str: string): Array { - return Array.from(Buffer.from(str).values()) - } - export function bufToBase64String (buffer: Buffer, start: number, length: number): string { return buffer.toString('base64', start, start + length) } From 1b32e35a924bb7ad5a11ea805001ec36ef8ecdd8 Mon Sep 17 00:00:00 2001 From: Julian Waller Date: Mon, 2 Dec 2019 20:24:42 +0000 Subject: [PATCH 16/68] fix: not resending packets when id has wrapped and retransmit is needed for just before the wrap --- src/lib/atemSocketChild.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/atemSocketChild.ts b/src/lib/atemSocketChild.ts index 8df2b97c3..fa5d74d4d 100644 --- a/src/lib/atemSocketChild.ts +++ b/src/lib/atemSocketChild.ts @@ -271,7 +271,7 @@ export class AtemSocketChild extends EventEmitter { sentPacket.resent++ this._sendPacket(sentPacket.payload) } else if (sentPacket && sentPacket.lastSent + IN_FLIGHT_TIMEOUT < Date.now()) { - if (sentPacket.resent <= MAX_PACKET_RETRIES && sentPacket.packetId < this._nextSendPacketId) { + if (sentPacket.resent <= MAX_PACKET_RETRIES && this._isPacketCoveredByAck(this._nextSendPacketId, sentPacket.packetId)) { sentPacket.lastSent = Date.now() sentPacket.resent++ From 022918ce5f92ff452e947ccd90ca2cd78bd7f8e4 Mon Sep 17 00:00:00 2001 From: Julian Waller Date: Mon, 2 Dec 2019 20:57:12 +0000 Subject: [PATCH 17/68] fix: handle udp message errors gracefully --- src/lib/atemSocketChild.ts | 48 ++++++++++++++++++++++++-------------- 1 file changed, 30 insertions(+), 18 deletions(-) diff --git a/src/lib/atemSocketChild.ts b/src/lib/atemSocketChild.ts index fa5d74d4d..2fcb8d858 100644 --- a/src/lib/atemSocketChild.ts +++ b/src/lib/atemSocketChild.ts @@ -68,22 +68,7 @@ export class AtemSocketChild extends EventEmitter { return } - // This includes a 'disconnect' - if (this._connectionState === ConnectionState.Established) { - this._connectionState = ConnectionState.Closed - this.emit(IPCMessageType.Disconnect) - } - - // Reset connection - this._nextSendPacketId = 1 - this._sessionId = 0 - this.log('reconnect') - - // Try doing reconnect - if (this._address && this._port) { - this._sendPacket(Util.COMMAND_CONNECT_HELLO) - this._connectionState = ConnectionState.SynSent - } + this.restartConnection() }, CONNECTION_RETRY_INTERVAL) } // Check for retransmits every 10 milliseconds @@ -98,8 +83,7 @@ export class AtemSocketChild extends EventEmitter { this._port = port } - this._sendPacket(Util.COMMAND_CONNECT_HELLO) - this._connectionState = ConnectionState.SynSent + this.restartConnection() } public disconnect (): Promise { @@ -126,6 +110,26 @@ export class AtemSocketChild extends EventEmitter { }) } + public restartConnection (): void { + // This includes a 'disconnect' + if (this._connectionState === ConnectionState.Established) { + this._connectionState = ConnectionState.Closed + this.emit(IPCMessageType.Disconnect) + } + + // Reset connection + this._nextSendPacketId = 1 + this._sessionId = 0 + this._inFlight = [] + this.log('reconnect') + + // Try doing reconnect + if (this._address && this._port) { + this._sendPacket(Util.COMMAND_CONNECT_HELLO) + this._connectionState = ConnectionState.SynSent + } + } + public log (payload: string): void { this.emit(IPCMessageType.Log, payload) } @@ -158,6 +162,14 @@ export class AtemSocketChild extends EventEmitter { this._socket = createSocket('udp4') this._socket.bind() this._socket.on('message', (packet, rinfo) => this._receivePacket(packet, rinfo)) + this._socket.on('error', err => { + this.log(`Connection error: ${err}`) + + if (this._connectionState === ConnectionState.Established) { + // If connection is open, then restart. Otherwise the reconnectTimer will handle it + this.restartConnection() + } + }) return this._socket } From 22ff62982d49039be3f85c9eddc80af90c7dcb37 Mon Sep 17 00:00:00 2001 From: Julian Waller Date: Mon, 2 Dec 2019 20:59:02 +0000 Subject: [PATCH 18/68] chore: rename CommandTimeout event to be more generic --- src/atem.ts | 4 ++-- src/enums/index.ts | 2 +- src/lib/atemSocket.ts | 6 +++--- src/lib/atemSocketChild.ts | 6 +++--- src/socket-child.ts | 4 ++-- 5 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/atem.ts b/src/atem.ts index 540516043..6400c15c0 100644 --- a/src/atem.ts +++ b/src/atem.ts @@ -85,8 +85,8 @@ export class Atem extends EventEmitter { this.emit('receivedCommand', command) this._mutateState(command) }) - this.socket.on(Enums.IPCMessageType.CommandAcknowledged, ({ trackingId }: {trackingId: number}) => this._resolveCommand(trackingId)) - this.socket.on(Enums.IPCMessageType.CommandTimeout, ({ trackingId }: {trackingId: number}) => this._rejectCommand(trackingId)) + this.socket.on(Enums.IPCMessageType.CommandAcknowledged, (trackingId: number) => this._resolveCommand(trackingId)) + this.socket.on(Enums.IPCMessageType.CommandReject, (trackingId: number) => this._rejectCommand(trackingId)) this.socket.on('error', (e) => this.emit('error', e)) this.socket.on('connect', () => this.emit('connected')) this.socket.on('disconnect', () => this.emit('disconnected')) diff --git a/src/enums/index.ts b/src/enums/index.ts index afa43d174..b352725b9 100644 --- a/src/enums/index.ts +++ b/src/enums/index.ts @@ -205,7 +205,7 @@ export enum IPCMessageType { InboundCommand = 'inboundCommand', OutboundCommand = 'outboundCommand', CommandAcknowledged = 'commandAcknowledged', - CommandTimeout = 'commandTimeout' + CommandReject = 'commandReject' } export enum TransferMode { diff --git a/src/lib/atemSocket.ts b/src/lib/atemSocket.ts index 331e38cdd..e8eba2b23 100644 --- a/src/lib/atemSocket.ts +++ b/src/lib/atemSocket.ts @@ -155,10 +155,10 @@ export class AtemSocket extends EventEmitter { this.log(message.payload) break case IPCMessageType.CommandAcknowledged: - this.emit(IPCMessageType.CommandAcknowledged, message.payload) + this.emit(IPCMessageType.CommandAcknowledged, message.payload.trackingId) break - case IPCMessageType.CommandTimeout: - this.emit(IPCMessageType.CommandTimeout, message.payload) + case IPCMessageType.CommandReject: + this.emit(IPCMessageType.CommandReject, message.payload.trackingId) break case IPCMessageType.InboundCommand: this._parseCommand(Buffer.from(payload.packet.data)) diff --git a/src/lib/atemSocketChild.ts b/src/lib/atemSocketChild.ts index 2fcb8d858..35edf93c8 100644 --- a/src/lib/atemSocketChild.ts +++ b/src/lib/atemSocketChild.ts @@ -45,13 +45,13 @@ export class AtemSocketChild extends EventEmitter { ((event: IPCMessageType.Log, listener: (payload: string) => void) => this) & ((event: IPCMessageType.InboundCommand, listener: (payload: Buffer, packetId: number) => void) => this) & ((event: IPCMessageType.CommandAcknowledged, listener: (packetId: number, trackingId: number) => void) => this) & - ((event: IPCMessageType.CommandTimeout, listener: (packetId: number, trackingId: number) => void) => this) + ((event: IPCMessageType.CommandReject, listener: (packetId: number, trackingId: number) => void) => this) public emit!: ((event: IPCMessageType.Disconnect) => boolean) & ((event: IPCMessageType.Log, payload: string) => boolean) & ((event: IPCMessageType.InboundCommand, payload: Buffer, packetId: number) => boolean) & ((event: IPCMessageType.CommandAcknowledged, packetId: number, trackingId: number) => boolean) & - ((event: IPCMessageType.CommandTimeout, packetId: number, trackingId: number) => boolean) + ((event: IPCMessageType.CommandReject, packetId: number, trackingId: number) => boolean) constructor (options: { address?: string, port?: number } = {}) { super() @@ -294,7 +294,7 @@ export class AtemSocketChild extends EventEmitter { this._sendPacket(sentPacket.payload) retransmitFromPacketId = sentPacket.packetId } else { - this.emit(IPCMessageType.CommandTimeout, sentPacket.packetId, sentPacket.trackingId) + this.emit(IPCMessageType.CommandReject, sentPacket.packetId, sentPacket.trackingId) this.log(`Timed out: ${sentPacket.packetId}`) if (this._debug) { diff --git a/src/socket-child.ts b/src/socket-child.ts index 5834d4195..9ca29e1b0 100644 --- a/src/socket-child.ts +++ b/src/socket-child.ts @@ -73,9 +73,9 @@ singleton.on(IPCMessageType.CommandAcknowledged, (commandId: number, trackingId: }) }) -singleton.on(IPCMessageType.CommandTimeout, (commandId: number, trackingId: number) => { +singleton.on(IPCMessageType.CommandReject, (commandId: number, trackingId: number) => { sendParentMessage({ - cmd: IPCMessageType.CommandTimeout, + cmd: IPCMessageType.CommandReject, payload: { commandId, trackingId From 537d90701959fa4c99e478814e53d4ea2f664e79 Mon Sep 17 00:00:00 2001 From: Julian Waller Date: Mon, 2 Dec 2019 21:46:45 +0000 Subject: [PATCH 19/68] feat: retransmit on demand and handle impossible retransmits by resetting the connection --- src/lib/atemSocketChild.ts | 76 ++++++++++++++++++++------------------ 1 file changed, 40 insertions(+), 36 deletions(-) diff --git a/src/lib/atemSocketChild.ts b/src/lib/atemSocketChild.ts index 35edf93c8..8b7da9ea6 100644 --- a/src/lib/atemSocketChild.ts +++ b/src/lib/atemSocketChild.ts @@ -5,10 +5,10 @@ import { ConnectionState, IPCMessageType, PacketFlag } from '../enums' import * as NanoTimer from 'nanotimer' import { DEFAULT_PORT } from '../atem' -const IN_FLIGHT_TIMEOUT = 30 // ms +const IN_FLIGHT_TIMEOUT = 60 // ms const CONNECTION_TIMEOUT = 5000 // ms const CONNECTION_RETRY_INTERVAL = 1000 // ms -const MAX_PACKET_RETRIES = 5 +const MAX_PACKET_RETRIES = 10 const MAX_PACKET_ID = (1 << 15) // Atem expects 15 not 16 bits before wrapping const MAX_PACKET_PER_ACK = 16 @@ -44,14 +44,12 @@ export class AtemSocketChild extends EventEmitter { public on!: ((event: IPCMessageType.Disconnect, listener: () => void) => this) & ((event: IPCMessageType.Log, listener: (payload: string) => void) => this) & ((event: IPCMessageType.InboundCommand, listener: (payload: Buffer, packetId: number) => void) => this) & - ((event: IPCMessageType.CommandAcknowledged, listener: (packetId: number, trackingId: number) => void) => this) & - ((event: IPCMessageType.CommandReject, listener: (packetId: number, trackingId: number) => void) => this) + ((event: IPCMessageType.CommandAcknowledged, listener: (packetId: number, trackingId: number) => void) => this) public emit!: ((event: IPCMessageType.Disconnect) => boolean) & ((event: IPCMessageType.Log, payload: string) => boolean) & ((event: IPCMessageType.InboundCommand, payload: Buffer, packetId: number) => boolean) & - ((event: IPCMessageType.CommandAcknowledged, packetId: number, trackingId: number) => boolean) & - ((event: IPCMessageType.CommandReject, packetId: number, trackingId: number) => boolean) + ((event: IPCMessageType.CommandAcknowledged, packetId: number, trackingId: number) => boolean) constructor (options: { address?: string, port?: number } = {}) { super() @@ -76,10 +74,10 @@ export class AtemSocketChild extends EventEmitter { this._retransmitTimer = setInterval(() => this._checkForRetransmit(), 10) } - if (address) { + if (address !== undefined) { this._address = address } - if (port) { + if (port !== undefined) { this._port = port } @@ -206,8 +204,7 @@ export class AtemSocketChild extends EventEmitter { const fromPacketId = packet.readUInt16BE(6) this.log(`Retransmit request: ${fromPacketId}`) - // TODO - enable and test this - // this._checkForRetransmit(fromPacketId) + this._retransmitFrom(fromPacketId) } // Got a packet that needs an ack @@ -239,13 +236,16 @@ export class AtemSocketChild extends EventEmitter { return true } }) + // this.log(`${Date.now()} Got ack ${ackPacketId} Remaining=${this._inFlight.length}`) } } } private _sendPacket (packet: Buffer) { if (this._debug) this.log(`SEND ${packet}`) + if (Math.random() > 0.25) { this._socket.send(packet, 0, packet.length, this._port, this._address) + } } private _sendOrQueueAck () { @@ -276,38 +276,42 @@ export class AtemSocketChild extends EventEmitter { this._sendPacket(buffer) } - private _checkForRetransmit (retransmitFromPacketId?: number) { - this._inFlight = this._inFlight.filter(sentPacket => { - if (retransmitFromPacketId && sentPacket.packetId > retransmitFromPacketId) { - sentPacket.lastSent = Date.now() - sentPacket.resent++ - this._sendPacket(sentPacket.payload) - } else if (sentPacket && sentPacket.lastSent + IN_FLIGHT_TIMEOUT < Date.now()) { - if (sentPacket.resent <= MAX_PACKET_RETRIES && this._isPacketCoveredByAck(this._nextSendPacketId, sentPacket.packetId)) { + private _retransmitFrom (fromId: number) { + // this.log(`Resending from ${fromId} to ${this._inFlight.length > 0 ? this._inFlight[this._inFlight.length - 1].packetId : '-'}`) + + const fromIndex = this._inFlight.findIndex(pkt => pkt.packetId === fromId) + if (fromIndex === -1) { + // fromId is not inflight, so we cannot resend. only fix is to abort + this.restartConnection() + } else { + this.log(`Resending from ${fromId} to ${this._inFlight[this._inFlight.length - 1].packetId}`) + // Resend from the requested + for (let i = fromIndex; i < this._inFlight.length; i++) { + const sentPacket = this._inFlight[i] + if (sentPacket.packetId === fromId || !this._isPacketCoveredByAck(fromId, sentPacket.packetId)) { sentPacket.lastSent = Date.now() sentPacket.resent++ - this.log(`Resending ${sentPacket.packetId}`) - if (this._debug) { - this.log(`RESEND: ${sentPacket}`) - } + // this.log(`${Date.now()} Resending ${sentPacket.packetId} Last=${this._nextSendPacketId - 1}`) this._sendPacket(sentPacket.payload) - retransmitFromPacketId = sentPacket.packetId - } else { - this.emit(IPCMessageType.CommandReject, sentPacket.packetId, sentPacket.trackingId) - - this.log(`Timed out: ${sentPacket.packetId}`) - if (this._debug) { - this.log(`TIMED OUT: ${sentPacket}`) - } - // @todo: we should probably break up the connection here. - - // Discard - return false } } + } + } - return true - }) + private _checkForRetransmit () { + for (const sentPacket of this._inFlight) { + if (sentPacket.lastSent + IN_FLIGHT_TIMEOUT < Date.now()) { + if (sentPacket.resent <= MAX_PACKET_RETRIES && this._isPacketCoveredByAck(this._nextSendPacketId, sentPacket.packetId)) { + this.log(`Retransmit from timeout: ${sentPacket.packetId}`) + // Retransmit the packet and anything after it + this._retransmitFrom(sentPacket.packetId) + } else { + // A command has timed out, so we need to reset to avoid getting stuck + this.restartConnection() + } + return + } + } } } From 35a85a5c13d84e58e89c2a1aa3e1c253b2968dbe Mon Sep 17 00:00:00 2001 From: Julian Waller Date: Mon, 2 Dec 2019 21:49:03 +0000 Subject: [PATCH 20/68] feat: individual commands cannot be rejected --- src/atem.ts | 26 ++++++++++++++------------ src/enums/index.ts | 1 - src/lib/atemSocket.ts | 3 --- src/lib/atemSocketChild.ts | 2 ++ src/socket-child.ts | 10 ---------- 5 files changed, 16 insertions(+), 26 deletions(-) diff --git a/src/atem.ts b/src/atem.ts index 6400c15c0..405516adb 100644 --- a/src/atem.ts +++ b/src/atem.ts @@ -36,8 +36,8 @@ export interface AtemOptions { interface SentCommand { command: ISerializableCommand - resolve: (cmd: ISerializableCommand) => void - reject: (cmd: ISerializableCommand) => void + resolve: () => void + reject: () => void } export const DEFAULT_PORT = 9910 @@ -47,7 +47,7 @@ export class Atem extends EventEmitter { private readonly _state: AtemState private readonly dataTransferManager: DT.DataTransferManager private readonly _log: (...args: any[]) => void - private readonly _sentQueue: {[packetId: string]: SentCommand } = {} + private _sentQueue: {[packetId: string]: SentCommand } = {} public on!: ((event: 'error', listener: (message: any) => void) => this) & ((event: 'connected', listener: () => void) => this) & @@ -86,10 +86,12 @@ export class Atem extends EventEmitter { this._mutateState(command) }) this.socket.on(Enums.IPCMessageType.CommandAcknowledged, (trackingId: number) => this._resolveCommand(trackingId)) - this.socket.on(Enums.IPCMessageType.CommandReject, (trackingId: number) => this._rejectCommand(trackingId)) this.socket.on('error', (e) => this.emit('error', e)) this.socket.on('connect', () => this.emit('connected')) - this.socket.on('disconnect', () => this.emit('disconnected')) + this.socket.on('disconnect', () => { + this._rejectAllCommands() + this.emit('disconnected') + }) } get state (): Readonly { @@ -479,16 +481,16 @@ export class Atem extends EventEmitter { private _resolveCommand (trackingId: number) { const sent = this._sentQueue[trackingId] if (sent) { - sent.resolve(sent.command) + sent.resolve() delete this._sentQueue[trackingId] } } - private _rejectCommand (trackingId: number) { - const sent = this._sentQueue[trackingId] - if (sent) { - sent.reject(sent.command) - delete this._sentQueue[trackingId] - } + private _rejectAllCommands () { + // Take a copy in case the promises cause more mutations + const sentQueue = this._sentQueue + this._sentQueue = {} + + Object.values(sentQueue).forEach(sent => sent.reject()) } } diff --git a/src/enums/index.ts b/src/enums/index.ts index b352725b9..3eb9df36f 100644 --- a/src/enums/index.ts +++ b/src/enums/index.ts @@ -205,7 +205,6 @@ export enum IPCMessageType { InboundCommand = 'inboundCommand', OutboundCommand = 'outboundCommand', CommandAcknowledged = 'commandAcknowledged', - CommandReject = 'commandReject' } export enum TransferMode { diff --git a/src/lib/atemSocket.ts b/src/lib/atemSocket.ts index e8eba2b23..487fd1b44 100644 --- a/src/lib/atemSocket.ts +++ b/src/lib/atemSocket.ts @@ -157,9 +157,6 @@ export class AtemSocket extends EventEmitter { case IPCMessageType.CommandAcknowledged: this.emit(IPCMessageType.CommandAcknowledged, message.payload.trackingId) break - case IPCMessageType.CommandReject: - this.emit(IPCMessageType.CommandReject, message.payload.trackingId) - break case IPCMessageType.InboundCommand: this._parseCommand(Buffer.from(payload.packet.data)) break diff --git a/src/lib/atemSocketChild.ts b/src/lib/atemSocketChild.ts index 8b7da9ea6..059f7f6c8 100644 --- a/src/lib/atemSocketChild.ts +++ b/src/lib/atemSocketChild.ts @@ -282,6 +282,7 @@ export class AtemSocketChild extends EventEmitter { const fromIndex = this._inFlight.findIndex(pkt => pkt.packetId === fromId) if (fromIndex === -1) { // fromId is not inflight, so we cannot resend. only fix is to abort + this.log(`Unable to resend: ${fromId}`) this.restartConnection() } else { this.log(`Resending from ${fromId} to ${this._inFlight[this._inFlight.length - 1].packetId}`) @@ -308,6 +309,7 @@ export class AtemSocketChild extends EventEmitter { this._retransmitFrom(sentPacket.packetId) } else { // A command has timed out, so we need to reset to avoid getting stuck + this.log(`Packet timed out: ${sentPacket.packetId}`) this.restartConnection() } return diff --git a/src/socket-child.ts b/src/socket-child.ts index 9ca29e1b0..e663f831c 100644 --- a/src/socket-child.ts +++ b/src/socket-child.ts @@ -73,16 +73,6 @@ singleton.on(IPCMessageType.CommandAcknowledged, (commandId: number, trackingId: }) }) -singleton.on(IPCMessageType.CommandReject, (commandId: number, trackingId: number) => { - sendParentMessage({ - cmd: IPCMessageType.CommandReject, - payload: { - commandId, - trackingId - } - }) -}) - function sendParentMessage (message: {cmd: IPCMessageType; payload?: any}) { Util.sendIPCMessage(global, 'process', message, singleton.log.bind(singleton)).catch(() => { /* Discard errors. */ }) } From 447f1d1d256daab2eee6326fd9c39bd6723e0da4 Mon Sep 17 00:00:00 2001 From: Julian Waller Date: Mon, 2 Dec 2019 22:11:59 +0000 Subject: [PATCH 21/68] fix: ensure the retransmit fromId is within range --- src/lib/atemSocketChild.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/lib/atemSocketChild.ts b/src/lib/atemSocketChild.ts index 059f7f6c8..2fd5db181 100644 --- a/src/lib/atemSocketChild.ts +++ b/src/lib/atemSocketChild.ts @@ -112,6 +112,7 @@ export class AtemSocketChild extends EventEmitter { // This includes a 'disconnect' if (this._connectionState === ConnectionState.Established) { this._connectionState = ConnectionState.Closed + this._createSocket() this.emit(IPCMessageType.Disconnect) } @@ -243,9 +244,7 @@ export class AtemSocketChild extends EventEmitter { private _sendPacket (packet: Buffer) { if (this._debug) this.log(`SEND ${packet}`) - if (Math.random() > 0.25) { this._socket.send(packet, 0, packet.length, this._port, this._address) - } } private _sendOrQueueAck () { @@ -279,6 +278,9 @@ export class AtemSocketChild extends EventEmitter { private _retransmitFrom (fromId: number) { // this.log(`Resending from ${fromId} to ${this._inFlight.length > 0 ? this._inFlight[this._inFlight.length - 1].packetId : '-'}`) + // The atem will ask for MAX_PACKET_ID to be retransmitted when it really wants 0 + fromId = fromId % MAX_PACKET_ID + const fromIndex = this._inFlight.findIndex(pkt => pkt.packetId === fromId) if (fromIndex === -1) { // fromId is not inflight, so we cannot resend. only fix is to abort From 570a6f16a0e8f937ade0fe7791a3bb0905d527aa Mon Sep 17 00:00:00 2001 From: Julian Waller Date: Mon, 2 Dec 2019 23:20:01 +0000 Subject: [PATCH 22/68] wip: atemSocketChild takes callbacks instead of being an eventEmitter --- src/enums/index.ts | 2 +- src/lib/__tests__/socket-child.spec.ts | 38 +++++++------ src/lib/atemSocketChild.ts | 40 ++++++-------- src/socket-child.ts | 76 +++++++++++++------------- 4 files changed, 78 insertions(+), 78 deletions(-) diff --git a/src/enums/index.ts b/src/enums/index.ts index 3eb9df36f..9cfebbff3 100644 --- a/src/enums/index.ts +++ b/src/enums/index.ts @@ -204,7 +204,7 @@ export enum IPCMessageType { Disconnect = 'disconnect', InboundCommand = 'inboundCommand', OutboundCommand = 'outboundCommand', - CommandAcknowledged = 'commandAcknowledged', + CommandAcknowledged = 'commandAcknowledged' } export enum TransferMode { diff --git a/src/lib/__tests__/socket-child.spec.ts b/src/lib/__tests__/socket-child.spec.ts index 03630d674..2df392022 100644 --- a/src/lib/__tests__/socket-child.spec.ts +++ b/src/lib/__tests__/socket-child.spec.ts @@ -3,7 +3,7 @@ import { Socket } from '../__mocks__/dgram' import { AtemSocketChild } from '../atemSocketChild' import { Util } from '../..' import * as lolex from 'lolex' -import { ConnectionState, PacketFlag, IPCMessageType } from '../../enums' +import { ConnectionState, PacketFlag } from '../../enums' import { DEFAULT_PORT } from '../../atem' const ADDRESS = '127.0.0.1' @@ -29,6 +29,10 @@ function fakeConnect (child: AtemSocketChild) { child2._address = '127.0.0.1' } +function createSocketChild (onCommandReceived?: (payload: Buffer, packetId: number) => void, onCommandAcknowledged?: (packetId: number, trackingId: number) => void) { + return new AtemSocketChild(() => null, () => null, onCommandReceived || (() => null), onCommandAcknowledged || (() => null)) +} + describe('SocketChild', () => { let clock: lolex.InstalledClock beforeEach(() => { @@ -39,7 +43,7 @@ describe('SocketChild', () => { }) test('Establish connection', async () => { - const child = new AtemSocketChild() + const child = createSocketChild() try { const socket = getSocket(child) @@ -120,7 +124,7 @@ describe('SocketChild', () => { } test('Ack - delayed', async () => { - const child = new AtemSocketChild() + const child = createSocketChild() try { fakeConnect(child) const socket = getSocket(child) @@ -163,7 +167,7 @@ describe('SocketChild', () => { }) test('Ack - bulk', async () => { - const child = new AtemSocketChild() + const child = createSocketChild() try { fakeConnect(child) const socket = getSocket(child) @@ -210,7 +214,8 @@ describe('SocketChild', () => { }) test('Inbound commands', async () => { - const child = new AtemSocketChild() + let gotCmds: number[] = [] + const child = createSocketChild(buf => gotCmds.push(buf.length)) try { fakeConnect(child) const socket = getSocket(child) @@ -222,8 +227,7 @@ describe('SocketChild', () => { expect(false).toBeTruthy() } - let gotCmds: number[] = [] - child.on(IPCMessageType.InboundCommand, buf => gotCmds.push(buf.length)) + gotCmds = [] // Nothing socket.emitMessage(genAckRequestMessage(1)) @@ -262,7 +266,8 @@ describe('SocketChild', () => { }) test('Inbound commands - around wrap', async () => { - const child = new AtemSocketChild() + let gotCmds: number[] = [] + const child = createSocketChild(buf => gotCmds.push(buf.length)) try { fakeConnect(child) const socket = getSocket(child) @@ -275,8 +280,7 @@ describe('SocketChild', () => { expect(false).toBeTruthy() } - let gotCmds: number[] = [] - child.on(IPCMessageType.InboundCommand, buf => gotCmds.push(buf.length)) + gotCmds = [] // Nothing socket.emitMessage(Buffer.concat([genAckRequestMessage(32766, 1), Buffer.from([0])])) @@ -336,7 +340,7 @@ describe('SocketChild', () => { }) test('SendCommand', async () => { - const child = new AtemSocketChild() + const child = createSocketChild() try { fakeConnect(child) const socket = getSocket(child) @@ -396,7 +400,8 @@ describe('SocketChild', () => { } test('SendCommand - acks', async () => { - const child = new AtemSocketChild() + let acked: Array<{packetId: number, trackingId: number}> = [] + const child = createSocketChild(undefined, (packetId, trackingId) => acked.push({ packetId, trackingId })) try { fakeConnect(child) const socket = getSocket(child) @@ -411,8 +416,7 @@ describe('SocketChild', () => { received.push(msg.readUInt16BE(10)) } - let acked: Array<{packetId: number, trackingId: number}> = [] - child.on(IPCMessageType.CommandAcknowledged, (packetId, trackingId) => acked.push({ packetId, trackingId })) + acked = [] // Send some stuff const buf1 = Buffer.from([0, 1, 2]) @@ -453,7 +457,8 @@ describe('SocketChild', () => { }) test('SendCommand - acks wrap', async () => { - const child = new AtemSocketChild() + let acked: Array<{packetId: number, trackingId: number}> = [] + const child = createSocketChild(undefined, (packetId, trackingId) => acked.push({ packetId, trackingId })) try { fakeConnect(child) const socket = getSocket(child) @@ -468,8 +473,7 @@ describe('SocketChild', () => { received.push(msg.readUInt16BE(10)) } - let acked: Array<{packetId: number, trackingId: number}> = [] - child.on(IPCMessageType.CommandAcknowledged, (packetId, trackingId) => acked.push({ packetId, trackingId })) + acked = [] // Send some stuff const buf1 = Buffer.from([0, 1, 2]) diff --git a/src/lib/atemSocketChild.ts b/src/lib/atemSocketChild.ts index 2fd5db181..93a1a483f 100644 --- a/src/lib/atemSocketChild.ts +++ b/src/lib/atemSocketChild.ts @@ -1,7 +1,6 @@ import { createSocket, Socket, RemoteInfo } from 'dgram' -import { EventEmitter } from 'events' import { Util } from './atemUtil' -import { ConnectionState, IPCMessageType, PacketFlag } from '../enums' +import { ConnectionState, PacketFlag } from '../enums' import * as NanoTimer from 'nanotimer' import { DEFAULT_PORT } from '../atem' @@ -20,7 +19,7 @@ interface InFlightPacket { resent: number } -export class AtemSocketChild extends EventEmitter { +export class AtemSocketChild { private readonly _debug = false private _connectionState = ConnectionState.Closed @@ -30,7 +29,7 @@ export class AtemSocketChild extends EventEmitter { private _nextSendPacketId = 1 private _sessionId: number = 0 - private _address: string + private _address: string = '' private _port: number = DEFAULT_PORT private _socket: Socket @@ -41,20 +40,17 @@ export class AtemSocketChild extends EventEmitter { private _ackTimerRunning = false private _receivedWithoutAck: number = 0 - public on!: ((event: IPCMessageType.Disconnect, listener: () => void) => this) & - ((event: IPCMessageType.Log, listener: (payload: string) => void) => this) & - ((event: IPCMessageType.InboundCommand, listener: (payload: Buffer, packetId: number) => void) => this) & - ((event: IPCMessageType.CommandAcknowledged, listener: (packetId: number, trackingId: number) => void) => this) + private readonly onDisconnect: () => void + private readonly onLog: (message: string) => void + private readonly onCommandReceived: (payload: Buffer, packetId: number) => void + private readonly onCommandAcknowledged: (packetId: number, trackingId: number) => void - public emit!: ((event: IPCMessageType.Disconnect) => boolean) & - ((event: IPCMessageType.Log, payload: string) => boolean) & - ((event: IPCMessageType.InboundCommand, payload: Buffer, packetId: number) => boolean) & - ((event: IPCMessageType.CommandAcknowledged, packetId: number, trackingId: number) => boolean) + constructor (onDisconnect: () => void, onLog: (message: string) => void, onCommandReceived: (payload: Buffer, packetId: number) => void, onCommandAcknowledged: (packetId: number, trackingId: number) => void) { + this.onDisconnect = onDisconnect + this.onLog = onLog + this.onCommandReceived = onCommandReceived + this.onCommandAcknowledged = onCommandAcknowledged - constructor (options: { address?: string, port?: number } = {}) { - super() - this._address = options.address || '' - this._port = options.port || this._port this._socket = this._createSocket() } @@ -104,7 +100,7 @@ export class AtemSocketChild extends EventEmitter { }).then(() => { this._connectionState = ConnectionState.Closed this._createSocket() - this.emit(IPCMessageType.Disconnect) + this.onDisconnect() }) } @@ -113,7 +109,7 @@ export class AtemSocketChild extends EventEmitter { if (this._connectionState === ConnectionState.Established) { this._connectionState = ConnectionState.Closed this._createSocket() - this.emit(IPCMessageType.Disconnect) + this.onDisconnect() } // Reset connection @@ -129,8 +125,8 @@ export class AtemSocketChild extends EventEmitter { } } - public log (payload: string): void { - this.emit(IPCMessageType.Log, payload) + public log (message: string): void { + this.onLog(message) } public sendCommand (payload: Buffer, trackingId: number): void { @@ -217,7 +213,7 @@ export class AtemSocketChild extends EventEmitter { // It might have commands if (length > 12) { - this.emit(IPCMessageType.InboundCommand, packet.slice(12), remotePacketId) + this.onCommandReceived(packet.slice(12), remotePacketId) } } else if (this._isPacketCoveredByAck(this._lastReceivedPacketId, remotePacketId)) { // We got a retransmit of something we have already acked, so reack it @@ -230,7 +226,7 @@ export class AtemSocketChild extends EventEmitter { const ackPacketId = packet.readUInt16BE(4) this._inFlight = this._inFlight.filter(pkt => { if (this._isPacketCoveredByAck(ackPacketId, pkt.packetId)) { - this.emit(IPCMessageType.CommandAcknowledged, pkt.packetId, pkt.trackingId) + this.onCommandAcknowledged(pkt.packetId, pkt.trackingId) return false } else { // Not acked yet diff --git a/src/socket-child.ts b/src/socket-child.ts index e663f831c..db1bb0580 100644 --- a/src/socket-child.ts +++ b/src/socket-child.ts @@ -2,7 +2,44 @@ import { IPCMessageType } from './enums' import { Util } from './lib/atemUtil' import { AtemSocketChild } from './lib/atemSocketChild' -const singleton = new AtemSocketChild() +function sendParentMessage (message: {cmd: IPCMessageType; payload?: any}) { + Util.sendIPCMessage(global, 'process', message, singleton.log.bind(singleton)).catch(() => { /* Discard errors. */ }) +} + +function onDisconnect () { + sendParentMessage({ + cmd: IPCMessageType.Disconnect + }) +} + +function onLog (message: string) { + sendParentMessage({ + cmd: IPCMessageType.Log, + payload: message + }) +} + +function onCommandReceived (packet: Buffer, remotePacketId: number) { + sendParentMessage({ + cmd: IPCMessageType.InboundCommand, + payload: { + packet, + remotePacketId + } + }) +} + +function onCommandAcknowledged (packetId: number, trackingId: number) { + sendParentMessage({ + cmd: IPCMessageType.CommandAcknowledged, + payload: { + packetId, + trackingId + } + }) +} + +const singleton = new AtemSocketChild(onDisconnect, onLog, onCommandReceived, onCommandAcknowledged) process.on('message', message => { if (typeof message !== 'object') { return @@ -39,40 +76,3 @@ process.on('unhandledRejection', reason => { process.exit(1) }, 10) }) - -singleton.on(IPCMessageType.Disconnect, () => { - sendParentMessage({ - cmd: IPCMessageType.Disconnect - }) -}) - -singleton.on(IPCMessageType.Log, (message: string) => { - sendParentMessage({ - cmd: IPCMessageType.Log, - payload: message - }) -}) - -singleton.on(IPCMessageType.InboundCommand, (packet: Buffer, remotePacketId: number) => { - sendParentMessage({ - cmd: IPCMessageType.InboundCommand, - payload: { - packet, - remotePacketId - } - }) -}) - -singleton.on(IPCMessageType.CommandAcknowledged, (commandId: number, trackingId: number) => { - sendParentMessage({ - cmd: IPCMessageType.CommandAcknowledged, - payload: { - commandId, - trackingId - } - }) -}) - -function sendParentMessage (message: {cmd: IPCMessageType; payload?: any}) { - Util.sendIPCMessage(global, 'process', message, singleton.log.bind(singleton)).catch(() => { /* Discard errors. */ }) -} From 234284ea57d62189b654d6ec3886f9bba71836d3 Mon Sep 17 00:00:00 2001 From: Julian Waller Date: Wed, 4 Dec 2019 09:47:43 +0000 Subject: [PATCH 23/68] fix: wrap transferIndex once it reaches maximum --- src/dataTransfer/index.ts | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/src/dataTransfer/index.ts b/src/dataTransfer/index.ts index 224d36ad3..0f631c698 100644 --- a/src/dataTransfer/index.ts +++ b/src/dataTransfer/index.ts @@ -8,6 +8,7 @@ import DataTransferAudio from './dataTransferAudio' import { ISerializableCommand } from '../commands/CommandBase' const MAX_PACKETS_TO_SEND_PER_TICK = 10 +const MAX_TRANSFER_INDEX = (1 << 16) - 1 // Inclusive maximum export class DataTransferManager { private readonly commandQueue: Array = [] @@ -37,7 +38,10 @@ export class DataTransferManager { const commandsToSend = this.commandQueue.splice(0, MAX_PACKETS_TO_SEND_PER_TICK) commandsToSend.forEach(command => { - sendCommand(command).catch(() => { /* discard error */ }) + sendCommand(command).catch((e) => { + // TODO - handle this better. it should probably kill/restart the upload. and should also be logged in some way + console.log(`Transfer send error: ${e}`) + }) }) }, 0) // TODO - should this be done slower? } @@ -97,23 +101,29 @@ export class DataTransferManager { } public uploadStill (index: number, data: Buffer, name: string, description: string) { - const transfer = new DataTransferStill(this.transferIndex++, index, data, name, description) + const transfer = new DataTransferStill(this.nextTransferIndex, index, data, name, description) return this.stillsLock.enqueue(transfer) } public async uploadClip (index: number, data: Array, name: string) { - const frames = data.map((frame, id) => new DataTransferFrame(this.transferIndex++, 1 + index, id, frame)) + const frames = data.map((frame, id) => new DataTransferFrame(this.nextTransferIndex, 1 + index, id, frame)) const transfer = new DataTransferClip(1 + index, name, frames) const lock = await this.getClipLock(index) return lock.enqueue(transfer) } public async uploadAudio (index: number, data: Buffer, name: string) { - const transfer = new DataTransferAudio(this.transferIndex++, 1 + index, data, name) + const transfer = new DataTransferAudio(this.nextTransferIndex, 1 + index, data, name) const lock = await this.getClipLock(index) return lock.enqueue(transfer) } + private get nextTransferIndex () { + const index = this.transferIndex++ + if (this.transferIndex > MAX_TRANSFER_INDEX) this.transferIndex = 0 + return index + } + private async getClipLock (index: number) { const lock = this.clipLocks[index] if (lock) { From c31fc1a1c239089aaea0e76600fe6e9735f3079a Mon Sep 17 00:00:00 2001 From: Julian Waller Date: Wed, 4 Dec 2019 22:54:04 +0000 Subject: [PATCH 24/68] fix: tidy up multiviewer state object --- src/state/settings.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/state/settings.ts b/src/state/settings.ts index e391ecc5e..c99e4ed4a 100644 --- a/src/state/settings.ts +++ b/src/state/settings.ts @@ -11,7 +11,7 @@ export interface MultiViewerWindowState extends MultiViewerSourceState { export class MultiViewer { public readonly index: number - public readonly windows: { [index: string]: MultiViewerWindowState | undefined } = {} + public readonly windows: Array = [] constructor (index: number) { this.index = index @@ -19,7 +19,7 @@ export class MultiViewer { } export class SettingsState { - public readonly multiViewers: { [index: string]: MultiViewer | undefined } = {} + public readonly multiViewers: Array = [] public videoMode: number constructor () { From a451a90d997cc95595efa68f5fe746ab2b487758 Mon Sep 17 00:00:00 2001 From: Julian Waller Date: Wed, 4 Dec 2019 21:23:01 +0000 Subject: [PATCH 25/68] fix: create new state object on connection start --- src/atem.ts | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/atem.ts b/src/atem.ts index 405516adb..5484ad7f0 100644 --- a/src/atem.ts +++ b/src/atem.ts @@ -44,9 +44,9 @@ export const DEFAULT_PORT = 9910 export class Atem extends EventEmitter { private readonly socket: AtemSocket - private readonly _state: AtemState private readonly dataTransferManager: DT.DataTransferManager private readonly _log: (...args: any[]) => void + private _state: AtemState private _sentQueue: {[packetId: string]: SentCommand } = {} public on!: ((event: 'error', listener: (message: any) => void) => this) & @@ -465,6 +465,11 @@ export class Atem extends EventEmitter { } private _mutateState (command: IDeserializedCommand) { + if (command.constructor.name === Commands.VersionCommand.name) { + // On start of connection, create a new state object + this._state = new AtemState() + } + let changePaths = command.applyToState(this.state) if (!Array.isArray(changePaths)) { changePaths = [ changePaths ] From a9f52698eefd0677971beeb94c08d1f7d7826ee4 Mon Sep 17 00:00:00 2001 From: Julian Waller Date: Wed, 4 Dec 2019 23:09:08 +0000 Subject: [PATCH 26/68] fix: move exit-hook inside dataTransferManager to ensure it gets run when needed --- src/atem.ts | 10 ---------- src/dataTransfer/index.ts | 19 +++++++++++++------ 2 files changed, 13 insertions(+), 16 deletions(-) diff --git a/src/atem.ts b/src/atem.ts index 5484ad7f0..3f533e3e7 100644 --- a/src/atem.ts +++ b/src/atem.ts @@ -24,7 +24,6 @@ import * as DT from './dataTransfer' import { Util } from './lib/atemUtil' import * as Enums from './enums' import { AudioChannel, AudioMasterChannel } from './state/audio' -import exitHook = require('exit-hook') import { listVisibleInputs } from './lib/tally' export interface AtemOptions { @@ -72,15 +71,6 @@ export class Atem extends EventEmitter { this.socket.on('connect', () => this.dataTransferManager.startCommandSending((command: ISerializableCommand) => this.sendCommand(command))) this.socket.on('disconnect', () => this.dataTransferManager.stopCommandSending()) - // When the parent process begins exiting, remove the listeners on our child process. - // We do this to avoid throwing an error when the child process exits - // as a natural part of the parent process exiting. - exitHook(() => { - if (this.dataTransferManager) { - this.dataTransferManager.stopCommandSending() - } - }) - this.socket.on('receivedStateChange', (command: IDeserializedCommand) => { this.emit('receivedCommand', command) this._mutateState(command) diff --git a/src/dataTransfer/index.ts b/src/dataTransfer/index.ts index 0f631c698..effd9b329 100644 --- a/src/dataTransfer/index.ts +++ b/src/dataTransfer/index.ts @@ -1,5 +1,6 @@ -import { Commands, Enums } from '..' +import exitHook = require('exit-hook') +import { Commands, Enums } from '..' import DataLock from './dataLock' import DataTransferFrame from './dataTransferFrame' import DataTransferStill from './dataTransferStill' @@ -13,16 +14,14 @@ const MAX_TRANSFER_INDEX = (1 << 16) - 1 // Inclusive maximum export class DataTransferManager { private readonly commandQueue: Array = [] - private readonly stillsLock = new DataLock(0, cmd => { - // console.log('SEND', cmd.constructor.name) - this.commandQueue.push(cmd) - }) + private readonly stillsLock = new DataLock(0, cmd => this.commandQueue.push(cmd)) private readonly clipLocks = [ new DataLock(1, cmd => this.commandQueue.push(cmd)), new DataLock(2, cmd => this.commandQueue.push(cmd)) ] - private interval: NodeJS.Timer | undefined + private interval?: NodeJS.Timer + private exitUnsubscribe?: () => void private transferIndex: number = 0 @@ -45,8 +44,16 @@ export class DataTransferManager { }) }, 0) // TODO - should this be done slower? } + if (!this.exitUnsubscribe) { + this.exitUnsubscribe = exitHook(() => { + this.stopCommandSending() + }) + } } public stopCommandSending () { + if (this.exitUnsubscribe) { + this.exitUnsubscribe = undefined + } if (this.interval) { clearInterval(this.interval) this.interval = undefined From d20b1852041e81dde5a25d3ddd52ac8e30697dad Mon Sep 17 00:00:00 2001 From: Julian Waller Date: Fri, 18 Oct 2019 18:56:26 +0100 Subject: [PATCH 27/68] feat: Replace usage of fork with threadedClass --- package.json | 3 +- src/__tests__/index.spec.ts | 8 +- src/atem.ts | 15 ++- src/lib/atemSocket.ts | 193 ++++++++++++++---------------------- src/lib/atemUtil.ts | 56 ----------- yarn.lock | 35 +++---- 6 files changed, 105 insertions(+), 205 deletions(-) diff --git a/package.json b/package.json index c2eb5d8ac..f95007fb0 100644 --- a/package.json +++ b/package.json @@ -112,9 +112,10 @@ "video" ], "dependencies": { + "emittery": "^0.5.1", "exit-hook": "^2.0.0", "nanotimer": "^0.3.15", - "p-retry": "^4.1.0", + "threadedclass": "^0.6.8", "tslib": "^1.9.0", "wavefile": "^8.4.4" }, diff --git a/src/__tests__/index.spec.ts b/src/__tests__/index.spec.ts index 9ed5b70cc..021c4872e 100644 --- a/src/__tests__/index.spec.ts +++ b/src/__tests__/index.spec.ts @@ -3,14 +3,10 @@ import { Atem, Enums } from '../index' function cleanupAtem (atem: Atem) { const atem2 = atem as any atem2.dataTransferManager.stopCommandSending() - - const sock = atem2.socket._socketProcess - sock.removeAllListeners() - sock.kill() } test('Simple test', async () => { - const nb = new Atem() + const nb = new Atem({ disableMultithreaded: true }) try { nb.on('error', () => null) @@ -21,7 +17,7 @@ test('Simple test', async () => { }) function createConnection (apiVersion: Enums.ProtocolVersion) { - const conn = new Atem({ debug: true }) + const conn = new Atem({ debug: true, disableMultithreaded: true }) // conn.on('error', () => null) conn.sendCommand = jest.fn() conn.state.info.apiVersion = apiVersion diff --git a/src/atem.ts b/src/atem.ts index 3f533e3e7..27eb9963d 100644 --- a/src/atem.ts +++ b/src/atem.ts @@ -30,7 +30,9 @@ export interface AtemOptions { address?: string, port?: number, debug?: boolean, - externalLog?: (arg0?: any,arg1?: any,arg2?: any,arg3?: any) => void + disableMultithreaded?: boolean + + externalLog?: (arg0?: any, arg1?: any, arg2?: any, arg3?: any) => void } interface SentCommand { @@ -62,10 +64,11 @@ export class Atem extends EventEmitter { this._state = new AtemState() this.socket = new AtemSocket({ - debug: (options || {}).debug, + debug: (options || {}).debug || false, log: this._log, - address: (options || {}).address, - port: (options || {}).port + address: (options || {}).address || '', + port: (options || {}).port || DEFAULT_PORT, + disableMultithreaded: (options || {}).disableMultithreaded || false }) this.dataTransferManager = new DT.DataTransferManager() this.socket.on('connect', () => this.dataTransferManager.startCommandSending((command: ISerializableCommand) => this.sendCommand(command))) @@ -82,6 +85,10 @@ export class Atem extends EventEmitter { this._rejectAllCommands() this.emit('disconnected') }) + this.socket.on('restarted', () => { + this._rejectAllCommands() + this.emit('disconnected') + }) } get state (): Readonly { diff --git a/src/lib/atemSocket.ts b/src/lib/atemSocket.ts index 487fd1b44..c3babe285 100644 --- a/src/lib/atemSocket.ts +++ b/src/lib/atemSocket.ts @@ -1,46 +1,53 @@ -import { ChildProcess, fork } from 'child_process' import { EventEmitter } from 'events' -import * as path from 'path' import { CommandParser } from './atemCommandParser' import { IPCMessageType } from '../enums' -import exitHook = require('exit-hook') -import { Util } from './atemUtil' +// import exitHook = require('exit-hook') import { VersionCommand, ISerializableCommand, IDeserializedCommand } from '../commands' import { DEFAULT_PORT } from '../atem' +import { threadedClass, ThreadedClass, ThreadedClassManager } from 'threadedclass' +import { AtemSocketChild } from './atemSocketChild' + +export interface AtemSocketOptions { + address: string + port: number + debug: boolean + disableMultithreaded: boolean + + log: (args1: any, args2?: any, args3?: any) => void +} export class AtemSocket extends EventEmitter { - private _debug = false + private readonly _debug: boolean + private readonly _disableMultithreaded: boolean + private readonly _commandParser: CommandParser = new CommandParser() + private _nextCommandTrackingId = 0 private _address: string private _port: number = DEFAULT_PORT - private _shouldConnect = false - private _socketProcess: ChildProcess | null - private _commandParser: CommandParser = new CommandParser() + private _socketProcess: ThreadedClass | undefined - constructor (options: { address?: string, port?: number, debug?: boolean, log?: (...args: any[]) => void }) { - super() - this._address = options.address || '' - this._port = options.port || this._port - this._debug = options.debug || false - this.log = options.log || this.log + private readonly log: (args1: any, args2?: any, args3?: any) => void - this._socketProcess = null - this._createSocketProcess() + constructor (options: AtemSocketOptions) { + super() + this._address = options.address + this._port = options.port + this._debug = options.debug + this._disableMultithreaded = options.disableMultithreaded + this.log = options.log // When the parent process begins exiting, remove the listeners on our child process. // We do this to avoid throwing an error when the child process exits // as a natural part of the parent process exiting. - exitHook(() => { - if (this._socketProcess) { - this._socketProcess.removeAllListeners() - this._socketProcess.kill() - } - }) + // exitHook(() => { + // if (this._socketProcess) { + // this._socketProcess.removeAllListeners() + // this._socketProcess.kill() + // } + // }) } - public connect (address?: string, port?: number) { - this._shouldConnect = true - + public async connect (address?: string, port?: number): Promise { if (address) { this._address = address } @@ -48,25 +55,17 @@ export class AtemSocket extends EventEmitter { this._port = port } - return this._sendSubprocessMessage({ - cmd: IPCMessageType.Connect, - payload: { - address: this._address, - port: this._port - } - }) - } - - public disconnect () { - this._shouldConnect = false - - return this._sendSubprocessMessage({ - cmd: IPCMessageType.Disconnect - }) + if (!this._socketProcess) { + this._socketProcess = await this._createSocketProcess() + } else { + await this._socketProcess.connect(this._address, this._port) + } } - public log (..._args: any[]): void { - // Will be re-assigned by the top-level ATEM class. + public async disconnect (): Promise { + if (this._socketProcess) { + await this._socketProcess.disconnect() + } } get nextCommandTrackingId (): number { @@ -76,94 +75,52 @@ export class AtemSocket extends EventEmitter { return ++this._nextCommandTrackingId } - public _sendCommand (command: ISerializableCommand, trackingId: number) { - if (typeof (command as any).serialize !== 'function') { - return Promise.reject(new Error('Command is not serializable')) - } + public async _sendCommand (command: ISerializableCommand, trackingId: number) { + if (this._socketProcess) { + if (typeof (command as any).serialize !== 'function') { + throw new Error('Command is not serializable') + } - const payload = command.serialize(this._commandParser.version) - const fullPayload = Buffer.alloc(payload.length + 8, 0) - fullPayload.writeUInt16BE(fullPayload.length, 0) - fullPayload.write((command.constructor as any).rawName, 4, 4) - payload.copy(fullPayload, 8, 0) + const payload = command.serialize(this._commandParser.version) + const fullPayload = Buffer.alloc(payload.length + 8, 0) + fullPayload.writeUInt16BE(fullPayload.length, 0) + fullPayload.write((command.constructor as any).rawName, 4, 4) + payload.copy(fullPayload, 8, 0) - if (this._debug) this.log('PAYLOAD', command.constructor.name, fullPayload) + if (this._debug) this.log('PAYLOAD', command.constructor.name, fullPayload) - return this._sendSubprocessMessage({ - cmd: IPCMessageType.OutboundCommand, - payload: { - data: fullPayload, - trackingId - } - }) - } - - private _createSocketProcess () { - if (this._socketProcess) { - this._socketProcess.removeAllListeners() - this._socketProcess.kill() - this._socketProcess = null + await this._socketProcess.sendCommand(fullPayload, trackingId) + } else { + throw new Error('Socket process is not open') } + } - this._socketProcess = fork(path.resolve(__dirname, '../../dist/socket-child.js'), [], { - silent: !this._debug, - stdio: this._debug ? [0, 1, 2, 'ipc'] : undefined - }) - this._socketProcess.on('stdout', out => console.log(out)) - this._socketProcess.on('message', this._receiveSubprocessMessage.bind(this)) - this._socketProcess.on('error', error => { - this.emit('error', error) - this.log('socket process error:', error) + private async _createSocketProcess (address?: string, port?: number) { + const socketProcess = await threadedClass('./atemSocketChild.js', AtemSocketChild, [{ + address, + port + }], { + instanceName: 'atem-connection', + freezeLimit: 200, + autoRestart: true, + disableMultithreading: this._disableMultithreaded }) - this._socketProcess.on('exit', (code, signal) => { - process.nextTick(() => { - this.emit('error', new Error(`The socket process unexpectedly closed (code: "${code}", signal: "${signal}")`)) - this.log('socket process exit:', code, signal) - this._createSocketProcess() - }) - }) - - if (this._shouldConnect) { + // await socketProcess.on(IPCMessageType.Disconnect, () => this.emit(IPCMessageType.Disconnect)) + // await socketProcess.on(IPCMessageType.Log, (payload: string) => this.log(payload)) + // await socketProcess.on(IPCMessageType.CommandAcknowledged, (packetId: number, trackingId: number) => this.emit(IPCMessageType.CommandAcknowledged, { packetId, trackingId })) + // await socketProcess.on(IPCMessageType.CommandTimeout, (packetId: number, trackingId: number) => this.emit(IPCMessageType.CommandTimeout, { packetId, trackingId })) + // await socketProcess.on(IPCMessageType.InboundCommand, (payload: Buffer) => this._parseCommand(Buffer.from(payload))) + + ThreadedClassManager.onEvent(socketProcess, 'restarted', () => { + this.emit('restarted') this.connect().catch(error => { const errorMsg = 'Failed to reconnect after respawning socket process' this.emit('error', error) this.log(errorMsg + ':', error && error.message) }) - } - } - - private async _sendSubprocessMessage (message: {cmd: IPCMessageType; payload?: any, _messageId?: number}) { - if (!this._socketProcess) { - throw new Error('Socket process process does not exist') - } - - return Util.sendIPCMessage(this, '_socketProcess', message, this.log) - } - - private _receiveSubprocessMessage (message: any) { - if (typeof message !== 'object') { - return - } - - if (typeof message.cmd !== 'string' || message.cmd.length <= 0) { - return - } + }) - const payload = message.payload - switch (message.cmd) { - case IPCMessageType.Log: - this.log(message.payload) - break - case IPCMessageType.CommandAcknowledged: - this.emit(IPCMessageType.CommandAcknowledged, message.payload.trackingId) - break - case IPCMessageType.InboundCommand: - this._parseCommand(Buffer.from(payload.packet.data)) - break - case IPCMessageType.Disconnect: - this.emit(IPCMessageType.Disconnect) - break - } + return socketProcess } private _parseCommand (buffer: Buffer) { diff --git a/src/lib/atemUtil.ts b/src/lib/atemUtil.ts index 6534323c3..d12c8b452 100644 --- a/src/lib/atemUtil.ts +++ b/src/lib/atemUtil.ts @@ -1,5 +1,3 @@ -import { IPCMessageType } from '../enums' -import * as pRetry from 'p-retry' import { Enums } from '..' // @ts-ignore import WaveFile = require('wavefile') @@ -31,60 +29,6 @@ export namespace Util { return value } - export function sendIPCMessage ( - scope: any, - processProperty: string, - message: {cmd: IPCMessageType; payload?: any, _messageId?: number}, - log: Function - ) { - return pRetry(() => { - return new Promise((resolve, reject) => { - // This ensures that we will always grab the currently in-use process, if it has been re-made. - const destProcess = scope[processProperty] - if (!destProcess || typeof destProcess.send !== 'function') { - return reject(new Error('Destination process has gone away')) - } - - let handled = false - const timeout = setTimeout(() => { - reject(new Error('Failed to send IPC message')) - }, 1500) - - // From https://nodejs.org/api/child_process.html#child_process_subprocess_send_message_sendhandle_options_callback: - // "subprocess.send() will return false if the channel has closed or when the backlog of - // unsent messages exceeds a threshold that makes it unwise to send more. - // Otherwise, the method returns true." - destProcess.send(message, (error: Error) => { - clearTimeout(timeout) - if (handled) { - return - } - - if (error) { - handled = true - reject(error) - } else { - resolve() - } - - handled = true - }) - - // if (!sendResult && !handled) { - // reject(new Error('Failed to send IPC message')) - // handled = true - // } - }) - }, { - onFailedAttempt: error => { - if (log) { - log(`Failed to send IPC message: ${error.message} (attempt ${error.attemptNumber}/${error.attemptNumber + error.retriesLeft}).`) - } - }, - retries: 5 - }) - } - export const COMMAND_CONNECT_HELLO = Buffer.from([ 0x10, 0x14, 0x53, 0xAB, 0x00, 0x00, 0x00, 0x00, diff --git a/yarn.lock b/yarn.lock index 703f1416e..4b0f31e65 100644 --- a/yarn.lock +++ b/yarn.lock @@ -390,11 +390,6 @@ resolved "https://registry.yarnpkg.com/@types/node/-/node-12.12.14.tgz#1c1d6e3c75dba466e0326948d56e8bd72a1903d2" integrity sha512-u/SJDyXwuihpwjXy7hOOghagLEV1KdAST6syfnOk6QZAMzZuWZqXy5aYYZbh8Jdpd4escVFP0MvftHNDb9pruA== -"@types/retry@^0.12.0": - version "0.12.0" - resolved "https://registry.yarnpkg.com/@types/retry/-/retry-0.12.0.tgz#2b35eccfcee7d38cd72ad99232fbd58bffb3c84d" - integrity sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA== - "@types/stack-utils@^1.0.1": version "1.0.1" resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-1.0.1.tgz#0a851d3bd96498fa25c33ab7278ed3bd65f06c3e" @@ -864,7 +859,7 @@ cacheable-request@^6.0.0: normalize-url "^4.1.0" responselike "^1.0.2" -callsites@^3.0.0: +callsites@^3.0.0, callsites@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== @@ -1569,6 +1564,11 @@ email-addresses@^3.0.1: resolved "https://registry.yarnpkg.com/email-addresses/-/email-addresses-3.1.0.tgz#cabf7e085cbdb63008a70319a74e6136188812fb" integrity sha512-k0/r7GrWVL32kZlGwfPNgB2Y/mMXVTq/decgLczm/j34whdaspNrZO8CnXPf1laaHxI6ptUlsnAxN+UAPw+fzg== +emittery@^0.5.1: + version "0.5.1" + resolved "https://registry.yarnpkg.com/emittery/-/emittery-0.5.1.tgz#9fbbf57e9aecc258d727d78858a598eb05ea5c96" + integrity sha512-sYZXNHH9PhTfs98ROEFVC3bLiR8KSqXQsEHIwZ9J6H0RaQObC3JYq4G8IvDd0b45/LxfGKYBpmaUN4LiKytaNw== + emoji-regex@^7.0.1: version "7.0.3" resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-7.0.3.tgz#933a04052860c85e83c122479c4748a8e4c72156" @@ -4045,14 +4045,6 @@ p-reduce@^1.0.0: resolved "https://registry.yarnpkg.com/p-reduce/-/p-reduce-1.0.0.tgz#18c2b0dd936a4690a529f8231f58a0fdb6a47dfa" integrity sha1-GMKw3ZNqRpClKfgjH1ig/bakffo= -p-retry@^4.1.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/p-retry/-/p-retry-4.2.0.tgz#ea9066c6b44f23cab4cd42f6147cdbbc6604da5d" - integrity sha512-jPH38/MRh263KKcq0wBNOGFJbm+U6784RilTmHjB/HM9kH9V8WlCpVUcdOmip9cjXOh6MxZ5yk1z2SjDUJfWmA== - dependencies: - "@types/retry" "^0.12.0" - retry "^0.12.0" - p-try@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/p-try/-/p-try-1.0.0.tgz#cbc79cdbaf8fd4228e13f621f2b1a237c1b207b3" @@ -4602,11 +4594,6 @@ ret@~0.1.10: resolved "https://registry.yarnpkg.com/ret/-/ret-0.1.15.tgz#b8a4825d5bdb1fc3f6f53c2bc33f81388681c7bc" integrity sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg== -retry@^0.12.0: - version "0.12.0" - resolved "https://registry.yarnpkg.com/retry/-/retry-0.12.0.tgz#1b42a6266a21f07421d1b0b54b7dc167b01c013b" - integrity sha1-G0KmJmoh8HQh0bC1S33BZ7AcATs= - rimraf@^2.5.4, rimraf@^2.6.1, rimraf@^2.6.2, rimraf@^2.6.3: version "2.7.1" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec" @@ -5183,6 +5170,14 @@ text-extensions@^1.0.0: resolved "https://registry.yarnpkg.com/text-extensions/-/text-extensions-1.9.0.tgz#1853e45fee39c945ce6f6c36b2d659b5aabc2a26" integrity sha512-wiBrwC1EhBelW12Zy26JeOUkQ5mRu+5o8rpsJk5+2t+Y5vE7e842qtZDQ2g1NpX/29HdyFeJ4nSIhI47ENSxlQ== +threadedclass@^0.6.8: + version "0.6.8" + resolved "https://registry.yarnpkg.com/threadedclass/-/threadedclass-0.6.8.tgz#7eba5d9c7b3b40b9b5a6edcee222b54d209336bf" + integrity sha512-pAQSA7bM1r2tSuag6buf7o7xJ3m5W3zF77xG1SlD+7yPC09Ly/JBm4rVpXY+Ryy20An3PvdHwlkAonizBvUiFA== + dependencies: + callsites "^3.1.0" + tslib "^1.9.3" + throat@^4.0.0: version "4.1.0" resolved "https://registry.yarnpkg.com/throat/-/throat-4.1.0.tgz#89037cbc92c56ab18926e6ba4cbb200e15672a6a" @@ -5349,7 +5344,7 @@ tslib@1.9.0: resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.9.0.tgz#e37a86fda8cbbaf23a057f473c9f4dc64e5fc2e8" integrity sha512-f/qGG2tUkrISBlQZEjEqoZ3B2+npJjIf04H1wuAv9iA8i04Icp+61KRXxFdha22670NJopsZCIjhC3SnjPRKrQ== -tslib@^1.8.0, tslib@^1.8.1, tslib@^1.9.0: +tslib@^1.8.0, tslib@^1.8.1, tslib@^1.9.0, tslib@^1.9.3: version "1.10.0" resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.10.0.tgz#c3c19f95973fb0a62973fb09d90d961ee43e5c8a" integrity sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ== From c0a2471a022c21f8265e186858c460a4851f68aa Mon Sep 17 00:00:00 2001 From: Julian Waller Date: Sat, 19 Oct 2019 02:08:32 +0100 Subject: [PATCH 28/68] feat(tests): Tests for basic atem methods --- jest.config.js | 4 +- src/__tests__/atem.spec.ts | 226 ++++++++++++++++++++++++++++++++++++ src/__tests__/index.spec.ts | 6 +- src/__tests__/lib.ts | 6 + src/atem.ts | 17 ++- 5 files changed, 243 insertions(+), 16 deletions(-) create mode 100644 src/__tests__/atem.spec.ts create mode 100644 src/__tests__/lib.ts diff --git a/jest.config.js b/jest.config.js index 3dca92d4d..a99a73613 100644 --- a/jest.config.js +++ b/jest.config.js @@ -27,10 +27,10 @@ module.exports = { coverageDirectory: "./coverage/", collectCoverage: true, collectCoverageFrom: [ - "**/src/**", + "**/src/**/**", "!**/src/@types/**", "!**/__tests__/**", - "!**/__mocks__/**", + "!**/__mocks__/**", '!**/node_modules/**', '!**/dist/**' ] diff --git a/src/__tests__/atem.spec.ts b/src/__tests__/atem.spec.ts new file mode 100644 index 000000000..4abd2a052 --- /dev/null +++ b/src/__tests__/atem.spec.ts @@ -0,0 +1,226 @@ +import { Atem, DEFAULT_PORT } from '../atem' +import { cleanupAtem } from './lib' +import { CutCommand } from '../commands' +import { IPCMessageType } from '../enums' +import { promisify } from 'util' +import { EventEmitter } from 'events' + +import { AtemSocket } from '../lib/atemSocket' +jest.mock('../lib/atemSocket.ts') + +const setImmediatePromise = promisify(setImmediate) + +describe('Atem', () => { + beforeEach(() => { + (AtemSocket as any).mockClear() + }) + + test('constructor test 1', async () => { + const conn = new Atem({ disableMultithreaded: true, externalLog: () => null }) + + try { + const socket = (conn as any).socket as AtemSocket + expect(socket).toBeTruthy() + + expect(AtemSocket).toHaveBeenCalledTimes(1) + expect(AtemSocket).toHaveBeenCalledWith({ + address: '', + debug: false, + disableMultithreaded: true, + log: (conn as any)._log, + port: DEFAULT_PORT + }) + } finally { + cleanupAtem(conn) + } + }) + test('constructor test 2', async () => { + const conn = new Atem({ debug: true, address: 'test1', port: 23 }) + + try { + const socket = (conn as any).socket as AtemSocket + expect(socket).toBeTruthy() + + expect(AtemSocket).toHaveBeenCalledTimes(1) + expect(AtemSocket).toHaveBeenCalledWith({ + address: 'test1', + debug: true, + disableMultithreaded: false, + log: (conn as any)._log, + port: 23 + }) + } finally { + cleanupAtem(conn) + } + }) + + test('connect', async () => { + const conn = new Atem({ debug: true, address: 'test1', port: 23 }) + + try { + const socket = (conn as any).socket as AtemSocket + expect(socket).toBeTruthy() + + socket.connect = jest.fn(() => Promise.resolve(5) as any) + + const res = conn.connect('127.9.8.7', 98) + expect(await res).toEqual(5) + + expect(socket.connect).toHaveBeenCalledTimes(1) + expect(socket.connect).toHaveBeenCalledWith('127.9.8.7', 98) + + } finally { + cleanupAtem(conn) + } + }) + + test('disconnect', async () => { + const conn = new Atem({ debug: true, address: 'test1', port: 23 }) + + try { + const socket = (conn as any).socket as AtemSocket + expect(socket).toBeTruthy() + + socket.disconnect = jest.fn(() => Promise.resolve(35) as any) + + const res = await conn.disconnect() + expect(res).toEqual(35) + + expect(socket.disconnect).toHaveBeenCalledTimes(1) + expect(socket.disconnect).toHaveBeenCalledWith() + + } finally { + cleanupAtem(conn) + } + }) + + test('sendCommand - good', async () => { + (AtemSocket as any).mockImplementation(() => new EventEmitter()) + const conn = new Atem({ debug: true, address: 'test1', port: 23 }) + + try { + const socket = (conn as any).socket as AtemSocket + expect(socket).toBeTruthy() + + let nextTrackId = 123 + Object.defineProperty(socket, 'nextCommandTrackingId', { + get: jest.fn(() => nextTrackId++), + set: jest.fn() + }) + expect(socket.nextCommandTrackingId).toEqual(123) + + socket._sendCommand = jest.fn(() => Promise.resolve(35) as any) + + const sentQueue = (conn as any)._sentQueue as object + expect(Object.keys(sentQueue)).toHaveLength(0) + + const cmd = new CutCommand(0) + const res = conn.sendCommand(cmd) + await setImmediatePromise() + expect(Object.keys(sentQueue)).toHaveLength(1) + + expect(socket._sendCommand).toHaveBeenCalledTimes(1) + expect(socket._sendCommand).toHaveBeenCalledWith(cmd, 124) + + // Trigger the ack, and it should switfy resolve + socket.emit(IPCMessageType.CommandAcknowledged, { trackingId: 124 }) + expect(Object.keys(sentQueue)).toHaveLength(0) + + // Finally, it should now resolve without a timeout + expect(await res).toEqual(cmd) + } finally { + cleanupAtem(conn) + } + }, 500) + + test('sendCommand - timeout', async () => { + (AtemSocket as any).mockImplementation(() => new EventEmitter()) + const conn = new Atem({ debug: true, address: 'test1', port: 23 }) + + try { + const socket = (conn as any).socket as AtemSocket + expect(socket).toBeTruthy() + + let nextTrackId = 123 + Object.defineProperty(socket, 'nextCommandTrackingId', { + get: jest.fn(() => nextTrackId++), + set: jest.fn() + }) + expect(socket.nextCommandTrackingId).toEqual(123) + + socket._sendCommand = jest.fn(() => Promise.resolve(35) as any) + + const sentQueue = (conn as any)._sentQueue as object + expect(Object.keys(sentQueue)).toHaveLength(0) + + const cmd = new CutCommand(0) + const res = conn.sendCommand(cmd) + await setImmediatePromise() + expect(Object.keys(sentQueue)).toHaveLength(1) + + expect(socket._sendCommand).toHaveBeenCalledTimes(1) + expect(socket._sendCommand).toHaveBeenCalledWith(cmd, 124) + + // Trigger the timeout, and it should switfy resolve + socket.emit(IPCMessageType.CommandTimeout, { trackingId: 124 }) + expect(Object.keys(sentQueue)).toHaveLength(0) + + // Finally, it should now resolve without a timeout + try { + await res + // Should not get here + expect(false).toBeTruthy() + } catch (e) { + expect(e).toEqual(cmd) + } + // expect(await res).toEqual(cmd) + } finally { + cleanupAtem(conn) + } + }, 500) + + test('sendCommand - send error', async () => { + (AtemSocket as any).mockImplementation(() => new EventEmitter()) + const conn = new Atem({ debug: true, address: 'test1', port: 23 }) + + try { + const socket = (conn as any).socket as AtemSocket + expect(socket).toBeTruthy() + + let nextTrackId = 123 + Object.defineProperty(socket, 'nextCommandTrackingId', { + get: jest.fn(() => nextTrackId++), + set: jest.fn() + }) + expect(socket.nextCommandTrackingId).toEqual(123) + + socket._sendCommand = jest.fn(() => Promise.reject(35) as any) + + const sentQueue = (conn as any)._sentQueue as object + expect(Object.keys(sentQueue)).toHaveLength(0) + + const cmd = new CutCommand(0) + const res = conn.sendCommand(cmd) + + // Send command should be called + expect(socket._sendCommand).toHaveBeenCalledTimes(1) + expect(socket._sendCommand).toHaveBeenCalledWith(cmd, 124) + + expect(Object.keys(sentQueue)).toHaveLength(0) + + // Finally, it should now resolve without a timeout + try { + await res + // Should not get here + expect(false).toBeTruthy() + } catch (e) { + // Should be the error thrown by sendCommand + expect(e).toEqual(35) + } + // expect(await res).toEqual(cmd) + } finally { + cleanupAtem(conn) + } + }, 500) + +}) diff --git a/src/__tests__/index.spec.ts b/src/__tests__/index.spec.ts index 021c4872e..278503cc5 100644 --- a/src/__tests__/index.spec.ts +++ b/src/__tests__/index.spec.ts @@ -1,9 +1,5 @@ import { Atem, Enums } from '../index' - -function cleanupAtem (atem: Atem) { - const atem2 = atem as any - atem2.dataTransferManager.stopCommandSending() -} +import { cleanupAtem } from './lib' test('Simple test', async () => { const nb = new Atem({ disableMultithreaded: true }) diff --git a/src/__tests__/lib.ts b/src/__tests__/lib.ts new file mode 100644 index 000000000..09c44ee96 --- /dev/null +++ b/src/__tests__/lib.ts @@ -0,0 +1,6 @@ +import { Atem } from '../atem' + +export function cleanupAtem (atem: Atem) { + const atem2 = atem as any + atem2.dataTransferManager.stopCommandSending() +} diff --git a/src/atem.ts b/src/atem.ts index 27eb9963d..4e992ff08 100644 --- a/src/atem.ts +++ b/src/atem.ts @@ -100,20 +100,19 @@ export class Atem extends EventEmitter { } public disconnect (): Promise { - return new Promise((resolve, reject) => { - this.socket.disconnect().then(() => resolve()).catch(reject) - }) + return this.socket.disconnect() } public sendCommand (command: ISerializableCommand): Promise { const commandTrackingId = this.socket.nextCommandTrackingId return new Promise((resolve, reject) => { - this._sentQueue[commandTrackingId] = { - command, - resolve, - reject - } - this.socket._sendCommand(command, commandTrackingId).catch(reject) + this.socket._sendCommand(command, commandTrackingId).then(() => { + this._sentQueue[commandTrackingId] = { + command, + resolve, + reject + } + }).catch(reject) }) } From caa9ac54d39173476c75da4cd82919c85c31c67a Mon Sep 17 00:00:00 2001 From: Julian Waller Date: Sun, 1 Dec 2019 21:22:53 +0000 Subject: [PATCH 29/68] feat(tests): For atemsocket class (child process wrapper) --- jest.config.js | 4 +- package.json | 3 +- src/__tests__/atem.spec.ts | 70 +-- src/atem.ts | 2 +- src/lib/__mocks__/dgram.ts | 5 +- src/lib/__tests__/atemSocket.spec.ts | 582 +++++++++++++++++++++++++ src/lib/__tests__/socket-child.spec.ts | 82 ++-- src/lib/atemSocket.ts | 48 +- src/lib/atemSocketChild.ts | 88 ++-- src/socket-child.ts | 78 ---- yarn.lock | 7 +- 11 files changed, 742 insertions(+), 227 deletions(-) create mode 100644 src/lib/__tests__/atemSocket.spec.ts delete mode 100644 src/socket-child.ts diff --git a/jest.config.js b/jest.config.js index a99a73613..8f7770d92 100644 --- a/jest.config.js +++ b/jest.config.js @@ -27,8 +27,8 @@ module.exports = { coverageDirectory: "./coverage/", collectCoverage: true, collectCoverageFrom: [ - "**/src/**/**", - "!**/src/@types/**", + "src/**/*.{js,ts}", + "!**/@types/**", "!**/__tests__/**", "!**/__mocks__/**", '!**/node_modules/**', diff --git a/package.json b/package.json index f95007fb0..72a7e56df 100644 --- a/package.json +++ b/package.json @@ -112,11 +112,10 @@ "video" ], "dependencies": { - "emittery": "^0.5.1", "exit-hook": "^2.0.0", "nanotimer": "^0.3.15", "threadedclass": "^0.6.8", - "tslib": "^1.9.0", + "tslib": "^1.10.0", "wavefile": "^8.4.4" }, "standard-version": { diff --git a/src/__tests__/atem.spec.ts b/src/__tests__/atem.spec.ts index 4abd2a052..b5b4bfd67 100644 --- a/src/__tests__/atem.spec.ts +++ b/src/__tests__/atem.spec.ts @@ -102,14 +102,14 @@ describe('Atem', () => { const socket = (conn as any).socket as AtemSocket expect(socket).toBeTruthy() - let nextTrackId = 123 + let nextId = 123 Object.defineProperty(socket, 'nextCommandTrackingId', { - get: jest.fn(() => nextTrackId++), + get: jest.fn(() => nextId++), set: jest.fn() }) expect(socket.nextCommandTrackingId).toEqual(123) - socket._sendCommand = jest.fn(() => Promise.resolve(35) as any) + socket.sendCommand = jest.fn(() => Promise.resolve(35) as any) const sentQueue = (conn as any)._sentQueue as object expect(Object.keys(sentQueue)).toHaveLength(0) @@ -119,61 +119,15 @@ describe('Atem', () => { await setImmediatePromise() expect(Object.keys(sentQueue)).toHaveLength(1) - expect(socket._sendCommand).toHaveBeenCalledTimes(1) - expect(socket._sendCommand).toHaveBeenCalledWith(cmd, 124) + expect(socket.sendCommand).toHaveBeenCalledTimes(1) + expect(socket.sendCommand).toHaveBeenCalledWith(cmd, 124) // Trigger the ack, and it should switfy resolve - socket.emit(IPCMessageType.CommandAcknowledged, { trackingId: 124 }) + socket.emit(IPCMessageType.CommandAcknowledged, 124) expect(Object.keys(sentQueue)).toHaveLength(0) // Finally, it should now resolve without a timeout - expect(await res).toEqual(cmd) - } finally { - cleanupAtem(conn) - } - }, 500) - - test('sendCommand - timeout', async () => { - (AtemSocket as any).mockImplementation(() => new EventEmitter()) - const conn = new Atem({ debug: true, address: 'test1', port: 23 }) - - try { - const socket = (conn as any).socket as AtemSocket - expect(socket).toBeTruthy() - - let nextTrackId = 123 - Object.defineProperty(socket, 'nextCommandTrackingId', { - get: jest.fn(() => nextTrackId++), - set: jest.fn() - }) - expect(socket.nextCommandTrackingId).toEqual(123) - - socket._sendCommand = jest.fn(() => Promise.resolve(35) as any) - - const sentQueue = (conn as any)._sentQueue as object - expect(Object.keys(sentQueue)).toHaveLength(0) - - const cmd = new CutCommand(0) - const res = conn.sendCommand(cmd) - await setImmediatePromise() - expect(Object.keys(sentQueue)).toHaveLength(1) - - expect(socket._sendCommand).toHaveBeenCalledTimes(1) - expect(socket._sendCommand).toHaveBeenCalledWith(cmd, 124) - - // Trigger the timeout, and it should switfy resolve - socket.emit(IPCMessageType.CommandTimeout, { trackingId: 124 }) - expect(Object.keys(sentQueue)).toHaveLength(0) - - // Finally, it should now resolve without a timeout - try { - await res - // Should not get here - expect(false).toBeTruthy() - } catch (e) { - expect(e).toEqual(cmd) - } - // expect(await res).toEqual(cmd) + expect(await res).toBeUndefined() } finally { cleanupAtem(conn) } @@ -187,14 +141,14 @@ describe('Atem', () => { const socket = (conn as any).socket as AtemSocket expect(socket).toBeTruthy() - let nextTrackId = 123 + let nextId = 123 Object.defineProperty(socket, 'nextCommandTrackingId', { - get: jest.fn(() => nextTrackId++), + get: jest.fn(() => nextId++), set: jest.fn() }) expect(socket.nextCommandTrackingId).toEqual(123) - socket._sendCommand = jest.fn(() => Promise.reject(35) as any) + socket.sendCommand = jest.fn(() => Promise.reject(35) as any) const sentQueue = (conn as any)._sentQueue as object expect(Object.keys(sentQueue)).toHaveLength(0) @@ -203,8 +157,8 @@ describe('Atem', () => { const res = conn.sendCommand(cmd) // Send command should be called - expect(socket._sendCommand).toHaveBeenCalledTimes(1) - expect(socket._sendCommand).toHaveBeenCalledWith(cmd, 124) + expect(socket.sendCommand).toHaveBeenCalledTimes(1) + expect(socket.sendCommand).toHaveBeenCalledWith(cmd, 124) expect(Object.keys(sentQueue)).toHaveLength(0) diff --git a/src/atem.ts b/src/atem.ts index 4e992ff08..c9add8ad3 100644 --- a/src/atem.ts +++ b/src/atem.ts @@ -106,7 +106,7 @@ export class Atem extends EventEmitter { public sendCommand (command: ISerializableCommand): Promise { const commandTrackingId = this.socket.nextCommandTrackingId return new Promise((resolve, reject) => { - this.socket._sendCommand(command, commandTrackingId).then(() => { + this.socket.sendCommand(command, commandTrackingId).then(() => { this._sentQueue[commandTrackingId] = { command, resolve, diff --git a/src/lib/__mocks__/dgram.ts b/src/lib/__mocks__/dgram.ts index 424edbea4..b33792a40 100644 --- a/src/lib/__mocks__/dgram.ts +++ b/src/lib/__mocks__/dgram.ts @@ -2,6 +2,7 @@ import { EventEmitter } from 'events' import { SocketType, RemoteInfo } from 'dgram' import 'jest-extended' import { DEFAULT_PORT } from '../../atem' +import { InstalledClock } from 'lolex' export class Socket extends EventEmitter { public isOpen: boolean = false @@ -15,7 +16,7 @@ export class Socket extends EventEmitter { public sendImpl?: (msg: Buffer) => void - public emitMessage (msg: Buffer) { + public async emitMessage (clock: InstalledClock, msg: Buffer) { expect(Buffer.isBuffer(msg)).toBeTruthy() const rinfo: RemoteInfo = { @@ -25,6 +26,8 @@ export class Socket extends EventEmitter { size: msg.length } this.emit('message', msg, rinfo) + + await clock.tickAsync(0) } public bind (port?: number, address?: string, callback?: () => void): void { diff --git a/src/lib/__tests__/atemSocket.spec.ts b/src/lib/__tests__/atemSocket.spec.ts new file mode 100644 index 000000000..c5573fca2 --- /dev/null +++ b/src/lib/__tests__/atemSocket.spec.ts @@ -0,0 +1,582 @@ +import { CutCommand, ProductIdentifierCommand, InitCompleteCommand, VersionCommand, ProgramInputUpdateCommand, PreviewInputUpdateCommand, ISerializableCommand, BasicWritableCommand, DeserializedCommand } from '../../commands' +import { IPCMessageType, ProtocolVersion, Model } from '../../enums' +import { AtemSocket } from '../atemSocket' +import { ThreadedClass, ThreadedClassManager } from 'threadedclass' +import { Buffer } from 'buffer' +import { CommandParser } from '../atemCommandParser' +import * as lolex from 'lolex' +import { AtemSocketChild } from '../atemSocketChild' +// import { promisify } from 'util' +jest.mock('../atemSocketChild') + +export class AtemSocketChildMock { + public onDisconnect?: () => Promise + public onLog?: (message: string) => Promise + public onCommandReceived?: (payload: Buffer, packetId: number) => Promise + public onCommandAcknowledged?: (packetId: number, trackingId: number) => Promise + + // constructor (_options: { address: string, port: number, debug: boolean }, onDisconnect: () => Promise, onLog: (message: string) => Promise, onCommandReceived: (payload: Buffer, packetId: number) => Promise, onCommandAcknowledged: (packetId: number, trackingId: number) => Promise) { + // // this._debug = options.debug + // // this._address = options.address + // // this._port = options.port + + // this.onDisconnect = null + // this.onLog = onLog + // this.onCommandReceived = onCommandReceived + // this.onCommandAcknowledged = onCommandAcknowledged + // } + + public hackSetFuncs (onDisconnect: () => Promise, onLog: (message: string) => Promise, onCommandReceived: (payload: Buffer, packetId: number) => Promise, onCommandAcknowledged: (packetId: number, trackingId: number) => Promise) { + this.onDisconnect = onDisconnect + this.onLog = onLog + this.onCommandReceived = onCommandReceived + this.onCommandAcknowledged = onCommandAcknowledged + } + + public connect = jest.fn() + public disconnect = jest.fn(() => Promise.resolve(87)) + public sendCommand = jest.fn() +} + +const AtemSocketChildSingleton = new AtemSocketChildMock() +;(AtemSocketChild as any).mockImplementation(() => AtemSocketChildSingleton) + +class ThreadedClassManagerMock { + public handlers: Function[] = [] + + public onEvent (_socketProcess: any, _event: string, cb: Function): { stop: () => void } { + ThreadedClassManagerSingleton.handlers.push(cb) + return { stop: () => null } + } +} +const ThreadedClassManagerSingleton = new ThreadedClassManagerMock() +jest.spyOn(ThreadedClassManager, 'onEvent').mockImplementation(ThreadedClassManagerSingleton.onEvent) + +describe('AtemSocket', () => { + let clock: lolex.InstalledClock + + function mockClear (lite?: boolean) { + (AtemSocketChild as any).mockClear() + AtemSocketChildSingleton.connect.mockClear() + AtemSocketChildSingleton.disconnect.mockClear() + AtemSocketChildSingleton.sendCommand.mockClear() + + if (!lite) { + AtemSocketChildSingleton.onLog = undefined + AtemSocketChildSingleton.onDisconnect = undefined + AtemSocketChildSingleton.onCommandAcknowledged = undefined + AtemSocketChildSingleton.onCommandReceived = undefined + } + } + beforeEach(() => { + clock = lolex.install() + mockClear() + ThreadedClassManagerSingleton.handlers = [] + }) + afterEach(() => { + clock.uninstall() + }) + + function createSocket () { + return new AtemSocket({ + debug: false, + address: '', + port: 890, + disableMultithreaded: true, + log: console.log + }) + } + + function getChild (socket: AtemSocket): ThreadedClass | undefined { + return (socket as any)._socketProcess + } + + test('connect initial', async () => { + const socket = createSocket() + expect(getChild(socket)).toBeFalsy() + + await socket.connect() + + expect((socket as any)._address).toEqual('') + expect((socket as any)._port).toEqual(890) + + expect(getChild(socket)).toBeTruthy() + // Connect was not called explicitly + expect(AtemSocketChildSingleton.connect).toHaveBeenCalledTimes(1) + expect(AtemSocketChildSingleton.disconnect).toHaveBeenCalledTimes(0) + expect(AtemSocketChildSingleton.sendCommand).toHaveBeenCalledTimes(0) + + // New child was constructed + expect(AtemSocketChild).toHaveBeenCalledTimes(1) + expect(AtemSocketChild).toHaveBeenCalledWith({ address: '', port: 890, debug: false }, null, null, null, null) + }) + test('connect initial with params', async () => { + const socket = createSocket() + expect(getChild(socket)).toBeFalsy() + + await socket.connect('abc', 765) + + expect((socket as any)._address).toEqual('abc') + expect((socket as any)._port).toEqual(765) + + expect(getChild(socket)).toBeTruthy() + // Connect was not called explicitly + expect(AtemSocketChildSingleton.connect).toHaveBeenCalledTimes(1) + expect(AtemSocketChildSingleton.disconnect).toHaveBeenCalledTimes(0) + expect(AtemSocketChildSingleton.sendCommand).toHaveBeenCalledTimes(0) + + // New child was constructed + expect(AtemSocketChild).toHaveBeenCalledTimes(1) + expect(AtemSocketChild).toHaveBeenCalledWith({ address: 'abc', port: 765, debug: false }, null, null, null, null) + }) + test('connect change details', async () => { + const socket = createSocket() + expect(getChild(socket)).toBeFalsy() + + await socket.connect() + + expect((socket as any)._address).toEqual('') + expect((socket as any)._port).toEqual(890) + + expect(getChild(socket)).toBeTruthy() + + // Connect was not called explicitly + expect(AtemSocketChild).toHaveBeenCalledTimes(1) + expect(AtemSocketChildSingleton.connect).toHaveBeenCalledTimes(1) + expect(AtemSocketChildSingleton.disconnect).toHaveBeenCalledTimes(0) + expect(AtemSocketChildSingleton.sendCommand).toHaveBeenCalledTimes(0) + + mockClear() + + await socket.connect('new', 455) + + expect((socket as any)._address).toEqual('new') + expect((socket as any)._port).toEqual(455) + + // connect was called explicitly + expect(AtemSocketChild).toHaveBeenCalledTimes(0) + expect(AtemSocketChildSingleton.connect).toHaveBeenCalledTimes(1) + expect(AtemSocketChildSingleton.disconnect).toHaveBeenCalledTimes(0) + expect(AtemSocketChildSingleton.sendCommand).toHaveBeenCalledTimes(0) + expect(AtemSocketChildSingleton.connect).toHaveBeenCalledWith('new', 455) + }) + + test('nextCommandTrackingId', () => { + const socket = createSocket() + + expect(socket.nextCommandTrackingId).toEqual(1) + expect(socket.nextCommandTrackingId).toEqual(2) + expect(socket.nextCommandTrackingId).toEqual(3) + }) + + test('disconnect', async () => { + const socket = createSocket() + expect(getChild(socket)).toBeFalsy() + + await socket.connect() + + expect(getChild(socket)).toBeTruthy() + mockClear() + + await socket.disconnect() + + // connect was called explicitly + expect(AtemSocketChild).toHaveBeenCalledTimes(0) + expect(AtemSocketChildSingleton.connect).toHaveBeenCalledTimes(0) + expect(AtemSocketChildSingleton.disconnect).toHaveBeenCalledTimes(1) + expect(AtemSocketChildSingleton.sendCommand).toHaveBeenCalledTimes(0) + expect(AtemSocketChildSingleton.disconnect).toHaveBeenCalledWith() + }) + + test('disconnect - not open', async () => { + const socket = createSocket() + expect(getChild(socket)).toBeFalsy() + + await socket.disconnect() + + // connect was called explicitly + expect(AtemSocketChild).toHaveBeenCalledTimes(0) + expect(AtemSocketChildSingleton.connect).toHaveBeenCalledTimes(0) + expect(AtemSocketChildSingleton.disconnect).toHaveBeenCalledTimes(0) + expect(AtemSocketChildSingleton.sendCommand).toHaveBeenCalledTimes(0) + }) + + test('sendCommand - not open', async () => { + const socket = createSocket() + expect(getChild(socket)).toBeFalsy() + + try { + const cmd = new CutCommand(0) + await socket.sendCommand(cmd, 1) + // Should not get here + expect(false).toBeTruthy() + } catch (e) { + expect(e.message).toEqual('Socket process is not open') + } + + // connect was called explicitly + expect(AtemSocketChild).toHaveBeenCalledTimes(0) + expect(AtemSocketChildSingleton.connect).toHaveBeenCalledTimes(0) + expect(AtemSocketChildSingleton.disconnect).toHaveBeenCalledTimes(0) + expect(AtemSocketChildSingleton.sendCommand).toHaveBeenCalledTimes(0) + }) + + test('sendCommand - not serializable', async () => { + const socket = createSocket() + expect(getChild(socket)).toBeFalsy() + + await socket.connect() + mockClear() + expect(getChild(socket)).toBeTruthy() + + const cmd = new ProductIdentifierCommand({ + model: Model.OneME, + productIdentifier: 'ATEM OneME' + }) as any as ISerializableCommand + expect(cmd.serialize).toBeFalsy() + try { + await socket.sendCommand(cmd, 1) + // Should not get here + expect(false).toBeTruthy() + } catch (e) { + expect(e.message).toEqual('Command is not serializable') + } + + // connect was called explicitly + expect(AtemSocketChild).toHaveBeenCalledTimes(0) + expect(AtemSocketChildSingleton.connect).toHaveBeenCalledTimes(0) + expect(AtemSocketChildSingleton.disconnect).toHaveBeenCalledTimes(0) + expect(AtemSocketChildSingleton.sendCommand).toHaveBeenCalledTimes(0) + }) + + test('sendCommand', async () => { + const socket = createSocket() + expect(getChild(socket)).toBeFalsy() + + await socket.connect() + mockClear() + expect(getChild(socket)).toBeTruthy() + + class MockCommand extends BasicWritableCommand<{}> { + public static readonly rawName = 'TEST' + + public serialize () { + return Buffer.from('test payload') + } + } + + const cmd = new MockCommand({}) + const cmdId = 836 + await socket.sendCommand(cmd, cmdId) + + // connect was called explicitly + expect(AtemSocketChild).toHaveBeenCalledTimes(0) + expect(AtemSocketChildSingleton.connect).toHaveBeenCalledTimes(0) + expect(AtemSocketChildSingleton.disconnect).toHaveBeenCalledTimes(0) + expect(AtemSocketChildSingleton.sendCommand).toHaveBeenCalledTimes(1) + + const expectedBuffer = Buffer.concat([Buffer.from([0, 20, 0, 0, 84, 69, 83, 84]), cmd.serialize()]) + expect(AtemSocketChildSingleton.sendCommand).toHaveBeenCalledWith(expectedBuffer, cmdId) + }) + + test('events', async () => { + const socket = createSocket() + expect(getChild(socket)).toBeFalsy() + + await socket.connect() + expect(getChild(socket)).toBeTruthy() + + const disconnect = jest.fn() + // const log = jest.fn() + const ack = jest.fn() + + socket.on(IPCMessageType.Disconnect, disconnect) + socket.on(IPCMessageType.CommandAcknowledged, ack) + + expect(AtemSocketChildSingleton.onDisconnect).toBeDefined() + await AtemSocketChildSingleton.onDisconnect!() + await clock.tickAsync(0) + expect(disconnect).toHaveBeenCalledTimes(1) + + expect(AtemSocketChildSingleton.onCommandAcknowledged).toBeDefined() + await AtemSocketChildSingleton.onCommandAcknowledged!(675, 98) + await clock.tickAsync(0) + expect(ack).toHaveBeenCalledTimes(1) + expect(ack).toHaveBeenCalledWith({ packetId: 675, trackingId: 98 }) + + }) + + test('receive - init complete', async () => { + const socket = createSocket() + expect(getChild(socket)).toBeFalsy() + + await socket.connect() + mockClear(true) + expect(getChild(socket)).toBeTruthy() + + const connect = jest.fn() + const error = jest.fn() + const change = jest.fn() + + socket.on('connect', connect) + socket.on('error', error) + socket.on('receivedStateChange', change) + + const parser = (socket as any)._commandParser as CommandParser + expect(parser).toBeTruthy() + const parserSpy = jest.spyOn(parser, 'commandFromRawName') + + const testBuffer = Buffer.from([0, 8, 0, 0, ...Buffer.from('InCm', 'ascii')]) + const pktId = 822 + expect(AtemSocketChildSingleton.onCommandReceived).toBeDefined() + await AtemSocketChildSingleton.onCommandReceived!(testBuffer, pktId) + await clock.tickAsync(0) + + expect(connect).toHaveBeenCalledTimes(1) + expect(error).toHaveBeenCalledTimes(0) + expect(change).toHaveBeenCalledTimes(1) + + expect(parserSpy).toHaveBeenCalledTimes(1) + expect(parserSpy).toHaveBeenCalledWith('InCm') + + // A change with the command + const expectedCmd = new InitCompleteCommand() + expect(change).toHaveBeenCalledWith(expectedCmd) + }) + test('receive - protocol version', async () => { + const socket = createSocket() + expect(getChild(socket)).toBeFalsy() + + await socket.connect() + mockClear(true) + expect(getChild(socket)).toBeTruthy() + + const connect = jest.fn() + const error = jest.fn() + const change = jest.fn() + + socket.on('connect', connect) + socket.on('error', error) + socket.on('receivedStateChange', change) + + const parser = (socket as any)._commandParser as CommandParser + expect(parser).toBeTruthy() + const parserSpy = jest.spyOn(parser, 'commandFromRawName') + expect(parser.version).toEqual(ProtocolVersion.V7_2) // Default + + const testBuffer = Buffer.from([0, 12, 0, 0, ...Buffer.from('_ver', 'ascii'), 0x01, 0x02, 0x03, 0x04]) + const pktId = 822 + expect(AtemSocketChildSingleton.onCommandReceived).toBeDefined() + await AtemSocketChildSingleton.onCommandReceived!(testBuffer, pktId) + await clock.tickAsync(0) + + expect(connect).toHaveBeenCalledTimes(0) + expect(error).toHaveBeenCalledTimes(0) + expect(change).toHaveBeenCalledTimes(1) + + expect(parserSpy).toHaveBeenCalledTimes(1) + expect(parserSpy).toHaveBeenCalledWith('_ver') + + expect(parser.version).toEqual(0x01020304) // Parsed + + // A change with the command + const expectedCmd = new VersionCommand(0x01020304) + expect(change).toHaveBeenCalledWith(expectedCmd) + }) + test('receive - multiple commands', async () => { + const socket = createSocket() + expect(getChild(socket)).toBeFalsy() + + await socket.connect() + mockClear(true) + expect(getChild(socket)).toBeTruthy() + + const connect = jest.fn() + const error = jest.fn() + const change = jest.fn() + + socket.on('connect', connect) + socket.on('error', error) + socket.on('receivedStateChange', change) + + const parser = (socket as any)._commandParser as CommandParser + expect(parser).toBeTruthy() + const parserSpy = jest.spyOn(parser, 'commandFromRawName') + expect(parser.version).toEqual(ProtocolVersion.V7_2) // Default + + const expectedCmd1 = new ProgramInputUpdateCommand(0, { source: 0x0123 }) + const expectedCmd2 = new PreviewInputUpdateCommand(1, { source: 0x0444 }) + + const testCmd1 = Buffer.from([0, 12, 0, 0, ...Buffer.from(ProgramInputUpdateCommand.rawName, 'ascii'), 0x00, 0x00, 0x01, 0x23]) + const testCmd2 = Buffer.from([0, 12, 0, 0, ...Buffer.from(PreviewInputUpdateCommand.rawName, 'ascii'), 0x01, 0x00, 0x04, 0x44]) + const pktId = 822 + expect(AtemSocketChildSingleton.onCommandReceived).toBeDefined() + await AtemSocketChildSingleton.onCommandReceived!(Buffer.concat([testCmd1, testCmd2]), pktId) + await clock.tickAsync(0) + + expect(connect).toHaveBeenCalledTimes(0) + expect(error).toHaveBeenCalledTimes(0) + expect(change).toHaveBeenCalledTimes(2) + + expect(parserSpy).toHaveBeenCalledTimes(2) + expect(parserSpy).toHaveBeenCalledWith(ProgramInputUpdateCommand.rawName) + expect(parserSpy).toHaveBeenCalledWith(PreviewInputUpdateCommand.rawName) + + // A change with the command + expect(change).toHaveBeenCalledWith(expectedCmd1) + expect(change).toHaveBeenCalledWith(expectedCmd2) + }) + test('receive - empty buffer', async () => { + const socket = createSocket() + expect(getChild(socket)).toBeFalsy() + + await socket.connect() + mockClear(true) + expect(getChild(socket)).toBeTruthy() + + const connect = jest.fn() + const error = jest.fn() + const change = jest.fn() + + socket.on('connect', connect) + socket.on('error', error) + socket.on('receivedStateChange', change) + + const testBuffer = Buffer.alloc(0) + const pktId = 822 + expect(AtemSocketChildSingleton.onCommandReceived).toBeDefined() + await AtemSocketChildSingleton.onCommandReceived!(testBuffer, pktId) + await clock.tickAsync(0) + + expect(connect).toHaveBeenCalledTimes(0) + expect(error).toHaveBeenCalledTimes(0) + expect(change).toHaveBeenCalledTimes(0) + }) + test('receive - corrupt', async () => { + const socket = createSocket() + expect(getChild(socket)).toBeFalsy() + + await socket.connect() + mockClear(true) + expect(getChild(socket)).toBeTruthy() + + const connect = jest.fn() + const error = jest.fn() + const change = jest.fn() + + socket.on('connect', connect) + socket.on('error', error) + socket.on('receivedStateChange', change) + + const testBuffer = Buffer.alloc(10, 0) + const pktId = 822 + expect(AtemSocketChildSingleton.onCommandReceived).toBeDefined() + await AtemSocketChildSingleton.onCommandReceived!(testBuffer, pktId) + await clock.tickAsync(0) + + expect(connect).toHaveBeenCalledTimes(0) + expect(error).toHaveBeenCalledTimes(0) + expect(change).toHaveBeenCalledTimes(0) + }) + test('receive - deserialize error', async () => { + const socket = createSocket() + expect(getChild(socket)).toBeFalsy() + + await socket.connect() + mockClear(true) + expect(getChild(socket)).toBeTruthy() + + const connect = jest.fn() + const error = jest.fn() + const change = jest.fn() + + socket.on('connect', connect) + socket.on('error', error) + socket.on('receivedStateChange', change) + + class BrokenCommand extends DeserializedCommand<{}> { + public static readonly rawName = 'TEST' + + public deserialize () { + throw new Error('Deserialize failure') + } + public applyToState (): string[] { + throw new Error('Method not implemented.') + } + } + + const parser = (socket as any)._commandParser as CommandParser + expect(parser).toBeTruthy() + const parserSpy = jest.spyOn(parser, 'commandFromRawName') + parserSpy.mockImplementationOnce(() => new BrokenCommand({})) + + // const expectedCmd1 = new ProgramInputUpdateCommand(0, { source: 0x0123 }) + const expectedCmd2 = new PreviewInputUpdateCommand(1, { source: 0x0444 }) + + const testCmd1 = Buffer.from([0, 12, 0, 0, ...Buffer.from(ProgramInputUpdateCommand.rawName, 'ascii'), 0x00, 0x00, 0x01, 0x23]) + const testCmd2 = Buffer.from([0, 12, 0, 0, ...Buffer.from(PreviewInputUpdateCommand.rawName, 'ascii'), 0x01, 0x00, 0x04, 0x44]) + const pktId = 822 + expect(AtemSocketChildSingleton.onCommandReceived).toBeDefined() + await AtemSocketChildSingleton.onCommandReceived!(Buffer.concat([testCmd1, testCmd2]), pktId) + await clock.tickAsync(0) + + expect(connect).toHaveBeenCalledTimes(0) + expect(error).toHaveBeenCalledTimes(1) + expect(change).toHaveBeenCalledTimes(1) + + expect(parserSpy).toHaveBeenCalledTimes(2) + expect(parserSpy).toHaveBeenCalledWith(ProgramInputUpdateCommand.rawName) + expect(parserSpy).toHaveBeenCalledWith(PreviewInputUpdateCommand.rawName) + + // The second command should have been a success + expect(change).toHaveBeenCalledWith(expectedCmd2) + expect(error).toHaveBeenCalledWith(new Error('Deserialize failure')) + }) + + test('receive - thread restart', async () => { + const socket = createSocket() + expect(getChild(socket)).toBeFalsy() + + await socket.connect() + mockClear() + expect(getChild(socket)).toBeTruthy() + + const connect = socket.connect = jest.fn(() => Promise.resolve()) + + const restarted = jest.fn() + socket.on('restarted', restarted) + + expect(ThreadedClassManagerSingleton.handlers).toHaveLength(1) + // simulate a restart + ThreadedClassManagerSingleton.handlers.forEach(handler => handler()) + + expect(restarted).toHaveBeenCalledTimes(1) + expect(connect).toHaveBeenCalledTimes(1) + }) + // test('receive - thread restart with error', async () => { + // const socket = createSocket() + // expect(getChild(socket)).toBeFalsy() + + // await socket.connect() + // mockClear() + // expect(getChild(socket)).toBeTruthy() + + // const connect = socket.connect = jest.fn(() => Promise.reject('soemthing')) + + // const restarted = jest.fn() + // const error = jest.fn() + // socket.on('restarted', restarted) + // socket.on('error', error) + + // expect(ThreadedClassManagerSingleton.handlers).toHaveLength(1) + // // simulate a restart + // ThreadedClassManagerSingleton.handlers.forEach(handler => handler()) + // await promisify(setImmediate)() + + // expect(restarted).toHaveBeenCalledTimes(1) + // expect(connect).toHaveBeenCalledTimes(1) + // expect(error).toHaveBeenCalledTimes(1) + // expect(error).toHaveBeenCalledWith('soemthing') + // }) + +}) diff --git a/src/lib/__tests__/socket-child.spec.ts b/src/lib/__tests__/socket-child.spec.ts index 2df392022..1a3a172de 100644 --- a/src/lib/__tests__/socket-child.spec.ts +++ b/src/lib/__tests__/socket-child.spec.ts @@ -29,8 +29,18 @@ function fakeConnect (child: AtemSocketChild) { child2._address = '127.0.0.1' } -function createSocketChild (onCommandReceived?: (payload: Buffer, packetId: number) => void, onCommandAcknowledged?: (packetId: number, trackingId: number) => void) { - return new AtemSocketChild(() => null, () => null, onCommandReceived || (() => null), onCommandAcknowledged || (() => null)) +function createSocketChild (onCommandReceived?: (payload: Buffer, packetId: number) => Promise, onCommandAcknowledged?: (packetId: number, trackingId: number) => Promise) { + return new AtemSocketChild( + { + address: ADDRESS, + port: DEFAULT_PORT, + debug: false + }, + () => Promise.resolve(), + () => Promise.resolve(), + onCommandReceived || (() => Promise.resolve()), + onCommandAcknowledged || (() => Promise.resolve()) + ) } describe('SocketChild', () => { @@ -59,7 +69,7 @@ describe('SocketChild', () => { } expect(getState(child)).toEqual(ConnectionState.Closed) - child.connect(ADDRESS) + await child.connect(ADDRESS, DEFAULT_PORT) // Ensure everything has ticked through clock.tick(20) @@ -84,7 +94,7 @@ describe('SocketChild', () => { } // Now get the connection established - socket.emitMessage(Buffer.from([ + await socket.emitMessage(clock, Buffer.from([ 0x10, 0x14, // Length & Type 0x53, 0x1b, // Session Id 0x00, 0x00, // Not acking @@ -95,7 +105,7 @@ describe('SocketChild', () => { ])) // Ensure everything has ticked through - clock.tick(20) + await clock.tickAsync(20) // Confirm something was sent expect(receivedPacket).toBeTruthy() @@ -142,7 +152,7 @@ describe('SocketChild', () => { } } - socket.emitMessage(genAckRequestMessage(1)) + await socket.emitMessage(clock, genAckRequestMessage(1)) // Nothing should have been sent immediately expect(acked).toEqual([]) @@ -186,16 +196,16 @@ describe('SocketChild', () => { } for (let i = 1; i <= 15; i++) { - socket.emitMessage(genAckRequestMessage(i)) + await socket.emitMessage(clock, genAckRequestMessage(i)) } // Nothing should have been sent yet - clock.tick(4) + await clock.tickAsync(4) expect(acked).toEqual([]) expect(gotUnknown).toBeFalse() // One more will trigger an ack - socket.emitMessage(genAckRequestMessage(16)) + await socket.emitMessage(clock, genAckRequestMessage(16)) expect(acked).toEqual([16]) expect(gotUnknown).toBeFalse() acked = [] @@ -215,7 +225,10 @@ describe('SocketChild', () => { test('Inbound commands', async () => { let gotCmds: number[] = [] - const child = createSocketChild(buf => gotCmds.push(buf.length)) + const child = createSocketChild(buf => { + gotCmds.push(buf.length) + return Promise.resolve() + }) try { fakeConnect(child) const socket = getSocket(child) @@ -230,29 +243,29 @@ describe('SocketChild', () => { gotCmds = [] // Nothing - socket.emitMessage(genAckRequestMessage(1)) + await socket.emitMessage(clock, genAckRequestMessage(1)) expect(gotCmds).toEqual([]) expect(gotUnknown).toBeFalse() // Some payload const buffer = Buffer.concat([genAckRequestMessage(2, 1), Buffer.from([0])]) - socket.emitMessage(buffer) + await socket.emitMessage(clock, buffer) expect(gotCmds).toEqual([1]) expect(gotUnknown).toBeFalse() gotCmds = [] // Repeated should not re-emit - socket.emitMessage(buffer) + await socket.emitMessage(clock, buffer) expect(gotCmds).toEqual([]) expect(gotUnknown).toBeFalse() // Previous should not re-emit - socket.emitMessage(Buffer.concat([genAckRequestMessage(1, 1), Buffer.from([0])])) + await socket.emitMessage(clock, Buffer.concat([genAckRequestMessage(1, 1), Buffer.from([0])])) expect(gotCmds).toEqual([]) expect(gotUnknown).toBeFalse() // Another payload - socket.emitMessage(Buffer.concat([genAckRequestMessage(3, 1), Buffer.from([0])])) + await socket.emitMessage(clock, Buffer.concat([genAckRequestMessage(3, 1), Buffer.from([0])])) expect(gotCmds).toEqual([1]) expect(gotUnknown).toBeFalse() gotCmds = [] @@ -267,7 +280,10 @@ describe('SocketChild', () => { test('Inbound commands - around wrap', async () => { let gotCmds: number[] = [] - const child = createSocketChild(buf => gotCmds.push(buf.length)) + const child = createSocketChild(buf => { + gotCmds.push(buf.length) + return Promise.resolve() + }) try { fakeConnect(child) const socket = getSocket(child) @@ -283,50 +299,50 @@ describe('SocketChild', () => { gotCmds = [] // Nothing - socket.emitMessage(Buffer.concat([genAckRequestMessage(32766, 1), Buffer.from([0])])) + await socket.emitMessage(clock, Buffer.concat([genAckRequestMessage(32766, 1), Buffer.from([0])])) expect(gotCmds).toEqual([]) expect(gotUnknown).toBeFalse() // Some payload const lastBuffer = Buffer.concat([genAckRequestMessage(32767, 1), Buffer.from([0])]) - socket.emitMessage(lastBuffer) + await socket.emitMessage(clock, lastBuffer) expect(gotCmds).toEqual([1]) expect(gotUnknown).toBeFalse() gotCmds = [] // Should not re-emit - socket.emitMessage(lastBuffer) + await socket.emitMessage(clock, lastBuffer) expect(gotCmds).toEqual([]) expect(gotUnknown).toBeFalse() gotCmds = [] // Now it has wrapped const firstBuffer = Buffer.concat([genAckRequestMessage(0, 1), Buffer.from([0])]) - socket.emitMessage(firstBuffer) + await socket.emitMessage(clock, firstBuffer) expect(gotCmds).toEqual([1]) expect(gotUnknown).toBeFalse() gotCmds = [] // Next buffer - socket.emitMessage(Buffer.concat([genAckRequestMessage(1, 1), Buffer.from([0])])) + await socket.emitMessage(clock, Buffer.concat([genAckRequestMessage(1, 1), Buffer.from([0])])) expect(gotCmds).toEqual([1]) expect(gotUnknown).toBeFalse() gotCmds = [] // Should not re-emit - socket.emitMessage(firstBuffer) + await socket.emitMessage(clock, firstBuffer) expect(gotCmds).toEqual([]) expect(gotUnknown).toBeFalse() gotCmds = [] // Retransmit of lastBuffer is not uncommon, it should not re-emit - socket.emitMessage(lastBuffer) + await socket.emitMessage(clock, lastBuffer) expect(gotCmds).toEqual([]) expect(gotUnknown).toBeFalse() gotCmds = [] // Ensure that the first buffer still does not re-emit - socket.emitMessage(firstBuffer) + await socket.emitMessage(clock, firstBuffer) expect(gotCmds).toEqual([]) expect(gotUnknown).toBeFalse() gotCmds = [] @@ -401,7 +417,10 @@ describe('SocketChild', () => { test('SendCommand - acks', async () => { let acked: Array<{packetId: number, trackingId: number}> = [] - const child = createSocketChild(undefined, (packetId, trackingId) => acked.push({ packetId, trackingId })) + const child = createSocketChild(undefined, (packetId, trackingId) => { + acked.push({ packetId, trackingId }) + return Promise.resolve() + }) try { fakeConnect(child) const socket = getSocket(child) @@ -432,7 +451,7 @@ describe('SocketChild', () => { expect(acked).toEqual([]) // Ack a couple - socket.emitMessage(genAckCommandMessage(125)) + await socket.emitMessage(clock, genAckCommandMessage(125)) expect(getInflightIds(child)).toEqual([126, 127, 128]) expect(acked).toEqual([ { packetId: 123, trackingId: 5 }, @@ -442,7 +461,7 @@ describe('SocketChild', () => { acked = [] // Another ack - socket.emitMessage(genAckCommandMessage(126)) + await socket.emitMessage(clock, genAckCommandMessage(126)) expect(getInflightIds(child)).toEqual([127, 128]) expect(acked).toEqual([ { packetId: 126, trackingId: 8 } @@ -458,7 +477,10 @@ describe('SocketChild', () => { test('SendCommand - acks wrap', async () => { let acked: Array<{packetId: number, trackingId: number}> = [] - const child = createSocketChild(undefined, (packetId, trackingId) => acked.push({ packetId, trackingId })) + const child = createSocketChild(undefined, (packetId, trackingId) => { + acked.push({ packetId, trackingId }) + return Promise.resolve() + }) try { fakeConnect(child) const socket = getSocket(child) @@ -489,7 +511,7 @@ describe('SocketChild', () => { expect(acked).toEqual([]) // Ack a couple - socket.emitMessage(genAckCommandMessage(32766)) + await socket.emitMessage(clock, genAckCommandMessage(32766)) expect(getInflightIds(child)).toEqual([32767, 0, 1]) expect(acked).toEqual([ { packetId: 32764, trackingId: 5 }, @@ -499,7 +521,7 @@ describe('SocketChild', () => { acked = [] // Another ack - socket.emitMessage(genAckCommandMessage(0)) + await socket.emitMessage(clock, genAckCommandMessage(0)) expect(getInflightIds(child)).toEqual([1]) expect(acked).toEqual([ { packetId: 32767, trackingId: 8 }, diff --git a/src/lib/atemSocket.ts b/src/lib/atemSocket.ts index c3babe285..45e04ba71 100644 --- a/src/lib/atemSocket.ts +++ b/src/lib/atemSocket.ts @@ -75,7 +75,7 @@ export class AtemSocket extends EventEmitter { return ++this._nextCommandTrackingId } - public async _sendCommand (command: ISerializableCommand, trackingId: number) { + public async sendCommand (command: ISerializableCommand, trackingId: number): Promise { if (this._socketProcess) { if (typeof (command as any).serialize !== 'function') { throw new Error('Command is not serializable') @@ -95,21 +95,33 @@ export class AtemSocket extends EventEmitter { } } - private async _createSocketProcess (address?: string, port?: number) { - const socketProcess = await threadedClass('./atemSocketChild.js', AtemSocketChild, [{ - address, - port - }], { + private async _createSocketProcess () { + const socketProcess = await threadedClass('./atemSocketChild', AtemSocketChild, [ + { + address: this._address, + port: this._port, + debug: this._debug + }, + null, + null, + null, + null + // () => this.emit(IPCMessageType.Disconnect), // onDisconnect + // (message: string) => this.log(message), // onLog + // (payload: Buffer) => this._parseCommand(Buffer.from(payload)), // onCommandReceived + // (packetId: number, trackingId: number) => this.emit(IPCMessageType.CommandAcknowledged, { packetId, trackingId }) // onCommandAcknowledged + ], { instanceName: 'atem-connection', freezeLimit: 200, autoRestart: true, disableMultithreading: this._disableMultithreaded }) - // await socketProcess.on(IPCMessageType.Disconnect, () => this.emit(IPCMessageType.Disconnect)) - // await socketProcess.on(IPCMessageType.Log, (payload: string) => this.log(payload)) - // await socketProcess.on(IPCMessageType.CommandAcknowledged, (packetId: number, trackingId: number) => this.emit(IPCMessageType.CommandAcknowledged, { packetId, trackingId })) - // await socketProcess.on(IPCMessageType.CommandTimeout, (packetId: number, trackingId: number) => this.emit(IPCMessageType.CommandTimeout, { packetId, trackingId })) - // await socketProcess.on(IPCMessageType.InboundCommand, (payload: Buffer) => this._parseCommand(Buffer.from(payload))) + await socketProcess.hackSetFuncs( + () => this.emit(IPCMessageType.Disconnect), // onDisconnect + (message: string) => this.log(message), // onLog + (payload: Buffer) => this._parseCommand(Buffer.from(payload)), // onCommandReceived + (packetId: number, trackingId: number) => this.emit(IPCMessageType.CommandAcknowledged, { packetId, trackingId }) // onCommandAcknowledged + ) ThreadedClassManager.onEvent(socketProcess, 'restarted', () => { this.emit('restarted') @@ -120,13 +132,25 @@ export class AtemSocket extends EventEmitter { }) }) + await socketProcess.connect(this._address, this._port) + return socketProcess } private _parseCommand (buffer: Buffer) { + if (buffer.length < 8) { + // Commands are never less than 8, as that is the header + return + } + const length = buffer.readUInt16BE(0) const name = buffer.toString('ascii', 4, 8) + if (length < 8) { + // Commands are never less than 8, as that is the header + return + } + if (name === 'InCm') { this.emit('connect') } @@ -146,7 +170,7 @@ export class AtemSocket extends EventEmitter { } catch (e) { this.emit('error', e) } - } + } // TODO - log the unknown command? if (buffer.length > length) { this._parseCommand(buffer.slice(length)) diff --git a/src/lib/atemSocketChild.ts b/src/lib/atemSocketChild.ts index 93a1a483f..3d6f2d7b7 100644 --- a/src/lib/atemSocketChild.ts +++ b/src/lib/atemSocketChild.ts @@ -2,7 +2,6 @@ import { createSocket, Socket, RemoteInfo } from 'dgram' import { Util } from './atemUtil' import { ConnectionState, PacketFlag } from '../enums' import * as NanoTimer from 'nanotimer' -import { DEFAULT_PORT } from '../atem' const IN_FLIGHT_TIMEOUT = 60 // ms const CONNECTION_TIMEOUT = 5000 // ms @@ -20,7 +19,7 @@ interface InFlightPacket { } export class AtemSocketChild { - private readonly _debug = false + private readonly _debug: boolean private _connectionState = ConnectionState.Closed private _reconnectTimer: NodeJS.Timer | undefined @@ -29,8 +28,8 @@ export class AtemSocketChild { private _nextSendPacketId = 1 private _sessionId: number = 0 - private _address: string = '' - private _port: number = DEFAULT_PORT + private _address: string + private _port: number private _socket: Socket private _lastReceivedAt: number = Date.now() @@ -40,12 +39,16 @@ export class AtemSocketChild { private _ackTimerRunning = false private _receivedWithoutAck: number = 0 - private readonly onDisconnect: () => void - private readonly onLog: (message: string) => void - private readonly onCommandReceived: (payload: Buffer, packetId: number) => void - private readonly onCommandAcknowledged: (packetId: number, trackingId: number) => void + private onDisconnect: () => Promise + private onLog: (message: string) => Promise + private onCommandReceived: (payload: Buffer, packetId: number) => Promise + private onCommandAcknowledged: (packetId: number, trackingId: number) => Promise + + constructor (options: { address: string, port: number, debug: boolean }, onDisconnect: () => Promise, onLog: (message: string) => Promise, onCommandReceived: (payload: Buffer, packetId: number) => Promise, onCommandAcknowledged: (packetId: number, trackingId: number) => Promise) { + this._debug = options.debug + this._address = options.address + this._port = options.port - constructor (onDisconnect: () => void, onLog: (message: string) => void, onCommandReceived: (payload: Buffer, packetId: number) => void, onCommandAcknowledged: (packetId: number, trackingId: number) => void) { this.onDisconnect = onDisconnect this.onLog = onLog this.onCommandReceived = onCommandReceived @@ -54,15 +57,26 @@ export class AtemSocketChild { this._socket = this._createSocket() } - public connect (address?: string, port?: number): void { + public hackSetFuncs (onDisconnect: () => Promise, onLog: (message: string) => Promise, onCommandReceived: (payload: Buffer, packetId: number) => Promise, onCommandAcknowledged: (packetId: number, trackingId: number) => Promise) { + this.onDisconnect = onDisconnect + this.onLog = onLog + this.onCommandReceived = onCommandReceived + this.onCommandAcknowledged = onCommandAcknowledged + } + + public connect (address: string, port: number): Promise { if (!this._reconnectTimer) { - this._reconnectTimer = setInterval(() => { + this._reconnectTimer = setInterval(async () => { if (this._lastReceivedAt + CONNECTION_TIMEOUT > Date.now()) { // We heard from the atem recently return } - this.restartConnection() + try { + await this.restartConnection() + } catch (e) { + this.log(`Reconnect failed: ${e}`) + } }, CONNECTION_RETRY_INTERVAL) } // Check for retransmits every 10 milliseconds @@ -70,14 +84,10 @@ export class AtemSocketChild { this._retransmitTimer = setInterval(() => this._checkForRetransmit(), 10) } - if (address !== undefined) { - this._address = address - } - if (port !== undefined) { - this._port = port - } + this._address = address + this._port = port - this.restartConnection() + return this.restartConnection() } public disconnect (): Promise { @@ -100,16 +110,16 @@ export class AtemSocketChild { }).then(() => { this._connectionState = ConnectionState.Closed this._createSocket() - this.onDisconnect() + return this.onDisconnect() }) } - public restartConnection (): void { + public async restartConnection (): Promise { // This includes a 'disconnect' if (this._connectionState === ConnectionState.Established) { this._connectionState = ConnectionState.Closed this._createSocket() - this.onDisconnect() + await this.onDisconnect() } // Reset connection @@ -119,13 +129,12 @@ export class AtemSocketChild { this.log('reconnect') // Try doing reconnect - if (this._address && this._port) { - this._sendPacket(Util.COMMAND_CONNECT_HELLO) - this._connectionState = ConnectionState.SynSent - } + this._sendPacket(Util.COMMAND_CONNECT_HELLO) + this._connectionState = ConnectionState.SynSent } public log (message: string): void { + // tslint:disable-next-line: no-floating-promises this.onLog(message) } @@ -157,12 +166,12 @@ export class AtemSocketChild { this._socket = createSocket('udp4') this._socket.bind() this._socket.on('message', (packet, rinfo) => this._receivePacket(packet, rinfo)) - this._socket.on('error', err => { + this._socket.on('error', async err => { this.log(`Connection error: ${err}`) if (this._connectionState === ConnectionState.Established) { // If connection is open, then restart. Otherwise the reconnectTimer will handle it - this.restartConnection() + await this.restartConnection() } }) @@ -195,13 +204,15 @@ export class AtemSocketChild { return } + const ps: Array> = [] + if (this._connectionState === ConnectionState.Established) { // Device asked for retransmit if (flags & PacketFlag.RetransmitRequest) { const fromPacketId = packet.readUInt16BE(6) this.log(`Retransmit request: ${fromPacketId}`) - this._retransmitFrom(fromPacketId) + ps.push(this._retransmitFrom(fromPacketId)) } // Got a packet that needs an ack @@ -213,7 +224,7 @@ export class AtemSocketChild { // It might have commands if (length > 12) { - this.onCommandReceived(packet.slice(12), remotePacketId) + ps.push(this.onCommandReceived(packet.slice(12), remotePacketId)) } } else if (this._isPacketCoveredByAck(this._lastReceivedPacketId, remotePacketId)) { // We got a retransmit of something we have already acked, so reack it @@ -226,7 +237,7 @@ export class AtemSocketChild { const ackPacketId = packet.readUInt16BE(4) this._inFlight = this._inFlight.filter(pkt => { if (this._isPacketCoveredByAck(ackPacketId, pkt.packetId)) { - this.onCommandAcknowledged(pkt.packetId, pkt.trackingId) + ps.push(this.onCommandAcknowledged(pkt.packetId, pkt.trackingId)) return false } else { // Not acked yet @@ -236,6 +247,8 @@ export class AtemSocketChild { // this.log(`${Date.now()} Got ack ${ackPacketId} Remaining=${this._inFlight.length}`) } } + + return Promise.all(ps) } private _sendPacket (packet: Buffer) { @@ -271,7 +284,7 @@ export class AtemSocketChild { this._sendPacket(buffer) } - private _retransmitFrom (fromId: number) { + private async _retransmitFrom (fromId: number) { // this.log(`Resending from ${fromId} to ${this._inFlight.length > 0 ? this._inFlight[this._inFlight.length - 1].packetId : '-'}`) // The atem will ask for MAX_PACKET_ID to be retransmitted when it really wants 0 @@ -281,7 +294,7 @@ export class AtemSocketChild { if (fromIndex === -1) { // fromId is not inflight, so we cannot resend. only fix is to abort this.log(`Unable to resend: ${fromId}`) - this.restartConnection() + await this.restartConnection() } else { this.log(`Resending from ${fromId} to ${this._inFlight[this._inFlight.length - 1].packetId}`) // Resend from the requested @@ -298,20 +311,21 @@ export class AtemSocketChild { } } - private _checkForRetransmit () { + private _checkForRetransmit (): Promise { for (const sentPacket of this._inFlight) { if (sentPacket.lastSent + IN_FLIGHT_TIMEOUT < Date.now()) { if (sentPacket.resent <= MAX_PACKET_RETRIES && this._isPacketCoveredByAck(this._nextSendPacketId, sentPacket.packetId)) { this.log(`Retransmit from timeout: ${sentPacket.packetId}`) // Retransmit the packet and anything after it - this._retransmitFrom(sentPacket.packetId) + return this._retransmitFrom(sentPacket.packetId) } else { // A command has timed out, so we need to reset to avoid getting stuck this.log(`Packet timed out: ${sentPacket.packetId}`) - this.restartConnection() + return this.restartConnection() } - return } } + + return Promise.resolve() } } diff --git a/src/socket-child.ts b/src/socket-child.ts deleted file mode 100644 index db1bb0580..000000000 --- a/src/socket-child.ts +++ /dev/null @@ -1,78 +0,0 @@ -import { IPCMessageType } from './enums' -import { Util } from './lib/atemUtil' -import { AtemSocketChild } from './lib/atemSocketChild' - -function sendParentMessage (message: {cmd: IPCMessageType; payload?: any}) { - Util.sendIPCMessage(global, 'process', message, singleton.log.bind(singleton)).catch(() => { /* Discard errors. */ }) -} - -function onDisconnect () { - sendParentMessage({ - cmd: IPCMessageType.Disconnect - }) -} - -function onLog (message: string) { - sendParentMessage({ - cmd: IPCMessageType.Log, - payload: message - }) -} - -function onCommandReceived (packet: Buffer, remotePacketId: number) { - sendParentMessage({ - cmd: IPCMessageType.InboundCommand, - payload: { - packet, - remotePacketId - } - }) -} - -function onCommandAcknowledged (packetId: number, trackingId: number) { - sendParentMessage({ - cmd: IPCMessageType.CommandAcknowledged, - payload: { - packetId, - trackingId - } - }) -} - -const singleton = new AtemSocketChild(onDisconnect, onLog, onCommandReceived, onCommandAcknowledged) -process.on('message', message => { - if (typeof message !== 'object') { - return - } - - if (typeof message.cmd !== 'string' || message.cmd.length <= 0) { - return - } - - const payload = message.payload - switch (message.cmd) { - case IPCMessageType.Connect: - singleton.connect(payload.address, payload.port) - break - case IPCMessageType.Disconnect: - singleton.disconnect().catch(() => { /* discard error */ }) - break - case IPCMessageType.OutboundCommand: - singleton.sendCommand(Buffer.from(payload.data.data), payload.trackingId) - break - } -}) - -process.on('uncaughtException', error => { - console.error('uncaughtException:', error) - setTimeout(() => { - process.exit(1) - }, 10) -}) - -process.on('unhandledRejection', reason => { - console.error('unhandledRejection:', reason) - setTimeout(() => { - process.exit(1) - }, 10) -}) diff --git a/yarn.lock b/yarn.lock index 4b0f31e65..2b0951455 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1564,11 +1564,6 @@ email-addresses@^3.0.1: resolved "https://registry.yarnpkg.com/email-addresses/-/email-addresses-3.1.0.tgz#cabf7e085cbdb63008a70319a74e6136188812fb" integrity sha512-k0/r7GrWVL32kZlGwfPNgB2Y/mMXVTq/decgLczm/j34whdaspNrZO8CnXPf1laaHxI6ptUlsnAxN+UAPw+fzg== -emittery@^0.5.1: - version "0.5.1" - resolved "https://registry.yarnpkg.com/emittery/-/emittery-0.5.1.tgz#9fbbf57e9aecc258d727d78858a598eb05ea5c96" - integrity sha512-sYZXNHH9PhTfs98ROEFVC3bLiR8KSqXQsEHIwZ9J6H0RaQObC3JYq4G8IvDd0b45/LxfGKYBpmaUN4LiKytaNw== - emoji-regex@^7.0.1: version "7.0.3" resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-7.0.3.tgz#933a04052860c85e83c122479c4748a8e4c72156" @@ -5344,7 +5339,7 @@ tslib@1.9.0: resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.9.0.tgz#e37a86fda8cbbaf23a057f473c9f4dc64e5fc2e8" integrity sha512-f/qGG2tUkrISBlQZEjEqoZ3B2+npJjIf04H1wuAv9iA8i04Icp+61KRXxFdha22670NJopsZCIjhC3SnjPRKrQ== -tslib@^1.8.0, tslib@^1.8.1, tslib@^1.9.0, tslib@^1.9.3: +tslib@^1.10.0, tslib@^1.8.0, tslib@^1.8.1, tslib@^1.9.3: version "1.10.0" resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.10.0.tgz#c3c19f95973fb0a62973fb09d90d961ee43e5c8a" integrity sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ== From 69c7d326d47921efee9830fdec155c24a04708d8 Mon Sep 17 00:00:00 2001 From: Julian Waller Date: Wed, 4 Dec 2019 21:35:53 +0000 Subject: [PATCH 30/68] fix: use dev threadedclass and remove some hacks --- package.json | 2 +- src/lib/atemSocket.ts | 20 +++++--------------- src/lib/atemSocketChild.ts | 15 ++++----------- yarn.lock | 7 +++---- 4 files changed, 13 insertions(+), 31 deletions(-) diff --git a/package.json b/package.json index 72a7e56df..2bfd1abea 100644 --- a/package.json +++ b/package.json @@ -114,7 +114,7 @@ "dependencies": { "exit-hook": "^2.0.0", "nanotimer": "^0.3.15", - "threadedclass": "^0.6.8", + "threadedclass": "https://github.com/Julusian/threadedClass.git#dist/feat/node12-types", "tslib": "^1.10.0", "wavefile": "^8.4.4" }, diff --git a/src/lib/atemSocket.ts b/src/lib/atemSocket.ts index 45e04ba71..7169ea705 100644 --- a/src/lib/atemSocket.ts +++ b/src/lib/atemSocket.ts @@ -96,32 +96,22 @@ export class AtemSocket extends EventEmitter { } private async _createSocketProcess () { - const socketProcess = await threadedClass('./atemSocketChild', AtemSocketChild, [ + const socketProcess = await threadedClass('./atemSocketChild', AtemSocketChild, [ { address: this._address, port: this._port, debug: this._debug }, - null, - null, - null, - null - // () => this.emit(IPCMessageType.Disconnect), // onDisconnect - // (message: string) => this.log(message), // onLog - // (payload: Buffer) => this._parseCommand(Buffer.from(payload)), // onCommandReceived - // (packetId: number, trackingId: number) => this.emit(IPCMessageType.CommandAcknowledged, { packetId, trackingId }) // onCommandAcknowledged + async () => { this.emit(IPCMessageType.Disconnect) }, // onDisconnect + async (message: string) => this.log(message), // onLog + async (payload: Buffer) => this._parseCommand(Buffer.from(payload)), // onCommandReceived + async (packetId: number, trackingId: number) => { this.emit(IPCMessageType.CommandAcknowledged, { packetId, trackingId }) } // onCommandAcknowledged ], { instanceName: 'atem-connection', freezeLimit: 200, autoRestart: true, disableMultithreading: this._disableMultithreaded }) - await socketProcess.hackSetFuncs( - () => this.emit(IPCMessageType.Disconnect), // onDisconnect - (message: string) => this.log(message), // onLog - (payload: Buffer) => this._parseCommand(Buffer.from(payload)), // onCommandReceived - (packetId: number, trackingId: number) => this.emit(IPCMessageType.CommandAcknowledged, { packetId, trackingId }) // onCommandAcknowledged - ) ThreadedClassManager.onEvent(socketProcess, 'restarted', () => { this.emit('restarted') diff --git a/src/lib/atemSocketChild.ts b/src/lib/atemSocketChild.ts index 3d6f2d7b7..8f300870c 100644 --- a/src/lib/atemSocketChild.ts +++ b/src/lib/atemSocketChild.ts @@ -39,10 +39,10 @@ export class AtemSocketChild { private _ackTimerRunning = false private _receivedWithoutAck: number = 0 - private onDisconnect: () => Promise - private onLog: (message: string) => Promise - private onCommandReceived: (payload: Buffer, packetId: number) => Promise - private onCommandAcknowledged: (packetId: number, trackingId: number) => Promise + private readonly onDisconnect: () => Promise + private readonly onLog: (message: string) => Promise + private readonly onCommandReceived: (payload: Buffer, packetId: number) => Promise + private readonly onCommandAcknowledged: (packetId: number, trackingId: number) => Promise constructor (options: { address: string, port: number, debug: boolean }, onDisconnect: () => Promise, onLog: (message: string) => Promise, onCommandReceived: (payload: Buffer, packetId: number) => Promise, onCommandAcknowledged: (packetId: number, trackingId: number) => Promise) { this._debug = options.debug @@ -57,13 +57,6 @@ export class AtemSocketChild { this._socket = this._createSocket() } - public hackSetFuncs (onDisconnect: () => Promise, onLog: (message: string) => Promise, onCommandReceived: (payload: Buffer, packetId: number) => Promise, onCommandAcknowledged: (packetId: number, trackingId: number) => Promise) { - this.onDisconnect = onDisconnect - this.onLog = onLog - this.onCommandReceived = onCommandReceived - this.onCommandAcknowledged = onCommandAcknowledged - } - public connect (address: string, port: number): Promise { if (!this._reconnectTimer) { this._reconnectTimer = setInterval(async () => { diff --git a/yarn.lock b/yarn.lock index 2b0951455..317f3d09f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5165,10 +5165,9 @@ text-extensions@^1.0.0: resolved "https://registry.yarnpkg.com/text-extensions/-/text-extensions-1.9.0.tgz#1853e45fee39c945ce6f6c36b2d659b5aabc2a26" integrity sha512-wiBrwC1EhBelW12Zy26JeOUkQ5mRu+5o8rpsJk5+2t+Y5vE7e842qtZDQ2g1NpX/29HdyFeJ4nSIhI47ENSxlQ== -threadedclass@^0.6.8: - version "0.6.8" - resolved "https://registry.yarnpkg.com/threadedclass/-/threadedclass-0.6.8.tgz#7eba5d9c7b3b40b9b5a6edcee222b54d209336bf" - integrity sha512-pAQSA7bM1r2tSuag6buf7o7xJ3m5W3zF77xG1SlD+7yPC09Ly/JBm4rVpXY+Ryy20An3PvdHwlkAonizBvUiFA== +"threadedclass@https://github.com/Julusian/threadedClass.git#dist/feat/node12-types": + version "0.0.0-develop" + resolved "https://github.com/Julusian/threadedClass.git#9a40b3357db293b8a8429526a4bf7d8d4de8a10f" dependencies: callsites "^3.1.0" tslib "^1.9.3" From 3b07d0a2d0b6394f851ab76346f72d84f679dd44 Mon Sep 17 00:00:00 2001 From: Julian Waller Date: Wed, 4 Dec 2019 22:21:51 +0000 Subject: [PATCH 31/68] fix: replace IPCMessageType with stricter basic strings --- src/__tests__/atem.spec.ts | 3 +- src/atem.ts | 10 +++++-- src/enums/index.ts | 9 ------ src/lib/__tests__/atemSocket.spec.ts | 41 ++++++++++++++-------------- src/lib/atemSocket.ts | 21 +++++++++++--- 5 files changed, 46 insertions(+), 38 deletions(-) diff --git a/src/__tests__/atem.spec.ts b/src/__tests__/atem.spec.ts index b5b4bfd67..9c47d19ea 100644 --- a/src/__tests__/atem.spec.ts +++ b/src/__tests__/atem.spec.ts @@ -1,7 +1,6 @@ import { Atem, DEFAULT_PORT } from '../atem' import { cleanupAtem } from './lib' import { CutCommand } from '../commands' -import { IPCMessageType } from '../enums' import { promisify } from 'util' import { EventEmitter } from 'events' @@ -123,7 +122,7 @@ describe('Atem', () => { expect(socket.sendCommand).toHaveBeenCalledWith(cmd, 124) // Trigger the ack, and it should switfy resolve - socket.emit(IPCMessageType.CommandAcknowledged, 124) + socket.emit('commandAck', 124) expect(Object.keys(sentQueue)).toHaveLength(0) // Finally, it should now resolve without a timeout diff --git a/src/atem.ts b/src/atem.ts index c9add8ad3..e2eff952c 100644 --- a/src/atem.ts +++ b/src/atem.ts @@ -56,6 +56,12 @@ export class Atem extends EventEmitter { ((event: 'stateChanged', listener: (state: AtemState, path: string) => void) => this) & ((event: 'receivedCommand', listener: (cmd: IDeserializedCommand) => void) => this) + public emit!: ((event: 'error', message: any) => boolean) & + ((event: 'connected') => boolean) & + ((event: 'disconnected') => boolean) & + ((event: 'stateChanged', state: AtemState, path: string) => boolean) & + ((event: 'receivedCommand', cmd: IDeserializedCommand) => boolean) + constructor (options?: AtemOptions) { super() this._log = (options && options.externalLog) || function (...args: any[]): void { @@ -74,11 +80,11 @@ export class Atem extends EventEmitter { this.socket.on('connect', () => this.dataTransferManager.startCommandSending((command: ISerializableCommand) => this.sendCommand(command))) this.socket.on('disconnect', () => this.dataTransferManager.stopCommandSending()) - this.socket.on('receivedStateChange', (command: IDeserializedCommand) => { + this.socket.on('commandReceived', (command: IDeserializedCommand) => { this.emit('receivedCommand', command) this._mutateState(command) }) - this.socket.on(Enums.IPCMessageType.CommandAcknowledged, (trackingId: number) => this._resolveCommand(trackingId)) + this.socket.on('commandAck', (trackingId: number) => this._resolveCommand(trackingId)) this.socket.on('error', (e) => this.emit('error', e)) this.socket.on('connect', () => this.emit('connected')) this.socket.on('disconnect', () => { diff --git a/src/enums/index.ts b/src/enums/index.ts index 9cfebbff3..2c0f1fa4f 100644 --- a/src/enums/index.ts +++ b/src/enums/index.ts @@ -198,15 +198,6 @@ export enum SuperSourceArtOption { Foreground } -export enum IPCMessageType { - Log = 'log', - Connect = 'connect', - Disconnect = 'disconnect', - InboundCommand = 'inboundCommand', - OutboundCommand = 'outboundCommand', - CommandAcknowledged = 'commandAcknowledged' -} - export enum TransferMode { NoOp, Write, diff --git a/src/lib/__tests__/atemSocket.spec.ts b/src/lib/__tests__/atemSocket.spec.ts index c5573fca2..3bb2fa2a0 100644 --- a/src/lib/__tests__/atemSocket.spec.ts +++ b/src/lib/__tests__/atemSocket.spec.ts @@ -1,5 +1,5 @@ import { CutCommand, ProductIdentifierCommand, InitCompleteCommand, VersionCommand, ProgramInputUpdateCommand, PreviewInputUpdateCommand, ISerializableCommand, BasicWritableCommand, DeserializedCommand } from '../../commands' -import { IPCMessageType, ProtocolVersion, Model } from '../../enums' +import { ProtocolVersion, Model } from '../../enums' import { AtemSocket } from '../atemSocket' import { ThreadedClass, ThreadedClassManager } from 'threadedclass' import { Buffer } from 'buffer' @@ -20,26 +20,25 @@ export class AtemSocketChildMock { // // this._address = options.address // // this._port = options.port - // this.onDisconnect = null + // this.onDisconnect = onDisconnect // this.onLog = onLog // this.onCommandReceived = onCommandReceived // this.onCommandAcknowledged = onCommandAcknowledged // } - public hackSetFuncs (onDisconnect: () => Promise, onLog: (message: string) => Promise, onCommandReceived: (payload: Buffer, packetId: number) => Promise, onCommandAcknowledged: (packetId: number, trackingId: number) => Promise) { - this.onDisconnect = onDisconnect - this.onLog = onLog - this.onCommandReceived = onCommandReceived - this.onCommandAcknowledged = onCommandAcknowledged - } - public connect = jest.fn() public disconnect = jest.fn(() => Promise.resolve(87)) public sendCommand = jest.fn() } const AtemSocketChildSingleton = new AtemSocketChildMock() -;(AtemSocketChild as any).mockImplementation(() => AtemSocketChildSingleton) +;(AtemSocketChild as any).mockImplementation((_opts: any, onDisconnect: () => Promise, onLog: (message: string) => Promise, onCommandReceived: (payload: Buffer, packetId: number) => Promise, onCommandAcknowledged: (packetId: number, trackingId: number) => Promise) => { + AtemSocketChildSingleton.onDisconnect = onDisconnect + AtemSocketChildSingleton.onLog = onLog + AtemSocketChildSingleton.onCommandReceived = onCommandReceived + AtemSocketChildSingleton.onCommandAcknowledged = onCommandAcknowledged + return AtemSocketChildSingleton +}) class ThreadedClassManagerMock { public handlers: Function[] = [] @@ -108,7 +107,7 @@ describe('AtemSocket', () => { // New child was constructed expect(AtemSocketChild).toHaveBeenCalledTimes(1) - expect(AtemSocketChild).toHaveBeenCalledWith({ address: '', port: 890, debug: false }, null, null, null, null) + expect(AtemSocketChild).toHaveBeenCalledWith({ address: '', port: 890, debug: false }, expect.toBeFunction(), expect.toBeFunction(), expect.toBeFunction(), expect.toBeFunction()) }) test('connect initial with params', async () => { const socket = createSocket() @@ -127,7 +126,7 @@ describe('AtemSocket', () => { // New child was constructed expect(AtemSocketChild).toHaveBeenCalledTimes(1) - expect(AtemSocketChild).toHaveBeenCalledWith({ address: 'abc', port: 765, debug: false }, null, null, null, null) + expect(AtemSocketChild).toHaveBeenCalledWith({ address: 'abc', port: 765, debug: false }, expect.toBeFunction(), expect.toBeFunction(), expect.toBeFunction(), expect.toBeFunction()) }) test('connect change details', async () => { const socket = createSocket() @@ -290,8 +289,8 @@ describe('AtemSocket', () => { // const log = jest.fn() const ack = jest.fn() - socket.on(IPCMessageType.Disconnect, disconnect) - socket.on(IPCMessageType.CommandAcknowledged, ack) + socket.on('disconnect', disconnect) + socket.on('commandAck', ack) expect(AtemSocketChildSingleton.onDisconnect).toBeDefined() await AtemSocketChildSingleton.onDisconnect!() @@ -302,7 +301,7 @@ describe('AtemSocket', () => { await AtemSocketChildSingleton.onCommandAcknowledged!(675, 98) await clock.tickAsync(0) expect(ack).toHaveBeenCalledTimes(1) - expect(ack).toHaveBeenCalledWith({ packetId: 675, trackingId: 98 }) + expect(ack).toHaveBeenCalledWith(98) }) @@ -320,7 +319,7 @@ describe('AtemSocket', () => { socket.on('connect', connect) socket.on('error', error) - socket.on('receivedStateChange', change) + socket.on('commandReceived', change) const parser = (socket as any)._commandParser as CommandParser expect(parser).toBeTruthy() @@ -357,7 +356,7 @@ describe('AtemSocket', () => { socket.on('connect', connect) socket.on('error', error) - socket.on('receivedStateChange', change) + socket.on('commandReceived', change) const parser = (socket as any)._commandParser as CommandParser expect(parser).toBeTruthy() @@ -397,7 +396,7 @@ describe('AtemSocket', () => { socket.on('connect', connect) socket.on('error', error) - socket.on('receivedStateChange', change) + socket.on('commandReceived', change) const parser = (socket as any)._commandParser as CommandParser expect(parser).toBeTruthy() @@ -440,7 +439,7 @@ describe('AtemSocket', () => { socket.on('connect', connect) socket.on('error', error) - socket.on('receivedStateChange', change) + socket.on('commandReceived', change) const testBuffer = Buffer.alloc(0) const pktId = 822 @@ -466,7 +465,7 @@ describe('AtemSocket', () => { socket.on('connect', connect) socket.on('error', error) - socket.on('receivedStateChange', change) + socket.on('commandReceived', change) const testBuffer = Buffer.alloc(10, 0) const pktId = 822 @@ -492,7 +491,7 @@ describe('AtemSocket', () => { socket.on('connect', connect) socket.on('error', error) - socket.on('receivedStateChange', change) + socket.on('commandReceived', change) class BrokenCommand extends DeserializedCommand<{}> { public static readonly rawName = 'TEST' diff --git a/src/lib/atemSocket.ts b/src/lib/atemSocket.ts index 7169ea705..5a1c3791b 100644 --- a/src/lib/atemSocket.ts +++ b/src/lib/atemSocket.ts @@ -1,6 +1,5 @@ import { EventEmitter } from 'events' import { CommandParser } from './atemCommandParser' -import { IPCMessageType } from '../enums' // import exitHook = require('exit-hook') import { VersionCommand, ISerializableCommand, IDeserializedCommand } from '../commands' import { DEFAULT_PORT } from '../atem' @@ -28,6 +27,20 @@ export class AtemSocket extends EventEmitter { private readonly log: (args1: any, args2?: any, args3?: any) => void + public on!: ((event: 'disconnect', listener: () => void) => this) & + ((event: 'connect', listener: () => void) => this) & + ((event: 'restarted', listener: () => void) => this) & + ((event: 'error', listener: (message: string) => void) => this) & + ((event: 'commandReceived', listener: (cmd: IDeserializedCommand) => void) => this) & + ((event: 'commandAck', listener: (trackingId: number) => void) => this) + + public emit!: ((event: 'disconnect') => boolean) & + ((event: 'connect') => boolean) & + ((event: 'restarted') => boolean) & + ((event: 'error', message: string) => boolean) & + ((event: 'commandReceived', cmd: IDeserializedCommand) => boolean) & + ((event: 'commandAck', trackingId: number) => boolean) + constructor (options: AtemSocketOptions) { super() this._address = options.address @@ -102,10 +115,10 @@ export class AtemSocket extends EventEmitter { port: this._port, debug: this._debug }, - async () => { this.emit(IPCMessageType.Disconnect) }, // onDisconnect + async () => { this.emit('disconnect') }, // onDisconnect async (message: string) => this.log(message), // onLog async (payload: Buffer) => this._parseCommand(Buffer.from(payload)), // onCommandReceived - async (packetId: number, trackingId: number) => { this.emit(IPCMessageType.CommandAcknowledged, { packetId, trackingId }) } // onCommandAcknowledged + async (_packetId: number, trackingId: number) => { this.emit('commandAck', trackingId) } // onCommandAcknowledged ], { instanceName: 'atem-connection', freezeLimit: 200, @@ -156,7 +169,7 @@ export class AtemSocket extends EventEmitter { this._commandParser.version = verCmd.properties.version } - this.emit('receivedStateChange', cmd) + this.emit('commandReceived', cmd) } catch (e) { this.emit('error', e) } From 8b840f4af98db59388937c2a8bb6a4a12e794bb8 Mon Sep 17 00:00:00 2001 From: Julian Waller Date: Wed, 4 Dec 2019 23:36:22 +0000 Subject: [PATCH 32/68] fix: make cleanup of connections better --- src/atem.ts | 28 ++++++++++----------- src/dataTransfer/index.ts | 1 + src/lib/__tests__/atemSocket.spec.ts | 6 ++--- src/lib/atemSocket.ts | 37 ++++++++++++++-------------- 4 files changed, 37 insertions(+), 35 deletions(-) diff --git a/src/atem.ts b/src/atem.ts index e2eff952c..f38168e87 100644 --- a/src/atem.ts +++ b/src/atem.ts @@ -32,7 +32,7 @@ export interface AtemOptions { debug?: boolean, disableMultithreaded?: boolean - externalLog?: (arg0?: any, arg1?: any, arg2?: any, arg3?: any) => void + externalLog?: (...args: any[]) => void } interface SentCommand { @@ -64,9 +64,7 @@ export class Atem extends EventEmitter { constructor (options?: AtemOptions) { super() - this._log = (options && options.externalLog) || function (...args: any[]): void { - console.log(...args) - } + this._log = (options && options.externalLog) || ((...args: any[]) => { console.log(...args) }) this._state = new AtemState() this.socket = new AtemSocket({ @@ -77,21 +75,19 @@ export class Atem extends EventEmitter { disableMultithreaded: (options || {}).disableMultithreaded || false }) this.dataTransferManager = new DT.DataTransferManager() - this.socket.on('connect', () => this.dataTransferManager.startCommandSending((command: ISerializableCommand) => this.sendCommand(command))) - this.socket.on('disconnect', () => this.dataTransferManager.stopCommandSending()) - this.socket.on('commandReceived', (command: IDeserializedCommand) => { + this.socket.on('commandReceived', command => { this.emit('receivedCommand', command) this._mutateState(command) }) - this.socket.on('commandAck', (trackingId: number) => this._resolveCommand(trackingId)) - this.socket.on('error', (e) => this.emit('error', e)) - this.socket.on('connect', () => this.emit('connected')) - this.socket.on('disconnect', () => { - this._rejectAllCommands() - this.emit('disconnected') + this.socket.on('commandAck', trackingId => this._resolveCommand(trackingId)) + this.socket.on('error', e => this.emit('error', e)) + this.socket.on('connect', () => { + this.dataTransferManager.startCommandSending(command => this.sendCommand(command)) + this.emit('connected') }) - this.socket.on('restarted', () => { + this.socket.on('disconnect', () => { + this.dataTransferManager.stopCommandSending() this._rejectAllCommands() this.emit('disconnected') }) @@ -109,6 +105,10 @@ export class Atem extends EventEmitter { return this.socket.disconnect() } + public destroy (): Promise { + return this.socket.destroy() + } + public sendCommand (command: ISerializableCommand): Promise { const commandTrackingId = this.socket.nextCommandTrackingId return new Promise((resolve, reject) => { diff --git a/src/dataTransfer/index.ts b/src/dataTransfer/index.ts index effd9b329..5ee79468e 100644 --- a/src/dataTransfer/index.ts +++ b/src/dataTransfer/index.ts @@ -52,6 +52,7 @@ export class DataTransferManager { } public stopCommandSending () { if (this.exitUnsubscribe) { + this.exitUnsubscribe() this.exitUnsubscribe = undefined } if (this.interval) { diff --git a/src/lib/__tests__/atemSocket.spec.ts b/src/lib/__tests__/atemSocket.spec.ts index 3bb2fa2a0..97b57cadf 100644 --- a/src/lib/__tests__/atemSocket.spec.ts +++ b/src/lib/__tests__/atemSocket.spec.ts @@ -542,14 +542,14 @@ describe('AtemSocket', () => { const connect = socket.connect = jest.fn(() => Promise.resolve()) - const restarted = jest.fn() - socket.on('restarted', restarted) + const disconnected = jest.fn() + socket.on('disconnect', disconnected) expect(ThreadedClassManagerSingleton.handlers).toHaveLength(1) // simulate a restart ThreadedClassManagerSingleton.handlers.forEach(handler => handler()) - expect(restarted).toHaveBeenCalledTimes(1) + expect(disconnected).toHaveBeenCalledTimes(1) expect(connect).toHaveBeenCalledTimes(1) }) // test('receive - thread restart with error', async () => { diff --git a/src/lib/atemSocket.ts b/src/lib/atemSocket.ts index 5a1c3791b..0c0ef1485 100644 --- a/src/lib/atemSocket.ts +++ b/src/lib/atemSocket.ts @@ -1,6 +1,6 @@ import { EventEmitter } from 'events' import { CommandParser } from './atemCommandParser' -// import exitHook = require('exit-hook') +import exitHook = require('exit-hook') import { VersionCommand, ISerializableCommand, IDeserializedCommand } from '../commands' import { DEFAULT_PORT } from '../atem' import { threadedClass, ThreadedClass, ThreadedClassManager } from 'threadedclass' @@ -12,7 +12,7 @@ export interface AtemSocketOptions { debug: boolean disableMultithreaded: boolean - log: (args1: any, args2?: any, args3?: any) => void + log: (...args: any[]) => void } export class AtemSocket extends EventEmitter { @@ -24,19 +24,18 @@ export class AtemSocket extends EventEmitter { private _address: string private _port: number = DEFAULT_PORT private _socketProcess: ThreadedClass | undefined + private _exitUnsubscribe?: () => void private readonly log: (args1: any, args2?: any, args3?: any) => void public on!: ((event: 'disconnect', listener: () => void) => this) & ((event: 'connect', listener: () => void) => this) & - ((event: 'restarted', listener: () => void) => this) & ((event: 'error', listener: (message: string) => void) => this) & ((event: 'commandReceived', listener: (cmd: IDeserializedCommand) => void) => this) & ((event: 'commandAck', listener: (trackingId: number) => void) => this) public emit!: ((event: 'disconnect') => boolean) & ((event: 'connect') => boolean) & - ((event: 'restarted') => boolean) & ((event: 'error', message: string) => boolean) & ((event: 'commandReceived', cmd: IDeserializedCommand) => boolean) & ((event: 'commandAck', trackingId: number) => boolean) @@ -48,16 +47,6 @@ export class AtemSocket extends EventEmitter { this._debug = options.debug this._disableMultithreaded = options.disableMultithreaded this.log = options.log - - // When the parent process begins exiting, remove the listeners on our child process. - // We do this to avoid throwing an error when the child process exits - // as a natural part of the parent process exiting. - // exitHook(() => { - // if (this._socketProcess) { - // this._socketProcess.removeAllListeners() - // this._socketProcess.kill() - // } - // }) } public async connect (address?: string, port?: number): Promise { @@ -70,11 +59,24 @@ export class AtemSocket extends EventEmitter { if (!this._socketProcess) { this._socketProcess = await this._createSocketProcess() + this._exitUnsubscribe = exitHook(() => this.destroy()) } else { await this._socketProcess.connect(this._address, this._port) } } + public async destroy () { + await this.disconnect() + if (this._socketProcess) { + await ThreadedClassManager.destroy(this._socketProcess) + this._socketProcess = undefined + } + if (this._exitUnsubscribe) { + this._exitUnsubscribe() + this._exitUnsubscribe = undefined + } + } + public async disconnect (): Promise { if (this._socketProcess) { await this._socketProcess.disconnect() @@ -127,11 +129,10 @@ export class AtemSocket extends EventEmitter { }) ThreadedClassManager.onEvent(socketProcess, 'restarted', () => { - this.emit('restarted') + this.emit('disconnect') this.connect().catch(error => { - const errorMsg = 'Failed to reconnect after respawning socket process' - this.emit('error', error) - this.log(errorMsg + ':', error && error.message) + const errorMsg = `Failed to reconnect after respawning socket process: ${error}` + this.emit('error', errorMsg) }) }) From bf279479ccd5bff95767b93334328b074af8ff18 Mon Sep 17 00:00:00 2001 From: Julian Waller Date: Wed, 4 Dec 2019 23:43:55 +0000 Subject: [PATCH 33/68] fix: typedoc --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 2bfd1abea..2adc17c80 100644 --- a/package.json +++ b/package.json @@ -37,8 +37,8 @@ "send-coverage": "codecov", "docs": "yarn docs:html && open-cli docs/index.html", "docs:test": "yarn docs:html", - "docs:html": "typedoc src/index.ts --excludePrivate --mode file --theme minimal --out docs", - "docs:json": "typedoc --mode file --json docs/typedoc.json src/index.ts", + "docs:html": "typedoc src/index.ts --ignoreCompilerErrors --excludePrivate --mode file --theme minimal --out docs", + "docs:json": "typedoc --ignoreCompilerErrors --mode file --json docs/typedoc.json src/index.ts", "docs:publish": "yarn docs:html && gh-pages -d docs", "changelog": "standard-version", "release": "yarn reset && yarn docs:publish && yarn changelog", From 1ac7da862c66cc57b82a37c98b51cc5dcfa4e682 Mon Sep 17 00:00:00 2001 From: Julian Waller Date: Thu, 5 Dec 2019 22:17:11 +0000 Subject: [PATCH 34/68] feat: batch commands --- examples/upload.ts | 6 --- src/__tests__/atem.spec.ts | 18 +++++--- src/atem.ts | 35 +++++++++----- src/dataTransfer/__tests__/index.spec.ts | 4 +- src/dataTransfer/index.ts | 6 +-- src/lib/__tests__/atemSocket.spec.ts | 40 ++++++++-------- src/lib/__tests__/socket-child.spec.ts | 58 ++++++++++++++++-------- src/lib/atemSocket.ts | 25 +++++----- src/lib/atemSocketChild.ts | 20 ++++++-- 9 files changed, 130 insertions(+), 82 deletions(-) diff --git a/examples/upload.ts b/examples/upload.ts index d3fc29082..9416d90d3 100644 --- a/examples/upload.ts +++ b/examples/upload.ts @@ -30,12 +30,6 @@ function uploadNext () { console.log('') console.log('UPLOAD GOT STUCK') console.log('') - - const dt = (conn as any).dataTransferManager - fs.writeFileSync('upload-stuck', JSON.stringify({ - stills: dt.stillsLock, - clips: dt.clipLocks - }, undefined, 4)) }, 20000) setTimeout(() => uploadNext(), 0) diff --git a/src/__tests__/atem.spec.ts b/src/__tests__/atem.spec.ts index 9c47d19ea..75c567e4d 100644 --- a/src/__tests__/atem.spec.ts +++ b/src/__tests__/atem.spec.ts @@ -108,7 +108,7 @@ describe('Atem', () => { }) expect(socket.nextCommandTrackingId).toEqual(123) - socket.sendCommand = jest.fn(() => Promise.resolve(35) as any) + socket.sendCommands = jest.fn(() => Promise.resolve(35) as any) const sentQueue = (conn as any)._sentQueue as object expect(Object.keys(sentQueue)).toHaveLength(0) @@ -118,8 +118,11 @@ describe('Atem', () => { await setImmediatePromise() expect(Object.keys(sentQueue)).toHaveLength(1) - expect(socket.sendCommand).toHaveBeenCalledTimes(1) - expect(socket.sendCommand).toHaveBeenCalledWith(cmd, 124) + expect(socket.sendCommands).toHaveBeenCalledTimes(1) + expect(socket.sendCommands).toHaveBeenCalledWith([{ + rawCommand: cmd, + trackingId: 124 + }]) // Trigger the ack, and it should switfy resolve socket.emit('commandAck', 124) @@ -147,7 +150,7 @@ describe('Atem', () => { }) expect(socket.nextCommandTrackingId).toEqual(123) - socket.sendCommand = jest.fn(() => Promise.reject(35) as any) + socket.sendCommands = jest.fn(() => Promise.reject(35) as any) const sentQueue = (conn as any)._sentQueue as object expect(Object.keys(sentQueue)).toHaveLength(0) @@ -156,8 +159,11 @@ describe('Atem', () => { const res = conn.sendCommand(cmd) // Send command should be called - expect(socket.sendCommand).toHaveBeenCalledTimes(1) - expect(socket.sendCommand).toHaveBeenCalledWith(cmd, 124) + expect(socket.sendCommands).toHaveBeenCalledTimes(1) + expect(socket.sendCommands).toHaveBeenCalledWith([{ + rawCommand: cmd, + trackingId: 124 + }]) expect(Object.keys(sentQueue)).toHaveLength(0) diff --git a/src/atem.ts b/src/atem.ts index f38168e87..907bd8e28 100644 --- a/src/atem.ts +++ b/src/atem.ts @@ -83,7 +83,7 @@ export class Atem extends EventEmitter { this.socket.on('commandAck', trackingId => this._resolveCommand(trackingId)) this.socket.on('error', e => this.emit('error', e)) this.socket.on('connect', () => { - this.dataTransferManager.startCommandSending(command => this.sendCommand(command)) + this.dataTransferManager.startCommandSending(cmds => this.sendCommands(cmds)) this.emit('connected') }) this.socket.on('disconnect', () => { @@ -109,19 +109,32 @@ export class Atem extends EventEmitter { return this.socket.destroy() } - public sendCommand (command: ISerializableCommand): Promise { - const commandTrackingId = this.socket.nextCommandTrackingId - return new Promise((resolve, reject) => { - this.socket.sendCommand(command, commandTrackingId).then(() => { - this._sentQueue[commandTrackingId] = { - command, - resolve, - reject - } - }).catch(reject) + private sendCommands (commands: ISerializableCommand[]): Array> { + const cmds2 = commands.map(cmd => ({ + rawCommand: cmd, + trackingId: this.socket.nextCommandTrackingId + })) + + const sendPromise = this.socket.sendCommands(cmds2) + + return cmds2.map(cmd => { + // TODO - does this work? + return sendPromise.then(() => { + return new Promise((resolve, reject) => { + this._sentQueue[cmd.trackingId] = { + command: cmd.rawCommand, + resolve, + reject + } + }) + }) }) } + public sendCommand (command: ISerializableCommand): Promise { + return this.sendCommands([command])[0] + } + public changeProgramInput (input: number, me: number = 0) { const command = new Commands.ProgramInputCommand(me, input) return this.sendCommand(command) diff --git a/src/dataTransfer/__tests__/index.spec.ts b/src/dataTransfer/__tests__/index.spec.ts index fcbaf0d46..ca0613e1a 100644 --- a/src/dataTransfer/__tests__/index.spec.ts +++ b/src/dataTransfer/__tests__/index.spec.ts @@ -32,7 +32,7 @@ function mangleCommand (cmd: any, dir: string) { function runDataTransferTest (spec: any) { const manager = new DataTransferManager() - manager.startCommandSending(cmd => { + manager.startCommandSending(cmds => cmds.map(cmd => { const expectedCmd = spec.shift() const gotCmd = mangleCommand(cmd, 'send') expect(expectedCmd).toEqual(gotCmd) @@ -46,7 +46,7 @@ function runDataTransferTest (spec: any) { } return Promise.resolve(cmd) - }) + })) return manager } diff --git a/src/dataTransfer/index.ts b/src/dataTransfer/index.ts index 5ee79468e..4dd8d2ac0 100644 --- a/src/dataTransfer/index.ts +++ b/src/dataTransfer/index.ts @@ -25,7 +25,7 @@ export class DataTransferManager { private transferIndex: number = 0 - public startCommandSending (sendCommand: (command: ISerializableCommand) => Promise) { + public startCommandSending (sendCommands: (cmds: ISerializableCommand[]) => Array>) { if (!this.interval) { // New connection means a new queue this.commandQueue.splice(0, this.commandQueue.length) @@ -36,8 +36,8 @@ export class DataTransferManager { } const commandsToSend = this.commandQueue.splice(0, MAX_PACKETS_TO_SEND_PER_TICK) - commandsToSend.forEach(command => { - sendCommand(command).catch((e) => { + sendCommands(commandsToSend).forEach(cmdRes => { + cmdRes.catch((e) => { // TODO - handle this better. it should probably kill/restart the upload. and should also be logged in some way console.log(`Transfer send error: ${e}`) }) diff --git a/src/lib/__tests__/atemSocket.spec.ts b/src/lib/__tests__/atemSocket.spec.ts index 97b57cadf..817323e89 100644 --- a/src/lib/__tests__/atemSocket.spec.ts +++ b/src/lib/__tests__/atemSocket.spec.ts @@ -28,7 +28,7 @@ export class AtemSocketChildMock { public connect = jest.fn() public disconnect = jest.fn(() => Promise.resolve(87)) - public sendCommand = jest.fn() + public sendCommands = jest.fn() } const AtemSocketChildSingleton = new AtemSocketChildMock() @@ -58,7 +58,7 @@ describe('AtemSocket', () => { (AtemSocketChild as any).mockClear() AtemSocketChildSingleton.connect.mockClear() AtemSocketChildSingleton.disconnect.mockClear() - AtemSocketChildSingleton.sendCommand.mockClear() + AtemSocketChildSingleton.sendCommands.mockClear() if (!lite) { AtemSocketChildSingleton.onLog = undefined @@ -103,7 +103,7 @@ describe('AtemSocket', () => { // Connect was not called explicitly expect(AtemSocketChildSingleton.connect).toHaveBeenCalledTimes(1) expect(AtemSocketChildSingleton.disconnect).toHaveBeenCalledTimes(0) - expect(AtemSocketChildSingleton.sendCommand).toHaveBeenCalledTimes(0) + expect(AtemSocketChildSingleton.sendCommands).toHaveBeenCalledTimes(0) // New child was constructed expect(AtemSocketChild).toHaveBeenCalledTimes(1) @@ -122,7 +122,7 @@ describe('AtemSocket', () => { // Connect was not called explicitly expect(AtemSocketChildSingleton.connect).toHaveBeenCalledTimes(1) expect(AtemSocketChildSingleton.disconnect).toHaveBeenCalledTimes(0) - expect(AtemSocketChildSingleton.sendCommand).toHaveBeenCalledTimes(0) + expect(AtemSocketChildSingleton.sendCommands).toHaveBeenCalledTimes(0) // New child was constructed expect(AtemSocketChild).toHaveBeenCalledTimes(1) @@ -143,7 +143,7 @@ describe('AtemSocket', () => { expect(AtemSocketChild).toHaveBeenCalledTimes(1) expect(AtemSocketChildSingleton.connect).toHaveBeenCalledTimes(1) expect(AtemSocketChildSingleton.disconnect).toHaveBeenCalledTimes(0) - expect(AtemSocketChildSingleton.sendCommand).toHaveBeenCalledTimes(0) + expect(AtemSocketChildSingleton.sendCommands).toHaveBeenCalledTimes(0) mockClear() @@ -156,7 +156,7 @@ describe('AtemSocket', () => { expect(AtemSocketChild).toHaveBeenCalledTimes(0) expect(AtemSocketChildSingleton.connect).toHaveBeenCalledTimes(1) expect(AtemSocketChildSingleton.disconnect).toHaveBeenCalledTimes(0) - expect(AtemSocketChildSingleton.sendCommand).toHaveBeenCalledTimes(0) + expect(AtemSocketChildSingleton.sendCommands).toHaveBeenCalledTimes(0) expect(AtemSocketChildSingleton.connect).toHaveBeenCalledWith('new', 455) }) @@ -183,7 +183,7 @@ describe('AtemSocket', () => { expect(AtemSocketChild).toHaveBeenCalledTimes(0) expect(AtemSocketChildSingleton.connect).toHaveBeenCalledTimes(0) expect(AtemSocketChildSingleton.disconnect).toHaveBeenCalledTimes(1) - expect(AtemSocketChildSingleton.sendCommand).toHaveBeenCalledTimes(0) + expect(AtemSocketChildSingleton.sendCommands).toHaveBeenCalledTimes(0) expect(AtemSocketChildSingleton.disconnect).toHaveBeenCalledWith() }) @@ -197,7 +197,7 @@ describe('AtemSocket', () => { expect(AtemSocketChild).toHaveBeenCalledTimes(0) expect(AtemSocketChildSingleton.connect).toHaveBeenCalledTimes(0) expect(AtemSocketChildSingleton.disconnect).toHaveBeenCalledTimes(0) - expect(AtemSocketChildSingleton.sendCommand).toHaveBeenCalledTimes(0) + expect(AtemSocketChildSingleton.sendCommands).toHaveBeenCalledTimes(0) }) test('sendCommand - not open', async () => { @@ -206,7 +206,7 @@ describe('AtemSocket', () => { try { const cmd = new CutCommand(0) - await socket.sendCommand(cmd, 1) + await socket.sendCommands([{ rawCommand: cmd, trackingId: 1 }]) // Should not get here expect(false).toBeTruthy() } catch (e) { @@ -217,7 +217,7 @@ describe('AtemSocket', () => { expect(AtemSocketChild).toHaveBeenCalledTimes(0) expect(AtemSocketChildSingleton.connect).toHaveBeenCalledTimes(0) expect(AtemSocketChildSingleton.disconnect).toHaveBeenCalledTimes(0) - expect(AtemSocketChildSingleton.sendCommand).toHaveBeenCalledTimes(0) + expect(AtemSocketChildSingleton.sendCommands).toHaveBeenCalledTimes(0) }) test('sendCommand - not serializable', async () => { @@ -234,18 +234,18 @@ describe('AtemSocket', () => { }) as any as ISerializableCommand expect(cmd.serialize).toBeFalsy() try { - await socket.sendCommand(cmd, 1) + await socket.sendCommands([{ rawCommand: cmd, trackingId: 1 }]) // Should not get here expect(false).toBeTruthy() } catch (e) { - expect(e.message).toEqual('Command is not serializable') + expect(e.message).toEqual('Command ProductIdentifierCommand is not serializable') } // connect was called explicitly expect(AtemSocketChild).toHaveBeenCalledTimes(0) expect(AtemSocketChildSingleton.connect).toHaveBeenCalledTimes(0) expect(AtemSocketChildSingleton.disconnect).toHaveBeenCalledTimes(0) - expect(AtemSocketChildSingleton.sendCommand).toHaveBeenCalledTimes(0) + expect(AtemSocketChildSingleton.sendCommands).toHaveBeenCalledTimes(0) }) test('sendCommand', async () => { @@ -266,16 +266,20 @@ describe('AtemSocket', () => { const cmd = new MockCommand({}) const cmdId = 836 - await socket.sendCommand(cmd, cmdId) + await socket.sendCommands([{ rawCommand: cmd, trackingId: cmdId }]) // connect was called explicitly expect(AtemSocketChild).toHaveBeenCalledTimes(0) expect(AtemSocketChildSingleton.connect).toHaveBeenCalledTimes(0) expect(AtemSocketChildSingleton.disconnect).toHaveBeenCalledTimes(0) - expect(AtemSocketChildSingleton.sendCommand).toHaveBeenCalledTimes(1) - - const expectedBuffer = Buffer.concat([Buffer.from([0, 20, 0, 0, 84, 69, 83, 84]), cmd.serialize()]) - expect(AtemSocketChildSingleton.sendCommand).toHaveBeenCalledWith(expectedBuffer, cmdId) + expect(AtemSocketChildSingleton.sendCommands).toHaveBeenCalledTimes(1) + + const expectedBuffer = [...cmd.serialize()] + expect(AtemSocketChildSingleton.sendCommands).toHaveBeenCalledWith([{ + payload: expectedBuffer, + rawName: 'TEST', + trackingId: cmdId + }]) }) test('events', async () => { diff --git a/src/lib/__tests__/socket-child.spec.ts b/src/lib/__tests__/socket-child.spec.ts index 1a3a172de..85747e35b 100644 --- a/src/lib/__tests__/socket-child.spec.ts +++ b/src/lib/__tests__/socket-child.spec.ts @@ -355,7 +355,7 @@ describe('SocketChild', () => { } }) - test('SendCommand', async () => { + test('SendCommands', async () => { const child = createSocketChild() try { fakeConnect(child) @@ -375,20 +375,26 @@ describe('SocketChild', () => { } // Send something - const buf1 = Buffer.from([0, 1, 2]) - child.sendCommand(buf1, 1) + const buf1 = [0, 1, 2] + const cmdName = 'test' + const buf1Expected = Buffer.alloc(11) + buf1Expected.writeUInt16BE(buf1Expected.length, 0) + buf1Expected.write(cmdName, 4, 4) + Buffer.from(buf1).copy(buf1Expected, 8) + + child.sendCommands([{ payload: buf1, rawName: cmdName, trackingId: 1 }]) expect(received).toEqual([{ id: 123, - payload: buf1 + payload: buf1Expected }]) received = [] expect(getInflightIds(child)).toEqual([123]) // Send another - child.sendCommand(buf1, 1) + child.sendCommands([{ payload: buf1, rawName: cmdName, trackingId: 1 }]) expect(received).toEqual([{ id: 124, - payload: buf1 + payload: buf1Expected }]) received = [] expect(getInflightIds(child)).toEqual([123, 124 ]) @@ -438,13 +444,19 @@ describe('SocketChild', () => { acked = [] // Send some stuff - const buf1 = Buffer.from([0, 1, 2]) - child.sendCommand(buf1, 5) - child.sendCommand(buf1, 6) - child.sendCommand(buf1, 7) - child.sendCommand(buf1, 8) - child.sendCommand(buf1, 9) - child.sendCommand(buf1, 10) + const buf1 = [0, 1, 2] + child.sendCommands([ + { payload: buf1, rawName: '', trackingId: 5 }, + { payload: buf1, rawName: '', trackingId: 6 }, + { payload: buf1, rawName: '', trackingId: 7 } + ]) + child.sendCommands([ + { payload: buf1, rawName: '', trackingId: 8 } + ]) + child.sendCommands([ + { payload: buf1, rawName: '', trackingId: 9 }, + { payload: buf1, rawName: '', trackingId: 10 } + ]) expect(received).toEqual([123, 124, 125, 126, 127, 128]) received = [] expect(getInflightIds(child)).toEqual([123, 124, 125, 126, 127, 128]) @@ -498,13 +510,19 @@ describe('SocketChild', () => { acked = [] // Send some stuff - const buf1 = Buffer.from([0, 1, 2]) - child.sendCommand(buf1, 5) // 32764 - child.sendCommand(buf1, 6) // 32765 - child.sendCommand(buf1, 7) // 32766 - child.sendCommand(buf1, 8) // 32767 - child.sendCommand(buf1, 9) // 0 - child.sendCommand(buf1, 10)// 1 + const buf1 = [0, 1, 2] + child.sendCommands([ + { payload: buf1, rawName: '', trackingId: 5 }, // 32764 + { payload: buf1, rawName: '', trackingId: 6 }, // 32765 + { payload: buf1, rawName: '', trackingId: 7 } // 32766 + ]) + child.sendCommands([ + { payload: buf1, rawName: '', trackingId: 8 } // 32767 + ]) + child.sendCommands([ + { payload: buf1, rawName: '', trackingId: 9 }, // 0 + { payload: buf1, rawName: '', trackingId: 10 } // 1 + ]) expect(received).toEqual([32764, 32765, 32766, 32767, 0, 1]) received = [] expect(getInflightIds(child)).toEqual([32764, 32765, 32766, 32767, 0, 1]) diff --git a/src/lib/atemSocket.ts b/src/lib/atemSocket.ts index 0c0ef1485..38e94aa44 100644 --- a/src/lib/atemSocket.ts +++ b/src/lib/atemSocket.ts @@ -90,21 +90,24 @@ export class AtemSocket extends EventEmitter { return ++this._nextCommandTrackingId } - public async sendCommand (command: ISerializableCommand, trackingId: number): Promise { + public async sendCommands (commands: Array<{ rawCommand: ISerializableCommand, trackingId: number}>): Promise { if (this._socketProcess) { - if (typeof (command as any).serialize !== 'function') { - throw new Error('Command is not serializable') - } + const commands2 = commands.map(cmd => { + if (typeof (cmd.rawCommand as any).serialize !== 'function') { + throw new Error(`Command ${cmd.rawCommand.constructor.name} is not serializable`) + } - const payload = command.serialize(this._commandParser.version) - const fullPayload = Buffer.alloc(payload.length + 8, 0) - fullPayload.writeUInt16BE(fullPayload.length, 0) - fullPayload.write((command.constructor as any).rawName, 4, 4) - payload.copy(fullPayload, 8, 0) + const payload = cmd.rawCommand.serialize(this._commandParser.version) + if (this._debug) this.log('PAYLOAD', cmd.rawCommand.constructor.name, payload) - if (this._debug) this.log('PAYLOAD', command.constructor.name, fullPayload) + return { + payload: [...payload], + rawName: (cmd.rawCommand.constructor as any).rawName, + trackingId: cmd.trackingId + } + }) - await this._socketProcess.sendCommand(fullPayload, trackingId) + await this._socketProcess.sendCommands(commands2) } else { throw new Error('Socket process is not open') } diff --git a/src/lib/atemSocketChild.ts b/src/lib/atemSocketChild.ts index 8f300870c..3b3a06097 100644 --- a/src/lib/atemSocketChild.ts +++ b/src/lib/atemSocketChild.ts @@ -131,19 +131,29 @@ export class AtemSocketChild { this.onLog(message) } - public sendCommand (payload: Buffer, trackingId: number): void { + public sendCommands (commands: Array<{ payload: number[], rawName: string, trackingId: number }>): void { + commands.forEach(cmd => { + this.sendCommand(cmd.payload, cmd.rawName, cmd.trackingId) + }) + } + + private sendCommand (payload: number[], rawName: string, trackingId: number): void { const packetId = this._nextSendPacketId++ if (this._nextSendPacketId >= MAX_PACKET_ID) this._nextSendPacketId = 0 const opcode = PacketFlag.AckRequest << 11 - if (this._debug) this.log(`SEND ${payload}`) - const buffer = Buffer.alloc(12 + payload.length, 0) - buffer.writeUInt16BE(opcode | (payload.length + 12), 0) // Opcode & Length + const buffer = Buffer.alloc(20 + payload.length, 0) + buffer.writeUInt16BE(opcode | (payload.length + 20), 0) // Opcode & Length buffer.writeUInt16BE(this._sessionId, 2) buffer.writeUInt16BE(packetId, 10) - payload.copy(buffer, 12) + // Command + buffer.writeUInt16BE(payload.length + 8, 12) + buffer.write(rawName, 16, 4) + + // Body + Buffer.from(payload).copy(buffer, 20) this._sendPacket(buffer) this._inFlight.push({ From 0086eeebf15890d9efb5a0042d4e5635ef4d9a2e Mon Sep 17 00:00:00 2001 From: Julian Waller Date: Fri, 6 Dec 2019 00:05:29 +0000 Subject: [PATCH 35/68] fix: some command tests --- src/commands/DeviceProfile/topologyCommand.ts | 1 - .../Key/MixEffectKeyFlyKeyframeGetCommand.ts | 2 +- src/commands/__tests__/index.spec.ts | 48 +++++++++++-------- src/commands/__tests__/util.ts | 14 +++++- src/commands/__tests__/v8.0.1.spec.ts | 2 +- src/commands/__tests__/v8.0.spec.ts | 10 ++-- src/lib/atemUtil.ts | 4 +- src/state/info.ts | 1 - src/state/video/upstreamKeyers.ts | 2 +- 9 files changed, 52 insertions(+), 32 deletions(-) diff --git a/src/commands/DeviceProfile/topologyCommand.ts b/src/commands/DeviceProfile/topologyCommand.ts index 214c77a85..7c39c2675 100644 --- a/src/commands/DeviceProfile/topologyCommand.ts +++ b/src/commands/DeviceProfile/topologyCommand.ts @@ -17,7 +17,6 @@ export class TopologyCommand extends DeserializedCommand { maxHyperdecks: rawCommand[7], DVEs: rawCommand[8], stingers: rawCommand[9], - hasSuperSources: rawCommand[10] !== 0, superSources: rawCommand[10], talkbackOverSDI: rawCommand[13] } diff --git a/src/commands/MixEffects/Key/MixEffectKeyFlyKeyframeGetCommand.ts b/src/commands/MixEffects/Key/MixEffectKeyFlyKeyframeGetCommand.ts index 73e697956..e3c6af534 100644 --- a/src/commands/MixEffects/Key/MixEffectKeyFlyKeyframeGetCommand.ts +++ b/src/commands/MixEffects/Key/MixEffectKeyFlyKeyframeGetCommand.ts @@ -48,7 +48,7 @@ export class MixEffectKeyFlyKeyframeGetCommand extends DeserializedCommand ({ val: Math.round(v * 10) / 10 }), + 'balance': (v: number) => ({ val: Math.round(v) }), 'gain': (v: number) => ({ val: Math.round(v * 100) / 100 }) + }, + processDeserialized: props => { + props.gain = Math.round(props.gain * 100) / 100 } }, 'CAMI': { @@ -236,15 +239,15 @@ const commandConverters: CommandTestConverterSet = { 'index': 'index' }, propertyAliases: { - 'balance': (v: number) => ({ val: Math.round(v * 10) / 10 }), - 'gain': (v: number) => ({ val: Math.round(v * 100) / 100 }) + 'balance': (v: number) => ({ val: Math.round(v * 200) / 200 }) + // 'gain': (v: number) => ({ val: Math.round(v * 100) / 100 }) } }, 'AMMO': { idAliases: {}, propertyAliases: { 'programOutFollowFadeToBlack': (val: any) => ({ val, name: 'followFadeToBlack' }), - 'balance': (v: number) => ({ val: Math.round(v * 10) / 10 }), + 'balance': (v: number) => ({ val: Math.round(v) }), 'gain': (v: number) => ({ val: Math.round(v * 100) / 100 }) } }, @@ -259,10 +262,6 @@ const commandConverters: CommandTestConverterSet = { 'videoSources': (val: any) => ({ val, name: 'sources' }), 'superSource': (val: any) => ({ val, name: 'superSources' }), 'talkbackOverSDI': () => ({ val: 0 }) // @todo: should be fixed in atem-connection - }, - customMutate: (obj: any) => { - obj.hasSuperSources = obj.superSources !== 0 - return obj } }, 'FTCD': { @@ -771,21 +770,34 @@ const commandConverters: CommandTestConverterSet = { }, 'KKFP': { idAliases: { - 'keyerIndex': 'upstreamKeyerId', - 'mixEffectIndex': 'mixEffect' + 'upstreamKeyerId': 'keyerIndex', + 'mixEffect': 'mixEffectIndex' }, propertyAliases: { 'bevelPosition': (val: any) => ({ val, name: 'borderBevelPosition' }), 'bevelSoftness': (val: any) => ({ val, name: 'borderBevelSoftness' }), 'innerSoftness': (val: any) => ({ val, name: 'borderInnerSoftness' }), - 'innerWidth': (val: any) => ({ val, name: 'borderInnerWidth' }), + 'innerWidth': (val: any) => ({ val: Math.round(val * 100), name: 'borderInnerWidth' }), 'keyFrame': (val: any) => ({ val, name: 'keyFrameId' }), 'outerSoftness': (val: any) => ({ val, name: 'borderOuterSoftness' }), - 'outerWidth': (val: any) => ({ val, name: 'borderOuterWidth' }), - 'xPosition': (val: any) => ({ val, name: 'positionX' }), - 'xSize': (val: any) => ({ val, name: 'sizeX' }), - 'yPosition': (val: any) => ({ val, name: 'positionY' }), - 'ySize': (val: any) => ({ val, name: 'sizeY' }) + 'outerWidth': (val: any) => ({ val: Math.round(val * 100), name: 'borderOuterWidth' }), + 'xPosition': (val: any) => ({ val: Math.round(val * 1000), name: 'positionX' }), + 'xSize': (val: any) => ({ val: Math.round(val * 1000), name: 'sizeX' }), + 'yPosition': (val: any) => ({ val: Math.round(val * 1000), name: 'positionY' }), + 'ySize': (val: any) => ({ val: Math.round(val * 1000), name: 'sizeY' }), + 'rotation': (val: any) => ({ val: Math.round(val * 10) }), + 'borderHue': (val: any) => ({ val: Math.round(val * 10) }), + 'borderLuma': (val: any) => ({ val: Math.round(val * 10) }), + 'borderSaturation': (val: any) => ({ val: Math.round(val * 10) }), + 'lightSourceDirection': (val: any) => ({ val: Math.round(val * 10) }), + 'maskBottom': (val: any) => ({ val: Math.round(val * 1000) }), + 'maskTop': (val: any) => ({ val: Math.round(val * 1000) }), + 'maskLeft': (val: any) => ({ val: Math.round(val * 1000) }), + 'maskRight': (val: any) => ({ val: Math.round(val * 1000) }) + }, + customMutate: (obj: any) => { + delete obj.maskEnabled + return obj } }, 'MPCE': { @@ -823,10 +835,6 @@ describe('Commands v7.2', () => { const testCase = TestCases[i] switch (testCase.name) { // Temporarily ignore the failures - case 'AMMO': - case 'KKFP': // LibAtem incorrectly(?) uses doubles - case 'CAMI': // floating point errors I think - case 'AMIP': // floating point errors I think case 'FTSU': // Unkown props getting overwritten by generator: https://github.com/LibAtem/LibAtem/blob/master/LibAtem/Commands/DataTransfer/DataTransferDownloadRequestCommand.cs case 'TDpP': // Range validation errors continue diff --git a/src/commands/__tests__/util.ts b/src/commands/__tests__/util.ts index d667c8d94..3080c6b80 100644 --- a/src/commands/__tests__/util.ts +++ b/src/commands/__tests__/util.ts @@ -4,9 +4,13 @@ import { IDeserializedCommand, ISerializableCommand } from '../CommandBase' export type CommandTestConverterSet = { [key: string]: CommandTestConverter } export interface CommandTestConverter { - idAliases: { [key: string]: string } + /** Internal name to LibAtem name */ + idAliases: { [internalName: string]: string } + /** LibAtem name to Internal name & mutated value */ propertyAliases: { [key: string]: (v: any) => { name?: string, val: any } } customMutate?: (v: any) => any + /** pre-process deserialized command */ + processDeserialized?: (v: any) => void } export interface TestCase { @@ -19,6 +23,10 @@ export function runTestForCommand (commandParser: CommandParser, commandConverte const cmdConstructor = commandParser.commandFromRawName(testCase.name) if (!cmdConstructor && allowUnknown) return + // if (i !== 1121) { + // return + // } + let matchedCase = false if (cmdConstructor) { const buffer = Buffer.from(testCase.bytes.replace(/-/g, ''), 'hex') @@ -48,6 +56,10 @@ export function runTestForCommand (commandParser: CommandParser, commandConverte // delete (cmd as any).rawCommand if (converter) { + if (converter.processDeserialized) { + converter.processDeserialized(cmd.properties) + } + for (const key in cmd) { const newName = converter.idAliases[key] if (cmd.hasOwnProperty(key) && newName) { diff --git a/src/commands/__tests__/v8.0.1.spec.ts b/src/commands/__tests__/v8.0.1.spec.ts index 2e0a3cd50..477ecebe1 100644 --- a/src/commands/__tests__/v8.0.1.spec.ts +++ b/src/commands/__tests__/v8.0.1.spec.ts @@ -32,7 +32,7 @@ describe('Commands v8.0.1', () => { switch (testCase.name) { // Not parsed // case '_MvC': - // return + // continue } runTestForCommand(commandParser, commandConverters, i, testCase) diff --git a/src/commands/__tests__/v8.0.spec.ts b/src/commands/__tests__/v8.0.spec.ts index ceb80555c..7dbdd0027 100644 --- a/src/commands/__tests__/v8.0.spec.ts +++ b/src/commands/__tests__/v8.0.spec.ts @@ -10,7 +10,7 @@ const commandConverters: CommandTestConverterSet = { 'index': 'index' }, propertyAliases: { - 'balance': (v: number) => ({ val: Math.round(v * 10) / 10 }), + 'balance': (v: number) => ({ val: Math.round(v) }), 'gain': (v: number) => ({ val: Math.round(v * 100) / 100 }) } }, @@ -30,7 +30,8 @@ const commandConverters: CommandTestConverterSet = { 'hyperDecks': (val: any) => ({ val, name: 'maxHyperdecks' }), 'mixEffectBlocks': (val: any) => ({ val, name: 'MEs' }), 'serialPort': (val: any) => ({ val, name: 'serialPorts' }), - 'videoSources': (val: any) => ({ val, name: 'sources' }) + 'videoSources': (val: any) => ({ val, name: 'sources' }), + 'superSource': (val: any) => ({ val, name: 'superSources' }) } }, 'SSrc': { @@ -129,8 +130,9 @@ describe('Commands v8.0', () => { switch (testCase.name) { // Not parsed - case '_MvC': - return + case '_MvC': // Not parsed + case 'AMIP': // portType max value + continue } runTestForCommand(commandParser, commandConverters, i, testCase) diff --git a/src/lib/atemUtil.ts b/src/lib/atemUtil.ts index d12c8b452..6f6ae7933 100644 --- a/src/lib/atemUtil.ts +++ b/src/lib/atemUtil.ts @@ -145,12 +145,12 @@ export namespace Util { } export function DecibelToUInt16BE (input: number) { - return parseInt(Math.pow(10, input / 20) * 32768 + '', 10) + return Math.floor(Math.pow(10, input / 20) * 32768) } export function IntToBalance (input: number): number { // -100000 = -50, 0x0000 = 0, 0x2710 = +50 - return Math.round((input / 200) * 10) / 10 + return Math.round(input / 200) } export function BalanceToInt (input: number): number { return Math.round(input * 200) diff --git a/src/state/info.ts b/src/state/info.ts index 7b055fc03..cd84d5bef 100644 --- a/src/state/info.ts +++ b/src/state/info.ts @@ -11,7 +11,6 @@ export interface AtemCapabilites { readonly maxHyperdecks: number readonly DVEs: number readonly stingers: number - readonly hasSuperSources: boolean readonly superSources: number readonly talkbackOverSDI: number } diff --git a/src/state/video/upstreamKeyers.ts b/src/state/video/upstreamKeyers.ts index 12e046995..801bf7745 100644 --- a/src/state/video/upstreamKeyers.ts +++ b/src/state/video/upstreamKeyers.ts @@ -49,7 +49,7 @@ export interface UpstreamKeyerDVESettings extends UpstreamKeyerDVEBase { rate: number } -export interface UpstreamKeyerFlyKeyframe extends UpstreamKeyerDVEBase { +export interface UpstreamKeyerFlyKeyframe extends Omit { readonly keyFrameId: number } From d1cf1741bc2c97f4e39dc8960e41234c76ee50e0 Mon Sep 17 00:00:00 2001 From: Julian Waller Date: Fri, 6 Dec 2019 18:12:08 +0000 Subject: [PATCH 36/68] feat: tests for audio and clips uploading --- .../testUtils/generate-data-transfer-spec.ts | 60 + src/dataTransfer/__tests__/index.spec.ts | 93 +- src/dataTransfer/__tests__/sampleAudio.wav | Bin 0 -> 406346 bytes .../__tests__/upload-clip-sequence.json | 179977 +++++++++++++++ .../__tests__/upload-still-sequence.json | 2 +- .../__tests__/upload-wav-sequence.json | 3047 + src/dataTransfer/dataTransfer.ts | 10 +- src/dataTransfer/index.ts | 2 +- src/lib/atemUtil.ts | 3 +- 9 files changed, 183122 insertions(+), 72 deletions(-) create mode 100644 examples/testUtils/generate-data-transfer-spec.ts create mode 100644 src/dataTransfer/__tests__/sampleAudio.wav create mode 100644 src/dataTransfer/__tests__/upload-clip-sequence.json create mode 100644 src/dataTransfer/__tests__/upload-wav-sequence.json diff --git a/examples/testUtils/generate-data-transfer-spec.ts b/examples/testUtils/generate-data-transfer-spec.ts new file mode 100644 index 000000000..8e9225996 --- /dev/null +++ b/examples/testUtils/generate-data-transfer-spec.ts @@ -0,0 +1,60 @@ +import { Atem } from '../../dist' +import { DataTransferManager } from '../../dist/dataTransfer' +import * as fs from 'fs' + +const frameBuffer = Buffer.alloc(1920 * 1080 * 4,0) +// const wavBuffer = fs.readFileSync('./src/dataTransfer/__tests__/sampleAudio.wav') + +const nb = new Atem({ debug: false }) +nb.on('error', () => null) + +nb.on('connected', async () => { + console.log('connected') + const commands: any[] = [] + + const procCmd = (cmd: any, dir: string) => { + const props = { ...cmd.properties } + Object.keys(props).forEach(k => { + if (Buffer.isBuffer(props[k])) { + const buf = props[k] as Buffer + props[k] = { bufferLength: buf.length } + } + }) + return { + name: cmd.constructor.name, + properties: props, + direction: dir + } + } + + const transfer = new DataTransferManager() + transfer.startCommandSending(cmds => { + return cmds.map(cmd => { + commands.push(procCmd(cmd, 'send')) + return nb.sendCommand(cmd) + }) + }) + nb.on('receivedCommand', cmd => { + commands.push(procCmd(cmd, 'recv')) + transfer.handleCommand(cmd) + }) + + console.log('uploading') + // await transfer.uploadStill(0, frameBuffer, 'some still', '') + // await transfer.uploadAudio(1, wavBuffer, 'audio file') + await transfer.uploadClip(1, [frameBuffer, frameBuffer, frameBuffer], 'clip file') + + console.log('uploaded') + + await new Promise(resolve => setTimeout(resolve, 1000)) + + // console.log(JSON.stringify({ + // sent: sentCommands, + // received: receivedCommands + // })) + fs.writeFileSync('upload.json', JSON.stringify(commands, undefined, '\t')) + + process.exit(0) + +}) +nb.connect('10.42.13.98', 9910) diff --git a/src/dataTransfer/__tests__/index.spec.ts b/src/dataTransfer/__tests__/index.spec.ts index ca0613e1a..49bdd57dc 100644 --- a/src/dataTransfer/__tests__/index.spec.ts +++ b/src/dataTransfer/__tests__/index.spec.ts @@ -56,73 +56,38 @@ test('Test Still upload', async () => { const newBuffer = Buffer.alloc(1920 * 1080 * 4, 0) const manager = runDataTransferTest(spec) - await manager.uploadStill(0, newBuffer, 'some still', '') + await manager.uploadStill(2, newBuffer, 'some still', '') - await new Promise(resolve => setTimeout(resolve, 1000)) + await new Promise(resolve => setTimeout(resolve, 200)) // Nothing should be left by this point expect(spec).toHaveLength(0) }) -// function cleanupAtem (atem: Atem) { -// const atem2 = atem as any -// atem2.dataTransferManager.stop() - -// const sock = atem2.socket._socketProcess -// sock.removeAllListeners() -// sock.kill() -// } - -// test('TMP: Generate DataTransferSpec', async () => { -// const newBuffer = Buffer.alloc(1920 * 1080 * 4, 0) - -// const nb = new Atem({ debug: false }) -// try { -// nb.on('error', () => null) - -// await new Promise(resolve => { -// nb.on('connected', resolve) -// nb.connect('10.42.13.99') -// }) - -// const commands: any[] = [] - -// const procCmd = (cmd: AbstractCommand, dir: string) => { -// const props = { ...cmd.properties } -// Object.keys(props).forEach(k => { -// if (Buffer.isBuffer(props[k])) { -// const buf = props[k] as Buffer -// props[k] = { bufferLength: buf.length } -// } -// }) -// return { -// name: cmd.constructor.name, -// properties: props, -// direction: dir -// } -// } - -// const transfer = new DataTransferManager(cmd => { -// commands.push(procCmd(cmd, 'send')) -// return nb.sendCommand(cmd) -// }) -// nb.on('receivedCommand', cmd => { -// commands.push(procCmd(cmd, 'recv')) -// transfer.handleCommand(cmd) -// }) - -// await transfer.uploadStill(0, newBuffer, 'some still', '') - -// await new Promise(resolve => setTimeout(resolve, 1000)) - -// // console.log(JSON.stringify({ -// // sent: sentCommands, -// // received: receivedCommands -// // })) -// writeFileSync('upload.json', JSON.stringify(commands, undefined, '\t')) - -// expect(nb).toBeTruthy() -// } finally { -// cleanupAtem(nb) -// } -// }) +test('Test Wav upload', async () => { + const spec: any[] = JSON.parse(readFileSync(path.join(__dirname, './upload-wav-sequence.json')).toString()) + + const newBuffer = readFileSync(path.join(__dirname, './sampleAudio.wav')) + + const manager = runDataTransferTest(spec) + await manager.uploadAudio(1, newBuffer, 'audio file') + + await new Promise(resolve => setTimeout(resolve, 200)) + + // Nothing should be left by this point + expect(spec).toHaveLength(0) +}) + +test('Test clip upload', async () => { + const spec: any[] = JSON.parse(readFileSync(path.join(__dirname, './upload-clip-sequence.json')).toString()) + + const newBuffer = Buffer.alloc(1920 * 1080 * 4, 0) + + const manager = runDataTransferTest(spec) + await manager.uploadClip(1, [newBuffer, newBuffer, newBuffer], 'clip file') + + await new Promise(resolve => setTimeout(resolve, 200)) + + // Nothing should be left by this point + expect(spec).toHaveLength(0) +}, 10000) diff --git a/src/dataTransfer/__tests__/sampleAudio.wav b/src/dataTransfer/__tests__/sampleAudio.wav new file mode 100644 index 0000000000000000000000000000000000000000..50a2d4c1e07b21a0277d4258e20323db8430acba GIT binary patch literal 406346 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 gv%>Noc-FVc)V>T4kLtt-VgzY8N^#o`=SXhT-O- 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 pY``&W9j_gS-3A1@8T;4CU+5}pJe5~tc-lF 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 - private readonly completionPromise: Promise public resolvePromise: (value?: DataTransfer | PromiseLike | undefined) => void public rejectPromise: (reason?: any) => void constructor (transferId: number, storeId: number) { - this.transferId = transferId + this._transferId = transferId this.storeId = storeId // Make typescript happy @@ -27,6 +25,10 @@ export default abstract class DataTransfer { }) } + get transferId () { + return this._transferId + } + get promise () { return this.completionPromise } diff --git a/src/dataTransfer/index.ts b/src/dataTransfer/index.ts index 4dd8d2ac0..ab3009bd2 100644 --- a/src/dataTransfer/index.ts +++ b/src/dataTransfer/index.ts @@ -115,7 +115,7 @@ export class DataTransferManager { public async uploadClip (index: number, data: Array, name: string) { const frames = data.map((frame, id) => new DataTransferFrame(this.nextTransferIndex, 1 + index, id, frame)) - const transfer = new DataTransferClip(1 + index, name, frames) + const transfer = new DataTransferClip(index, name, frames) const lock = await this.getClipLock(index) return lock.enqueue(transfer) } diff --git a/src/lib/atemUtil.ts b/src/lib/atemUtil.ts index 6f6ae7933..f34f140c8 100644 --- a/src/lib/atemUtil.ts +++ b/src/lib/atemUtil.ts @@ -131,9 +131,8 @@ export namespace Util { const buffer = Buffer.from(wav.data.samples) const buffer2 = Buffer.alloc(buffer.length) for (let i = 0; i < buffer.length; i += 3) { - // TODO - is this the correct way around? (only matters for readability) // 24bit samples, change endian - buffer2.writeUIntLE(buffer.readUIntBE(i, 3), i, 3) + buffer2.writeUIntBE(buffer.readUIntLE(i, 3), i, 3) } return buffer2 From 0f005ec04fd8cd4b0d9d7fc98ddd004891366d52 Mon Sep 17 00:00:00 2001 From: Julian Waller Date: Fri, 6 Dec 2019 18:25:16 +0000 Subject: [PATCH 37/68] chore: refactor convertRGBAToYUV422 --- src/lib/atemUtil.ts | 28 ++++++++++++---------------- 1 file changed, 12 insertions(+), 16 deletions(-) diff --git a/src/lib/atemUtil.ts b/src/lib/atemUtil.ts index f34f140c8..f429fdad2 100644 --- a/src/lib/atemUtil.ts +++ b/src/lib/atemUtil.ts @@ -62,6 +62,14 @@ export namespace Util { const KBoKRi = KB / KRi * HalfCbCrRange const KGoKRi = KG / KRi * HalfCbCrRange + const genColor = (rawA: number, uv16: number, y16: number) => { + const a = ((rawA << 2) * 219 / 255) + (16 << 2) + const y = Math.round(y16) >> 6 + const uv = Math.round(uv16) >> 6 + + return (a << 20) + (uv << 10) + y + } + const buffer = Buffer.alloc(width * height * 4) for (let i = 0; i < width * height * 4; i += 8) { const r1 = data[i + 0] @@ -72,28 +80,16 @@ export namespace Util { const g2 = data[i + 5] const b2 = data[i + 6] - const a1 = ((data[i + 3] << 2) * 219 / 255) + (16 << 2) - const a2 = ((data[i + 7] << 2) * 219 / 255) + (16 << 2) + const a1 = data[i + 3] + const a2 = data[i + 7] const y16a = YOffset + KR * YRange * r1 + KG * YRange * g1 + KB * YRange * b1 const cb16 = CbCrOffset + (-KRoKBi * r1 - KGoKBi * g1 + HalfCbCrRange * b1) const y16b = YOffset + KR * YRange * r2 + KG * YRange * g2 + KB * YRange * b2 const cr16 = CbCrOffset + (HalfCbCrRange * r1 - KGoKRi * g1 - KBoKRi * b1) - const y1 = Math.round(y16a) >> 6 - const u1 = Math.round(cb16) >> 6 - const y2 = Math.round(y16b) >> 6 - const v2 = Math.round(cr16) >> 6 - - // TODO - rewrite using buffer.writeUIntLE/writeUIntBE? - buffer[i + 0] = a1 >> 4 - buffer[i + 1] = ((a1 & 0x0f) << 4) | (u1 >> 6) - buffer[i + 2] = ((u1 & 0x3f) << 2) | (y1 >> 8) - buffer[i + 3] = y1 & 0xff - buffer[i + 4] = a2 >> 4 - buffer[i + 5] = ((a2 & 0x0f) << 4) | (v2 >> 6) - buffer[i + 6] = ((v2 & 0x3f) << 2) | (y2 >> 8) - buffer[i + 7] = y2 & 0xff + buffer.writeUInt32BE(genColor(a1, cb16, y16a), i) + buffer.writeUInt32BE(genColor(a2, cr16, y16b), i + 4) } return buffer } From 24eb1da8981217b75b65cbcb4145cef850268d64 Mon Sep 17 00:00:00 2001 From: Julian Waller Date: Fri, 6 Dec 2019 18:41:42 +0000 Subject: [PATCH 38/68] feat: ensure state update after deserialize is successful --- src/commands/__tests__/util.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/commands/__tests__/util.ts b/src/commands/__tests__/util.ts index 3080c6b80..7186d0565 100644 --- a/src/commands/__tests__/util.ts +++ b/src/commands/__tests__/util.ts @@ -1,6 +1,7 @@ import { CommandParser } from '../../lib/atemCommandParser' import { ProtocolVersion } from '../../enums' import { IDeserializedCommand, ISerializableCommand } from '../CommandBase' +import { AtemState } from '../../state' export type CommandTestConverterSet = { [key: string]: CommandTestConverter } export interface CommandTestConverter { @@ -70,6 +71,10 @@ export function runTestForCommand (commandParser: CommandParser, commandConverte } expect(cmd.properties).toEqual(mutatedCommand) + + const state = new AtemState() + // Ensure state update doesnt error + expect(cmd.applyToState(state)).toBeTruthy() }) } From 29e61bd7fbeb567ef9861e7585216aa672039ae7 Mon Sep 17 00:00:00 2001 From: Julian Waller Date: Fri, 6 Dec 2019 19:06:22 +0000 Subject: [PATCH 39/68] feat: don't validate deserialized commands values are in range --- .../DownstreamKeyPropertiesCommand.ts | 23 ++++--- .../DownstreamKeySourcesCommand.ts | 3 +- .../DownstreamKeyStateCommand.ts | 5 +- .../Media/MediaPlayerStatusCommand.ts | 3 +- .../FadeToBlack/FadeToBlackRateCommand.ts | 3 +- .../FadeToBlack/FadeToBlackStateCommand.ts | 5 +- .../Key/MixEffectKeyChromaCommand.ts | 13 ++-- .../MixEffects/Key/MixEffectKeyDVECommand.ts | 55 ++++++++--------- .../Key/MixEffectKeyFlyKeyframeGetCommand.ts | 50 ++++++++------- .../MixEffectKeyFlyPropertiesGetCommand.ts | 5 +- .../MixEffects/Key/MixEffectKeyLumaCommand.ts | 9 ++- .../Key/MixEffectKeyOnAirCommand.ts | 5 +- .../Key/MixEffectKeyPatternCommand.ts | 17 +++--- .../Key/MixEffectKeyPropertiesGetCommand.ts | 15 +++-- .../MixEffects/PreviewInputCommand.ts | 3 +- .../MixEffects/ProgramInputCommand.ts | 3 +- .../Transition/TransitionDVECommand.ts | 13 ++-- .../Transition/TransitionDipCommand.ts | 5 +- .../Transition/TransitionMixCommand.ts | 5 +- .../Transition/TransitionPositionCommand.ts | 7 +-- .../Transition/TransitionPreviewCommand.ts | 3 +- .../Transition/TransitionPropertiesCommand.ts | 11 ++-- .../Transition/TransitionStingerCommand.ts | 7 +-- .../Transition/TransitionWipeCommand.ts | 17 +++--- .../SuperSourceBoxParametersCommand.ts | 15 +++-- .../SuperSourcePropertiesCommand.ts | 61 +++++++++---------- src/lib/atemUtil.ts | 16 ----- 27 files changed, 167 insertions(+), 210 deletions(-) diff --git a/src/commands/DownstreamKey/DownstreamKeyPropertiesCommand.ts b/src/commands/DownstreamKey/DownstreamKeyPropertiesCommand.ts index e5387d23a..a17e2a4ba 100644 --- a/src/commands/DownstreamKey/DownstreamKeyPropertiesCommand.ts +++ b/src/commands/DownstreamKey/DownstreamKeyPropertiesCommand.ts @@ -1,7 +1,6 @@ import { DeserializedCommand } from '../CommandBase' import { AtemState } from '../../state' import { DownstreamKeyerProperties } from '../../state/video/downstreamKeyers' -import { Util } from '../..' export class DownstreamKeyPropertiesCommand extends DeserializedCommand { public static readonly rawName = 'DskP' @@ -17,20 +16,20 @@ export class DownstreamKeyPropertiesCommand extends DeserializedCommand { @@ -15,7 +14,7 @@ export class DownstreamKeySourcesCommand extends DeserializedCommand { @@ -16,7 +15,7 @@ export class DownstreamKeyStateCommand extends DeserializedCommand { public static MaskFlags = { @@ -44,7 +43,7 @@ export class MediaPlayerStatusUpdateCommand extends DeserializedCommand { public static readonly rawName = 'FtbC' @@ -34,7 +33,7 @@ export class FadeToBlackRateUpdateCommand extends DeserializedCommand<{ rate: nu } public static deserialize (rawCommand: Buffer) { - const mixEffect = Util.parseNumberBetween(rawCommand[0], 0, 3) + const mixEffect = rawCommand.readUInt8(0) const rate = rawCommand.readUInt8(1) return new FadeToBlackRateUpdateCommand(mixEffect, rate) diff --git a/src/commands/MixEffects/FadeToBlack/FadeToBlackStateCommand.ts b/src/commands/MixEffects/FadeToBlack/FadeToBlackStateCommand.ts index 300cd59a7..2cf30d2fe 100644 --- a/src/commands/MixEffects/FadeToBlack/FadeToBlackStateCommand.ts +++ b/src/commands/MixEffects/FadeToBlack/FadeToBlackStateCommand.ts @@ -1,6 +1,5 @@ import { DeserializedCommand } from '../../CommandBase' import { AtemState } from '../../../state' -import { Util } from '../../..' export interface FadeToBlackProps { isFullyBlack: boolean @@ -20,11 +19,11 @@ export class FadeToBlackStateCommand extends DeserializedCommand { public static MaskFlags = { @@ -53,13 +52,13 @@ export class MixEffectKeyChromaUpdateCommand extends DeserializedCommand { public static MaskFlags = { @@ -100,42 +99,42 @@ export class MixEffectKeyDVEUpdateCommand extends DeserializedCommand(rawCommand.readUInt8(26), Enums.BorderBevel), - borderOuterWidth: Util.parseNumberBetween(rawCommand.readUInt16BE(28), 0, 1600), - borderInnerWidth: Util.parseNumberBetween(rawCommand.readUInt16BE(30), 0, 1600), - borderOuterSoftness: Util.parseNumberBetween(rawCommand.readInt8(32), 0, 100), - borderInnerSoftness: Util.parseNumberBetween(rawCommand.readInt8(33), 0, 100), - borderBevelSoftness: Util.parseNumberBetween(rawCommand.readInt8(34), 0, 100), - borderBevelPosition: Util.parseNumberBetween(rawCommand.readInt8(35), 0, 100), - - borderOpacity: Util.parseNumberBetween(rawCommand.readInt8(36), 0, 100), - borderHue: Util.parseNumberBetween(rawCommand.readUInt16BE(38), 0, 3600), - borderSaturation: Util.parseNumberBetween(rawCommand.readUInt16BE(40), 0, 1000), - borderLuma: Util.parseNumberBetween(rawCommand.readUInt16BE(42), 0, 1000), - - lightSourceDirection: Util.parseNumberBetween(rawCommand.readUInt16BE(44), 0, 3599), - lightSourceAltitude: Util.parseNumberBetween(rawCommand.readUInt8(46), 0, 100), + borderBevel: rawCommand.readUInt8(26), + borderOuterWidth: rawCommand.readUInt16BE(28), + borderInnerWidth: rawCommand.readUInt16BE(30), + borderOuterSoftness: rawCommand.readInt8(32), + borderInnerSoftness: rawCommand.readInt8(33), + borderBevelSoftness: rawCommand.readInt8(34), + borderBevelPosition: rawCommand.readInt8(35), + + borderOpacity: rawCommand.readInt8(36), + borderHue: rawCommand.readUInt16BE(38), + borderSaturation: rawCommand.readUInt16BE(40), + borderLuma: rawCommand.readUInt16BE(42), + + lightSourceDirection: rawCommand.readUInt16BE(44), + lightSourceAltitude: rawCommand.readUInt8(46), maskEnabled: rawCommand[47] === 1, - maskTop: Util.parseNumberBetween(rawCommand.readUInt16BE(48), 0, 38000), - maskBottom: Util.parseNumberBetween(rawCommand.readUInt16BE(50), 0, 38000), - maskLeft: Util.parseNumberBetween(rawCommand.readUInt16BE(52), 0, 52000), - maskRight: Util.parseNumberBetween(rawCommand.readUInt16BE(54), 0, 52000), + maskTop: rawCommand.readUInt16BE(48), + maskBottom: rawCommand.readUInt16BE(50), + maskLeft: rawCommand.readUInt16BE(52), + maskRight: rawCommand.readUInt16BE(54), - rate: Util.parseNumberBetween(rawCommand.readUInt8(56), 0, 250) + rate: rawCommand.readUInt8(56) } return new MixEffectKeyDVEUpdateCommand(mixEffect, upstreamKeyerId, properties) diff --git a/src/commands/MixEffects/Key/MixEffectKeyFlyKeyframeGetCommand.ts b/src/commands/MixEffects/Key/MixEffectKeyFlyKeyframeGetCommand.ts index e3c6af534..2abab0a10 100644 --- a/src/commands/MixEffects/Key/MixEffectKeyFlyKeyframeGetCommand.ts +++ b/src/commands/MixEffects/Key/MixEffectKeyFlyKeyframeGetCommand.ts @@ -1,7 +1,6 @@ import { DeserializedCommand } from '../../CommandBase' import { AtemState } from '../../../state' import { UpstreamKeyerFlyKeyframe } from '../../../state/video/upstreamKeyers' -import { Util } from '../../..' export class MixEffectKeyFlyKeyframeGetCommand extends DeserializedCommand { public static readonly rawName = 'KKFP' @@ -19,40 +18,39 @@ export class MixEffectKeyFlyKeyframeGetCommand extends DeserializedCommand { public static readonly rawName = 'KeFS' @@ -17,8 +16,8 @@ export class MixEffectKeyFlyPropertiesGetCommand extends DeserializedCommand { public static MaskFlags = { @@ -51,12 +50,12 @@ export class MixEffectKeyLumaUpdateCommand extends DeserializedCommand { public static readonly rawName = 'CKOn' @@ -38,8 +37,8 @@ export class MixEffectKeyOnAirUpdateCommand extends DeserializedCommand<{onAir: } public static deserialize (rawCommand: Buffer) { - const mixEffect = Util.parseNumberBetween(rawCommand[0], 0, 3) - const upstreamKeyerId = Util.parseNumberBetween(rawCommand[1], 0, 3) + const mixEffect = rawCommand[0] + const upstreamKeyerId = rawCommand[1] const properties = { onAir: rawCommand[2] === 1 } diff --git a/src/commands/MixEffects/Key/MixEffectKeyPatternCommand.ts b/src/commands/MixEffects/Key/MixEffectKeyPatternCommand.ts index 187fb6762..5d13cae1d 100644 --- a/src/commands/MixEffects/Key/MixEffectKeyPatternCommand.ts +++ b/src/commands/MixEffects/Key/MixEffectKeyPatternCommand.ts @@ -1,7 +1,6 @@ import { WritableCommand, DeserializedCommand } from '../../CommandBase' import { AtemState } from '../../../state' import { UpstreamKeyerPatternSettings } from '../../../state/video/upstreamKeyers' -import { Util, Enums } from '../../..' export class MixEffectKeyPatternCommand extends WritableCommand { public static MaskFlags = { @@ -58,15 +57,15 @@ export class MixEffectKeyUpdateCommand extends DeserializedCommand(rawCommand[2], Enums.Pattern), - size: Util.parseNumberBetween(rawCommand.readUInt16BE(4), 0, 10000), - symmetry: Util.parseNumberBetween(rawCommand.readUInt16BE(6), 0, 10000), - softness: Util.parseNumberBetween(rawCommand.readUInt16BE(8), 0, 10000), - positionX: Util.parseNumberBetween(rawCommand.readUInt16BE(10), 0, 10000), - positionY: Util.parseNumberBetween(rawCommand.readUInt16BE(12), 0, 10000), + style: rawCommand.readUInt8(2), + size: rawCommand.readUInt16BE(4), + symmetry: rawCommand.readUInt16BE(6), + softness: rawCommand.readUInt16BE(8), + positionX: rawCommand.readUInt16BE(10), + positionY: rawCommand.readUInt16BE(12), invert: rawCommand[14] === 1 } diff --git a/src/commands/MixEffects/Key/MixEffectKeyPropertiesGetCommand.ts b/src/commands/MixEffects/Key/MixEffectKeyPropertiesGetCommand.ts index 044991730..05821bd0a 100644 --- a/src/commands/MixEffects/Key/MixEffectKeyPropertiesGetCommand.ts +++ b/src/commands/MixEffects/Key/MixEffectKeyPropertiesGetCommand.ts @@ -1,7 +1,6 @@ import { DeserializedCommand } from '../../CommandBase' import { AtemState } from '../../../state' import { UpstreamKeyerBase } from '../../../state/video/upstreamKeyers' -import { Util, Enums } from '../../..' export class MixEffectKeyPropertiesGetCommand extends DeserializedCommand { public static readonly rawName = 'KeBP' @@ -15,18 +14,18 @@ export class MixEffectKeyPropertiesGetCommand extends DeserializedCommand(rawCommand[2], Enums.MixEffectKeyType), + upstreamKeyerId: rawCommand[1], + mixEffectKeyType: rawCommand.readUInt8(2), flyEnabled: rawCommand[5] === 1, fillSource: rawCommand.readUInt16BE(6), cutSource: rawCommand.readUInt16BE(8), maskEnabled: rawCommand[10] === 1, - maskTop: Util.parseNumberBetween(rawCommand.readInt16BE(12), -9000, 9000), - maskBottom: Util.parseNumberBetween(rawCommand.readInt16BE(14), -9000, 9000), - maskLeft: Util.parseNumberBetween(rawCommand.readInt16BE(16), -16000, 16000), - maskRight: Util.parseNumberBetween(rawCommand.readInt16BE(18), -16000, 16000) + maskTop: rawCommand.readInt16BE(12), + maskBottom: rawCommand.readInt16BE(14), + maskLeft: rawCommand.readInt16BE(16), + maskRight: rawCommand.readInt16BE(18) } return new MixEffectKeyPropertiesGetCommand(mixEffect, properties) diff --git a/src/commands/MixEffects/PreviewInputCommand.ts b/src/commands/MixEffects/PreviewInputCommand.ts index b4d1aff47..a12b2936a 100644 --- a/src/commands/MixEffects/PreviewInputCommand.ts +++ b/src/commands/MixEffects/PreviewInputCommand.ts @@ -1,6 +1,5 @@ import { BasicWritableCommand, DeserializedCommand } from '../CommandBase' import { AtemState } from '../../state' -import { Util } from '../..' export interface InputSource { source: number @@ -37,7 +36,7 @@ export class PreviewInputUpdateCommand extends DeserializedCommand } public static deserialize (rawCommand: Buffer): PreviewInputUpdateCommand { - const mixEffect = Util.parseNumberBetween(rawCommand[0], 0, 3) + const mixEffect = rawCommand[0] const properties = { source: rawCommand.readUInt16BE(2) } diff --git a/src/commands/MixEffects/ProgramInputCommand.ts b/src/commands/MixEffects/ProgramInputCommand.ts index 5a5bb7c9a..bc905e128 100644 --- a/src/commands/MixEffects/ProgramInputCommand.ts +++ b/src/commands/MixEffects/ProgramInputCommand.ts @@ -1,6 +1,5 @@ import { BasicWritableCommand, DeserializedCommand } from '../CommandBase' import { AtemState } from '../../state' -import { Util } from '../..' import { InputSource } from './PreviewInputCommand' export class ProgramInputCommand extends BasicWritableCommand { @@ -34,7 +33,7 @@ export class ProgramInputUpdateCommand extends DeserializedCommand } public static deserialize (rawCommand: Buffer): ProgramInputUpdateCommand { - const mixEffect = Util.parseNumberBetween(rawCommand[0], 0, 3) + const mixEffect = rawCommand[0] const properties = { source: rawCommand.readUInt16BE(2) } diff --git a/src/commands/MixEffects/Transition/TransitionDVECommand.ts b/src/commands/MixEffects/Transition/TransitionDVECommand.ts index 85511bfb5..1fc8babed 100644 --- a/src/commands/MixEffects/Transition/TransitionDVECommand.ts +++ b/src/commands/MixEffects/Transition/TransitionDVECommand.ts @@ -1,7 +1,6 @@ import { WritableCommand, DeserializedCommand } from '../../CommandBase' import { AtemState } from '../../../state' import { DVETransitionSettings } from '../../../state/video' -import { Util, Enums } from '../../..' export class TransitionDVECommand extends WritableCommand { public static MaskFlags = { @@ -65,18 +64,18 @@ export class TransitionDVEUpdateCommand extends DeserializedCommand(rawCommand[3], Enums.DVEEffect), + rate: rawCommand[1], + logoRate: rawCommand[2], + style: rawCommand.readUInt8(3), fillSource: rawCommand[4] << 8 | (rawCommand[5] & 0xff), keySource: rawCommand[6] << 8 | (rawCommand[7] & 0xff), enableKey: rawCommand[8] === 1, preMultiplied: rawCommand[9] === 1, - clip: Util.parseNumberBetween(rawCommand.readUInt16BE(10), 0, 1000), - gain: Util.parseNumberBetween(rawCommand.readUInt16BE(12), 0, 1000), + clip: rawCommand.readUInt16BE(10), + gain: rawCommand.readUInt16BE(12), invertKey: rawCommand[14] === 1, reverse: rawCommand[15] === 1, flipFlop: rawCommand[16] === 1 diff --git a/src/commands/MixEffects/Transition/TransitionDipCommand.ts b/src/commands/MixEffects/Transition/TransitionDipCommand.ts index c2bb17f6d..7173fa220 100644 --- a/src/commands/MixEffects/Transition/TransitionDipCommand.ts +++ b/src/commands/MixEffects/Transition/TransitionDipCommand.ts @@ -1,7 +1,6 @@ import { WritableCommand, DeserializedCommand } from '../../CommandBase' import { AtemState } from '../../../state' import { DipTransitionSettings } from '../../../state/video' -import { Util } from '../../..' export class TransitionDipCommand extends WritableCommand { public static MaskFlags = { @@ -40,9 +39,9 @@ export class TransitionDipUpdateCommand extends DeserializedCommand { public static readonly rawName = 'CTMx' @@ -34,9 +33,9 @@ export class TransitionMixUpdateCommand extends DeserializedCommand { public static MaskFlags = { @@ -43,12 +42,12 @@ export class TransitionPropertiesUpdateCommand extends DeserializedCommand(rawCommand[1], Enums.TransitionStyle),// rawCommand[1], - selection: rawCommand[2], - nextStyle: Util.parseEnum(rawCommand[3], Enums.TransitionStyle), - nextSelection: rawCommand[4] + style: rawCommand.readUInt8(1), + selection: rawCommand.readUInt8(2), + nextStyle: rawCommand.readUInt8(3), + nextSelection: rawCommand.readUInt8(4) } return new TransitionPropertiesUpdateCommand(mixEffect, properties) diff --git a/src/commands/MixEffects/Transition/TransitionStingerCommand.ts b/src/commands/MixEffects/Transition/TransitionStingerCommand.ts index 51515c41e..2dd81c6e1 100644 --- a/src/commands/MixEffects/Transition/TransitionStingerCommand.ts +++ b/src/commands/MixEffects/Transition/TransitionStingerCommand.ts @@ -1,7 +1,6 @@ import { WritableCommand, DeserializedCommand } from '../../CommandBase' import { AtemState } from '../../../state' import { StingerTransitionSettings } from '../../../state/video' -import { Util } from '../../..' export class TransitionStingerCommand extends WritableCommand { public static MaskFlags = { @@ -59,13 +58,13 @@ export class TransitionStingerUpdateCommand extends DeserializedCommand { public static MaskFlags = { @@ -61,16 +60,16 @@ export class TransitionWipeUpdateCommand extends DeserializedCommand(rawCommand[2], Enums.Pattern), - borderWidth: Util.parseNumberBetween(rawCommand.readUInt16BE(4), 0, 10000), + rate: rawCommand[1], + pattern: rawCommand.readUInt8(2), + borderWidth: rawCommand.readUInt16BE(4), borderInput: rawCommand.readUInt16BE(6), - symmetry: Util.parseNumberBetween(rawCommand.readUInt16BE(8), 0, 10000), - borderSoftness: Util.parseNumberBetween(rawCommand.readUInt16BE(10), 0, 10000), - xPosition: Util.parseNumberBetween(rawCommand.readUInt16BE(12), 0, 10000), - yPosition: Util.parseNumberBetween(rawCommand.readUInt16BE(14), 0, 10000), + symmetry: rawCommand.readUInt16BE(8), + borderSoftness: rawCommand.readUInt16BE(10), + xPosition: rawCommand.readUInt16BE(12), + yPosition: rawCommand.readUInt16BE(14), reverseDirection: rawCommand[16] === 1, flipFlop: rawCommand[17] === 1 } diff --git a/src/commands/SuperSource/SuperSourceBoxParametersCommand.ts b/src/commands/SuperSource/SuperSourceBoxParametersCommand.ts index 52cb6994c..50545d6e3 100644 --- a/src/commands/SuperSource/SuperSourceBoxParametersCommand.ts +++ b/src/commands/SuperSource/SuperSourceBoxParametersCommand.ts @@ -1,7 +1,6 @@ import { WritableCommand, DeserializedCommand } from '../CommandBase' import { AtemState } from '../../state' import { SuperSourceBox } from '../../state/video' -import { Util } from '../..' import { ProtocolVersion } from '../../enums' export class SuperSourceBoxParametersCommand extends WritableCommand { @@ -81,14 +80,14 @@ export class SuperSourceBoxParametersUpdateCommand extends DeserializedCommand 0 ? 2 : 1] === 1, source: rawCommand.readUInt16BE(i + 2), - x: Util.parseNumberBetween(rawCommand.readInt16BE(i + 4), -4800, 4800), - y: Util.parseNumberBetween(rawCommand.readInt16BE(i + 6), -3400, 3400), - size: Util.parseNumberBetween(rawCommand.readUInt16BE(i + 8), 70, 1000), + x: rawCommand.readInt16BE(i + 4), + y: rawCommand.readInt16BE(i + 6), + size: rawCommand.readUInt16BE(i + 8), cropped: rawCommand[i + 10] === 1, - cropTop: Util.parseNumberBetween(rawCommand.readUInt16BE(i + 12), 0, 18000), - cropBottom: Util.parseNumberBetween(rawCommand.readUInt16BE(i + 14), 0, 18000), - cropLeft: Util.parseNumberBetween(rawCommand.readUInt16BE(i + 16), 0, 32000), - cropRight: Util.parseNumberBetween(rawCommand.readUInt16BE(i + 18), 0, 32000) + cropTop: rawCommand.readUInt16BE(i + 12), + cropBottom: rawCommand.readUInt16BE(i + 14), + cropLeft: rawCommand.readUInt16BE(i + 16), + cropRight: rawCommand.readUInt16BE(i + 18) } return new SuperSourceBoxParametersUpdateCommand(ssrcId, boxId, properties) diff --git a/src/commands/SuperSource/SuperSourcePropertiesCommand.ts b/src/commands/SuperSource/SuperSourcePropertiesCommand.ts index 26e80976d..a71b5037b 100644 --- a/src/commands/SuperSource/SuperSourcePropertiesCommand.ts +++ b/src/commands/SuperSource/SuperSourcePropertiesCommand.ts @@ -1,7 +1,6 @@ import { WritableCommand, DeserializedCommand } from '../CommandBase' import { AtemState } from '../../state' import { SuperSourceProperties, SuperSourceBorder } from '../../state/video' -import { Util, Enums } from '../..' import { ProtocolVersion } from '../../enums' export class SuperSourcePropertiesCommand extends WritableCommand { @@ -164,27 +163,27 @@ export class SuperSourcePropertiesUpdateCommand extends DeserializedCommand<{ pr properties: { artFillSource: rawCommand.readUInt16BE(0), artCutSource: rawCommand.readUInt16BE(2), - artOption: Util.parseEnum(rawCommand.readUInt8(4), Enums.SuperSourceArtOption), + artOption: rawCommand.readUInt8(4), artPreMultiplied: rawCommand[5] === 1, - artClip: Util.parseNumberBetween(rawCommand.readUInt16BE(6), 0, 1000), - artGain: Util.parseNumberBetween(rawCommand.readUInt16BE(8), 0, 1000), + artClip: rawCommand.readUInt16BE(6), + artGain: rawCommand.readUInt16BE(8), artInvertKey: rawCommand[10] === 1 }, border: { borderEnabled: rawCommand[11] === 1, - borderBevel: Util.parseEnum(rawCommand.readUInt8(12), Enums.BorderBevel), - borderOuterWidth: Util.parseNumberBetween(rawCommand.readUInt16BE(14), 0, 1600), - borderInnerWidth: Util.parseNumberBetween(rawCommand.readUInt16BE(16), 0, 1600), - borderOuterSoftness: Util.parseNumberBetween(rawCommand.readUInt8(18), 0, 100), - borderInnerSoftness: Util.parseNumberBetween(rawCommand.readUInt8(19), 0, 100), - borderBevelSoftness: Util.parseNumberBetween(rawCommand.readUInt8(20), 0, 100), - borderBevelPosition: Util.parseNumberBetween(rawCommand.readUInt8(21), 0, 100), - borderHue: Util.parseNumberBetween(rawCommand.readUInt16BE(22), 0, 3599), - borderSaturation: Util.parseNumberBetween(rawCommand.readUInt16BE(24), 0, 1000), - borderLuma: Util.parseNumberBetween(rawCommand.readUInt16BE(26), 0, 1000), - borderLightSourceDirection: Util.parseNumberBetween(rawCommand.readUInt16BE(28), 0, 3599), - borderLightSourceAltitude: Util.parseNumberBetween(rawCommand.readUInt8(30), 0, 100) + borderBevel: rawCommand.readUInt8(12), + borderOuterWidth: rawCommand.readUInt16BE(14), + borderInnerWidth: rawCommand.readUInt16BE(16), + borderOuterSoftness: rawCommand.readUInt8(18), + borderInnerSoftness: rawCommand.readUInt8(19), + borderBevelSoftness: rawCommand.readUInt8(20), + borderBevelPosition: rawCommand.readUInt8(21), + borderHue: rawCommand.readUInt16BE(22), + borderSaturation: rawCommand.readUInt16BE(24), + borderLuma: rawCommand.readUInt16BE(26), + borderLightSourceDirection: rawCommand.readUInt16BE(28), + borderLightSourceAltitude: rawCommand.readUInt8(30) } } @@ -219,10 +218,10 @@ export class SuperSourcePropertiesUpdateV8Command extends DeserializedCommand(rawCommand.readUInt8(6), Enums.SuperSourceArtOption), + artOption: rawCommand.readUInt8(6), artPreMultiplied: rawCommand[7] === 1, - artClip: Util.parseNumberBetween(rawCommand.readUInt16BE(8), 0, 1000), - artGain: Util.parseNumberBetween(rawCommand.readUInt16BE(10), 0, 1000), + artClip: rawCommand.readUInt16BE(8), + artGain: rawCommand.readUInt16BE(10), artInvertKey: rawCommand[12] === 1 } @@ -254,18 +253,18 @@ export class SuperSourceBorderUpdateCommand extends DeserializedCommand(rawCommand.readUInt8(2), Enums.BorderBevel), - borderOuterWidth: Util.parseNumberBetween(rawCommand.readUInt16BE(4), 0, 1600), - borderInnerWidth: Util.parseNumberBetween(rawCommand.readUInt16BE(6), 0, 1600), - borderOuterSoftness: Util.parseNumberBetween(rawCommand.readUInt8(8), 0, 100), - borderInnerSoftness: Util.parseNumberBetween(rawCommand.readUInt8(9), 0, 100), - borderBevelSoftness: Util.parseNumberBetween(rawCommand.readUInt8(10), 0, 100), - borderBevelPosition: Util.parseNumberBetween(rawCommand.readUInt8(11), 0, 100), - borderHue: Util.parseNumberBetween(rawCommand.readUInt16BE(12), 0, 3599), - borderSaturation: Util.parseNumberBetween(rawCommand.readUInt16BE(14), 0, 1000), - borderLuma: Util.parseNumberBetween(rawCommand.readUInt16BE(16), 0, 1000), - borderLightSourceDirection: Util.parseNumberBetween(rawCommand.readUInt16BE(18), 0, 3599), - borderLightSourceAltitude: Util.parseNumberBetween(rawCommand.readUInt8(20), 0, 100) + borderBevel: rawCommand.readUInt8(2), + borderOuterWidth: rawCommand.readUInt16BE(4), + borderInnerWidth: rawCommand.readUInt16BE(6), + borderOuterSoftness: rawCommand.readUInt8(8), + borderInnerSoftness: rawCommand.readUInt8(9), + borderBevelSoftness: rawCommand.readUInt8(10), + borderBevelPosition: rawCommand.readUInt8(11), + borderHue: rawCommand.readUInt16BE(12), + borderSaturation: rawCommand.readUInt16BE(14), + borderLuma: rawCommand.readUInt16BE(16), + borderLightSourceDirection: rawCommand.readUInt16BE(18), + borderLightSourceAltitude: rawCommand.readUInt8(20) } return new SuperSourceBorderUpdateCommand(ssrcId, properties) diff --git a/src/lib/atemUtil.ts b/src/lib/atemUtil.ts index f429fdad2..232276151 100644 --- a/src/lib/atemUtil.ts +++ b/src/lib/atemUtil.ts @@ -13,22 +13,6 @@ export namespace Util { return slice.toString('ascii', 0, nullIndex < 0 ? slice.length : nullIndex) } - export function parseNumberBetween (num: number, min: number, max: number): number { - if (num > max) { - throw Error(`Number too big: ${num} > ${max}`) - } else if (num < min) { - throw Error(`Number too small: ${num} < ${min}`) - } - return num - } - - export function parseEnum (value: G, type: any): G { - if (!type[value]) { - throw Error(`Value ${value} is not a valid option in enum`) - } - return value - } - export const COMMAND_CONNECT_HELLO = Buffer.from([ 0x10, 0x14, 0x53, 0xAB, 0x00, 0x00, 0x00, 0x00, From 062e9775ed67982bbd02b530aea180fe6c20ffd9 Mon Sep 17 00:00:00 2001 From: Julian Waller Date: Fri, 6 Dec 2019 20:14:08 +0000 Subject: [PATCH 40/68] feat: attempt to handle out of range features safely --- src/__tests__/tally.spec.ts | 11 ++++++-- src/__tests__/util.ts | 25 +++++++++++++++++++ src/commands/DeviceProfile/topologyCommand.ts | 9 +++++-- .../DownstreamKeyPropertiesCommand.ts | 4 +++ .../DownstreamKeySourcesCommand.ts | 4 +++ .../DownstreamKeyStateCommand.ts | 8 ++++++ .../Media/MediaPlayerSourceCommand.ts | 4 +++ .../Media/MediaPlayerStatusCommand.ts | 4 +++ .../Media/MediaPoolClipDescription.ts | 12 +++++---- .../Media/MediaPoolFrameDescription.ts | 11 +++++--- .../FadeToBlack/FadeToBlackRateCommand.ts | 4 +++ .../FadeToBlack/FadeToBlackStateCommand.ts | 4 +++ .../Key/MixEffectKeyChromaCommand.ts | 4 +++ .../MixEffects/Key/MixEffectKeyDVECommand.ts | 4 +++ .../Key/MixEffectKeyFlyKeyframeGetCommand.ts | 4 +++ .../MixEffectKeyFlyPropertiesGetCommand.ts | 4 +++ .../MixEffects/Key/MixEffectKeyLumaCommand.ts | 4 +++ .../Key/MixEffectKeyOnAirCommand.ts | 4 +++ .../Key/MixEffectKeyPatternCommand.ts | 4 +++ .../Key/MixEffectKeyPropertiesGetCommand.ts | 13 +++++++--- .../MixEffects/PreviewInputCommand.ts | 4 +++ .../MixEffects/ProgramInputCommand.ts | 4 +++ .../Transition/TransitionDVECommand.ts | 4 +++ .../Transition/TransitionDipCommand.ts | 4 +++ .../Transition/TransitionMixCommand.ts | 4 +++ .../Transition/TransitionPositionCommand.ts | 4 +++ .../Transition/TransitionPreviewCommand.ts | 4 +++ .../Transition/TransitionPropertiesCommand.ts | 4 +++ .../Transition/TransitionStingerCommand.ts | 4 +++ .../Transition/TransitionWipeCommand.ts | 4 +++ .../Settings/MultiViewerSourceCommand.ts | 4 +++ .../SuperSourceBoxParametersCommand.ts | 4 +++ .../SuperSourcePropertiesCommand.ts | 12 +++++++++ src/commands/__tests__/index.spec.ts | 8 +++++- src/commands/__tests__/util.ts | 4 +-- src/commands/__tests__/v8.0.spec.ts | 8 +++++- src/lib/__tests__/atemSocket.spec.ts | 4 +-- src/lib/atemSocket.ts | 2 +- src/state/info.ts | 5 +++- 39 files changed, 208 insertions(+), 24 deletions(-) diff --git a/src/__tests__/tally.spec.ts b/src/__tests__/tally.spec.ts index 5ff070097..64b5beb86 100644 --- a/src/__tests__/tally.spec.ts +++ b/src/__tests__/tally.spec.ts @@ -3,7 +3,7 @@ import { listVisibleInputs } from '../lib/tally' import { readFileSync } from 'fs' import { resolve } from 'path' -import { parseAtemState } from './util' +import { parseAtemState, createEmptyState } from './util' function readJson (fileName: string) { const filePath = resolve(__dirname, fileName) @@ -12,7 +12,14 @@ function readJson (fileName: string) { } function loadRawState (file: string) { - return parseAtemState(readJson(`./tally/${file}-state.json`)) + const loadedState = parseAtemState(readJson(`./tally/${file}-state.json`)) + + if (!loadedState.info.capabilities) { + const emptyState = createEmptyState() + loadedState.info.capabilities = emptyState.info.capabilities + } + + return loadedState } function loadTally (file: string) { const rawTally = readJson(`./tally/${file}-tally.json`) as Commands.TallyBySourceCommand['properties'] diff --git a/src/__tests__/util.ts b/src/__tests__/util.ts index 3addca7fe..762b256a5 100644 --- a/src/__tests__/util.ts +++ b/src/__tests__/util.ts @@ -27,3 +27,28 @@ export function parseAtemState (rawState: any): AtemState { return state } + +export function createEmptyState () { + const state = new AtemState() + + // These should be the maximum supported by any device. + // But they can also be whatever is needed to allow the tests to run without error + state.info.capabilities = { + mixEffects: 4, + sources: 40, + colorGenerators: 2, + auxilliaries: 6, + talkbackOutputs: 8, + mediaPlayers: 4, + serialPorts: 1, + maxHyperdecks: 4, + DVEs: 1, + stingers: 1, + superSources: 2, + talkbackOverSDI: 0, + multiViewers: 255, + downstreamKeyers: 4 + } + + return state +} \ No newline at end of file diff --git a/src/commands/DeviceProfile/topologyCommand.ts b/src/commands/DeviceProfile/topologyCommand.ts index 7c39c2675..57d35cdbc 100644 --- a/src/commands/DeviceProfile/topologyCommand.ts +++ b/src/commands/DeviceProfile/topologyCommand.ts @@ -7,7 +7,7 @@ export class TopologyCommand extends DeserializedCommand { public static deserialize (rawCommand: Buffer) { const properties = { - MEs: rawCommand[0], + mixEffects: rawCommand[0], sources: rawCommand[1], colorGenerators: rawCommand[2], auxilliaries: rawCommand[3], @@ -18,7 +18,12 @@ export class TopologyCommand extends DeserializedCommand { DVEs: rawCommand[8], stingers: rawCommand[9], superSources: rawCommand[10], - talkbackOverSDI: rawCommand[13] + talkbackOverSDI: rawCommand[13], + + // TODO - define the below properly + multiViewers: 2, + downstreamKeyers: 2, + upstreamKeyers: 2 } return new TopologyCommand(properties) diff --git a/src/commands/DownstreamKey/DownstreamKeyPropertiesCommand.ts b/src/commands/DownstreamKey/DownstreamKeyPropertiesCommand.ts index a17e2a4ba..d43969cd8 100644 --- a/src/commands/DownstreamKey/DownstreamKeyPropertiesCommand.ts +++ b/src/commands/DownstreamKey/DownstreamKeyPropertiesCommand.ts @@ -37,6 +37,10 @@ export class DownstreamKeyPropertiesCommand extends DeserializedCommand= state.info.capabilities.downstreamKeyers) { + throw new Error(`DownstreamKeyer ${this.downstreamKeyerId} is not valid`) + } + state.video.getDownstreamKeyer(this.downstreamKeyerId).properties = this.properties return `video.downstreamKeyers.${this.downstreamKeyerId}` } diff --git a/src/commands/DownstreamKey/DownstreamKeySourcesCommand.ts b/src/commands/DownstreamKey/DownstreamKeySourcesCommand.ts index e13b46eee..03f417dfe 100644 --- a/src/commands/DownstreamKey/DownstreamKeySourcesCommand.ts +++ b/src/commands/DownstreamKey/DownstreamKeySourcesCommand.ts @@ -24,6 +24,10 @@ export class DownstreamKeySourcesCommand extends DeserializedCommand= state.info.capabilities.downstreamKeyers) { + throw new Error(`DownstreamKeyer ${this.downstreamKeyerId} is not valid`) + } + state.video.getDownstreamKeyer(this.downstreamKeyerId).sources = this.properties return `video.downstreamKeyers.${this.downstreamKeyerId}` } diff --git a/src/commands/DownstreamKey/DownstreamKeyStateCommand.ts b/src/commands/DownstreamKey/DownstreamKeyStateCommand.ts index dd69bce13..580365b0c 100644 --- a/src/commands/DownstreamKey/DownstreamKeyStateCommand.ts +++ b/src/commands/DownstreamKey/DownstreamKeyStateCommand.ts @@ -27,6 +27,10 @@ export class DownstreamKeyStateCommand extends DeserializedCommand= state.info.capabilities.downstreamKeyers) { + throw new Error(`DownstreamKeyer ${this.downstreamKeyerId} is not valid`) + } + state.video.downstreamKeyers[this.downstreamKeyerId] = { ...state.video.getDownstreamKeyer(this.downstreamKeyerId), ...this.properties @@ -61,6 +65,10 @@ export class DownstreamKeyStateV8Command extends DeserializedCommand= state.info.capabilities.downstreamKeyers) { + throw new Error(`DownstreamKeyer ${this.downstreamKeyerId} is not valid`) + } + state.video.downstreamKeyers[this.downstreamKeyerId] = { ...state.video.getDownstreamKeyer(this.downstreamKeyerId), ...this.properties diff --git a/src/commands/Media/MediaPlayerSourceCommand.ts b/src/commands/Media/MediaPlayerSourceCommand.ts index 7c53ae1c2..5e084d963 100644 --- a/src/commands/Media/MediaPlayerSourceCommand.ts +++ b/src/commands/Media/MediaPlayerSourceCommand.ts @@ -53,6 +53,10 @@ export class MediaPlayerSourceUpdateCommand extends DeserializedCommand= state.info.capabilities.mediaPlayers) { + throw new Error(`MediaPlayer ${this.mediaPlayerId} is not valid`) + } + state.media.players[this.mediaPlayerId] = { ...state.media.getMediaPlayer(this.mediaPlayerId), ...this.properties diff --git a/src/commands/Media/MediaPlayerStatusCommand.ts b/src/commands/Media/MediaPlayerStatusCommand.ts index b4e073537..423f72750 100644 --- a/src/commands/Media/MediaPlayerStatusCommand.ts +++ b/src/commands/Media/MediaPlayerStatusCommand.ts @@ -55,6 +55,10 @@ export class MediaPlayerStatusUpdateCommand extends DeserializedCommand= state.info.capabilities.mediaPlayers) { + throw new Error(`MediaPlayer ${this.mediaPlayerId} is not valid`) + } + state.media.players[this.mediaPlayerId] = { ...state.media.getMediaPlayer(this.mediaPlayerId), ...this.properties diff --git a/src/commands/Media/MediaPoolClipDescription.ts b/src/commands/Media/MediaPoolClipDescription.ts index 69a48a57d..baad63d9b 100644 --- a/src/commands/Media/MediaPoolClipDescription.ts +++ b/src/commands/Media/MediaPoolClipDescription.ts @@ -6,12 +6,12 @@ import { Util } from '../../lib/atemUtil' export class MediaPoolClipDescriptionCommand extends DeserializedCommand> { public static readonly rawName = 'MPCS' - public readonly mediaPool: number + public readonly clipId: number constructor (mediaPool: number, properties: Omit) { super(properties) - this.mediaPool = mediaPool + this.clipId = mediaPool } public static deserialize (rawCommand: Buffer) { @@ -26,10 +26,12 @@ export class MediaPoolClipDescriptionCommand extends DeserializedCommand= state.info.capabilities.mixEffects) { + throw new Error(`MixEffect ${this.mixEffect} is not valid`) + } + const mixEffect = state.video.getMe(this.mixEffect) mixEffect.fadeToBlack = { isFullyBlack: false, diff --git a/src/commands/MixEffects/FadeToBlack/FadeToBlackStateCommand.ts b/src/commands/MixEffects/FadeToBlack/FadeToBlackStateCommand.ts index 2cf30d2fe..fd31bf184 100644 --- a/src/commands/MixEffects/FadeToBlack/FadeToBlackStateCommand.ts +++ b/src/commands/MixEffects/FadeToBlack/FadeToBlackStateCommand.ts @@ -30,6 +30,10 @@ export class FadeToBlackStateCommand extends DeserializedCommand= state.info.capabilities.mixEffects) { + throw new Error(`MixEffect ${this.mixEffect} is not valid`) + } + const mixEffect = state.video.getMe(this.mixEffect) mixEffect.fadeToBlack = { rate: 0, diff --git a/src/commands/MixEffects/Key/MixEffectKeyChromaCommand.ts b/src/commands/MixEffects/Key/MixEffectKeyChromaCommand.ts index 6469cf9ea..138972b15 100644 --- a/src/commands/MixEffects/Key/MixEffectKeyChromaCommand.ts +++ b/src/commands/MixEffects/Key/MixEffectKeyChromaCommand.ts @@ -66,6 +66,10 @@ export class MixEffectKeyChromaUpdateCommand extends DeserializedCommand= state.info.capabilities.mixEffects || this.upstreamKeyerId >= state.info.capabilities.upstreamKeyers) { + throw new Error(`UpstreamKeyer ${this.mixEffect}-${this.upstreamKeyerId} is not valid`) + } + const mixEffect = state.video.getMe(this.mixEffect) const upstreamKeyer = mixEffect.getUpstreamKeyer(this.upstreamKeyerId) upstreamKeyer.chromaSettings = { diff --git a/src/commands/MixEffects/Key/MixEffectKeyDVECommand.ts b/src/commands/MixEffects/Key/MixEffectKeyDVECommand.ts index be61c7e5a..13559d24c 100644 --- a/src/commands/MixEffects/Key/MixEffectKeyDVECommand.ts +++ b/src/commands/MixEffects/Key/MixEffectKeyDVECommand.ts @@ -141,6 +141,10 @@ export class MixEffectKeyDVEUpdateCommand extends DeserializedCommand= state.info.capabilities.mixEffects || this.upstreamKeyerId >= state.info.capabilities.upstreamKeyers) { + throw new Error(`UpstreamKeyer ${this.mixEffect}-${this.upstreamKeyerId} is not valid`) + } + const mixEffect = state.video.getMe(this.mixEffect) const upstreamKeyer = mixEffect.getUpstreamKeyer(this.upstreamKeyerId) upstreamKeyer.dveSettings = { diff --git a/src/commands/MixEffects/Key/MixEffectKeyFlyKeyframeGetCommand.ts b/src/commands/MixEffects/Key/MixEffectKeyFlyKeyframeGetCommand.ts index 2abab0a10..fd06232c3 100644 --- a/src/commands/MixEffects/Key/MixEffectKeyFlyKeyframeGetCommand.ts +++ b/src/commands/MixEffects/Key/MixEffectKeyFlyKeyframeGetCommand.ts @@ -57,6 +57,10 @@ export class MixEffectKeyFlyKeyframeGetCommand extends DeserializedCommand= state.info.capabilities.mixEffects || this.upstreamKeyerId >= state.info.capabilities.upstreamKeyers) { + throw new Error(`UpstreamKeyer ${this.mixEffect}-${this.upstreamKeyerId} is not valid`) + } + const mixEffect = state.video.getMe(this.mixEffect) const upstreamKeyer = mixEffect.getUpstreamKeyer(this.upstreamKeyerId) upstreamKeyer.flyKeyframes[this.properties.keyFrameId] = { diff --git a/src/commands/MixEffects/Key/MixEffectKeyFlyPropertiesGetCommand.ts b/src/commands/MixEffects/Key/MixEffectKeyFlyPropertiesGetCommand.ts index 9ea9607fb..3f7a60df4 100644 --- a/src/commands/MixEffects/Key/MixEffectKeyFlyPropertiesGetCommand.ts +++ b/src/commands/MixEffects/Key/MixEffectKeyFlyPropertiesGetCommand.ts @@ -28,6 +28,10 @@ export class MixEffectKeyFlyPropertiesGetCommand extends DeserializedCommand= state.info.capabilities.mixEffects || this.upstreamKeyerId >= state.info.capabilities.upstreamKeyers) { + throw new Error(`UpstreamKeyer ${this.mixEffect}-${this.upstreamKeyerId} is not valid`) + } + const mixEffect = state.video.getMe(this.mixEffect) const upstreamKeyer = mixEffect.getUpstreamKeyer(this.upstreamKeyerId) upstreamKeyer.flyProperties = { diff --git a/src/commands/MixEffects/Key/MixEffectKeyLumaCommand.ts b/src/commands/MixEffects/Key/MixEffectKeyLumaCommand.ts index 09b374a76..f91478126 100644 --- a/src/commands/MixEffects/Key/MixEffectKeyLumaCommand.ts +++ b/src/commands/MixEffects/Key/MixEffectKeyLumaCommand.ts @@ -63,6 +63,10 @@ export class MixEffectKeyLumaUpdateCommand extends DeserializedCommand= state.info.capabilities.mixEffects || this.upstreamKeyerId >= state.info.capabilities.upstreamKeyers) { + throw new Error(`UpstreamKeyer ${this.mixEffect}-${this.upstreamKeyerId} is not valid`) + } + const mixEffect = state.video.getMe(this.mixEffect) const upstreamKeyer = mixEffect.getUpstreamKeyer(this.upstreamKeyerId) upstreamKeyer.lumaSettings = { diff --git a/src/commands/MixEffects/Key/MixEffectKeyOnAirCommand.ts b/src/commands/MixEffects/Key/MixEffectKeyOnAirCommand.ts index daabfc043..519a4ab0c 100644 --- a/src/commands/MixEffects/Key/MixEffectKeyOnAirCommand.ts +++ b/src/commands/MixEffects/Key/MixEffectKeyOnAirCommand.ts @@ -46,6 +46,10 @@ export class MixEffectKeyOnAirUpdateCommand extends DeserializedCommand<{onAir: } public applyToState (state: AtemState) { + if (!state.info.capabilities || this.mixEffect >= state.info.capabilities.mixEffects || this.upstreamKeyerId >= state.info.capabilities.upstreamKeyers) { + throw new Error(`UpstreamKeyer ${this.mixEffect}-${this.upstreamKeyerId} is not valid`) + } + const mixEffect = state.video.getMe(this.mixEffect) const upstreamKeyer = mixEffect.getUpstreamKeyer(this.upstreamKeyerId) upstreamKeyer.onAir = this.properties.onAir diff --git a/src/commands/MixEffects/Key/MixEffectKeyPatternCommand.ts b/src/commands/MixEffects/Key/MixEffectKeyPatternCommand.ts index 5d13cae1d..67cadfc5e 100644 --- a/src/commands/MixEffects/Key/MixEffectKeyPatternCommand.ts +++ b/src/commands/MixEffects/Key/MixEffectKeyPatternCommand.ts @@ -73,6 +73,10 @@ export class MixEffectKeyUpdateCommand extends DeserializedCommand= state.info.capabilities.mixEffects || this.upstreamKeyerId >= state.info.capabilities.upstreamKeyers) { + throw new Error(`UpstreamKeyer ${this.mixEffect}-${this.upstreamKeyerId} is not valid`) + } + const mixEffect = state.video.getMe(this.mixEffect) const upstreamKeyer = mixEffect.getUpstreamKeyer(this.upstreamKeyerId) upstreamKeyer.patternSettings = { diff --git a/src/commands/MixEffects/Key/MixEffectKeyPropertiesGetCommand.ts b/src/commands/MixEffects/Key/MixEffectKeyPropertiesGetCommand.ts index 05821bd0a..ec520d30b 100644 --- a/src/commands/MixEffects/Key/MixEffectKeyPropertiesGetCommand.ts +++ b/src/commands/MixEffects/Key/MixEffectKeyPropertiesGetCommand.ts @@ -6,17 +6,20 @@ export class MixEffectKeyPropertiesGetCommand extends DeserializedCommand= state.info.capabilities.mixEffects || this.upstreamKeyerId >= state.info.capabilities.upstreamKeyers) { + throw new Error(`UpstreamKeyer ${this.mixEffect}-${this.upstreamKeyerId} is not valid`) + } + const mixEffect = state.video.getMe(this.mixEffect) mixEffect.upstreamKeyers[this.properties.upstreamKeyerId] = { ...mixEffect.getUpstreamKeyer(this.properties.upstreamKeyerId), diff --git a/src/commands/MixEffects/PreviewInputCommand.ts b/src/commands/MixEffects/PreviewInputCommand.ts index a12b2936a..48a239ff4 100644 --- a/src/commands/MixEffects/PreviewInputCommand.ts +++ b/src/commands/MixEffects/PreviewInputCommand.ts @@ -45,6 +45,10 @@ export class PreviewInputUpdateCommand extends DeserializedCommand } public applyToState (state: AtemState) { + if (!state.info.capabilities || this.mixEffect >= state.info.capabilities.mixEffects) { + throw new Error(`MixEffect ${this.mixEffect} is not valid`) + } + const mixEffect = state.video.getMe(this.mixEffect) mixEffect.previewInput = this.properties.source return `video.ME.${this.mixEffect}.previewInput` diff --git a/src/commands/MixEffects/ProgramInputCommand.ts b/src/commands/MixEffects/ProgramInputCommand.ts index bc905e128..5f66203a2 100644 --- a/src/commands/MixEffects/ProgramInputCommand.ts +++ b/src/commands/MixEffects/ProgramInputCommand.ts @@ -42,6 +42,10 @@ export class ProgramInputUpdateCommand extends DeserializedCommand } public applyToState (state: AtemState) { + if (!state.info.capabilities || this.mixEffect >= state.info.capabilities.mixEffects) { + throw new Error(`MixEffect ${this.mixEffect} is not valid`) + } + const mixEffect = state.video.getMe(this.mixEffect) mixEffect.programInput = this.properties.source return `video.ME.${this.mixEffect}.programInput` diff --git a/src/commands/MixEffects/Transition/TransitionDVECommand.ts b/src/commands/MixEffects/Transition/TransitionDVECommand.ts index 1fc8babed..e24385d87 100644 --- a/src/commands/MixEffects/Transition/TransitionDVECommand.ts +++ b/src/commands/MixEffects/Transition/TransitionDVECommand.ts @@ -85,6 +85,10 @@ export class TransitionDVEUpdateCommand extends DeserializedCommand= state.info.capabilities.mixEffects) { + throw new Error(`MixEffect ${this.mixEffect} is not valid`) + } + const mixEffect = state.video.getMe(this.mixEffect) mixEffect.transitionSettings.DVE = { ...this.properties diff --git a/src/commands/MixEffects/Transition/TransitionDipCommand.ts b/src/commands/MixEffects/Transition/TransitionDipCommand.ts index 7173fa220..fb8db3b3a 100644 --- a/src/commands/MixEffects/Transition/TransitionDipCommand.ts +++ b/src/commands/MixEffects/Transition/TransitionDipCommand.ts @@ -49,6 +49,10 @@ export class TransitionDipUpdateCommand extends DeserializedCommand= state.info.capabilities.mixEffects) { + throw new Error(`MixEffect ${this.mixEffect} is not valid`) + } + const mixEffect = state.video.getMe(this.mixEffect) mixEffect.transitionSettings.dip = { ...this.properties diff --git a/src/commands/MixEffects/Transition/TransitionMixCommand.ts b/src/commands/MixEffects/Transition/TransitionMixCommand.ts index 907869c6f..856db8d19 100644 --- a/src/commands/MixEffects/Transition/TransitionMixCommand.ts +++ b/src/commands/MixEffects/Transition/TransitionMixCommand.ts @@ -42,6 +42,10 @@ export class TransitionMixUpdateCommand extends DeserializedCommand= state.info.capabilities.mixEffects) { + throw new Error(`MixEffect ${this.mixEffect} is not valid`) + } + const mixEffect = state.video.getMe(this.mixEffect) mixEffect.transitionSettings.mix = { ...this.properties diff --git a/src/commands/MixEffects/Transition/TransitionPositionCommand.ts b/src/commands/MixEffects/Transition/TransitionPositionCommand.ts index 2b034d81b..ed0685a9a 100644 --- a/src/commands/MixEffects/Transition/TransitionPositionCommand.ts +++ b/src/commands/MixEffects/Transition/TransitionPositionCommand.ts @@ -52,6 +52,10 @@ export class TransitionPositionUpdateCommand extends DeserializedCommand= state.info.capabilities.mixEffects) { + throw new Error(`MixEffect ${this.mixEffect} is not valid`) + } + const mixEffect = state.video.getMe(this.mixEffect) mixEffect.transitionFramesLeft = this.properties.remainingFrames mixEffect.transitionPosition = this.properties.handlePosition diff --git a/src/commands/MixEffects/Transition/TransitionPreviewCommand.ts b/src/commands/MixEffects/Transition/TransitionPreviewCommand.ts index c6d9764b5..a97dc309b 100644 --- a/src/commands/MixEffects/Transition/TransitionPreviewCommand.ts +++ b/src/commands/MixEffects/Transition/TransitionPreviewCommand.ts @@ -45,6 +45,10 @@ export class PreviewTransitionUpdateCommand extends DeserializedCommand= state.info.capabilities.mixEffects) { + throw new Error(`MixEffect ${this.mixEffect} is not valid`) + } + const mixEffect = state.video.getMe(this.mixEffect) mixEffect.transitionPreview = this.properties.preview return `video.ME.${this.mixEffect}.transitionPreview` diff --git a/src/commands/MixEffects/Transition/TransitionPropertiesCommand.ts b/src/commands/MixEffects/Transition/TransitionPropertiesCommand.ts index 514f045b3..170451044 100644 --- a/src/commands/MixEffects/Transition/TransitionPropertiesCommand.ts +++ b/src/commands/MixEffects/Transition/TransitionPropertiesCommand.ts @@ -54,6 +54,10 @@ export class TransitionPropertiesUpdateCommand extends DeserializedCommand= state.info.capabilities.mixEffects) { + throw new Error(`MixEffect ${this.mixEffect} is not valid`) + } + const mixEffect = state.video.getMe(this.mixEffect) mixEffect.transitionProperties = { ...this.properties diff --git a/src/commands/MixEffects/Transition/TransitionStingerCommand.ts b/src/commands/MixEffects/Transition/TransitionStingerCommand.ts index 2dd81c6e1..d5d39538c 100644 --- a/src/commands/MixEffects/Transition/TransitionStingerCommand.ts +++ b/src/commands/MixEffects/Transition/TransitionStingerCommand.ts @@ -77,6 +77,10 @@ export class TransitionStingerUpdateCommand extends DeserializedCommand= state.info.capabilities.mixEffects) { + throw new Error(`MixEffect ${this.mixEffect} is not valid`) + } + const mixEffect = state.video.getMe(this.mixEffect) mixEffect.transitionSettings.stinger = { ...this.properties diff --git a/src/commands/MixEffects/Transition/TransitionWipeCommand.ts b/src/commands/MixEffects/Transition/TransitionWipeCommand.ts index 0fdb38e6c..7f6f6b285 100644 --- a/src/commands/MixEffects/Transition/TransitionWipeCommand.ts +++ b/src/commands/MixEffects/Transition/TransitionWipeCommand.ts @@ -78,6 +78,10 @@ export class TransitionWipeUpdateCommand extends DeserializedCommand= state.info.capabilities.mixEffects) { + throw new Error(`MixEffect ${this.mixEffect} is not valid`) + } + const mixEffect = state.video.getMe(this.mixEffect) mixEffect.transitionSettings.wipe = { ...this.properties diff --git a/src/commands/Settings/MultiViewerSourceCommand.ts b/src/commands/Settings/MultiViewerSourceCommand.ts index 54c37df67..34fe64592 100644 --- a/src/commands/Settings/MultiViewerSourceCommand.ts +++ b/src/commands/Settings/MultiViewerSourceCommand.ts @@ -44,6 +44,10 @@ export class MultiViewerSourceUpdateCommand extends DeserializedCommand= state.info.capabilities.multiViewers) { + throw new Error(`MultiViewer ${this.multiViewerId} is not valid`) + } + const multiviewer = state.settings.getMultiViewer(this.multiViewerId) multiviewer.windows[this.properties.windowIndex] = { ...multiviewer.windows[this.properties.windowIndex], diff --git a/src/commands/SuperSource/SuperSourceBoxParametersCommand.ts b/src/commands/SuperSource/SuperSourceBoxParametersCommand.ts index 50545d6e3..58e85a561 100644 --- a/src/commands/SuperSource/SuperSourceBoxParametersCommand.ts +++ b/src/commands/SuperSource/SuperSourceBoxParametersCommand.ts @@ -94,6 +94,10 @@ export class SuperSourceBoxParametersUpdateCommand extends DeserializedCommand= state.info.capabilities.superSources) { + throw new Error(`SuperSource ${this.ssrcId} is not valid`) + } + const supersource = state.video.getSuperSource(this.ssrcId) supersource.boxes[this.boxId] = { ...this.properties diff --git a/src/commands/SuperSource/SuperSourcePropertiesCommand.ts b/src/commands/SuperSource/SuperSourcePropertiesCommand.ts index a71b5037b..c88a4b6d1 100644 --- a/src/commands/SuperSource/SuperSourcePropertiesCommand.ts +++ b/src/commands/SuperSource/SuperSourcePropertiesCommand.ts @@ -191,6 +191,10 @@ export class SuperSourcePropertiesUpdateCommand extends DeserializedCommand<{ pr } public applyToState (state: AtemState) { + if (!state.info.capabilities || !state.info.capabilities.superSources) { + throw new Error(`SuperSource 0 is not valid`) + } + const supersource = state.video.getSuperSource(0) supersource.properties = this.properties.properties supersource.border = this.properties.border @@ -229,6 +233,10 @@ export class SuperSourcePropertiesUpdateV8Command extends DeserializedCommand= state.info.capabilities.superSources) { + throw new Error(`SuperSource ${this.ssrcId} is not valid`) + } + const supersource = state.video.getSuperSource(this.ssrcId) supersource.properties = { ...this.properties @@ -271,6 +279,10 @@ export class SuperSourceBorderUpdateCommand extends DeserializedCommand= state.info.capabilities.superSources) { + throw new Error(`SuperSource ${this.ssrcId} is not valid`) + } + const supersource = state.video.getSuperSource(this.ssrcId) supersource.border = this.properties diff --git a/src/commands/__tests__/index.spec.ts b/src/commands/__tests__/index.spec.ts index 0339c7587..0f1ca2d90 100644 --- a/src/commands/__tests__/index.spec.ts +++ b/src/commands/__tests__/index.spec.ts @@ -257,11 +257,17 @@ const commandConverters: CommandTestConverterSet = { 'auxiliaries': (val: any) => ({ val, name: 'auxilliaries' }), 'dVE': (val: any) => ({ val, name: 'DVEs' }), 'hyperDecks': (val: any) => ({ val, name: 'maxHyperdecks' }), - 'mixEffectBlocks': (val: any) => ({ val, name: 'MEs' }), + 'mixEffectBlocks': (val: any) => ({ val, name: 'mixEffects' }), 'serialPort': (val: any) => ({ val, name: 'serialPorts' }), 'videoSources': (val: any) => ({ val, name: 'sources' }), 'superSource': (val: any) => ({ val, name: 'superSources' }), 'talkbackOverSDI': () => ({ val: 0 }) // @todo: should be fixed in atem-connection + }, + customMutate: obj => { + obj.downstreamKeyers = 2 + obj.multiViewers = 2 + obj.upstreamKeyers = 2 + return obj } }, 'FTCD': { diff --git a/src/commands/__tests__/util.ts b/src/commands/__tests__/util.ts index 7186d0565..430f4cc56 100644 --- a/src/commands/__tests__/util.ts +++ b/src/commands/__tests__/util.ts @@ -1,7 +1,7 @@ import { CommandParser } from '../../lib/atemCommandParser' import { ProtocolVersion } from '../../enums' import { IDeserializedCommand, ISerializableCommand } from '../CommandBase' -import { AtemState } from '../../state' +import { createEmptyState } from '../../__tests__/util' export type CommandTestConverterSet = { [key: string]: CommandTestConverter } export interface CommandTestConverter { @@ -72,7 +72,7 @@ export function runTestForCommand (commandParser: CommandParser, commandConverte expect(cmd.properties).toEqual(mutatedCommand) - const state = new AtemState() + const state = createEmptyState() // Ensure state update doesnt error expect(cmd.applyToState(state)).toBeTruthy() }) diff --git a/src/commands/__tests__/v8.0.spec.ts b/src/commands/__tests__/v8.0.spec.ts index 7dbdd0027..9825a54a4 100644 --- a/src/commands/__tests__/v8.0.spec.ts +++ b/src/commands/__tests__/v8.0.spec.ts @@ -28,10 +28,16 @@ const commandConverters: CommandTestConverterSet = { 'auxiliaries': (val: any) => ({ val, name: 'auxilliaries' }), 'dVE': (val: any) => ({ val, name: 'DVEs' }), 'hyperDecks': (val: any) => ({ val, name: 'maxHyperdecks' }), - 'mixEffectBlocks': (val: any) => ({ val, name: 'MEs' }), + 'mixEffectBlocks': (val: any) => ({ val, name: 'mixEffects' }), 'serialPort': (val: any) => ({ val, name: 'serialPorts' }), 'videoSources': (val: any) => ({ val, name: 'sources' }), 'superSource': (val: any) => ({ val, name: 'superSources' }) + }, + customMutate: obj => { + obj.downstreamKeyers = 2 + obj.multiViewers = 2 + obj.upstreamKeyers = 2 + return obj } }, 'SSrc': { diff --git a/src/lib/__tests__/atemSocket.spec.ts b/src/lib/__tests__/atemSocket.spec.ts index 817323e89..8dcb6e90a 100644 --- a/src/lib/__tests__/atemSocket.spec.ts +++ b/src/lib/__tests__/atemSocket.spec.ts @@ -501,7 +501,7 @@ describe('AtemSocket', () => { public static readonly rawName = 'TEST' public deserialize () { - throw new Error('Deserialize failure') + throw new Error('Broken command') } public applyToState (): string[] { throw new Error('Method not implemented.') @@ -533,7 +533,7 @@ describe('AtemSocket', () => { // The second command should have been a success expect(change).toHaveBeenCalledWith(expectedCmd2) - expect(error).toHaveBeenCalledWith(new Error('Deserialize failure')) + expect(error).toHaveBeenCalledWith('Failed to deserialize command: BrokenCommand: Error: Broken command') }) test('receive - thread restart', async () => { diff --git a/src/lib/atemSocket.ts b/src/lib/atemSocket.ts index 38e94aa44..8d374fe21 100644 --- a/src/lib/atemSocket.ts +++ b/src/lib/atemSocket.ts @@ -175,7 +175,7 @@ export class AtemSocket extends EventEmitter { this.emit('commandReceived', cmd) } catch (e) { - this.emit('error', e) + this.emit('error', `Failed to deserialize command: ${cmdConstructor.constructor.name}: ${e}`) } } // TODO - log the unknown command? diff --git a/src/state/info.ts b/src/state/info.ts index cd84d5bef..4ffd2a0bc 100644 --- a/src/state/info.ts +++ b/src/state/info.ts @@ -1,7 +1,7 @@ import { Model, ProtocolVersion } from '../enums' export interface AtemCapabilites { - readonly MEs: number + readonly mixEffects: number readonly sources: number readonly colorGenerators: number readonly auxilliaries: number @@ -13,6 +13,9 @@ export interface AtemCapabilites { readonly stingers: number readonly superSources: number readonly talkbackOverSDI: number + readonly downstreamKeyers: number + readonly multiViewers: number + readonly upstreamKeyers: number } export interface SuperSourceInfo { From c52a3e8ca2ab5c43325d14d94dcd793d45803726 Mon Sep 17 00:00:00 2001 From: Julian Waller Date: Fri, 6 Dec 2019 20:23:04 +0000 Subject: [PATCH 41/68] chore: use Buffer.readUInt8 instead of direct index operator --- src/__tests__/util.ts | 5 ++-- src/commands/AuxSourceCommand.ts | 2 +- src/commands/DataTransfer/LockStateCommand.ts | 2 +- .../DeviceProfile/productIdentifierCommand.ts | 2 +- .../DeviceProfile/superSourceConfigCommand.ts | 4 ++-- src/commands/DeviceProfile/topologyCommand.ts | 24 +++++++++---------- .../DownstreamKeyPropertiesCommand.ts | 2 +- .../DownstreamKeyStateCommand.ts | 22 ++++++++--------- src/commands/Inputs/InputPropertiesCommand.ts | 4 ++-- src/commands/Macro/MacroPropertiesCommand.ts | 2 +- .../Macro/MacroRecordingStatusCommand.ts | 2 +- src/commands/Macro/MacroRunStatusCommand.ts | 6 ++--- .../Media/MediaPlayerSourceCommand.ts | 8 +++---- .../Media/MediaPlayerStatusCommand.ts | 10 ++++---- .../Media/MediaPoolClipDescription.ts | 4 ++-- .../Media/MediaPoolFrameDescription.ts | 6 ++--- .../Key/MixEffectKeyChromaCommand.ts | 6 ++--- .../MixEffects/Key/MixEffectKeyDVECommand.ts | 10 ++++---- .../Key/MixEffectKeyFlyKeyframeGetCommand.ts | 8 +++---- .../MixEffectKeyFlyPropertiesGetCommand.ts | 12 +++++----- .../MixEffects/Key/MixEffectKeyLumaCommand.ts | 8 +++---- .../Key/MixEffectKeyOnAirCommand.ts | 6 ++--- .../Key/MixEffectKeyPatternCommand.ts | 6 ++--- .../Key/MixEffectKeyPropertiesGetCommand.ts | 8 +++---- .../MixEffects/PreviewInputCommand.ts | 2 +- .../MixEffects/ProgramInputCommand.ts | 2 +- .../Transition/TransitionDVECommand.ts | 20 ++++++++-------- .../Transition/TransitionDipCommand.ts | 6 ++--- .../Transition/TransitionMixCommand.ts | 4 ++-- .../Transition/TransitionPositionCommand.ts | 6 ++--- .../Transition/TransitionPreviewCommand.ts | 4 ++-- .../Transition/TransitionPropertiesCommand.ts | 2 +- .../Transition/TransitionStingerCommand.ts | 16 ++++++------- .../Transition/TransitionWipeCommand.ts | 8 +++---- src/commands/PowerStatusCommand.ts | 4 ++-- src/commands/Settings/VideoMode.ts | 2 +- .../SuperSourceBoxParametersCommand.ts | 4 ++-- .../SuperSourcePropertiesCommand.ts | 12 +++++----- 38 files changed, 131 insertions(+), 130 deletions(-) diff --git a/src/__tests__/util.ts b/src/__tests__/util.ts index 762b256a5..119111a46 100644 --- a/src/__tests__/util.ts +++ b/src/__tests__/util.ts @@ -47,8 +47,9 @@ export function createEmptyState () { superSources: 2, talkbackOverSDI: 0, multiViewers: 255, - downstreamKeyers: 4 + downstreamKeyers: 4, + upstreamKeyers: 4 } return state -} \ No newline at end of file +} diff --git a/src/commands/AuxSourceCommand.ts b/src/commands/AuxSourceCommand.ts index 54d704902..e8ce73a9a 100644 --- a/src/commands/AuxSourceCommand.ts +++ b/src/commands/AuxSourceCommand.ts @@ -37,7 +37,7 @@ export class AuxSourceUpdateCommand extends DeserializedCommand } public static deserialize (rawCommand: Buffer): AuxSourceUpdateCommand { - const auxBus = rawCommand[0] + const auxBus = rawCommand.readUInt8(0) const properties = { source: rawCommand.readUInt16BE(2) } diff --git a/src/commands/DataTransfer/LockStateCommand.ts b/src/commands/DataTransfer/LockStateCommand.ts index 6369954ee..5ceaef7c0 100644 --- a/src/commands/DataTransfer/LockStateCommand.ts +++ b/src/commands/DataTransfer/LockStateCommand.ts @@ -26,7 +26,7 @@ export class LockStateUpdateCommand extends DeserializedCommand public static deserialize (rawCommand: Buffer) { const properties = { index: rawCommand.readUInt16BE(0), - locked: rawCommand[2] === 1 + locked: rawCommand.readUInt8(2) === 1 } return new LockStateUpdateCommand(properties) diff --git a/src/commands/DeviceProfile/productIdentifierCommand.ts b/src/commands/DeviceProfile/productIdentifierCommand.ts index ecc2f7c98..5cde9a6e1 100644 --- a/src/commands/DeviceProfile/productIdentifierCommand.ts +++ b/src/commands/DeviceProfile/productIdentifierCommand.ts @@ -10,7 +10,7 @@ export class ProductIdentifierCommand extends DeserializedCommand= ProtocolVersion.V8_0) { - return new SuperSourceConfigCommand(rawCommand[0], { boxCount: rawCommand[2] }) + return new SuperSourceConfigCommand(rawCommand.readUInt8(0), { boxCount: rawCommand.readUInt8(2) }) } else { - return new SuperSourceConfigCommand(0, { boxCount: rawCommand[0] }) + return new SuperSourceConfigCommand(0, { boxCount: rawCommand.readUInt8(0) }) } } diff --git a/src/commands/DeviceProfile/topologyCommand.ts b/src/commands/DeviceProfile/topologyCommand.ts index 57d35cdbc..c1b90200c 100644 --- a/src/commands/DeviceProfile/topologyCommand.ts +++ b/src/commands/DeviceProfile/topologyCommand.ts @@ -7,18 +7,18 @@ export class TopologyCommand extends DeserializedCommand { public static deserialize (rawCommand: Buffer) { const properties = { - mixEffects: rawCommand[0], - sources: rawCommand[1], - colorGenerators: rawCommand[2], - auxilliaries: rawCommand[3], - talkbackOutputs: rawCommand[4], - mediaPlayers: rawCommand[5], - serialPorts: rawCommand[6], - maxHyperdecks: rawCommand[7], - DVEs: rawCommand[8], - stingers: rawCommand[9], - superSources: rawCommand[10], - talkbackOverSDI: rawCommand[13], + mixEffects: rawCommand.readUInt8(0), + sources: rawCommand.readUInt8(1), + colorGenerators: rawCommand.readUInt8(2), + auxilliaries: rawCommand.readUInt8(3), + talkbackOutputs: rawCommand.readUInt8(4), + mediaPlayers: rawCommand.readUInt8(5), + serialPorts: rawCommand.readUInt8(6), + maxHyperdecks: rawCommand.readUInt8(7), + DVEs: rawCommand.readUInt8(8), + stingers: rawCommand.readUInt8(9), + superSources: rawCommand.readUInt8(10), + talkbackOverSDI: rawCommand.readUInt8(13), // TODO - define the below properly multiViewers: 2, diff --git a/src/commands/DownstreamKey/DownstreamKeyPropertiesCommand.ts b/src/commands/DownstreamKey/DownstreamKeyPropertiesCommand.ts index d43969cd8..9e4e4aea9 100644 --- a/src/commands/DownstreamKey/DownstreamKeyPropertiesCommand.ts +++ b/src/commands/DownstreamKey/DownstreamKeyPropertiesCommand.ts @@ -14,7 +14,7 @@ export class DownstreamKeyPropertiesCommand extends DeserializedCommand 0 ? externalPorts : null, - isExternal: rawCommand[28] === 0, + isExternal: rawCommand.readUInt8(28) === 0, externalPortType: rawCommand.readUInt8(31), internalPortType: rawCommand.readUInt8(32), sourceAvailability: rawCommand.readUInt8(34), diff --git a/src/commands/Macro/MacroPropertiesCommand.ts b/src/commands/Macro/MacroPropertiesCommand.ts index cc05c66de..0d4f3563f 100644 --- a/src/commands/Macro/MacroPropertiesCommand.ts +++ b/src/commands/Macro/MacroPropertiesCommand.ts @@ -21,7 +21,7 @@ export class MacroPropertiesCommand extends DeserializedCommand public static deserialize (rawCommand: Buffer) { const properties = { - isRunning: Boolean(rawCommand[0] & 1 << 0), - isWaiting: Boolean(rawCommand[0] & 1 << 1), - loop: Boolean(rawCommand[1] & 1 << 0), + isRunning: Boolean(rawCommand.readUInt8(0) & 1 << 0), + isWaiting: Boolean(rawCommand.readUInt8(0) & 1 << 1), + loop: Boolean(rawCommand.readUInt8(1) & 1 << 0), macroIndex: rawCommand.readUInt16BE(2) } diff --git a/src/commands/Media/MediaPlayerSourceCommand.ts b/src/commands/Media/MediaPlayerSourceCommand.ts index 5e084d963..645b77ab6 100644 --- a/src/commands/Media/MediaPlayerSourceCommand.ts +++ b/src/commands/Media/MediaPlayerSourceCommand.ts @@ -42,11 +42,11 @@ export class MediaPlayerSourceUpdateCommand extends DeserializedCommand } public static deserialize (rawCommand: Buffer): PreviewInputUpdateCommand { - const mixEffect = rawCommand[0] + const mixEffect = rawCommand.readUInt8(0) const properties = { source: rawCommand.readUInt16BE(2) } diff --git a/src/commands/MixEffects/ProgramInputCommand.ts b/src/commands/MixEffects/ProgramInputCommand.ts index 5f66203a2..a9a7aee2e 100644 --- a/src/commands/MixEffects/ProgramInputCommand.ts +++ b/src/commands/MixEffects/ProgramInputCommand.ts @@ -33,7 +33,7 @@ export class ProgramInputUpdateCommand extends DeserializedCommand } public static deserialize (rawCommand: Buffer): ProgramInputUpdateCommand { - const mixEffect = rawCommand[0] + const mixEffect = rawCommand.readUInt8(0) const properties = { source: rawCommand.readUInt16BE(2) } diff --git a/src/commands/MixEffects/Transition/TransitionDVECommand.ts b/src/commands/MixEffects/Transition/TransitionDVECommand.ts index e24385d87..2de34c383 100644 --- a/src/commands/MixEffects/Transition/TransitionDVECommand.ts +++ b/src/commands/MixEffects/Transition/TransitionDVECommand.ts @@ -64,21 +64,21 @@ export class TransitionDVEUpdateCommand extends DeserializedCommand { public static deserialize (rawCommand: Buffer): PowerStatusCommand { const properties = [ - Boolean(rawCommand[0] & 1 << 0), - Boolean(rawCommand[0] & 1 << 1) + Boolean(rawCommand.readUInt8(0) & 1 << 0), + Boolean(rawCommand.readUInt8(0) & 1 << 1) ] return new PowerStatusCommand(properties) diff --git a/src/commands/Settings/VideoMode.ts b/src/commands/Settings/VideoMode.ts index 4327ee79b..086b29030 100644 --- a/src/commands/Settings/VideoMode.ts +++ b/src/commands/Settings/VideoMode.ts @@ -28,7 +28,7 @@ export class VideoModeUpdateCommand extends DeserializedCommand } public static deserialize (rawCommand: Buffer): VideoModeUpdateCommand { - return new VideoModeUpdateCommand(rawCommand[0]) + return new VideoModeUpdateCommand(rawCommand.readUInt8(0)) } public applyToState (state: AtemState) { diff --git a/src/commands/SuperSource/SuperSourceBoxParametersCommand.ts b/src/commands/SuperSource/SuperSourceBoxParametersCommand.ts index 58e85a561..3abb0fee1 100644 --- a/src/commands/SuperSource/SuperSourceBoxParametersCommand.ts +++ b/src/commands/SuperSource/SuperSourceBoxParametersCommand.ts @@ -78,12 +78,12 @@ export class SuperSourceBoxParametersUpdateCommand extends DeserializedCommand 0 ? 1 : 0) const properties = { - enabled: rawCommand[i > 0 ? 2 : 1] === 1, + enabled: rawCommand.readUInt8(i > 0 ? 2 : 1) === 1, source: rawCommand.readUInt16BE(i + 2), x: rawCommand.readInt16BE(i + 4), y: rawCommand.readInt16BE(i + 6), size: rawCommand.readUInt16BE(i + 8), - cropped: rawCommand[i + 10] === 1, + cropped: rawCommand.readUInt8(i + 10) === 1, cropTop: rawCommand.readUInt16BE(i + 12), cropBottom: rawCommand.readUInt16BE(i + 14), cropLeft: rawCommand.readUInt16BE(i + 16), diff --git a/src/commands/SuperSource/SuperSourcePropertiesCommand.ts b/src/commands/SuperSource/SuperSourcePropertiesCommand.ts index c88a4b6d1..0f3b2b2a2 100644 --- a/src/commands/SuperSource/SuperSourcePropertiesCommand.ts +++ b/src/commands/SuperSource/SuperSourcePropertiesCommand.ts @@ -164,14 +164,14 @@ export class SuperSourcePropertiesUpdateCommand extends DeserializedCommand<{ pr artFillSource: rawCommand.readUInt16BE(0), artCutSource: rawCommand.readUInt16BE(2), artOption: rawCommand.readUInt8(4), - artPreMultiplied: rawCommand[5] === 1, + artPreMultiplied: rawCommand.readUInt8(5) === 1, artClip: rawCommand.readUInt16BE(6), artGain: rawCommand.readUInt16BE(8), - artInvertKey: rawCommand[10] === 1 + artInvertKey: rawCommand.readUInt8(10) === 1 }, border: { - borderEnabled: rawCommand[11] === 1, + borderEnabled: rawCommand.readUInt8(11) === 1, borderBevel: rawCommand.readUInt8(12), borderOuterWidth: rawCommand.readUInt16BE(14), borderInnerWidth: rawCommand.readUInt16BE(16), @@ -223,10 +223,10 @@ export class SuperSourcePropertiesUpdateV8Command extends DeserializedCommand Date: Fri, 6 Dec 2019 20:29:13 +0000 Subject: [PATCH 42/68] fix: gracefully emit error if applyToState fails --- src/atem.ts | 13 +++++++++---- src/commands/__tests__/index.spec.ts | 2 +- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/src/atem.ts b/src/atem.ts index 907bd8e28..d163e8884 100644 --- a/src/atem.ts +++ b/src/atem.ts @@ -485,11 +485,16 @@ export class Atem extends EventEmitter { this._state = new AtemState() } - let changePaths = command.applyToState(this.state) - if (!Array.isArray(changePaths)) { - changePaths = [ changePaths ] + try { + let changePaths = command.applyToState(this.state) + if (!Array.isArray(changePaths)) { + changePaths = [ changePaths ] + } + changePaths.forEach(path => this.emit('stateChanged', this._state, path)) + } catch (e) { + // TODO - should we error or warn on this? + this.emit('error', `MutateState failed: ${e}`) } - changePaths.forEach(path => this.emit('stateChanged', this._state, path)) for (const commandName in DataTransferCommands) { if (command.constructor.name === commandName) { diff --git a/src/commands/__tests__/index.spec.ts b/src/commands/__tests__/index.spec.ts index 0f1ca2d90..6f0208584 100644 --- a/src/commands/__tests__/index.spec.ts +++ b/src/commands/__tests__/index.spec.ts @@ -655,7 +655,7 @@ const commandConverters: CommandTestConverterSet = { }, 'MPCS': { idAliases: { - 'mediaPool': 'index' + 'clipId': 'index' }, propertyAliases: {} }, From aa9cea64fa470d429a3ee3c79f22d025a1f7ca5a Mon Sep 17 00:00:00 2001 From: Julian Waller Date: Fri, 6 Dec 2019 21:07:59 +0000 Subject: [PATCH 43/68] fix: ignore dve commands if not supported --- src/commands/MixEffects/Key/MixEffectKeyDVECommand.ts | 2 ++ .../MixEffects/Key/MixEffectKeyFlyKeyframeGetCommand.ts | 2 ++ src/commands/MixEffects/Transition/TransitionDVECommand.ts | 2 ++ 3 files changed, 6 insertions(+) diff --git a/src/commands/MixEffects/Key/MixEffectKeyDVECommand.ts b/src/commands/MixEffects/Key/MixEffectKeyDVECommand.ts index 660a163e1..7d3dd313b 100644 --- a/src/commands/MixEffects/Key/MixEffectKeyDVECommand.ts +++ b/src/commands/MixEffects/Key/MixEffectKeyDVECommand.ts @@ -143,6 +143,8 @@ export class MixEffectKeyDVEUpdateCommand extends DeserializedCommand= state.info.capabilities.mixEffects || this.upstreamKeyerId >= state.info.capabilities.upstreamKeyers) { throw new Error(`UpstreamKeyer ${this.mixEffect}-${this.upstreamKeyerId} is not valid`) + } else if (!state.info.capabilities.DVEs) { + throw new Error(`DVE is not supported`) } const mixEffect = state.video.getMe(this.mixEffect) diff --git a/src/commands/MixEffects/Key/MixEffectKeyFlyKeyframeGetCommand.ts b/src/commands/MixEffects/Key/MixEffectKeyFlyKeyframeGetCommand.ts index 720543c42..952d79e6e 100644 --- a/src/commands/MixEffects/Key/MixEffectKeyFlyKeyframeGetCommand.ts +++ b/src/commands/MixEffects/Key/MixEffectKeyFlyKeyframeGetCommand.ts @@ -59,6 +59,8 @@ export class MixEffectKeyFlyKeyframeGetCommand extends DeserializedCommand= state.info.capabilities.mixEffects || this.upstreamKeyerId >= state.info.capabilities.upstreamKeyers) { throw new Error(`UpstreamKeyer ${this.mixEffect}-${this.upstreamKeyerId} is not valid`) + } else if (this.keyFrameId <= 0 || this.keyFrameId > 2) { + throw new Error(`KeyFrame ${this.keyFrameId} is not valid`) } const mixEffect = state.video.getMe(this.mixEffect) diff --git a/src/commands/MixEffects/Transition/TransitionDVECommand.ts b/src/commands/MixEffects/Transition/TransitionDVECommand.ts index 2de34c383..97d0337b3 100644 --- a/src/commands/MixEffects/Transition/TransitionDVECommand.ts +++ b/src/commands/MixEffects/Transition/TransitionDVECommand.ts @@ -87,6 +87,8 @@ export class TransitionDVEUpdateCommand extends DeserializedCommand= state.info.capabilities.mixEffects) { throw new Error(`MixEffect ${this.mixEffect} is not valid`) + } else if (!state.info.capabilities.DVEs) { + throw new Error(`DVE is not supported`) } const mixEffect = state.video.getMe(this.mixEffect) From e07fb62a16b870c8b50b8d10b6509e2bf4dd1a6f Mon Sep 17 00:00:00 2001 From: Julian Waller Date: Sat, 7 Dec 2019 13:52:38 +0000 Subject: [PATCH 44/68] chore: tidy enums --- src/enums/index.ts | 35 -------------------------- src/lib/__tests__/socket-child.spec.ts | 3 +-- src/lib/atemSocketChild.ts | 15 ++++++++++- src/state/settings.ts | 4 ++- 4 files changed, 18 insertions(+), 39 deletions(-) diff --git a/src/enums/index.ts b/src/enums/index.ts index 2c0f1fa4f..5ba897926 100644 --- a/src/enums/index.ts +++ b/src/enums/index.ts @@ -26,26 +26,6 @@ export enum TransitionStyle { STING = 0x04 } -export enum TallyState { - None = 0x00, - Program = 0x01, - Preview = 0x02 -} - -export enum ConnectionState { - Closed = 0x00, - SynSent = 0x01, - Established = 0x02 -} - -export enum PacketFlag { - AckRequest = 0x01, - Connect = 0x02, - IsRetransmit = 0x04, - RetransmitRequest = 0x08, - AckReply = 0x10 -} - export enum DVEEffect { SwooshTopLeft= 0, SwooshTop = 1, @@ -205,14 +185,6 @@ export enum TransferMode { WriteAudio = 256 } -export enum StoragePool { - Stills, - Clip1, - Clip2, - Audio1, - Audio2 -} - export enum VideoMode { N525i5994NTSC, P625i50PAL, @@ -251,13 +223,6 @@ export enum MediaSourceType { Clip } -export enum MultiViewerLayout { - Top = 0, - Bottom = 1, - Left = 2, - Right = 3 -} - export enum AudioMixOption { Off = 0, On = 1, diff --git a/src/lib/__tests__/socket-child.spec.ts b/src/lib/__tests__/socket-child.spec.ts index 85747e35b..136a3e318 100644 --- a/src/lib/__tests__/socket-child.spec.ts +++ b/src/lib/__tests__/socket-child.spec.ts @@ -1,9 +1,8 @@ jest.mock('dgram') import { Socket } from '../__mocks__/dgram' -import { AtemSocketChild } from '../atemSocketChild' +import { AtemSocketChild, ConnectionState, PacketFlag } from '../atemSocketChild' import { Util } from '../..' import * as lolex from 'lolex' -import { ConnectionState, PacketFlag } from '../../enums' import { DEFAULT_PORT } from '../../atem' const ADDRESS = '127.0.0.1' diff --git a/src/lib/atemSocketChild.ts b/src/lib/atemSocketChild.ts index 3b3a06097..04b1fa825 100644 --- a/src/lib/atemSocketChild.ts +++ b/src/lib/atemSocketChild.ts @@ -1,6 +1,5 @@ import { createSocket, Socket, RemoteInfo } from 'dgram' import { Util } from './atemUtil' -import { ConnectionState, PacketFlag } from '../enums' import * as NanoTimer from 'nanotimer' const IN_FLIGHT_TIMEOUT = 60 // ms @@ -10,6 +9,20 @@ const MAX_PACKET_RETRIES = 10 const MAX_PACKET_ID = (1 << 15) // Atem expects 15 not 16 bits before wrapping const MAX_PACKET_PER_ACK = 16 +export enum ConnectionState { + Closed = 0x00, + SynSent = 0x01, + Established = 0x02 +} + +export enum PacketFlag { + AckRequest = 0x01, + Connect = 0x02, + IsRetransmit = 0x04, + RetransmitRequest = 0x08, + AckReply = 0x10 +} + interface InFlightPacket { readonly packetId: number readonly trackingId: number diff --git a/src/state/settings.ts b/src/state/settings.ts index c99e4ed4a..fff3cfc5a 100644 --- a/src/state/settings.ts +++ b/src/state/settings.ts @@ -1,3 +1,5 @@ +import { VideoMode } from '../enums' + export interface MultiViewerSourceState { source: number windowIndex: number @@ -20,7 +22,7 @@ export class MultiViewer { export class SettingsState { public readonly multiViewers: Array = [] - public videoMode: number + public videoMode: VideoMode constructor () { this.videoMode = 0 From 652603d7b576277536d485f99548da9c8adf0217 Mon Sep 17 00:00:00 2001 From: Julian Waller Date: Sat, 7 Dec 2019 14:51:49 +0000 Subject: [PATCH 45/68] chore: more socket-child tests --- src/lib/__tests__/socket-child.spec.ts | 314 ++++++++++++++++++++++++- src/lib/atemCommandParser.ts | 2 +- src/lib/atemSocketChild.ts | 6 +- 3 files changed, 318 insertions(+), 4 deletions(-) diff --git a/src/lib/__tests__/socket-child.spec.ts b/src/lib/__tests__/socket-child.spec.ts index 136a3e318..5d49eb7e6 100644 --- a/src/lib/__tests__/socket-child.spec.ts +++ b/src/lib/__tests__/socket-child.spec.ts @@ -26,16 +26,22 @@ function fakeConnect (child: AtemSocketChild) { const child2 = child as any child2._connectionState = ConnectionState.Established child2._address = '127.0.0.1' + child2.startTimers() } -function createSocketChild (onCommandReceived?: (payload: Buffer, packetId: number) => Promise, onCommandAcknowledged?: (packetId: number, trackingId: number) => Promise) { +function createSocketChild ( + onCommandReceived?: (payload: Buffer, packetId: number) => Promise, + onCommandAcknowledged?: (packetId: number, trackingId: number) => Promise, + onDisconnect?: () => Promise + ) { return new AtemSocketChild( { address: ADDRESS, port: DEFAULT_PORT, debug: false }, - () => Promise.resolve(), + onDisconnect || (() => Promise.resolve()), + // async msg => { console.log(msg) }, () => Promise.resolve(), onCommandReceived || (() => Promise.resolve()), onCommandAcknowledged || (() => Promise.resolve()) @@ -553,4 +559,308 @@ describe('SocketChild', () => { } }) + test('SendCommand - retransmit timeouts', async () => { + let acked: Array<{packetId: number, trackingId: number}> = [] + const child = createSocketChild(undefined, (packetId, trackingId) => { + acked.push({ packetId, trackingId }) + return Promise.resolve() + }) + try { + fakeConnect(child) + const socket = getSocket(child) + + ;(child as any)._nextSendPacketId = 32764 // 32767 is max + + let received: number[] = [] + socket.sendImpl = (msg: Buffer) => { + const opcode = msg.readUInt8(0) >> 3 + expect(opcode).toEqual(PacketFlag.AckRequest) + + received.push(msg.readUInt16BE(10)) + } + + acked = [] + + // Send some stuff + const buf1 = [0, 1, 2] + child.sendCommands([ + { payload: buf1, rawName: '', trackingId: 5 }, // 32764 + { payload: buf1, rawName: '', trackingId: 6 }, // 32765 + { payload: buf1, rawName: '', trackingId: 7 }, // 32766 + { payload: buf1, rawName: '', trackingId: 8 }, // 32767 + { payload: buf1, rawName: '', trackingId: 9 }, // 0 + { payload: buf1, rawName: '', trackingId: 10 } // 1 + ]) + expect(received).toEqual([32764, 32765, 32766, 32767, 0, 1]) + received = [] + expect(getInflightIds(child)).toEqual([32764, 32765, 32766, 32767, 0, 1]) + expect(acked).toEqual([]) + + // Ack a couple to ensure socket is running properly + await socket.emitMessage(clock, genAckCommandMessage(32765)) + expect(getInflightIds(child)).toEqual([32766, 32767, 0, 1]) + expect(acked).toEqual([ + { packetId: 32764, trackingId: 5 }, + { packetId: 32765, trackingId: 6 } + ]) + acked = [] + expect(received).toEqual([]) + received = [] + + // Let the commands be resent + await clock.tickAsync(80) + expect(received).toEqual([32766, 32767, 0, 1]) + received = [] + + // Should keep happening + await clock.tickAsync(80) + expect(received).toEqual([32766, 32767, 0, 1]) + received = [] + + // Add another to the queue + child.sendCommands([ + { payload: buf1, rawName: '', trackingId: 11 } // 2 + ]) + expect(received).toEqual([2]) + received = [] + expect(getInflightIds(child)).toEqual([32766, 32767, 0, 1, 2]) + expect(acked).toEqual([]) + + // And again, this time with the new thing + await clock.tickAsync(80) + expect(received).toEqual([32766, 32767, 0, 1, 2]) + received = [] + + } finally { + if (child) { + // Try and cleanup any timers + await child.disconnect() + } + } + }) + + function genRetransmitRequestCommandMessage (pktId: number) { + const buffer = Buffer.from([ + 0x40, 0x0c, // Length & Type + 0x53, 0x1b, // Session Id + 0x00, 0x00, // Not acking + 0x00, 0x00, // retransmit - set after + 0x00, 0x00, // 'Client pkt id' Not needed + 0x00, 0x00 // No Packet Id + ]) + buffer.writeUInt16BE(pktId, 6) // retransmit Id + + return buffer + } + + test('SendCommand - retransmit request', async () => { + let acked: Array<{packetId: number, trackingId: number}> = [] + const child = createSocketChild(undefined, (packetId, trackingId) => { + acked.push({ packetId, trackingId }) + return Promise.resolve() + }) + try { + fakeConnect(child) + const socket = getSocket(child) + + ;(child as any)._nextSendPacketId = 32764 // 32767 is max + + let received: number[] = [] + socket.sendImpl = (msg: Buffer) => { + const opcode = msg.readUInt8(0) >> 3 + expect(opcode).toEqual(PacketFlag.AckRequest) + + received.push(msg.readUInt16BE(10)) + } + + acked = [] + + // Send some stuff + const buf1 = [0, 1, 2] + child.sendCommands([ + { payload: buf1, rawName: '', trackingId: 5 }, // 32764 + { payload: buf1, rawName: '', trackingId: 6 }, // 32765 + { payload: buf1, rawName: '', trackingId: 7 }, // 32766 + { payload: buf1, rawName: '', trackingId: 8 }, // 32767 + { payload: buf1, rawName: '', trackingId: 9 }, // 0 + { payload: buf1, rawName: '', trackingId: 10 } // 1 + ]) + expect(received).toEqual([32764, 32765, 32766, 32767, 0, 1]) + received = [] + expect(getInflightIds(child)).toEqual([32764, 32765, 32766, 32767, 0, 1]) + expect(acked).toEqual([]) + + // Ack a couple to ensure socket is running properly + await socket.emitMessage(clock, genAckCommandMessage(32765)) + expect(getInflightIds(child)).toEqual([32766, 32767, 0, 1]) + expect(acked).toEqual([ + { packetId: 32764, trackingId: 5 }, + { packetId: 32765, trackingId: 6 } + ]) + acked = [] + expect(received).toEqual([]) + received = [] + + // The device asks for a retransmit + await socket.emitMessage(clock, genRetransmitRequestCommandMessage(32766)) + expect(received).toEqual([32766, 32767, 0, 1]) + received = [] + + // And again + await socket.emitMessage(clock, genRetransmitRequestCommandMessage(32767)) + expect(received).toEqual([32767, 0, 1]) + received = [] + + } finally { + if (child) { + // Try and cleanup any timers + await child.disconnect() + } + } + }) + + test('SendCommand - retransmit request future', async () => { + const acked: Array<{packetId: number, trackingId: number}> = [] + let connected = true + const child = createSocketChild(undefined, (packetId, trackingId) => { + acked.push({ packetId, trackingId }) + return Promise.resolve() + }, async () => { connected = false }) + try { + fakeConnect(child) + const socket = getSocket(child) + + ;(child as any)._nextSendPacketId = 32767 // 32767 is max + connected = true + + // Send some stuff + const buf1 = [0, 1, 2] + child.sendCommands([ + { payload: buf1, rawName: '', trackingId: 5 }, // 32767 + { payload: buf1, rawName: '', trackingId: 6 } // 0 + ]) + expect(getInflightIds(child)).toEqual([32767, 0]) + expect(acked).toEqual([]) + expect(connected).toBeTrue() + + // The device asks for a retransmit of a future packet + await socket.emitMessage(clock, genRetransmitRequestCommandMessage(1)) + expect(getInflightIds(child)).toEqual([]) + expect(connected).toBeFalse() + + } finally { + if (child) { + // Try and cleanup any timers + await child.disconnect() + } + } + }) + + test('SendCommand - retransmit request previous', async () => { + const acked: Array<{packetId: number, trackingId: number}> = [] + let connected = true + const child = createSocketChild(undefined, (packetId, trackingId) => { + acked.push({ packetId, trackingId }) + return Promise.resolve() + }, async () => { connected = false }) + try { + fakeConnect(child) + const socket = getSocket(child) + + ;(child as any)._nextSendPacketId = 32767 // 32767 is max + connected = true + + // Send some stuff + const buf1 = [0, 1, 2] + child.sendCommands([ + { payload: buf1, rawName: '', trackingId: 5 }, // 32767 + { payload: buf1, rawName: '', trackingId: 6 } // 0 + ]) + expect(getInflightIds(child)).toEqual([32767, 0]) + expect(acked).toEqual([]) + expect(connected).toBeTrue() + + // The device asks for a retransmit of a past packet + await socket.emitMessage(clock, genRetransmitRequestCommandMessage(32766)) + expect(getInflightIds(child)).toEqual([]) + expect(connected).toBeFalse() + + } finally { + if (child) { + // Try and cleanup any timers + await child.disconnect() + } + } + }) + + test('Reconnect timer', async () => { + let acked: Array<{packetId: number, trackingId: number}> = [] + let connected = true + const child = createSocketChild(undefined, (packetId, trackingId) => { + acked.push({ packetId, trackingId }) + return Promise.resolve() + }, async () => { connected = false }) + try { + fakeConnect(child) + const socket = getSocket(child) + + ;(child as any)._nextSendPacketId = 32767 // 32767 is max + connected = true + + acked = [] + + // Send some stuff + const buf1 = [0, 1, 2] + child.sendCommands([ + { payload: buf1, rawName: '', trackingId: 5 }, // 32767 + { payload: buf1, rawName: '', trackingId: 6 } // 0 + ]) + expect(getInflightIds(child)).toEqual([32767, 0]) + expect(acked).toEqual([]) + expect(connected).toBeTrue() + + // Ack a couple to ensure socket is running properly + await socket.emitMessage(clock, genAckCommandMessage(0)) + expect(getInflightIds(child)).toEqual([]) + expect(acked).toEqual([ + { packetId: 32767, trackingId: 5 }, + { packetId: 0, trackingId: 6 } + ]) + acked = [] + + // Tick to let the timer execute + await clock.tickAsync(1500) + expect(connected).toBeTrue() + expect(getInflightIds(child)).toEqual([]) + expect(acked).toEqual([]) + + // Still nothing + await clock.tickAsync(1500) + expect(connected).toBeTrue() + expect(getInflightIds(child)).toEqual([]) + expect(acked).toEqual([]) + + // Not quite + await clock.tickAsync(1990) + expect(connected).toBeTrue() + child.sendCommands([ + { payload: buf1, rawName: '', trackingId: 7 } // 1 + ]) + expect(getInflightIds(child)).toEqual([1]) + expect(acked).toEqual([]) + + // Timeout + await clock.tickAsync(20) + expect(connected).toBeFalse() + expect(getInflightIds(child)).toEqual([]) + expect(acked).toEqual([]) + + } finally { + if (child) { + // Try and cleanup any timers + await child.disconnect() + } + } + }) + }) diff --git a/src/lib/atemCommandParser.ts b/src/lib/atemCommandParser.ts index 28b6839d0..db626cf8e 100644 --- a/src/lib/atemCommandParser.ts +++ b/src/lib/atemCommandParser.ts @@ -16,7 +16,7 @@ export class CommandParser { this.commands[rawName].push(cmdConstructor) } } catch (e) { - // wwwwhatever + // probably not a valid command } } } diff --git a/src/lib/atemSocketChild.ts b/src/lib/atemSocketChild.ts index 04b1fa825..da0ad9654 100644 --- a/src/lib/atemSocketChild.ts +++ b/src/lib/atemSocketChild.ts @@ -70,7 +70,7 @@ export class AtemSocketChild { this._socket = this._createSocket() } - public connect (address: string, port: number): Promise { + private startTimers () { if (!this._reconnectTimer) { this._reconnectTimer = setInterval(async () => { if (this._lastReceivedAt + CONNECTION_TIMEOUT > Date.now()) { @@ -89,6 +89,10 @@ export class AtemSocketChild { if (!this._retransmitTimer) { this._retransmitTimer = setInterval(() => this._checkForRetransmit(), 10) } + } + + public connect (address: string, port: number): Promise { + this.startTimers() this._address = address this._port = port From 5a899105be185c1b078187b11a18ff16ec42429e Mon Sep 17 00:00:00 2001 From: Julian Waller Date: Sat, 7 Dec 2019 15:05:21 +0000 Subject: [PATCH 46/68] chore: enable test --- src/commands/__tests__/index.spec.ts | 1 - yarn.lock | 50 ++++++++++++++-------------- 2 files changed, 25 insertions(+), 26 deletions(-) diff --git a/src/commands/__tests__/index.spec.ts b/src/commands/__tests__/index.spec.ts index 6f0208584..3918cbdae 100644 --- a/src/commands/__tests__/index.spec.ts +++ b/src/commands/__tests__/index.spec.ts @@ -842,7 +842,6 @@ describe('Commands v7.2', () => { switch (testCase.name) { // Temporarily ignore the failures case 'FTSU': // Unkown props getting overwritten by generator: https://github.com/LibAtem/LibAtem/blob/master/LibAtem/Commands/DataTransfer/DataTransferDownloadRequestCommand.cs - case 'TDpP': // Range validation errors continue } diff --git a/yarn.lock b/yarn.lock index 317f3d09f..6bc56fdd6 100644 --- a/yarn.lock +++ b/yarn.lock @@ -10,14 +10,14 @@ "@babel/highlight" "^7.0.0" "@babel/core@^7.1.0": - version "7.7.4" - resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.7.4.tgz#37e864532200cb6b50ee9a4045f5f817840166ab" - integrity sha512-+bYbx56j4nYBmpsWtnPUsKW3NdnYxbqyfrP2w9wILBuHzdfIKz9prieZK0DFPyIzkjYVUe4QkusGL07r5pXznQ== + version "7.7.5" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.7.5.tgz#ae1323cd035b5160293307f50647e83f8ba62f7e" + integrity sha512-M42+ScN4+1S9iB6f+TL7QBpoQETxbclx+KNoKJABghnKYE+fMzSGqst0BZJc8CpI625bwPwYgUyRvxZ+0mZzpw== dependencies: "@babel/code-frame" "^7.5.5" "@babel/generator" "^7.7.4" "@babel/helpers" "^7.7.4" - "@babel/parser" "^7.7.4" + "@babel/parser" "^7.7.5" "@babel/template" "^7.7.4" "@babel/traverse" "^7.7.4" "@babel/types" "^7.7.4" @@ -85,10 +85,10 @@ esutils "^2.0.2" js-tokens "^4.0.0" -"@babel/parser@^7.1.0", "@babel/parser@^7.4.3", "@babel/parser@^7.7.4": - version "7.7.4" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.7.4.tgz#75ab2d7110c2cf2fa949959afb05fa346d2231bb" - integrity sha512-jIwvLO0zCL+O/LmEJQjWA75MQTWwx3c3u2JOTDK5D3/9egrWRRA0/0hk9XXywYnXZVVpzrBYeIQTmhwUaePI9g== +"@babel/parser@^7.1.0", "@babel/parser@^7.4.3", "@babel/parser@^7.7.4", "@babel/parser@^7.7.5": + version "7.7.5" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.7.5.tgz#cbf45321619ac12d83363fcf9c94bb67fa646d71" + integrity sha512-KNlOe9+/nk4i29g0VXgl8PEXIRms5xKLJeuZ6UptN0fHv+jDiriG+y94X6qAgWTR0h3KaoM1wK5G5h7MHFRSig== "@babel/plugin-syntax-object-rest-spread@^7.0.0": version "7.7.4" @@ -803,7 +803,7 @@ bs-logger@0.x: dependencies: fast-json-stable-stringify "2.x" -bser@^2.0.0: +bser@2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/bser/-/bser-2.1.1.tgz#e6787da20ece9d07998533cfd9de6f5c38f4bc05" integrity sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ== @@ -1421,9 +1421,9 @@ deep-is@~0.1.3: integrity sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ= defer-to-connect@^1.0.1: - version "1.1.0" - resolved "https://registry.yarnpkg.com/defer-to-connect/-/defer-to-connect-1.1.0.tgz#b41bd7efa8508cef13f8456975f7a278c72833fd" - integrity sha512-WE2sZoctWm/v4smfCAdjYbrfS55JiMRdlY9ZubFhsYbteCK9+BvAx4YV7nPjYM6ZnX5BcoVKwfmyx9sIFTgQMQ== + version "1.1.1" + resolved "https://registry.yarnpkg.com/defer-to-connect/-/defer-to-connect-1.1.1.tgz#88ae694b93f67b81815a2c8c769aef6574ac8f2f" + integrity sha512-J7thop4u3mRTkYRQ+Vpfwy2G5Ehoy82I14+14W4YMDLKdWloI9gSzRbV30s/NckQGVJtPkWNcW4oMAUigTdqiQ== define-properties@^1.1.2, define-properties@^1.1.3: version "1.1.3" @@ -1589,9 +1589,9 @@ error-ex@^1.2.0, error-ex@^1.3.1: is-arrayish "^0.2.1" es-abstract@^1.5.1: - version "1.16.2" - resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.16.2.tgz#4e874331645e9925edef141e74fc4bd144669d34" - integrity sha512-jYo/J8XU2emLXl3OLwfwtuFfuF2w6DYPs+xy9ZfVyPkDcrauu6LYrw/q2TyCtrbc/KUdCiC5e9UajRhgNkVopA== + version "1.16.3" + resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.16.3.tgz#52490d978f96ff9f89ec15b5cf244304a5bca161" + integrity sha512-WtY7Fx5LiOnSYgF5eg/1T+GONaGmpvpPdCpSnYij+U2gDTL0UPfWrhDw7b2IYb+9NQJsYpCA0wOQvZfsd6YwRw== dependencies: es-to-primitive "^1.2.1" function-bind "^1.1.1" @@ -1804,11 +1804,11 @@ fast-levenshtein@~2.0.6: integrity sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc= fb-watchman@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/fb-watchman/-/fb-watchman-2.0.0.tgz#54e9abf7dfa2f26cd9b1636c588c1afc05de5d58" - integrity sha1-VOmr99+i8mzZsWNsWIwa/AXeXVg= + version "2.0.1" + resolved "https://registry.yarnpkg.com/fb-watchman/-/fb-watchman-2.0.1.tgz#fc84fb39d2709cf3ff6d743706157bb5708a8a85" + integrity sha512-DkPJKQeY6kKwmuMretBhr7G6Vodr7bFwDYTXIkfG1gjvNpaxBTQV3PbXg6bR1c1UP4jPOX0jHUbbHANL9vRjVg== dependencies: - bser "^2.0.0" + bser "2.1.1" figures@3.0.0: version "3.0.0" @@ -4261,9 +4261,9 @@ pseudomap@^1.0.2: integrity sha1-8FKijacOYYkX7wqKw0wa5aaChrM= psl@^1.1.24, psl@^1.1.28: - version "1.5.0" - resolved "https://registry.yarnpkg.com/psl/-/psl-1.5.0.tgz#47fd1292def7fdb1e138cd78afa8814cebcf7b13" - integrity sha512-4vqUjKi2huMu1OJiLhi3jN6jeeKvMZdI1tYgi/njW5zV52jNLgSAZSdN16m9bJFe61/cT8ulmw4qFitV9QRsEA== + version "1.6.0" + resolved "https://registry.yarnpkg.com/psl/-/psl-1.6.0.tgz#60557582ee23b6c43719d9890fb4170ecd91e110" + integrity sha512-SYKKmVel98NCOYXpkwUqZqh0ahZeeKfmisiLIcEZdsb+WbLv02g/dI5BUmZnIyOe7RzZtLax81nnb2HbvC2tzA== pump@^3.0.0: version "3.0.0" @@ -5463,9 +5463,9 @@ typedoc@^0.15.0: typescript "3.7.x" typescript@3.7.x: - version "3.7.2" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.7.2.tgz#27e489b95fa5909445e9fef5ee48d81697ad18fb" - integrity sha512-ml7V7JfiN2Xwvcer+XAf2csGO1bPBdRbFCkYBczNZggrBZ9c7G3riSUeJmqEU5uOtXNPMhE3n+R4FA/3YOAWOQ== + version "3.7.3" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.7.3.tgz#b36840668a16458a7025b9eabfad11b66ab85c69" + integrity sha512-Mcr/Qk7hXqFBXMN7p7Lusj1ktCBydylfQM/FZCk5glCNQJrCUKPkMHdo9R0MTFWsC/4kPFvDS0fDPvukfCkFsw== typescript@~3.6.4: version "3.6.4" From 093c2b7fe8d1e65981bea363ca4bd21044368ff7 Mon Sep 17 00:00:00 2001 From: Julian Waller Date: Sat, 7 Dec 2019 15:46:24 +0000 Subject: [PATCH 47/68] chore: bump version as this is a breaking change --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 2adc17c80..01e524fc7 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "atem-connection", - "version": "1.0.0-0", + "version": "2.0.0-0", "description": "Typescript Node.js library for connecting with an ATEM switcher.", "main": "dist/index.js", "typings": "dist/index.d.ts", From ad6c5233c2590e2d28ffa0f35dd823edf68d3f4b Mon Sep 17 00:00:00 2001 From: Julian Waller Date: Sat, 7 Dec 2019 16:02:05 +0000 Subject: [PATCH 48/68] chore: update readme and some TODOs --- README.md | 15 ++++------ src/atem.ts | 28 +++++++++---------- src/commands/Inputs/InputPropertiesCommand.ts | 3 -- src/commands/__tests__/util.ts | 2 +- src/dataTransfer/__tests__/index.spec.ts | 2 +- src/dataTransfer/index.ts | 4 +-- src/lib/__mocks__/dgram.ts | 1 - src/lib/tally.ts | 2 +- 8 files changed, 23 insertions(+), 34 deletions(-) diff --git a/README.md b/README.md index 7bed0d16a..2c20339a6 100644 --- a/README.md +++ b/README.md @@ -37,20 +37,15 @@ const myAtem = new Atem({ externalLog: console.log }) myAtem.connect('192.168.168.240') myAtem.on('connected', () => { - myAtem.changeProgramInput(3).then((res) => { - console.log(res) - // ProgramInputCommand { - // flag: 0, - // rawName: 'PrgI', - // mixEffect: 0, - // properties: { source: 3 }, - // resolve: [Function], - // reject: [Function] } + myAtem.changeProgramInput(3).then(() => { + // Fired once the atem has acknowledged the command + // Note: the state likely hasnt updated yet, but will follow shortly + console.log('Program input set') }) console.log(myAtem.state) }) -myAtem.on('stateChanged', function(err, state) { +myAtem.on('stateChanged', (state, pathToChange) => { console.log(state); // catch the ATEM state. }); ``` diff --git a/src/atem.ts b/src/atem.ts index d163e8884..7d8647d97 100644 --- a/src/atem.ts +++ b/src/atem.ts @@ -109,29 +109,27 @@ export class Atem extends EventEmitter { return this.socket.destroy() } - private sendCommands (commands: ISerializableCommand[]): Array> { - const cmds2 = commands.map(cmd => ({ + private sendCommands (commands: ISerializableCommand[]): Array> { + const commands2 = commands.map(cmd => ({ rawCommand: cmd, trackingId: this.socket.nextCommandTrackingId })) - const sendPromise = this.socket.sendCommands(cmds2) - - return cmds2.map(cmd => { - // TODO - does this work? - return sendPromise.then(() => { - return new Promise((resolve, reject) => { - this._sentQueue[cmd.trackingId] = { - command: cmd.rawCommand, - resolve, - reject - } - }) + const sendPromise = this.socket.sendCommands(commands2) + + return commands2.map(async cmd => { + await sendPromise + return new Promise((resolve, reject) => { + this._sentQueue[cmd.trackingId] = { + command: cmd.rawCommand, + resolve, + reject + } }) }) } - public sendCommand (command: ISerializableCommand): Promise { + public sendCommand (command: ISerializableCommand): Promise { return this.sendCommands([command])[0] } diff --git a/src/commands/Inputs/InputPropertiesCommand.ts b/src/commands/Inputs/InputPropertiesCommand.ts index 5171d8831..0609f97a9 100644 --- a/src/commands/Inputs/InputPropertiesCommand.ts +++ b/src/commands/Inputs/InputPropertiesCommand.ts @@ -80,9 +80,6 @@ export class InputPropertiesUpdateCommand extends DeserializedCommand { diff --git a/src/dataTransfer/__tests__/index.spec.ts b/src/dataTransfer/__tests__/index.spec.ts index 49bdd57dc..0599ef077 100644 --- a/src/dataTransfer/__tests__/index.spec.ts +++ b/src/dataTransfer/__tests__/index.spec.ts @@ -45,7 +45,7 @@ function runDataTransferTest (spec: any) { manager.handleCommand(nextCmd2) } - return Promise.resolve(cmd) + return Promise.resolve() })) return manager } diff --git a/src/dataTransfer/index.ts b/src/dataTransfer/index.ts index ab3009bd2..8d722a0f2 100644 --- a/src/dataTransfer/index.ts +++ b/src/dataTransfer/index.ts @@ -25,7 +25,7 @@ export class DataTransferManager { private transferIndex: number = 0 - public startCommandSending (sendCommands: (cmds: ISerializableCommand[]) => Array>) { + public startCommandSending (sendCommands: (cmds: ISerializableCommand[]) => Array>) { if (!this.interval) { // New connection means a new queue this.commandQueue.splice(0, this.commandQueue.length) @@ -42,7 +42,7 @@ export class DataTransferManager { console.log(`Transfer send error: ${e}`) }) }) - }, 0) // TODO - should this be done slower? + }, 0) } if (!this.exitUnsubscribe) { this.exitUnsubscribe = exitHook(() => { diff --git a/src/lib/__mocks__/dgram.ts b/src/lib/__mocks__/dgram.ts index b33792a40..006b1fa0a 100644 --- a/src/lib/__mocks__/dgram.ts +++ b/src/lib/__mocks__/dgram.ts @@ -60,7 +60,6 @@ export class Socket extends EventEmitter { public close (cb?: Function) { this.isOpen = false - // TODO - optional delay? if (cb) cb() } } diff --git a/src/lib/tally.ts b/src/lib/tally.ts index 4b4f39bf5..8b3d24240 100644 --- a/src/lib/tally.ts +++ b/src/lib/tally.ts @@ -89,7 +89,7 @@ function _calcActiveMeInputs (mode: 'program' | 'preview', state: AtemState, meI if (usk) { const keyerMask = 1 << (usk.upstreamKeyerId + 1) const isPartOfTransition = meRef.transitionProperties.selection & keyerMask - if (mode === 'program') { // TODO - verify these conditions + if (mode === 'program') { if (meRef.inTransition) { return usk.onAir || isPartOfTransition } From 17b1fdb70b314c171d6301b3948129b62935da0e Mon Sep 17 00:00:00 2001 From: Julian Waller Date: Mon, 9 Dec 2019 11:41:22 +0000 Subject: [PATCH 49/68] fix: export keyer state types --- src/state/video/index.ts | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/state/video/index.ts b/src/state/video/index.ts index 5a44da1ff..75e4e8479 100644 --- a/src/state/video/index.ts +++ b/src/state/video/index.ts @@ -1,6 +1,8 @@ import * as Enum from '../../enums' import * as USK from './upstreamKeyers' -import { DownstreamKeyer } from './downstreamKeyers' +import * as DSK from './downstreamKeyers' + +export { USK, DSK } export interface DipTransitionSettings { rate: number @@ -193,7 +195,7 @@ export interface FadeToBlackProperties { export class AtemVideoState { public readonly ME: Array = [] - public readonly downstreamKeyers: Array = [] + public readonly downstreamKeyers: Array = [] public readonly auxilliaries: Array = [] public readonly superSources: Array = [] @@ -223,7 +225,7 @@ export class AtemVideoState { return ssrc } - public getDownstreamKeyer (index: number, dontCreate?: boolean): DownstreamKeyer { + public getDownstreamKeyer (index: number, dontCreate?: boolean): DSK.DownstreamKeyer { let dsk = this.downstreamKeyers[index] if (!dsk) { dsk = { From 115b6d0081797e04475c284b5b77d82f879dd6da Mon Sep 17 00:00:00 2001 From: Julian Waller Date: Mon, 9 Dec 2019 11:41:53 +0000 Subject: [PATCH 50/68] chore: tidy datatransfer command rejection --- src/dataTransfer/index.ts | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/dataTransfer/index.ts b/src/dataTransfer/index.ts index 8d722a0f2..2e5e04d9e 100644 --- a/src/dataTransfer/index.ts +++ b/src/dataTransfer/index.ts @@ -36,11 +36,10 @@ export class DataTransferManager { } const commandsToSend = this.commandQueue.splice(0, MAX_PACKETS_TO_SEND_PER_TICK) - sendCommands(commandsToSend).forEach(cmdRes => { - cmdRes.catch((e) => { - // TODO - handle this better. it should probably kill/restart the upload. and should also be logged in some way - console.log(`Transfer send error: ${e}`) - }) + // The only way commands are rejected is if the connection dies, so if any reject then we fail + Promise.all(sendCommands(commandsToSend)).catch((e) => { + // TODO - handle this better. it should kill/restart the upload. and should also be logged in some way + console.log(`Transfer send error: ${e}`) }) }, 0) } From 85ac91f8402af4bb3798dbc4540ee4a7f6a85dc7 Mon Sep 17 00:00:00 2001 From: Julian Waller Date: Mon, 9 Dec 2019 20:06:47 +0000 Subject: [PATCH 51/68] fix: some defaults --- src/commands/CommandBase.ts | 1 - src/state/video/index.ts | 4 ++-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/commands/CommandBase.ts b/src/commands/CommandBase.ts index 33abae2a6..e7eef39f0 100644 --- a/src/commands/CommandBase.ts +++ b/src/commands/CommandBase.ts @@ -24,7 +24,6 @@ export interface ISerializableCommand { } export abstract class BasicWritableCommand implements ISerializableCommand { - public static readonly MaskFlags?: { [key: string]: number } public static readonly minimumVersion?: ProtocolVersion protected _properties: T diff --git a/src/state/video/index.ts b/src/state/video/index.ts index 75e4e8479..fec74eb6e 100644 --- a/src/state/video/index.ts +++ b/src/state/video/index.ts @@ -104,9 +104,9 @@ export class MixEffect implements IMixEffect { this.transitionProperties = { style: Enum.TransitionStyle.MIX, - selection: 0, + selection: 1, nextStyle: Enum.TransitionStyle.MIX, - nextSelection: 0 + nextSelection: 1 } } From d6e02d806f407678284fb1c9e9ed34bd5a68ae05 Mon Sep 17 00:00:00 2001 From: Julian Waller Date: Mon, 9 Dec 2019 20:07:24 +0000 Subject: [PATCH 52/68] feat: split Atem into a BasicAtem base class, as an easier to mock alternative when commands are constructed manually --- src/atem.ts | 98 ++++++++++++++++++++++++++++------------------------- 1 file changed, 52 insertions(+), 46 deletions(-) diff --git a/src/atem.ts b/src/atem.ts index 7d8647d97..6bcd0bfc2 100644 --- a/src/atem.ts +++ b/src/atem.ts @@ -43,9 +43,9 @@ interface SentCommand { export const DEFAULT_PORT = 9910 -export class Atem extends EventEmitter { +export class BasicAtem extends EventEmitter { private readonly socket: AtemSocket - private readonly dataTransferManager: DT.DataTransferManager + protected readonly dataTransferManager: DT.DataTransferManager private readonly _log: (...args: any[]) => void private _state: AtemState private _sentQueue: {[packetId: string]: SentCommand } = {} @@ -133,6 +133,52 @@ export class Atem extends EventEmitter { return this.sendCommands([command])[0] } + private _mutateState (command: IDeserializedCommand) { + if (command.constructor.name === Commands.VersionCommand.name) { + // On start of connection, create a new state object + this._state = new AtemState() + } + + try { + let changePaths = command.applyToState(this.state) + if (!Array.isArray(changePaths)) { + changePaths = [ changePaths ] + } + changePaths.forEach(path => this.emit('stateChanged', this._state, path)) + } catch (e) { + // TODO - should we error or warn on this? + this.emit('error', `MutateState failed: ${e}`) + } + + for (const commandName in DataTransferCommands) { + if (command.constructor.name === commandName) { + this.dataTransferManager.handleCommand(command) + } + } + } + + private _resolveCommand (trackingId: number) { + const sent = this._sentQueue[trackingId] + if (sent) { + sent.resolve() + delete this._sentQueue[trackingId] + } + } + + private _rejectAllCommands () { + // Take a copy in case the promises cause more mutations + const sentQueue = this._sentQueue + this._sentQueue = {} + + Object.values(sentQueue).forEach(sent => sent.reject()) + } +} + +export class Atem extends BasicAtem { + constructor (options?: AtemOptions) { + super(options) + } + public changeProgramInput (input: number, me: number = 0) { const command = new Commands.ProgramInputCommand(me, input) return this.sendCommand(command) @@ -326,7 +372,7 @@ export class Atem extends EventEmitter { } public setSuperSourceProperties (newProps: Partial, ssrcId: number = 0) { - if (this._state.info.apiVersion >= Enums.ProtocolVersion.V8_0) { + if (this.state.info.apiVersion >= Enums.ProtocolVersion.V8_0) { const command = new Commands.SuperSourcePropertiesV8Command(ssrcId) command.updateProps(newProps) return this.sendCommand(command) @@ -338,7 +384,7 @@ export class Atem extends EventEmitter { } public setSuperSourceBorder (newProps: Partial, ssrcId: number = 0) { - if (this._state.info.apiVersion >= Enums.ProtocolVersion.V8_0) { + if (this.state.info.apiVersion >= Enums.ProtocolVersion.V8_0) { const command = new Commands.SuperSourceBorderCommand(ssrcId) command.updateProps(newProps) return this.sendCommand(command) @@ -407,7 +453,7 @@ export class Atem extends EventEmitter { } public uploadStill (index: number, data: Buffer, name: string, description: string) { - const resolution = Util.getResolution(this._state.settings.videoMode) + const resolution = Util.getResolution(this.state.settings.videoMode) return this.dataTransferManager.uploadStill( index, Util.convertRGBAToYUV422(resolution[0], resolution[1], data), @@ -417,7 +463,7 @@ export class Atem extends EventEmitter { } public uploadClip (index: number, frames: Array, name: string) { - const resolution = Util.getResolution(this._state.settings.videoMode) + const resolution = Util.getResolution(this.state.settings.videoMode) const data: Array = [] for (const frame of frames) { data.push(Util.convertRGBAToYUV422(resolution[0], resolution[1], frame)) @@ -476,44 +522,4 @@ export class Atem extends EventEmitter { public listVisibleInputs (mode: 'program' | 'preview', me = 0): number[] { return listVisibleInputs(mode, this.state, me) } - - private _mutateState (command: IDeserializedCommand) { - if (command.constructor.name === Commands.VersionCommand.name) { - // On start of connection, create a new state object - this._state = new AtemState() - } - - try { - let changePaths = command.applyToState(this.state) - if (!Array.isArray(changePaths)) { - changePaths = [ changePaths ] - } - changePaths.forEach(path => this.emit('stateChanged', this._state, path)) - } catch (e) { - // TODO - should we error or warn on this? - this.emit('error', `MutateState failed: ${e}`) - } - - for (const commandName in DataTransferCommands) { - if (command.constructor.name === commandName) { - this.dataTransferManager.handleCommand(command) - } - } - } - - private _resolveCommand (trackingId: number) { - const sent = this._sentQueue[trackingId] - if (sent) { - sent.resolve() - delete this._sentQueue[trackingId] - } - } - - private _rejectAllCommands () { - // Take a copy in case the promises cause more mutations - const sentQueue = this._sentQueue - this._sentQueue = {} - - Object.values(sentQueue).forEach(sent => sent.reject()) - } } From f646e923afd1d18bf186247e065d17b6ec52a1db Mon Sep 17 00:00:00 2001 From: Julian Waller Date: Mon, 9 Dec 2019 22:48:24 +0000 Subject: [PATCH 53/68] feat: emit more events in batches, rather than for individual commands --- src/__tests__/atem.spec.ts | 2 +- src/atem.ts | 115 ++++++++++++------- src/lib/__tests__/atemSocket.spec.ts | 146 +++++++++++-------------- src/lib/__tests__/socket-child.spec.ts | 43 ++------ src/lib/atemSocket.ts | 69 ++++++------ src/lib/atemSocketChild.ts | 19 ++-- src/state/index.ts | 2 +- src/state/macro.ts | 2 +- 8 files changed, 201 insertions(+), 197 deletions(-) diff --git a/src/__tests__/atem.spec.ts b/src/__tests__/atem.spec.ts index 75c567e4d..c07b7531f 100644 --- a/src/__tests__/atem.spec.ts +++ b/src/__tests__/atem.spec.ts @@ -125,7 +125,7 @@ describe('Atem', () => { }]) // Trigger the ack, and it should switfy resolve - socket.emit('commandAck', 124) + socket.emit('commandsAck', [124]) expect(Object.keys(sentQueue)).toHaveLength(0) // Finally, it should now resolve without a timeout diff --git a/src/atem.ts b/src/atem.ts index 6bcd0bfc2..a85065d17 100644 --- a/src/atem.ts +++ b/src/atem.ts @@ -41,32 +41,40 @@ interface SentCommand { reject: () => void } +export enum AtemConnectionStatus { + CLOSED, + CONNECTING, + CONNECTED +} + export const DEFAULT_PORT = 9910 export class BasicAtem extends EventEmitter { private readonly socket: AtemSocket protected readonly dataTransferManager: DT.DataTransferManager private readonly _log: (...args: any[]) => void - private _state: AtemState + private _state: AtemState | undefined private _sentQueue: {[packetId: string]: SentCommand } = {} + private _status: AtemConnectionStatus public on!: ((event: 'error', listener: (message: any) => void) => this) & ((event: 'connected', listener: () => void) => this) & ((event: 'disconnected', listener: () => void) => this) & - ((event: 'stateChanged', listener: (state: AtemState, path: string) => void) => this) & - ((event: 'receivedCommand', listener: (cmd: IDeserializedCommand) => void) => this) + ((event: 'stateChanged', listener: (state: AtemState, paths: string[]) => void) => this) & + ((event: 'receivedCommands', listener: (cmds: IDeserializedCommand[]) => void) => this) public emit!: ((event: 'error', message: any) => boolean) & ((event: 'connected') => boolean) & ((event: 'disconnected') => boolean) & - ((event: 'stateChanged', state: AtemState, path: string) => boolean) & - ((event: 'receivedCommand', cmd: IDeserializedCommand) => boolean) + ((event: 'stateChanged', state: AtemState, paths: string[]) => boolean) & + ((event: 'receivedCommands', cmds: IDeserializedCommand[]) => boolean) constructor (options?: AtemOptions) { super() this._log = (options && options.externalLog) || ((...args: any[]) => { console.log(...args) }) this._state = new AtemState() + this._status = AtemConnectionStatus.CLOSED this.socket = new AtemSocket({ debug: (options || {}).debug || false, log: this._log, @@ -76,24 +84,31 @@ export class BasicAtem extends EventEmitter { }) this.dataTransferManager = new DT.DataTransferManager() - this.socket.on('commandReceived', command => { - this.emit('receivedCommand', command) - this._mutateState(command) + this.socket.on('commandsReceived', commands => { + this.emit('receivedCommands', commands) + this._mutateState(commands) }) - this.socket.on('commandAck', trackingId => this._resolveCommand(trackingId)) + this.socket.on('commandsAck', trackingIds => this._resolveCommands(trackingIds)) this.socket.on('error', e => this.emit('error', e)) - this.socket.on('connect', () => { - this.dataTransferManager.startCommandSending(cmds => this.sendCommands(cmds)) - this.emit('connected') - }) this.socket.on('disconnect', () => { + this._status = AtemConnectionStatus.CLOSED this.dataTransferManager.stopCommandSending() this._rejectAllCommands() this.emit('disconnected') + this._state = undefined }) } - get state (): Readonly { + private _onInitComplete () { + this.dataTransferManager.startCommandSending(cmds => this.sendCommands(cmds)) + this.emit('connected') + } + + get status (): AtemConnectionStatus { + return this._status + } + + get state (): Readonly | undefined { return this._state } @@ -133,36 +148,56 @@ export class BasicAtem extends EventEmitter { return this.sendCommands([command])[0] } - private _mutateState (command: IDeserializedCommand) { - if (command.constructor.name === Commands.VersionCommand.name) { + private _mutateState (commands: IDeserializedCommand[]) { + // Is this the start of a new connection? + if (commands.find(cmd => cmd.constructor.name === Commands.VersionCommand.name)) { // On start of connection, create a new state object this._state = new AtemState() + this._status = AtemConnectionStatus.CONNECTING } - try { - let changePaths = command.applyToState(this.state) - if (!Array.isArray(changePaths)) { - changePaths = [ changePaths ] + const allChangedPaths: string[] = [] + + const state = this._state + commands.forEach(command => { + if (state) { + try { + const changePaths = command.applyToState(state) + if (!Array.isArray(changePaths)) { + allChangedPaths.push(changePaths) + } else { + allChangedPaths.push(...changePaths) + } + } catch (e) { + // TODO - should we error or warn on this? + this.emit('error', `MutateState failed: ${e}`) + } } - changePaths.forEach(path => this.emit('stateChanged', this._state, path)) - } catch (e) { - // TODO - should we error or warn on this? - this.emit('error', `MutateState failed: ${e}`) - } - for (const commandName in DataTransferCommands) { - if (command.constructor.name === commandName) { - this.dataTransferManager.handleCommand(command) + for (const commandName in DataTransferCommands) { + if (command.constructor.name === commandName) { + this.dataTransferManager.handleCommand(command) + } } + }) + + const initComplete = commands.find(cmd => cmd.constructor.name === Commands.InitCompleteCommand.name) + if (initComplete) { + this._status = AtemConnectionStatus.CONNECTED + this._onInitComplete() + } else if (state && this._status === AtemConnectionStatus.CONNECTED && allChangedPaths.length > 0) { + this.emit('stateChanged', state, allChangedPaths) } } - private _resolveCommand (trackingId: number) { - const sent = this._sentQueue[trackingId] - if (sent) { - sent.resolve() - delete this._sentQueue[trackingId] - } + private _resolveCommands (trackingIds: number[]) { + trackingIds.forEach(trackingId => { + const sent = this._sentQueue[trackingId] + if (sent) { + sent.resolve() + delete this._sentQueue[trackingId] + } + }) } private _rejectAllCommands () { @@ -372,7 +407,7 @@ export class Atem extends BasicAtem { } public setSuperSourceProperties (newProps: Partial, ssrcId: number = 0) { - if (this.state.info.apiVersion >= Enums.ProtocolVersion.V8_0) { + if (this.state && this.state.info.apiVersion >= Enums.ProtocolVersion.V8_0) { const command = new Commands.SuperSourcePropertiesV8Command(ssrcId) command.updateProps(newProps) return this.sendCommand(command) @@ -384,7 +419,7 @@ export class Atem extends BasicAtem { } public setSuperSourceBorder (newProps: Partial, ssrcId: number = 0) { - if (this.state.info.apiVersion >= Enums.ProtocolVersion.V8_0) { + if (this.state && this.state.info.apiVersion >= Enums.ProtocolVersion.V8_0) { const command = new Commands.SuperSourceBorderCommand(ssrcId) command.updateProps(newProps) return this.sendCommand(command) @@ -453,6 +488,7 @@ export class Atem extends BasicAtem { } public uploadStill (index: number, data: Buffer, name: string, description: string) { + if (!this.state) return Promise.reject() const resolution = Util.getResolution(this.state.settings.videoMode) return this.dataTransferManager.uploadStill( index, @@ -463,6 +499,7 @@ export class Atem extends BasicAtem { } public uploadClip (index: number, frames: Array, name: string) { + if (!this.state) return Promise.reject() const resolution = Util.getResolution(this.state.settings.videoMode) const data: Array = [] for (const frame of frames) { @@ -520,6 +557,10 @@ export class Atem extends BasicAtem { } public listVisibleInputs (mode: 'program' | 'preview', me = 0): number[] { - return listVisibleInputs(mode, this.state, me) + if (this.state) { + return listVisibleInputs(mode, this.state, me) + } else { + return [] + } } } diff --git a/src/lib/__tests__/atemSocket.spec.ts b/src/lib/__tests__/atemSocket.spec.ts index 8dcb6e90a..140e3b903 100644 --- a/src/lib/__tests__/atemSocket.spec.ts +++ b/src/lib/__tests__/atemSocket.spec.ts @@ -1,4 +1,4 @@ -import { CutCommand, ProductIdentifierCommand, InitCompleteCommand, VersionCommand, ProgramInputUpdateCommand, PreviewInputUpdateCommand, ISerializableCommand, BasicWritableCommand, DeserializedCommand } from '../../commands' +import { CutCommand, ProductIdentifierCommand, VersionCommand, ProgramInputUpdateCommand, PreviewInputUpdateCommand, ISerializableCommand, BasicWritableCommand, DeserializedCommand } from '../../commands' import { ProtocolVersion, Model } from '../../enums' import { AtemSocket } from '../atemSocket' import { ThreadedClass, ThreadedClassManager } from 'threadedclass' @@ -9,34 +9,42 @@ import { AtemSocketChild } from '../atemSocketChild' // import { promisify } from 'util' jest.mock('../atemSocketChild') -export class AtemSocketChildMock { - public onDisconnect?: () => Promise - public onLog?: (message: string) => Promise - public onCommandReceived?: (payload: Buffer, packetId: number) => Promise - public onCommandAcknowledged?: (packetId: number, trackingId: number) => Promise - - // constructor (_options: { address: string, port: number, debug: boolean }, onDisconnect: () => Promise, onLog: (message: string) => Promise, onCommandReceived: (payload: Buffer, packetId: number) => Promise, onCommandAcknowledged: (packetId: number, trackingId: number) => Promise) { - // // this._debug = options.debug - // // this._address = options.address - // // this._port = options.port - - // this.onDisconnect = onDisconnect - // this.onLog = onLog - // this.onCommandReceived = onCommandReceived - // this.onCommandAcknowledged = onCommandAcknowledged - // } - - public connect = jest.fn() - public disconnect = jest.fn(() => Promise.resolve(87)) - public sendCommands = jest.fn() +// @ts-ignore +export class AtemSocketChildMock implements AtemSocketChild { + public onDisconnect: () => Promise + public onLog: (message: string) => Promise + public onCommandsReceived: (payload: Buffer, packetId: number) => Promise + public onCommandsAcknowledged: (ids: Array<{ packetId: number, trackingId: number }>) => Promise + + constructor () { + // this._debug = options.debug + // this._address = options.address + // this._port = options.port + + this.onDisconnect = () => Promise.resolve() + this.onLog = () => Promise.resolve() + this.onCommandsReceived = () => Promise.resolve() + this.onCommandsAcknowledged = () => Promise.resolve() + } + + public restartConnection () { + return Promise.resolve() + } + public log (message: string) { + console.log(message) + } + + public connect = jest.fn(() => Promise.resolve()) + public disconnect = jest.fn(() => Promise.resolve()) + public sendCommands = jest.fn(() => Promise.resolve()) } const AtemSocketChildSingleton = new AtemSocketChildMock() -;(AtemSocketChild as any).mockImplementation((_opts: any, onDisconnect: () => Promise, onLog: (message: string) => Promise, onCommandReceived: (payload: Buffer, packetId: number) => Promise, onCommandAcknowledged: (packetId: number, trackingId: number) => Promise) => { +;(AtemSocketChild as any).mockImplementation((_opts: any, onDisconnect: () => Promise, onLog: (message: string) => Promise, onCommandsReceived: (payload: Buffer, packetId: number) => Promise, onCommandsAcknowledged: (ids: Array<{ packetId: number, trackingId: number }>) => Promise) => { AtemSocketChildSingleton.onDisconnect = onDisconnect AtemSocketChildSingleton.onLog = onLog - AtemSocketChildSingleton.onCommandReceived = onCommandReceived - AtemSocketChildSingleton.onCommandAcknowledged = onCommandAcknowledged + AtemSocketChildSingleton.onCommandsReceived = onCommandsReceived + AtemSocketChildSingleton.onCommandsAcknowledged = onCommandsAcknowledged return AtemSocketChildSingleton }) @@ -61,10 +69,10 @@ describe('AtemSocket', () => { AtemSocketChildSingleton.sendCommands.mockClear() if (!lite) { - AtemSocketChildSingleton.onLog = undefined - AtemSocketChildSingleton.onDisconnect = undefined - AtemSocketChildSingleton.onCommandAcknowledged = undefined - AtemSocketChildSingleton.onCommandReceived = undefined + AtemSocketChildSingleton.onLog = () => Promise.resolve() + AtemSocketChildSingleton.onDisconnect = () => Promise.resolve() + AtemSocketChildSingleton.onCommandsAcknowledged = () => Promise.resolve() + AtemSocketChildSingleton.onCommandsReceived = () => Promise.resolve() } } beforeEach(() => { @@ -294,18 +302,18 @@ describe('AtemSocket', () => { const ack = jest.fn() socket.on('disconnect', disconnect) - socket.on('commandAck', ack) + socket.on('commandsAck', ack) expect(AtemSocketChildSingleton.onDisconnect).toBeDefined() - await AtemSocketChildSingleton.onDisconnect!() + await AtemSocketChildSingleton.onDisconnect() await clock.tickAsync(0) expect(disconnect).toHaveBeenCalledTimes(1) - expect(AtemSocketChildSingleton.onCommandAcknowledged).toBeDefined() - await AtemSocketChildSingleton.onCommandAcknowledged!(675, 98) + expect(AtemSocketChildSingleton.onCommandsAcknowledged).toBeDefined() + await AtemSocketChildSingleton.onCommandsAcknowledged([{ packetId: 675, trackingId: 98 }]) await clock.tickAsync(0) expect(ack).toHaveBeenCalledTimes(1) - expect(ack).toHaveBeenCalledWith(98) + expect(ack).toHaveBeenCalledWith([98]) }) @@ -317,13 +325,11 @@ describe('AtemSocket', () => { mockClear(true) expect(getChild(socket)).toBeTruthy() - const connect = jest.fn() const error = jest.fn() const change = jest.fn() - socket.on('connect', connect) socket.on('error', error) - socket.on('commandReceived', change) + socket.on('commandsReceived', change) const parser = (socket as any)._commandParser as CommandParser expect(parser).toBeTruthy() @@ -331,20 +337,14 @@ describe('AtemSocket', () => { const testBuffer = Buffer.from([0, 8, 0, 0, ...Buffer.from('InCm', 'ascii')]) const pktId = 822 - expect(AtemSocketChildSingleton.onCommandReceived).toBeDefined() - await AtemSocketChildSingleton.onCommandReceived!(testBuffer, pktId) + expect(AtemSocketChildSingleton.onCommandsReceived).toBeDefined() + await AtemSocketChildSingleton.onCommandsReceived(testBuffer, pktId) await clock.tickAsync(0) - expect(connect).toHaveBeenCalledTimes(1) expect(error).toHaveBeenCalledTimes(0) - expect(change).toHaveBeenCalledTimes(1) - - expect(parserSpy).toHaveBeenCalledTimes(1) - expect(parserSpy).toHaveBeenCalledWith('InCm') + expect(change).toHaveBeenCalledTimes(0) - // A change with the command - const expectedCmd = new InitCompleteCommand() - expect(change).toHaveBeenCalledWith(expectedCmd) + expect(parserSpy).toHaveBeenCalledTimes(0) }) test('receive - protocol version', async () => { const socket = createSocket() @@ -354,13 +354,11 @@ describe('AtemSocket', () => { mockClear(true) expect(getChild(socket)).toBeTruthy() - const connect = jest.fn() const error = jest.fn() const change = jest.fn() - socket.on('connect', connect) socket.on('error', error) - socket.on('commandReceived', change) + socket.on('commandsReceived', change) const parser = (socket as any)._commandParser as CommandParser expect(parser).toBeTruthy() @@ -369,11 +367,10 @@ describe('AtemSocket', () => { const testBuffer = Buffer.from([0, 12, 0, 0, ...Buffer.from('_ver', 'ascii'), 0x01, 0x02, 0x03, 0x04]) const pktId = 822 - expect(AtemSocketChildSingleton.onCommandReceived).toBeDefined() - await AtemSocketChildSingleton.onCommandReceived!(testBuffer, pktId) + expect(AtemSocketChildSingleton.onCommandsReceived).toBeDefined() + await AtemSocketChildSingleton.onCommandsReceived(testBuffer, pktId) await clock.tickAsync(0) - expect(connect).toHaveBeenCalledTimes(0) expect(error).toHaveBeenCalledTimes(0) expect(change).toHaveBeenCalledTimes(1) @@ -384,7 +381,7 @@ describe('AtemSocket', () => { // A change with the command const expectedCmd = new VersionCommand(0x01020304) - expect(change).toHaveBeenCalledWith(expectedCmd) + expect(change).toHaveBeenCalledWith([expectedCmd]) }) test('receive - multiple commands', async () => { const socket = createSocket() @@ -394,13 +391,11 @@ describe('AtemSocket', () => { mockClear(true) expect(getChild(socket)).toBeTruthy() - const connect = jest.fn() const error = jest.fn() const change = jest.fn() - socket.on('connect', connect) socket.on('error', error) - socket.on('commandReceived', change) + socket.on('commandsReceived', change) const parser = (socket as any)._commandParser as CommandParser expect(parser).toBeTruthy() @@ -413,21 +408,19 @@ describe('AtemSocket', () => { const testCmd1 = Buffer.from([0, 12, 0, 0, ...Buffer.from(ProgramInputUpdateCommand.rawName, 'ascii'), 0x00, 0x00, 0x01, 0x23]) const testCmd2 = Buffer.from([0, 12, 0, 0, ...Buffer.from(PreviewInputUpdateCommand.rawName, 'ascii'), 0x01, 0x00, 0x04, 0x44]) const pktId = 822 - expect(AtemSocketChildSingleton.onCommandReceived).toBeDefined() - await AtemSocketChildSingleton.onCommandReceived!(Buffer.concat([testCmd1, testCmd2]), pktId) + expect(AtemSocketChildSingleton.onCommandsReceived).toBeDefined() + await AtemSocketChildSingleton.onCommandsReceived(Buffer.concat([testCmd1, testCmd2]), pktId) await clock.tickAsync(0) - expect(connect).toHaveBeenCalledTimes(0) expect(error).toHaveBeenCalledTimes(0) - expect(change).toHaveBeenCalledTimes(2) + expect(change).toHaveBeenCalledTimes(1) expect(parserSpy).toHaveBeenCalledTimes(2) expect(parserSpy).toHaveBeenCalledWith(ProgramInputUpdateCommand.rawName) expect(parserSpy).toHaveBeenCalledWith(PreviewInputUpdateCommand.rawName) // A change with the command - expect(change).toHaveBeenCalledWith(expectedCmd1) - expect(change).toHaveBeenCalledWith(expectedCmd2) + expect(change).toHaveBeenCalledWith([expectedCmd1, expectedCmd2]) }) test('receive - empty buffer', async () => { const socket = createSocket() @@ -437,21 +430,18 @@ describe('AtemSocket', () => { mockClear(true) expect(getChild(socket)).toBeTruthy() - const connect = jest.fn() const error = jest.fn() const change = jest.fn() - socket.on('connect', connect) socket.on('error', error) - socket.on('commandReceived', change) + socket.on('commandsReceived', change) const testBuffer = Buffer.alloc(0) const pktId = 822 - expect(AtemSocketChildSingleton.onCommandReceived).toBeDefined() - await AtemSocketChildSingleton.onCommandReceived!(testBuffer, pktId) + expect(AtemSocketChildSingleton.onCommandsReceived).toBeDefined() + await AtemSocketChildSingleton.onCommandsReceived(testBuffer, pktId) await clock.tickAsync(0) - expect(connect).toHaveBeenCalledTimes(0) expect(error).toHaveBeenCalledTimes(0) expect(change).toHaveBeenCalledTimes(0) }) @@ -463,21 +453,18 @@ describe('AtemSocket', () => { mockClear(true) expect(getChild(socket)).toBeTruthy() - const connect = jest.fn() const error = jest.fn() const change = jest.fn() - socket.on('connect', connect) socket.on('error', error) - socket.on('commandReceived', change) + socket.on('commandsReceived', change) const testBuffer = Buffer.alloc(10, 0) const pktId = 822 - expect(AtemSocketChildSingleton.onCommandReceived).toBeDefined() - await AtemSocketChildSingleton.onCommandReceived!(testBuffer, pktId) + expect(AtemSocketChildSingleton.onCommandsReceived).toBeDefined() + await AtemSocketChildSingleton.onCommandsReceived(testBuffer, pktId) await clock.tickAsync(0) - expect(connect).toHaveBeenCalledTimes(0) expect(error).toHaveBeenCalledTimes(0) expect(change).toHaveBeenCalledTimes(0) }) @@ -489,13 +476,11 @@ describe('AtemSocket', () => { mockClear(true) expect(getChild(socket)).toBeTruthy() - const connect = jest.fn() const error = jest.fn() const change = jest.fn() - socket.on('connect', connect) socket.on('error', error) - socket.on('commandReceived', change) + socket.on('commandsReceived', change) class BrokenCommand extends DeserializedCommand<{}> { public static readonly rawName = 'TEST' @@ -519,11 +504,10 @@ describe('AtemSocket', () => { const testCmd1 = Buffer.from([0, 12, 0, 0, ...Buffer.from(ProgramInputUpdateCommand.rawName, 'ascii'), 0x00, 0x00, 0x01, 0x23]) const testCmd2 = Buffer.from([0, 12, 0, 0, ...Buffer.from(PreviewInputUpdateCommand.rawName, 'ascii'), 0x01, 0x00, 0x04, 0x44]) const pktId = 822 - expect(AtemSocketChildSingleton.onCommandReceived).toBeDefined() - await AtemSocketChildSingleton.onCommandReceived!(Buffer.concat([testCmd1, testCmd2]), pktId) + expect(AtemSocketChildSingleton.onCommandsReceived).toBeDefined() + await AtemSocketChildSingleton.onCommandsReceived(Buffer.concat([testCmd1, testCmd2]), pktId) await clock.tickAsync(0) - expect(connect).toHaveBeenCalledTimes(0) expect(error).toHaveBeenCalledTimes(1) expect(change).toHaveBeenCalledTimes(1) @@ -532,7 +516,7 @@ describe('AtemSocket', () => { expect(parserSpy).toHaveBeenCalledWith(PreviewInputUpdateCommand.rawName) // The second command should have been a success - expect(change).toHaveBeenCalledWith(expectedCmd2) + expect(change).toHaveBeenCalledWith([expectedCmd2]) expect(error).toHaveBeenCalledWith('Failed to deserialize command: BrokenCommand: Error: Broken command') }) diff --git a/src/lib/__tests__/socket-child.spec.ts b/src/lib/__tests__/socket-child.spec.ts index 5d49eb7e6..0538a6662 100644 --- a/src/lib/__tests__/socket-child.spec.ts +++ b/src/lib/__tests__/socket-child.spec.ts @@ -30,8 +30,8 @@ function fakeConnect (child: AtemSocketChild) { } function createSocketChild ( - onCommandReceived?: (payload: Buffer, packetId: number) => Promise, - onCommandAcknowledged?: (packetId: number, trackingId: number) => Promise, + onCommandsReceived?: (payload: Buffer, packetId: number) => Promise, + onCommandsAcknowledged?: (ids: Array<{ packetId: number, trackingId: number }>) => Promise, onDisconnect?: () => Promise ) { return new AtemSocketChild( @@ -43,8 +43,8 @@ function createSocketChild ( onDisconnect || (() => Promise.resolve()), // async msg => { console.log(msg) }, () => Promise.resolve(), - onCommandReceived || (() => Promise.resolve()), - onCommandAcknowledged || (() => Promise.resolve()) + onCommandsReceived || (() => Promise.resolve()), + onCommandsAcknowledged || (() => Promise.resolve()) ) } @@ -428,10 +428,7 @@ describe('SocketChild', () => { test('SendCommand - acks', async () => { let acked: Array<{packetId: number, trackingId: number}> = [] - const child = createSocketChild(undefined, (packetId, trackingId) => { - acked.push({ packetId, trackingId }) - return Promise.resolve() - }) + const child = createSocketChild(undefined, async ids => { acked.push(...ids) }) try { fakeConnect(child) const socket = getSocket(child) @@ -494,10 +491,7 @@ describe('SocketChild', () => { test('SendCommand - acks wrap', async () => { let acked: Array<{packetId: number, trackingId: number}> = [] - const child = createSocketChild(undefined, (packetId, trackingId) => { - acked.push({ packetId, trackingId }) - return Promise.resolve() - }) + const child = createSocketChild(undefined, async ids => { acked.push(...ids) }) try { fakeConnect(child) const socket = getSocket(child) @@ -561,10 +555,7 @@ describe('SocketChild', () => { test('SendCommand - retransmit timeouts', async () => { let acked: Array<{packetId: number, trackingId: number}> = [] - const child = createSocketChild(undefined, (packetId, trackingId) => { - acked.push({ packetId, trackingId }) - return Promise.resolve() - }) + const child = createSocketChild(undefined, async ids => { acked.push(...ids) }) try { fakeConnect(child) const socket = getSocket(child) @@ -655,10 +646,7 @@ describe('SocketChild', () => { test('SendCommand - retransmit request', async () => { let acked: Array<{packetId: number, trackingId: number}> = [] - const child = createSocketChild(undefined, (packetId, trackingId) => { - acked.push({ packetId, trackingId }) - return Promise.resolve() - }) + const child = createSocketChild(undefined, async ids => { acked.push(...ids) }) try { fakeConnect(child) const socket = getSocket(child) @@ -722,10 +710,7 @@ describe('SocketChild', () => { test('SendCommand - retransmit request future', async () => { const acked: Array<{packetId: number, trackingId: number}> = [] let connected = true - const child = createSocketChild(undefined, (packetId, trackingId) => { - acked.push({ packetId, trackingId }) - return Promise.resolve() - }, async () => { connected = false }) + const child = createSocketChild(undefined, async ids => { acked.push(...ids) }, async () => { connected = false }) try { fakeConnect(child) const socket = getSocket(child) @@ -759,10 +744,7 @@ describe('SocketChild', () => { test('SendCommand - retransmit request previous', async () => { const acked: Array<{packetId: number, trackingId: number}> = [] let connected = true - const child = createSocketChild(undefined, (packetId, trackingId) => { - acked.push({ packetId, trackingId }) - return Promise.resolve() - }, async () => { connected = false }) + const child = createSocketChild(undefined, async ids => { acked.push(...ids) }, async () => { connected = false }) try { fakeConnect(child) const socket = getSocket(child) @@ -796,10 +778,7 @@ describe('SocketChild', () => { test('Reconnect timer', async () => { let acked: Array<{packetId: number, trackingId: number}> = [] let connected = true - const child = createSocketChild(undefined, (packetId, trackingId) => { - acked.push({ packetId, trackingId }) - return Promise.resolve() - }, async () => { connected = false }) + const child = createSocketChild(undefined, async ids => { acked.push(...ids) }, async () => { connected = false }) try { fakeConnect(child) const socket = getSocket(child) diff --git a/src/lib/atemSocket.ts b/src/lib/atemSocket.ts index 8d374fe21..bd8d95e17 100644 --- a/src/lib/atemSocket.ts +++ b/src/lib/atemSocket.ts @@ -29,16 +29,14 @@ export class AtemSocket extends EventEmitter { private readonly log: (args1: any, args2?: any, args3?: any) => void public on!: ((event: 'disconnect', listener: () => void) => this) & - ((event: 'connect', listener: () => void) => this) & ((event: 'error', listener: (message: string) => void) => this) & - ((event: 'commandReceived', listener: (cmd: IDeserializedCommand) => void) => this) & - ((event: 'commandAck', listener: (trackingId: number) => void) => this) + ((event: 'commandsReceived', listener: (cmds: IDeserializedCommand[]) => void) => this) & + ((event: 'commandsAck', listener: (trackingIds: number[]) => void) => this) public emit!: ((event: 'disconnect') => boolean) & - ((event: 'connect') => boolean) & ((event: 'error', message: string) => boolean) & - ((event: 'commandReceived', cmd: IDeserializedCommand) => boolean) & - ((event: 'commandAck', trackingId: number) => boolean) + ((event: 'commandsReceived', cmds: IDeserializedCommand[]) => boolean) & + ((event: 'commandsAck', trackingIds: number[]) => boolean) constructor (options: AtemSocketOptions) { super() @@ -122,8 +120,8 @@ export class AtemSocket extends EventEmitter { }, async () => { this.emit('disconnect') }, // onDisconnect async (message: string) => this.log(message), // onLog - async (payload: Buffer) => this._parseCommand(Buffer.from(payload)), // onCommandReceived - async (_packetId: number, trackingId: number) => { this.emit('commandAck', trackingId) } // onCommandAcknowledged + async (payload: Buffer) => this._parseCommands(Buffer.from(payload)), // onCommandsReceived + async (ids: Array<{ packetId: number, trackingId: number }>) => { this.emit('commandsAck', ids.map(id => id.trackingId)) } // onCommandsAcknowledged ], { instanceName: 'atem-connection', freezeLimit: 200, @@ -144,43 +142,40 @@ export class AtemSocket extends EventEmitter { return socketProcess } - private _parseCommand (buffer: Buffer) { - if (buffer.length < 8) { - // Commands are never less than 8, as that is the header - return - } + private _parseCommands (buffer: Buffer) { + const parsedCommands: IDeserializedCommand[] = [] - const length = buffer.readUInt16BE(0) - const name = buffer.toString('ascii', 4, 8) + while (buffer.length > 8) { + const length = buffer.readUInt16BE(0) + const name = buffer.toString('ascii', 4, 8) - if (length < 8) { - // Commands are never less than 8, as that is the header - return - } + if (length < 8) { + // Commands are never less than 8, as that is the header + break + } - if (name === 'InCm') { - this.emit('connect') - } + const cmdConstructor = this._commandParser.commandFromRawName(name) + if (cmdConstructor && typeof cmdConstructor.deserialize === 'function') { + try { + const cmd: IDeserializedCommand = cmdConstructor.deserialize(buffer.slice(0, length).slice(8), this._commandParser.version) - // this.log('COMMAND', `${name}(${length})`, buffer.slice(0, length)) - const cmdConstructor = this._commandParser.commandFromRawName(name) - if (cmdConstructor && typeof cmdConstructor.deserialize === 'function') { - try { - const cmd: IDeserializedCommand = cmdConstructor.deserialize(buffer.slice(0, length).slice(8), this._commandParser.version) + if (cmdConstructor.name === VersionCommand.name) { // init started + const verCmd = cmd as VersionCommand + this._commandParser.version = verCmd.properties.version + } - if (name === '_ver') { // init started - const verCmd = cmd as VersionCommand - this._commandParser.version = verCmd.properties.version + parsedCommands.push(cmd) + } catch (e) { + this.emit('error', `Failed to deserialize command: ${cmdConstructor.constructor.name}: ${e}`) } + } // TODO - log the unknown command? - this.emit('commandReceived', cmd) - } catch (e) { - this.emit('error', `Failed to deserialize command: ${cmdConstructor.constructor.name}: ${e}`) - } - } // TODO - log the unknown command? + // Trim the buffer + buffer = buffer.slice(length) + } - if (buffer.length > length) { - this._parseCommand(buffer.slice(length)) + if (parsedCommands.length > 0) { + this.emit('commandsReceived', parsedCommands) } } } diff --git a/src/lib/atemSocketChild.ts b/src/lib/atemSocketChild.ts index da0ad9654..8fb9a7749 100644 --- a/src/lib/atemSocketChild.ts +++ b/src/lib/atemSocketChild.ts @@ -54,18 +54,18 @@ export class AtemSocketChild { private readonly onDisconnect: () => Promise private readonly onLog: (message: string) => Promise - private readonly onCommandReceived: (payload: Buffer, packetId: number) => Promise - private readonly onCommandAcknowledged: (packetId: number, trackingId: number) => Promise + private readonly onCommandsReceived: (payload: Buffer, packetId: number) => Promise + private readonly onCommandsAcknowledged: (ids: Array<{ packetId: number, trackingId: number }>) => Promise - constructor (options: { address: string, port: number, debug: boolean }, onDisconnect: () => Promise, onLog: (message: string) => Promise, onCommandReceived: (payload: Buffer, packetId: number) => Promise, onCommandAcknowledged: (packetId: number, trackingId: number) => Promise) { + constructor (options: { address: string, port: number, debug: boolean }, onDisconnect: () => Promise, onLog: (message: string) => Promise, onCommandReceived: (payload: Buffer, packetId: number) => Promise, onCommandAcknowledged: (ids: Array<{ packetId: number, trackingId: number }>) => Promise) { this._debug = options.debug this._address = options.address this._port = options.port this.onDisconnect = onDisconnect this.onLog = onLog - this.onCommandReceived = onCommandReceived - this.onCommandAcknowledged = onCommandAcknowledged + this.onCommandsReceived = onCommandReceived + this.onCommandsAcknowledged = onCommandAcknowledged this._socket = this._createSocket() } @@ -244,7 +244,7 @@ export class AtemSocketChild { // It might have commands if (length > 12) { - ps.push(this.onCommandReceived(packet.slice(12), remotePacketId)) + ps.push(this.onCommandsReceived(packet.slice(12), remotePacketId)) } } else if (this._isPacketCoveredByAck(this._lastReceivedPacketId, remotePacketId)) { // We got a retransmit of something we have already acked, so reack it @@ -255,15 +255,20 @@ export class AtemSocketChild { // Device ack'ed our packet if (flags & PacketFlag.AckReply) { const ackPacketId = packet.readUInt16BE(4) + const ackedCommands: Array<{ packetId: number, trackingId: number }> = [] this._inFlight = this._inFlight.filter(pkt => { if (this._isPacketCoveredByAck(ackPacketId, pkt.packetId)) { - ps.push(this.onCommandAcknowledged(pkt.packetId, pkt.trackingId)) + ackedCommands.push({ + packetId: pkt.packetId, + trackingId: pkt.trackingId + }) return false } else { // Not acked yet return true } }) + ps.push(this.onCommandsAcknowledged(ackedCommands)) // this.log(`${Date.now()} Got ack ${ackPacketId} Remaining=${this._inFlight.length}`) } } diff --git a/src/state/index.ts b/src/state/index.ts index 10e809eac..86e7a2d4c 100644 --- a/src/state/index.ts +++ b/src/state/index.ts @@ -11,7 +11,7 @@ export class AtemState { public video: AtemVideoState = new AtemVideoState() public audio: AtemAudioState = new AtemAudioState() public media: MediaState = new MediaState() - public inputs: Array = [] + public inputs: Array = [] // TODO should this be `| undefined` or an object? public macro: MacroState = new MacroState() public settings: SettingsState = new SettingsState() } diff --git a/src/state/macro.ts b/src/state/macro.ts index cfcbb59ed..7c9e26811 100644 --- a/src/state/macro.ts +++ b/src/state/macro.ts @@ -20,7 +20,7 @@ export interface MacroPropertiesState { export class MacroState { public macroPlayer: MacroPlayerState public macroRecorder: MacroRecorderState - public readonly macroProperties: Array = [] + public readonly macroProperties: Array = [] constructor () { this.macroPlayer = { From 137d135bc73b5bf68ef6907ba55f0cb4465eb620 Mon Sep 17 00:00:00 2001 From: Julian Waller Date: Tue, 10 Dec 2019 21:12:03 +0000 Subject: [PATCH 54/68] feat: parse some more deviceprofile commands --- src/__tests__/util.ts | 8 ++-- .../DeviceProfile/audioMixerConfigCommand.ts | 23 +++++++++++ src/commands/DeviceProfile/index.ts | 4 ++ .../DeviceProfile/macroPoolConfigCommand.ts | 22 ++++++++++ .../DeviceProfile/mediaPoolConfigCommand.ts | 23 +++++++++++ .../mixEffectBlockConfigCommand.ts | 24 +++++++++++ src/commands/DeviceProfile/topologyCommand.ts | 20 +++++++--- src/commands/__tests__/data-v7.2.json | 40 +++++++++---------- src/commands/__tests__/data-v8.0.json | 40 +++++++++---------- src/commands/__tests__/index.spec.ts | 10 ++++- src/commands/__tests__/v8.0.spec.ts | 2 - src/lib/atemSocketChild.ts | 2 +- src/state/info.ts | 32 ++++++++++++--- 13 files changed, 190 insertions(+), 60 deletions(-) create mode 100644 src/commands/DeviceProfile/audioMixerConfigCommand.ts create mode 100644 src/commands/DeviceProfile/macroPoolConfigCommand.ts create mode 100644 src/commands/DeviceProfile/mediaPoolConfigCommand.ts create mode 100644 src/commands/DeviceProfile/mixEffectBlockConfigCommand.ts diff --git a/src/__tests__/util.ts b/src/__tests__/util.ts index 119111a46..7d392e259 100644 --- a/src/__tests__/util.ts +++ b/src/__tests__/util.ts @@ -36,19 +36,19 @@ export function createEmptyState () { state.info.capabilities = { mixEffects: 4, sources: 40, - colorGenerators: 2, auxilliaries: 6, - talkbackOutputs: 8, + mixMinusOutputs: 8, mediaPlayers: 4, serialPorts: 1, maxHyperdecks: 4, DVEs: 1, stingers: 1, superSources: 2, - talkbackOverSDI: 0, + // talkbackOverSDI: 0, multiViewers: 255, downstreamKeyers: 4, - upstreamKeyers: 4 + cameraControl: true, + advancedChromaKeyers: true } return state diff --git a/src/commands/DeviceProfile/audioMixerConfigCommand.ts b/src/commands/DeviceProfile/audioMixerConfigCommand.ts new file mode 100644 index 000000000..ba4922a5c --- /dev/null +++ b/src/commands/DeviceProfile/audioMixerConfigCommand.ts @@ -0,0 +1,23 @@ +import { DeserializedCommand } from '../CommandBase' +import { AtemState } from '../../state' +import { AudioMixerInfo } from '../../state/info' + +export class AudioMixerConfigCommand extends DeserializedCommand { + public static readonly rawName = '_AMC' + + constructor (properties: AudioMixerInfo) { + super(properties) + } + + public static deserialize (rawCommand: Buffer): AudioMixerConfigCommand { + return new AudioMixerConfigCommand({ + inputs: rawCommand.readUInt8(0), + monitors: rawCommand.readUInt8(1) + }) + } + + public applyToState (state: AtemState) { + state.info.audioMixer = this.properties + return `info.audioMixer` + } +} diff --git a/src/commands/DeviceProfile/index.ts b/src/commands/DeviceProfile/index.ts index 9f39e9a62..467288264 100644 --- a/src/commands/DeviceProfile/index.ts +++ b/src/commands/DeviceProfile/index.ts @@ -2,3 +2,7 @@ export * from './versionCommand' export * from './topologyCommand' export * from './productIdentifierCommand' export * from './superSourceConfigCommand' +export * from './audioMixerConfigCommand' +export * from './macroPoolConfigCommand' +export * from './mediaPoolConfigCommand' +export * from './mixEffectBlockConfigCommand' diff --git a/src/commands/DeviceProfile/macroPoolConfigCommand.ts b/src/commands/DeviceProfile/macroPoolConfigCommand.ts new file mode 100644 index 000000000..501080ddf --- /dev/null +++ b/src/commands/DeviceProfile/macroPoolConfigCommand.ts @@ -0,0 +1,22 @@ +import { DeserializedCommand } from '../CommandBase' +import { AtemState } from '../../state' +import { MacroPoolInfo } from '../../state/info' + +export class MacroPoolConfigCommand extends DeserializedCommand { + public static readonly rawName = '_MAC' + + constructor (properties: MacroPoolInfo) { + super(properties) + } + + public static deserialize (rawCommand: Buffer): MacroPoolConfigCommand { + return new MacroPoolConfigCommand({ + macroCount: rawCommand.readUInt8(0) + }) + } + + public applyToState (state: AtemState) { + state.info.macroPool = this.properties + return `info.macroPool` + } +} diff --git a/src/commands/DeviceProfile/mediaPoolConfigCommand.ts b/src/commands/DeviceProfile/mediaPoolConfigCommand.ts new file mode 100644 index 000000000..2abc8809b --- /dev/null +++ b/src/commands/DeviceProfile/mediaPoolConfigCommand.ts @@ -0,0 +1,23 @@ +import { DeserializedCommand } from '../CommandBase' +import { AtemState } from '../../state' +import { MediaPoolInfo } from '../../state/info' + +export class MediaPoolConfigCommand extends DeserializedCommand { + public static readonly rawName = '_mpl' + + constructor (properties: MediaPoolInfo) { + super(properties) + } + + public static deserialize (rawCommand: Buffer): MediaPoolConfigCommand { + return new MediaPoolConfigCommand({ + stillCount: rawCommand.readUInt8(0), + clipCount: rawCommand.readUInt8(1) + }) + } + + public applyToState (state: AtemState) { + state.info.mediaPool = this.properties + return `info.mediaPool` + } +} diff --git a/src/commands/DeviceProfile/mixEffectBlockConfigCommand.ts b/src/commands/DeviceProfile/mixEffectBlockConfigCommand.ts new file mode 100644 index 000000000..195ed0cd0 --- /dev/null +++ b/src/commands/DeviceProfile/mixEffectBlockConfigCommand.ts @@ -0,0 +1,24 @@ +import { DeserializedCommand } from '../CommandBase' +import { AtemState } from '../../state' +import { MixEffectInfo } from '../../state/info' + +export class MixEffectBlockConfigCommand extends DeserializedCommand { + public static readonly rawName = '_MeC' + + public readonly index: number + + constructor (index: number, properties: MixEffectInfo) { + super(properties) + + this.index = index + } + + public static deserialize (rawCommand: Buffer): MixEffectBlockConfigCommand { + return new MixEffectBlockConfigCommand(rawCommand.readUInt8(0), { keyCount: rawCommand.readUInt8(1) }) + } + + public applyToState (state: AtemState) { + state.info.mixEffects[this.index] = this.properties + return `info.mixEffects` + } +} diff --git a/src/commands/DeviceProfile/topologyCommand.ts b/src/commands/DeviceProfile/topologyCommand.ts index c1b90200c..d025c5218 100644 --- a/src/commands/DeviceProfile/topologyCommand.ts +++ b/src/commands/DeviceProfile/topologyCommand.ts @@ -9,21 +9,29 @@ export class TopologyCommand extends DeserializedCommand { const properties = { mixEffects: rawCommand.readUInt8(0), sources: rawCommand.readUInt8(1), - colorGenerators: rawCommand.readUInt8(2), + downstreamKeyers: rawCommand.readUInt8(2), auxilliaries: rawCommand.readUInt8(3), - talkbackOutputs: rawCommand.readUInt8(4), + mixMinusOutputs: rawCommand.readUInt8(4), mediaPlayers: rawCommand.readUInt8(5), serialPorts: rawCommand.readUInt8(6), maxHyperdecks: rawCommand.readUInt8(7), DVEs: rawCommand.readUInt8(8), stingers: rawCommand.readUInt8(9), superSources: rawCommand.readUInt8(10), - talkbackOverSDI: rawCommand.readUInt8(13), + // talkbackOverSDI: rawCommand.readUInt8(13), + + cameraControl: rawCommand.readUInt8(17) === 1, + + // Note: these are defined below as they can overflow in older firmwares + advancedChromaKeyers: false, // TODO - define the below properly - multiViewers: 2, - downstreamKeyers: 2, - upstreamKeyers: 2 + multiViewers: 2 + } + + // in 7.4? + if (rawCommand.length > 20) { + properties.advancedChromaKeyers = rawCommand.readUInt8(21) === 1 } return new TopologyCommand(properties) diff --git a/src/commands/__tests__/data-v7.2.json b/src/commands/__tests__/data-v7.2.json index 5135f6168..6e420c415 100644 --- a/src/commands/__tests__/data-v7.2.json +++ b/src/commands/__tests__/data-v7.2.json @@ -11523,9 +11523,9 @@ "command": { "MixEffectBlocks": 114, "VideoSources": 149, - "ColorGenerators": 135, + "DownstreamKeyers": 135, "Auxiliaries": 104, - "TalkbackOutputs": 46, + "mixMinusOutputs": 46, "MediaPlayers": 95, "SerialPort": 249, "HyperDecks": 56, @@ -11541,9 +11541,9 @@ "command": { "MixEffectBlocks": 125, "VideoSources": 163, - "ColorGenerators": 145, + "DownstreamKeyers": 145, "Auxiliaries": 142, - "TalkbackOutputs": 172, + "mixMinusOutputs": 172, "MediaPlayers": 181, "SerialPort": 63, "HyperDecks": 248, @@ -11559,9 +11559,9 @@ "command": { "MixEffectBlocks": 67, "VideoSources": 89, - "ColorGenerators": 204, + "DownstreamKeyers": 204, "Auxiliaries": 108, - "TalkbackOutputs": 128, + "mixMinusOutputs": 128, "MediaPlayers": 148, "SerialPort": 132, "HyperDecks": 197, @@ -11577,9 +11577,9 @@ "command": { "MixEffectBlocks": 16, "VideoSources": 4, - "ColorGenerators": 145, + "DownstreamKeyers": 145, "Auxiliaries": 39, - "TalkbackOutputs": 142, + "mixMinusOutputs": 142, "MediaPlayers": 10, "SerialPort": 175, "HyperDecks": 119, @@ -11595,9 +11595,9 @@ "command": { "MixEffectBlocks": 164, "VideoSources": 126, - "ColorGenerators": 194, + "DownstreamKeyers": 194, "Auxiliaries": 200, - "TalkbackOutputs": 188, + "mixMinusOutputs": 188, "MediaPlayers": 155, "SerialPort": 79, "HyperDecks": 11, @@ -11613,9 +11613,9 @@ "command": { "MixEffectBlocks": 146, "VideoSources": 141, - "ColorGenerators": 183, + "DownstreamKeyers": 183, "Auxiliaries": 23, - "TalkbackOutputs": 244, + "mixMinusOutputs": 244, "MediaPlayers": 27, "SerialPort": 251, "HyperDecks": 214, @@ -11631,9 +11631,9 @@ "command": { "MixEffectBlocks": 35, "VideoSources": 23, - "ColorGenerators": 105, + "DownstreamKeyers": 105, "Auxiliaries": 118, - "TalkbackOutputs": 181, + "mixMinusOutputs": 181, "MediaPlayers": 84, "SerialPort": 231, "HyperDecks": 17, @@ -11649,9 +11649,9 @@ "command": { "MixEffectBlocks": 208, "VideoSources": 187, - "ColorGenerators": 9, + "DownstreamKeyers": 9, "Auxiliaries": 17, - "TalkbackOutputs": 86, + "mixMinusOutputs": 86, "MediaPlayers": 115, "SerialPort": 88, "HyperDecks": 85, @@ -11667,9 +11667,9 @@ "command": { "MixEffectBlocks": 82, "VideoSources": 151, - "ColorGenerators": 130, + "DownstreamKeyers": 130, "Auxiliaries": 200, - "TalkbackOutputs": 54, + "mixMinusOutputs": 54, "MediaPlayers": 25, "SerialPort": 171, "HyperDecks": 52, @@ -11685,9 +11685,9 @@ "command": { "MixEffectBlocks": 50, "VideoSources": 215, - "ColorGenerators": 85, + "DownstreamKeyers": 85, "Auxiliaries": 115, - "TalkbackOutputs": 210, + "mixMinusOutputs": 210, "MediaPlayers": 19, "SerialPort": 107, "HyperDecks": 149, diff --git a/src/commands/__tests__/data-v8.0.json b/src/commands/__tests__/data-v8.0.json index 4e697693d..fd425c401 100644 --- a/src/commands/__tests__/data-v8.0.json +++ b/src/commands/__tests__/data-v8.0.json @@ -1285,9 +1285,9 @@ "command": { "MixEffectBlocks": 86, "VideoSources": 175, - "ColorGenerators": 134, + "DownstreamKeyers": 134, "Auxiliaries": 183, - "TalkbackOutputs": 224, + "mixMinusOutputs": 224, "MediaPlayers": 11, "SerialPort": 132, "HyperDecks": 1, @@ -1303,9 +1303,9 @@ "command": { "MixEffectBlocks": 7, "VideoSources": 73, - "ColorGenerators": 251, + "DownstreamKeyers": 251, "Auxiliaries": 205, - "TalkbackOutputs": 126, + "mixMinusOutputs": 126, "MediaPlayers": 110, "SerialPort": 249, "HyperDecks": 131, @@ -1321,9 +1321,9 @@ "command": { "MixEffectBlocks": 41, "VideoSources": 187, - "ColorGenerators": 80, + "DownstreamKeyers": 80, "Auxiliaries": 20, - "TalkbackOutputs": 19, + "mixMinusOutputs": 19, "MediaPlayers": 193, "SerialPort": 134, "HyperDecks": 107, @@ -1339,9 +1339,9 @@ "command": { "MixEffectBlocks": 60, "VideoSources": 200, - "ColorGenerators": 202, + "DownstreamKeyers": 202, "Auxiliaries": 251, - "TalkbackOutputs": 89, + "mixMinusOutputs": 89, "MediaPlayers": 222, "SerialPort": 111, "HyperDecks": 60, @@ -1357,9 +1357,9 @@ "command": { "MixEffectBlocks": 42, "VideoSources": 143, - "ColorGenerators": 159, + "DownstreamKeyers": 159, "Auxiliaries": 240, - "TalkbackOutputs": 145, + "mixMinusOutputs": 145, "MediaPlayers": 52, "SerialPort": 23, "HyperDecks": 77, @@ -1375,9 +1375,9 @@ "command": { "MixEffectBlocks": 185, "VideoSources": 111, - "ColorGenerators": 237, + "DownstreamKeyers": 237, "Auxiliaries": 72, - "TalkbackOutputs": 107, + "mixMinusOutputs": 107, "MediaPlayers": 123, "SerialPort": 7, "HyperDecks": 230, @@ -1393,9 +1393,9 @@ "command": { "MixEffectBlocks": 162, "VideoSources": 253, - "ColorGenerators": 42, + "DownstreamKeyers": 42, "Auxiliaries": 242, - "TalkbackOutputs": 152, + "mixMinusOutputs": 152, "MediaPlayers": 17, "SerialPort": 144, "HyperDecks": 92, @@ -1411,9 +1411,9 @@ "command": { "MixEffectBlocks": 34, "VideoSources": 149, - "ColorGenerators": 217, + "DownstreamKeyers": 217, "Auxiliaries": 157, - "TalkbackOutputs": 8, + "mixMinusOutputs": 8, "MediaPlayers": 111, "SerialPort": 201, "HyperDecks": 103, @@ -1429,9 +1429,9 @@ "command": { "MixEffectBlocks": 240, "VideoSources": 39, - "ColorGenerators": 207, + "DownstreamKeyers": 207, "Auxiliaries": 164, - "TalkbackOutputs": 196, + "mixMinusOutputs": 196, "MediaPlayers": 182, "SerialPort": 203, "HyperDecks": 89, @@ -1447,9 +1447,9 @@ "command": { "MixEffectBlocks": 10, "VideoSources": 36, - "ColorGenerators": 180, + "DownstreamKeyers": 180, "Auxiliaries": 80, - "TalkbackOutputs": 67, + "mixMinusOutputs": 67, "MediaPlayers": 48, "SerialPort": 7, "HyperDecks": 192, diff --git a/src/commands/__tests__/index.spec.ts b/src/commands/__tests__/index.spec.ts index 3918cbdae..7dfeee987 100644 --- a/src/commands/__tests__/index.spec.ts +++ b/src/commands/__tests__/index.spec.ts @@ -264,12 +264,18 @@ const commandConverters: CommandTestConverterSet = { 'talkbackOverSDI': () => ({ val: 0 }) // @todo: should be fixed in atem-connection }, customMutate: obj => { - obj.downstreamKeyers = 2 obj.multiViewers = 2 - obj.upstreamKeyers = 2 return obj } }, + '_MeC': { + idAliases: { + 'index': 'index' + }, + propertyAliases: { + 'balance': (v: number) => ({ val: Math.round(v * 200) / 200 }) + } + }, 'FTCD': { idAliases: {}, propertyAliases: {}, diff --git a/src/commands/__tests__/v8.0.spec.ts b/src/commands/__tests__/v8.0.spec.ts index 9825a54a4..02ecc3646 100644 --- a/src/commands/__tests__/v8.0.spec.ts +++ b/src/commands/__tests__/v8.0.spec.ts @@ -34,9 +34,7 @@ const commandConverters: CommandTestConverterSet = { 'superSource': (val: any) => ({ val, name: 'superSources' }) }, customMutate: obj => { - obj.downstreamKeyers = 2 obj.multiViewers = 2 - obj.upstreamKeyers = 2 return obj } }, diff --git a/src/lib/atemSocketChild.ts b/src/lib/atemSocketChild.ts index 8fb9a7749..94fae3024 100644 --- a/src/lib/atemSocketChild.ts +++ b/src/lib/atemSocketChild.ts @@ -17,7 +17,7 @@ export enum ConnectionState { export enum PacketFlag { AckRequest = 0x01, - Connect = 0x02, + Connect = 0x02, // TODO - 'new session id'? or something like that IsRetransmit = 0x04, RetransmitRequest = 0x08, AckReply = 0x10 diff --git a/src/state/info.ts b/src/state/info.ts index 4ffd2a0bc..f9e1ded66 100644 --- a/src/state/info.ts +++ b/src/state/info.ts @@ -3,23 +3,41 @@ import { Model, ProtocolVersion } from '../enums' export interface AtemCapabilites { readonly mixEffects: number readonly sources: number - readonly colorGenerators: number readonly auxilliaries: number - readonly talkbackOutputs: number + readonly mixMinusOutputs: number readonly mediaPlayers: number readonly serialPorts: number readonly maxHyperdecks: number readonly DVEs: number readonly stingers: number readonly superSources: number - readonly talkbackOverSDI: number + // readonly talkbackOverSDI: number readonly downstreamKeyers: number + readonly cameraControl: boolean + readonly advancedChromaKeyers: boolean readonly multiViewers: number - readonly upstreamKeyers: number +} + +export interface MixEffectInfo { + readonly keyCount: number } export interface SuperSourceInfo { - boxCount: number + readonly boxCount: number +} + +export interface AudioMixerInfo { + readonly inputs: number + readonly monitors: number +} + +export interface MacroPoolInfo { + readonly macroCount: number +} + +export interface MediaPoolInfo { + readonly stillCount: number + readonly clipCount: number } export class DeviceInfo { @@ -28,5 +46,9 @@ export class DeviceInfo { public model: Model = Model.Unknown public productIdentifier?: string public superSources: SuperSourceInfo[] = [] + public mixEffects: MixEffectInfo[] = [] public power: boolean[] = [] + public audioMixer?: AudioMixerInfo + public macroPool?: MacroPoolInfo + public mediaPool?: MediaPoolInfo } From d884eb1b120d972c110985c958cb27f3ccb9d935 Mon Sep 17 00:00:00 2001 From: Julian Waller Date: Sat, 14 Dec 2019 00:06:53 +0000 Subject: [PATCH 55/68] fix: upstream keyers using missing field to check validity --- src/commands/MixEffects/Key/MixEffectKeyChromaCommand.ts | 3 ++- src/commands/MixEffects/Key/MixEffectKeyDVECommand.ts | 5 +++-- .../MixEffects/Key/MixEffectKeyFlyKeyframeGetCommand.ts | 3 ++- .../MixEffects/Key/MixEffectKeyFlyPropertiesGetCommand.ts | 3 ++- src/commands/MixEffects/Key/MixEffectKeyLumaCommand.ts | 3 ++- src/commands/MixEffects/Key/MixEffectKeyOnAirCommand.ts | 3 ++- src/commands/MixEffects/Key/MixEffectKeyPatternCommand.ts | 3 ++- .../MixEffects/Key/MixEffectKeyPropertiesGetCommand.ts | 3 ++- src/state/info.ts | 4 ++-- 9 files changed, 19 insertions(+), 11 deletions(-) diff --git a/src/commands/MixEffects/Key/MixEffectKeyChromaCommand.ts b/src/commands/MixEffects/Key/MixEffectKeyChromaCommand.ts index 85f533153..2065b3fe2 100644 --- a/src/commands/MixEffects/Key/MixEffectKeyChromaCommand.ts +++ b/src/commands/MixEffects/Key/MixEffectKeyChromaCommand.ts @@ -66,7 +66,8 @@ export class MixEffectKeyChromaUpdateCommand extends DeserializedCommand= state.info.capabilities.mixEffects || this.upstreamKeyerId >= state.info.capabilities.upstreamKeyers) { + const meInfo = state.info.mixEffects[this.mixEffect] + if (!meInfo || this.upstreamKeyerId >= meInfo.keyCount) { throw new Error(`UpstreamKeyer ${this.mixEffect}-${this.upstreamKeyerId} is not valid`) } diff --git a/src/commands/MixEffects/Key/MixEffectKeyDVECommand.ts b/src/commands/MixEffects/Key/MixEffectKeyDVECommand.ts index 7d3dd313b..5ff144599 100644 --- a/src/commands/MixEffects/Key/MixEffectKeyDVECommand.ts +++ b/src/commands/MixEffects/Key/MixEffectKeyDVECommand.ts @@ -141,9 +141,10 @@ export class MixEffectKeyDVEUpdateCommand extends DeserializedCommand= state.info.capabilities.mixEffects || this.upstreamKeyerId >= state.info.capabilities.upstreamKeyers) { + const meInfo = state.info.mixEffects[this.mixEffect] + if (!meInfo || this.upstreamKeyerId >= meInfo.keyCount) { throw new Error(`UpstreamKeyer ${this.mixEffect}-${this.upstreamKeyerId} is not valid`) - } else if (!state.info.capabilities.DVEs) { + } else if (!state.info.capabilities || !state.info.capabilities.DVEs) { throw new Error(`DVE is not supported`) } diff --git a/src/commands/MixEffects/Key/MixEffectKeyFlyKeyframeGetCommand.ts b/src/commands/MixEffects/Key/MixEffectKeyFlyKeyframeGetCommand.ts index 952d79e6e..233033b39 100644 --- a/src/commands/MixEffects/Key/MixEffectKeyFlyKeyframeGetCommand.ts +++ b/src/commands/MixEffects/Key/MixEffectKeyFlyKeyframeGetCommand.ts @@ -57,7 +57,8 @@ export class MixEffectKeyFlyKeyframeGetCommand extends DeserializedCommand= state.info.capabilities.mixEffects || this.upstreamKeyerId >= state.info.capabilities.upstreamKeyers) { + const meInfo = state.info.mixEffects[this.mixEffect] + if (!meInfo || this.upstreamKeyerId >= meInfo.keyCount) { throw new Error(`UpstreamKeyer ${this.mixEffect}-${this.upstreamKeyerId} is not valid`) } else if (this.keyFrameId <= 0 || this.keyFrameId > 2) { throw new Error(`KeyFrame ${this.keyFrameId} is not valid`) diff --git a/src/commands/MixEffects/Key/MixEffectKeyFlyPropertiesGetCommand.ts b/src/commands/MixEffects/Key/MixEffectKeyFlyPropertiesGetCommand.ts index 1bef9fb17..d7664ed23 100644 --- a/src/commands/MixEffects/Key/MixEffectKeyFlyPropertiesGetCommand.ts +++ b/src/commands/MixEffects/Key/MixEffectKeyFlyPropertiesGetCommand.ts @@ -28,7 +28,8 @@ export class MixEffectKeyFlyPropertiesGetCommand extends DeserializedCommand= state.info.capabilities.mixEffects || this.upstreamKeyerId >= state.info.capabilities.upstreamKeyers) { + const meInfo = state.info.mixEffects[this.mixEffect] + if (!meInfo || this.upstreamKeyerId >= meInfo.keyCount) { throw new Error(`UpstreamKeyer ${this.mixEffect}-${this.upstreamKeyerId} is not valid`) } diff --git a/src/commands/MixEffects/Key/MixEffectKeyLumaCommand.ts b/src/commands/MixEffects/Key/MixEffectKeyLumaCommand.ts index fed7cdcde..97a8a20eb 100644 --- a/src/commands/MixEffects/Key/MixEffectKeyLumaCommand.ts +++ b/src/commands/MixEffects/Key/MixEffectKeyLumaCommand.ts @@ -63,7 +63,8 @@ export class MixEffectKeyLumaUpdateCommand extends DeserializedCommand= state.info.capabilities.mixEffects || this.upstreamKeyerId >= state.info.capabilities.upstreamKeyers) { + const meInfo = state.info.mixEffects[this.mixEffect] + if (!meInfo || this.upstreamKeyerId >= meInfo.keyCount) { throw new Error(`UpstreamKeyer ${this.mixEffect}-${this.upstreamKeyerId} is not valid`) } diff --git a/src/commands/MixEffects/Key/MixEffectKeyOnAirCommand.ts b/src/commands/MixEffects/Key/MixEffectKeyOnAirCommand.ts index 69d56499c..a62d9a659 100644 --- a/src/commands/MixEffects/Key/MixEffectKeyOnAirCommand.ts +++ b/src/commands/MixEffects/Key/MixEffectKeyOnAirCommand.ts @@ -46,7 +46,8 @@ export class MixEffectKeyOnAirUpdateCommand extends DeserializedCommand<{onAir: } public applyToState (state: AtemState) { - if (!state.info.capabilities || this.mixEffect >= state.info.capabilities.mixEffects || this.upstreamKeyerId >= state.info.capabilities.upstreamKeyers) { + const meInfo = state.info.mixEffects[this.mixEffect] + if (!meInfo || this.upstreamKeyerId >= meInfo.keyCount) { throw new Error(`UpstreamKeyer ${this.mixEffect}-${this.upstreamKeyerId} is not valid`) } diff --git a/src/commands/MixEffects/Key/MixEffectKeyPatternCommand.ts b/src/commands/MixEffects/Key/MixEffectKeyPatternCommand.ts index 6ceb93dd0..f336b8f86 100644 --- a/src/commands/MixEffects/Key/MixEffectKeyPatternCommand.ts +++ b/src/commands/MixEffects/Key/MixEffectKeyPatternCommand.ts @@ -73,7 +73,8 @@ export class MixEffectKeyUpdateCommand extends DeserializedCommand= state.info.capabilities.mixEffects || this.upstreamKeyerId >= state.info.capabilities.upstreamKeyers) { + const meInfo = state.info.mixEffects[this.mixEffect] + if (!meInfo || this.upstreamKeyerId >= meInfo.keyCount) { throw new Error(`UpstreamKeyer ${this.mixEffect}-${this.upstreamKeyerId} is not valid`) } diff --git a/src/commands/MixEffects/Key/MixEffectKeyPropertiesGetCommand.ts b/src/commands/MixEffects/Key/MixEffectKeyPropertiesGetCommand.ts index 9afd22239..98d02ef4f 100644 --- a/src/commands/MixEffects/Key/MixEffectKeyPropertiesGetCommand.ts +++ b/src/commands/MixEffects/Key/MixEffectKeyPropertiesGetCommand.ts @@ -35,7 +35,8 @@ export class MixEffectKeyPropertiesGetCommand extends DeserializedCommand= state.info.capabilities.mixEffects || this.upstreamKeyerId >= state.info.capabilities.upstreamKeyers) { + const meInfo = state.info.mixEffects[this.mixEffect] + if (!meInfo || this.upstreamKeyerId >= meInfo.keyCount) { throw new Error(`UpstreamKeyer ${this.mixEffect}-${this.upstreamKeyerId} is not valid`) } diff --git a/src/state/info.ts b/src/state/info.ts index f9e1ded66..d90870e60 100644 --- a/src/state/info.ts +++ b/src/state/info.ts @@ -45,8 +45,8 @@ export class DeviceInfo { public capabilities?: AtemCapabilites public model: Model = Model.Unknown public productIdentifier?: string - public superSources: SuperSourceInfo[] = [] - public mixEffects: MixEffectInfo[] = [] + public superSources: Array = [] + public mixEffects: Array = [] public power: boolean[] = [] public audioMixer?: AudioMixerInfo public macroPool?: MacroPoolInfo From 611d12c579f318750c4f140a041c7a16703ab6a0 Mon Sep 17 00:00:00 2001 From: Julian Waller Date: Sat, 14 Dec 2019 00:07:09 +0000 Subject: [PATCH 56/68] fix: format received buffers as hex in debug messages --- src/lib/atemSocketChild.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lib/atemSocketChild.ts b/src/lib/atemSocketChild.ts index 94fae3024..00c7add0b 100644 --- a/src/lib/atemSocketChild.ts +++ b/src/lib/atemSocketChild.ts @@ -207,7 +207,7 @@ export class AtemSocketChild { } private _receivePacket (packet: Buffer, rinfo: RemoteInfo) { - if (this._debug) this.log(`RECV ${packet}`) + if (this._debug) this.log(`RECV ${packet.toString('hex')}`) this._lastReceivedAt = Date.now() const length = packet.readUInt16BE(0) & 0x07ff if (length !== rinfo.size) return @@ -277,7 +277,7 @@ export class AtemSocketChild { } private _sendPacket (packet: Buffer) { - if (this._debug) this.log(`SEND ${packet}`) + if (this._debug) this.log(`SEND ${packet.toString('hex')}`) this._socket.send(packet, 0, packet.length, this._port, this._address) } From e57d44c322dc22da99f672629a9fff53caf831c7 Mon Sep 17 00:00:00 2001 From: Julian Waller Date: Sat, 14 Dec 2019 15:09:22 +0000 Subject: [PATCH 57/68] fix: tests --- src/__tests__/index.spec.ts | 9 ++++++++- src/__tests__/util.ts | 14 ++++++++++++++ src/commands/__tests__/index.spec.ts | 1 + src/commands/__tests__/v8.0.spec.ts | 1 + 4 files changed, 24 insertions(+), 1 deletion(-) diff --git a/src/__tests__/index.spec.ts b/src/__tests__/index.spec.ts index 278503cc5..4093a2ebe 100644 --- a/src/__tests__/index.spec.ts +++ b/src/__tests__/index.spec.ts @@ -1,5 +1,6 @@ import { Atem, Enums } from '../index' import { cleanupAtem } from './lib' +import { createEmptyState } from './util' test('Simple test', async () => { const nb = new Atem({ disableMultithreaded: true }) @@ -14,9 +15,15 @@ test('Simple test', async () => { function createConnection (apiVersion: Enums.ProtocolVersion) { const conn = new Atem({ debug: true, disableMultithreaded: true }) + + // Create a state object + const state = createEmptyState() + state.info.apiVersion = apiVersion + // conn.on('error', () => null) conn.sendCommand = jest.fn() - conn.state.info.apiVersion = apiVersion + + ;(conn as any)._state = state return conn } diff --git a/src/__tests__/util.ts b/src/__tests__/util.ts index 7d392e259..0132e88da 100644 --- a/src/__tests__/util.ts +++ b/src/__tests__/util.ts @@ -50,6 +50,20 @@ export function createEmptyState () { cameraControl: true, advancedChromaKeyers: true } + state.info.mixEffects = [ + { + keyCount: 4 + }, + { + keyCount: 4 + }, + { + keyCount: 4 + }, + { + keyCount: 4 + } + ] return state } diff --git a/src/commands/__tests__/index.spec.ts b/src/commands/__tests__/index.spec.ts index 7dfeee987..3bc01b1fd 100644 --- a/src/commands/__tests__/index.spec.ts +++ b/src/commands/__tests__/index.spec.ts @@ -847,6 +847,7 @@ describe('Commands v7.2', () => { const testCase = TestCases[i] switch (testCase.name) { // Temporarily ignore the failures + case '_top': // New properties not implemented in LibAtem yet case 'FTSU': // Unkown props getting overwritten by generator: https://github.com/LibAtem/LibAtem/blob/master/LibAtem/Commands/DataTransfer/DataTransferDownloadRequestCommand.cs continue } diff --git a/src/commands/__tests__/v8.0.spec.ts b/src/commands/__tests__/v8.0.spec.ts index 02ecc3646..99287927a 100644 --- a/src/commands/__tests__/v8.0.spec.ts +++ b/src/commands/__tests__/v8.0.spec.ts @@ -134,6 +134,7 @@ describe('Commands v8.0', () => { switch (testCase.name) { // Not parsed + case '_top': // New properties not implemented in LibAtem yet case '_MvC': // Not parsed case 'AMIP': // portType max value continue From 1f7ef94d393f6f176c3e4159cac5199b05b6314a Mon Sep 17 00:00:00 2001 From: Julian Waller Date: Mon, 16 Dec 2019 23:26:36 +0000 Subject: [PATCH 58/68] feat: Add tests to ensure device connection is successful --- src/__tests__/connection.spec.ts | 84 +++++++++++++++++++ src/__tests__/connection/2me-v8.1.data | 17 ++++ src/__tests__/connection/4me4k-v7.5.2.data | 35 ++++++++ .../connection/constellation-v8.0.2.data | 80 ++++++++++++++++++ src/__tests__/connection/dump.js | 46 ++++++++++ src/__tests__/connection/ps4k-v7.2.data | 8 ++ src/__tests__/connection/tvshd-v8.0.0.data | 5 ++ 7 files changed, 275 insertions(+) create mode 100644 src/__tests__/connection.spec.ts create mode 100644 src/__tests__/connection/2me-v8.1.data create mode 100644 src/__tests__/connection/4me4k-v7.5.2.data create mode 100644 src/__tests__/connection/constellation-v8.0.2.data create mode 100644 src/__tests__/connection/dump.js create mode 100644 src/__tests__/connection/ps4k-v7.2.data create mode 100644 src/__tests__/connection/tvshd-v8.0.0.data diff --git a/src/__tests__/connection.spec.ts b/src/__tests__/connection.spec.ts new file mode 100644 index 000000000..744fb634c --- /dev/null +++ b/src/__tests__/connection.spec.ts @@ -0,0 +1,84 @@ +import { readFileSync } from 'fs' +import { resolve } from 'path' +import { AtemSocketChild } from '../lib/atemSocketChild' +import { ThreadedClass } from 'threadedclass' +import { BasicAtem } from '../atem' +jest.mock('../lib/atemSocketChild') + +// @ts-ignore +export class AtemSocketChildMock implements AtemSocketChild { + public onDisconnect: () => Promise + public onLog: (message: string) => Promise + public onCommandsReceived: (payload: Buffer, packetId: number) => Promise + public onCommandsAcknowledged: (ids: Array<{ packetId: number, trackingId: number }>) => Promise + + constructor (onDisconnect: () => Promise, onLog: (message: string) => Promise, onCommandsReceived: (payload: Buffer, packetId: number) => Promise, onCommandsAcknowledged: (ids: Array<{ packetId: number, trackingId: number }>) => Promise) { + this.onDisconnect = onDisconnect + this.onLog = onLog + this.onCommandsReceived = onCommandsReceived + this.onCommandsAcknowledged = onCommandsAcknowledged + } + + public restartConnection () { + return Promise.resolve() + } + public log (message: string) { + console.log(message) + } + + public connect = jest.fn(() => Promise.resolve()) + public disconnect = jest.fn(() => Promise.resolve()) + public sendCommands = jest.fn(() => Promise.resolve()) +} + +(AtemSocketChild as any).mockImplementation((_opts: any, onDisconnect: () => Promise, onLog: (message: string) => Promise, onCommandsReceived: (payload: Buffer, packetId: number) => Promise, onCommandsAcknowledged: (ids: Array<{ packetId: number, trackingId: number }>) => Promise) => { + return new AtemSocketChildMock(onDisconnect, onLog, onCommandsReceived, onCommandsAcknowledged) +}) + +function createConnection () { + return new BasicAtem({ + debug: false, + address: '', + port: 890, + disableMultithreaded: true, + externalLog: console.log + }) +} + +function getChild (conn: BasicAtem): ThreadedClass { + return (conn as any).socket._socketProcess +} + +function runTestMe1 (name: string, filename: string) { + const filePath = resolve(__dirname, `./connection/${filename}.data`) + const fileData = readFileSync(filePath).toString().split('\n') + + test(`${name}`, async () => { + const conn = createConnection() + await conn.connect('') + + const child = getChild(conn) + expect(child).toBeTruthy() + expect(child.onCommandsReceived).toBeTruthy() + + for (const i in fileData) { + const buffer = Buffer.from(fileData[i].trim(), 'hex') + await child.onCommandsReceived(buffer, i) + } + + // console.log(conn.state) + }) +} + +describe('connection', () => { + /** + * Test cases can be generated with the dump.js script. + * These tests run the payload through the parser to ensure that the commands does not error. + */ + + runTestMe1('2me v8.1', '2me-v8.1') + runTestMe1('4me4k v7.5.2', '4me4k-v7.5.2') + runTestMe1('constellation v8.0.2', 'constellation-v8.0.2') + runTestMe1('ps4k v7.2', 'ps4k-v7.2') + runTestMe1('tvshd v8.0.0', 'tvshd-v8.0.0') +}) diff --git a/src/__tests__/connection/2me-v8.1.data b/src/__tests__/connection/2me-v8.1.data new file mode 100644 index 000000000..c8abc3e86 --- /dev/null +++ b/src/__tests__/connection/2me-v8.1.data @@ -0,0 +1,17 @@ +000c00005f7665720002001d003400005f70696e4154454d2032204d2f452050726f64756374696f6e2053776974636865720000005072700200000003000000002000075f746f70022502060002010401010101000000010001010100000000000c59005f4d654300020503000c00005f4d654301027270000c00005f6d706c20022a000014530c5f4d7643020a01010000000000000000000c2a005f53534300010420000c42285f414d43130100010074f4185f564d43000800000000000000000080000000000001f44800000000400000000000024800d10000008000000000000300000000000040000000000004d1f46800000010000000000005f47000000000200000000000064c00000000004000000000000700d1f4000000800000000000000c2eec5f4d414364000018003053285f44564501010023101112131415161718191a1b1c1d1e1f22000102030405060708090a0b0c0d0e0f202144000cf4c0506f777203d1f4d0000c2eb05669644d06157330000cf4e044634f7401001770000cf5b854634c6b0053b79c002cf510496e50720000426c61636b00000280100012d68000d1f5100000426c6b0001000100010001001f03002ce710496e5072000143616d657261203100820000001e00d1f5bc000043616d3101d40003000100531f03002c1770496e5072000243616d657261203200b000d1f5b800d1f580001543616d3201800001000100021f03002cb3d7496e5072000343616d6572612033008800d1f58000d1f5c400d143616d3301740001000100121f03002cf5b8496e5072000443616d6572612034009c0153b79c00000000015843616d3401180001000100001f03002c1770496e5072000543616d657261203500dc00d1f8ac00d1f8b800d143616d3501580001000100d11f03002c0000496e5072000643616d657261203600000a2a0dc50165e29800d143616d36011000010001002a1f03002ce710496e5072000743616d65726120370000014f2a0e0000001400d143616d3701100001000100151f03002c0000496e5072000843616d6572612038007001543798bbb6bee7000043616d3801780001000100021f03002c0000496e507200094d503100f6a800134228000200000a2a0d6300004d50310000000001000100581f03002c0000496e5072000a4d5031204e65787400c000d1f6d000d1f6c800134d50314e004c0001000100d11f03002cb79c496e5072000b4d5032202846756c6c736b6a65726d29007001554d503200009c0001000100121f03002c1770496e5072000c4d5033202853747564696f0000180000000200304d50330000200001000100d11f03002cf7c8496e5072000d44534b3246000011375400001770000000800156444b324600c80001000100111f03002c0080496e5072000e44534b324b0000d1f770000000000002000000d1444b324b000e0001000100d11f03002c0390496e5072000f44534b314b00001136642000000f440f0f220f0f444b314b00000001000100001f03002c0010496e5072001044534b3146000158ee4400000001000000010000444b314600820001000100d11f03002cf8b8496e507203e8436f6c6f72204261727300d1f87c00d1f88800d14261727301a00100010002001f03002c8010496e507207d1436f6c6f72203100f82000001e8c0000000500d1436f6c31011c0100010003d10f03002c2280496e507207d2436f6c6f72203200000020466f726d6174204572436f6c3201000100010003100f03002cf940496e50720bc24d6564696120506c617965722031003048ff00314d50310001e80100010004001f03002c0005496e50720bc34d6564696120506c617965722031204b657900144d50314b01150100010005331f03 +002c0000496e50720bcc4d6564696120506c6179657220320032204d2f454d50320001750100010004201f03002c6368496e50720bcd4d6564696120506c617965722032204b657900254d50324b01040100010005001f03002c0101496e507217705375706572536f757263650000005f4d654301025353726301000100010006021b03002c530c496e507227244d4520322050474d0000000c2a005f53534300014d2f453201280100010080010b01002cf418496e507227254d452032205056570080000000000001f44800005076773201000100010080d10b01002c0000496e5072271a4d4520312050474d000004d1f4680000001000004d2f453101700100010080000300002c064c496e5072271b4d4520312050565700000000800000000000000c5076773101430100010080300300002c5645496e50721b59436c65616e20466565642031001f22000102030443666431010a0100010080200300002cf4c0496e50721b5a436c65616e204665656420320030000cf4e044634366643201700100010080630300002cb79c496e50721f4141312073737263006b00000280100012d68000d141757831006c0100010081000200002c1f03496e50721f42417578696c6961727920320000820000001e00d14175783201610100010081030200002c1f03496e50721f434133206d6978206d696e757300b000d1f5b800d14175783300610100010081010200002c1f03496e50721f444134206c6f6f6b6168656164008800d1f58000d14175783400610100010081010200002c1f03496e50721f45417578696c69617279203500009c0153b79c00004175783501610100010081010200002c1f03496e50721f46417578696c6961727920360000dc00d1f8ac00d14175783601610100010081010200000c1f034d76564d00075072000c43614d76564d01060000000c0dc54d76564d02074361000c01104d76564d03061f03000ce7104d76564d04044361000c72614d76564d05052a0e000c00144d76564d06060110000c00014d76564d07070000000c50724d765072000c0061001000704d76496e0000271b00004361001001784d76496e0001271a00000000001050724d76496e0002000900004228001000004d76496e0003000a00000000001000014d76496e0004000b0000507200104d504d76496e0005000c0000f6d00010f6c84d76496e000600100000000100101f034d76496e0007000f00004d50001028464d76496e0008000d0000007000104d504d76496e0009000e00001f03000c17704d765072010c0050001028534d76496e010027250000000200104d504d76496e0101272400001f030010f7c84d76496e01021f4100004600001037544d76496e01031f430000444b001000c84d76496e01041f4400000080001050724d76496e01051f460000f770001000004d76496e010600010000000e001000014d76496e0107000200005072001044534d76496e010800030000000f00100f224d76496e0109000500000001000c1f0350726749006e00010010445350727649005800090000000100100001547253530000010001010001000c1f0354725072000050720010436f54725073000019730000f87c000cf888544d7850001901a0000c01005444705000190000001c507254577050001901200000000013880000138813880000436f001c011c544476500019191b000000000000000000000000006f7220001c0000545374500001002000000000003200000019000d00010f03000cf9404b654f6e00000065001c61204b6542500000000101000000000000502328dcd8c1803e8000141f034b654c6d000000720000000000696120001461794b65436b000000000000000000000015001801004b655074000000dc00001388000001f401f40014 +004400004b65445600004d650000000000000000000000000000000000000000000000750032003200000000002c00000000000000000000000000000000000019722032001065794b6546530000000000000000003c1f034b4b465000000172000003e8000003e8000000000000000000000000000000000000000000000000000003e80168190c0000000000000000003c20504b4b465000000200000003e8000003e8000000000000000000000000000000000000000000250000000003e8016819800000000000000000000c50764b654f6e00010000001c0b014b654250000100010100000d000e00502328dcd8c1803e80001400104b654c6d0001017000000000000003000014064c4b65436b000100000000000000000000001880004b6550740001007600001388000001f401f40000004456454b6544560001436c00000000000000000000000000000000000000000000000a0032003200000000002c000000000000000000000000000000000000193200300010f4e04b6546530001000000000000003c03004b4b465000010172000003e8000003e8000000000000000000000000000000000000000000000000000003e8016819030000000000000000003c6c694b4b465000010282000003e8000003e8000000000000000000000000000000000000000000430000000003e80168196e0000000000000000000c4175507267490100000c0010020050727649016e00010044413400106f6f547253530100010001d1f580000c4175547250720100010000100200547250730100197200004175000c6c69544d78500119009c000cb79c5444705001190000001c0100545770500119010300000000138800001388138800007920001c00dc544476500119191b000000000000000000000000000c1f03001c564d545374500101006100000000000600000019000d0001564d000c43614b654f6e0100004d001c1f034b6542500100000101000000000000612328dcd8c1803e80001400144b654c6d01000010000000000076564d001400004b65436b0100000000000000000000700018496e4b6550740100006100001388000001f401f4001a004400004b6544560100496e000000000000000000000000000000000000000000000000003200320000000000040000000000000000000000000000000000001900f6d00010f6c84b6546530100000000000001003c1f034b4b46500100010f000003e8000003e8000000000000000000000000000000000000000000090000000003e8016819700000000000000000003c28534b4b465001000225000003e8000003e8000000000000000000000000000000000000000000020000000003e8016819540000000000000000000c444b4b654f6e0101006e001c1f444b6542500101000101000000000000462328dcd8c1803e800014496e4b654c6d0101000e000000000076496e001400024b65436b0101000000000000000000030018000f4b6550740101006e00001388000001f401f40003004467494b65445601014453000000000000000000000000000000000000000000000000003200320000000000720000000000000000000000000000000000001900f87c0010f8884b65465301010000000c0000003c70504b4b465001010172000003e8000003e8000000000000000000000000000000000000000000440000000003e8016819000000000000000000003c72204b4b465001010250000003e8000003e8000000000000000000000000000000000000000000000000000003e80168195000000000000000000010005044736b4200800010000f1f03001c4c6d44736b50000019010000000000002328dcd8c1803e8000000010000044736b530001000000195074001000dc44736b420100000d000e0014 +001c000044736b50010019010000000000002328dcd8c1803e8000000010000044736b530101000000190000000c00004674625000190000000c00004674625300000019000c65794674625001190000000c0000467462530100001900100172436f6c56000001f403e801f400100000436f6c560100010e03e801f4000c00004175785300680003000c000041757853013c0004000c4650417578530200000a000c03e84175785303000007000c00004175785304000005000c00004175785305680008001400004d505370005a005a0000000000000000004c0b014d504353000000010100000d000e00502328dcd8c1803e80001400104b654c6d0001017000000000000003000014064c4b65436b000100000000000000000000001880004b650000005c00764d504153010000000000000000000000000000000000006c00000000000000000000000000000000000000000000000a0032003200000000002c000000000000000000000000000000000000193200300010f4e04b654653004c00004d504353010000004b4b465000010172000003e8000003e8000000000000000000000000000000000000000000000000000003e8016819030000000000000000003c6c694b4b0000005c02824d50415302000000000000000000000000000000000000000000000000430000000003e80168196e0000000000000000000c4175507267490100000c0010020050727649016e00010044413400106f6f54725353010001000020f5804d50666500720000000000000000000000000000000000000000000000206c694d506665001900010000000000000000000000000000000000570000002001034d506665008800020000000000000000000000000000000000190000002000004d506665000000030000000000000000000000000000000000000000002000004d506665000100040000000000000000000000000000000000650000002000014d506665000000050000000000000000000000000000000000000000002000004d506665001400060000000000000000000000000000000000180000002050744d506665000000070000000000000000000000000000000000000000002000004d506665000000080000000000000000000000000000000000000000002000004d506665000000090000000000000000000000000000000000650000002000004d506665003c000a0000000000000000000000000000000000000000002000004d5066650000000b0000000000000000000000000000000000000000002000004d506665004b000c0000000000000000000000000000000000000000002000004d5066650000000d00000000000000000000000000000000000000000020444b4d5066650001000e00000000000000000000000000000000000000000020dcd84d5066650014000f00000000000000000000000000000000001400000020436b4d506665000000100000000000000000000000000000000000000000002001f44d506665004400110000000000000000000000000000000000000000002000004d506665000000120000000000000000000000000000000000000000002000004d5066650000001300000000000000000000000000000000003c0000002046504d506665000000140000000000000000000000000000000000000000002000004d5066650000001500000000000000000000000000000000004b0000002002504d506665000000160000000000000000000000000000000000000000002000004d50666500680017000000000000000000000000000000000080000000201f034d506665007300180000000000000000000000000000000000800000002000004d5066650001001900000000000000000000000000000000000e0000 +002000004d5066650000001a000000000000000000000000000000000010000000206b534d5066650019001b0000000000000000000000000000000000740000002000194d5066650074001c000000000000000000000000000000000010000000206c564d50666500e8001d00000000000000000000000000000000000c0000002078534d506665000c001e0000000000000000000000000000000000000000002003e84d5066650000001f0000000000000000000000000000000000750000 +058000004d50664d010000000570000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f970 +004000004d50664d0100005700300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +058000004d50664d020000000570000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f970 +004000004d50664d0200005700300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c00004d5043450001000000100000524350530000000100000000000c00004d5043450101010100100000524350530100000100000000001c000052584d530000000000000000000000000000000000020000001c000052584350000001000000000000000000000000000000000000280000525853530000000000000000ffffffff0000000000000000000000000000000000000000000c00005258434300000000001c000052584d530001000000000000000000000000000000020000001c000052584350000101000000000000000000000000000000000000280000525853530001000000000000ffffffff0000000000000000000000000000000000000000000c00005258434300010000001c000052584d530002000000000000000000000000000000020000001c000052584350000201000000000000000000000000000000000000280000525853530002000000000000ffffffff0000000000000000000000000000000000000000000c00005258434300020000001c000052584d530003000000000000000000000000000000020000001c000052584350000301000000000000000000000000000000000000280000525853530003000000000000ffffffff0000000000000000000000000000000000000000000c00005258434300030000001800005353726300000bc20bc301010000000000000000002000005353426400000000003200320000000000000000000000000a0000000020000053534250000001000001fce000320244010000000000000007d0000000200000535342500001010007d103200032024400000000000000000000000000200000535342500002000000000000000003e800000000000000000000000000200000535342500003000000000000000003e8000000000000000000000000000c0000414d50500100000000180000414d49500001000000010001000080000000000000180000414d49500002000000020001000080000000000000180000414d49500003000000030001000080000000000000180000414d49500004000000040001000080000000000000180000414d49500005000000050001000080000000000000180000414d49500006000000060001000080000000000000180000414d49500007000000070001000080000000000000180000414d49500008000000080001000080000000000000180000414d49500009000000090001000080000000000000180000414d4950000a0000000a0001000080000000000000180000414d4950000b0000000b0001000080000000000000180000414d4950000c0000000c0001000080000000000000180000414d4950000d0000000d0001000080000000000000180000414d4950000e0000000e0001000080000000000000180000414d4950000f0000000f0001000080000000000000180000414d49500010000000100001000080000000000000180000414d495007d1010000000100000080000000000000180000414d495007d2010000010100000080000000000000180000414d495003e9020000000020000080000000000000100000414d4d4f800000000000000000140000414d6d4f0100800000000001000007d000440000414d546c0013000100000200000300000400000500000600000700000800000900000a00000b00000c00000d00000e00000f0000100007d10007d20003e90000000c00004c4b535400000000000c00004c4b535400010000000c00004c4b535400020000001000005f546c430001000010000000001c0000546c496e0010010000000000000002000000010101010000 +007c0000546c53720025000000000101000200000300000400000500000600000700000800000902000a00000b00000c00000d01000e01000f0100100103e80007d10007d2000bc2000bc3000bcc000bcd00177000272400272500271a00271b001b59001b5a001f41001f42001f43001f44001f45001f46001c0000003c4d53546c46630010000100000200000300000400000500000600000700000800000900000a00000b00000c00000d00000e00000f000010005353000c00004d5250720000ffff000c00004d52635300000000001400004d507270000001000003000073646600001800004d507270000101000005000064756d6d79000000001c00004d50727000020100000900026c69622d64756d6d79643200001800004d507270000301000006000053696e646572ffff001800004d507270000401000008000073657474696e6773001443434d50727000050100000100007a020000001400004d507270000601000004000064657631001443504d507270000701000004000064657632001800004d507270000801000005000064756d6d79ffffff001800004d5072700009010000050000636f6c6f720c0000001443434d507270000a01000003000066746200001c00004d507270000b01000009000064736b2070726f7073030100001800004d507270000c0100000700006368726f6d613153001c00004d507270000d0100000c00006476652d616c746974756465001800004d507270000e0100000800006476652d616c743200240bc24d507270000f0100001200007472616e73207769706520616e64206469700000002800004d507270001001000009000e456e7465722048454c547765656e20696e746f2048454c00002800004d5072700011010000080010457869742048454c547765656e206f7574206f662048454c002042504d50727000120100000d000078706c6f73696f6e2d74657374200000001842504d50727000130100000500007465737432000000002000004d50727000140100000d0000616e6f74686572206d6163726f010001001080004d5072700015000000000000001000004d5072700016000000000000001000004d5072700017000000000000002480004d507270001801000011000066616b6520616e20696d706c6f73696f6e180000001049504d5072700019000000000000001000004d507270001a000000000000002000014d507270001b0100000f0000656e64206f6620746865206c696e6500001000004d507270001c000000000000001000014d507270001d000000000000001049504d507270001e000000000000001800004d507270001f0100000500006d65646961008000001000004d5072700020000000000000001000014d5072700021000000000000001049504d5072700022000000000000001000004d5072700023000000000000001000014d5072700024000000000000001049504d5072700025000000000000001000004d5072700026000000000000001000014d5072700027000000000000001049504d5072700028000000000000001000004d5072700029000000000000001001004d507270002a000000000000001049504d507270002b000000000000001000004d507270002c000000000000001000204d507270002d00000000000000104d4f4d507270002e00000000000000106d4f4d507270002f000000000000001000004d5072700030000000000000001000004d5072700031000000000000001000094d507270003200000000000000100e004d5072700033000000000000001000004d5072700034000000000000001000004d5072700035000000000000001053544d5072700036000000000000001000004d5072700037000000000000001001004d5072700038000000000000001000004d5072700039000000000000 +001000004d507270003a000000000000001000004d507270003b000000000000001000084d507270003c00000000000000100d014d507270003d000000000000001000074d507270003e000000000000001017704d507270003f000000000000001059004d50727000400000000000000010001f4d5072700041000000000000001046634d5072700042000000000000001000054d507270004300000000000000100a004d5072700044000000000000001000004d50727000450000000000000010ffff4d5072700046000000000000001000004d5072700047000000000000001066004d5072700048000000000000001000004d5072700049000000000000001072704d507270004a00000000000000106d6d4d507270004b000000000000001001004d507270004c000000000000001000004d507270004d000000000000001074744d507270004e000000000000001001004d507270004f000000000000001072704d5072700050000000000000001043504d5072700051000000000000001076324d5072700052000000000000001000004d5072700053000000000000001072704d5072700054000000000000001000004d5072700055000000000000001000004d5072700056000000000000001001004d5072700057000000000000001001004d5072700058000000000000001000004d5072700059000000000000001072704d507270005a000000000000001074694d507270005b000000000000001001004d507270005c00000000000000100bc24d507270005d0000000000000010616e4d507270005e000000000000001000004d507270005f0000000000000010000e4d5072700060000000000000001020694d5072700061000000000000001072704d50727000620000000000000010454c4d5072700063000000000000000c454c4343737400001388002001004343645001000080000000010000000000200000000042504d5072700020010043436450010002800000000100000000005072702a000100000d000000206f744343645001010d0100010000000000000050727000150000000000000020000043436450010101010001000000000000005072700217000000000000002080004343645001010202000000010000000000616e2015e0706c6f73696f00200000434364500101050300000000000100000010000000004e20001a00000020000043436450010108010001000000000000006e6420016620746865206c00206500434364500104040100010000000000000010000100507270001d00000020000043436450010800800000000400000000001800000000000000000000002000004343645001080180000000040000000000200000000000000000000000207270434364500108028000000004000000000022000008000800080008000020727043436450010803800000000400000000002400000000000000000000002072704343645001080480000000020000000000260000040008000010000100207270434364500108058000000001000000000028000008000000001000000020727043436450010806800000000200000000002a000000000800001049500020727043436450010b00800000000200000000002c000000000000001000200020727043436450020000800000000100000000002e00000000000000106d4f0020727043436450020002800000000100000000003000002a00000000100000002072704343645002010d010001000000000000003200000000000000100e00002072704343645002010101000100000000000000340000020000000010000000207270434364500201020200000001000000000036000015e000000010000000207270434364500201050300000000000100000038000000004e2000100000 +002000004343645002010801000100000000000000507270013b000000000000002000084343645002040401000100000000000000507270003d00000000000000200007434364500208008000000004000000000050727000000000000000000020590043436450020801800000000400000000005072700000000000000000002046634343645002080280000000040000000000507270080008000800080000200a00434364500208038000000004000000000050727000000000000000000020ffff43436450020804800000000200000000005072700400080000000000002066004343645002080580000000010000000000507270080000000000000000207270434364500208068000000002000000000050727000000800000000000020010043436450020b0080000000020000000000507270000000000000000000207474434364500300008000000001000000000050727000000000000000000020727043436450030002800000000100000000005072702a00000000000000002076324343645003010d010001000000000000005072700053000000000000002072704343645003010101000100000000000000507270025500000000000000200000434364500301020200000001000000000050727015e000000000000000200100434364500301050300000000000100000050727000004e2000000000002072704343645003010801000100000000000000507270015b000000000000002001004343645003040401000100000000000000507270005d0000000000000020616e434364500308008000000004000000000050727000000000000000000020000e4343645003080180000000040000000000507270000000000000000000207270434364500308028000000004000000000050727008000800080008000020454c434364500308038000000004000000000000008000000000000000000020000043436450030804800000000200000000000002800400080000000000002072704343645003080580000000010000000000010d01080000000000000000207270434364500308068000000002000000000001010100000800000000000020727043436450030b0080000000020000000000010202000000000000000000206e20434364500400008000000001000000000001050300000000000100000020000043436450040002800000000100000000000108012a00000000000000002064204343645004010d010001000000000000000404010001000000000000002000014343645004010101000100000000000000080080020000040000000000200000434364500401020200000001000000000008018015e000040000000000200000434364500401050300000000000100000008028000004e200000000000200000434364500401080100010000000000000008038001000004000000000020000043436450040404010001000000000000000804800000000200000000002000004343645004080080000000040000000000080580000000000000000000200000434364500408018000000004000000000008068000000000000000000020000043436450040802800000000400000000000b0080080008000800080000200000434364500408038000000004000000000000008000000000000000000020000043436450040804800000000200000000000002800400080000000000002000004343645004080580000000010000000000010d01080000000000000000200000434364500408068000000002000000000001010100000800000000000020000043436450040b0080000000020000000000010202000000000000000000200000434364500500008000000001000000000001050300000000000100000020000043436450050002800000000100000000000000002a0000000000f970 +002000004343645005010d01000100000000000000507270003b000000000000002000084343645005010101000100000000000000507270023d00000000000000200007434364500501020200000001000000000050727015e000000000000000205900434364500501050300000000000100000050727000004e2000000000002046634343645005010801000100000000000000507270010008000800080000200a00434364500504040100010000000000000050727000000000000000000020ffff434364500508008000000004000000000050727000000000000000000020660043436450050801800000000400000000005072700000000000000000002072704343645005080280000000040000000000507270080008000800080000200100434364500508038000000004000000000050727000000000000000000020747443436450050804800000000200000000005072700400080000000000002072704343645005080580000000010000000000507270080000000000000000207632434364500508068000000002000000000050727000000800000000000020727043436450050b0080000000020000000000507270000000000000000000200000434364500600008000000001000000000050727000000000000000000020010043436450060002800000000100000000005072702a004e2000000000002072704343645006010d01000100000000000000507270005b000000000000002001004343645006010101000100000000000000507270025d0000000000000020616e434364500601020200000001000000000050727015e00000000000000020000e434364500601050300000000000100000050727000004e200000000000207270434364500601080100010000000000000050727001000800080008000020454c434364500604040100010000000000000000008000000000000000000020000043436450060800800000000400000000000002800000000000000000002072704343645006080180000000040000000000010d0100000000000000000020727043436450060802800000000400000000000101010800080008000800002072704343645006080380000000040000000000010202000000000000000000206e2043436450060804800000000200000000000105030400080000010000002000004343645006080580000000010000000000010801080000000000000000206420434364500608068000000002000000000004040100000800000000000020000143436450060b0080000000020000000000080080000000000000000000200000434364500700008000000001000000000008018000000004000000000020000043436450070002800000000100000000000802802a004e2000000000002000004343645007010d010001000000000000000803800000000400000000002000004343645007010101000100000000000000080480020000020000000000200000434364500701020200000001000000000008058015e000000000000000200000434364500701050300000000000100000008068000004e20000000000020000043436450070108010001000000000000000b0080010008000800080000200000434364500704040100010000000000000000008000000000000000000020000043436450070800800000000400000000000002800000000000000000002000004343645007080180000000040000000000010d010000000000000000002000004343645007080280000000040000000000010101080008000800080000200000434364500708038000000004000000000001020200000000000000000020000043436450070804800000000200000000000105030400080000010000002000004343645007080580000000010000000000000000080000000000f970 +00200000434364500708068000000002000000000050727000000800000000000020000843436450070b0080000000020000000000507270000000000000000000200007434364500800008000000001000000000050727000000000000000000020590043436450080002800000000100000000005072702a004e2000000000002046634343645008010d01000100000000000000507270000008000800080000200a00434364500801010100010000000000000050727002000000000000000020ffff434364500801020200000001000000000050727015e000000000000000206600434364500801050300000000000100000050727000004e2000000000002072704343645008010801000100000000000000507270010008000800080000200100434364500804040100010000000000000050727000000000000000000020747443436450080800800000000400000000005072700000000000000000002072704343645008080180000000040000000000507270000000000000000000207632434364500808028000000004000000000050727008000800080008000020727043436450080803800000000400000000005072700000000000000000002000004343645008080480000000020000000000507270040008000000000000200100434364500808058000000001000000000050727008004e200000000000207270434364500808068000000002000000000050727000000800000000000020010043436450080b008000000002000000000050727000000000000000000020616e434364500900008000000001000000000050727000000000000000000020000e43436450090002800000000100000000005072702a004e2000000000002072704343645009010d0100010000000000000050727000000800080008000020454c4343645009010101000100000000000000000080020000000000000000200000434364500901020200000001000000000000028015e0000000000000002072704343645009010503000000000001000000010d0100004e20000000000020727043436450090108010001000000000000000101010100080008000800002072704343645009040401000100000000000000010202000000000000000000206e2043436450090800800000000400000000000105030000000000000000002000004343645009080180000000040000000000010801000000000000000000206420434364500908028000000004000000000004040108000800080008000020000143436450090803800000000400000000000800800000000000000000002000004343645009080480000000020000000000080180040008000000000000200000434364500908058000000001000000000008028008004e200000000000200000434364500908068000000002000000000008038000000800000000000020000043436450090b0080000000020000000000080480000000000000000000200000434364500a000080000000010000000000080580000000000000000000200000434364500a0002800000000100000000000806802a004e200000000000200000434364500a010d010001000000000000000b0080000008000800080000200000434364500a010101000100000000000000000080020000000000000000200000434364500a01020200000001000000000000028015e000000000000000200000434364500a010503000000000001000000010d0100004e200000000000200000434364500a010801000100000000000000010101010008000800080000200000434364500a040401000100000000000000010202000000000000000000200000434364500a080080000000040000000000010503000000000000000000200000434364500a0801800000000400000000000000000000000000000000 +00200000434364500a080280000000040000000000507270080008000800080000200008434364500a080380000000040000000000507270000000000000000000200007434364500a080480000000020000000000507270040008000000000000205900434364500a08058000000001000000000050727008004e200000000000204663434364500a080680000000020000000000507270000008000800080000200a00434364500a0b008000000002000000000050727000000000000000000020ffff434364500b000080000000010000000000507270000000000000000000206600434364500b0002800000000100000000005072702a004e200000000000207270434364500b010d01000100000000000000507270000008000800080000200100434364500b010101000100000000000000507270020000000000000000207474434364500b01020200000001000000000050727015e000000000000000207270434364500b01050300000000000100000050727000004e200000000000207632434364500b010801000100000000000000507270010008000800080000207270434364500b040401000100000000000000507270000000000000000000200000434364500b080080000000040000000000507270000000000000000000200100434364500b080180000000040000000000507270000000000000000000207270434364500b080280000000040000000000507270080008000800080000200100434364500b08038000000004000000000050727000000000000000000020616e434364500b08048000000002000000000050727004000800000000000020000e434364500b08058000000001000000000050727008004e200000000000207270434364500b08068000000002000000000050727000000800080008000020454c434364500b0b0080000000020000000000000080000000000000000000200000434364500c000080000000010000000000000280000000000000000000207270434364500c000280000000010000000000010d012a004e200000000000207270434364500c010d01000100000000000000010101000008000800080000207270434364500c010101000100000000000000010202020000000000000000206e20434364500c01020200000001000000000001050315e000000000000000200000434364500c01050300000000000100000001080100004e200000000000206420434364500c010801000100000000000000040401010008000800080000200001434364500c040401000100000000000000080080000000000000000000200000434364500c080080000000040000000000080180000000000000000000200000434364500c080180000000040000000000080280000000000000000000200000434364500c080280000000040000000000080380080008000800080000200000434364500c080380000000040000000000080480000000000000000000200000434364500c080480000000020000000000080580040008000000000000200000434364500c08058000000001000000000008068008004e200000000000200000434364500c0806800000000200000000000b0080000008000800080000200000434364500c0b0080000000020000000000000080000000000000000000200000434364500d000080000000010000000000000280000000000000000000200000434364500d000280000000010000000000010d012a004e200000000000200000434364500d010d01000100000000000000010101000008000800080000200000434364500d010101000100000000000000010202020000000000000000200000434364500d01020200000001000000000001050315e000000000000000200000434364500d01050300000000000100000000000000004e2000000000 +00200000434364500d010801000100000000000000507270010008000800080000200008434364500d040401000100000000000000507270000000000000000000200007434364500d080080000000040000000000507270000000000000000000205900434364500d080180000000040000000000507270000000000000000000204663434364500d080280000000040000000000507270080008000800080000200a00434364500d08038000000004000000000050727000000000000000000020ffff434364500d080480000000020000000000507270040008000000000000206600434364500d08058000000001000000000050727008004e200000000000207270434364500d080680000000020000000000507270000008000800080000200100434364500d0b0080000000020000000000507270000000000000000000207474434364500e000080000000010000000000507270000000000000000000207270434364500e0002800000000100000000005072702a004e200000000000207632434364500e010d01000100000000000000507270000008000800080000207270434364500e010101000100000000000000507270020000000000000000200000434364500e01020200000001000000000050727015e000000000000000200100434364500e01050300000000000100000050727000004e200000000000207270434364500e010801000100000000000000507270010008000800080000200100434364500e04040100010000000000000050727000000000000000000020616e434364500e08008000000004000000000050727000000000000000000020000e434364500e080180000000040000000000507270000000000000000000207270434364500e08028000000004000000000050727008000800080008000020454c434364500e080380000000040000000000000080000000000000000000200000434364500e080480000000020000000000000280040008000000000000207270434364500e080580000000010000000000010d0108004e200000000000207270434364500e080680000000020000000000010101000008000800080000207270434364500e0b0080000000020000000000010202000000000000000000206e20434364500f000080000000010000000000010503000000000000000000200000434364500f0002800000000100000000000108012a004e200000000000206420434364500f010d01000100000000000000040401000008000800080000200001434364500f010101000100000000000000080080020000000000000000200000434364500f01020200000001000000000008018015e000000000000000200000434364500f01050300000000000100000008028000004e200000000000200000434364500f010801000100000000000000080380010008000800080000200000434364500f040401000100000000000000080480000000000000000000200000434364500f080080000000040000000000080580000000000000000000200000434364500f080180000000040000000000080680000000000000000000200000434364500f0802800000000400000000000b0080080008000800080000200000434364500f080380000000040000000000000080000000000000000000200000434364500f080480000000020000000000000280040008000000000000200000434364500f080580000000010000000000010d0108004e200000000000200000434364500f080680000000020000000000010101000008000800080000200000434364500f0b0080000000020000000000010202000000000000000000200000434364501000008000000001000000000001050300000000000000000020000043436450100002800000000100000000000000002a004e2000000000 +002000004343645010010d010001000000000000005072700000080008000800002000084343645010010101000100000000000000507270020000000000000000200007434364501001020200000001000000000050727015e000000000000000205900434364501001050300000000000100000050727000004e2000000000002046634343645010010801000100000000000000507270010008000800080000200a00434364501004040100010000000000000050727000000000000000000020ffff43436450100800800000000400000000005072700000000000000000002066004343645010080180000000040000000000507270000000000000000000207270434364501008028000000004000000000050727008000800080008000020010043436450100803800000000400000000005072700000000000000000002074744343645010080480000000020000000000507270040008000000000000207270434364501008058000000001000000000050727008004e200000000000207632434364501008068000000002000000000050727000000800080008000020727043436450100b00800000000200000000005072700000000000000000000c00005350744d01010202000c000153505a5300009600000c0000505a435300200100000c6450496e436d01000000 \ No newline at end of file diff --git a/src/__tests__/connection/4me4k-v7.5.2.data b/src/__tests__/connection/4me4k-v7.5.2.data new file mode 100644 index 000000000..2054d5dd0 --- /dev/null +++ b/src/__tests__/connection/4me4k-v7.5.2.data @@ -0,0 +1,35 @@ +000c00005f7665720002001b003400005f70696e4154454d2034204d2f452042726f6164636173742053747564696f20344b00004d5072700010000007000000002000005f746f70044302060004010401010101140000010101010101000000000c00005f4d654300040000000c00005f4d654301047270000c00005f4d654302040000000c00005f4d654303040000000c00005f6d706c40020000001000005f4d7643020a010101010101000c00005f53534304507270000c00005f414d431a01000000cc00005f564d4300100000041080000000001000000010050000000000002000000020061b000000010040000000400750727000020080000000800810800000004100000001000900000000008200000002000a1e000000010440000004000b50727000020880000008000c10800000011440000010000d00000000022880000020000e21000000004100000001000f5072700000820000000200101000000001044000000440110000000002088000000880122400000001144000001440135072700002288000002880000c00005f4d414364260000003000005f44564501010023101112131415161718191a1b1c1d1e1f22000102030405060708090a0b0c0d0e0f202100000c0000506f777203507270000c00005669644d06100001000c00004448566d04040000000c00004448566d05050000000c00004448566d06067270000c00004448566d07070001000c00004448566d08080000000c00004448566d09090000000c00004448566d0a0a7270000c00004448566d0b0b0001000c00004448566d0c0c0000000c00004448566d0d0d0000000c00004448566d0e087270000c00004448566d0f090001000c00004448566d10060000000c00004448566d11070000000c00004448566d120c7270000c00004448566d130d0001000c00005633736c00c31303002c0000496e50720000426c61636b0000000000b4c31303000000008024426c6b0001000100010001001f0f002c0000496e5072000143616d65726120310001b4c31303e0670403360043310000000000010001000a1f0f002c0000496e5072000243616d657261203200033683f801e06704030e00433200c300030001000100671f0f002c0000496e5072000343616d65726120330001020000004583f80100004333000b000300010001000b1f0f002c0000496e5072000443616d65726120340000100b07035418200070174334008400010001000100001f0f002c0000496e5072000543616d65726120350000330000000501330a2cc34335000000000001000100011f0f002c0000496e5072000643616d6572612036000a80000000000000008a844336000200000001000100011f0f002c0000496e5072000743616d65726120370000d0ada1000501330a7a84433700c300060001000100001f0f002c0000496e5072000843616d65726120380000b6260000e06704030000433800ec00000001000100001f0f002c0000496e5072000943616d65726120390000000000008000000000004339007800030001000100001f0f002c0000496e5072000a43616d65726120313000010000000100000001004331300000000001000100001f0f002c0000496e5072000b43616d6572612031310088f210004c40a20074544331310000010001000100401f0f002c0000496e5072000c43616d657261203132008f52a1000c961000000043313200000000010001009a1f0f002c0000496e5072000d56542058000100000000000000002000000000007800000000000001000100641f0f002c0000496e5072000e5654205900726d6174204572726f725d0a00ffff5900280000000001000100001f0f002c0000496e5072000f47726170686963732046696c6c000000000000004746584b00000001000100001f0f +002c0000496e507200104772617068696373204b6579004d2034204d2f454746584600640001000100531f0f002c0000496e5072001100700010000007000000002080005f746f7004430006000400040001000100001f0f002c0000496e5072001200005f4d654300040000000c00005f4d654301040070000c00000001000100041f0f002c0000496e507200130000000c00005f6d706c40020000001000005f4d0043020a000100010001000c1f0f002c0000496e5072001400005f414d431a01000000cc72705f564d4300100000041000000001000100001f0f002c0000496e507203e8436f6c6f722042617273000000400750727000024261727301800100010002001f0f002c0000496e507207d1436f6c6f72203100000000010440000004000b50436f6c3101800100010003100f0f002c0000496e507207d2436f6c6f7220320020000e210000000041000000436f6c3201700100010003000f0f002c0000496e50720bc24d6564696120506c6179657220310024000000014d50310001400100010004021f0f002c0000496e50720bc34d6564696120506c617965722031204b657900114d50314b011701000100051d1f0f002c0000496e50720bcc4d6564696120506c617965722032006f777203504d50320001000100010004101f0f002c0000496e50720bcd4d6564696120506c617965722032204b657900484d50324b01700100010005481f0f002c0000496e50720bd64d6564696120506c61796572203300090000000c4d503300016d01000100040c1f0f002c0000496e50720bd74d6564696120506c617965722033204b6579000d4d50334b01000100010005081f0f002c0000496e50720be04d6564696120506c617965722034000c000144484d50340001000100010004481f0f002c0000496e50720be14d6564696120506c617965722034204b6579002c4d50344b01720100010005631f0f002c0000496e507217705375706572536f7572636500010001001f0f002c5353726301720100010006651b0f002c0000496e50720faa4d452031204b65792031204d61736b001f0f002c4d314b3101720100010082650300002c0000496e50720fb44d452031204b65792032204d61736b001f0f002c4d314b3201720100010082650300002c0000496e50720fbe4d452031204b65792033204d61736b001f0f002c4d314b3301720100010082650300002c0000496e50720fc84d452031204b65792034204d61736b001f0f002c4d314b3401720100010082650300002c0000496e5072139244534b2031204d61736b0001000100011f0f002c444b314d01720100010082650300002c0000496e5072139c44534b2032204d61736b0001000100011f0f002c444b324d01720100010082650300002c0000496e5072271a4d4520312050474d00060001000100001f0f002c50676d3101720100010080650300002c0000496e5072271b4d4520312050565700000001000100001f0f002c5076773101720100010080650300002c0000496e507227244d4520322050474d00030001000100001f0f002c50676d3201720100010080650b01002c0000496e507227254d4520322050565700000001000100001f0f002c5076773201720100010080650b01002c0000496e50721b59436c65616e20466565642031000100401f0f002c4366643101720100010080650300002c0000496e50721b5a436c65616e204665656420320001009a1f0f002c4366643201720100010080580300002c0000496e50721f41417578696c69617279203100000100641f0f002c4175783101720100010081590200002c0000496e50721f42417578696c69617279203200000100001f0f002c4175783201720100010081700200002c0000496e50721f43417578696c69617279203300000100001f0f6c454175783301000100010081070200 +002c0000496e50721f44417578696c69617279203400004d2034204d2f454175783401640100010081530200002c0000496e50721f45417578696c6961727920350080005f746f7004434175783501040100010081000200002c0000496e50721f46417578696c6961727920360000005f4d654301044175783601000100010081040200002c0000496e50720fd24d452032204b65792031204d61736b0000005f4d4d324b31010101000100820c0300002c0000496e50720fdc4d452032204b65792032204d61736b004d4300104d324b3201000100010082000300002c0000496e50720fe64d452032204b65792033204d61736b00727000024d324b3301800100010082000300002c0000496e50720ff04d452032204b65792034204d61736b0004000b504d324b3401800100010082100300002c0000496e50720ffa4d452033204b65792031204d61736b00410000004d334b3101700100010082000300002c0000496e507210044d452033204b65792032204d61736b00000000014d334b3201400100010082020300002c0000496e5072100e4d452033204b65792033204d61736b00657900114d334b33011701000100821d0300002c0000496e507210184d452033204b65792034204d61736b00777203504d334b3401000100010082100300002c0000496e507210224d452034204b65792031204d61736b00657900484d344b3101700100010082480300002c0000496e5072102c4d452034204b65792032204d61736b000000000c4d344b32016d01000100820c0300002c0000496e507210364d452034204b65792033204d61736b006579000d4d344b3301000100010082080300002c0000496e507210404d452034204b65792034204d61736b00000144484d344b3401000100010082480300002c0000496e5072272e4d4520332050474d007965722034204b6579002c50676d3301720100010080630b03002c0000496e5072272f4d4520332050565700636500010001001f0f002c5076773301720100010080650b03002c0000496e507227384d4520342050474d0031204d61736b001f0f002c50676d3401720100010080650b07002c0000496e507227394d452034205056570032204d61736b001f0f002c5076773401720100010080650b07000c00004d76564d04044d45000c00004d76564d05056173000c00004d76564d06060172000c00004d76564d07070000000c00004d76564d0808204b000c00004d76564d09091f0f000c00004d76564d0a060100000c00004d76564d0b075072000c00004d76564d0c06736b000c00004d76564d0d07444b000c00004d76564d0e080300000c00004d76564d0f094453000c00004d76564d10060001000c00004d76564d11070172000c00004d76564d12060000000c00004d76564d13072050000c00004d76507200000001001000004d76496e0000271a01650300000c000056754d4300000045001000004d76496e0001271b00001f0f000c000056754d4300010000001000004d76496e0002000101244d45000c000056754d4300020001001000004d76496e0003000201000100000c000056754d4300030072001000004d76496e0004000301010001000c000056754d4300040072001000004d76496e00050004016e5072000c000056754d4300050064001000004d76496e0006000501310172000c000056754d4300060000001000004d76496e0007000601656564000c000056754d4300070066001000004d76496e00080007012c0000000c000056754d4300080069001000004d76496e00090008012c4175000c000056754d4300090000000c000056754d6f00644175000c00004d76507201000101001000004d76496e0100272401000100000c000056754d4301000072001000004d76496e0101272500000001000c000056754d4301010000 +001000004d76496e0102000901696c69000c000056754d430102004d001000004d76496e0103000a01530200000c000056754d4301030075001000004d76496e0104000d01746f70000c000056754d4301040000001000004d76496e0105000e01464175000c000056754d4301050000001000004d76496e0106000b01000100000c000056754d4301060072001000004d76496e0107000f014d6173000c000056754d4301070001001000004d76496e01080011016e5072000c000056754d4301080032001000004d76496e0109001101320100000c000056754d4301090000000c000056754d6f0164204b000c00005072674900000001001000005072764900000001000003000010000054725353000001000132204b000c0000547250720000040000100000547250730000190000000300000c0000544d785000194d45000c000054447050001907d1001c00005457705000190670000007d1138800001388138800005072001c0000544476500019191c0bc20bc3010101f402bc000000320140001c0000545374500001018001f402bc000e00020049002200052033000c00004b654f6e00000033001c00004b6542500000000101000000000000722328dcd8c1803e80001400004b654c6d0000007201f402bc00340100002000004b41436b00000000000001f4000000000000000003e8000000000000001800004b41434300000000c3e920bf02711620083d0530001800004b6550740000064b138813880000138813880000004400004b65445600000100000001f4000001f4000000000000000000000000010000330032003200000032640d0000000003e8016819000000000000000000196e5072001000004b65465300000000004d0073003c00004b4b465000000100000003e8000003e8000000000000000000000000000000000000000000720000000003e8016819670000000000000000003c00004b4b465000000272000003e8000003e8000000000000000000000000000000000000000000000000000003e8016819010000000000000000000c00004b654f6e00010073001c00004b6542500001000101000000000000072328dcd8c1803e80001400004b654c6d0001003201f402bc00001f0f002000004b41436b00010000000001f4000000000000000003e8000000000000001800004b41434300010000c3e920bf02711620083d0530001800004b65507400010672138813880000138813880034004400004b65445600014d31000001f4000001f4000000000000000000000000010000530032003200000032640c0000000003e801681900000000000000000019080300001000004b65465300010000000c0020003c00004b4b46500001010f000003e8000003e8000000000000000000000000000000000000000000070000000003e8016819720000000000000000003c00004b4b465000010200000003e8000003e80000000000000000000000000000000000000000000c0000000003e8016819000000000000000000000c00004b654f6e00020050001c00004b6542500002000101000000000000022328dcd8c1803e80001400004b654c6d0002004501f402bc00040003002000004b41436b00020000000001f4000000000000000003e8000000000000001800004b41434300020000c3e920bf02711620083d0530001800004b6550740002064313881388000013881388006e004400004b65445600020001000001f4000001f400000000000000000000000001000000003200320000003264080000000003e8016819000000000000000000190c0172001000004b654653000200000075006f003c00004b4b465000020172000003e8000003e8000000000000000000000000000000000000000000000000000003e80168196e0000000000000000 +003c00004b4b465000020209000003e8000003e8000000000000000000000000000000000000000000530000000003e8016819430000000000000000000c00004b654f6e00030070001c00004b65425000030001010000000000006e2328dcd8c1803e80001400004b654c6d0003000001f402bc0076496e002000004b41436b00030000000001f4000000000000000003e8000000000000001800004b41434300030000c3e920bf02711620083d0530001800004b65507400030645138813880000138813880073004400004b65445600030100000001f4000001f40000000000000000000000000100004b003200320000003264000000000003e801681900000000000000000019100100001000004b65465300030000000c0034003c00004b4b465000030132000003e8000003e8000000000000000000000000000000000000000000440000000003e8016819000000000000000000003c00004b4b465000030288000003e8000003e8000000000000000000000000000000000000000000320000000003e8016819500000000000000000000c00005072674901050001001000005072764901000001001c011700100000547253530100010001000072000c000054725072010020340010000054725073010019bc00000100000c0000544d785001190000000c000054447050011907d1001c00005457705001190679000007d1138800001388138800001620001c0000544476500119191c0bc20bc3010101f402bc000000880000001c0000545374500101010001f402bc000000020049002200050000000c00004b654f6e01000032001c00004b6542500100000101000000000000002328dcd8c1803e80001400004b654c6d0100000001f402bc003c0001002000004b41436b01000000000001f4000000000000000003e8000000000000001800004b41434301000000c3e920bf02711620083d0530001800004b65507401000672138813880000138813880000004400004b65445601000000000001f4000001f400000000000000000000000001000000003200320000003264010000000003e801681900000000000000000019000007001000004b654653010000000065006d003c00004b4b46500100010f000003e8000003e8000000000000000000000000000000000000000000000000000003e8016819430000000000000000003c00004b4b46500100024d000003e8000003e8000000000000000000000000000000000000000000010000000003e8016819f40000000000000000000c00004b654f6e01010032001c00004b6542500101000101000000000000002328dcd8c1803e80001400004b654c6d0101000001f402bc003c564d002000004b41436b01010000000001f4000000000000000003e8000000000000001800004b41434301010000c3e920bf02711620083d0530001800004b65507401010600138813880000138813880000004400004b65445601010000000001f4000001f400000000000000000000000001000000003200320000003264020000000003e801681900000000000000000019000002001000004b654653010100000065006d003c00004b4b465001010103000003e8000003e8000000000000000000000000000000000000000000000000000003e8016819430000000000000000003c00004b4b465001010272000003e8000003e8000000000000000000000000000000000000000000020000000003e8016819f40000000000000000000c00004b654f6e01020032001c00004b6542500102000101000000000000002328dcd8c1803e80001400004b654c6d0102000001f402bc003c4175002000004b41436b01020000000001f4000000000000000003e8000000000000001800004b41434301020000c3e920bf02711620083d0530 +001800004b65507401020609138813880000138813880000004400004b65445601020000000001f4000001f400000000000000000000000001000000003200320000003264030000000003e80168190000000000000000001900006e001000004b654653010200000065006d003c00004b4b46500102016e000003e8000003e8000000000000000000000000000000000000000000000000000003e8016819430000000000000000003c00004b4b465001020211000003e8000003e8000000000000000000000000000000000000000000030000000003e8016819f40000000000000000000c00004b654f6e01030032001c00004b6542500103000101000000000000002328dcd8c1803e80001400004b654c6d0103000001f402bc003c5072002000004b41436b01030000000001f4000000000000000003e8000000000000001800004b41434301030000c3e920bf02711620083d0530001800004b65507401030688138813880000138813880000004400004b65445601030000000001f4000001f400000000000000000000000001000000003200320000003264050000000003e801681900000000000000000019104250001000004b65465301030000000c00d8003c00004b4b46500103016d000003e8000003e8000000000000000000000000000000000000000000440000000003e8016819000000000000000000003c00004b4b465001030288000003e8000003e8000000000000000000000000000000000000000000880000000003e8016819500000000000000000000c00005072674902050001001000005072764902000001001c003200100000547253530200010001000000000c00005472507202004d450010000054725073020019bc00000001000c0000544d785002190000000c000054447050021907d1001c00005457705002190600000007d1138800001388138800001620001c0000544476500219191c0bc20bc3010101f402bc000000880000001c0000545374500201010001f402bc000000020049002200050000000c00004b654f6e02000032001c00004b6542500200000101000000000000002328dcd8c1803e80001400004b654c6d0200000001f402bc003c0032002000004b41436b02000000000001f4000000000000000003e8000000000000001800004b41434302000000c3e920bf02711620083d0530001800004b6550740200064d138813880000138813880000004400004b65445602000000000001f4000001f400000000000000000000000001000000003200320000003264010000000003e801681900000000000000000019000000001000004b654653020000000065006d003c00004b4b46500200014d000003e8000003e8000000000000000000000000000000000000000000000000000003e8016819430000000000000000003c00004b4b46500200026e000003e8000003e8000000000000000000000000000000000000000000010000000003e8016819f40000000000000000000c00004b654f6e02010032001c00004b6542500201000101000000000000002328dcd8c1803e80001400004b654c6d0201000001f402bc003c0045002000004b41436b02010000000001f4000000000000000003e8000000000000001800004b41434302010000c3e920bf02711620083d0530001800004b65507402010672138813880000138813880000004400004b65445602010000000001f4000001f400000000000000000000000001000000003200320000003264020000000003e801681900000000000000000019000000001000004b654653020100000065006d003c00004b4b465002010175000003e8000003e8000000000000000000000000000000000000000000000000000003e8016819430000000000000000 +003c00004b4b465002010209000003e8000003e8000000000000000000000000000000000000000000000000000003e8016819000000000000000000000c00004b654f6e02020000001c00004b65425002020001010000000000006e2328dcd8c1803e80001400004b654c6d0202000001f402bc0002016e002000004b41436b02020000000001f4000000000000000003e8000000000000001800004b41434302020000c3e920bf02711620083d0530001800004b655074020206e8138813880000138813880000004400004b65445602020000000001f4000001f40000000000000000000000000100006e003200320000003264650000000003e801681900000000000000000019803e80001000004b6546530202000000f400bc003c00004b4b46500202016b000003e8000003e8000000000000000000000000000000000000000000410000000003e8016819bf0000000000000000003c00004b4b465002020288000003e8000003e8000000000000000000000000000000000000000000000000000003e8016819000000000000000000000c00004b654f6e02030000001c00004b6542500203000101000000000000502328dcd8c1803e80001400004b654c6d0203007201f402bc0003016d002000004b41436b02030000000001f4000000000000000003e8000000000000001800004b41434302030000c3e920bf02711620083d0530001800004b655074020306e8138813880000138813880000004400004b65445602030000000001f4000001f400000000000000000000000001000049003200320000003264720000000003e801681900000000000000000019000100001000004b6546530203000000000045003c00004b4b4650020301bc000003e8000003e80000000000000000000000000000000000000000001c0000000003e8016819000000000000000000003c00004b4b465002030230000003e8000003e8000000000000000000000000000000000000000000530000000003e8016819bc0000000000000000000c000050726749036500010010000050727649036500010000000100100000547253530300010001803e80000c000054725072030000000010000054725073030019500000436b000c0000544d785003190000000c000054447050031907d1001c00005457705003190600000007d1138800001388138800001620001c0000544476500319191c0bc20bc3010101f402bc000000654456001c000054537450030101f401f402bc000000020049002200050000000c00004b654f6e03000000001c00004b6542500300000101000000000000002328dcd8c1803e80001400004b654c6d0300000001f402bc0000014d002000004b41436b03000000000001f4000000000000000003e8000000000000001800004b41434303000000c3e920bf02711620083d0530001800004b655074030006e8138813880000138813880000004400004b65445603000000000001f4000001f40000000000000000000000000100006e003200320000003264650000000003e801681900000000000000000019803e80001000004b6546530300000000f400bc003c00004b4b46500300016b000003e8000003e8000000000000000000000000000000000000000000410000000003e8016819bf0000000000000000003c00004b4b465003000272000003e8000003e8000000000000000000000000000000000000000000000000000003e8016819000000000000000000000c00004b654f6e03010000001c00004b6542500301000101000000000000002328dcd8c1803e80001400004b654c6d0301000001f402bc00010175002000004b41436b03010000000001f4000000000000000003e8000000000000001800004b41434303010000c3e920bf02711620083d0530 +001800004b65507403010609138813880000138813880000004400004b65445603010000000001f4000001f400000000000000000000000001000000003200320000003264020000000003e80168190000000000000000001900006e001000004b654653030100000065006d003c00004b4b46500301016e000003e8000003e8000000000000000000000000000000000000000000000000000003e8016819430000000000000000003c00004b4b465003010211000003e8000003e8000000000000000000000000000000000000000000020000000003e8016819f40000000000000000000c00004b654f6e03020032001c00004b6542500302000101000000000000002328dcd8c1803e80001400004b654c6d0302000001f402bc003c5072002000004b41436b03020000000001f4000000000000000003e8000000000000001800004b41434303020000c3e920bf02711620083d0530001800004b65507403020688138813880000138813880000004400004b65445603020000000001f4000001f400000000000000000000000001000000003200320000003264030000000003e801681900000000000000000019000050001000004b654653030200000065006d003c00004b4b46500302016d000003e8000003e8000000000000000000000000000000000000000000000000000003e8016819430000000000000000003c00004b4b465003020288000003e8000003e8000000000000000000000000000000000000000000030000000003e8016819f40000000000000000000c00004b654f6e03030032001c00004b6542500303000101000000000000002328dcd8c1803e80001400004b654c6d0303000001f402bc003c4c6d002000004b41436b03030000000001f4000000000000000003e8000000000000001800004b41434303030000c3e920bf02711620083d0530001800004b65507403030630138813880000138813880000004400004b65445603030000000001f4000001f400000000000000000000000001000000003200320000003264650000000003e801681900000000000000000019100000001000004b65465303030000000c00d8003c00004b4b4650030301bc000003e8000003e8000000000000000000000000000000000000000000440000000003e8016819000000000000000000003c00004b4b465003030288000003e8000003e8000000000000000000000000000000000000000000650000000003e80168195000000000000000000010000044736b420005000000000032001c000044736b500000190001f402bc00002328dcd8c1803e8000000010000044736b530000000019654c6d0010000044736b4201000000000003e8001c000044736b500100190001f402bc00002328dcd8c1803e8000000010000044736b530100000019e920bf000c0000467462500019026e000c00004674625300000019000c00004674625001190000000c00004674625301000019000c00004674625002190000000c00004674625302000019000c000046746250031903e8000c0000467462530300001900100000436f6c56006501f403e801f400100000436f6c56014b010e03e801f4000c000041757853000003e8000c000041757853010003e8000c000041757853020003e8000c000041757853030003e8000c000041757853040003e8000c000041757853050003e8000c00004d50537002d002d0004c00004d504353000000e8016819000000000000000000000c00324b654f6e03010000001c03e84b6542500301000101000000000000002328dcd8c1803e80001400004b654c6d03010000 +005c00004d50415301000000000000000000000000000000000000004b65445603010000000001f4000001f400000000000000000000000001000000003200320000003264020000000003e80168190000000000000000001900006e004c00004d504353010000000065006d003c00004b4b46500301016e000003e8000003e8000000000000000000000000000000000000000000000000000003e8016819430000000000000000005c00004d504153020000000000000000000000000000000000000000000000000000000000000000020000000003e8016819f40000000000000000000c00004b654f6e03020032001c00324b654250030200010100000000000000002000004d506665001400000000000000000000000000000000000000200000002000004d506665000000010000000000000000000000000000000000180000002000004d50666500e900020000000000000000000000000000000000020000002000004d506665008800030000000000000000000000000000000000000000002000004d506665000000040000000000000000000000000000000000000000002000004d506665000000050000000000000000000000000000000000650000002000004d506665000200060000000000000000000000000000000000000000002000004d5066650000000700000000000000000000000000000000003c0000002000004d506665000000080000000000000000000000000000000000000000002000004d506665000000090000000000000000000000000000000000650000002000004d5066650065000a0000000000000000000000000000000000800000002000004d5066650003000b0000000000000000000000000000000000030000002000004d5066650000000c0000000000000000000000000000000000030000002000004d506665003d000d0000000000000000000000000000000000000000002000004d5066650065000e0000000000000000000000000000000000000000002000004d5066650032000f0000000000000000000000000000000000000000002000004d5066650010001000000000000000000000000000000000004b0000002000004d506665000000110000000000000000000000000000000000000000002000004d506665006800120000000000000000000000000000000000030000002000004d506665000000130000000000000000000000000000000000650000002000004d506665000000140000000000000000000000000000000000000000002000004d506665000000150000000000000000000000000000000000100000002000004d5066650065001600000000000000000000000000000000001c0000002000004d50666500f400170000000000000000000000000000000000730000002000004d506665000c00180000000000000000000000000000000000000000002000004d506665001900190000000000000000000000000000000000740000002000004d5066650074001a00000000000000000000000000000000000c0000002000004d5066650010001b00000000000000000000000000000000006f0000002000004d506665000c001c0000000000000000000000000000000000000000002000004d5066650000001d0000000000000000000000000000000000750000002000004d5066650075001e00000000000000000000000000000000004c0000002000004d5066650068001f0000000000000000000000000000000000010000002000004d506665000100200000000000000000000000000000000000140000002000004d50666500f400210000000000000000000000000000000000000000002000004d50666500e800220000000000000000000000000000000000e90000 +002000004d506665000000230000000000000000000000000000000000650000002000004d506665000000240000000000000000000000000000000000320000002000004d5066650000002500000000000000000000000000000000004c0000002000004d506665006500260000000000000000000000000000000000000000002000004d506665000000270000000000000000000000000000000000680000002000004d506665005c00280000000000000000000000000000000000000000002000004d506665000000290000000000000000000000000000000000000000002000004d5066650065002a0000000000000000000000000000000000000000002000004d5066650050002b0000000000000000000000000000000000000000002000004d5066650050002c0000000000000000000000000000000000000000002000004d5066650050002d0000000000000000000000000000000000000000002000004d5066650050002e0000000000000000000000000000000000000000002000004d5066650050002f0000000000000000000000000000000000000000002000004d506665005000300000000000000000000000000000000000000000002000004d506665005000310000000000000000000000000000000000000000002000004d506665005000320000000000000000000000000000000000000000002000004d506665005000330000000000000000000000000000000000000000002000004d506665005000340000000000000000000000000000000000000000002000004d506665005000350000000000000000000000000000000000000000002000004d506665005000360000000000000000000000000000000000000000002000004d506665005000370000000000000000000000000000000000000000002000004d506665005000380000000000000000000000000000000000000000002000004d506665005000390000000000000000000000000000000000000000002000004d5066650050003a0000000000000000000000000000000000000000002000004d5066650050003b0000000000000000000000000000000000000000002000004d5066650050003c0000000000000000000000000000000000000000002000004d5066650050003d0000000000000000000000000000000000000000002000004d5066650050003e0000000000000000000000000000000000000000002000004d5066650050003f0000000000000000000000000000000000000000 +058000004d50664d0100000005700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200 +058000004d50664d0100005705700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200 +058000004d50664d010000ae05700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200 +058000004d50664d0100010505700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200 +058000004d50664d0100015c05700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200 +058000004d50664d010001b305700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200 +058000004d50664d0100020a05700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200 +058000004d50664d0100026105700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200 +019000004d50664d010002b801800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +058000004d50664d0200000005700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200 +058000004d50664d0200005705700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200 +058000004d50664d020000ae05700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200 +058000004d50664d0200010505700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200 +058000004d50664d0200015c05700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200 +058000004d50664d020001b305700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200 +058000004d50664d0200020a05700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200 +058000004d50664d0200026105700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200 +019000004d50664d020002b801800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c00004d5043450001000000100000524350530000000100000000000c00004d5043450101010100100000524350530100000100000000000c00004d5043450201020000100000524350530200000100000000000c00004d5043450301030100100000524350530300000100000000001c000052584d530000000000000000000000000000000000020000001c000052584350000001000000000000000000000000000000000000280000525853530000000000000000ffffffff0000000000000000000000000000000000000000000c00005258434300000000001c000052584d530001000000000000000000000000000000020000001c000052584350000101000000000000000000000000000000000000280000525853530001000000000000ffffffff0000000000000000000000000000000000000000000c00005258434300010000001c000052584d530002000000000000000000000000000000020000001c000052584350000201000000000000000000000000000000000000280000525853530002000000000000ffffffff0000000000000000000000000000000000000000000c00005258434300020000001c000052584d530003000000000000000000000000000000020000001c000052584350000301000000000000000000000000000000000000280000525853530003000000000000ffffffff0000000000000000000000000000000000000000000c0000525843430003000000280000535372630bc20bc3000001f402bc0000010000320032000000320000000003e801681900001c00005353425000010000fce001c201f400000000000000000000001c00005353425001010000032001c201f400000000000000000000001c00005353425002010000fce0fe3e01f400000000000000000000001c000053534250030100000320fe3e01f400000000000000000000000c0000414d50500000000000180000414d49500001000000010001000080000000000000180000414d49500002000000020001000080000000000000180000414d49500003000000030001000080000000000000180000414d49500004000000040001000080000000000000180000414d49500005000000050001000080000000000000180000414d49500006000000060001000080000000000000180000414d49500007000000070001000080000000000000180000414d49500008000000080001000080000000000000180000414d49500009000000090001000080000000000000180000414d4950000a0000000a0001000080000000000000180000414d4950000b0000000b0001000080000000000000180000414d4950000c0000000c00010000800000000000 +00180000414d4950000d00b8000d0001000080000000000000180000414d4950000e0000000e0001000080000000000000180000414d4950000f0000000f0001000080000000000000180000414d49500010000000100001000080000000000000180000414d49500011000000110001000080000000000000180000414d49500012000000120001000080000000000000180000414d49500013000000130001000080000000000000180000414d49500014000000140001000080000000000000180000414d495007d1010000000100020080000000000000180000414d495007d2010000010100020080000000000000180000414d495007d3010000020100020080000000000000180000414d495007d4010000030100020080000000000000180000414d495004b1020000000080010080000000000000180000414d495003e9020000010020010080000000000000100000414d4d4f800000000000000000140000414d6d4f0100800000000001000007d000580000414d546c001a000100000200000300000400000500000600000700000800000900000a00000b00000c00000d00000e00000f0000100000110000120000130000140007d10007d20007d30007d40004b10103e901000c000041544d500010000000100000544d495000010001000c000000100000544d4950000200010043505300100000544d49500003000100584d5300100000544d4950000400010000000000100000544d4950000500010000010000100000544d4950000600010000000000100000544d4950000700010000000000100000544d4950000800010000000000100000544d4950000900010058434300100000544d4950000a00010001000000100000544d4950000b00010002000000100000544d4950000c00010000000000100000544d4950000d00010028000000100000544d4950000e000100ffffff00100000544d4950000f00010000000000100000544d4950001000010001000000100000544d4950001100010000000000100000544d495000120001001c000000100000544d4950001300010000000000100000544d49500014000100585353000c00004c4b5354000000ff000c00004c4b535400010000000c00004c4b535400020000001000005f546c430001000014584d5300200000546c496e00140300000000000000000000000000000000000000010000d40000546c53720043000000000103000200000300000400000500000600000700000800000900000a00000b00000c00000d00000e00000f0000100000110000120000130000140003e80007d10007d2000bc2000bc3000bcc000bcd000bd6000bd7000be0000be1001770000faa000fb4000fbe000fc800139200139c00271a00271b002724002725001b59001b5a001f41001f42001f43001f44001f45001f46000fd2000fdc000fe6000ff0000ffa00100400100e00101800102200102c00103600104000272e00272f002738002739000000480000546c46630014000100000200000300000400000500000600000700000800000900000a00000b00000c00000d00000e00000f000010000011000012000013000014000000000c00004d5250720000ffff000c00004d52635300180000001000004d5072700000000000000000001000004d5072700001000000000000001000004d5072700002000000000000001000004d5072700003000000000000001000004d5072700004000000000000001400004d507270000501000004000057697065001000004d5072700006000000000000001000004d5072700007000000000000001000004d5072700008000000000000001000004d5072700009000000000000001000004d507270000a000000000000001000004d507270000b000000000000001000004d507270000c000000000000 +001000004d507270000d000000000000001000004d507270000e000000000000001000004d507270000f000000000000001000004d5072700010000000000000001000004d5072700011000000000000001000004d5072700012000000000000001000004d5072700013000000000000001000004d5072700014000000000000001000004d5072700015000000000000001000004d5072700016000000000000001000004d5072700017000000000000001000004d5072700018000000000000001000004d5072700019000000000000001000004d507270001a000000000000001000004d507270001b000000000000001000004d507270001c000000000000001000004d507270001d000000000000001000004d507270001e000000000000001000004d507270001f000000000000001000004d5072700020000000000000001000004d5072700021000000000000001000004d5072700022000000000000001000004d5072700023000000000000001000004d5072700024000000000000001000004d5072700025000000000000001000004d5072700026000000000000001000004d5072700027000000000000001000004d5072700028000000000000001000004d5072700029000000000000001000004d507270002a000000000000001000004d507270002b000000000000001000004d507270002c000000000000001000004d507270002d000000000000001000004d507270002e000000000000001000004d507270002f000000000000001000004d5072700030000000000000001000004d5072700031000000000000001000004d5072700032000000000000001000004d5072700033000000000000001000004d5072700034000000000000001000004d5072700035000000000000001000004d5072700036000000000000001000004d5072700037000000000000001000004d5072700038000000000000001000004d5072700039000000000000001000004d507270003a000000000000001000004d507270003b000000000000001000004d507270003c000000000000001000004d507270003d000000000000001000004d507270003e000000000000001000004d507270003f000000000000001000004d5072700040000000000000001000004d5072700041000000000000001000004d5072700042000000000000001000004d5072700043000000000000001000004d5072700044000000000000001000004d5072700045000000000000001000004d5072700046000000000000001000004d5072700047000000000000001000004d5072700048000000000000001000004d5072700049000000000000001000004d507270004a000000000000001000004d507270004b000000000000001000004d507270004c000000000000001000004d507270004d000000000000001000004d507270004e000000000000001000004d507270004f000000000000001000004d5072700050000000000000001000004d5072700051000000000000001000004d5072700052000000000000001000004d5072700053000000000000001000004d5072700054000000000000001000004d5072700055000000000000001000004d5072700056000000000000001000004d5072700057000000000000001000004d5072700058000000000000001000004d5072700059000000000000001000004d507270005a000000000000001000004d507270005b000000000000001000004d507270005c000000000000001000004d507270005d000000000000001000004d507270005e000000000000001000004d507270005f000000000000001000004d5072700060000000000000001000004d5072700061000000000000001000004d5072700062000000000000001000004d5072700063000000000000000c00004343737400001388 +00200000434364500100008000000001000000000050727000000000000000000020000043436450010002800000000100000000005072702a00000000000000002000004343645001010d010001000000000000005072700012000000000000002000004343645001010101000100000000000000507270021400000000000000200000434364500101020200000001000000000050727015e000000000000000200000434364500101050300000000000100000050727000004e2000000000002000004343645001010801000100000000000000507270011a000000000000002000004343645001040401000100000000000000507270001c00000000000000200000434364500108008000000004000000000050727000000000000000000020000043436450010801800000000400000000005072700000000000000000002000004343645001080280000000040000000000507270080008000800080000200000434364500108038000000004000000000050727000000000000000000020000043436450010804800000000200000000005072700400080000000000002000004343645001080580000000010000000000507270080000000000000000200000434364500108068000000002000000000050727000000800000000000020000043436450010b0080000000020000000000507270000000000000000000200000434364500200008000000001000000000050727000000000000000000020000043436450020002800000000100000000005072702a00000000000000002000004343645002010d010001000000000000005072700032000000000000002000004343645002010101000100000000000000507270023400000000000000200000434364500201020200000001000000000050727015e000000000000000200000434364500201050300000000000100000050727000004e2000000000002000004343645002010801000100000000000000507270013a000000000000002000004343645002040401000100000000000000507270003c00000000000000200000434364500208008000000004000000000050727000000000000000000020000043436450020801800000000400000000005072700000000000000000002000004343645002080280000000040000000000507270080008000800080000200000434364500208038000000004000000000050727000000000000000000020000043436450020804800000000200000000005072700400080000000000002000004343645002080580000000010000000000507270080000000000000000200000434364500208068000000002000000000050727000000800000000000020000043436450020b0080000000020000000000507270000000000000000000200000434364500300008000000001000000000050727000000000000000000020000043436450030002800000000100000000005072702a00000000000000002000004343645003010d010001000000000000005072700052000000000000002000004343645003010101000100000000000000507270025400000000000000200000434364500301020200000001000000000050727015e000000000000000200000434364500301050300000000000100000050727000004e2000000000002000004343645003010801000100000000000000507270015a000000000000002000004343645003040401000100000000000000507270005c0000000000000020000043436450030800800000000400000000005072700000000000000000002000004343645003080180000000040000000000507270000000000000000000200000434364500308028000000004000000000050727008000800080008000020000043436450030803800000000400000000004373740000000000000000 +0020000043436450030804800000000200000000005072700400080000000000002000004343645003080580000000010000000000507270080000000000000000200000434364500308068000000002000000000050727000000800000000000020000043436450030b0080000000020000000000507270000000000000000000200000434364500400008000000001000000000050727000000000000000000020000043436450040002800000000100000000005072702a004e2000000000002000004343645004010d01000100000000000000507270001a000000000000002000004343645004010101000100000000000000507270021c00000000000000200000434364500401020200000001000000000050727015e000000000000000200000434364500401050300000000000100000050727000004e20000000000020000043436450040108010001000000000000005072700100080008000800002000004343645004040401000100000000000000507270000000000000000000200000434364500408008000000004000000000050727000000000000000000020000043436450040801800000000400000000005072700000000000000000002000004343645004080280000000040000000000507270080008000800080000200000434364500408038000000004000000000050727000000000000000000020000043436450040804800000000200000000005072700400080000000000002000004343645004080580000000010000000000507270080000000000000000200000434364500408068000000002000000000050727000000800000000000020000043436450040b0080000000020000000000507270000000000000000000200000434364500500008000000001000000000050727000000000000000000020000043436450050002800000000100000000005072702a004e2000000000002000004343645005010d01000100000000000000507270003a000000000000002000004343645005010101000100000000000000507270023c00000000000000200000434364500501020200000001000000000050727015e000000000000000200000434364500501050300000000000100000050727000004e20000000000020000043436450050108010001000000000000005072700100080008000800002000004343645005040401000100000000000000507270000000000000000000200000434364500508008000000004000000000050727000000000000000000020000043436450050801800000000400000000005072700000000000000000002000004343645005080280000000040000000000507270080008000800080000200000434364500508038000000004000000000050727000000000000000000020000043436450050804800000000200000000005072700400080000000000002000004343645005080580000000010000000000507270080000000000000000200000434364500508068000000002000000000050727000000800000000000020000043436450050b0080000000020000000000507270000000000000000000200000434364500600008000000001000000000050727000000000000000000020000043436450060002800000000100000000005072702a004e2000000000002000004343645006010d01000100000000000000507270005a000000000000002000004343645006010101000100000000000000507270025c00000000000000200000434364500601020200000001000000000050727015e000000000000000200000434364500601050300000000000100000050727000004e200000000000200000434364500601080100010000000000000050727001000800080008000020000043436450060404010001000000000000004373740000000000000000 +0020000043436450060800800000000400000000005072700000000000000000002000004343645006080180000000040000000000507270000000000000000000200000434364500608028000000004000000000050727008000800080008000020000043436450060803800000000400000000005072700000000000000000002000004343645006080480000000020000000000507270040008000000000000200000434364500608058000000001000000000050727008004e200000000000200000434364500608068000000002000000000050727000000800000000000020000043436450060b0080000000020000000000507270000000000000000000200000434364500700008000000001000000000050727000000000000000000020000043436450070002800000000100000000005072702a004e2000000000002000004343645007010d010001000000000000005072700000080008000800002000004343645007010101000100000000000000507270020000000000000000200000434364500701020200000001000000000050727015e000000000000000200000434364500701050300000000000100000050727000004e2000000000002000004343645007010801000100000000000000507270010008000800080000200000434364500704040100010000000000000050727000000000000000000020000043436450070800800000000400000000005072700000000000000000002000004343645007080180000000040000000000507270000000000000000000200000434364500708028000000004000000000050727008000800080008000020000043436450070803800000000400000000005072700000000000000000002000004343645007080480000000020000000000507270040008000000000000200000434364500708058000000001000000000050727008004e200000000000200000434364500708068000000002000000000050727000000800000000000020000043436450070b0080000000020000000000507270000000000000000000200000434364500800008000000001000000000050727000000000000000000020000043436450080002800000000100000000005072702a004e2000000000002000004343645008010d010001000000000000005072700000080008000800002000004343645008010101000100000000000000507270020000000000000000200000434364500801020200000001000000000050727015e000000000000000200000434364500801050300000000000100000050727000004e2000000000002000004343645008010801000100000000000000507270010008000800080000200000434364500804040100010000000000000050727000000000000000000020000043436450080800800000000400000000005072700000000000000000002000004343645008080180000000040000000000507270000000000000000000200000434364500808028000000004000000000050727008000800080008000020000043436450080803800000000400000000005072700000000000000000002000004343645008080480000000020000000000507270040008000000000000200000434364500808058000000001000000000050727008004e200000000000200000434364500808068000000002000000000050727000000800000000000020000043436450080b0080000000020000000000507270000000000000000000200000434364500900008000000001000000000050727000000000000000000020000043436450090002800000000100000000005072702a004e2000000000002000004343645009010d0100010000000000000050727000000800080008000020000043436450090101010001000000000000004373740200000000000000 +00200000434364500901020200000001000000000050727015e000000000000000200000434364500901050300000000000100000050727000004e2000000000002000004343645009010801000100000000000000507270010008000800080000200000434364500904040100010000000000000050727000000000000000000020000043436450090800800000000400000000005072700000000000000000002000004343645009080180000000040000000000507270000000000000000000200000434364500908028000000004000000000050727008000800080008000020000043436450090803800000000400000000005072700000000000000000002000004343645009080480000000020000000000507270040008000000000000200000434364500908058000000001000000000050727008004e200000000000200000434364500908068000000002000000000050727000000800080008000020000043436450090b0080000000020000000000507270000000000000000000200000434364500a000080000000010000000000507270000000000000000000200000434364500a0002800000000100000000005072702a004e200000000000200000434364500a010d01000100000000000000507270000008000800080000200000434364500a010101000100000000000000507270020000000000000000200000434364500a01020200000001000000000050727015e000000000000000200000434364500a01050300000000000100000050727000004e200000000000200000434364500a010801000100000000000000507270010008000800080000200000434364500a040401000100000000000000507270000000000000000000200000434364500a080080000000040000000000507270000000000000000000200000434364500a080180000000040000000000507270000000000000000000200000434364500a080280000000040000000000507270080008000800080000200000434364500a080380000000040000000000507270000000000000000000200000434364500a080480000000020000000000507270040008000000000000200000434364500a08058000000001000000000050727008004e200000000000200000434364500a080680000000020000000000507270000008000800080000200000434364500a0b0080000000020000000000507270000000000000000000200000434364500b000080000000010000000000507270000000000000000000200000434364500b0002800000000100000000005072702a004e200000000000200000434364500b010d01000100000000000000507270000008000800080000200000434364500b010101000100000000000000507270020000000000000000200000434364500b01020200000001000000000050727015e000000000000000200000434364500b01050300000000000100000050727000004e200000000000200000434364500b010801000100000000000000507270010008000800080000200000434364500b040401000100000000000000507270000000000000000000200000434364500b080080000000040000000000507270000000000000000000200000434364500b080180000000040000000000507270000000000000000000200000434364500b080280000000040000000000507270080008000800080000200000434364500b080380000000040000000000507270000000000000000000200000434364500b080480000000020000000000507270040008000000000000200000434364500b08058000000001000000000050727008004e200000000000200000434364500b080680000000020000000000507270000008000800080000200000434364500b0b00800000000200000000004373740000000000000000 +00200000434364500d000080000000010000000000507270000000000000000000200000434364500d0002800000000100000000005072702a004e200000000000200000434364500d010d01000100000000000000507270000008000800080000200000434364500d010101000100000000000000507270020000000000000000200000434364500d01020200000001000000000050727015e000000000000000200000434364500d01050300000000000100000050727000004e200000000000200000434364500d010801000100000000000000507270010008000800080000200000434364500d040401000100000000000000507270000000000000000000200000434364500d080080000000040000000000507270000000000000000000200000434364500d080180000000040000000000507270000000000000000000200000434364500d080280000000040000000000507270080008000800080000200000434364500d080380000000040000000000507270000000000000000000200000434364500d080480000000020000000000507270040008000000000000200000434364500d08058000000001000000000050727008004e200000000000200000434364500d080680000000020000000000507270000008000800080000200000434364500d0b0080000000020000000000507270000000000000000000200000434364500e000080000000010000000000507270000000000000000000200000434364500e0002800000000100000000005072702a004e200000000000200000434364500e010d01000100000000000000507270000008000800080000200000434364500e010101000100000000000000507270020000000000000000200000434364500e01020200000001000000000050727015e000000000000000200000434364500e01050300000000000100000050727000004e200000000000200000434364500e010801000100000000000000507270010008000800080000200000434364500e040401000100000000000000507270000000000000000000200000434364500e080080000000040000000000507270000000000000000000200000434364500e080180000000040000000000507270000000000000000000200000434364500e080280000000040000000000507270080008000800080000200000434364500e080380000000040000000000507270000000000000000000200000434364500e080480000000020000000000507270040008000000000000200000434364500e08058000000001000000000050727008004e200000000000200000434364500e080680000000020000000000507270000008000800080000200000434364500e0b00800000000200000000005072700000000000000000000c00005350744d00010202000c000053505a5300009600000c0000505a435300200e00000c0000496e436d01000000 \ No newline at end of file diff --git a/src/__tests__/connection/constellation-v8.0.2.data b/src/__tests__/connection/constellation-v8.0.2.data new file mode 100644 index 000000000..392c16bbf --- /dev/null +++ b/src/__tests__/connection/constellation-v8.0.2.data @@ -0,0 +1,80 @@ +000c00005f7665720002001d003400005f70696e4154454d20436f6e7374656c6c6174696f6e20384b000801000100000000000000507270010008000b000800002000005f746f70046e04181804010401010200022801000001010101010100000c00005f4d654300040080000c00005f4d654301047270000c00005f4d654302040101000c00005f4d654303040004000c00005f6d706c40040000001400005f4d7643041001010100010100010004000c00005f53534300010400000c00005f53534301010402000c00005f4641434e010000003c00005f46454300040200010000000000001e0000018b0200000200000064000005c804000000000001c200001ee6084a060300000578000054c4012a00005f564d4300164e200400000000000010000000000005068000000000200000000000067000000001004000000000000743436400020080000000000008000000000041000000000000090000000000820000000000000a02000c0001040000000000000b000c000002080000000000000c0c64500005144000000000000d000000000a288000000000000e0000200000410000000000000f00010000008200000000000010000800000104000000000000116450260002080000000000001200005000051440000000000013002010000a28800000000000140000040010410000000000011500000000208200000000000116502608004104000000000001170050720082080000000000011820440001451400000000000119000400028a28000000000001000c00005f4d4143644f4343002000005f44564500010011101112131415161718191a1b1c1d1e1f22504343000c0000506f777203020000000c00005669644d06000000000c00005633736c00502608000c000054634c6b00000050002c0000496e507200014c495645203100502608068000000002000000004c31007000000001000100001f0f002c0000496e507200024c495645203200000050727000000000000000004c32005000430001000100801f0f002c0000496e507200034c495645203300000020727043436450270002804c33000100000001000100701f0f002c0000496e507200044c495645203400010001000000000000005072704c34000000000001000100701f0f002c0000496e507200054c495645203500700200000000000000002072704c35005000010001000100011f0f002c0000496e507200064c495645203600704343645027010503000000004c36000000500001000100201f0f002c0000496e507200074c495645203700000000000000507270010008004c37000000200001000100501f0f002c0000496e507200084c495645203800000000000000207270434364504c38008000000001000100001f0f002c0000496e507200094c495645203900502708018000000004000000004c39000100000001000100001f0f002c0000496e5072000a4c495645203130000001010108000800080008004c31300000430001000100801f0f002c0000496e5072000b4b414d20310000000020727043436450270804804b31000200000001000100031f0f002c0000496e5072000c4b414d203200cd0a0400000004000000245ccd0a4b32000a00000001000100021f0f002c0000496e5072000d4b414d2033000000c0e70102145ccd0a040000004b33000000dc0001000100001f0f002c0000496e5072000e4b414d2034000a0001000000644a01021edcdc024b34000000180001000100021f0f002c0000496e5072000f4b414d20350000007e180d0278646975736366584b35005300460001000100721f0f002c0000496e507200104b414d2031730002d0d07f0400000000084a06034b31730000000001000100001f0f002c0000496e507200114b414d20327300de0a0aadde0a0aadde010000004b32730000420001000100001f0f +002c0000496e507200124b414d2033730070696e4154454d20436f6e73744b33730000690001000100001f0f002c0000496e507200134b414d2034730000080000204f505f746f70046e4b34730000040001000100281f0f002c0000496e507200144b414d20357300040080000c00045f4d654301044b35730000000001000100041f0f002c0000496e5072001556697a204f766c2066696c6c0000001406035f4d6f766c4600010001000100011f0f002c0000496e507200164450202865767329004301010402000c00005f464556530000000001000100461f0f002c0000496e50720017001e0000018b0200000200000064000005c804000000000000c200010001004a1f0f002c0000496e5072001800005f564d4300164e20040000000000001000000000000500800001000100001f0f002c0000496e5072001900000000000743436400020080000000000008000000000000000001000100091f0f002c0000496e5072001a536572766572204100000000000b000c000002084100000000000001000100051f0f002c0000496e5072001b53657276657220420000002000004100000000004200000100000001000100001f0f002c0000496e5072001c53657276657220430008000000000000120000504300144000000001000100201f0f002c0000496e5072001d4a696e676c652046696c6c0000000000208200004a696e4600500001000100001f0f002c0000496e5072001e4456452066696c6c0000014514000000000001196476654600280001000100011f0f002c0000496e5072001f4a696e676c65204b6579001110111213141516176a696e4b001d0001000100431f0f002c0000496e50720020445645206b65790006000000000c00205633736c6476654b000c00010001006b1f0f002c0000496e5072002100014c495645203100502608068000000002000000004c3100700001000100011f0f002c0000496e5072002256697a206f766c206b65790072700000000000006f766c4b00500001000100011f0f002c0000496e5072002344502b20286576732b29002072704343645027006576732b00010001000100011f0f002c0000496e50720024536f6669652055520001000100000000000000505552003400000001000100011f0f002c0000496e5072002550726f6d707465722041000000000000000000205072410000500001000100011f0f002c0000496e5072002650726f6d707465722042004364502701050300005072420000000001000100011f0f002c0000496e5072002700074c495645203700000000000000507270010000004c3700000001000100011f0f002c0000496e5072002800084c495645203800000000000000207270434300504c3800800001000100011f0f002c0000496e50720000426c61636b002039005027080180000000040000426c6b0001010100010001011f0f002c0000496e507203e8436f6c6f722042617273000101010800080008004261727301000100010002011f0f002c0000496e507207d1436f6c6f72203100000000207270434364502708436f6c3101020100010003010f0f002c0000496e507207d2436f6c6f72203200cd0a0400000004000000245c436f6c32010a0100010003010f0f002c0000496e50720bc24d6564696120506c617965722031005ccd0a04004d50310001000100010004011f0f002c0000496e50720bc34d6564696120506c617965722031204b657900dc4d50314b01000100010005011f0f002c0000496e50720bcc4d6564696120506c6179657220320064697573634d50320001530100010004011f0f002c0000496e50720bcd4d6564696120506c617965722032204b6579004a4d50324b01000100010005011f0f002c0000496e50720bd64d6564696120506c617965722033000aadde01004d50330001000100010004011f0f +002c0000496e50720bd74d6564696120506c617965722033204b657900744d50334b01690100010005001f0f002c0000496e50720be04d6564696120506c61796572203400746f70046e4d50340001040100010004281f0f002c0000496e50720be14d6564696120506c617965722034204b657900044d50344b01000100010005041f0f002c0000496e507217705375706572536f75726365203100001406035f4d5353310001010100010006011b0f002c0000496e507217715375706572536f75726365203200000c00005f465353320001000100010006461b0f002c0000496e50720faa4d452031204b65792031204d61736b0005c804004d314b3101c201000100824a0300002c0000496e50720fb44d452031204b65792032204d61736b00001000004d314b3201800100010082000300002c0000496e50720fbe4d452031204b65792033204d61736b00000008004d314b3301000100010082090300002c0000496e50720fc84d452031204b65792034204d61736b00000002084d314b3401000100010082050300002c0000496e50720fd24d452032204b65792031204d61736b00000000004d324b3101000100010082000300002c0000496e50720fdc4d452032204b65792032204d61736b00120000504d324b3201000100010082200300002c0000496e50720fe64d452032204b65792033204d61736b00208200004d324b3301500100010082000300002c0000496e50720ff04d452032204b65792034204d61736b00000001194d324b3401280100010082010300002c0000496e50720ffa4d452033204b65792031204d61736b00141516174d334b31011d0100010082430300002c0000496e507210044d452033204b65792032204d61736b005633736c4d334b32010c01000100826b0300002c0000496e5072100e4d452033204b65792033204d61736b00000200004d334b3301700100010082010300002c0000496e507210184d452033204b65792034204d61736b00000000004d334b3401500100010082010300002c0000496e507210224d452034204b65792031204d61736b00645027004d344b3101010100010082010300002c0000496e5072102c4d452034204b65792032204d61736b00000000504d344b3201000100010082010300002c0000496e507210364d452034204b65792033204d61736b00000000204d344b3301500100010082010300002c0000496e507210404d452034204b65792034204d61736b00050300004d344b3401000100010082010300002c0000496e5072139244534b2031204d61736b00000000005072700100444b314d01000100010082010300002c0000496e5072139c44534b2032204d61736b00000000002072704343444b324d01800100010082010300002c0000496e507213a644534b2033204d61736b00080180000000040000444b334d01010100010082010300002c0000496e507213b044534b2034204d61736b00010101080008000800444b344d01000100010082010300002c0000496e5072271a4d4520312050474d0000002072704343645027084d2f453101020100010080010300002c0000496e5072271b4d45203120505657000a0400000004000000245c50767731010a0100010080010300002c0000496e507227244d4520322050474d007965722031005ccd0a04004d2f453201000100010080010b01002c0000496e507227254d45203220505657007965722031204b657900dc5076773201000100010080010b01002c0000496e5072272e4d4520332050474d0079657220320064697573634d2f453301530100010080010b03002c0000496e5072272f4d45203320505657007965722032204b6579004a5076773301000100010080010b03002c0000496e507227384d4520342050474d007965722033000aadde01004d2f453401000100010080010b07 +002c0000496e507227394d45203420505657007965722033204b657900745076773401690100010080000b07002c0000496e50721b59436c65616e20466565642031003400746f70046e4366643101040100010080280300002c0000496e50721b5a436c65616e204665656420320034204b657900044366643201000100010080040300002c0000496e50721b5b436c65616e204665656420330000001406035f4d4366643301010100010080010300002c0000496e50721b5c436c65616e204665656420340000000c00005f464366643401000100010080460300002c0000496e50721f4150474d20284d65312900204d61736b0005c8040050474d0000c201000100814a0200002c0000496e50721f4250474d20434c45414e20286d6534290000100000434c4e0000800100010081000200002c0000496e50721f434155582031202877616c6c2900736b00000008004155583100000100010081090200002c0000496e50721f4441555820322028617229004d61736b00000002084155583200000100010081050200002c0000496e50721f45415558203320286f766c290061736b00000000004155583300000100010081000200002c0000496e50721f464155582034202866756c6c2900736b00120000504155583400000100010081200200002c0000496e50721f4741555820352028766964656f206d6978206d692950474d2d00500100010081000200002c0000496e50721f484155582036202876656e756529006b00000001194155583600280100010081010200002c0000496e50721f4941555820372028536f666965206e2e205056572950565700001d0100010081430200002c0000496e50721f4a4f757470757420313000204d61736b005633736c4f743130010c01000100816b0200002c0000496e50721f4b4f757470757420313100204d61736b00000200004f74313101700100010081010200002c0000496e50721f4c4f757470757420313200204d61736b00000000004f74313201500100010081010200002c0000496e50721f4d4f757470757420313300204d61736b00645027004f74313301010100010081010200002c0000496e50721f4e4f757470757420313400204d61736b00000000504f74313401000100010081010200002c0000496e50721f4f4f757470757420313500204d61736b00000000204f74313501500100010081010200002c0000496e50721f504f757470757420313600204d61736b00050300004f74313601000100010081010200002c0000496e50721f514f757470757420313700000000000050727001004f74313701000100010081010200002c0000496e50721f524f757470757420313800000000000020727043434f74313801800100010081010200002c0000496e50721f534f757470757420313900000801800000000400004f74313901010100010081010200002c0000496e50721f544f757470757420323000000101010800080008004f74323001000100010081010200002c0000496e50721f554f757470757420323100002072704343645027084f74323101020100010081010200002c0000496e50721f564f7574707574203232000400000004000000245c4f743232010a0100010081010200002c0000496e50721f574f75747075742032330065722031005ccd0a04004f74323301000100010081010200002c0000496e50721f584f75747075742032340065722031204b657900dc4f74323401000100010081010200000c00004d76564d04044d45000c00004d76564d05052032000c00004d76564d06060153000c00004d76564d0707002c000c00004d76564d08082050000c00004d76564d09096579000c00004d76564d0a0a0100000c00004d76564d0b0b5072000c00004d76564d0c0c0079000c00004d76564d0d0d4d2f000c00004d76564d0e0e0b07 +000c00004d76564d0f0f4d45000c00004d76564d10102033000c00004d76564d11110169000c00004d76564d12120000000c00004d76564d13136e20000c00004d76564d14146f70000c00004d76564d15150100000c00004d76564d16165072000c00004d76564d17176564000c00004d76564d18184366000c00004d76564d19190300000c00004d765072000c006c001000004d76496e0000177000000603000c000056754d4300000000000c000053614d7700000172001000004d76496e0001000201000000000c000056754d4300010100000c000053614d7700010000001000004d76496e0002271a01002900000c000056754d4300020147000c000053614d7700020100001000004d76496e000300040100434c000c000056754d4300030110000c000053614d7700030000001000004d76496e0004000501004155000c000056754d4300040173000c000053614d7700040000001000004d76496e0005000601005072000c000056754d4300050129000c000053614d7700050055001000004d76496e0006000701000000000c000056754d4300060120000c000053614d7700060000001000004d76496e0007000801000200000c000056754d4300070155000c000053614d7700070073001000004d76496e0008001501000100000c000056754d4300080172000c000053614d7700080164001000004d76496e0009002201000050000c000056754d4300090117000c000053614d7700090020001000004d76496e000a001d01004155000c000056754d43000a0100000c000053614d77000a0155001000004d76496e000b001e01005056000c000056754d43000b0100000c000053614d77000b0072001000004d76496e000c001a01006173000c000056754d43000c010c000c000053614d77000c002c001000004d76496e000d001b01003100000c000056754d43000d0174000c000053614d77000d0000001000004d76496e000e001c01007574000c000056754d43000e0100000c000053614d77000e0000001000004d76496e000f000101004f75000c000056754d43000f0173000c000053614d77000f0001000c000056754d6f0064002c000c00004d765072010c0074001000004d76496e0100177000004f74000c000056754d4301000000000c000053614d7701000075001000004d76496e0101001201000000000c000056754d4301010100000c000053614d7701010072001000004d76496e0102271a01006173000c000056754d4301020000000c000053614d770102012c001000004d76496e0103001401003700000c000056754d4301030174000c000053614d7701030000001000004d76496e0104001501007574000c000056754d4301040170000c000053614d7701040000001000004d76496e0105001601004f75000c000056754d4301050180000c000053614d7701050001001000004d76496e0106001701005072000c000056754d4301060100000c000053614d7701060074001000004d76496e010700180100002c000c000056754d4301070174000c000053614d7701070050001000004d76496e0108001501000200000c000056754d4301080175000c000053614d7701080100001000004d76496e0109002201000100000c000056754d4301090172000c000053614d7701090000001000004d76496e010a001d01000100000c000056754d43010a012c000c000053614d77010a0174001000004d76496e010b001e01004f74000c000056754d43010b0100000c000053614d77010b0045001000004d76496e010c001a01006975000c000056754d43010c0100000c000053614d77010c0072001000004d76496e010d001b0100564d000c000056754d43010d014d000c000053614d77010d004d001000004d76496e010e001c01000079000c000056754d43010e012f000c000053614d77010e0007 +001000004d76496e010f000101002050000c000056754d43010f0179000c000053614d77010f0000000c000056754d6f01645072000c00004d765072020f0064001000004d76496e020000210100564d000c000056754d430200014d000c000053614d770200014d001000004d76496e0201002201004366000c000056754d4302010100000c000053614d770201006c001000004d76496e0202002301000603000c000056754d4302020100000c000053614d7702020172001000004d76496e0203002401000000000c000056754d4302030100000c000053614d7702030000001000004d76496e0204002501002900000c000056754d4302040147000c000053614d7702040000001000004d76496e020500260100434c000c000056754d4302050110000c000053614d7702050000001000004d76496e0206002701004155000c000056754d4302060173000c000053614d7702060000001000004d76496e0207002801005072000c000056754d4302070129000c000053614d7702070055001000004d76496e02081f4101000000000c000056754d4302080120000c000053614d7702080100001000004d76496e02091f4201000200000c000056754d4302090155000c000053614d7702090073001000004d76496e020a1f4301000100000c000056754d43020a0172000c000053614d77020a0164001000004d76496e020b1f4401000050000c000056754d43020b0117000c000053614d77020b0020001000004d76496e020c1f4501004155000c000056754d43020c0100000c000053614d77020c0055001000004d76496e020d1f4601005056000c000056754d43020d0100000c000053614d77020d0072001000004d76496e020e1f4701006173000c000056754d43020e010c000c000053614d77020e002c001000004d76496e020f1f4801003100000c000056754d43020f0174000c000053614d77020f0000000c000056754d6f0264001c000c00004d765072030f0043001000004d76496e03001f4901000000000c000056754d4303000101000c000053614d7703000143001000004d76496e03011f4a01000001000c000056754d430301012c000c000053614d7703010074001000004d76496e03021f4b01004f74000c000056754d4303020100000c000053614d7703020175001000004d76496e03031f4c01000000000c000056754d4303030100000c000053614d7703030072001000004d76496e03041f4d01006173000c000056754d4303040100000c000053614d770304002c001000004d76496e03051f4e01003700000c000056754d4303050174000c000053614d7703050000001000004d76496e03061f4f01007574000c000056754d4303060170000c000053614d7703060000001000004d76496e03071f5001004f75000c000056754d4303070180000c000053614d7703070001001000004d76496e03081f5101005072000c000056754d4303080100000c000053614d7703080174001000004d76496e03091f520100002c000c000056754d4303090174000c000053614d7703090050001000004d76496e030a1f5301000200000c000056754d43030a0175000c000053614d77030a0100001000004d76496e030b1f5401000100000c000056754d43030b0172000c000053614d77030b0000001000004d76496e030c1f5501000100000c000056754d43030c012c000c000053614d77030c0074001000004d76496e030d1f5601004f74000c000056754d43030d0100000c000053614d77030d0045001000004d76496e030e1f5701006975000c000056754d43030e0100000c000053614d77030e0072001000004d76496e030f1f580100564d000c000056754d43030f014d000c000053614d77030f004d000c000056754d6f0364001c000c000050726749007507d1001000005072764900610012000e0007 +00100000547253530000010001002050000c000054725072000001790010000054725073000019000000564d000c0000544d78500019564d000c00005444705000190000001c0000545770500019014d00000000138800001388138800005072001c0000544476500019191b000000000000000000000000000c0100001c0000545374500000005000000000000100000019000d0001496e000c00004b654f6e00000066001c00004b6542500000000101000000000000720000000000000000001400004b654c6d000000000000000000030100002000004b41436b00000000000001f4000000000000000003e8000000000000001800004b41434300000000c3e920bf02711620083d0530001800004b6550740000004c00001388000001f401f40010004400004b654456000000000000000000000000000000000000000000000000000000430000000000000000006100000000000000000000000000000000000001005072001000004b65465300000000000c0073003c00004b4b465000000100000003e8000003e8000000000000000000000000000000000000ff005c610000000003e8016819550000000000000000003c00004b4b465000000243000003e8000003e80000000000000000000000000000000000000000ff000000000003e8016819430000000000000000000c00004b654f6e0001006d001c00004b6542500001000101000000000000430000000000000000001400004b654c6d0001006e00000000000c1f45002000004b41436b00010000000001f4000000000000000003e8000000000000001800004b41434300010000c3e920bf02711620083d0530001800004b6550740001007200001388000001f401f40047004400004b65445600014d4300000000000000000000000000000000000000000000006e0000000000000000000c000000000000000000000000000000000000010f0000001000004b65465300010000000c0074003c00004b4b465000010100000003e8000003e8000000000000000000000000000000000000ff005c610000000003e8016819730000000000000000003c00004b4b465000010243000003e8000003e80000000000000000000000000000000000000000ff000000000003e8016819430000000000000000000c00004b654f6e00020074001c00004b6542500002000101000000000000430000000000000000001400004b654c6d000200750000000000041f4d002000004b41436b00020000000001f4000000000000000003e8000000000000001800004b41434300020000c3e920bf02711620083d0530001800004b6550740002000000001388000001f401f4004f004400004b65445600024d4300000000000000000000000000000000000000000000006e0000000000000000000c00000000000000000000000000000000000001070001001000004b6546530002000000000072003c00004b4b465000020100000003e8000003e8000000000000000000000000000000000000ff005c0c0000000003e8016819740000000000000000003c00004b4b46500002026e000003e8000003e80000000000000000000000000000000000000000ff0a0000000003e80168196e0000000000000000000c00004b654f6e00030072001c00004b65425000030001010000000000006e0000000000000000001400004b654c6d0003002c0000000000614d77002000004b41436b00030000000001f4000000000000000003e8000000000000001800004b41434300030000c3e920bf02711620083d0530001800004b6550740003004300001388000001f401f40077004400004b6544560003496e0000000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000017507d1001000004b65465300030000000e0007 +003c00004b4b465000030100000003e8000003e8000000000000000000000000000000000000ff005c000000000003e8016819500000000000000000003c00004b4b46500003026e000003e8000003e80000000000000000000000000000000000000000ff440000000003e8016819000000000000000000000c000050726749015300000010000050727649010100000019000d00100000547253530100010001000066000c0000547250720100000100100000547250730100190000000000000c0000544d785001190000000c00005444705001190000001c000054577050011901f400000000138800001388138800000000001c0000544476500119191b0000000000000000000000000018496e001c000054537450010000880000000000f400000019000d00014456000c00004b654f6e01000000001c00004b6542500100000101000000000000000000000000000000001400004b654c6d010000000000000000005072002000004b41436b01000000000001f4000000000000000003e8000000000000001800004b41434301000000c3e920bf02711620083d0530001800004b6550740100005500001388000001f401f40000004400004b654456010003e8000000000000000000000000000000000000000000000000000000000000000000680000000000000000000000000000000000000101006d001000004b6546530100000000000000003c00004b4b465001000100000003e8000003e8000000000000000000000000000000000000ff005c010000000003e8016819000000000000000000003c00004b4b465001000243000003e8000003e80000000000000000000000000000000000000000ff000000000003e8016819470000000000000000000c00004b654f6e01010000001c00004b6542500101000101000000000000000000000000000000001400004b654c6d0101000000000000000f0000002000004b41436b01010000000001f4000000000000000003e8000000000000001800004b41434301010000c3e920bf02711620083d0530001800004b6550740101007300001388000001f401f40001004400004b654456010103e80000000000000000000000000000000000000000000000000000000000000000006800000000000000000000000000000000000001020074001000004b6546530101000000000000003c00004b4b465001010100000003e8000003e8000000000000000000000000000000000000ff005c020000000003e8016819000000000000000000003c00004b4b465001010243000003e8000003e80000000000000000000000000000000000000000ff000000000003e80168194f0000000000000000000c00004b654f6e01020000001c00004b6542500102000101000000000000000000000000000000001400004b654c6d010200000000000000070001002000004b41436b01020000000001f4000000000000000003e8000000000000001800004b41434301020000c3e920bf02711620083d0530001800004b6550740102007400001388000001f401f40050004400004b654456010203e80000000000000000000000000000000000000000000000000000000000000000006800000000000000000000000000000000000001030072001000004b6546530102000000000000003c00004b4b465001020100000003e8000003e8000000000000000000000000000000000000ff005c030000000003e8016819000000000000000000003c00004b4b465001020243000003e8000003e80000000000000000000000000000000000000000ff000000000003e8016819770000000000000000000c00004b654f6e01030000001c00004b6542500103000101000000000000000000000000000000001400004b654c6d0103000000000000007507d1 +002000004b41436b01030000000001f4000000000000000003e8000000000000001800004b41434301030000c3e920bf02711620083d0530001800004b6550740103005000001388000001f401f400e8004400004b65445601030000000000000000000000000000000000000000000000000000000000000000000000720000000000000000000000000000000000000119000d001000004b6546530103000000000066003c00004b4b465001030101000003e8000003e8000000000000000000000000000000000000ff005c0c0000000003e8016819000000000000000000003c00004b4b465001030200000003e8000003e80000000000000000000000000000000000000000ff000000000003e8016819740000000000000000000c000050726749021900000010000050727649026500000000000000100000547253530200010001000000000c0000547250720200000000100000547250730200190000000000000c0000544d78500219436b000c00005444705002190000001c00005457705002190100000000001388000013881388000020bf001c0000544476500219191b000000000000000000000000000001f4001c0000545374500200005600000000000000000019000d00010000000c00004b654f6e02000000001c00004b6542500200000101000000000000000000000000000000001400004b654c6d020000530000000000000000002000004b41436b02000000000001f4000000000000000003e8000000000000001800004b41434302000000c3e920bf02711620083d0530001800004b6550740200005000001388000001f401f400e8004400004b654456020000000000000000000000000000000000000000000000000000000000000000000000006500000000000000000000000000000000000001000000001000004b6546530200000000140000003c00004b4b465002000100000003e8000003e8000000000000000000000000000000000000ff005ce80000000003e8016819e80000000000000000003c00004b4b465002000230000003e8000003e80000000000000000000000000000000000000000ff650000000003e8016819000000000000000000000c00004b654f6e02010000001c00004b6542500201000101000000000000000000000000000000001400004b654c6d020100530000000000000000002000004b41436b02010000000001f4000000000000000003e8000000000000001800004b41434302010000c3e920bf02711620083d0530001800004b6550740201005000001388000001f401f400e8004400004b654456020100000000000000000000000000000000000000000000000000000000000000000000006500000000000000000000000000000000000001000000001000004b6546530201000000140000003c00004b4b465002010100000003e8000003e8000000000000000000000000000000000000ff005ce80000000003e8016819e80000000000000000003c00004b4b465002010230000003e8000003e80000000000000000000000000000000000000000ff650000000003e8016819000000000000000000000c00004b654f6e02020000001c00004b6542500202000101000000000000000000000000000000001400004b654c6d020200530000000000000000002000004b41436b02020000000001f4000000000000000003e8000000000000001800004b41434302020000c3e920bf02711620083d0530001800004b6550740202005000001388000001f401f400e8004400004b654456020200000000000000000000000000000000000000000000000000000000000000000000006500000000000000000000000000000000000001000000001000004b6546530202000000140000 +003c00004b4b465002020100000003e8000003e8000000000000000000000000000000000000ff005c030000000003e8016819200000000000000000003c00004b4b465002020288000003e8000003e80000000000000000000000000000000000000000ff000000000003e8016819000000000000000000000c00004b654f6e02030000001c00004b65425002030001010000000000006e0000000000000000001400004b654c6d0203005000000000000003e8002000004b41436b02030000000001f4000000000000000003e8000000000000001800004b41434302030000c3e920bf02711620083d0530001800004b6550740203000000001388000001f401f40000004400004b654456020303e80000000000000000000000000000000000000000000000000000000000000000006500000000000000000000000000000000000001000000001000004b6546530203000000100000003c00004b4b465002030100000003e8000003e8000000000000000000000000000000000000ff005c570000000003e8016819000000000000000000003c00004b4b465002030250000003e8000003e80000000000000000000000000000000000000000ff000000000003e8016819000000000000000000000c000050726749030007d1001000005072764903000000000000000010000054725353030001000114006d000c0000547250720300000000100000547250730300196b00000000000c0000544d785003190000000c00005444705003190000001c000054577050031901bf00000000138800001388138800005074001c0000544476500319191b00000000000000000000000000000000001c0000545374500300000000000000000000000019000d00010000000c00004b654f6e03000000001c00004b6542500300000101000000000000000000000000000000001400004b654c6d0300005000000000000003e8002000004b41436b03000000000001f4000000000000000003e8000000000000001800004b41434303000000c3e920bf02711620083d0530001800004b6550740300000000001388000001f401f40000004400004b654456030003e80000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000001140074001000004b6546530300000000000000003c00004b4b465003000100000003e8000003e8000000000000000000000000000000000000ff005c010000000003e8016819200000000000000000003c00004b4b465003000288000003e8000003e80000000000000000000000000000000000000000ff000000000003e8016819000000000000000000000c00004b654f6e03010000001c00004b654250030100010100001d001f00000000000000000000001400004b654c6d0301015000000000000003e8002000004b41436b03010000000001f4000000000000000003e8000000000000001800004b41434303010000c3e920bf02711620083d0530001800004b6550740301000000001388000001f401f40000004400004b654456030103e80000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000001140072001000004b6546530301000000000000003c00004b4b465003010100000003e8000003e8000000000000000000000000000000000000ff005c020000000003e8016819200000000000000000003c00004b4b465003010288000003e8000003e80000000000000000000000000000000000000000ff000000000003e8016819000000000000000000000c00004b654f6e03020000001c00004b6542500302000101000000000000000000000000000000001400004b654c6d0302000000000000007507d1 +002000004b41436b03020000000001f4000000000000000003e8000000000000001800004b41434303020000c3e920bf02711620083d0530001800004b6550740302005000001388000001f401f400e8004400004b654456030200000000000000000000000000000000000000000000000000000000000000000000006500000000000000000000000000000000000001000000001000004b6546530302000000140066003c00004b4b465003020100000003e8000003e8000000000000000000000000000000000000ff005ce80000000003e8016819000000000000000000003c00004b4b465003020230000003e8000003e80000000000000000000000000000000000000000ff650000000003e8016819000000000000000000000c00004b654f6e03030000001c00004b6542500303000101000000000000000000000000000000001400004b654c6d030300530000000000100000002000004b41436b03030000000001f4000000000000000003e8000000000000001800004b41434303030000c3e920bf02711620083d0530001800004b6550740303005000001388000001f401f400e8004400004b654456030300000000000000000000000000000000000000000000000000000000000000000000007200000000000000000000000000000000000001000000001000004b654653030300000014006d003c00004b4b465003030100000003e8000003e8000000000000000000000000000000000000ff005c0c0000000003e8016819000000000000000000003c00004b4b465003030200000003e8000003e80000000000000000000000000000000000000000ff000000000003e80168190000000000000000000010000044736b420019001500220000001c000044736b5000001901000000000000000000000000000000000010000044736b5300010000001900000010000044736b420100001d001f03e8001c000044736b5001001900000000000000000000000000000000000010000044736b5301010000001900000010000044736b42023d0000000003e8001c000044736b5002001900000000000000000000000000000044560010000044736b5302000000011900000010000044736b420300000000000000001c000044736b5003001900000000000000000000000000000000740010000044736b530300000001190000000c00004674625000190100000c00004674625300000019000c00004674625001190000000c00004674625301000019000c00004674625002190000000c00004674625302000019000c00004674625003190000000c0000467462530300001900100000436f6c56000007c603e8022b00100000436f6c56010c010e03e801f4000c0000417578530065271a000c000041757853011f2738000c00004175785302140000000c00004175785303000000000c00004175785304410000000c00004175785305000000000c00004175785306000000000c00004175785307010000000c000041757853083d1770000c00004175785309011770000c0000417578530af40000000c0000417578530b010000000c0000417578530c000000000c0000417578530d000000000c0000417578530e020000000c0000417578530f000000000c00004175785310100000000c00004175785311000000000c00004175785312010000000c00004175785313000000000c00004175785314000000000c00004175785315000000000c00004175785316000000000c00004175785317010000001400004d505370019001900190019000000000004c00004d50435300000000000003e8016819000000000000000000000c00004b654f6e03020000001c00004b6542500302000101000000000000000000000000000000001400004b650000 +005c00004d504153010000000000000000000000000000000000000000000000001800004b41434303020000c3e920bf02711620083d0530001800004b6550740302005000001388000001f401f400e8004400004b65445603020000004c00004d5043530100000000000000000000000000000000000000000000000065000000000000000000000000000000000000010000000010006e4b6546530302000000140066003c0000005c00004d5041530200000000000000000000000000000000000000000000000000ff005ce80000000003e8016819000000000000000000003c20bf4b4b465003020230000003e8000003e800000000000000000000000000000000004c00004d504353020000e8016819000000000000000000000c00004b654f6e03030000001c00004b6542500303000101000000000000000000000000000000001400004b654c6d03030000005c00004d50415303000000000000000000000000000000000000000000000003e8000000000000001800004b41434303030000c3e920bf02711620083d0530001800004b6550740303005000001388000001f401f400e800440000004c00004d5043530300000000000000000000000000000000000000000000000000000000000000007200000000000000000000000000000000000001000000001000004b65465303030000005c00004d50415304000000000000000000000000000000000000000000000000000000000000000000ff005c0c0000000003e8016819000000000000000000003c01bf4b4b465003030200000003e8000003e80000000000000000002000004d506665000000000000000000000000000000000000000000000000002000004d506665001900010000000000000000000000000000000000000000002000004d506665000000020000000000000000000000000000000000100000002000004d506665001f00030000000000000000000000000000000000000000002000004d506665001000040000000000000000000000000000000000730000002000004d506665001c00050000000000000000000000000000000000000000002000004d506665007300060000000000000000000000000000000000000000002000004d506665007300070000000000000000000000000000000000000000002000004d5066650000000800000000000000000000000000000000000c0000002000004d506665000c00090000000000000000000000000000000000000000002000004d5066650019000a0000000000000000000000000000000000740000002000004d5066650074000b0000000000000000000000000000000000e80000002000004d506665000c000c00000000000000000000000000000000000c0000002000004d506665000c000d0000000000000000000000000000000000000000002000004d5066650041000e0000000000000000000000000000000000750000002000004d5066650075000f00000000000000000000000000000000000c0000002000004d506665000c00100000000000000000000000000000000000010000002000004d506665000000110000000000000000000000000000000000750000002000004d5066650075001200000000000000000000000000000000000c0000002000004d506665000c00130000000000000000000000000000000000000000002000004d506665000000140000000000000000000000000000000000750000002000004d506665007500150000000000000000000000000000000000900000002000004d506665005000160000000000000000000000000000000000000000002000004d506665000200170000000000000000000000000000000000000000002000004d506665001400180000000000000000000000000000000000100000 +002000004d506665000000190000000000000000000000000000000000000000002000004d5066650002001a0000000000000000000000000000000000650000002000004d5066650000001b00000000000000000000000000000000004c0000002000004d5066650000001c0000000000000000000000000000000000650000002000004d5066650000001d0000000000000000000000000000000000020000002000004d506665005c001e0000000000000000000000000000000000000000002000004d5066650000001f0000000000000000000000000000000000000000002000004d506665000200200000000000000000000000000000000000000000002000004d5066650050002100000000000000000000000000000000000c0000002000004d506665001c00220000000000000000000000000000000000000000002000004d506665006500230000000000000000000000000000000000000000002000004d506665000000240000000000000000000000000000000000410000002000004d506665007100250000000000000000000000000000000000000000002000004d506665004400260000000000000000000000000000000000000000002000004d506665000000270000000000000000000000000000000000000000002000004d506665000000280000000000000000000000000000000000500000002000004d506665000000290000000000000000000000000000000000000000002000004d5066650000002a00000000000000000000000000000000004b0000002000004d5066650000002b0000000000000000000000000000000000000000002000004d5066650000002c0000000000000000000000000000000000190000002000004d5066650000002d0000000000000000000000000000000000000000002000004d5066650000002e00000000000000000000000000000000001f0000002000004d5066650000002f0000000000000000000000000000000000100000002000004d5066650000003000000000000000000000000000000000001c0000002000004d506665000000310000000000000000000000000000000000730000002000004d506665000000320000000000000000000000000000000000730000002000004d506665000000330000000000000000000000000000000000000000002000004d5066650000003400000000000000000000000000000000000c0000002000004d506665000000350000000000000000000000000000000000190000002000004d506665000000360000000000000000000000000000000000740000002000004d5066650000003700000000000000000000000000000000000c0000002000004d5066650000003800000000000000000000000000000000000c0000002000004d506665000000390000000000000000000000000000000000410000002000004d5066650000003a0000000000000000000000000000000000750000002000004d5066650000003b00000000000000000000000000000000000c0000002000004d5066650000003c0000000000000000000000000000000000000000002000004d5066650000003d0000000000000000000000000000000000750000002000004d5066650000003e00000000000000000000000000000000000c0000002000004d5066650000003f0000000000000000000000000000000000000000 +058000004d50664d0100000005700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007 +058000004d50664d0100005705700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007 +058000004d50664d010000ae05700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007 +058000004d50664d0100010505700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007 +035000004d50664d0100015c0340000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +058000004d50664d0200000005700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007 +058000004d50664d0200005705700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007 +058000004d50664d020000ae05700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007 +058000004d50664d0200010505700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007 +035000004d50664d0200015c0340000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +058000004d50664d0300000005700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007 +058000004d50664d0300005705700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007 +058000004d50664d030000ae05700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007 +058000004d50664d0300010505700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007 +035000004d50664d0300015c0340000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +058000004d50664d0400000005700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007 +058000004d50664d0400005705700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007 +058000004d50664d040000ae05700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007 +058000004d50664d0400010505700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007 +035000004d50664d0400015c0340000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c00004d5043450001000000100000524350530000000100000000000c00004d5043450101010100100000524350530100000100000000000c00004d5043450201020200100000524350530200000100000000000c00004d5043450301030300100000524350530300000100000000001c000052584d530000000000000000000000000000000000020000001c000052584350000001000000000000000000000000000000000000280000525853530000000000000000ffffffff0000000000000000000000000000000000000000000c00005258434300000000001c000052584d530001000000000000000000000000000000020000001c000052584350000101000000000000000000000000000000000000280000525853530001000000000000ffffffff0000000000000000000000000000000000000000000c00005258434300010000001c000052584d530002000000000000000000000000000000020000001c000052584350000201000000000000000000000000000000000000280000525853530002000000000000ffffffff0000000000000000000000000000000000000000000c00005258434300020000001c000052584d530003000000000000000000000000000000020000001c000052584350000301000000000000000000000000000000000000280000525853530003000000000000ffffffff0000000000000000000000000000000000000000000c00005258434300030000000c00005353437300000000 +00180000535372630000001e002001010000000000000000002000005353426400000000000000000000000000000000000000000a00000000200000535342500000010003e8fce000320244010000000000000007d0000000200000535342500001010003e803200032024400000000000000000000000000200000535342500002000000000000000003e800000000000000000000000000200000535342500003000000000000000003e8000000000000000000000000001800005353726301000000000000000000000000000000002000005353426401000000000000000000000000000000000000000a00000000200000535342500100000000000000000003e800000000000000000000000000200000535342500101000000000000000003e800000000000000000000000000200000535342500102000000000000000003e800000000000000000000000000200000535342500103000000000000000003e8000000000000000000000000000c0000464d505000000000001800004641495000010000000100010000020602000000003c0000464153500001000000000000ffffffffffff010001000000000000000000000006010000000000000000000000000000fffffff807010000002c0000414542500001000000000000ffffffffffff010000003310010100000000002e0000000000470000002c0000414542500001000000000000ffffffffffff010001012d010f010000000000310000000000500000002c0000414542500001000000000000ffffffffffff010002012d040f020000000000ab0000000000e60000002c0000414542500001000000000000ffffffffffff010003012d040f0400000000031e0000000000e60000002c0000414542500001000000000000ffffffffffff010004012d200f08000000001c5c0000000000500000002c0000414542500001000000000000ffffffffffff0100050033020808000000003264000000000047000000300000414958500001000000000000ffffffffffff010000000000ffffee6c0708006e0000008c000000000000245400300000414943500001000000000000ffffffffffff010000000000fffff25400c800000000008c0000000000002454002c000041494c500001000000000000ffffffffffff0100000c0000fffffb50000000470000000000002454001800004641495000020000000200010000020602100000003c00004641535000020000000c0000ffffffffffff0100010000000000000000000000060100000000000000000000000003030000000007015053002c0000414542500002000052584d53ffffffffffff010000003310010100000000002e0000000000474350002c0000414542500002000000000000ffffffffffff010001012d010f010000000000310000000000500000002c0000414542500002000000000000ffffffffffff010002012d040f020000000000ab0000000000e60000002c00004145425000020000001c0000ffffffffffff010003012d040f0400000000031e0000000000e60000002c00004145425000020000ffffffffffffffffffff010004012d200f08000000001c5c0000000000504343002c00004145425000024d5300020000ffffffffffff0100050033020808000000003264000000000047010000300000414958500002000000000000ffffffffffff010000000000ffffee6c0708006e0000008c000000000000245400300000414943500002000052584343ffffffffffff010000584d53fffff25400c800000000008c0000000000002454002c000041494c500002010000000000ffffffffffff010000000000fffffb50000000470000000000002454001800004641495000030000000300010000020602000000 +003c0000464153500003001e00200101ffffffffffff0100010000000000000000000000060100000000000000000000000000000000000007010000002c0000414542500003fce000320244ffffffffffff010000003310010100000000002e0000000000470320002c0000414542500003000000000000ffffffffffff010001012d010f010000000000310000000000500000002c0000414542500003425000030000ffffffffffff010002012d040f020000000000ab0000000000e67263002c0000414542500003000000000000ffffffffffff010003012d040f0400000000031e0000000000e60000002c0000414542500003425001000000ffffffffffff010004012d200f08000000001c5c0000000000504250002c000041454250000303e800000000ffffffffffff010005003302080842500000326400000000004703e800300000414958500003000000200000ffffffffffff010000000000ffffee6c0708006e0000008c000000000000245400300000414943500003000046414950ffffffffffff010000000206fffff25400c800000000008c0000000000002454002c000041494c500003000000000000ffffffffffff010000000000fffffb50000000470000000000002454001800004641495000040000000400010000020602ff0100003c0000464153500004002e00000000ffffffffffff01000100005000000000000000000601ffff0000000000000000000000000000000007010000002c0000414542500004425000010000ffffffffffff01000000331001012d040000002e0000000000470000002c0000414542500004425000010000ffffffffffff010001012d010f012d04000000310000000000500000002c0000414542500004425000010000ffffffffffff010002012d040f022d20000000ab0000000000e60000002c0000414542500004425000010000ffffffffffff010003012d040f0433020000031e0000000000e60000002c0000414542500004585000010000ffffffffffff010004012d200f08000000001c5c000000000050008c002c0000414542500004000041494350ffffffffffff01000500330208080100000032640000000000470000003000004149585000042454002c0000ffffffffffff010000000000ffffee6c0708006e0000008c000000000000245400300000414943500004000146414950ffffffffffff010000000206fffff25400c850530000008c0000000000002454002c000041494c500004000000000000ffffffffffff010000000000fffffb50000000470000000000002454001800004641495000050000000500010000020602ff0100003c0000464153500005002e00000000ffffffffffff01000100005000000000000000000601ffff0000000000000000000000000000000007010000002c0000414542500005425000020000ffffffffffff01000000331001012d040000002e0000000000470000002c0000414542500005425000020000ffffffffffff010001012d010f012d04000000310000000000500000002c0000414542500005425000020000ffffffffffff010002012d040f022d20000000ab0000000000e60000002c0000414542500005425000024d53ffffffffffff010003012d040f0433020000031e0000000000e60000002c0000414542500005585000020000ffffffffffff010004012d200f08000000001c5c000000000050008c002c0000414542500005000041494350ffffffffffff01000500330208080100000032640000000000470000003000004149585000052454002c0000ffffffffffff010000000000ffffee6c0708006e0000008c000000000000245400300000414943500005ffff46414950ffffffffffff010000000206fffff25400c800000000008c0000000000002454 +002c000041494c500005001e00200101ffffffffffff010000000000fffffb50000000470000000000002454001800004641495000060000000600010000020602454250003c0000464153500006ffffffff0100ffffffffffff01000100002e0000000000470000060102440000000000000000000000000000000007010100002c0000414542500006003100000000ffffffffffff010000003310010142500000002e0000000000470100002c000041454250000600ab00000000ffffffffffff010001012d010f010000000000310000000000500100002c0000414542500006031e00000000ffffffffffff010002012d040f024250000000ab0000000000e60100002c00004145425000061c5c00000000ffffffffffff010003012d040f0403e80000031e0000000000e60100002c0000414542500006326400000000ffffffffffff010004012d200f08000000001c5c0000000000500100002c0000414542500006006e0000008cffffffffffff0100050033020808435000003264000000000047ffff00300000414958500006f25400c80000ffffffffffff010000002454ffffee6c0708006e0000008c000000000000245400300000414943500006fb5000000047ffffffffffff010000180000fffff25400c800000000008c0000000000002454002c000041494c500006002e00000000ffffffffffff010000000050fffffb50000000470000000000002454001800004641495000070000000700010000020602454250003c0000464153500007ffffffff0100ffffffffffff01000100002e0000000000470000060100000000000000000000000000000000000007010100002c0000414542500007003100000000ffffffffffff010000003310010142500000002e0000000000470100002c000041454250000700ab00000000ffffffffffff010001012d010f014250000000310000000000500100002c0000414542500007031e00000000ffffffffffff010002012d040f025850000000ab0000000000e60100002c00004145425000071c5c00000000ffffffffffff010003012d040f0400000000031e0000000000e60100002c0000414542500007326400000000ffffffffffff010004012d200f08245400001c5c0000000000500100002c0000414542500007006e0000008cffffffffffff0100050033020808435000003264000000000047ffff00300000414958500007f25400c85053ffffffffffff010000002454ffffee6c0708006e0000008c000000000000245400300000414943500007fb5000000047ffffffffffff010000180001fffff25400c800000000008c0000000000002454002c000041494c500007002e00000000ffffffffffff010000000050fffffb50000000470000000000002454001800004641495000080000000800010000020602454250003c0000464153500008ffffffff0100ffffffffffff01000100002e0000000000470000060100000000000000000000000000000000000007010100002c0000414542500008003100000000ffffffffffff010000003310010142500000002e0000000000470100002c000041454250000800ab00000000ffffffffffff010001012d010f014250000000310000000000500100002c0000414542500008031e00000000ffffffffffff010002012d040f025850000000ab0000000000e60100002c00004145425000081c5c00000000ffffffffffff010003012d040f0400000000031e0000000000e60100002c0000414542500008326400000000ffffffffffff010004012d200f08245400001c5c0000000000500100002c0000414542500008006e0000008cffffffffffff0100050033020808435000003264000000000047ffff +00300000414958500008001e00200101ffffffffffff010000000000ffffee6c0708006e0000008c000000000000245400300000414943500008000100000206ffffffffffff010000415350fffff25400c801000000008c0000000000002454002c000041494c500008024400000000ffffffffffff010000000000fffffb5000000047000000000000245400180000464149500009000000090001000002060200002e003c00004641535000092d0441454250ffffffffffff0100010000ff0000000000010000060100000000000000000000000001000000000007014250002c0000414542500009ffffffff0100ffffffffffff010000003310010100000000002e0000000000474250002c0000414542500009ffffffff0100ffffffffffff010001012d010f010000000000310000000000504250002c0000414542500009ffffffff0100ffffffffffff010002012d040f020000000000ab0000000000e64250002c0000414542500009ffffffff0100ffffffffffff010003012d040f0400000000031e0000000000e65850002c0000414542500009ffffffff0100ffffffffffff010004012d200f08008c00001c5c0000000000500100002c00004145425000090047ffffffffffffffffffff0100050033020808000000003264000000000047245400300000414958500009002e00000000ffffffffffff010000000050ffffee6c0708006e0000008c000000000000245400300000414943500009000100000206ffffffffffff010000415350fffff25400c801000000008c0000000000002454002c000041494c500009000000000000ffffffffffff010000000000fffffb500000004700000000000024540018000046414950000a0000000a0001000002060200002e003c000046415350000a2d0441454250ffffffffffff0100010000ff0000000000010000060142500000000000000000000001000000000007014250002c000041454250000affffffff0100ffffffffffff010000003310010100000000002e0000000000474250002c000041454250000affffffff0100ffffffffffff010001012d010f010000000000310000000000504250002c000041454250000affffffff0100ffffffffffff010002012d040f020000000000ab0000000000e64250002c000041454250000affffffff0100ffffffffffff010003012d040f0400000000031e0000000000e65850002c000041454250000affffffff0100ffffffffffff010004012d200f08008c00001c5c0000000000500100002c000041454250000a0047ffffffffffffffffffff010005003302080800000000326400000000004724540030000041495850000a002e00000000ffffffffffff010000000050ffffee6c0708006e0000008c00000000000024540030000041494350000a000100000206ffffffffffff010000415350fffff25400c801000000008c0000000000002454002c000041494c50000a000000000000ffffffffffff010000000000fffffb500000004700000000000024540018000046414950000b0000000b0001000002060200002e003c000046415350000b2d0441454250ffffffffffff0100010000ff0000000000010000060142500000000000000000000001000000000007014250002c000041454250000bffffffff0100ffffffffffff010000003310010100000000002e0000000000474250002c000041454250000bffffffff0100ffffffffffff010001012d010f010000000000310000000000504250002c000041454250000bffffffff0100ffffffffffff010002012d040f020000000000ab0000000000e64250002c000041454250000bffffffff0100ffffffffffff010003012d040f0400000000031e0000000000e60206 +002c000041454250000b001e00200101ffffffffffff010004012d200f08ee6c00001c5c0000000000500000002c000041454250000b435000080001ffffffffffff0100050033020808535000003264000000000047008c0030000041495850000b000041494c50ffffffffffff01000000ffffffffee6c0708006e0000008c00000000000024540030000041494350000b495000090000ffffffffffff01000000002efffff25400c853500000008c0000000000002454002c000041494c50000b000000010000ffffffffffff010000000000fffffb500000004700000000000024540018000046414950000c0000000c00010000020602003310003c000046415350000c000000474250ffffffffffff0100010000ff0000000000ff0000060101000000000000000000000000310000000007014250002c000041454250000cffffffff0100ffffffffffff010000003310010100000000002e0000000000474250002c000041454250000cffffffff0100ffffffffffff010001012d010f010000000000310000000000505850002c000041454250000cffffffff0100ffffffffffff010002012d040f02008c000000ab0000000000e60100002c000041454250000c0047ffffffffffffffffffff010003012d040f0400000000031e0000000000e62454002c000041454250000c002e00000000ffffffffffff010004012d200f08ee6c00001c5c0000000000500000002c000041454250000c435000090001ffffffffffff0100050033020808535000003264000000000047008c0030000041495850000c000041494c50ffffffffffff01000000ffffffffee6c0708006e0000008c00000000000024540030000041494350000c4950000a0000ffffffffffff01000000002efffff25400c853500000008c0000000000002454002c000041494c50000c000000010000ffffffffffff010000000000fffffb500000004700000000000024540018000046414950000d0000000d00010000020602003310003c000046415350000d000000474250ffffffffffff0100010000ff0000000000ff0000060101000000000000000000000000310000000007014250002c000041454250000dffffffff0100ffffffffffff010000003310010100000000002e0000000000474250002c000041454250000dffffffff0100ffffffffffff010001012d010f010000000000310000000000505850002c000041454250000dffffffff0100ffffffffffff010002012d040f02008c000000ab0000000000e60100002c000041454250000d0047ffffffffffffffffffff010003012d040f0400000000031e0000000000e62454002c000041454250000d002e00000000ffffffffffff010004012d200f08ee6c00001c5c0000000000500000002c000041454250000d4350000a0001ffffffffffff0100050033020808535000003264000000000047008c0030000041495850000d000041494c50ffffffffffff01000000ffffffffee6c0708006e0000008c00000000000024540030000041494350000d4950000b0000ffffffffffff01000000002efffff25400c853500000008c0000000000002454002c000041494c50000d000000010000ffffffffffff010000000000fffffb500000004700000000000024540018000046414950000e0000000e00010000020602003310003c000046415350000e000000474250ffffffffffff0100010000ff0000000000ff0000060101000000000000000000000000310000000007014250002c000041454250000effffffff0100ffffffffffff010000003310010100000000002e0000000000474250002c000041454250000effffffff0100ffffffffffff010001012d010f010000000000310000000000500206 +002c000041454250000e001e00200101ffffffffffff010002012d040f02ee6c000000ab0000000000e60000002c000041454250000e435000080001ffffffffffff010003012d040f0453500000031e0000000000e6008c002c000041454250000e000041494c50ffffffffffff010004012d200f08ee6c00001c5c0000000000500000002c000041454250000e4350000b4950ffffffffffff0100050033020808002e00003264000000000047008c0030000041495850000e010041494c50ffffffffffff01000000ffffffffee6c0708006e0000008c00000000000024540030000041494350000e4950000c0000ffffffffffff010000003310fffff25400c853500000008c0000000000002454002c000041494c50000e000000ff0000ffffffffffff010000000000fffffb500000004700000000000024540018000046414950000f0000000f00010000020602003310003c000046415350000f000000474250ffffffffffff0100010000ff0000000000ff0000060101000000000000000000000000310000000007015850002c000041454250000fffffffff0100ffffffffffff0100000033100101008c0000002e0000000000470100002c000041454250000f0047ffffffffffffffffffff010001012d010f010000000000310000000000502454002c000041454250000f002e00000000ffffffffffff010002012d040f02ee6c000000ab0000000000e60000002c000041454250000f435000090001ffffffffffff010003012d040f0453500000031e0000000000e6008c002c000041454250000f000041494c50ffffffffffff010004012d200f08ee6c00001c5c0000000000500000002c000041454250000f4350000c4950ffffffffffff0100050033020808002e00003264000000000047008c0030000041495850000f010041494c50ffffffffffff01000000ffffffffee6c0708006e0000008c00000000000024540030000041494350000f4950000d0000ffffffffffff010000003310fffff25400c853500000008c0000000000002454002c000041494c50000f000000ff0000ffffffffffff010000000000fffffb50000000470000000000002454001800004641495000100000001000010000020602003310003c0000464153500010000000474250ffffffffffff0100010000ff0000000000ff0000060101000000000000000000000000310000000007015850002c0000414542500010ffffffff0100ffffffffffff0100000033100101008c0000002e0000000000470100002c00004145425000100047ffffffffffffffffffff010001012d010f010000000000310000000000502454002c0000414542500010002e00000000ffffffffffff010002012d040f02ee6c000000ab0000000000e60000002c00004145425000104350000a0001ffffffffffff010003012d040f0453500000031e0000000000e6008c002c0000414542500010000041494c50ffffffffffff010004012d200f08ee6c00001c5c0000000000500000002c00004145425000104350000d4950ffffffffffff0100050033020808002e00003264000000000047008c00300000414958500010010041494c50ffffffffffff01000000ffffffffee6c0708006e0000008c0000000000002454003000004149435000104950000e0000ffffffffffff010000003310fffff25400c853500000008c0000000000002454002c000041494c500010000000ff0000ffffffffffff010000000000fffffb50000000470000000000002454001800004641495000110000001100010000020602003310003c0000464153500011000000474250ffffffffffff0100010000ff0000000000ff0000060101000000000000000000000000310000000007010206 +002c0000414542500011001e00200101ffffffffffff0100000033100101ee6c0000002e0000000000470000002c0000414542500011435000080001ffffffffffff010001012d010f01535000000031000000000050008c002c0000414542500011000041494c50ffffffffffff010002012d040f02ee6c000000ab0000000000e60000002c00004145425000114350000b4950ffffffffffff010003012d040f04002e0000031e0000000000e6008c002c0000414542500011010041494c50ffffffffffff010004012d200f08ee6c00001c5c0000000000500000002c00004145425000114350000e4950ffffffffffff0100050033020808331000003264000000000047008c00300000414958500011010041494c50ffffffffffff01000000ffffffffee6c0708006e0000008c0000000000002454003000004149435000114950000f0000ffffffffffff010000003310fffff25400c853500000008c0000000000002454002c000041494c500011000000ff0000ffffffffffff010000000000fffffb50000000470000000000002454001800004641495000120000001200010000020602003310003c0000464153500012000000470100ffffffffffff0100010000470000000000ff0000060101000000000000000000000000310000000007012454002c0000414542500012002e00000000ffffffffffff0100000033100101ee6c0000002e0000000000470000002c0000414542500012435000090001ffffffffffff010001012d010f01535000000031000000000050008c002c0000414542500012000041494c50ffffffffffff010002012d040f02ee6c000000ab0000000000e60000002c00004145425000124350000c4950ffffffffffff010003012d040f04002e0000031e0000000000e6008c002c0000414542500012010041494c50ffffffffffff010004012d200f08ee6c00001c5c0000000000500000002c00004145425000124350000f4950ffffffffffff0100050033020808331000003264000000000047008c00300000414958500012010041494c50ffffffffffff01000000ffffffffee6c0708006e0000008c000000000000245400300000414943500012495000100000ffffffffffff010000003310fffff25400c853500000008c0000000000002454002c000041494c500012000000ff0000ffffffffffff010000000000fffffb50000000470000000000002454001800004641495000130000001300010000020602003310003c0000464153500013000000470100ffffffffffff0100010000470000000000ff0000060101000000000000000000000000310000000007012454002c0000414542500013002e00000000ffffffffffff0100000033100101ee6c0000002e0000000000470000002c00004145425000134350000a0001ffffffffffff010001012d010f01535000000031000000000050008c002c0000414542500013000041494c50ffffffffffff010002012d040f02ee6c000000ab0000000000e60000002c00004145425000134350000d4950ffffffffffff010003012d040f04002e0000031e0000000000e6008c002c0000414542500013010041494c50ffffffffffff010004012d200f08ee6c00001c5c0000000000500000002c0000414542500013435000104950ffffffffffff0100050033020808331000003264000000000047008c00300000414958500013010041494c50ffffffffffff01000000ffffffffee6c0708006e0000008c000000000000245400300000414943500013495000110000ffffffffffff010000003310fffff25400c853500000008c0000000000002454002c000041494c500013000000ff0000ffffffffffff010000000000fffffb50000000470000000000002454001800004641495000140000001400010000020602000000 +003c0000464153500014001e00200101ffffffffffff0100010000100000000000000000060100000000000000000000000042500000000007010001002c00004145425000142d010f015350ffffffffffff010000003310010100000000002e0000000000474c50002c00004145425000142d040f02ee6cffffffffffff010001012d010f012454000000310000000000504950002c00004145425000142d040f04002effffffffffff010002012d040f020000000000ab0000000000e64c50002c00004145425000142d200f08ee6cffffffffffff010003012d040f0424540000031e0000000000e64950002c0000414542500014330208083310ffffffffffff010004012d200f08000000001c5c0000000000504c50002c0000414542500014ffffffffee6cffffffffffff0100050033020808245400003264000000000047495000300000414958500014010000003310ffffffffffff01000000008cffffee6c0708006e0000008c000000000000245400300000414943500014010000000000ffffffffffff010000000000fffff25400c842500000008c0000000000002454002c000041494c500014008c46415350ffffffffffff010000fffffffffffb50000000470000000000002454001800004641495000150000001500010000020602012454003c0000464153500015002e00000000ffffffffffff0100010000100000000000000000060100000000000000000000000042500000000007010001002c00004145425000152d010f015350ffffffffffff010000003310010100000000002e0000000000474c50002c00004145425000152d040f02ee6cffffffffffff010001012d010f012454000000310000000000504950002c00004145425000152d040f04002effffffffffff010002012d040f020000000000ab0000000000e64c50002c00004145425000152d200f08ee6cffffffffffff010003012d040f0424540000031e0000000000e64950002c0000414542500015330208083310ffffffffffff010004012d200f08000000001c5c0000000000504c50002c0000414542500015ffffffffee6cffffffffffff0100050033020808245400003264000000000047495000300000414958500015010000003310ffffffffffff01000000008cffffee6c0708006e0000008c000000000000245400300000414943500015010000000000ffffffffffff010000000000fffff25400c842500000008c0000000000002454002c000041494c500015008c46415350ffffffffffff010000fffffffffffb50000000470000000000002454001800004641495000160000001600010000020602012454003c0000464153500016002e00000000ffffffffffff0100010000100000000000000000060100000000000000000000000042500000000007010001002c00004145425000162d010f015350ffffffffffff010000003310010100000000002e0000000000474c50002c00004145425000162d040f02ee6cffffffffffff010001012d010f012454000000310000000000504950002c00004145425000162d040f04002effffffffffff010002012d040f020000000000ab0000000000e64c50002c00004145425000162d200f08ee6cffffffffffff010003012d040f0424540000031e0000000000e64950002c0000414542500016330208083310ffffffffffff010004012d200f08000000001c5c0000000000504c50002c0000414542500016ffffffffee6cffffffffffff0100050033020808245400003264000000000047495000300000414958500016010000003310ffffffffffff01000000008cffffee6c0708006e0000008c000000000000245400300000414943500016010000000000ffffffffffff010000000000fffff25400c800000000008c0000000000002454 +002c000041494c500016001e00200101ffffffffffff010000000010fffffb50000000470000000000002454001800004641495000170000001700010000020602454250003c0000464153500017ffffffff0100ffffffffffff01000100002e00000000004700000601ffff00000000000000000000ee6c0000000007010100002c0000414542500017003100000000ffffffffffff01000000331001012d040000002e0000000000470100002c000041454250001700ab00000000ffffffffffff010001012d010f012d20000000310000000000500100002c0000414542500017031e00000000ffffffffffff010002012d040f023302000000ab0000000000e60100002c00004145425000171c5c00000000ffffffffffff010003012d040f04ffff0000031e0000000000e60100002c0000414542500017326400000000ffffffffffff010004012d200f08010000001c5c0000000000500100002c0000414542500017006e0000008cffffffffffff0100050033020808435000003264000000000047ffff00300000414958500017f25400c84250ffffffffffff010000002454ffffee6c0708006e0000008c000000000000245400300000414943500017fb5000000047ffffffffffff010000180100fffff25400c800000000008c0000000000002454002c000041494c500017002e00000000ffffffffffff010000000010fffffb50000000470000000000002454001800004641495000180000001800010000020602454250003c0000464153500018ffffffff0100ffffffffffff01000100002e00000000004700000601ffff00000000000000000000ee6c0000000007010100002c0000414542500018003100000000ffffffffffff01000000331001012d040000002e0000000000470100002c000041454250001800ab00000000ffffffffffff010001012d010f012d20000000310000000000500100002c0000414542500018031e00000000ffffffffffff010002012d040f023302000000ab0000000000e60100002c00004145425000181c5c00000000ffffffffffff010003012d040f04ffff0000031e0000000000e60100002c0000414542500018326400000000ffffffffffff010004012d200f08010000001c5c0000000000500100002c0000414542500018006e0000008cffffffffffff0100050033020808435000003264000000000047ffff00300000414958500018f25400c84250ffffffffffff010000002454ffffee6c0708006e0000008c000000000000245400300000414943500018fb5000000047ffffffffffff010000180100fffff25400c800000000008c0000000000002454002c000041494c500018002e00000000ffffffffffff010000000010fffffb50000000470000000000002454001800004641495000190000001900010000020602454250003c0000464153500019ffffffff0100ffffffffffff01000100002e00000000004700000601ffff00000000000000000000ee6c0000000007010100002c0000414542500019003100000000ffffffffffff01000000331001012d040000002e0000000000470100002c000041454250001900ab00000000ffffffffffff010001012d010f012d20000000310000000000500100002c0000414542500019031e00000000ffffffffffff010002012d040f023302000000ab0000000000e60100002c00004145425000191c5c00000000ffffffffffff010003012d040f04ffff0000031e0000000000e60100002c0000414542500019326400000000ffffffffffff010004012d200f08010000001c5c0000000000500100002c0000414542500019006e0000008cffffffffffff0100050033020808435000003264000000000047ffff +00300000414958500019001e00200101ffffffffffff010000000010ffffee6c0708006e0000008c000000000000245400300000414943500019000100000206ffffffffffff010000415350fffff25400c801000000008c0000000000002454002c000041494c500019ffff00000000ffffffffffff010000000000fffffb500000004700000000000024540018000046414950001a0000001a0001000002060200002e003c000046415350001a2d0441454250ffffffffffff0100010000ff000000000001000006012d200000000000000000000001000000000007014250002c000041454250001affffffff0100ffffffffffff010000003310010100000000002e0000000000474250002c000041454250001affffffff0100ffffffffffff010001012d010f010000000000310000000000504250002c000041454250001affffffff0100ffffffffffff010002012d040f020000000000ab0000000000e64250002c000041454250001affffffff0100ffffffffffff010003012d040f0400000000031e0000000000e65850002c000041454250001affffffff0100ffffffffffff010004012d200f08008c00001c5c0000000000500100002c000041454250001a0047ffffffffffffffffffff010005003302080800000000326400000000004724540030000041495850001a002e00000000ffffffffffff010000000010ffffee6c0708006e0000008c00000000000024540030000041494350001a000100000206ffffffffffff010000415350fffff25400c801000000008c0000000000002454002c000041494c50001affff00000000ffffffffffff010000000000fffffb500000004700000000000024540018000046414950001b0000001b0001000002060200002e003c000046415350001b2d0441454250ffffffffffff0100010000ff000000000001000006012d200000000000000000000001000000000007014250002c000041454250001bffffffff0100ffffffffffff010000003310010100000000002e0000000000474250002c000041454250001bffffffff0100ffffffffffff010001012d010f010000000000310000000000504250002c000041454250001bffffffff0100ffffffffffff010002012d040f020000000000ab0000000000e64250002c000041454250001bffffffff0100ffffffffffff010003012d040f0400000000031e0000000000e65850002c000041454250001bffffffff0100ffffffffffff010004012d200f08008c00001c5c0000000000500100002c000041454250001b0047ffffffffffffffffffff010005003302080800000000326400000000004724540030000041495850001b002e00000000ffffffffffff010000000010ffffee6c0708006e0000008c00000000000024540030000041494350001b000100000206ffffffffffff010000415350fffff25400c801000000008c0000000000002454002c000041494c50001bffff00000000ffffffffffff010000000000fffffb500000004700000000000024540018000046414950001c0000001c0001000002060200002e003c000046415350001c2d0441454250ffffffffffff0100010000ff000000000001000006012d200000000000000000000001000000000007014250002c000041454250001cffffffff0100ffffffffffff010000003310010100000000002e0000000000474250002c000041454250001cffffffff0100ffffffffffff010001012d010f010000000000310000000000504250002c000041454250001cffffffff0100ffffffffffff010002012d040f020000000000ab0000000000e64250002c000041454250001cffffffff0100ffffffffffff010003012d040f0400000000031e0000000000e60000 +002c000041454250001c001e00200101ffffffffffff010004012d200f08ee6c00001c5c0000000000500000002c000041454250001c435000190001ffffffffffff0100050033020808535000003264000000000047008c0030000041495850001c000041494c50ffffffffffff01000000ffffffffee6c0708006e0000008c00000000000024540030000041494350001c4950001a0000ffffffffffff01000000002efffff25400c853500000008c0000000000002454002c000041494c50001c000000010000ffffffffffff010000000000fffffb500000004700000000000024540018000046414950001d0000001d00010000020602003310003c000046415350001d000000474250ffffffffffff0100010000ff0000000000ff0000060101000000000000000000000000310000000007014250002c000041454250001dffffffff0100ffffffffffff010000003310010100000000002e0000000000474250002c000041454250001dffffffff0100ffffffffffff010001012d010f010000000000310000000000505850002c000041454250001dffffffff0100ffffffffffff010002012d040f02008c000000ab0000000000e60100002c000041454250001d0047ffffffffffffffffffff010003012d040f0400000000031e0000000000e62454002c000041454250001d002e00000000ffffffffffff010004012d200f08ee6c00001c5c0000000000500000002c000041454250001d4350001a0001ffffffffffff0100050033020808535000003264000000000047008c0030000041495850001d000041494c50ffffffffffff01000000ffffffffee6c0708006e0000008c00000000000024540030000041494350001d4950001b0000ffffffffffff01000000002efffff25400c853500000008c0000000000002454002c000041494c50001d000000010000ffffffffffff010000000000fffffb500000004700000000000024540018000046414950001e0000001e00010000020602003310003c000046415350001e000000474250ffffffffffff0100010000ff0000000000ff0000060101000000000000000000000000310000000007014250002c000041454250001effffffff0100ffffffffffff010000003310010100000000002e0000000000474250002c000041454250001effffffff0100ffffffffffff010001012d010f010000000000310000000000505850002c000041454250001effffffff0100ffffffffffff010002012d040f02008c000000ab0000000000e60100002c000041454250001e0047ffffffffffffffffffff010003012d040f0400000000031e0000000000e62454002c000041454250001e002e00000000ffffffffffff010004012d200f08ee6c00001c5c0000000000500000002c000041454250001e4350001b0001ffffffffffff0100050033020808535000003264000000000047008c0030000041495850001e000041494c50ffffffffffff01000000ffffffffee6c0708006e0000008c00000000000024540030000041494350001e4950001c0000ffffffffffff01000000002efffff25400c853500000008c0000000000002454002c000041494c50001e000000010000ffffffffffff010000000000fffffb500000004700000000000024540018000046414950001f0000001f00010000020602003310003c000046415350001f000000474250ffffffffffff0100010000ff0000000000ff0000060101000000000000000000000000310000000007014250002c000041454250001fffffffff0100ffffffffffff010000003310010100000000002e0000000000474250002c000041454250001fffffffff0100ffffffffffff010001012d010f010000000000310000000000500000 +002c000041454250001f001e00200101ffffffffffff010002012d040f02ee6c000000ab0000000000e60000002c000041454250001f435000190001ffffffffffff010003012d040f0453500000031e0000000000e6008c002c000041454250001f000041494c50ffffffffffff010004012d200f08ee6c00001c5c0000000000500000002c000041454250001f4350001c4950ffffffffffff0100050033020808002e00003264000000000047008c0030000041495850001f010041494c50ffffffffffff01000000ffffffffee6c0708006e0000008c00000000000024540030000041494350001f4950001d0000ffffffffffff010000003310fffff25400c853500000008c0000000000002454002c000041494c50001f000000ff0000ffffffffffff010000000000fffffb50000000470000000000002454001800004641495000200000002000010000020602003310003c0000464153500020000000474250ffffffffffff0100010000ff0000000000ff0000060101000000000000000000000000310000000007015850002c0000414542500020ffffffff0100ffffffffffff0100000033100101008c0000002e0000000000470100002c00004145425000200047ffffffffffffffffffff010001012d010f010000000000310000000000502454002c0000414542500020002e00000000ffffffffffff010002012d040f02ee6c000000ab0000000000e60000002c00004145425000204350001a0001ffffffffffff010003012d040f0453500000031e0000000000e6008c002c0000414542500020000041494c50ffffffffffff010004012d200f08ee6c00001c5c0000000000500000002c00004145425000204350001d4950ffffffffffff0100050033020808002e00003264000000000047008c00300000414958500020010041494c50ffffffffffff01000000ffffffffee6c0708006e0000008c0000000000002454003000004149435000204950001e0000ffffffffffff010000003310fffff25400c853500000008c0000000000002454002c000041494c500020000000ff0000ffffffffffff010000000000fffffb50000000470000000000002454001800004641495000210000002100010000020602003310003c0000464153500021000000474250ffffffffffff0100010000ff0000000000ff0000060101000000000000000000000000310000000007015850002c0000414542500021ffffffff0100ffffffffffff0100000033100101008c0000002e0000000000470100002c00004145425000210047ffffffffffffffffffff010001012d010f010000000000310000000000502454002c0000414542500021002e00000000ffffffffffff010002012d040f02ee6c000000ab0000000000e60000002c00004145425000214350001b0001ffffffffffff010003012d040f0453500000031e0000000000e6008c002c0000414542500021000041494c50ffffffffffff010004012d200f08ee6c00001c5c0000000000500000002c00004145425000214350001e4950ffffffffffff0100050033020808002e00003264000000000047008c00300000414958500021010041494c50ffffffffffff01000000ffffffffee6c0708006e0000008c0000000000002454003000004149435000214950001f0000ffffffffffff010000003310fffff25400c853500000008c0000000000002454002c000041494c500021000000ff0000ffffffffffff010000000000fffffb50000000470000000000002454001800004641495000220000002200010000020602003310003c0000464153500022000000474250ffffffffffff0100010000ff0000000000ff0000060101000000000000000000000000310000000007010000 +002c0000414542500022001e00200101ffffffffffff0100000033100101ee6c0000002e0000000000470000002c0000414542500022435000190001ffffffffffff010001012d010f01535000000031000000000050008c002c0000414542500022000041494c50ffffffffffff010002012d040f02ee6c000000ab0000000000e60000002c00004145425000224350001c4950ffffffffffff010003012d040f04002e0000031e0000000000e6008c002c0000414542500022010041494c50ffffffffffff010004012d200f08ee6c00001c5c0000000000500000002c00004145425000224350001f4950ffffffffffff0100050033020808331000003264000000000047008c00300000414958500022010041494c50ffffffffffff01000000ffffffffee6c0708006e0000008c000000000000245400300000414943500022495000200000ffffffffffff010000003310fffff25400c853500000008c0000000000002454002c000041494c500022000000ff0000ffffffffffff010000000000fffffb50000000470000000000002454001800004641495000230000002300010000020602003310003c0000464153500023000000470100ffffffffffff0100010000470000000000ff0000060101000000000000000000000000310000000007012454002c0000414542500023002e00000000ffffffffffff0100000033100101ee6c0000002e0000000000470000002c00004145425000234350001a0001ffffffffffff010001012d010f01535000000031000000000050008c002c0000414542500023000041494c50ffffffffffff010002012d040f02ee6c000000ab0000000000e60000002c00004145425000234350001d4950ffffffffffff010003012d040f04002e0000031e0000000000e6008c002c0000414542500023010041494c50ffffffffffff010004012d200f08ee6c00001c5c0000000000500000002c0000414542500023435000204950ffffffffffff0100050033020808331000003264000000000047008c00300000414958500023010041494c50ffffffffffff01000000ffffffffee6c0708006e0000008c000000000000245400300000414943500023495000210000ffffffffffff010000003310fffff25400c853500000008c0000000000002454002c000041494c500023000000ff0000ffffffffffff010000000000fffffb50000000470000000000002454001800004641495000240000002400010000020602003310003c0000464153500024000000470100ffffffffffff0100010000470000000000ff0000060101000000000000000000000000310000000007012454002c0000414542500024002e00000000ffffffffffff0100000033100101ee6c0000002e0000000000470000002c00004145425000244350001b0001ffffffffffff010001012d010f01535000000031000000000050008c002c0000414542500024000041494c50ffffffffffff010002012d040f02ee6c000000ab0000000000e60000002c00004145425000244350001e4950ffffffffffff010003012d040f04002e0000031e0000000000e6008c002c0000414542500024010041494c50ffffffffffff010004012d200f08ee6c00001c5c0000000000500000002c0000414542500024435000214950ffffffffffff0100050033020808331000003264000000000047008c00300000414958500024010041494c50ffffffffffff01000000ffffffffee6c0708006e0000008c000000000000245400300000414943500024495000220000ffffffffffff010000003310fffff25400c853500000008c0000000000002454002c000041494c500024000000ff0000ffffffffffff010000000000fffffb50000000470000000000002454001800004641495000250000002500010000020602000000 +003c0000464153500025001e00200101ffffffffffff0100010000100000000000000000060100000000000000000000000042500000000007010001002c00004145425000252d010f015350ffffffffffff010000003310010100000000002e0000000000474c50002c00004145425000252d040f02ee6cffffffffffff010001012d010f012454000000310000000000504950002c00004145425000252d040f04002effffffffffff010002012d040f020000000000ab0000000000e64c50002c00004145425000252d200f08ee6cffffffffffff010003012d040f0424540000031e0000000000e64950002c0000414542500025330208083310ffffffffffff010004012d200f08000000001c5c0000000000504c50002c0000414542500025ffffffffee6cffffffffffff0100050033020808245400003264000000000047495000300000414958500025010000003310ffffffffffff01000000008cffffee6c0708006e0000008c000000000000245400300000414943500025010000000000ffffffffffff010000000000fffff25400c842500000008c0000000000002454002c000041494c500025008c46415350ffffffffffff010000fffffffffffb50000000470000000000002454001800004641495000260000002600010000020602012454003c0000464153500026002e00000000ffffffffffff0100010000100000000000000000060100000000000000000000000042500000000007010001002c00004145425000262d010f015350ffffffffffff010000003310010100000000002e0000000000474c50002c00004145425000262d040f02ee6cffffffffffff010001012d010f012454000000310000000000504950002c00004145425000262d040f04002effffffffffff010002012d040f020000000000ab0000000000e64c50002c00004145425000262d200f08ee6cffffffffffff010003012d040f0424540000031e0000000000e64950002c0000414542500026330208083310ffffffffffff010004012d200f08000000001c5c0000000000504c50002c0000414542500026ffffffffee6cffffffffffff0100050033020808245400003264000000000047495000300000414958500026010000003310ffffffffffff01000000008cffffee6c0708006e0000008c000000000000245400300000414943500026010000000000ffffffffffff010000000000fffff25400c842500000008c0000000000002454002c000041494c500026008c46415350ffffffffffff010000fffffffffffb50000000470000000000002454001800004641495000270000002700010000020602012454003c0000464153500027002e00000000ffffffffffff0100010000100000000000000000060100000000000000000000000042500000000007010001002c00004145425000272d010f015350ffffffffffff010000003310010100000000002e0000000000474c50002c00004145425000272d040f02ee6cffffffffffff010001012d010f012454000000310000000000504950002c00004145425000272d040f04002effffffffffff010002012d040f020000000000ab0000000000e64c50002c00004145425000272d200f08ee6cffffffffffff010003012d040f0424540000031e0000000000e64950002c0000414542500027330208083310ffffffffffff010004012d200f08000000001c5c0000000000504c50002c0000414542500027ffffffffee6cffffffffffff0100050033020808245400003264000000000047495000300000414958500027010000003310ffffffffffff01000000008cffffee6c0708006e0000008c000000000000245400300000414943500027010000000000ffffffffffff010000000000fffff25400c800000000008c0000000000002454 +002c000041494c500027001e00200101ffffffffffff010000000010fffffb50000000470000000000002454001800004641495000280000002800010000020602454250003c0000464153500028ffffffff0100ffffffffffff01000100002e00000000004700000601ffff00000000000000000000ee6c0000000007010100002c0000414542500028003100000000ffffffffffff01000000331001012d040000002e0000000000470100002c000041454250002800ab00000000ffffffffffff010001012d010f012d20000000310000000000500100002c0000414542500028031e00000000ffffffffffff010002012d040f023302000000ab0000000000e60100002c00004145425000281c5c00000000ffffffffffff010003012d040f04ffff0000031e0000000000e60100002c0000414542500028326400000000ffffffffffff010004012d200f08010000001c5c0000000000500100002c0000414542500028006e0000008cffffffffffff0100050033020808435000003264000000000047ffff00300000414958500028f25400c84250ffffffffffff010000002454ffffee6c0708006e0000008c000000000000245400300000414943500028fb5000000047ffffffffffff010000180100fffff25400c800000000008c0000000000002454002c000041494c500028002e00000000ffffffffffff010000000010fffffb50000000470000000000002454001800004641495007d10100000001000000020602454250003c00004641535007d1ffffffff0100ffffffffffff01000100002e00000000004700000601ffff00000000000000000000ee6c0000000005040100002c00004145425007d1003100000000ffffffffffff01000000331001012d040000002e0000000000470100002c00004145425007d100ab00000000ffffffffffff010001012d010f012d20000000310000000000500100002c00004145425007d1031e00000000ffffffffffff010002012d040f023302000000ab0000000000e60100002c00004145425007d11c5c00000000ffffffffffff010003012d040f04ffff0000031e0000000000e60100002c00004145425007d1326400000000ffffffffffff010004012d200f08010000001c5c0000000000500100002c00004145425007d1006e0000008cffffffffffff0100050033020808435000003264000000000047ffff003000004149585007d1f25400c84250ffffffffffff010000002454ffffee6c0708006e0000008c0000000000002454003000004149435007d1fb5000000047ffffffffffff010000180100fffff25400c800000000008c0000000000002454002c000041494c5007d1002e00000000ffffffffffff010000000010fffffb50000000470000000000002454001800004641495007d20100000101000000020602454250003c00004641535007d2ffffffff0100ffffffffffff01000100002e00000000004700000601ffff00000000000000000000ee6c0000000005040100002c00004145425007d2003100000000ffffffffffff01000000331001012d040000002e0000000000470100002c00004145425007d200ab00000000ffffffffffff010001012d010f012d20000000310000000000500100002c00004145425007d2031e00000000ffffffffffff010002012d040f023302000000ab0000000000e60100002c00004145425007d21c5c00000000ffffffffffff010003012d040f04ffff0000031e0000000000e60100002c00004145425007d2326400000000ffffffffffff010004012d200f08010000001c5c0000000000500100002c00004145425007d2006e0000008cffffffffffff0100050033020808435000003264000000000047ffff +003000004149585007d2001e00200101ffffffffffff010000000010ffffee6c0708006e0000008c0000000000002454003000004149435007d2000100000206ffffffffffff010000415350fffff25400c801000000008c0000000000002454002c000041494c5007d2ffff00000000ffffffffffff010000000000fffffb50000000470000000000002454001800004641495007d3010000020100000002060200002e003c00004641535007d32d0441454250ffffffffffff0100010000ff000000000001000006012d200000000000000000000001000000000005044250002c00004145425007d3ffffffff0100ffffffffffff010000003310010100000000002e0000000000474250002c00004145425007d3ffffffff0100ffffffffffff010001012d010f010000000000310000000000504250002c00004145425007d3ffffffff0100ffffffffffff010002012d040f020000000000ab0000000000e64250002c00004145425007d3ffffffff0100ffffffffffff010003012d040f0400000000031e0000000000e65850002c00004145425007d3ffffffff0100ffffffffffff010004012d200f08008c00001c5c0000000000500100002c00004145425007d30047ffffffffffffffffffff01000500330208080000000032640000000000472454003000004149585007d3002e00000000ffffffffffff010000000010ffffee6c0708006e0000008c0000000000002454003000004149435007d3010000000206ffffffffffff010000415350fffff25400c801000000008c0000000000002454002c000041494c5007d3ffff00000000ffffffffffff010000000000fffffb50000000470000000000002454001800004641495007d4010000030100000002060200002e003c00004641535007d42d0441454250ffffffffffff0100010000ff000000000001000006012d200000000000000000000001000000000005044250002c00004145425007d4ffffffff0100ffffffffffff010000003310010100000000002e0000000000474250002c00004145425007d4ffffffff0100ffffffffffff010001012d010f010000000000310000000000504250002c00004145425007d4ffffffff0100ffffffffffff010002012d040f020000000000ab0000000000e64250002c00004145425007d4ffffffff0100ffffffffffff010003012d040f0400000000031e0000000000e65850002c00004145425007d4ffffffff0100ffffffffffff010004012d200f08008c00001c5c0000000000500100002c00004145425007d40047ffffffffffffffffffff01000500330208080000000032640000000000472454003000004149585007d4002e00000000ffffffffffff010000000010ffffee6c0708006e0000008c0000000000002454003000004149435007d4010000000206ffffffffffff010000415350fffff25400c801000000008c0000000000002454002c000041494c5007d4ffff00000000ffffffffffff010000000000fffffb50000000470000000000002454001800004641495005dd040000000400000002060200002e003c00004641535005dd2d0441454250ffffffffffff0100010000ff000000000001000006012d200000000000000000000001000000000003014250002c00004145425005ddffffffff0100ffffffffffff010000003310010100000000002e0000000000474250002c00004145425005ddffffffff0100ffffffffffff010001012d010f010000000000310000000000504250002c00004145425005ddffffffff0100ffffffffffff010002012d040f020000000000ab0000000000e64250002c00004145425005ddffffffff0100ffffffffffff010003012d040f0400000000031e0000000000e60000 +002c00004145425005dd001e00200101ffffffffffff010004012d200f08ee6c00001c5c0000000000500000002c00004145425005dd435007d20001ffffffffffff0100050033020808535000003264000000000047008c003000004149585005dd000041494c50ffffffffffff01000000ffffffffee6c0708006e0000008c0000000000002454003000004149435005dd495007d30100ffffffffffff01000000002efffff25400c853500000008c0000000000002454002c000041494c5005dd000000010000ffffffffffff010000000000fffffb50000000470000000000002454001800004641495005de0400000104000000020602003310003c00004641535005de000000474250ffffffffffff0100010000ff0000000000ff0000060101000000000000000000000000310000000003014250002c00004145425005deffffffff0100ffffffffffff010000003310010100000000002e0000000000474250002c00004145425005deffffffff0100ffffffffffff010001012d010f010000000000310000000000505850002c00004145425005deffffffff0100ffffffffffff010002012d040f02008c000000ab0000000000e60100002c00004145425005de0047ffffffffffffffffffff010003012d040f0400000000031e0000000000e62454002c00004145425005de002e00000000ffffffffffff010004012d200f08ee6c00001c5c0000000000500000002c00004145425005de435007d30100ffffffffffff0100050033020808535000003264000000000047008c003000004149585005de000041494c50ffffffffffff01000000ffffffffee6c0708006e0000008c0000000000002454003000004149435005de495007d40100ffffffffffff01000000002efffff25400c853500000008c0000000000002454002c000041494c5005de000000010000ffffffffffff010000000000fffffb50000000470000000000002454001800004641495005df0400000204000000020602003310003c00004641535005df000000474250ffffffffffff0100010000ff0000000000ff0000060101000000000000000000000000310000000003014250002c00004145425005dfffffffff0100ffffffffffff010000003310010100000000002e0000000000474250002c00004145425005dfffffffff0100ffffffffffff010001012d010f010000000000310000000000505850002c00004145425005dfffffffff0100ffffffffffff010002012d040f02008c000000ab0000000000e60100002c00004145425005df0047ffffffffffffffffffff010003012d040f0400000000031e0000000000e62454002c00004145425005df002e00000000ffffffffffff010004012d200f08ee6c00001c5c0000000000500000002c00004145425005df435007d40100ffffffffffff0100050033020808535000003264000000000047008c003000004149585005df000041494c50ffffffffffff01000000ffffffffee6c0708006e0000008c0000000000002454003000004149435005df495005dd0400ffffffffffff01000000002efffff25400c853500000008c0000000000002454002c000041494c5005df000000010000ffffffffffff010000000000fffffb50000000470000000000002454001800004641495005e00400000304000000020602003310003c00004641535005e0000000474250ffffffffffff0100010000ff0000000000ff0000060101000000000000000000000000310000000003014250002c00004145425005e0ffffffff0100ffffffffffff010000003310010100000000002e0000000000474250002c00004145425005e0ffffffff0100ffffffffffff010001012d010f010000000000310000000000500000 +002c00004145425005e0001e00200101ffffffffffff010002012d040f02ee6c000000ab0000000000e60000002c00004145425005e0435007d20001ffffffffffff010003012d040f0453500000031e0000000000e6008c002c00004145425005e0000041494c50ffffffffffff010004012d200f08ee6c00001c5c0000000000500000002c00004145425005e0435005dd4950ffffffffffff0100050033020808002e00003264000000000047008c003000004149585005e0010041494c50ffffffffffff01000000ffffffffee6c0708006e0000008c0000000000002454003000004149435005e0495005de0400ffffffffffff010000003310fffff25400c853500000008c0000000000002454002c000041494c5005e0000000ff0000ffffffffffff010000000000fffffb50000000470000000000002454001800004641495005e10400000404000000020602003310003c00004641535005e1000000474250ffffffffffff0100010000ff0000000000ff0000060101000000000000000000000000310000000003015850002c00004145425005e1ffffffff0100ffffffffffff0100000033100101008c0000002e0000000000470100002c00004145425005e10047ffffffffffffffffffff010001012d010f010000000000310000000000502454002c00004145425005e1002e00000000ffffffffffff010002012d040f02ee6c000000ab0000000000e60000002c00004145425005e1435007d30100ffffffffffff010003012d040f0453500000031e0000000000e6008c002c00004145425005e1000041494c50ffffffffffff010004012d200f08ee6c00001c5c0000000000500000002c00004145425005e1435005de4950ffffffffffff0100050033020808002e00003264000000000047008c003000004149585005e1010041494c50ffffffffffff01000000ffffffffee6c0708006e0000008c0000000000002454003000004149435005e1495005df0400ffffffffffff010000003310fffff25400c853500000008c0000000000002454002c000041494c5005e1000000ff0000ffffffffffff010000000000fffffb50000000470000000000002454001800004641495005e20400000504000000020602003310003c00004641535005e2000000474250ffffffffffff0100010000ff0000000000ff0000060101000000000000000000000000310000000003015850002c00004145425005e2ffffffff0100ffffffffffff0100000033100101008c0000002e0000000000470100002c00004145425005e20047ffffffffffffffffffff010001012d010f010000000000310000000000502454002c00004145425005e2002e00000000ffffffffffff010002012d040f02ee6c000000ab0000000000e60000002c00004145425005e2435007d40100ffffffffffff010003012d040f0453500000031e0000000000e6008c002c00004145425005e2000041494c50ffffffffffff010004012d200f08ee6c00001c5c0000000000500000002c00004145425005e2435005df4950ffffffffffff0100050033020808002e00003264000000000047008c003000004149585005e2010041494c50ffffffffffff01000000ffffffffee6c0708006e0000008c0000000000002454003000004149435005e2495005e00400ffffffffffff010000003310fffff25400c853500000008c0000000000002454002c000041494c5005e2000000ff0000ffffffffffff010000000000fffffb50000000470000000000002454001800004641495005e30400000604000000020602003310003c00004641535005e3000000474250ffffffffffff0100010000ff0000000000ff0000060101000000000000000000000000310000000003010000 +002c00004145425005e3001e00200101ffffffffffff0100000033100101ee6c0000002e0000000000470000002c00004145425005e3435007d20001ffffffffffff010001012d010f01535000000031000000000050008c002c00004145425005e3000041494c50ffffffffffff010002012d040f02ee6c000000ab0000000000e60000002c00004145425005e3435005dd4950ffffffffffff010003012d040f04002e0000031e0000000000e6008c002c00004145425005e3010041494c50ffffffffffff010004012d200f08ee6c00001c5c0000000000500000002c00004145425005e3435005e04950ffffffffffff0100050033020808331000003264000000000047008c003000004149585005e3010041494c50ffffffffffff01000000ffffffffee6c0708006e0000008c0000000000002454003000004149435005e3495005e10400ffffffffffff010000003310fffff25400c853500000008c0000000000002454002c000041494c5005e3000000ff0000ffffffffffff010000000000fffffb50000000470000000000002454001800004641495005e40400000704000000020602003310003c00004641535005e4000000470100ffffffffffff0100010000470000000000ff0000060101000000000000000000000000310000000003012454002c00004145425005e4002e00000000ffffffffffff0100000033100101ee6c0000002e0000000000470000002c00004145425005e4435007d30100ffffffffffff010001012d010f01535000000031000000000050008c002c00004145425005e4000041494c50ffffffffffff010002012d040f02ee6c000000ab0000000000e60000002c00004145425005e4435005de4950ffffffffffff010003012d040f04002e0000031e0000000000e6008c002c00004145425005e4010041494c50ffffffffffff010004012d200f08ee6c00001c5c0000000000500000002c00004145425005e4435005e14950ffffffffffff0100050033020808331000003264000000000047008c003000004149585005e4010041494c50ffffffffffff01000000ffffffffee6c0708006e0000008c0000000000002454003000004149435005e4495005e20400ffffffffffff010000003310fffff25400c853500000008c0000000000002454002c000041494c5005e4000000ff0000ffffffffffff010000000000fffffb50000000470000000000002454001800004641495005e50400000804000000020602003310003c00004641535005e5000000470100ffffffffffff0100010000470000000000ff0000060101000000000000000000000000310000000003012454002c00004145425005e5002e00000000ffffffffffff0100000033100101ee6c0000002e0000000000470000002c00004145425005e5435007d40100ffffffffffff010001012d010f01535000000031000000000050008c002c00004145425005e5000041494c50ffffffffffff010002012d040f02ee6c000000ab0000000000e60000002c00004145425005e5435005df4950ffffffffffff010003012d040f04002e0000031e0000000000e6008c002c00004145425005e5010041494c50ffffffffffff010004012d200f08ee6c00001c5c0000000000500000002c00004145425005e5435005e24950ffffffffffff0100050033020808331000003264000000000047008c003000004149585005e5010041494c50ffffffffffff01000000ffffffffee6c0708006e0000008c0000000000002454003000004149435005e5495005e30400ffffffffffff010000003310fffff25400c853500000008c0000000000002454002c000041494c5005e5000000ff0000ffffffffffff010000000000fffffb50000000470000000000002454001800004641495005e60400000904000000020602000000 +003c00004641535005e6001e00200101ffffffffffff0100010000100000000000000000060100000000000000000000000042500000000003010001002c00004145425005e62d010f015350ffffffffffff010000003310010100000000002e0000000000474c50002c00004145425005e62d040f02ee6cffffffffffff010001012d010f012454000000310000000000504950002c00004145425005e62d040f04002effffffffffff010002012d040f020000000000ab0000000000e64c50002c00004145425005e62d200f08ee6cffffffffffff010003012d040f0424540000031e0000000000e64950002c00004145425005e6330208083310ffffffffffff010004012d200f08000000001c5c0000000000504c50002c00004145425005e6ffffffffee6cffffffffffff01000500330208082454000032640000000000474950003000004149585005e6010000003310ffffffffffff01000000008cffffee6c0708006e0000008c0000000000002454003000004149435005e6010000000000ffffffffffff010000000000fffff25400c842500000008c0000000000002454002c000041494c5005e6008c46415350ffffffffffff010000fffffffffffb50000000470000000000002454001800004641495005e70400000a04000000020602012454003c00004641535005e7002e00000000ffffffffffff0100010000100000000000000000060100000000000000000000000042500000000003010100002c00004145425005e72d010f015350ffffffffffff010000003310010100000000002e0000000000474c50002c00004145425005e72d040f02ee6cffffffffffff010001012d010f012454000000310000000000504950002c00004145425005e72d040f04002effffffffffff010002012d040f020000000000ab0000000000e64c50002c00004145425005e72d200f08ee6cffffffffffff010003012d040f0424540000031e0000000000e64950002c00004145425005e7330208083310ffffffffffff010004012d200f08000000001c5c0000000000504c50002c00004145425005e7ffffffffee6cffffffffffff01000500330208082454000032640000000000474950003000004149585005e7010000003310ffffffffffff01000000008cffffee6c0708006e0000008c0000000000002454003000004149435005e7010000000000ffffffffffff010000000000fffff25400c842500000008c0000000000002454002c000041494c5005e7008c46415350ffffffffffff010000fffffffffffb50000000470000000000002454001800004641495005e80400000b04000000020602012454003c00004641535005e8002e00000000ffffffffffff0100010000100000000000000000060100000000000000000000000042500000000003010100002c00004145425005e82d010f015350ffffffffffff010000003310010100000000002e0000000000474c50002c00004145425005e82d040f02ee6cffffffffffff010001012d010f012454000000310000000000504950002c00004145425005e82d040f04002effffffffffff010002012d040f020000000000ab0000000000e64c50002c00004145425005e82d200f08ee6cffffffffffff010003012d040f0424540000031e0000000000e64950002c00004145425005e8330208083310ffffffffffff010004012d200f08000000001c5c0000000000504c50002c00004145425005e8ffffffffee6cffffffffffff01000500330208082454000032640000000000474950003000004149585005e8010000003310ffffffffffff01000000008cffffee6c0708006e0000008c0000000000002454003000004149435005e8010000000000ffffffffffff010000000000fffff25400c800000000008c0000000000002454 +002c000041494c5005e8001e00200101ffffffffffff010000000010fffffb50000000470000000000002454001800004641495005e90400000c04000000020602454250003c00004641535005e9ffffffff0100ffffffffffff01000100002e00000000004700000601ffff00000000000000000000ee6c0000000003010100002c00004145425005e9003100000000ffffffffffff01000000331001012d040000002e0000000000470100002c00004145425005e900ab00000000ffffffffffff010001012d010f012d20000000310000000000500100002c00004145425005e9031e00000000ffffffffffff010002012d040f023302000000ab0000000000e60100002c00004145425005e91c5c00000000ffffffffffff010003012d040f04ffff0000031e0000000000e60100002c00004145425005e9326400000000ffffffffffff010004012d200f08010000001c5c0000000000500100002c00004145425005e9006e0000008cffffffffffff0100050033020808435000003264000000000047ffff003000004149585005e9f25400c84250ffffffffffff010000002454ffffee6c0708006e0000008c0000000000002454003000004149435005e9fb5000000047ffffffffffff010000180100fffff25400c804000000008c0000000000002454002c000041494c5005e9002e00000000ffffffffffff010000000010fffffb50000000470000000000002454001800004641495005ea0400000d04000000020602454250003c00004641535005eaffffffff0100ffffffffffff01000100002e00000000004700000601ffff00000000000000000000ee6c0000000003010100002c00004145425005ea003100000000ffffffffffff01000000331001012d040000002e0000000000470100002c00004145425005ea00ab00000000ffffffffffff010001012d010f012d20000000310000000000500100002c00004145425005ea031e00000000ffffffffffff010002012d040f023302000000ab0000000000e60100002c00004145425005ea1c5c00000000ffffffffffff010003012d040f04ffff0000031e0000000000e60100002c00004145425005ea326400000000ffffffffffff010004012d200f08010000001c5c0000000000500100002c00004145425005ea006e0000008cffffffffffff0100050033020808435000003264000000000047ffff003000004149585005eaf25400c84250ffffffffffff010000002454ffffee6c0708006e0000008c0000000000002454003000004149435005eafb5000000047ffffffffffff010000180100fffff25400c804000000008c0000000000002454002c000041494c5005ea002e00000000ffffffffffff010000000010fffffb50000000470000000000002454001800004641495005eb0400000e04000000020602454250003c00004641535005ebffffffff0100ffffffffffff01000100002e00000000004700000601ffff00000000000000000000ee6c0000000003010100002c00004145425005eb003100000000ffffffffffff01000000331001012d040000002e0000000000470100002c00004145425005eb00ab00000000ffffffffffff010001012d010f012d20000000310000000000500100002c00004145425005eb031e00000000ffffffffffff010002012d040f023302000000ab0000000000e60100002c00004145425005eb1c5c00000000ffffffffffff010003012d040f04ffff0000031e0000000000e60100002c00004145425005eb326400000000ffffffffffff010004012d200f08010000001c5c0000000000500100002c00004145425005eb006e0000008cffffffffffff0100050033020808435000003264000000000047ffff +003000004149585005eb001e00200101ffffffffffff010000000010ffffee6c0708006e0000008c0000000000002454003000004149435005eb040000000206ffffffffffff010000415350fffff25400c801000000008c0000000000002454002c000041494c5005ebffff00000000ffffffffffff010000000000fffffb50000000470000000000002454001800004641495005ec0400000f0400000002060200002e003c00004641535005ec2d0441454250ffffffffffff0100010000ff000000000001000006012d200000000000000000000001000000000003014250002c00004145425005ecffffffff0100ffffffffffff010000003310010100000000002e0000000000474250002c00004145425005ecffffffff0100ffffffffffff010001012d010f010000000000310000000000504250002c00004145425005ecffffffff0100ffffffffffff010002012d040f020000000000ab0000000000e64250002c00004145425005ecffffffff0100ffffffffffff010003012d040f0400000000031e0000000000e65850002c00004145425005ecffffffff0100ffffffffffff010004012d200f08008c00001c5c0000000000500100002c00004145425005ec0047ffffffffffffffffffff01000500330208080400000032640000000000472454003000004149585005ec002e00000000ffffffffffff010000000010ffffee6c0708006e0000008c0000000000002454003000004149435005ec040000000206ffffffffffff010000415350fffff25400c801000000008c0000000000002454002c000041494c5005ecffff00000000ffffffffffff010000000000fffffb50000000470000000000002454001800004641495005ed040000100400000002060200002e003c00004641535005ed2d0441454250ffffffffffff0100010000ff000000000001000006012d200000000000000000000001000000000003014250002c00004145425005edffffffff0100ffffffffffff010000003310010100000000002e0000000000474250002c00004145425005edffffffff0100ffffffffffff010001012d010f010000000000310000000000504250002c00004145425005edffffffff0100ffffffffffff010002012d040f020000000000ab0000000000e64250002c00004145425005edffffffff0100ffffffffffff010003012d040f0400000000031e0000000000e65850002c00004145425005edffffffff0100ffffffffffff010004012d200f08008c00001c5c0000000000500100002c00004145425005ed0047ffffffffffffffffffff01000500330208080400000032640000000000472454003000004149585005ed002e00000000ffffffffffff010000000010ffffee6c0708006e0000008c0000000000002454003000004149435005ed040000000206ffffffffffff010000415350fffff25400c801000000008c0000000000002454002c000041494c5005edffff00000000ffffffffffff010000000000fffffb50000000470000000000002454001800004641495005ee040000110400000002060200002e003c00004641535005ee2d0441454250ffffffffffff0100010000ff000000000001000006012d200000000000000000000001000000000003014250002c00004145425005eeffffffff0100ffffffffffff010000003310010100000000002e0000000000474250002c00004145425005eeffffffff0100ffffffffffff010001012d010f010000000000310000000000504250002c00004145425005eeffffffff0100ffffffffffff010002012d040f020000000000ab0000000000e64250002c00004145425005eeffffffff0100ffffffffffff010003012d040f0400000000031e0000000000e60000 +002c00004145425005ee001e00200101ffffffffffff010004012d200f08ee6c00001c5c0000000000500000002c00004145425005ee435005eb0400ffffffffffff0100050033020808535000003264000000000047008c003000004149585005ee000041494c50ffffffffffff01000000ffffffffee6c0708006e0000008c0000000000002454003000004149435005ee495005ec0400ffffffffffff01000000002efffff25400c853500000008c0000000000002454002c000041494c5005ee000000010000ffffffffffff010000000000fffffb50000000470000000000002454001800004641495005ef0400001204000000020602003310003c00004641535005ef000000474250ffffffffffff0100010000ff0000000000ff0000060101000000000000000000000000310000000003014250002c00004145425005efffffffff0100ffffffffffff010000003310010100000000002e0000000000474250002c00004145425005efffffffff0100ffffffffffff010001012d010f010000000000310000000000505850002c00004145425005efffffffff0100ffffffffffff010002012d040f02008c000000ab0000000000e60100002c00004145425005ef0047ffffffffffffffffffff010003012d040f0404000000031e0000000000e62454002c00004145425005ef002e00000000ffffffffffff010004012d200f08ee6c00001c5c0000000000500000002c00004145425005ef435005ec0400ffffffffffff0100050033020808535000003264000000000047008c003000004149585005ef000041494c50ffffffffffff01000000ffffffffee6c0708006e0000008c0000000000002454003000004149435005ef495005ed0400ffffffffffff01000000002efffff25400c853500000008c0000000000002454002c000041494c5005ef000000010000ffffffffffff010000000000fffffb50000000470000000000002454001800004641495005f00400001304000000020602003310003c00004641535005f0000000474250ffffffffffff0100010000ff0000000000ff0000060101000000000000000000000000310000000003014250002c00004145425005f0ffffffff0100ffffffffffff010000003310010100000000002e0000000000474250002c00004145425005f0ffffffff0100ffffffffffff010001012d010f010000000000310000000000505850002c00004145425005f0ffffffff0100ffffffffffff010002012d040f02008c000000ab0000000000e60100002c00004145425005f00047ffffffffffffffffffff010003012d040f0404000000031e0000000000e62454002c00004145425005f0002e00000000ffffffffffff010004012d200f08ee6c00001c5c0000000000500000002c00004145425005f0435005ed0400ffffffffffff0100050033020808535000003264000000000047008c003000004149585005f0000041494c50ffffffffffff01000000ffffffffee6c0708006e0000008c0000000000002454003000004149435005f0495005ee0400ffffffffffff01000000002efffff25400c853500000008c0000000000002454002c000041494c5005f0000000010000ffffffffffff010000000000fffffb50000000470000000000002454001800004641495005f10400001404000000020602003310003c00004641535005f1000000474250ffffffffffff0100010000ff0000000000ff0000060101000000000000000000000000310000000003014250002c00004145425005f1ffffffff0100ffffffffffff010000003310010100000000002e0000000000474250002c00004145425005f1ffffffff0100ffffffffffff010001012d010f010000000000310000000000500000 +002c00004145425005f1001e00200101ffffffffffff010002012d040f02ee6c000000ab0000000000e60000002c00004145425005f1435005eb0400ffffffffffff010003012d040f0453500000031e0000000000e6008c002c00004145425005f1000041494c50ffffffffffff010004012d200f08ee6c00001c5c0000000000500000002c00004145425005f1435005ee4950ffffffffffff0100050033020808002e00003264000000000047008c003000004149585005f1010041494c50ffffffffffff01000000ffffffffee6c0708006e0000008c0000000000002454003000004149435005f1495005ef0400ffffffffffff010000003310fffff25400c853500000008c0000000000002454002c000041494c5005f1000000ff0000ffffffffffff010000000000fffffb50000000470000000000002454001800004641495005f20400001504000000020602003310003c00004641535005f2000000474250ffffffffffff0100010000ff0000000000ff0000060101000000000000000000000000310000000003015850002c00004145425005f2ffffffff0100ffffffffffff0100000033100101008c0000002e0000000000470100002c00004145425005f20047ffffffffffffffffffff010001012d010f010400000000310000000000502454002c00004145425005f2002e00000000ffffffffffff010002012d040f02ee6c000000ab0000000000e60000002c00004145425005f2435005ec0400ffffffffffff010003012d040f0453500000031e0000000000e6008c002c00004145425005f2000041494c50ffffffffffff010004012d200f08ee6c00001c5c0000000000500000002c00004145425005f2435005ef4950ffffffffffff0100050033020808002e00003264000000000047008c003000004149585005f2010041494c50ffffffffffff01000000ffffffffee6c0708006e0000008c0000000000002454003000004149435005f2495005f00400ffffffffffff010000003310fffff25400c853500000008c0000000000002454002c000041494c5005f2000000ff0000ffffffffffff010000000000fffffb50000000470000000000002454001800004641495005f30400001604000000020602003310003c00004641535005f3000000474250ffffffffffff0100010000ff0000000000ff0000060101000000000000000000000000310000000003015850002c00004145425005f3ffffffff0100ffffffffffff0100000033100101008c0000002e0000000000470100002c00004145425005f30047ffffffffffffffffffff010001012d010f010400000000310000000000502454002c00004145425005f3002e00000000ffffffffffff010002012d040f02ee6c000000ab0000000000e60000002c00004145425005f3435005ed0400ffffffffffff010003012d040f0453500000031e0000000000e6008c002c00004145425005f3000041494c50ffffffffffff010004012d200f08ee6c00001c5c0000000000500000002c00004145425005f3435005f04950ffffffffffff0100050033020808002e00003264000000000047008c003000004149585005f3010041494c50ffffffffffff01000000ffffffffee6c0708006e0000008c0000000000002454003000004149435005f3495005f10400ffffffffffff010000003310fffff25400c853500000008c0000000000002454002c000041494c5005f3000000ff0000ffffffffffff010000000000fffffb50000000470000000000002454001800004641495005f40400001704000000020602003310003c00004641535005f4000000474250ffffffffffff0100010000ff0000000000ff0000060101000000000000000000000000310000000003010000 +002c00004145425005f4001e00200101ffffffffffff0100000033100101ee6c0000002e0000000000470000002c00004145425005f4435005eb0400ffffffffffff010001012d010f01535000000031000000000050008c002c00004145425005f4000041494c50ffffffffffff010002012d040f02ee6c000000ab0000000000e60000002c00004145425005f4435005ee4950ffffffffffff010003012d040f04002e0000031e0000000000e6008c002c00004145425005f4010041494c50ffffffffffff010004012d200f08ee6c00001c5c0000000000500000002c00004145425005f4435005f14950ffffffffffff0100050033020808331000003264000000000047008c003000004149585005f4010041494c50ffffffffffff01000000ffffffffee6c0708006e0000008c0000000000002454003000004149435005f4495005f20400ffffffffffff010000003310fffff25400c853500000008c0000000000002454002c000041494c5005f4000000ff0000ffffffffffff010000000000fffffb50000000470000000000002454001800004641495005f50400001804000000020602003310003c00004641535005f5000000470100ffffffffffff0100010000470000000000ff0000060101000000000000000000000000310000000003012454002c00004145425005f5002e00000000ffffffffffff0100000033100101ee6c0000002e0000000000470000002c00004145425005f5435005ec0400ffffffffffff010001012d010f01535000000031000000000050008c002c00004145425005f5000041494c50ffffffffffff010002012d040f02ee6c000000ab0000000000e60000002c00004145425005f5435005ef4950ffffffffffff010003012d040f04002e0000031e0000000000e6008c002c00004145425005f5010041494c50ffffffffffff010004012d200f08ee6c00001c5c0000000000500000002c00004145425005f5435005f24950ffffffffffff0100050033020808331000003264000000000047008c003000004149585005f5010041494c50ffffffffffff01000000ffffffffee6c0708006e0000008c0000000000002454003000004149435005f5495005f30400ffffffffffff010000003310fffff25400c853500000008c0000000000002454002c000041494c5005f5000000ff0000ffffffffffff010000000000fffffb50000000470000000000002454001800004641495005f60400001904000000020602003310003c00004641535005f6000000470100ffffffffffff0100010000470000000000ff0000060101000000000000000000000000310000000003012454002c00004145425005f6002e00000000ffffffffffff0100000033100101ee6c0000002e0000000000470000002c00004145425005f6435005ed0400ffffffffffff010001012d010f01535000000031000000000050008c002c00004145425005f6000041494c50ffffffffffff010002012d040f02ee6c000000ab0000000000e60000002c00004145425005f6435005f04950ffffffffffff010003012d040f04002e0000031e0000000000e6008c002c00004145425005f6010041494c50ffffffffffff010004012d200f08ee6c00001c5c0000000000500000002c00004145425005f6435005f34950ffffffffffff0100050033020808331000003264000000000047008c003000004149585005f6010041494c50ffffffffffff01000000ffffffffee6c0708006e0000008c0000000000002454003000004149435005f6495005f40400ffffffffffff010000003310fffff25400c853500000008c0000000000002454002c000041494c5005f6000000ff0000ffffffffffff010000000000fffffb50000000470000000000002454001800004641495005f70400001a04000000020602000000 +003c00004641535005f7001e00200101ffffffffffff0100010000100000000000000000060100000000000000000000000042500000000003010400002c00004145425005f72d010f015350ffffffffffff010000003310010100000000002e0000000000474c50002c00004145425005f72d040f02ee6cffffffffffff010001012d010f012454000000310000000000504950002c00004145425005f72d040f04002effffffffffff010002012d040f020000000000ab0000000000e64c50002c00004145425005f72d200f08ee6cffffffffffff010003012d040f0424540000031e0000000000e64950002c00004145425005f7330208083310ffffffffffff010004012d200f08000000001c5c0000000000504c50002c00004145425005f7ffffffffee6cffffffffffff01000500330208082454000032640000000000474950003000004149585005f7010000003310ffffffffffff01000000008cffffee6c0708006e0000008c0000000000002454003000004149435005f7010000000000ffffffffffff010000000000fffff25400c842500000008c0000000000002454002c000041494c5005f7008c46415350ffffffffffff010000fffffffffffb50000000470000000000002454001800004641495005f80400001b04000000020602012454003c00004641535005f8002e00000000ffffffffffff0100010000100000000000000000060100000000000000000000000042500000000003010400002c00004145425005f82d010f015350ffffffffffff010000003310010100000000002e0000000000474c50002c00004145425005f82d040f02ee6cffffffffffff010001012d010f012454000000310000000000504950002c00004145425005f82d040f04002effffffffffff010002012d040f020000000000ab0000000000e64c50002c00004145425005f82d200f08ee6cffffffffffff010003012d040f0424540000031e0000000000e64950002c00004145425005f8330208083310ffffffffffff010004012d200f08000000001c5c0000000000504c50002c00004145425005f8ffffffffee6cffffffffffff01000500330208082454000032640000000000474950003000004149585005f8010000003310ffffffffffff01000000008cffffee6c0708006e0000008c0000000000002454003000004149435005f8010000000000ffffffffffff010000000000fffff25400c842500000008c0000000000002454002c000041494c5005f8008c46415350ffffffffffff010000fffffffffffb50000000470000000000002454001800004641495005f90400001c04000000020602012454003c00004641535005f9002e00000000ffffffffffff0100010000100000000000000000060100000000000000000000000042500000000003010400002c00004145425005f92d010f015350ffffffffffff010000003310010100000000002e0000000000474c50002c00004145425005f92d040f02ee6cffffffffffff010001012d010f012454000000310000000000504950002c00004145425005f92d040f04002effffffffffff010002012d040f020000000000ab0000000000e64c50002c00004145425005f92d200f08ee6cffffffffffff010003012d040f0424540000031e0000000000e64950002c00004145425005f9330208083310ffffffffffff010004012d200f08000000001c5c0000000000504c50002c00004145425005f9ffffffffee6cffffffffffff01000500330208082454000032640000000000474950003000004149585005f9010000003310ffffffffffff01000000008cffffee6c0708006e0000008c0000000000002454003000004149435005f9010000000000ffffffffffff010000000000fffff25400c800000000008c0000000000002454 +002c000041494c5005f9001e00200101ffffffffffff010000000010fffffb50000000470000000000002454001800004641495005fa0400001d04000000020602454250003c00004641535005faffffffff0100ffffffffffff01000100002e00000000004700000601ffff00000000000000000000ee6c0000000003010100002c00004145425005fa003100000000ffffffffffff01000000331001012d040000002e0000000000470100002c00004145425005fa00ab00000000ffffffffffff010001012d010f012d20000000310000000000500100002c00004145425005fa031e00000000ffffffffffff010002012d040f023302000000ab0000000000e60100002c00004145425005fa1c5c00000000ffffffffffff010003012d040f04ffff0000031e0000000000e60100002c00004145425005fa326400000000ffffffffffff010004012d200f08010000001c5c0000000000500100002c00004145425005fa006e0000008cffffffffffff0100050033020808435000003264000000000047ffff003000004149585005faf25400c84250ffffffffffff010000002454ffffee6c0708006e0000008c0000000000002454003000004149435005fafb5000000047ffffffffffff010000180100fffff25400c804000000008c0000000000002454002c000041494c5005fa002e00000000ffffffffffff010000000010fffffb50000000470000000000002454001800004641495005fb0400001e04000000020602454250003c00004641535005fbffffffff0100ffffffffffff01000100002e00000000004700000601ffff00000000000000000000ee6c0000000003010100002c00004145425005fb003100000000ffffffffffff01000000331001012d040000002e0000000000470100002c00004145425005fb00ab00000000ffffffffffff010001012d010f012d20000000310000000000500100002c00004145425005fb031e00000000ffffffffffff010002012d040f023302000000ab0000000000e60100002c00004145425005fb1c5c00000000ffffffffffff010003012d040f04ffff0000031e0000000000e60100002c00004145425005fb326400000000ffffffffffff010004012d200f08010000001c5c0000000000500100002c00004145425005fb006e0000008cffffffffffff0100050033020808435000003264000000000047ffff003000004149585005fbf25400c84250ffffffffffff010000002454ffffee6c0708006e0000008c0000000000002454003000004149435005fbfb5000000047ffffffffffff010000180100fffff25400c804000000008c0000000000002454002c000041494c5005fb002e00000000ffffffffffff010000000010fffffb50000000470000000000002454001800004641495005fc0400001f04000000020602454250003c00004641535005fcffffffff0100ffffffffffff01000100002e00000000004700000601ffff00000000000000000000ee6c0000000003010100002c00004145425005fc003100000000ffffffffffff01000000331001012d040000002e0000000000470100002c00004145425005fc00ab00000000ffffffffffff010001012d010f012d20000000310000000000500100002c00004145425005fc031e00000000ffffffffffff010002012d040f023302000000ab0000000000e60100002c00004145425005fc1c5c00000000ffffffffffff010003012d040f04ffff0000031e0000000000e60100002c00004145425005fc326400000000ffffffffffff010004012d200f08010000001c5c0000000000500100002c00004145425005fc006e0000008cffffffffffff0100050033020808435000003264000000000047ffff +003000004149585005fc001e00200101ffffffffffff010000000010ffffee6c0708006e0000008c0000000000002454003000004149435005fc040000000206ffffffffffff010000415350fffff25400c801000000008c0000000000002454002c000041494c5005fcffff00000000ffffffffffff010000000000fffffb5000000047000000000000245400180000464149500515020000000200000001010100002e003c00004641535005152d0441454250ffffffffffffff00000400ff000000000001000006012d20000000000000000000000100ffffd8f003014250002c0000414542500515ffffffff0100ffffffffffffff0000003310010100000000002e0000000000474250002c0000414542500515ffffffff0100ffffffffffffff0001012d010f010000000000310000000000504250002c0000414542500515ffffffff0100ffffffffffffff0002012d040f020000000000ab0000000000e64250002c0000414542500515ffffffff0100ffffffffffffff0003012d040f0400000000031e0000000000e65850002c0000414542500515ffffffff0100ffffffffffffff0004012d200f08008c00001c5c0000000000500100002c00004145425005150047ffffffffffffffffffffff00050033020808040000003264000000000047245400300000414958500515002e00000000ffffffffffffff0000000010ffffee6c0708006e0000008c000000000000245400300000414943500515040000000206ffffffffffffff0000415350fffff25400c801000000008c0000000000002454002c000041494c500515ffff00000000ffffffffffffff0000000000fffffb5000000047000000000000245400180000464149500579020000010800010002060200002e003c00004641535005792d0441454250ffffffffffff0100010400ff000000000001000006012d200000000000000000000001000000000003024250002c0000414542500579ffffffff0100ffffffffffff010000003310010100000000002e0000000000474250002c0000414542500579ffffffff0100ffffffffffff010001012d010f010000000000310000000000504250002c0000414542500579ffffffff0100ffffffffffff010002012d040f020000000000ab0000000000e64250002c0000414542500579ffffffff0100ffffffffffff010003012d040f0400000000031e0000000000e65850002c0000414542500579ffffffff0100ffffffffffff010004012d200f08008c00001c5c0000000000500100002c00004145425005790047ffffffffffffffffffff0100050033020808040000003264000000000047245400300000414958500579002e00000000ffffffffffff010000000010ffffee6c0708006e0000008c000000000000245400300000414943500579040000000206ffffffffffff010000415350fffff25400c801000000008c0000000000002454002c000041494c500579ffff00000000ffffffffffff010000000000fffffb50000000470000000000002454 +036c0000464d546c004e001e00200101ffffffffffff0100000100ffffffffffff0100000200ffffffffffff0100000300ffffffffffff0100000400ffffffffffff0100000500ffffffffffff0100000600ffffffffffff0100000700ffffffffffff0100000800ffffffffffff0100000900ffffffffffff0100000a00ffffffffffff0100000b00ffffffffffff0100000c00ffffffffffff0100000d00ffffffffffff0100000e00ffffffffffff0100000f00ffffffffffff0100001000ffffffffffff0100001100ffffffffffff0100001200ffffffffffff0100001300ffffffffffff0100001400ffffffffffff0100001500ffffffffffff0100001600ffffffffffff0100001700ffffffffffff0100001800ffffffffffff0100001900ffffffffffff0100001a00ffffffffffff0100001b00ffffffffffff0100001c00ffffffffffff0100001d00ffffffffffff0100001e00ffffffffffff0100001f00ffffffffffff0100002000ffffffffffff0100002100ffffffffffff0100002200ffffffffffff0100002300ffffffffffff0100002400ffffffffffff0100002500ffffffffffff0100002600ffffffffffff0100002700ffffffffffff0100002800ffffffffffff010007d100ffffffffffff010007d200ffffffffffff010007d300ffffffffffff010007d400ffffffffffff010005dd00ffffffffffff010005de00ffffffffffff010005df00ffffffffffff010005e000ffffffffffff010005e100ffffffffffff010005e200ffffffffffff010005e300ffffffffffff010005e400ffffffffffff010005e500ffffffffffff010005e600ffffffffffff010005e700ffffffffffff010005e800ffffffffffff010005e900ffffffffffff010005ea00ffffffffffff010005eb00ffffffffffff010005ec00ffffffffffff010005ed00ffffffffffff010005ee00ffffffffffff010005ef00ffffffffffff010005f000ffffffffffff010005f100ffffffffffff010005f200ffffffffffff010005f300ffffffffffff010005f400ffffffffffff010005f500ffffffffffff010005f600ffffffffffff010005f700ffffffffffff010005f800ffffffffffff010005f900ffffffffffff010005fa00ffffffffffff010005fb00ffffffffffff010005fc00ffffffffffffff00051500ffffffffffff01000579010000001c000046414d500601585000000000000000000000000000ff0100001c0000414d4250000033100101008c0000002e0000000000470100001c0000414d425001012d010f01ffff000000310000000000503302001c0000414d425002012d040f022454000000ab0000000000e6002e001c0000414d425003012d040f0400100000031e0000000000e6008c001c0000414d425004012d200f08435000001c5c000000000050ffff001c0000414d42500500330208080100000032640000000000472454002000004d4f43500079fffffffff25400c8ffff0000008c0000000000002454001c0000414d4c5000002454fffffb5000000047000000000000245400280000464d4850fffffa24fffffda8002c2d04fffffc1800fc00abfffffc1800fffffffffffc18000c000041544d500000003100100000544d4950002c00010101005000100000544d495000ff00020101000000100000544d4950000000030101000000100000544d4950004500040101005c00100000544d495000ff00050101000400100000544d4950000000060101000000100000544d495000fc00070101000000100000544d4950000100080101000000100000544d4950005000090101008c00100000544d49500000000a010100ff00100000544d49500008000b0101006400100000544d495000ff000c0101000000100000544d49500000000d0101000000100000544d49500000000e01010007 +00100000544d4950004e000f0101000100100000544d495000010010010100ff00100000544d495000ff00110101000300100000544d495000000012010100ff00100000544d495000ff00130101000000100000544d495000000014010100ff00100000544d495000ff00150101000000100000544d495000010016010100ff00100000544d495000ff00170101000100100000544d495000ff0018010100ff00100000544d495000000019010100ff00100000544d495000ff001a0101000000100000544d49500011001b010100ff00100000544d495000ff001c0101001300100000544d49500000001d010100ff00100000544d495000ff001e0101000000100000544d49500000001f010100ff00100000544d495000ff00200101000000100000544d495000010021010100ff00100000544d495000ff00220101000100100000544d495000ff0023010100ff00100000544d495000000024010100ff00100000544d495000ff00250101000000100000544d495000210026010100ff00100000544d495000ff00270101002300100000544d495000000028010100ff000c000041544d50010000ff00100000544d495001ff00010101002700100000544d495001000002010100ff00100000544d495001ff00030101000700100000544d495001000004010100ff00100000544d495001ff00050101000000100000544d495001010006010100ff00100000544d495001ff00070101000100100000544d495001ff0008010100ff00100000544d495001000009010100ff00100000544d495001ff000a0101000000100000544d495001e5000b010100ff00100000544d495001ff000c010100e700100000544d49500105000d010100ff00100000544d495001ff000e0101000500100000544d49500100000f010100ff00100000544d495001ff00100101000000100000544d495001010011010100ff00100000544d495001ff00120101000100100000544d495001ff0013010100ff00100000544d495001000014010100ff00100000544d495001ff00150101000000100000544d495001f50016010100ff00100000544d495001ff0017010100f700100000544d495001050018010100ff00100000544d495001ff00190101000500100000544d49500100001a010100ff00100000544d495001ff001b0101000000100000544d49500101001c0101000000100000544d49500101001d0101000000100000544d495001ff001e010100ff00100000544d49500101001f0101002e00100000544d4950011c00200101005000100000544d4950010000210101000000100000544d4950014d00220101000400100000544d4950010000230101002e00100000544d4950010100240101001000100000544d495001e600250101000000100000544d4950010800260101005c00100000544d4950011c00270101005000100000544d49500100002801010000001400004d4d4f50000101010079000001010154001400004d4d4f50010101010000000001010147001400004d4d4f50020101010000000001010100001400004d4d4f500301010100ff0000010101a8001400004d4d4f500401010100ff0000010101ff001400004d4d4f50050101010000000001010100001400004d4d4f50060101010010000001010150001400004d4d4f5007010101004d000001010103001400004d4d4f5008010101004500000101015c001400004d4d4f500901010100010000010101ff001400004d4d4f500a0101010010000001010150001400004d4d4f500b010101004d000001010108001400004d4d4f500c010101005000000101018c001400004d4d4f500d0101010001000001010100001400004d4d4f500e0101010010000001010150001400004d4d4f500f010101004d00000101010d001400004d4d4f50100101010000000001010107 +001400004d4d4f501101010100010000010101ff001400004d4d4f50120101010010000001010150001400004d4d4f5013010101004d000001010112001400004d4d4f501401010100ff000001010100001400004d4d4f50150101010001000001010101001400004d4d4f50160101010010000001010150001400004d4d4f5017010101004d000001010117000c00004c4b535400000050000c00004c4b5354000100ff000c00004c4b5354000200ff000c00004c4b53540003001a000c00004c4b535400040050001000005f546c4300010000284d495000340000546c496e002800000000000000000000000000000000000200000100000000000000010001000001000000000000001f01540000546c5372006e000100000200000300000400000500000600000700000800000900000a00000b00000c00000d00000e00000f00001000001100001202001300001400001501001600001700001800001900001a00001b00001c00001d01001e00001f0100200000210000220100230000240000250000260000270000280000000003e80007d10107d2000bc2000bc3000bcc000bcd000bd6000bd7000be0000be1001770001771000faa000fb4000fbe000fc8000fd2000fdc000fe6000ff0000ffa00100400100e00101800102200102c00103600104000139201139c0113a60013b000271a00271b00272400272500272e00272f002738002739001b59001b5a001b5b001b5c001f41001f42001f43001f44001f45001f46001f47001f48001f49001f4a001f4b001f4c001f4d001f4e001f4f001f50001f51001f52001f53001f54001f55001f56001f57001f580000840000546c46630028000100000200000300000400000500000600000700000800000900000a00000b00000c00000d00000e00000f00001000001100001200001300001400001500001600001700001800001900001a00001b00001c00001d00001e00001f000020000021000022000023000024000025000026000027000028004950000c00004d5250720000ffff000c00004d52635300010000001000004d5072700000000000000000001000004d5072700001000000000000001000004d5072700002000000000000001000004d5072700003000000000000001000004d5072700004000000000000001000004d5072700005000000000000001000004d5072700006000000000000001000004d5072700007000000000000001000004d5072700008000000000000001000004d5072700009000000000000001000004d507270000a000000000000001000004d507270000b000000000000001000004d507270000c000000000000001000004d507270000d000000000000001000004d507270000e000000000000001000004d507270000f000000000000001000004d5072700010000000000000001000004d5072700011000000000000001000004d5072700012000000000000001000004d5072700013000000000000001000004d5072700014000000000000001000004d5072700015000000000000001000004d5072700016000000000000001000004d5072700017000000000000001000004d5072700018000000000000001000004d5072700019000000000000001000004d507270001a000000000000001000004d507270001b000000000000001000004d507270001c000000000000001000004d507270001d000000000000001000004d507270001e000000000000001000004d507270001f000000000000001000004d5072700020000000000000001000004d5072700021000000000000001000004d5072700022000000000000001000004d5072700023000000000000001000004d5072700024000000000000001000004d5072700025000000000000001000004d5072700026000000000000001000004d5072700027000000000000 +001000004d5072700028000000000000001000004d5072700029000000000000001000004d507270002a000000000000001000004d507270002b000000000000001000004d507270002c000000000000001000004d507270002d000000000000001000004d507270002e000000000000001000004d507270002f000000000000001000004d5072700030000000000000001000004d5072700031000000000000001000004d5072700032000000000000001000004d5072700033000000000000001000004d5072700034000000000000001000004d5072700035000000000000001000004d5072700036000000000000001000004d5072700037000000000000001000004d5072700038000000000000001000004d5072700039000000000000001000004d507270003a000000000000001000004d507270003b000000000000001000004d507270003c000000000000001000004d507270003d000000000000001000004d507270003e000000000000001000004d507270003f000000000000001000004d5072700040000000000000001000004d5072700041000000000000001000004d5072700042000000000000001000004d5072700043000000000000001000004d5072700044000000000000001000004d5072700045000000000000001000004d5072700046000000000000001000004d5072700047000000000000001000004d5072700048000000000000001000004d5072700049000000000000001000004d507270004a000000000000001000004d507270004b000000000000001000004d507270004c000000000000001000004d507270004d000000000000001000004d507270004e000000000000001000004d507270004f000000000000001000004d5072700050000000000000001000004d5072700051000000000000001000004d5072700052000000000000001000004d5072700053000000000000001000004d5072700054000000000000001000004d5072700055000000000000001000004d5072700056000000000000001000004d5072700057000000000000001000004d5072700058000000000000001000004d5072700059000000000000001000004d507270005a000000000000001000004d507270005b000000000000001000004d507270005c000000000000001000004d507270005d000000000000001000004d507270005e000000000000001000004d507270005f000000000000001000004d5072700060000000000000001000004d5072700061000000000000001000004d5072700062000000000000001000004d5072700063000000000000000c0000434373740000138800200000434364500100008000000001000000000050727000000000000000000020000043436450010002800000000100000000005072702a00000000000000002000004343645001010d010001000000000000005072700012000000000000002000004343645001010101000100000000000000507270021400000000000000200000434364500101020200000001000000000050727015e000000000000000200000434364500101050300000000000100000050727000004e2000000000002000004343645001010801000100000000000000507270011a000000000000002000004343645001040401000100000000000000507270001c00000000000000200000434364500108008000000004000000000050727000000000000000000020000043436450010801800000000400000000005072700000000000000000002000004343645001080280000000040000000000507270080008000800080000200000434364500108038000000004000000000050727000000000000000000020000043436450010804800000000200000000005072700400080000000000 +002000004343645001080580000000010000000000507270080000000000000000200000434364500108068000000002000000000050727000000800000000000020000043436450010b0080000000020000000000507270000000000000000000200000434364500200008000000001000000000050727000000000000000000020000043436450020002800000000100000000005072702a00000000000000002000004343645002010d010001000000000000005072700033000000000000002000004343645002010101000100000000000000507270023500000000000000200000434364500201020200000001000000000050727015e000000000000000200000434364500201050300000000000100000050727000004e2000000000002000004343645002010801000100000000000000507270013b000000000000002000004343645002040401000100000000000000507270003d00000000000000200000434364500208008000000004000000000050727000000000000000000020000043436450020801800000000400000000005072700000000000000000002000004343645002080280000000040000000000507270080008000800080000200000434364500208038000000004000000000050727000000000000000000020000043436450020804800000000200000000005072700400080000000000002000004343645002080580000000010000000000507270080000000000000000200000434364500208068000000002000000000050727000000800000000000020000043436450020b0080000000020000000000507270000000000000000000200000434364500300008000000001000000000050727000000000000000000020000043436450030002800000000100000000005072702a00000000000000002000004343645003010d010001000000000000005072700053000000000000002000004343645003010101000100000000000000507270025500000000000000200000434364500301020200000001000000000050727015e000000000000000200000434364500301050300000000000100000050727000004e2000000000002000004343645003010801000100000000000000507270015b000000000000002000004343645003040401000100000000000000507270005d00000000000000200000434364500308008000000004000000000050727000000000000000000020000043436450030801800000000400000000005072700000000000000000002000004343645003080280000000040000000000507270080008000800080000200000434364500308038000000004000000000000008000000000000000000020000043436450030804800000000200000000000002800400080000000000002000004343645003080580000000010000000000010d01080000000000000000200000434364500308068000000002000000000001010100000800000000000020000043436450030b0080000000020000000000010202000000000000000000200000434364500400008000000001000000000001050300000000000100000020000043436450040002800000000100000000000108012a00000000000000002000004343645004010d010001000000000000000404010001000000000000002000004343645004010101000100000000000000080080020000040000000000200000434364500401020200000001000000000008018015e000040000000000200000434364500401050300000000000100000008028000004e2000000000002000004343645004010801000100000000000000080380010000040000000000200000434364500404040100010000000000000008048000000002000000000020000043436450040800800000000400000000002700000000000000000000 +0020000043436450040801800000000400000000005072700000000000000000002000004343645004080280000000040000000000507270080008000800080000200000434364500408038000000004000000000050727000000000000000000020000043436450040804800000000200000000005072700400080000000000002000004343645004080580000000010000000000507270080000000000000000200000434364500408068000000002000000000050727000000800000000000020000043436450040b0080000000020000000000507270000000000000000000200000434364500500008000000001000000000050727000000000000000000020000043436450050002800000000100000000005072702a004e2000000000002000004343645005010d01000100000000000000507270003b000000000000002000004343645005010101000100000000000000507270023d00000000000000200000434364500501020200000001000000000050727015e000000000000000200000434364500501050300000000000100000050727000004e20000000000020000043436450050108010001000000000000005072700100080008000800002000004343645005040401000100000000000000507270000000000000000000200000434364500508008000000004000000000050727000000000000000000020000043436450050801800000000400000000005072700000000000000000002000004343645005080280000000040000000000507270080008000800080000200000434364500508038000000004000000000050727000000000000000000020000043436450050804800000000200000000005072700400080000000000002000004343645005080580000000010000000000507270080000000000000000200000434364500508068000000002000000000050727000000800000000000020000043436450050b0080000000020000000000507270000000000000000000200000434364500600008000000001000000000050727000000000000000000020000043436450060002800000000100000000005072702a004e2000000000002000004343645006010d01000100000000000000507270005b000000000000002000004343645006010101000100000000000000507270025d00000000000000200000434364500601020200000001000000000050727015e000000000000000200000434364500601050300000000000100000050727000004e2000000000002000004343645006010801000100000000000000507270010008000800080000200000434364500604040100010000000000000000008000000000000000000020000043436450060800800000000400000000000002800000000000000000002000004343645006080180000000040000000000010d010000000000000000002000004343645006080280000000040000000000010101080008000800080000200000434364500608038000000004000000000001020200000000000000000020000043436450060804800000000200000000000105030400080000010000002000004343645006080580000000010000000000010801080000000000000000200000434364500608068000000002000000000004040100000800000000000020000043436450060b0080000000020000000000080080000000000000000000200000434364500700008000000001000000000008018000000004000000000020000043436450070002800000000100000000000802802a004e2000000000002000004343645007010d010001000000000000000803800000000400000000002000004343645007010101000100000000000000080480020000020000000000200000434364500701020200000001000000000027000015e0000000000000 +00200000434364500701050300000000000100000050727000004e2000000000002000004343645007010801000100000000000000507270010008000800080000200000434364500704040100010000000000000050727000000000000000000020000043436450070800800000000400000000005072700000000000000000002000004343645007080180000000040000000000507270000000000000000000200000434364500708028000000004000000000050727008000800080008000020000043436450070803800000000400000000005072700000000000000000002000004343645007080480000000020000000000507270040008000000000000200000434364500708058000000001000000000050727008004e200000000000200000434364500708068000000002000000000050727000000800000000000020000043436450070b0080000000020000000000507270000000000000000000200000434364500800008000000001000000000050727000000000000000000020000043436450080002800000000100000000005072702a004e2000000000002000004343645008010d010001000000000000005072700000080008000800002000004343645008010101000100000000000000507270020000000000000000200000434364500801020200000001000000000050727015e000000000000000200000434364500801050300000000000100000050727000004e2000000000002000004343645008010801000100000000000000507270010008000800080000200000434364500804040100010000000000000050727000000000000000000020000043436450080800800000000400000000005072700000000000000000002000004343645008080180000000040000000000507270000000000000000000200000434364500808028000000004000000000050727008000800080008000020000043436450080803800000000400000000005072700000000000000000002000004343645008080480000000020000000000507270040008000000000000200000434364500808058000000001000000000050727008004e200000000000200000434364500808068000000002000000000050727000000800000000000020000043436450080b0080000000020000000000507270000000000000000000200000434364500900008000000001000000000050727000000000000000000020000043436450090002800000000100000000005072702a004e2000000000002000004343645009010d010001000000000000005072700000080008000800002000004343645009010101000100000000000000000080020000000000000000200000434364500901020200000001000000000000028015e0000000000000002000004343645009010503000000000001000000010d0100004e2000000000002000004343645009010801000100000000000000010101010008000800080000200000434364500904040100010000000000000001020200000000000000000020000043436450090800800000000400000000000105030000000000000000002000004343645009080180000000040000000000010801000000000000000000200000434364500908028000000004000000000004040108000800080008000020000043436450090803800000000400000000000800800000000000000000002000004343645009080480000000020000000000080180040008000000000000200000434364500908058000000001000000000008028008004e200000000000200000434364500908068000000002000000000008038000000800000000000020000043436450090b0080000000020000000000080480000000000000000000200000434364500a0000800000000100000000002700000000000000000000 +00200000434364500a0002800000000100000000005072702a004e200000000000200000434364500a010d01000100000000000000507270000008000800080000200000434364500a010101000100000000000000507270020000000000000000200000434364500a01020200000001000000000050727015e000000000000000200000434364500a01050300000000000100000050727000004e200000000000200000434364500a010801000100000000000000507270010008000800080000200000434364500a040401000100000000000000507270000000000000000000200000434364500a080080000000040000000000507270000000000000000000200000434364500a080180000000040000000000507270000000000000000000200000434364500a080280000000040000000000507270080008000800080000200000434364500a080380000000040000000000507270000000000000000000200000434364500a080480000000020000000000507270040008000000000000200000434364500a08058000000001000000000050727008004e200000000000200000434364500a080680000000020000000000507270000008000800080000200000434364500a0b0080000000020000000000507270000000000000000000200000434364500b000080000000010000000000507270000000000000000000200000434364500b0002800000000100000000005072702a004e200000000000200000434364500b010d01000100000000000000507270000008000800080000200000434364500b010101000100000000000000507270020000000000000000200000434364500b01020200000001000000000050727015e000000000000000200000434364500b01050300000000000100000050727000004e200000000000200000434364500b010801000100000000000000507270010008000800080000200000434364500b040401000100000000000000507270000000000000000000200000434364500b080080000000040000000000507270000000000000000000200000434364500b080180000000040000000000507270000000000000000000200000434364500b080280000000040000000000507270080008000800080000200000434364500b080380000000040000000000507270000000000000000000200000434364500b080480000000020000000000507270040008000000000000200000434364500b08058000000001000000000050727008004e200000000000200000434364500b080680000000020000000000507270000008000800080000200000434364500b0b0080000000020000000000000080000000000000000000200000434364500c000080000000010000000000000280000000000000000000200000434364500c000280000000010000000000010d012a004e200000000000200000434364500c010d01000100000000000000010101000008000800080000200000434364500c010101000100000000000000010202020000000000000000200000434364500c01020200000001000000000001050315e000000000000000200000434364500c01050300000000000100000001080100004e200000000000200000434364500c010801000100000000000000040401010008000800080000200000434364500c040401000100000000000000080080000000000000000000200000434364500c080080000000040000000000080180000000000000000000200000434364500c080180000000040000000000080280000000000000000000200000434364500c080280000000040000000000080380080008000800080000200000434364500c080380000000040000000000080480000000000000000000200000434364500c0804800000000200000000002700000400080000000000 +00200000434364500c08058000000001000000000050727008004e200000000000200000434364500c080680000000020000000000507270000008000800080000200000434364500c0b0080000000020000000000507270000000000000000000200000434364500d000080000000010000000000507270000000000000000000200000434364500d0002800000000100000000005072702a004e200000000000200000434364500d010d01000100000000000000507270000008000800080000200000434364500d010101000100000000000000507270020000000000000000200000434364500d01020200000001000000000050727015e000000000000000200000434364500d01050300000000000100000050727000004e200000000000200000434364500d010801000100000000000000507270010008000800080000200000434364500d040401000100000000000000507270000000000000000000200000434364500d080080000000040000000000507270000000000000000000200000434364500d080180000000040000000000507270000000000000000000200000434364500d080280000000040000000000507270080008000800080000200000434364500d080380000000040000000000507270000000000000000000200000434364500d080480000000020000000000507270040008000000000000200000434364500d08058000000001000000000050727008004e200000000000200000434364500d080680000000020000000000507270000008000800080000200000434364500d0b0080000000020000000000507270000000000000000000200000434364500e000080000000010000000000507270000000000000000000200000434364500e0002800000000100000000005072702a004e200000000000200000434364500e010d01000100000000000000507270000008000800080000200000434364500e010101000100000000000000507270020000000000000000200000434364500e01020200000001000000000050727015e000000000000000200000434364500e01050300000000000100000050727000004e200000000000200000434364500e010801000100000000000000507270010008000800080000200000434364500e040401000100000000000000507270000000000000000000200000434364500e080080000000040000000000507270000000000000000000200000434364500e080180000000040000000000507270000000000000000000200000434364500e080280000000040000000000507270080008000800080000200000434364500e080380000000040000000000000080000000000000000000200000434364500e080480000000020000000000000280040008000000000000200000434364500e080580000000010000000000010d0108004e200000000000200000434364500e080680000000020000000000010101000008000800080000200000434364500e0b0080000000020000000000010202000000000000000000200000434364500f000080000000010000000000010503000000000000000000200000434364500f0002800000000100000000000108012a004e200000000000200000434364500f010d01000100000000000000040401000008000800080000200000434364500f010101000100000000000000080080020000000000000000200000434364500f01020200000001000000000008018015e000000000000000200000434364500f01050300000000000100000008028000004e200000000000200000434364500f010801000100000000000000080380010008000800080000200000434364500f040401000100000000000000080480000000000000000000200000434364500f0800800000000400000000002700000000000000000000 +00200000434364500f080180000000040000000000507270000000000000000000200000434364500f080280000000040000000000507270080008000800080000200000434364500f080380000000040000000000507270000000000000000000200000434364500f080480000000020000000000507270040008000000000000200000434364500f08058000000001000000000050727008004e200000000000200000434364500f080680000000020000000000507270000008000800080000200000434364500f0b0080000000020000000000507270000000000000000000200000434364501000008000000001000000000050727000000000000000000020000043436450100002800000000100000000005072702a004e2000000000002000004343645010010d010001000000000000005072700000080008000800002000004343645010010101000100000000000000507270020000000000000000200000434364501001020200000001000000000050727015e000000000000000200000434364501001050300000000000100000050727000004e2000000000002000004343645010010801000100000000000000507270010008000800080000200000434364501004040100010000000000000050727000000000000000000020000043436450100800800000000400000000005072700000000000000000002000004343645010080180000000040000000000507270000000000000000000200000434364501008028000000004000000000050727008000800080008000020000043436450100803800000000400000000005072700000000000000000002000004343645010080480000000020000000000507270040008000000000000200000434364501008058000000001000000000050727008004e200000000000200000434364501008068000000002000000000050727000000800080008000020000043436450100b0080000000020000000000507270000000000000000000200000434364501100008000000001000000000050727000000000000000000020000043436450110002800000000100000000005072702a004e2000000000002000004343645011010d010001000000000000005072700000080008000800002000004343645011010101000100000000000000507270020000000000000000200000434364501101020200000001000000000050727015e000000000000000200000434364501101050300000000000100000050727000004e2000000000002000004343645011010801000100000000000000507270010008000800080000200000434364501104040100010000000000000000008000000000000000000020000043436450110800800000000400000000000002800000000000000000002000004343645011080180000000040000000000010d01000000000000000000200000434364501108028000000004000000000001010108000800080008000020000043436450110803800000000400000000000102020000000000000000002000004343645011080480000000020000000000010503040008000000000000200000434364501108058000000001000000000001080108004e200000000000200000434364501108068000000002000000000004040100000800080008000020000043436450110b0080000000020000000000080080000000000000000000200000434364501200008000000001000000000008018000000000000000000020000043436450120002800000000100000000000802802a004e2000000000002000004343645012010d010001000000000000000803800000080008000800002000004343645012010101000100000000000000080480020000000000000000200000434364501201020200000001000000000027000015e0000000000000 +00200000434364501201050300000000000100000050727000004e2000000000002000004343645012010801000100000000000000507270010008000800080000200000434364501204040100010000000000000050727000000000000000000020000043436450120800800000000400000000005072700000000000000000002000004343645012080180000000040000000000507270000000000000000000200000434364501208028000000004000000000050727008000800080008000020000043436450120803800000000400000000005072700000000000000000002000004343645012080480000000020000000000507270040008000000000000200000434364501208058000000001000000000050727008004e200000000000200000434364501208068000000002000000000050727000000800080008000020000043436450120b0080000000020000000000507270000000000000000000200000434364501300008000000001000000000050727000000000000000000020000043436450130002800000000100000000005072702a004e2000000000002000004343645013010d010001000000000000005072700000080008000800002000004343645013010101000100000000000000507270020000000000000000200000434364501301020200000001000000000050727015e000000000000000200000434364501301050300000000000100000050727000004e2000000000002000004343645013010801000100000000000000507270010008000800080000200000434364501304040100010000000000000050727000000000000000000020000043436450130800800000000400000000005072700000000000000000002000004343645013080180000000040000000000507270000000000000000000200000434364501308028000000004000000000050727008000800080008000020000043436450130803800000000400000000005072700000000000000000002000004343645013080480000000020000000000507270040008000000000000200000434364501308058000000001000000000050727008004e200000000000200000434364501308068000000002000000000050727000000800080008000020000043436450130b0080000000020000000000507270000000000000000000200000434364501400008000000001000000000050727000000000000000000020000043436450140002800000000100000000005072702a004e2000000000002000004343645014010d010001000000000000005072700000080008000800002000004343645014010101000100000000000000000080020000000000000000200000434364501401020200000001000000000000028015e0000000000000002000004343645014010503000000000001000000010d0100004e2000000000002000004343645014010801000100000000000000010101010008000800080000200000434364501404040100010000000000000001020200000000000000000020000043436450140800800000000400000000000105030000000000000000002000004343645014080180000000040000000000010801000000000000000000200000434364501408028000000004000000000004040108000800080008000020000043436450140803800000000400000000000800800000000000000000002000004343645014080480000000020000000000080180040008000000000000200000434364501408058000000001000000000008028008004e200000000000200000434364501408068000000002000000000008038000000800080008000020000043436450140b008000000002000000000008048000000000000000000020000043436450150000800000000100000000002700000000000000000000 +0020000043436450150002800000000100000000005072702a004e2000000000002000004343645015010d010001000000000000005072700000080008000800002000004343645015010101000100000000000000507270020000000000000000200000434364501501020200000001000000000050727015e000000000000000200000434364501501050300000000000100000050727000004e2000000000002000004343645015010801000100000000000000507270010008000800080000200000434364501504040100010000000000000050727000000000000000000020000043436450150800800000000400000000005072700000000000000000002000004343645015080180000000040000000000507270000000000000000000200000434364501508028000000004000000000050727008000800080008000020000043436450150803800000000400000000005072700000000000000000002000004343645015080480000000020000000000507270040008000000000000200000434364501508058000000001000000000050727008004e200000000000200000434364501508068000000002000000000050727000000800080008000020000043436450150b0080000000020000000000507270000000000000000000200000434364501600008000000001000000000050727000000000000000000020000043436450160002800000000100000000005072702a004e2000000000002000004343645016010d010001000000000000005072700000080008000800002000004343645016010101000100000000000000507270020000000000000000200000434364501601020200000001000000000050727015e000000000000000200000434364501601050300000000000100000050727000004e2000000000002000004343645016010801000100000000000000507270010008000800080000200000434364501604040100010000000000000050727000000000000000000020000043436450160800800000000400000000005072700000000000000000002000004343645016080180000000040000000000507270000000000000000000200000434364501608028000000004000000000050727008000800080008000020000043436450160803800000000400000000005072700000000000000000002000004343645016080480000000020000000000507270040008000000000000200000434364501608058000000001000000000050727008004e200000000000200000434364501608068000000002000000000050727000000800080008000020000043436450160b008000000002000000000000008000000000000000000020000043436450170000800000000100000000000002800000000000000000002000004343645017000280000000010000000000010d012a004e2000000000002000004343645017010d010001000000000000000101010000080008000800002000004343645017010101000100000000000000010202020000000000000000200000434364501701020200000001000000000001050315e000000000000000200000434364501701050300000000000100000001080100004e20000000000020000043436450170108010001000000000000000404010100080008000800002000004343645017040401000100000000000000080080000000000000000000200000434364501708008000000004000000000008018000000000000000000020000043436450170801800000000400000000000802800000000000000000002000004343645017080280000000040000000000080380080008000800080000200000434364501708038000000004000000000008048000000000000000000020000043436450170804800000000200000000002700000400080000000000 +00200000434364501708058000000001000000000050727008004e200000000000200000434364501708068000000002000000000050727000000800080008000020000043436450170b0080000000020000000000507270000000000000000000200000434364501800008000000001000000000050727000000000000000000020000043436450180002800000000100000000005072702a004e2000000000002000004343645018010d010001000000000000005072700000080008000800002000004343645018010101000100000000000000507270020000000000000000200000434364501801020200000001000000000050727015e000000000000000200000434364501801050300000000000100000050727000004e2000000000002000004343645018010801000100000000000000507270010008000800080000200000434364501804040100010000000000000050727000000000000000000020000043436450180800800000000400000000005072700000000000000000002000004343645018080180000000040000000000507270000000000000000000200000434364501808028000000004000000000050727008000800080008000020000043436450180803800000000400000000005072700000000000000000002000004343645018080480000000020000000000507270040008000000000000200000434364501808058000000001000000000050727008004e200000000000200000434364501808068000000002000000000050727000000800080008000020000043436450180b0080000000020000000000507270000000000000000000200000434364501900008000000001000000000050727000000000000000000020000043436450190002800000000100000000005072702a004e2000000000002000004343645019010d010001000000000000005072700000080008000800002000004343645019010101000100000000000000507270020000000000000000200000434364501901020200000001000000000050727015e000000000000000200000434364501901050300000000000100000050727000004e20000000000020000043436450190108010001000000000000005072700100080008000800002000004343645019040401000100000000000000507270000000000000000000200000434364501908008000000004000000000050727000000000000000000020000043436450190801800000000400000000005072700000000000000000002000004343645019080280000000040000000000507270080008000800080000200000434364501908038000000004000000000000008000000000000000000020000043436450190804800000000200000000000002800400080000000000002000004343645019080580000000010000000000010d0108004e200000000000200000434364501908068000000002000000000001010100000800080008000020000043436450190b0080000000020000000000010202000000000000000000200000434364501a000080000000010000000000010503000000000000000000200000434364501a0002800000000100000000000108012a004e200000000000200000434364501a010d01000100000000000000040401000008000800080000200000434364501a010101000100000000000000080080020000000000000000200000434364501a01020200000001000000000008018015e000000000000000200000434364501a01050300000000000100000008028000004e200000000000200000434364501a010801000100000000000000080380010008000800080000200000434364501a040401000100000000000000080480000000000000000000200000434364501a0800800000000400000000002700000000000000000000 +00200000434364501a080180000000040000000000507270000000000000000000200000434364501a080280000000040000000000507270080008000800080000200000434364501a080380000000040000000000507270000000000000000000200000434364501a080480000000020000000000507270040008000000000000200000434364501a08058000000001000000000050727008004e200000000000200000434364501a080680000000020000000000507270000008000800080000200000434364501a0b0080000000020000000000507270000000000000000000200000434364501b000080000000010000000000507270000000000000000000200000434364501b0002800000000100000000005072702a004e200000000000200000434364501b010d01000100000000000000507270000008000800080000200000434364501b010101000100000000000000507270020000000000000000200000434364501b01020200000001000000000050727015e000000000000000200000434364501b01050300000000000100000050727000004e200000000000200000434364501b010801000100000000000000507270010008000800080000200000434364501b040401000100000000000000507270000000000000000000200000434364501b080080000000040000000000507270000000000000000000200000434364501b080180000000040000000000507270000000000000000000200000434364501b080280000000040000000000507270080008000800080000200000434364501b080380000000040000000000507270000000000000000000200000434364501b080480000000020000000000507270040008000000000000200000434364501b08058000000001000000000050727008004e200000000000200000434364501b080680000000020000000000507270000008000800080000200000434364501b0b0080000000020000000000507270000000000000000000200000434364501c000080000000010000000000507270000000000000000000200000434364501c0002800000000100000000005072702a004e200000000000200000434364501c010d01000100000000000000507270000008000800080000200000434364501c010101000100000000000000507270020000000000000000200000434364501c01020200000001000000000050727015e000000000000000200000434364501c01050300000000000100000050727000004e200000000000200000434364501c010801000100000000000000507270010008000800080000200000434364501c040401000100000000000000000080000000000000000000200000434364501c080080000000040000000000000280000000000000000000200000434364501c080180000000040000000000010d01000000000000000000200000434364501c080280000000040000000000010101080008000800080000200000434364501c080380000000040000000000010202000000000000000000200000434364501c080480000000020000000000010503040008000000000000200000434364501c08058000000001000000000001080108004e200000000000200000434364501c080680000000020000000000040401000008000800080000200000434364501c0b0080000000020000000000080080000000000000000000200000434364501d000080000000010000000000080180000000000000000000200000434364501d0002800000000100000000000802802a004e200000000000200000434364501d010d01000100000000000000080380000008000800080000200000434364501d010101000100000000000000080480020000000000000000200000434364501d01020200000001000000000027000015e0000000000000 +00200000434364501d01050300000000000100000050727000004e200000000000200000434364501d010801000100000000000000507270010008000800080000200000434364501d040401000100000000000000507270000000000000000000200000434364501d080080000000040000000000507270000000000000000000200000434364501d080180000000040000000000507270000000000000000000200000434364501d080280000000040000000000507270080008000800080000200000434364501d080380000000040000000000507270000000000000000000200000434364501d080480000000020000000000507270040008000000000000200000434364501d08058000000001000000000050727008004e200000000000200000434364501d080680000000020000000000507270000008000800080000200000434364501d0b0080000000020000000000507270000000000000000000200000434364501e000080000000010000000000507270000000000000000000200000434364501e0002800000000100000000005072702a004e200000000000200000434364501e010d01000100000000000000507270000008000800080000200000434364501e010101000100000000000000507270020000000000000000200000434364501e01020200000001000000000050727015e000000000000000200000434364501e01050300000000000100000050727000004e200000000000200000434364501e010801000100000000000000507270010008000800080000200000434364501e040401000100000000000000507270000000000000000000200000434364501e080080000000040000000000507270000000000000000000200000434364501e080180000000040000000000507270000000000000000000200000434364501e080280000000040000000000507270080008000800080000200000434364501e080380000000040000000000507270000000000000000000200000434364501e080480000000020000000000507270040008000000000000200000434364501e08058000000001000000000050727008004e200000000000200000434364501e080680000000020000000000507270000008000800080000200000434364501e0b0080000000020000000000507270000000000000000000200000434364501f000080000000010000000000507270000000000000000000200000434364501f0002800000000100000000005072702a004e200000000000200000434364501f010d01000100000000000000507270000008000800080000200000434364501f010101000100000000000000000080020000000000000000200000434364501f01020200000001000000000000028015e000000000000000200000434364501f010503000000000001000000010d0100004e200000000000200000434364501f010801000100000000000000010101010008000800080000200000434364501f040401000100000000000000010202000000000000000000200000434364501f080080000000040000000000010503000000000000000000200000434364501f080180000000040000000000010801000000000000000000200000434364501f080280000000040000000000040401080008000800080000200000434364501f080380000000040000000000080080000000000000000000200000434364501f080480000000020000000000080180040008000000000000200000434364501f08058000000001000000000008028008004e200000000000200000434364501f080680000000020000000000080380000008000800080000200000434364501f0b008000000002000000000008048000000000000000000020000043436450200000800000000100000000002700000000000000000000 +0020000043436450200002800000000100000000005072702a004e2000000000002000004343645020010d010001000000000000005072700000080008000800002000004343645020010101000100000000000000507270020000000000000000200000434364502001020200000001000000000050727015e000000000000000200000434364502001050300000000000100000050727000004e2000000000002000004343645020010801000100000000000000507270010008000800080000200000434364502004040100010000000000000050727000000000000000000020000043436450200800800000000400000000005072700000000000000000002000004343645020080180000000040000000000507270000000000000000000200000434364502008028000000004000000000050727008000800080008000020000043436450200803800000000400000000005072700000000000000000002000004343645020080480000000020000000000507270040008000000000000200000434364502008058000000001000000000050727008004e200000000000200000434364502008068000000002000000000050727000000800080008000020000043436450200b0080000000020000000000507270000000000000000000200000434364502100008000000001000000000050727000000000000000000020000043436450210002800000000100000000005072702a004e2000000000002000004343645021010d010001000000000000005072700000080008000800002000004343645021010101000100000000000000507270020000000000000000200000434364502101020200000001000000000050727015e000000000000000200000434364502101050300000000000100000050727000004e2000000000002000004343645021010801000100000000000000507270010008000800080000200000434364502104040100010000000000000050727000000000000000000020000043436450210800800000000400000000005072700000000000000000002000004343645021080180000000040000000000507270000000000000000000200000434364502108028000000004000000000050727008000800080008000020000043436450210803800000000400000000005072700000000000000000002000004343645021080480000000020000000000507270040008000000000000200000434364502108058000000001000000000050727008004e200000000000200000434364502108068000000002000000000050727000000800080008000020000043436450210b008000000002000000000000008000000000000000000020000043436450220000800000000100000000000002800000000000000000002000004343645022000280000000010000000000010d012a004e2000000000002000004343645022010d010001000000000000000101010000080008000800002000004343645022010101000100000000000000010202020000000000000000200000434364502201020200000001000000000001050315e000000000000000200000434364502201050300000000000100000001080100004e20000000000020000043436450220108010001000000000000000404010100080008000800002000004343645022040401000100000000000000080080000000000000000000200000434364502208008000000004000000000008018000000000000000000020000043436450220801800000000400000000000802800000000000000000002000004343645022080280000000040000000000080380080008000800080000200000434364502208038000000004000000000008048000000000000000000020000043436450220804800000000200000000002700000400080000000000 +00200000434364502208058000000001000000000050727008004e200000000000200000434364502208068000000002000000000050727000000800080008000020000043436450220b0080000000020000000000507270000000000000000000200000434364502300008000000001000000000050727000000000000000000020000043436450230002800000000100000000005072702a004e2000000000002000004343645023010d010001000000000000005072700000080008000800002000004343645023010101000100000000000000507270020000000000000000200000434364502301020200000001000000000050727015e000000000000000200000434364502301050300000000000100000050727000004e2000000000002000004343645023010801000100000000000000507270010008000800080000200000434364502304040100010000000000000050727000000000000000000020000043436450230800800000000400000000005072700000000000000000002000004343645023080180000000040000000000507270000000000000000000200000434364502308028000000004000000000050727008000800080008000020000043436450230803800000000400000000005072700000000000000000002000004343645023080480000000020000000000507270040008000000000000200000434364502308058000000001000000000050727008004e200000000000200000434364502308068000000002000000000050727000000800080008000020000043436450230b0080000000020000000000507270000000000000000000200000434364502400008000000001000000000050727000000000000000000020000043436450240002800000000100000000005072702a004e2000000000002000004343645024010d010001000000000000005072700000080008000800002000004343645024010101000100000000000000507270020000000000000000200000434364502401020200000001000000000050727015e000000000000000200000434364502401050300000000000100000050727000004e20000000000020000043436450240108010001000000000000005072700100080008000800002000004343645024040401000100000000000000507270000000000000000000200000434364502408008000000004000000000050727000000000000000000020000043436450240801800000000400000000005072700000000000000000002000004343645024080280000000040000000000507270080008000800080000200000434364502408038000000004000000000000008000000000000000000020000043436450240804800000000200000000000002800400080000000000002000004343645024080580000000010000000000010d0108004e200000000000200000434364502408068000000002000000000001010100000800080008000020000043436450240b0080000000020000000000010202000000000000000000200000434364502500008000000001000000000001050300000000000000000020000043436450250002800000000100000000000108012a004e2000000000002000004343645025010d010001000000000000000404010000080008000800002000004343645025010101000100000000000000080080020000000000000000200000434364502501020200000001000000000008018015e000000000000000200000434364502501050300000000000100000008028000004e2000000000002000004343645025010801000100000000000000080380010008000800080000200000434364502504040100010000000000000008048000000000000000000020000043436450250800800000000400000000002700000000000000000000 +002000004343645025080180000000040000000000507270000000000000000000200000434364502508028000000004000000000050727008000800080008000020000043436450250803800000000400000000005072700000000000000000002000004343645025080480000000020000000000507270040008000000000000200000434364502508058000000001000000000050727008004e200000000000200000434364502508068000000002000000000050727000000800080008000020000043436450250b0080000000020000000000507270000000000000000000200000434364502600008000000001000000000050727000000000000000000020000043436450260002800000000100000000005072702a004e2000000000002000004343645026010d010001000000000000005072700000080008000800002000004343645026010101000100000000000000507270020000000000000000200000434364502601020200000001000000000050727015e000000000000000200000434364502601050300000000000100000050727000004e2000000000002000004343645026010801000100000000000000507270010008000800080000200000434364502604040100010000000000000050727000000000000000000020000043436450260800800000000400000000005072700000000000000000002000004343645026080180000000040000000000507270000000000000000000200000434364502608028000000004000000000050727008000800080008000020000043436450260803800000000400000000005072700000000000000000002000004343645026080480000000020000000000507270040008000000000000200000434364502608058000000001000000000050727008004e200000000000200000434364502608068000000002000000000050727000000800080008000020000043436450260b0080000000020000000000507270000000000000000000200000434364502700008000000001000000000050727000000000000000000020000043436450270002800000000100000000005072702a004e2000000000002000004343645027010d010001000000000000005072700000080008000800002000004343645027010101000100000000000000507270020000000000000000200000434364502701020200000001000000000050727015e000000000000000200000434364502701050300000000000100000050727000004e2000000000002000004343645027010801000100000000000000507270010008000800080000200000434364502704040100010000000000000000008000000000000000000020000043436450270800800000000400000000000002800000000000000000002000004343645027080180000000040000000000010d01000000000000000000200000434364502708028000000004000000000001010108000800080008000020000043436450270803800000000400000000000102020000000000000000002000004343645027080480000000020000000000010503040008000000000000200000434364502708058000000001000000000001080108004e200000000000200000434364502708068000000002000000000004040100000800080008000020000043436450270b0080000000020000000000080080000000000000000000200000434364502800008000000001000000000008018000000000000000000020000043436450280002800000000100000000000802802a004e2000000000002000004343645028010d010001000000000000000803800000080008000800002000004343645028010101000100000000000000080480020000000000000000200000434364502801020200000001000000000027000015e0000000000000 +00200000434364502801050300000000000100000050727000004e2000000000002000004343645028010801000100000000000000507270010008000800080000200000434364502804040100010000000000000050727000000000000000000020000043436450280800800000000400000000005072700000000000000000002000004343645028080180000000040000000000507270000000000000000000200000434364502808028000000004000000000050727008000800080008000020000043436450280803800000000400000000005072700000000000000000002000004343645028080480000000020000000000507270040008000000000000200000434364502808058000000001000000000050727008004e200000000000200000434364502808068000000002000000000050727000000800080008000020000043436450280b00800000000200000000005072700000000000000000000c00005350744d01010202000c000053505a5300009600000c0000505a435300200025000c0000496e436d01000000 \ No newline at end of file diff --git a/src/__tests__/connection/dump.js b/src/__tests__/connection/dump.js new file mode 100644 index 000000000..13e13a4cf --- /dev/null +++ b/src/__tests__/connection/dump.js @@ -0,0 +1,46 @@ +const fs = require('fs') +const path = require('path') +const { AtemSocket } = require('../../../dist/lib/atemSocket') +const { DEFAULT_PORT } = require('../../../dist') + +const args = process.argv.slice(2) +if (args.length < 2) { + console.log('Usage: node dump.js ') + console.log('eg: node dump.js 10.42.13.99 case1') + process.exit() +} + +const socket = new AtemSocket({ + debug: false, + log: console.log, + disableMultithreaded: true, + address: args[0], + port: DEFAULT_PORT +}) +socket.on('disconnect', () => { + console.log('disconnect') + process.exit(1) +}) + + +const output = [] + +socket.on('commandsReceived', cmds => { + const initComplete = cmds.find(cmd => cmd.constructor.name === 'InitCompleteCommand') + if (initComplete) { + console.log('complete') + const filePath = path.resolve(__dirname, `./${args[1]}.data`) + fs.writeFileSync(filePath, output.join('\n')) + process.exit(0) + } +}) + +const origParse = (socket._parseCommands).bind(socket) +socket._parseCommands = (payload) => { + output.push(payload.toString('hex')) + return origParse(payload) +} + + +socket.connect() +console.log('connecting') \ No newline at end of file diff --git a/src/__tests__/connection/ps4k-v7.2.data b/src/__tests__/connection/ps4k-v7.2.data new file mode 100644 index 000000000..e13323788 --- /dev/null +++ b/src/__tests__/connection/ps4k-v7.2.data @@ -0,0 +1,8 @@ +000c00005f76657200020016003400005f70696e4154454d2050726f64756374696f6e2053747564696f20344b0011600000000028369b604c081160043da460001c00005f746f70011802010002000400000001000101000001a360000c00005f4d65430001a260000c00005f6d706c14001060001000005f4d7643010a010100010101000c00005f414d430a01000000e400005f564d430012a36000c81060000000800000000101000000000000400000000202c810600000008000000004030000000000004000000008047ca260000000100000001005cfa86000000020000000200600000000000040000000400700000000000080000000800800000000000100000001000900000000000200000002000a00000000000040000004000b45106000000080000008000c00000000000040000010000de7276000000080000020000ed0a86000000100000001000f000000000002000000020010000000000000400000004011379b600000008000000080000c00005f4d414364000000000c0000506f777201000000000c00005669644d04d51260000c00004448566d00000000000c00004448566d01010000000c00004448566d02029b60000c00004448566d03031060000c00004448566d04041560000c00004448566d05050000000c00004448566d06061560000c00004448566d0707e041000c00004448566d08080000000c00004448566d0909a860000c00004448566d0a0aa360000c00004448566d0b0b0000000c00004448566d0c0c0000000c00004448566d0d0d2760000c00004448566d0e080000000c00004448566d0f09a960000c00004448566d1006a960000c00004448566d110788ca000c00005633736c00f92760002c0000496e5072000000178000000000cba860202020202121212100000000447300600100010001391301002c0000496e5072000150726f6a20535200000000000000841a1360a0cf5072535200600002000200dc1301002c0000496e5072000250726f6a20534c000000000000000100000000345072534c00000002000200f91301002c0000496e50720003566964656f2057616c6c0020202021212121000057616c6c00000002000200001301002c0000496e507200045265636f726400000000000000007cd11060980052656300006000020002000a1301002c0000496e50720005466f6c646261636b203100399b60470a0a0a0c0046626b3100000001000100001301002c0000496e50720006466f6c646261636b20320000000098399b60102746626b3200da00010001003a1301002c0000496e50720007446561643f000c000000540f1160543a9b6001004465616400600001000100e71301002c0000496e5072000852696368205265636f726400000094da126001005269636800600001000100001301002c0000496e507203e8436f6c6f7220426172730001000058451060a0004261727301000100010002001301002c0000496e507207d1436f6c6f72203100a860040c156006000000a467436f6c3101600100010003000301002c0000496e507207d2436f6c6f722032000000c82b006008e72760a000436f6c3201000100010003000301002c0000496e50720bc24d6564696120506c6179657220310000000074824d50310001600100010004001301002c0000496e50720bc34d6564696120506c617965722031204b657900004d50314b01000100010005331301002c0000496e50720bcc4d6564696120506c61796572203200000000c63a4d50320001000100010004f91301002c0000496e50720bcd4d6564696120506c617965722032204b657900214d50324b010001000100053b1301002c0000496e50720faa4b65792031204d61736b006174204572726f725d4d314b3101750100010082490300 +002c0000496e5072139244534b2031204d61736b0054454d2050726f6475444b314d012001000100826f0300002c0000496e5072139c44534b2032204d61736b001c00005f746f700118444b324d01040100010082010300002c0000496e5072271a00430001a260000c00005f6d706c1400106000104c49564500430100010080010300002c0000496e5072271b000000e400005f564d430012a36000c8106000005076770000010100010080000300002c0000496e50721b59436c65616e20466565642031004000000008047c4366643101100100010080cf0300002c0000496e50721b5a436c65616e2046656564203200000000008000004366643201000100010080000300002c0000496e50721f41417578696c6961727920310004000b45106000004175783101000100010081000200000c00004d76564d00070080000c00004d76564d01060100000c00004d76564d02070200000c00004d76564d03060040000c00004d76564d04040080000c00004d76564d05054143000c00004d76564d06067772000c00004d76564d0707644d000c00004d76564d0808566d000c00004d76564d0909566d000c00004d76564d0a06566d000c00004d76564d0b07566d000c00004d76564d0c06566d000c00004d76564d0d07566d000c00004d76564d0e08566d000c00004d76564d0f09566d000c00004d76564d1006566d000c00004d76564d1107566d000c00004d76507200000000001000004d76496e0000271b000b0000000c000056754d4300000000001000004d76496e0001271a010c0000000c000056754d4300010060001000004d76496e000200010148566d000c000056754d430002006d001000004d76496e0003000301f92760000c000056754d4300030017001000004d76496e0004000201212121000c000056754d4300040000001000004d76496e0005000401015072000c000056754d4300050100001000004d76496e0006000501020002000c000056754d4300060072001000004d76496e0007000601000000000c000056754d4300070000001000004d76496e0008271a016e5072000c000056754d430008006c001000004d76496e00090008016c0000000c000056754d4300090160000c000056754d6f00647264000c00005072674900d10007001000005072764900020007000a130100100000547253530000010001646261000c00005472507200000a0a00100000547250730000190100001301000c0000544d78500019466f000c000054447050001907d1001c000054577050001906da000007d1138800001388138800005072001c0000544476500c0000000f546011543a609b0001446561640060001c0000545374500001016001f402bc000800020049002200056f72000c00004b654f6e00000069001c00004b6542500000000000000bc20bc300722328dcd8c1803e80001400004b654c6d0000016001f402bc00730100001400004b65436b0000000003e803840000006f001800004b65507400000660138813880000138813880060004400004b654456002c006072506e496f43d20720726f6c0000003260002bc808e7276000a06f436c32010001000001000301032c009b606e497250c20b654d64696120001000004b6546530000000074824d50003c00004b4b46500400130160002c0072506e49654dc30b2061696479616c5072653120204b65790000504d4b31000100010100330501132c006027003c00004b4b46506469612079616c503220726500000000504d3ac6000100320001000104f91301002c60006e497250cd0b4d65696420616c5079610010000044736b420021000000000100001c000044736b500000190001f402bc00002328dcd8c1803e80736b0010000044736b5300000000193101750010000044736b420146000000009b60 +001c000044736b500100190001f402bc00002328dcd8c1803e80726f0010000044736b5301000000196f0300000c00004674625000194453000c0000467462530000001900100000436f6c56004d01f403e801f400100000436f6c56016e010e03e801f4000c000041757853006d0002002000004d5066650045000000000000000000000000000000000000001b0000002000004d506665001200010000000000000000000000000000000000000000002000004d5066650059000200000000000000000000000000000000007c0000002000004d50666500cf00030000000000000000000000000000000000650000002000004d5066650000000400000000000000000000000000000000006e0000002000004d506665007200050000000000000000000000000000000000000000002000004d5066650076000600000000000000000000000000000000000c0000002000004d506665000c00070000000000000000000000000000000000040000002000004d506665000500080000000000000000000000000000000000760000002000004d5066650076000900000000000000000000000000000000000c0000002000004d506665000c000a0000000000000000000000000000000000060000002000004d5066650007000b0000000000000000000000000000000000760000002000004d5066650076000c00000000000000000000000000000000000c0000002000004d5066650010000d0000000000000000000000000000000000750000002000004d5066650076000e0000000000000000000000000000000000010000002000004d5066650002000f0000000000000000000000000000000000100000002000004d50666500f900100000000000000000000000000000000000760000002000004d506665000c00110000000000000000000000000000000000050000002000004d506665007500120000000000000000000000000000000000020000002000004d5066650006001300000000000000000000000000000000000c0000000c00004d50434500010000000c00004d50434501010100001c000052584d530000006c000000000000006e0000000800020000001c00005258435000000100000c000000000000000000000000000000280000525853530000526500000000ffffffff000000000010a460000000000000000000006261000c0000525843430000000a001c000052584d53000119010000000000000060000000500002006f001c00005258435000010100001c00000000000000000000000007d100280000525853530001507200000000ffffffff0000000000546011000000000000000000000060000c00005258434300010060001c000052584d530002002200000000000000000000006e00020069001c0000525843500002010000000000000000000000000000003e8000280000525853530002016000000000ffffffff000000000065436b00000000000000000000006f000c00005258434300020060001c000052584d530003006000000000000000560000006000020049001c0000525843500003010000000000000000000000000000000100002800005258535300039b6000000000ffffffff0000000000106179000000000000000000004d50000c00005258434300030001001c0000414d49500001000b000100020061800000000000004b6579001c0000414d495000020000000200020000800000000000004b4650001c0000414d49500003006500030002004d80000000000000010001001c0000414d49500004005000040002006480000000000000102032001c0000414d49500005000000050001007380000000000000f402bc001c0000414d49500006006b00060001007380000000000000310175001c0000414d49500007000000070001008e80000000000000000000 +001c0000414d4950000800000008000100008000000000000080726f001c0000414d495004b1020000010080010c80000000000000194453001c0000414d495003e9021900020020016f80000000000000e801f400100000414d4d4f8000000000e801f400140000414d6d4f016d800000000001005007d000280000414d546c000a00010000020000030000040000050000060000070000080004b10103e901000c00004c4b535400000000001000005f546c43000100000859000200140000546c496e00080000000000000300000000500000546c5372001700000000010000020000030000040000050000060000070300080003e80007d10007d2000bc2000bc3000bcc000bcd000faa00139200139c00271a00271b001b59001b5a0000000c00004d5250720000ffff000c00004d52635300500000001c00004d50727000000100000c000050524f4720414c4c20415558001c00004d50727000010100000a00004d503120414c4c2054560000001400004d507270000201000003000043757400001800004d5072700003010000050000426c616e6b760009001000004d5072700004000000000000001000004d5072700005000000000000001000004d5072700006000000000000001000004d5072700007000000000000001000004d5072700008000000000000001000004d5072700009000000000000001000004d507270000a000000000000001000004d507270000b000000000000001000004d507270000c000000000000001000004d507270000d000000000000001000004d507270000e000000000000001000004d507270000f000000000000001000004d5072700010000000000000001000004d5072700011000000000000001000004d5072700012000000000000001000004d5072700013000000000000001c00004d507270001401000009000050616e656c204f4646506665001800004d507270001501000008000050616e656c204f4e001800004d50727000160100000800004d61696e204f4646001800004d50727000170100000700004d41494e204f4e6e001c00004d50727000180100000a000053747564696f204f4646006e001c00004d507270001901000009000053747564696f204f4e000000001800004d507270001a010000080000426f7468204f4646001000004d507270001b000000000000001000004d507270001c000000000000001000004d507270001d000000000000001000004d507270001e000000000000001000004d507270001f000000000000001000004d5072700020000000000000001000004d5072700021000000000000001000004d5072700022000000000000001000004d5072700023000000000000001000004d5072700024000000000000001000004d5072700025000000000000001000004d5072700026000000000000001000004d5072700027000000000000001000004d5072700028000000000000001000004d5072700029000000000000001000004d507270002a000000000000001000004d507270002b000000000000001000004d507270002c000000000000001000004d507270002d000000000000001000004d507270002e000000000000001000004d507270002f000000000000001000004d5072700030000000000000001000004d5072700031000000000000001000004d5072700032000000000000001000004d5072700033000000000000001000004d5072700034000000000000001000004d5072700035000000000000001000004d5072700036000000000000001000004d5072700037000000000000001000004d5072700038000000000000001000004d5072700039000000000000001000004d507270003a000000000000001000004d507270003b000000000000001000004d507270003c000000000000001000004d507270003d000000000000 +001000004d507270003e000000000000001000004d507270003f000000000000001000004d5072700040000000000000001000004d5072700041000000000000001000004d5072700042000000000000001000004d5072700043000000000000001000004d5072700044000000000000001000004d5072700045000000000000001000004d5072700046000000000000001000004d5072700047000000000000001000004d5072700048000000000000001000004d5072700049000000000000001000004d507270004a000000000000001000004d507270004b000000000000001000004d507270004c000000000000001000004d507270004d000000000000001000004d507270004e000000000000001000004d507270004f000000000000001000004d5072700050000000000000001000004d5072700051000000000000001000004d5072700052000000000000001000004d5072700053000000000000001000004d5072700054000000000000001000004d5072700055000000000000001000004d5072700056000000000000001000004d5072700057000000000000001000004d5072700058000000000000001000004d5072700059000000000000001000004d507270005a000000000000001000004d507270005b000000000000001000004d507270005c000000000000001000004d507270005d000000000000001000004d507270005e000000000000001000004d507270005f000000000000001000004d5072700060000000000000001000004d5072700061000000000000001000004d5072700062000000000000001000004d5072700063000000000000000c00004343737400001388002000004343645001000080000000010000000000507270000000000000000000200000434364500100038000000001000000000050727004000100000900000020000043436450010101010001000000000000001501000208000050616e6500200000434364500101020200000001000000000061696e15e04646001800000020000043436450010105030000000000010000001c434500004e200018010000200000434364500101080100010000000000000050727001190100000900000020000043436450010404010001000000000000001a010000080000426f746800200000434364500108008000000004000000000010000000000000000000000020000043436450010801800000000400000000001000000000000000000000002000004343645001080280000000040000000000100000080008000800080000200000434364500108038000000004000000000010000000000000000000000020000043436450010804800000000200000000001002bc0400080000240000002000004343645001080580000000010000000000104350080072700026000000200000434364500108068000000002000000000010016000000800002800000020000043436450010b008000000002000000000010722000000000002a000000200000434364500200008000000001000000000010006000007270002c000000200000434364500200038000000001000000000010010004007270002e0000002000004343645002010101000100000000000000100000025072700030000000200000434364500201020200000001000000000010000b15e072700032000000200000434364500201050300000000000100000010000200004e2000340000002000004343645002010801000100000000000000108000015072700036000000200000434364500204040100010000000000000010000000507270003800000020000043436450020800800000000400000000001002bc00000000000000000020000043436450020801800000000400000000001001000000000000000000 +002000004343645002080280000000040000000000507270080008000800080000200000434364500208038000000004000000000050727000000000000000000020000043436450020804800000000200000000005072700400080000000000002000004343645002080580000000010000000000507270080000000000000000200000434364500208068000000002000000000050727000000800000000000020000043436450020b0080000000020000000000507270000000000000000000200000434364500300008000000001000000000050727000000000000000000020000043436450030003800000000100000000005072700400000000000000002000004343645003010101000100000000000000507270024f00000000000000200000434364500301020200000001000000000050727015e000000000000000200000434364500301050300000000000100000050727000004e20000000000020000043436450030108010001000000000000005072700155000000000000002000004343645003040401000100000000000000507270005700000000000000200000434364500308008000000004000000000050727000000000000000000020000043436450030801800000000400000000005072700000000000000000002000004343645003080280000000040000000000507270080008000800080000200000434364500308038000000004000000000050727000000000000000000020000043436450030804800000000200000000005072700400080000000000002000004343645003080580000000010000000000507270080000000000000000200000434364500308068000000002000000000000008000000800000000000020000043436450030b0080000000020000000000000380000000000000000000200000434364500400008000000001000000000001010100000000000000000020000043436450040003800000000100000000000102020400000100000000002000004343645004010101000100000000000000010503020000000001000000200000434364500401020200000001000000000001080115e000000000000000200000434364500401050300000000000100000004040100004e200000000000200000434364500401080100010000000000000008008001000004000000000020000043436450040404010001000000000000000801800000000400000000002000004343645004080080000000040000000000080280000000000000000000200000434364500408018000000004000000000008038000000000000000000020000043436450040802800000000400000000000804800800080008000800002000004343645004080380000000040000000000080580000000000000000000200000434364500408048000000002000000000008068004000800000000000020000043436450040805800000000100000000000b0080080000020000000000200000434364500408068000000002000000000000008000000800000000000020000043436450040b0080000000020000000000000380000000000000000000200000434364500500008000000001000000000001010100000000000000000020000043436450050003800000000100000000000102020400000100000000002000004343645005010101000100000000000000010503020000000001000000200000434364500501020200000001000000000001080115e000000000000000200000434364500501050300000000000100000004040100004e2000000000002000004343645005010801000100000000000000080080010000040000000000200000434364500504040100010000000000000008018000000004000000000020000043436450050800800000000400000000005072700000000000000000 +0020000043436450050801800000000400000000005072700000000000000000002000004343645005080280000000040000000000507270080008000800080000200000434364500508038000000004000000000050727000000000000000000020000043436450050804800000000200000000005072700400080000000000002000004343645005080580000000010000000000507270080008000000000000200000434364500508068000000002000000000050727000000800000000000020000043436450050b008000000002000000000050727000000000000000000020000043436450060000800000000100000000005072700000000000000000002000004343645006000380000000010000000000507270040000000000000000200000434364500601010100010000000000000050727002e000000000000000200000434364500601020200000001000000000050727015e04e200000000000200000434364500601050300000000000100000050727000004e20000000000020000043436450060108010001000000000000005072700157000000000000002000004343645006040401000100000000000000507270000000000000000000200000434364500608008000000004000000000050727000000000000000000020000043436450060801800000000400000000005072700000000000000000002000004343645006080280000000040000000000507270080008000800080000200000434364500608038000000004000000000050727000000000000000000020000043436450060804800000000200000000005072700400080000000000002000004343645006080580000000010000000000000080080008000000000000200000434364500608068000000002000000000000038000000800000000000020000043436450060b008000000002000000000001010100000000000000000020000043436450070000800000000100000000000102020000000100000000002000004343645007000380000000010000000000010503040000000001000000200000434364500701010100010000000000000001080102e000000000000000200000434364500701020200000001000000000004040115e04e200000000000200000434364500701050300000000000100000008008000004e20000000000020000043436450070108010001000000000000000801800100000400000000002000004343645007040401000100000000000000080280000000000000000000200000434364500708008000000004000000000008038000000000000000000020000043436450070801800000000400000000000804800000000000000000002000004343645007080280000000040000000000080580080008000800080000200000434364500708038000000004000000000008068000000000000000000020000043436450070804800000000200000000000b00800400080000000000002000004343645007080580000000010000000000000080080008000000000000200000434364500708068000000002000000000000038000000800000000000020000043436450070b008000000002000000000001010100000000000000000020000043436450080000800000000100000000000102020000000100000000002000004343645008000380000000010000000000010503040000000001000000200000434364500801010100010000000000000001080102e000000000000000200000434364500801020200000001000000000004040115e04e200000000000200000434364500801050300000000000100000008008000004e200000000000200000434364500801080100010000000000000008018001000004000000000020000043436450080404010001000000000000005072700000000000000000 +00200000434364500808008000000004000000000050727000000000000000000020000043436450080801800000000400000000005072700000000000000000002000004343645008080280000000040000000000507270080008000800080000200000434364500808038000000004000000000050727000000000000000000020000043436450080804800000000200000000005072700400080000000000002000004343645008080580000000010000000000507270080008000000000000200000434364500808068000000002000000000050727000000800000000000020000043436450080b00800000000200000000005072700000000000000000000c0000496e436d01000380 \ No newline at end of file diff --git a/src/__tests__/connection/tvshd-v8.0.0.data b/src/__tests__/connection/tvshd-v8.0.0.data new file mode 100644 index 000000000..d308a297a --- /dev/null +++ b/src/__tests__/connection/tvshd-v8.0.0.data @@ -0,0 +1,5 @@ +000c00005f7665720002001c003400005f70696e4154454d2054656c65766973696f6e2053747564696f204844000000001000004d5072700045000008000000002000005f746f70011802010402010401000001010400000001010101000000000c00005f4d654300010000000c00005f6d706c14007270001400005f4d7643010a01010000010101000000000c00005f414d430a00017000c200005f564d43000e6c430050727000000080000000000001496e4d000000400000000000020000100000008000000000000300000000000040000000000004000000000000100000000000051902080000002000000000000600c8260000004000000000000738000000000080000000000008000000000001000000000000090000000000020000000000000a7000540000044000000000000b4d50720000088000000000000c10ffff0000144000000000000d000000000028800000000000000c00005f4d4143646e4d50002000005f44564500000011101112131415161718191a1b1c1d1e1f22704d50000c0000506f777201000010000c00005669644d04000000000c00005633736c0070005c000c000054634c6b00704d50002c0000496e50720000426c61636b007270005e00000000000000107270426c6b00015f0100010001001301002c0000496e5072000143616d657261203100507270006100000000000043616d3101500002000200001301002c0000496e5072000243616d6572612032000c7270434373740000138843616d3201500002000200001301002c0000496e5072000343616d657261203300100000000c7270496e436d43616d3301100002000200701301002c0000496e5072000443616d65726120340000000000104d534d50727043616d3401000002000200001301002c0000496e5072000543616d657261203500140000000000000010674943616d3501150001000100001301002c0000496e5072000643617370617243472046756c6c0000000000000046756c6c00500001000100001301002c0000496e5072000743617370617243472046696c6c007270001a000043472d4600100001000100701301002c0000496e507200084361737061724347204b65790010ffff4d50727043472d4b00000001000100001301002c0000496e507203e8436f6c6f722042617273000000000000001000004261727301200100010002001301002c0000496e507207d1436f6c6f722031004d5072700022000000000000436f6c3101500100010003000301002c0000496e507207d2436f6c6f72203200001000004d50727000250000436f6c3201100100010003700301002c0000496e50720bc24d6564696120506c61796572203100504d5072704d50310001000100010004001301002c0000496e50720bc34d6564696120506c617965722031204b657900004d50314b01540100010005051301002c0000496e50720bcc4d6564696120506c6179657220320005805406054d50320001740100010004001301002c0000496e50720bcd4d6564696120506c617965722032204b657900004d50324b013e0100010005021301002c0000496e50720faa4b65792031204d61736b000504000000040000004d314b3101540100010082000300002c0000496e5072139244534b2031204d61736b000088ba010268540605444b314d01000100010082020300002c0000496e5072139c44534b2032204d61736b0000010000004c2a0102444b324d013f0100010082020300002c0000496e5072271a50726f6772616d00243f0200ea020b027864697550676d0001490100010080000300002c0000496e5072271b50726576696577002427190200000000e0e600025076770001000100010080000300002c0000496e50721b59436c65616e20466565642031000aadde0a0aadde4366643101110100010080020300 +002c0000496e50721b5a436c65616e20466565642032004d2054656c657643666432012001000100806f0300002c0000496e50721f41417578696c69617279203100ffff5f746f7001184175783101040100010081040200000c00004d76564d00070006000c00004d76564d01060000000c00004d76564d02070000000c00004d76564d03060101000c00004d76564d04044d43000c00004d76564d05054d43000c00004d76564d06060080000c00004d76564d07070000000c00004d76564d08080000000c00004d76564d09090000000c00004d76564d0a060000000c00004d76564d0b071902000c00004d76564d0c060600000c00004d76564d0d070007000c00004d765072000c0000001000004d76496e0000271b00010000000c000056754d4300000070000c000053614d770000010b001000004d76496e0001271a0100ffff000c000056754d4300010100000c000053614d770001000c001000004d76496e0002000101005f44000c000056754d4300020015000c000053614d7700020070001000004d76496e000300020100000c000c000056754d430003000c000c000053614d770003000c001000004d76496e000400030100496e000c000056754d4300040070000c000053614d7700040070001000004d76496e000500040100002c000c000056754d4300050065000c000053614d7700050000001000004d76496e0006000501000000000c000056754d4300060002000c000053614d7700060070001000004d76496e0007000601000002000c000056754d430007016e000c000053614d7700070033001000004d76496e0008000701006d33000c000056754d430008012c000c000053614d7700080065001000004d76496e0009000801007270000c000056754d4300090000000c000053614d7700090005000c000056754d6f00640000000c000050726749006100060010000050727649000100000050496e0010000054725353000001000146756c000c00005472507200006c6c00100000547250730000192c0000496e000c0000544d785000194347000c00005444705000190000001c0000545770500019017000000000138800001388138800007370001c0000544476500019191b00000000000000000000000000010000001c000054537450000100e800000000002000020049002200050000000c00004b654f6e00000000001c00004b65425000000001010000000000006f0000000000000000001400004b654c6d000000310000000000000300001400004b65436b000000000000000000000000001800004b6550740000000000001388000001f401f40070004400004b65445600000bc20000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000001796572001000004b6546530000000000540000003c00004b4b46500000016e000003e8000003e8000000000000000000000000000000000000000000740000000003e80168192c0000000000000000003c00004b4b465000000272000003e8000003e8000000000000000000000000000000000000000000720000000003e80168196100000000000000000010000044736b420054000700088200001c000044736b5000001900000000000000000000000000000001020010000044736b5300010000190082020010000044736b420172000000004b20001c000044736b5001001900000000000000000000000000000082020010000044736b530100000019726f67000c00004674625000190b02000c0000467462530000001900100000436f6c56006101f403e801f400100000436f6c560127010e03e801f4000c00004175785300000000002000004d5066650000000000000000000000000000000000000000000a0000 +002000004d506665005a00010000000000000000000000000000000000760000002000004d506665006f00020000000000000000000000000000000000720000002000004d506665001800030000000000000000000000000000000000760000002000004d5066650076000400000000000000000000000000000000000c0000002000004d506665000c00050000000000000000000000000000000000050000002000004d506665000600060000000000000000000000000000000000760000002000004d5066650076000700000000000000000000000000000000000c0000002000004d506665000c00080000000000000000000000000000000000070000002000004d506665000c000900000000000000000000000000000000000c0000002000004d506665000c000a0000000000000000000000000000000000010000002000004d5066650075000b0000000000000000000000000000000000100000002000004d5066650000000c0000000000000000000000000000000000610000002000004d5066650076000d0000000000000000000000000000000000030000002000004d5066650003000e00000000000000000000000000000000000c0000002000004d506665000c000f0000000000000000000000000000000000050000002000004d506665007500100000000000000000000000000000000000100000002000004d506665000000110000000000000000000000000000000000610000002000004d506665007600120000000000000000000000000000000000070000002000004d5066650007001300000000000000000000000000000000000c0000000c00004d50434500010000000c00004d50434501010100001c000052584d5300007270c0a8016f00060143000501000002002c001c000052584350000001000075000000000000000000000000674900280000525853530000764900000000ffffffff0000000000725353000000000000000000000000000c00005258434300000001001c000052584d530001496e0000000000000050000000470002006c001c000052584350000101000057000000000000000000000000000000280000525853530001434700000000ffffffff000000000000000000000000000000000000002c000c00005258434300010000001c000052584d5300020000000000000000006e0000000000020000001c000052584350000201000000000000000000000000000000000000280000525853530002000000000000ffffffff0000000000000000000000000000000000000000000c00005258434300020088001c000052584d530003002c00000000000000c20000000000020000001c000052584350000301000000000000000000000000000000000000280000525853530003000000000000ffffffff0000000000654653000000000000000000000505000c000052584343000300e8000c0000414d50500000000000180000414d49500001000000010002000080000000000000180000414d49500002006900020002000080000000000000180000414d49500003000000030002000080000000000000180000414d49500004006100040002000080000000000000180000414d49500005000000050001007380000000000000180000414d49500006000000060001011080000000000000180000414d49500007002c00070001017280000000000000180000414d49500008000000080001000080000000000000180000414d49500515025300000200007200000000000000180000414d495003e9027500010020010080000000010000100000414d4d4f800000000010657600280000414d546c000a00010000020000030000040000050000060100070100080005150003e90100100000414d485040000000287a287a000c000041544d5000000100 +00100000544d4950005a00050101000000100000544d4950000000060101000000100000544d4950006f00070101000000100000544d49500000000801010000001400004d4d4f50000103000100000501000000001400004d4d4f50010103000120000601000065001400004d4d4f50020103000100000701000000001400004d4d4f5003010300010c000801000000000c00004c4b535400000000001000005f546c43000100000806000600140000546c496e00080000000000010101000000540000546c5372001800000200010000020000030000040000050000060100070100080103e80007d10007d2000bc2000bc3000bcc000bcd000faa00139201139c00271a00271b001b59001b5a001f4100000000240000546c466300080001000002000003000004000005000006000007000008000000000c00004d5250720000ffff000c00004d52635300000000001000004d5072700000000000000000001c00004d50727000010100000900006661646520746f2031000000001000004d5072700002000000000000001000004d5072700003000000000000001000004d5072700004000000000000001000004d5072700005000000000000001000004d5072700006000000000000001000004d5072700007000000000000001000004d5072700008000000000000001000004d5072700009000000000000001000004d507270000a000000000000001000004d507270000b000000000000001000004d507270000c000000000000001000004d507270000d000000000000001000004d507270000e000000000000001000004d507270000f000000000000001000004d5072700010000000000000001000004d5072700011000000000000001000004d5072700012000000000000001000004d5072700013000000000000001000004d5072700014000000000000001000004d5072700015000000000000001000004d5072700016000000000000001000004d5072700017000000000000001000004d5072700018000000000000001000004d5072700019000000000000001000004d507270001a000000000000001000004d507270001b000000000000001000004d507270001c000000000000001000004d507270001d000000000000001000004d507270001e000000000000001000004d507270001f000000000000001000004d5072700020000000000000001000004d5072700021000000000000001000004d5072700022000000000000001000004d5072700023000000000000001000004d5072700024000000000000001000004d5072700025000000000000001000004d5072700026000000000000001000004d5072700027000000000000001000004d5072700028000000000000001000004d5072700029000000000000001000004d507270002a000000000000001000004d507270002b000000000000001000004d507270002c000000000000001000004d507270002d000000000000001000004d507270002e000000000000001000004d507270002f000000000000001000004d5072700030000000000000001000004d5072700031000000000000001000004d5072700032000000000000001000004d5072700033000000000000001000004d5072700034000000000000001000004d5072700035000000000000001000004d5072700036000000000000001000004d5072700037000000000000001000004d5072700038000000000000001000004d5072700039000000000000001000004d507270003a000000000000001000004d507270003b000000000000001000004d507270003c000000000000001000004d507270003d000000000000001000004d507270003e000000000000001000004d507270003f000000000000001000004d5072700040000000000000001000004d5072700041000000000000 +001000004d5072700042000000000000001000004d5072700043000000000000001000004d5072700044000000000000001000004d5072700045000000000000001000004d5072700046000000000000001000004d5072700047000000000000001000004d5072700048000000000000001000004d5072700049000000000000001000004d507270004a000000000000001000004d507270004b000000000000001000004d507270004c000000000000001000004d507270004d000000000000001000004d507270004e000000000000001000004d507270004f000000000000001000004d5072700050000000000000001000004d5072700051000000000000001000004d5072700052000000000000001000004d5072700053000000000000001000004d5072700054000000000000001000004d5072700055000000000000001000004d5072700056000000000000001000004d5072700057000000000000001000004d5072700058000000000000001000004d5072700059000000000000001000004d507270005a000000000000001000004d507270005b000000000000001000004d507270005c000000000000001000004d507270005d000000000000001000004d507270005e000000000000001000004d507270005f000000000000001000004d5072700060000000000000001000004d5072700061000000000000001000004d5072700062000000000000001000004d5072700063000000000000000c00004343737400001388000c00005350744d010d0000000c000053505a5300009600000c0000505a435300100000000c0000496e436d01000000 \ No newline at end of file From 06ec5a5357fe10f5893d9ee057a7145b93b2ce88 Mon Sep 17 00:00:00 2001 From: Julian Waller Date: Mon, 16 Dec 2019 23:35:38 +0000 Subject: [PATCH 59/68] feat: parse multiviewerConfigCommand --- src/__tests__/connection.spec.ts | 10 ++++++++ src/atem.ts | 2 +- src/commands/DeviceProfile/index.ts | 1 + .../DeviceProfile/multiviewerConfigCommand.ts | 25 +++++++++++++++++++ src/commands/DeviceProfile/topologyCommand.ts | 3 --- .../Settings/MultiViewerSourceCommand.ts | 2 +- src/commands/__tests__/index.spec.ts | 4 --- src/commands/__tests__/v8.0.spec.ts | 4 --- src/state/info.ts | 7 +++++- 9 files changed, 44 insertions(+), 14 deletions(-) create mode 100644 src/commands/DeviceProfile/multiviewerConfigCommand.ts diff --git a/src/__tests__/connection.spec.ts b/src/__tests__/connection.spec.ts index 744fb634c..0322dab17 100644 --- a/src/__tests__/connection.spec.ts +++ b/src/__tests__/connection.spec.ts @@ -61,11 +61,21 @@ function runTestMe1 (name: string, filename: string) { expect(child).toBeTruthy() expect(child.onCommandsReceived).toBeTruthy() + const errors: any[] = [] + conn.on('error', e => { + // Ignore any errors that are due to bad ids, as they are 'good' errors + if (!e.indexOf('is not valid')) { + errors.push(e) + } + }) + for (const i in fileData) { const buffer = Buffer.from(fileData[i].trim(), 'hex') await child.onCommandsReceived(buffer, i) } + expect(errors).toEqual([]) + // console.log(conn.state) }) } diff --git a/src/atem.ts b/src/atem.ts index a85065d17..8801fd450 100644 --- a/src/atem.ts +++ b/src/atem.ts @@ -170,7 +170,7 @@ export class BasicAtem extends EventEmitter { } } catch (e) { // TODO - should we error or warn on this? - this.emit('error', `MutateState failed: ${e}`) + this.emit('error', `MutateState failed: ${e}. Command: ${command.constructor.name} ${JSON.stringify(command)}`) } } diff --git a/src/commands/DeviceProfile/index.ts b/src/commands/DeviceProfile/index.ts index 467288264..216a4657e 100644 --- a/src/commands/DeviceProfile/index.ts +++ b/src/commands/DeviceProfile/index.ts @@ -6,3 +6,4 @@ export * from './audioMixerConfigCommand' export * from './macroPoolConfigCommand' export * from './mediaPoolConfigCommand' export * from './mixEffectBlockConfigCommand' +export * from './multiviewerConfigCommand' diff --git a/src/commands/DeviceProfile/multiviewerConfigCommand.ts b/src/commands/DeviceProfile/multiviewerConfigCommand.ts new file mode 100644 index 000000000..002d6d72e --- /dev/null +++ b/src/commands/DeviceProfile/multiviewerConfigCommand.ts @@ -0,0 +1,25 @@ +import { DeserializedCommand } from '../CommandBase' +import { AtemState } from '../../state' +import { MultiviewerInfo } from '../../state/info' + +export class MultiviewerConfigCommand extends DeserializedCommand { + public static readonly rawName = '_MvC' + + constructor (properties: MultiviewerInfo) { + super(properties) + } + + public static deserialize (rawCommand: Buffer): MultiviewerConfigCommand { + return new MultiviewerConfigCommand({ + count: rawCommand.readUInt8(0), + windowCount: rawCommand.readUInt8(1) + // Note: there are a bunch more properties, but their use is not confirmed and has changed over time, + // also we dont care about them for now + }) + } + + public applyToState (state: AtemState) { + state.info.multiviewer = this.properties + return `info.multiviewer` + } +} diff --git a/src/commands/DeviceProfile/topologyCommand.ts b/src/commands/DeviceProfile/topologyCommand.ts index d025c5218..ea597e35e 100644 --- a/src/commands/DeviceProfile/topologyCommand.ts +++ b/src/commands/DeviceProfile/topologyCommand.ts @@ -24,9 +24,6 @@ export class TopologyCommand extends DeserializedCommand { // Note: these are defined below as they can overflow in older firmwares advancedChromaKeyers: false, - - // TODO - define the below properly - multiViewers: 2 } // in 7.4? diff --git a/src/commands/Settings/MultiViewerSourceCommand.ts b/src/commands/Settings/MultiViewerSourceCommand.ts index 34fe64592..f3101bfa1 100644 --- a/src/commands/Settings/MultiViewerSourceCommand.ts +++ b/src/commands/Settings/MultiViewerSourceCommand.ts @@ -44,7 +44,7 @@ export class MultiViewerSourceUpdateCommand extends DeserializedCommand= state.info.capabilities.multiViewers) { + if (!state.info.multiviewer || this.multiViewerId >= state.info.multiviewer.count) { throw new Error(`MultiViewer ${this.multiViewerId} is not valid`) } diff --git a/src/commands/__tests__/index.spec.ts b/src/commands/__tests__/index.spec.ts index 3bc01b1fd..3df0f00bb 100644 --- a/src/commands/__tests__/index.spec.ts +++ b/src/commands/__tests__/index.spec.ts @@ -262,10 +262,6 @@ const commandConverters: CommandTestConverterSet = { 'videoSources': (val: any) => ({ val, name: 'sources' }), 'superSource': (val: any) => ({ val, name: 'superSources' }), 'talkbackOverSDI': () => ({ val: 0 }) // @todo: should be fixed in atem-connection - }, - customMutate: obj => { - obj.multiViewers = 2 - return obj } }, '_MeC': { diff --git a/src/commands/__tests__/v8.0.spec.ts b/src/commands/__tests__/v8.0.spec.ts index 99287927a..4c877be3b 100644 --- a/src/commands/__tests__/v8.0.spec.ts +++ b/src/commands/__tests__/v8.0.spec.ts @@ -32,10 +32,6 @@ const commandConverters: CommandTestConverterSet = { 'serialPort': (val: any) => ({ val, name: 'serialPorts' }), 'videoSources': (val: any) => ({ val, name: 'sources' }), 'superSource': (val: any) => ({ val, name: 'superSources' }) - }, - customMutate: obj => { - obj.multiViewers = 2 - return obj } }, 'SSrc': { diff --git a/src/state/info.ts b/src/state/info.ts index d90870e60..cd1551be2 100644 --- a/src/state/info.ts +++ b/src/state/info.ts @@ -15,7 +15,6 @@ export interface AtemCapabilites { readonly downstreamKeyers: number readonly cameraControl: boolean readonly advancedChromaKeyers: boolean - readonly multiViewers: number } export interface MixEffectInfo { @@ -40,6 +39,11 @@ export interface MediaPoolInfo { readonly clipCount: number } +export interface MultiviewerInfo { + readonly count: number + readonly windowCount: number +} + export class DeviceInfo { public apiVersion: ProtocolVersion = 0 public capabilities?: AtemCapabilites @@ -51,4 +55,5 @@ export class DeviceInfo { public audioMixer?: AudioMixerInfo public macroPool?: MacroPoolInfo public mediaPool?: MediaPoolInfo + public multiviewer?: MultiviewerInfo } From 604880249b6942b632a0ffd528ef52b41d316646 Mon Sep 17 00:00:00 2001 From: Julian Waller Date: Mon, 16 Dec 2019 23:47:35 +0000 Subject: [PATCH 60/68] fix: tests --- package.json | 2 +- src/__tests__/util.ts | 5 ++++- src/commands/DeviceProfile/topologyCommand.ts | 2 +- src/commands/__tests__/index.spec.ts | 1 + src/commands/__tests__/v8.0.spec.ts | 2 +- yarn.lock | 11 ++++++----- 6 files changed, 14 insertions(+), 9 deletions(-) diff --git a/package.json b/package.json index 01e524fc7..e05bc9f39 100644 --- a/package.json +++ b/package.json @@ -114,7 +114,7 @@ "dependencies": { "exit-hook": "^2.0.0", "nanotimer": "^0.3.15", - "threadedclass": "https://github.com/Julusian/threadedClass.git#dist/feat/node12-types", + "threadedclass": "^0.7.0", "tslib": "^1.10.0", "wavefile": "^8.4.4" }, diff --git a/src/__tests__/util.ts b/src/__tests__/util.ts index 0132e88da..2c33e5124 100644 --- a/src/__tests__/util.ts +++ b/src/__tests__/util.ts @@ -45,7 +45,6 @@ export function createEmptyState () { stingers: 1, superSources: 2, // talkbackOverSDI: 0, - multiViewers: 255, downstreamKeyers: 4, cameraControl: true, advancedChromaKeyers: true @@ -64,6 +63,10 @@ export function createEmptyState () { keyCount: 4 } ] + state.info.multiviewer = { + count: 255, + windowCount: 16 + } return state } diff --git a/src/commands/DeviceProfile/topologyCommand.ts b/src/commands/DeviceProfile/topologyCommand.ts index ea597e35e..881fb5079 100644 --- a/src/commands/DeviceProfile/topologyCommand.ts +++ b/src/commands/DeviceProfile/topologyCommand.ts @@ -23,7 +23,7 @@ export class TopologyCommand extends DeserializedCommand { cameraControl: rawCommand.readUInt8(17) === 1, // Note: these are defined below as they can overflow in older firmwares - advancedChromaKeyers: false, + advancedChromaKeyers: false } // in 7.4? diff --git a/src/commands/__tests__/index.spec.ts b/src/commands/__tests__/index.spec.ts index 3df0f00bb..4717d137d 100644 --- a/src/commands/__tests__/index.spec.ts +++ b/src/commands/__tests__/index.spec.ts @@ -844,6 +844,7 @@ describe('Commands v7.2', () => { switch (testCase.name) { // Temporarily ignore the failures case '_top': // New properties not implemented in LibAtem yet + case '_MvC': // Not all properties parsed case 'FTSU': // Unkown props getting overwritten by generator: https://github.com/LibAtem/LibAtem/blob/master/LibAtem/Commands/DataTransfer/DataTransferDownloadRequestCommand.cs continue } diff --git a/src/commands/__tests__/v8.0.spec.ts b/src/commands/__tests__/v8.0.spec.ts index 4c877be3b..8e6a423d1 100644 --- a/src/commands/__tests__/v8.0.spec.ts +++ b/src/commands/__tests__/v8.0.spec.ts @@ -131,7 +131,7 @@ describe('Commands v8.0', () => { switch (testCase.name) { // Not parsed case '_top': // New properties not implemented in LibAtem yet - case '_MvC': // Not parsed + case '_MvC': // Not all properties parsed case 'AMIP': // portType max value continue } diff --git a/yarn.lock b/yarn.lock index 6bc56fdd6..a999a5196 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5165,12 +5165,13 @@ text-extensions@^1.0.0: resolved "https://registry.yarnpkg.com/text-extensions/-/text-extensions-1.9.0.tgz#1853e45fee39c945ce6f6c36b2d659b5aabc2a26" integrity sha512-wiBrwC1EhBelW12Zy26JeOUkQ5mRu+5o8rpsJk5+2t+Y5vE7e842qtZDQ2g1NpX/29HdyFeJ4nSIhI47ENSxlQ== -"threadedclass@https://github.com/Julusian/threadedClass.git#dist/feat/node12-types": - version "0.0.0-develop" - resolved "https://github.com/Julusian/threadedClass.git#9a40b3357db293b8a8429526a4bf7d8d4de8a10f" +threadedclass@^0.7.0: + version "0.7.0" + resolved "https://registry.yarnpkg.com/threadedclass/-/threadedclass-0.7.0.tgz#16d970211f930b5759fae83a4cde78563b0b5104" + integrity sha512-at4Ouv4JSbFz5hX5XnhjkukqOz+J086BHPXT3P6lD64rhYgzbOdWruyj8AgE7xfeh3Wd8nl9yUJiZ4ryoD9IFA== dependencies: callsites "^3.1.0" - tslib "^1.9.3" + tslib "^1.10.0" throat@^4.0.0: version "4.1.0" @@ -5338,7 +5339,7 @@ tslib@1.9.0: resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.9.0.tgz#e37a86fda8cbbaf23a057f473c9f4dc64e5fc2e8" integrity sha512-f/qGG2tUkrISBlQZEjEqoZ3B2+npJjIf04H1wuAv9iA8i04Icp+61KRXxFdha22670NJopsZCIjhC3SnjPRKrQ== -tslib@^1.10.0, tslib@^1.8.0, tslib@^1.8.1, tslib@^1.9.3: +tslib@^1.10.0, tslib@^1.8.0, tslib@^1.8.1: version "1.10.0" resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.10.0.tgz#c3c19f95973fb0a62973fb09d90d961ee43e5c8a" integrity sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ== From 1f8e5fdceaf9085df993570c3895102296537a55 Mon Sep 17 00:00:00 2001 From: Julian Waller Date: Fri, 20 Dec 2019 18:23:16 +0000 Subject: [PATCH 61/68] chore: add atem-mini connection test case --- src/__tests__/connection.spec.ts | 8 +++++--- src/__tests__/connection/1me-v8.1.data | 13 +++++++++++++ src/__tests__/connection/mini-v8.1.data | 6 ++++++ 3 files changed, 24 insertions(+), 3 deletions(-) create mode 100644 src/__tests__/connection/1me-v8.1.data create mode 100644 src/__tests__/connection/mini-v8.1.data diff --git a/src/__tests__/connection.spec.ts b/src/__tests__/connection.spec.ts index 0322dab17..5a611cc24 100644 --- a/src/__tests__/connection.spec.ts +++ b/src/__tests__/connection.spec.ts @@ -86,9 +86,11 @@ describe('connection', () => { * These tests run the payload through the parser to ensure that the commands does not error. */ - runTestMe1('2me v8.1', '2me-v8.1') - runTestMe1('4me4k v7.5.2', '4me4k-v7.5.2') - runTestMe1('constellation v8.0.2', 'constellation-v8.0.2') runTestMe1('ps4k v7.2', 'ps4k-v7.2') + runTestMe1('4me4k v7.5.2', '4me4k-v7.5.2') runTestMe1('tvshd v8.0.0', 'tvshd-v8.0.0') + runTestMe1('constellation v8.0.2', 'constellation-v8.0.2') + runTestMe1('2me v8.1', '2me-v8.1') + runTestMe1('mini v8.1', 'mini-v8.1') + runTestMe1('1me v8.1', '1me-v8.1') }) diff --git a/src/__tests__/connection/1me-v8.1.data b/src/__tests__/connection/1me-v8.1.data new file mode 100644 index 000000000..23f732009 --- /dev/null +++ b/src/__tests__/connection/1me-v8.1.data @@ -0,0 +1,13 @@ +000c00005f7665720002001d003400005f70696e4154454d2031204d2f452050726f64756374696f6e20537769746368657200654d5072700063000002000000002000005f746f70011702030002010401010001000000010001010100000053000c96005f4d654300044353000c72705f6d706c2002436d001400005f4d7643010a01010000000000000000000c72705f414d430b010000007443505f564d4300080000000000000000008000000000000100000000000040000000000002700015000000800000000000034d50720000004000000000000402000000000010000000000005b12c00000000200000000000060000000000004000000000000700cb20000000800000000000000c04015f4d414364000000003020685f44564501010023101112131415161718191a1b1c1d1e1f22000102030405060708090a0b0c0d0e0f202100000c20a0506f777201cb20a0000c0c385669644d06127ca4000cb12c44634f74003eb148000c15b454634c6b00127ca4002c1770496e50720000426c61636b00013d15b400000018000000020029426c6b0001d80100010001cb1301002c0000496e5072000143616d65726120310008000017700012cf78000243616d3101000006000400101301002c0000496e5072000243616d657261203200280000000000020000013d43616d3201000002000200cb1301002c0390496e5072000343616d657261203300182000000f440f0f820f0f43616d3301d00002000200001301002c6a00496e5072000443616d6572612034006401426a0000000001000043616d3401820002000200001301002c21e0496e5072000543616d657261203500880000001e00cb21d4000043616d3501d400010001003d1301002c1770496e5072000643616d657261203600000142453000cb2230001543616d3601700001000100161301002c0000496e5072000743616d657261203700151616161617171717000043616d37010c0001000100001301002c0000496e5072000843616d657261203800b800cb2388014245300a2a43616d38016f0001000100cb1301002c50f0496e507203e8436f6c6f72204261727300cb22e80142453000004261727301e00100010002101301002c000f496e507207d1436f6c6f72203100000000028010000000100000436f6c3101110100010003000301002c0000496e507207d2436f6c6f72203200b3d714141414151515151616436f6c3201170100010003cb0301002c000c496e50720bc24d6564696120506c6179657220310000000000cb4d503100010c0100010004cb1301002ca460496e50720bc34d6564696120506c617965722031204b657900cb4d50314b015c0100010005001301002c2710496e50720bcc4d6564696120506c61796572203200ffffff00004d50320001880100010004cb1301002cd1e8496e50720bcd4d6564696120506c617965722032204b657900cb4d50324b01980100010005001301002c0000496e5072271a50726f6772616d00eb870a2a0d620a2a0d6f012450676d0001500100010080620300002c2488496e5072271b5072657669657700ce7c00cb247c00cb248800cb5076770001a00100010080cb0300002c09c4496e50721b59436c65616e20466565642031000c00cb23f000004366643101200100010080cb0300002c0001496e50721b5a436c65616e20466565642032006c002c6c7c00cb4366643201f00100010080630300002c5553496e50721f41417578696c696172792031000a0000b6eb870a2a41757831016f0100010081000200002c24b8496e50721f42417578696c6961727920320024d0012309c4000041757832010001000100810d0200002c2510496e50721f43417578696c69617279203300151500298844002c4175783301200100010081000200000c6c7c4d76564d00072500 +000c00004d76564d0106001d000c00004d76564d0207454d000c204d4d76564d03066475000c696f4d76564d04046368000c00654d76564d05050000000c00004d76564d06066f70000c02034d76564d07070001000c00014d76507200050053001096004d76496e0000271b000072700010706c4d76496e0001271a00007643001001014d76496e000200010000727000104d434d76496e0003000100004d43001000004d76496e0004000100000000001000004d76496e0005271b00000270001000004d76496e0006000100007200001040004d76496e0007000100000010001000004d76496e0008000100000000001006004d76496e0009000100000007000c20005072674900000003001004015072764900000bcd0030206800105645547253530000010001151617000c1a1b547250720000010200100506547250730000140e00002100000c20a0544d7850001420a0000c0c3854447050001e07d1001cb12c54577050001e0c4800000bcd271027101388138800001770001c507254447650001e1e1b0bcd0bcd00000000000000000029426c001c01d8545374500002000100000000006e005a000a000400067261000c00084b654f6e00000078001c43614b6542500000000101000001000100002328dcd8c1803e80001472614b654c6d0000000000000000003d4361001401004b65436b000000000000000000000072001843614b65507400001118000000000000021213880061004401d04b654456000013010000000000000000000000000000000000000000000003000032003264646464643400000000000000004e0100000000000000001e054361001072614b6546530000010100cb00d4003c43614b4b4650000001010000000000000000fe0c0000fe0c0000fffb0000ee90ee90ffffffff00cb05b805b805b8081fff700000000000000000003c00004b4b4650000002610000000000000000fe0c0000fe0c0000fffb0000ee90ee90ffffffff000005b805b805b8081fff720000000000000000000c00b84b654f6e00010030001c43614b6542500001000101000001000100f02328dcd8c1803e80001472204b654c6d000100e80000000000004261001401e04b65436b0001000000000000000000720018436f4b6550740001110000000000000013881388006f004401114b654456000103010000000000000000000000000000000000000000000003140032003264646464643200000000000000004e0100000000000000001ec24d65001061204b6546530001010100000000003c4d504b4b4650000101000000000000000000fe0c0000fe0c0000fffb0000ee90ee90ffffffff004b05b805b805b8081fff5c0000000000000000003c27104b4b4650000102650000000000000000fe0c0000fe0c0000fffb0000ee90ee90ffffffff00cb05b805b805b8081fff720000000000000000000c61794b654f6e00020079001c4d504b6542500002000101000001000100002328dcd8c1803e80001472614b654c6d000200620000000000245067001401504b65436b000200000000000000000072001850724b6550740002117c000000000000138813880076004401a04b6544560002030000000000000000000000000000000000000000000000030c0032003264646464643100000000000000004e0100000000000000001e5a436c00106e204b65465300020101002c007c003c43664b4b4650000201000000000000000000fe0c0000fe0c0000fffb0000ee90ee90ffffffff25b605b805b805b8081fff6f03e807d00bb80fa0003c24b84b4b4650000202750000000000000000fe0c0000fe0c0000fffb0000ee90ee90ffffffff340d05b805b805b8081fff7203e807d00bb80fa0000c79204b654f6e00030044001c41754b65425000030001010000010001007c2328dcd8c1803e80 +001400004b654c6d0003001d000000000076564d0014454d4b65436b00030000000000000000006f0018564d4b655074000311650000000000001388138800000044564d4b654456000302030000000000000000000000000000000000000000000003000032003264646464640000000000000000004e0100000000000000001e1001010010496e4b6546530003010100100043003c496e4b4b4650000301430000000000000000fe0c0000fe0c0000fffb0000ee90ee90ffffffff000005b805b805b8081fff6e0000000000002f3f003c40004b4b4650000302010000000000000000fe0c0000fe0c0000fffb0000ee90ee90ffffffff000905b805b805b8081fff0000000000000000000010040144736b4200000bc20bc32068001c564544736b5000001e000000039600012328dcd8c1803e8001020010050644736b5300000000011e2100001020a044736b4201140bc20bc30c38001c705044736b5001006e000000000000012328dcd8c180cf3d27100010138844736b5301000000016e7650000c1e1b4674625000e40000000c000046746253000000e400107450436f6c5600000000006c000000100004436f6c56010c000000000000000c0078417578530065271b000c0001417578530101271b000cdcd8417578530214271b00144c6d4d505370005a005a0000000000000100004c436b4d5043530000000000000072001843614b65507400001118000000000000021213880061004401d04b65445600001301000000000000000000000000000000000000000000000000005c00324d50415301000000000000000000000000000000000000001e054361001072614b6546530000010100cb00d4003c43614b4b4650000001010000000000000000fe0c0000fe0c0000fffb0000ee90ee90ffffffff00cb05b8004c05b84d5043530100000000000000003c00004b4b4650000002610000000000000000fe0c0000fe0c0000fffb0000ee90ee90ffffffff000005b805b805b8081fff720000000000000000005c00b84d5041530200000000000000000000000000000000000001000100f02328dcd8c1803e80001472204b654c6d000100e80000000000004261001401e04b65436b0001000000000000000000720018436f4b65507400011100002000004d506665008800000000000000000000000000000000000000000000002000004d50666500000001000000000000000000000000000000000000000000204e014d50666500000002000000000000000000000000000000000000000000204d504d506665000100030000000000000000000000000000000000fb00000020ee904d506665004b000400000000000000000000000000000000003c0000002046504d5066650000000500000000000000000000000000000000009000000020ffff4d50666500b800060000000000000000000000000000000000650000002000794d506665006500070000000000000000000000000000000000800000002072614d506665000200080000000000000000000000000000000000020000002000004d506665001800090000000000000000000000000000000000880000002001a04d5066650002000a00000000000000000000000000000000000000000020030c4d5066650064000b00000000000000000000000000000000000000000020436c4d5066650065000c0000000000000000000000000000000000020000002000004d506665000c000d0000000000000000000000000000000000b60000002005b84d50666500e8000e0000000000000000000000000000000000000000002000004d506665000c000f0000000000000000000000000000000000b800000020ff724d50666500b800100000000000000000000000000000000000650000 +002000004d506665000300110000000000000000000000000000000000030000002000004d5066650018001200000000000000000000000000000000008800000020564d4d506665000300130000000000000000000000000000000000000000002003004d506665006400140000000000000000000000000000000000000000002001014d506665006500150000000000000000000000000000000000030000002000004d506665000c00160000000000000000000000000000000000000000002005b84d506665000000170000000000000000000000000000000000000000002000004d506665000c00180000000000000000000000000000000000b800000020ff004d5066650000001900000000000000000000000000000000001c000000206b504d5066650000001a0000000000000000000000000000000000730000002000004d5066650010001b000000000000000000000000000000000073000000206e004d5066650001001c0000000000000000000000000000000000000000002076504d5066650074001d000000000000000000000000000000000010000000206c564d506665006c001e00000000000000000000000000000000000c0000002078534d506665000c001f0000000000000000000000000000000000140000 +058000004d50664d0100000005700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002501 +004000004d50664d0100005700300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +058000004d50664d0200000005700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002501 +004000004d50664d0200005700300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c00004d50434500021f0000100000524350530000000100000000000c00004d50434501021f0000100000524350530100000100000000001c000052584d530000000000000000000000000000000000020000001c000052584350000001000000000000000000000000000000000000280000525853530000000000000000ffffffff0000000000000000000000000000000000000000000c00005258434300000000001c000052584d530001000000000000000000000000000000020000001c000052584350000101000000000000000000000000000000000000280000525853530001000000000000ffffffff0000000000000000000000000000000000000000000c00005258434300010000001c000052584d530002000000000000000000000000000000020000001c000052584350000201000000000000000000000000000000000000280000525853530002000000000000ffffffff0000000000000000000000000000000000000000000c00005258434300020000001c000052584d530003000000000000000000000000000000020000001c000052584350000301000000000000000000000000000000000000280000525853530003000000000000ffffffff0000000000000000000000000000000000000000000c00005258434300030000000c0000414d50500100000000180000414d49500001000000010004020000002710000000180000414d49500002000000020002020000002710000000180000414d49500003000000030002020000002710000000180000414d49500004000000040002020094fc2710000000180000414d49500005000000050001020000002710000000180000414d49500006000000060001020000002710000000180000414d49500007000000070001020000002710000000180000414d49500008000000080001020000002710000000180000414d495007d1010000000100020080000000000000180000414d495007d2010000010100000000002710000000180000414d495003e9020000000020000000002710000000100000414d4d4f800000000000000000140000414d6d4f0000000000000001000007d0002c0000414d546c000b00010000020000030100040000050000060000070000080007d10007d20003e90000000c00004c4b535400000000000c00004c4b535400010000000c00004c4b535400020000001000005f546c43000100000800000000140000546c496e00080000010000000000000000500000546c5372001700000000010000020000030100040000050000060000070000080003e80007d10007d2000bc2000bc3000bcc000bcd02271a00271b001b59001b5a001f41001f42001f43000000240000546c466300080001000002000003000004000005000006000007000008000000000c00004d5250720000ffff000c00004d52635300000000002400004d50727000000100001400007265636f72642d417564696f4d69786572526573001800004d507270000101000005000064756d6d79000000001c00004d50727000020100000900026c69622d64756d6d79643200002000004d50727000030100000d0000736964652d6f75742d77697065000000002000004d50727000040100000e000067726170682077697065206f75740000001000004d5072700005000000000000001c00004d50727000060100000c000067726170682d696e2d6e6577002000004d507270000701000010000067726170682d696e2d696e632d666c79001800004d507270000801000005000064756d6d79000000002400004d507270000901000011000067726170682d6f75742d696e632d666c79002501 +001000004d507270000a000000000000001000004d507270000b000000000000001800004d507270000c010000080000776970652d637574001000004d507270000d00000000000000101f004d507270000e000000000000001000004d507270000f000000000000001000004d5072700010000000000000001000004d5072700011000000000000001000004d5072700012000000000000001043504d5072700013000000000000001000004d5072700014000000000000001000004d5072700015000000000000001000004d5072700016000000000000001000004d507270001700000000000000104d534d5072700018000000000000001000004d5072700019000000000000001001004d507270001a000000000000001000004d507270001b000000000000001000004d507270001c000000000000001000004d507270001d000000000000002043434d507270001e0100001000007472616e732d6476652d656666656374001000004d507270001f000000000000001000004d5072700020000000000000001000004d50727000210000000000000010ffff4d5072700022000000000000001000004d5072700023000000000000001000004d5072700024000000000000001000004d5072700025000000000000001000004d5072700026000000000000001000004d5072700027000000000000001053534d5072700028000000000000001000004d5072700029000000000000001000004d507270002a000000000000001000004d507270002b000000000000001049504d507270002c000000000000001000004d507270002d000000000000001000024d507270002e000000000000001049504d507270002f000000000000001000004d5072700030000000000000001000024d5072700031000000000000001049504d5072700032000000000000001000004d5072700033000000000000001000014d5072700034000000000000001049504d5072700035000000000000001000004d5072700036000000000000001000014d5072700037000000000000001049504d5072700038000000000000001000004d5072700039000000000000001001004d507270003a000000000000001049504d507270003b000000000000001000004d507270003c000000000000001000004d507270003d000000000000001000014d507270003e000000000000001000014d507270003f000000000000001006004d5072700040000000000000001000004d5072700041000000000000001000004d5072700042000000000000001053544d5072700043000000000000001000004d5072700044000000000000001000004d5072700045000000000000001053724d5072700046000000000000001000044d50727000470000000000000010e8004d50727000480000000000000010000b4d507270004900000000000000101f414d507270004a000000000000001046634d507270004b000000000000001000054d507270004c000000000000001000004d507270004d000000000000001063534d507270004e000000000000001001004d507270004f0000000000000010696f4d5072700050000000000000001072704d5072700051000000000000001000004d5072700052000000000000001000024d5072700053000000000000001000004d5072700054000000000000001064654d5072700055000000000000001000004d5072700056000000000000001061704d5072700057000000000000001000004d5072700058000000000000001000004d5072700059000000000000001061704d507270005a000000000000001072704d507270005b0000000000000010696e4d507270005c000000000000001072704d507270005d000000000000001000004d507270005e000000000000001000004d507270005f000000000000 +001000004d5072700060000000000000001000004d5072700061000000000000001000004d5072700062000000000000001070654d5072700063000000000000000c000043437374000013880020727043436450010000800000000100000000000f000000000000001000000020727043436450010002800000000100000000001100002a00000000100000002072704343645001010d010001000000000000001300000000000000100000002072704343645001010101000100000000000000150000020000000010000000207270434364500101020200000001000000000017000015e0000000104d5300207270434364500101050300000000000100000019000000004e20001001000020727043436450010108010001000000000000001b000001000000001000000020727043436450010404010001000000000000001d000000000000002043430020727043436450010800800000000400000000002d65660000000000000000002072704343645001080180000000040000000000200000000000000000000000207270434364500108028000000004000000000022000008000800080008000020727043436450010803800000000400000000002400000000000000000000002072704343645001080480000000020000000000260000040008000010000000207270434364500108058000000001000000000028000008000000001000000020727043436450010806800000000200000000002a000000000800001000000020727043436450010b00800000000200000000002c000000000000001000000020727043436450020000800000000100000000002e000000000000001049500020727043436450020002800000000100000000003000002a00000000100002002072704343645002010d010001000000000000003200000000000000100000002072704343645002010101000100000000000000340000020000000010495000207270434364500201020200000001000000000036000015e000000010000100207270434364500201050300000000000100000038000000004e20001000000020727043436450020108010001000000000000003a000001000000001049500020727043436450020404010001000000000000003c000000000000001000000020727043436450020800800000000400000000003e000000000000000000000020727043436450020801800000000400000000004000000000000000000000002072704343645002080280000000040000000000420000080008000800080000207270434364500208038000000004000000000044000000000000000000000020727043436450020804800000000200000000004600000400080000100004002072704343645002080580000000010000000000480000080000000010000b0020727043436450020806800000000200000000004a000000000800001046630020727043436450020b00800000000200000000004c000000000000001000000020727043436450030000800000000100000000004e000000000000001001000020727043436450030002800000000100000000005000002a00000000107270002072704343645003010d010001000000000000005200000000000000100002002072704343645003010101000100000000000000540000020000000010646500207270434364500301020200000001000000000056000015e000000010617000207270434364500301050300000000000100000058000000004e20001000000020727043436450030108010001000000000000005a000001000000001072700020727043436450030404010001000000000000005c000000000000001072700020727043436450030800800000000400000000005e00000000000000000000 +0020000043436450030801800000000400000000005072700000000000000000002000004343645003080280000000040000000000507270080008000800080000200000434364500308038000000004000000000000008000000000000000000020000043436450030804800000000200000000000002800400080000000000002000004343645003080580000000010000000000010d01080000000000000000200000434364500308068000000002000000000001010100000800000000000020000043436450030b0080000000020000000000010202000000000000000000200000434364500400008000000001000000000001050300000000000100000020000043436450040002800000000100000000000108012a00000000000000002000004343645004010d010001000000000000000404010001000000000000002000004343645004010101000100000000000000080080020000040000000000206566434364500401020200000001000000000008018015e000040000000000200000434364500401050300000000000100000008028000004e200000000000200000434364500401080100010000000000000008038001000004000000000020000043436450040404010001000000000000000804800000000200000000002000004343645004080080000000040000000000080580000000000000000000200000434364500408018000000004000000000008068000000000000000000020000043436450040802800000000400000000000b0080080008000800080000200000434364500408038000000004000000000000008000000000000000000020000043436450040804800000000200000000000002800400080000000000002000004343645004080580000000010000000000010d01080000000000000000200000434364500408068000000002000000000001010100000800000000000020000043436450040b0080000000020000000000010202000000000000000000200000434364500500008000000001000000000001050300000000000100000020000043436450050002800000000100000000000108012a00000000000000002000004343645005010d010001000000000000000404010001000000000000002000004343645005010101000100000000000000080080020000040000000000200000434364500501020200000001000000000008018015e000040000000000200000434364500501050300000000000100000008028000004e200000000000200000434364500501080100010000000000000008038001000004000000000020000043436450050404010001000000000000000804800000000200000000002000004343645005080080000000040000000000080580000000000000000000200000434364500508018000000004000000000008068000000000000000000020000043436450050802800000000400000000000b0080080008000800080000200000434364500508038000000004000000000000008000000000000000000020000043436450050804800000000200000000000002800400080000000000002000004343645005080580000000010000000000010d01080000000000000000200000434364500508068000000002000000000001010100000800000000000020000043436450050b0080000000020000000000010202000000000000000000200000434364500600008000000001000000000001050300000000000100000020000043436450060002800000000100000000000108012a00000000000000002000004343645006010d010001000000000000000404010001000000000000002000004343645006010101000100000000000000080080020000040000000000200000434364500601020200000001000000000000000015e0666c79002501 +00200000434364500601050300000000000100000050727000004e2000000000002000004343645006010801000100000000000000507270010008000800080000200000434364500604040100010000000000000000008000000000000000000020000043436450060800800000000400000000000002800000000000000000002000004343645006080180000000040000000000010d010000000000000000002000004343645006080280000000040000000000010101080008000800080000200000434364500608038000000004000000000001020200000000000000000020000043436450060804800000000200000000000105030400080000010000002000004343645006080580000000010000000000010801080000000000000000200000434364500608068000000002000000000004040100000800000000000020000043436450060b0080000000020000000000080080000000000000000000206566434364500700008000000001000000000008018000000004000000000020000043436450070002800000000100000000000802802a004e2000000000002000004343645007010d010001000000000000000803800000000400000000002000004343645007010101000100000000000000080480020000020000000000200000434364500701020200000001000000000008058015e000000000000000200000434364500701050300000000000100000008068000004e20000000000020000043436450070108010001000000000000000b0080010008000800080000200000434364500704040100010000000000000000008000000000000000000020000043436450070800800000000400000000000002800000000000000000002000004343645007080180000000040000000000010d010000000000000000002000004343645007080280000000040000000000010101080008000800080000200000434364500708038000000004000000000001020200000000000000000020000043436450070804800000000200000000000105030400080000010000002000004343645007080580000000010000000000010801080000000000000000200000434364500708068000000002000000000004040100000800000000000020000043436450070b0080000000020000000000080080000000000000000000200000434364500800008000000001000000000008018000000004000000000020000043436450080002800000000100000000000802802a004e2000000000002000004343645008010d010001000000000000000803800000000400000000002000004343645008010101000100000000000000080480020000020000000000200000434364500801020200000001000000000008058015e000000000000000200000434364500801050300000000000100000008068000004e20000000000020000043436450080108010001000000000000000b0080010008000800080000200000434364500804040100010000000000000000008000000000000000000020000043436450080800800000000400000000000002800000000000000000002000004343645008080180000000040000000000010d010000000000000000002000004343645008080280000000040000000000010101080008000800080000200000434364500808038000000004000000000001020200000000000000000020000043436450080804800000000200000000000105030400080000010000002000004343645008080580000000010000000000010801080000000000000000200000434364500808068000000002000000000004040100000800000000000020000043436450080b00800000000200000000000800800000000000000000000c00005350744d00010202000c000153505a5300009600 +000c0000505a435300010503000c0000496e436d01507270 \ No newline at end of file diff --git a/src/__tests__/connection/mini-v8.1.data b/src/__tests__/connection/mini-v8.1.data new file mode 100644 index 000000000..abddf0371 --- /dev/null +++ b/src/__tests__/connection/mini-v8.1.data @@ -0,0 +1,6 @@ +000cffff5f7665720002001d003400005f70696e4154454d204d696e69000000001000474d5072700016000000000000001049504d507270001700000d0000000020ffff5f746f70010e01010001000401000000000001000000000000010000000c49505f4d654300010000000c00005f6d706c14007270000c00005f46414306002d01003c72705f464543000400000110ffff0000001e0000018b0200000000000064000005c8041e0000000001c200001ee60850727000000578000054c4007442505f564d430008000008000000000000000000000000090000000000000000000000000a7000220000000000000000000b4d50720000000000000000001a102d010000000000000000000c0000000000000000000000000d0000000000000000000000001b002600000000000000000000000c72705f4d4143640000000020ffff5f44564500000011101112131415161718191a1b1c1d1e1f22000000000c031e506f7772012a0000000c00005669644d1b507270000c00004169564d00000100000c727054634c6b00000000002c0000496e50720000426c61636b00001024544d507270002e00000000424c4b00010201000100012f1001002c0000496e5072000143616d65726120310000001000064d507270003143414d3101000002000200501101002c0000496e5072000243616d6572612032000000000000001000004d5043414d3201000002000200101101002c7270496e5072000343616d657261203300700036000000000000001043414d3301700002000200001101002cfb50496e5072000443616d6572612034000a4d50727000390000000043414d3401ff00020002003a1101002c0000496e507203e8436f6c6f7220426172730010ffff4d507270003c4241525301000100010002501001002c0000496e507207d1436f6c6f722031000000000000000010000d4d50434f4c3101000100010003100001002c7270496e507207d2436f6c6f72203200727000410000000000000010434f4c3201700100010003000001002c2d01496e50720bc24d6564696120506c6179657220310044000000004d50310001ff0100010004451001002c0000496e50720bc34d6564696120506c617965722031204b657900474d50314b01000100010005501001002c0000496e5072271a50726f6772616d00000000000000001033024d5050474d0001000100010080100100002c7270496e5072271b50726576696577007270004c00000000000000105056570001700100010080000100002cfb50496e50722af943616d65726120312044697265637400000000004449520001430002000200500100002c0000496e50721f414f757470757400000000001053724d50727000520000000001000100010081500000000c000050726749001000010010727050727649000000010010425000107270547253530000010001100000000c727054725072000000000010ffff5472507300001e0000000000000cffff544d7850001e0000000c000054447050001e07d1001c000054577050001e0600000007d11388206c1388138800004343001c727054447650001e1e1c0bc20bc3010101f402bc000000000000001c0031545374500001010001f402bc001000020049002200050000000c00004b654f6e00000070001c00004b65425000000101010000040bc300002328dcd8c1803e80001472704b654c6d0000010001f402bc00507270002000004b41436b00000000000001f4000000000000000003e8000000000000001800004b41434300000000c3e920bf02711a5c065503f7001853534b6550740000060013881388206c138813880070004400004b65445600003264000000c8000000c8000030d400001b580000000001000000000000140000000064500000000000000168190000000000000000001e130000 +0010ffff4b6546530000000000340000003c696e4b4b46500000016e000003e8000003e800000000000000000000000000000000000000000017000000000000016819ff0000000000000000003c00044b4b465000000200000003e8000003e8000000000000000000000000000000000000000000000000000000000168194300000000000000000010454344736b4200100bc20bc3001e001c018b44736b5000001e0101f402bc00002328dcd8c1803e801ee60010727044736b5300000000011e4250000c4d4346746250001e0000000c0000467462530000001e00100000436f6c5600000000000003e800100000436f6c560150010e03e801f4000c0000417578530000271a002000004d506665000000000000000000000000000000000000000000000000002000004d506665000000010000000000000000000000000000000000440000002000114d5066650015000200000000000000000000000000000000006f0000002000004d5066650069000300000000000000000000000000000000000c000000204c6b4d506665002c00040000000000000000000000000000000000500000002000004d506665000000050000000000000000000000000000000000010000002072614d506665001000060000000000000000000000000000000000500000002000004d506665000200070000000000000000000000000000000000500000002001004d506665001000080000000000000000000000000000000000330000002000004d5066650010000900000000000000000000000000000000006e0000002043614d5066650034000a0000000000000000000000000000000000020000002011014d506665006e000b0000000000000000000000000000000000500000002042414d5066650000000c00000000000000000000000000000000006f0000002000004d5066650010000d00000000000000000000000000000000002c0000002050724d506665006f000e0000000000000000000000000000000000320000002001004d506665002c000f0000000000000000000000000000000000720000002000004d506665000000100000000000000000000000000000000000c30000002061204d506665007200110000000000000000000000000000000000500000002000004d506665001a00120000000000000000000000000000000000500000002001004d506665001000130000000000000000000000000000000000000000000c00004d50434500010000000c01704361704101000100001cfb5052584d530000436100000000000000440000006300020000001c4449525843500000010000500000000000000000000000004f7500287574525853530000537200000000ffffffff0000000000000100000000000000000000006749000c00015258434300000049001c000152584d530001727000000000000000000000000000020070001c507252584350000101000072000000000000000000000000ffff00287850525853530001000000000000ffffffff000000000057705000000000000000000000206c000c13885258434300010070001c765052584d5300020bc300000000000000000000000000020031001c745052584350000201000010000000000000000000000000000000284f6e525853530002000000000000ffffffff0000000000c30000000000000000000000007270000c4c6d52584343000200bc001c727052584d530003436b00000000000000f40000000000020000001c0000525843500003010000410000000000000000000000001a5c002803f7525853530003507400000000ffffffff0000000000880070000000000000000000003264000c00c852584343000300d4000c1b58464d505000000000001800144641495000010000000100020000020602000000 +003cffff464153500001000000340000ffffffffffff01000100006e0000000000000000060100000000000000000000000000000000000007010000002c0000414542500001000000000000ffffffffffff010000003310010103e80000002e0000000000470000002c0000414542500001000000000000ffffffffffff010001012d010f010000000000310000000000500bc2002c001e4145425000016b5000001e01ffffffffffff010002012d040f021ee6000000ab0000000000e60000002c42504145425000016250001e0000ffffffffffff010003012d040f0400000000031e0000000000e603e8002c0000414542500001010e03e801f4ffffffffffff010004012d200f08000000001c5c0000000000500000002c0000414542500001000000000000ffffffffffff0100050033020808000000003264000000000047000000300000414958500001666500150002ffffffffffff010000000000ffffee6c0708006e0000008c000000000000245400300000414943500001000000000000ffffffffffff010000506665fffff25400c800000000008c0000000000002454002c000041494c500001666500000005ffffffffffff010000000000fffffb50000000470000000000002454001800064641495000020000000200020000020602500000003c0000464153500002000700000000ffffffffffff0100010000000000000000200000060166650000000000000000000000000000000007010000002c0000414542500002666500100009ffffffffffff010000003310010100000000002e0000000000476665002c000a414542500002000000000000ffffffffffff010001012d010f016665000000310000000000500000002c0000414542500002000000204241ffffffffffff010002012d040f020000000000ab0000000000e60000002c0000414542500002000d00000000ffffffffffff010003012d040f0400000000031e0000000000e6000e002c0000414542500002000000000000ffffffffffff010004012d200f08000f00001c5c0000000000500000002c000041454250000200004d506665ffffffffffff0100050033020808000000003264000000000047612000306665414958500002000000000000ffffffffffff010000000000ffffee6c0708006e0000008c000000000000245400300000414943500002000000200100ffffffffffff010000000000fffff25400c800000000008c0000000000002454002c434541494c500002017043617041ffffffffffff010000584d53fffffb50000000470000000000002454001800004641495000030050000300020000020602000000003c0000464153500003757452585353ffffffffffff0100010000ff0000000000000000060100000000000000000000000000010000000007010049002c0001414542500003727000000000ffffffffffff010000003310010150720000002e0000000000470000002c0000414542500003ffff00287850ffffffffffff010001012d010f01ffff000000310000000000500000002c0000414542500003138852584343ffffffffffff010002012d040f020bc3000000ab0000000000e60000002c0031414542500003435000020100ffffffffffff010003012d040f0400000000031e0000000000e60000002c0000414542500003000000c30000ffffffffffff010004012d200f084c6d00001c5c0000000000507270002c4d534145425000030000000000f4ffffffffffff010005003302080843500000326400000000004700000030000041495850000303f752585353ffffffffffff01000000ffffffffee6c0708006e0000008c0000000000002454003000c841494350000300d4000c1b58ffffffffffff010000180014fffff25400c800000000008c0000000000002454 +002cffff41494c500003000000340000ffffffffffff01000000006efffffb50000000470000000000002454001800004641495000040000000400020000020604454250003c0000464153500004ffffffff0100ffffffffffffff000000002e0000000000470000060100000000000000000000000000000000000007010100002c2d01414542500004003100000000ffffffffffffff000000331001016b500000002e0000000000470100002c2d0441454250000400ab00000000ffffffffffffff0001012d010f016250000000310000000000500100002c2d04414542500004031e00000000ffffffffffffff0002012d040f02010e000000ab0000000000e60100002c2d204145425000041c5c00000000ffffffffffffff0003012d040f0400000000031e0000000000e60100002c3302414542500004326400000000ffffffffffffff0004012d200f08666500001c5c0000000000500100002c0000414542500004006e0000008cffffffffffffff00050033020808435000003264000000000047ffff00300100414958500004f25400c80000ffffffffffffff0000002454ffffee6c0708006e0000008c000000000000245400300100414943500004fb5000000047ffffffffffffff0000180006fffff25400c800000000008c0000000000002454002c000041494c500004000700000000ffffffffffffff0000000000fffffb50000000470000000000002454003c0000464153500004000007010000ffffffffffffff01000000650000000000ff00000601010000000000000000000000002e0000000007016665002c000a414542500004000000000000ffffffffffffff0100003310010166650000002e0000000000470000002c0000414542500004000000204241ffffffffffffff0101012d010f010000000000310000000000500000002c0000414542500004000d00000000ffffffffffffff0102012d040f020000000000ab0000000000e6000e002c0000414542500004000000000000ffffffffffffff0103012d040f04000f0000031e0000000000e60000002c000041454250000400004d506665ffffffffffffff0104012d200f08000000001c5c0000000000506120002c6665414542500004000000000000ffffffffffffff01050033020808ee6c00003264000000000047000000302454414958500004435000020000ffffffffffffff0100000100ffffee6c0708006e0000008c0000000000002454003024544149435000044c5000020170ffffffffffffff0100ff0100fffff25400c8fb500000008c0000000000002454002c000041494c500004005000030002ffffffffffffff01003c0000fffffb50000000470000000000002454001801004641495005150200000002000000020602000000000c00004641414905150301003c0049464153500515425000037270ffffffffffff01000100000000000000000100000601002e000000000000000000000000000000000301ffff002c7850414542500515010001012d01ffffffffffff010000003310010100000000002e0000000000471388002c4343414542500515010002012d04ffffffffffff010001012d010f010000000000310000000000504350002c0100414542500515010003012d04ffffffffffff010002012d040f020000000000ab0000000000e60000002c0000414542500515010004012d20ffffffffffff010003012d040f0472700000031e0000000000e60000002c00f4414542500515010005003302ffffffffffff010004012d200f08000000001c5c00000000005003f7002c535341454250051501000000ffffffffffffffff01000500330208080000000032640000000000474350003000d4414958500515ffffffff0100ffffffffffff010000000000ffffee6c0708006e0000008c0000000000002454 +0030ffff414943500515000000340000ffffffffffff01000000006efffff25400c800470000008c0000000000002454002c495041494c500515000200000206ffffffffffff010000415350fffffb500000004700000000000024540018002e4641495005160200000102000000020602000000000c00004641414905160302003c2d01464153500516003100000000ffffffffffff0100010000100000000000000000060100000000000000000000000042500000000003010000002cffff4145425005162d010f016250ffffffffffff01000000331001012d040000002e0000000000470000002cffff4145425005162d040f02010effffffffffff010001012d010f012d20000000310000000000500000002cffff4145425005162d040f040000ffffffffffff010002012d040f023302000000ab0000000000e60000002cffff4145425005162d200f086665ffffffffffff010003012d040f0400000000031e0000000000e6008c002cffff414542500516330208084350ffffffffffff010004012d200f08010000001c5c0000000000500000002cffff4145425005162454ffffee6cffffffffffff0100050033020808245400003264000000000047fb5000300047414958500516ff0000180006ffffffffffff01000000008cffffee6c0708006e0000008c000000000000245400300000414943500516ff0000000000ffffffffffff010000000000fffff25400c800000000008c0000000000002454002cffff41494c500516006500000000ffffffffffff010000000000fffffb500000004700000000000024540060000a464d546c0007000000000000ffffffffffff0100000100ffffffffffff0100000200ffffffffffff0100000300ffffffffffffff00000400ffffffffffffff01000400ffffffffffff0100051500ffffffffffff0100051600454250001c000d46414d500601ffff000000000000000000000000000000ab001c0000414d425000003310010142500000002e000000000047ffff001cff01414d425001012d010f01031e000000310000000000500000001c4250414d425002012d040f02ffff000000ab0000000000e60000001c1c5c414d425003012d040f0466650000031e0000000000e60000001cffff414d425004012d200f08ee6c00001c5c0000000000500000001c2454414d425005003302080800000000326400000000004701000020ee6c4d4f43500000008cfffff25400c824540000008c0000000000002454001c0170414d4c5000ffff01fffffb50000000470000000000002454000c00004c4b53540000000000104c505f546c430001000004ffffff0010ff01546c496e000403000000004700340000546c5372000e00000000010300020000030000040003e80007d10007d2000bc2000bc300271a00271b002af9001f410000184250546c466300040001000002000003000004000000000c00004d5250720000ffff000c00004d526353000000000010ffff4d507270000000000000000000102d014d5072700001000000000000001000004d5072700002000000000000001043434d50727000030000000000000010ffff4d5072700004000000000000001000314d5072700005000000000000001042504d5072700006000000000000001001004d5072700007000000000000001000004d5072700008000000000000001001004d507270000900000000000000102d044d507270000a000000000000001000004d507270000b000000000000001033024d507270000c000000000000001000004d507270000d000000000000001053534d507270000e0000000000000010ffff4d507270000f000000000000001032644d5072700010000000000000001058504d5072700011000000000000001001004d50727000120000000000000010008c4d5072700013000000000000 +0010ffff4d50727000140000000000000010ffff4d5072700015000000000000001000474d5072700016000000000000001049504d50727000170000000000000010ffff4d5072700018000000000000001000474d5072700019000000000000001049504d507270001a000000000000001000004d507270001b00000000000000102d014d507270001c0000000000000010ffff4d507270001d000000000000001000004d507270001e000000000000001042504d507270001f000000000000001042504d5072700020000000000000001001004d5072700021000000000000001000004d507270002200000000000000102d044d507270002300000000000000102d014d5072700024000000000000001000004d5072700025000000000000001000004d5072700026000000000000001033024d50727000270000000000000010ffff4d50727000280000000000000010ffff4d50727000290000000000000010031e4d507270002a000000000000001042504d507270002b000000000000001001004d507270002c000000000000001000004d507270002d000000000000001024544d507270002e000000000000001033024d507270002f0000000000000010fb504d5072700030000000000000001000064d50727000310000000000000010ee6c4d5072700032000000000000001024544d5072700033000000000000001000004d50727000340000000000000010f2544d5072700035000000000000001024544d5072700036000000000000001000004d50727000370000000000000010fb504d50727000380000000000000010000a4d50727000390000000000000010ffff4d507270003a000000000000001000004d507270003b0000000000000010ffff4d507270003c0000000000000010ff014d507270003d0000000000000010ffff4d507270003e0000000000000010000d4d507270003f000000000000001000004d5072700040000000000000001042504d5072700041000000000000001000004d507270004200000000000000102d014d5072700043000000000000001000004d50727000440000000000000010ffff4d507270004500000000000000101c5c4d50727000460000000000000010031e4d5072700047000000000000001042504d5072700048000000000000001000004d5072700049000000000000001033024d507270004a000000000000001001004d507270004b0000000000000010f2544d507270004c000000000000001024544d507270004d0000000000000010fb504d507270004e000000000000001000004d507270004f00000000000000106c434d50727000500000000000000010496e4d5072700051000000000000001053724d5072700052000000000000001000044d50727000530000000000000010c3004d5072700054000000000000001042504d5072700055000000000000001000004d50727000560000000000000010ffff4d50727000570000000000000010ffff4d507270005800000000000000102d014d5072700059000000000000001000004d507270005a000000000000001043434d507270005b0000000000000010ffff4d507270005c000000000000001000314d507270005d000000000000001042504d507270005e000000000000001001004d507270005f000000000000001000004d5072700060000000000000001001004d507270006100000000000000102d044d5072700062000000000000001000004d5072700063000000000000000c3302496e436d010c0000 \ No newline at end of file From 6be10243d7fbb7fe19dce6c821c2e1a8f4ceb66f Mon Sep 17 00:00:00 2001 From: Julian Waller Date: Fri, 10 Jan 2020 11:49:49 +0000 Subject: [PATCH 62/68] fix: add atem-mini id --- src/enums/index.ts | 3 +- src/lib/atemSocket.ts | 4 +- yarn.lock | 375 +++++++++++++++++++++++------------------- 3 files changed, 213 insertions(+), 169 deletions(-) diff --git a/src/enums/index.ts b/src/enums/index.ts index 5ba897926..f9c7894dc 100644 --- a/src/enums/index.ts +++ b/src/enums/index.ts @@ -9,7 +9,8 @@ export enum Model { TwoMEBS4K = 0x07, TVSHD = 0x08, Constellation = 0x0b, - Constellation8K = 0x0c + Constellation8K = 0x0c, + Mini = 0x0d } export enum ProtocolVersion { diff --git a/src/lib/atemSocket.ts b/src/lib/atemSocket.ts index bd8d95e17..ff3683967 100644 --- a/src/lib/atemSocket.ts +++ b/src/lib/atemSocket.ts @@ -168,7 +168,9 @@ export class AtemSocket extends EventEmitter { } catch (e) { this.emit('error', `Failed to deserialize command: ${cmdConstructor.constructor.name}: ${e}`) } - } // TODO - log the unknown command? + } else if (this._debug) { + this.log(`Unknown command ${name} (${length}b)`) + } // Trim the buffer buffer = buffer.slice(length) diff --git a/yarn.lock b/yarn.lock index a999a5196..7c1432a95 100644 --- a/yarn.lock +++ b/yarn.lock @@ -10,14 +10,14 @@ "@babel/highlight" "^7.0.0" "@babel/core@^7.1.0": - version "7.7.5" - resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.7.5.tgz#ae1323cd035b5160293307f50647e83f8ba62f7e" - integrity sha512-M42+ScN4+1S9iB6f+TL7QBpoQETxbclx+KNoKJABghnKYE+fMzSGqst0BZJc8CpI625bwPwYgUyRvxZ+0mZzpw== + version "7.7.7" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.7.7.tgz#ee155d2e12300bcc0cff6a8ad46f2af5063803e9" + integrity sha512-jlSjuj/7z138NLZALxVgrx13AOtqip42ATZP7+kYl53GvDV6+4dCek1mVUo8z8c8Xnw/mx2q3d9HWh3griuesQ== dependencies: "@babel/code-frame" "^7.5.5" - "@babel/generator" "^7.7.4" + "@babel/generator" "^7.7.7" "@babel/helpers" "^7.7.4" - "@babel/parser" "^7.7.5" + "@babel/parser" "^7.7.7" "@babel/template" "^7.7.4" "@babel/traverse" "^7.7.4" "@babel/types" "^7.7.4" @@ -29,10 +29,10 @@ semver "^5.4.1" source-map "^0.5.0" -"@babel/generator@^7.4.0", "@babel/generator@^7.7.4": - version "7.7.4" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.7.4.tgz#db651e2840ca9aa66f327dcec1dc5f5fa9611369" - integrity sha512-m5qo2WgdOJeyYngKImbkyQrnUN1mPceaG5BV+G0E3gWsa4l/jCSryWJdM2x8OuGAOyh+3d5pVYfZWCiNFtynxg== +"@babel/generator@^7.4.0", "@babel/generator@^7.7.4", "@babel/generator@^7.7.7": + version "7.7.7" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.7.7.tgz#859ac733c44c74148e1a72980a64ec84b85f4f45" + integrity sha512-/AOIBpHh/JU1l0ZFS4kiRCBnLi6OTHzh0RPk3h9isBxkkqELtQNFi1Vr/tiG9p1yfoUdKVwISuXWQR+hwwM4VQ== dependencies: "@babel/types" "^7.7.4" jsesc "^2.5.1" @@ -85,10 +85,10 @@ esutils "^2.0.2" js-tokens "^4.0.0" -"@babel/parser@^7.1.0", "@babel/parser@^7.4.3", "@babel/parser@^7.7.4", "@babel/parser@^7.7.5": - version "7.7.5" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.7.5.tgz#cbf45321619ac12d83363fcf9c94bb67fa646d71" - integrity sha512-KNlOe9+/nk4i29g0VXgl8PEXIRms5xKLJeuZ6UptN0fHv+jDiriG+y94X6qAgWTR0h3KaoM1wK5G5h7MHFRSig== +"@babel/parser@^7.1.0", "@babel/parser@^7.4.3", "@babel/parser@^7.7.4", "@babel/parser@^7.7.7": + version "7.7.7" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.7.7.tgz#1b886595419cf92d811316d5b715a53ff38b4937" + integrity sha512-WtTZMZAZLbeymhkd/sEaPD8IQyGAhmuTuvTzLiCFM7iXiVdY0gc0IaI+cW0fh1BnSMbJSzXX6/fHllgHKwHhXw== "@babel/plugin-syntax-object-rest-spread@^7.0.0": version "7.7.4" @@ -303,6 +303,13 @@ resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-0.14.0.tgz#9fb3a3cf3132328151f353de4632e01e52102bea" integrity sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ== +"@sinonjs/commons@^1.7.0": + version "1.7.0" + resolved "https://registry.yarnpkg.com/@sinonjs/commons/-/commons-1.7.0.tgz#f90ffc52a2e519f018b13b6c4da03cbff36ebed6" + integrity sha512-qbk9AP+cZUsKdW1GJsBpxPKFmCJ0T8swwzVje3qFd+AkQb74Q/tiuzrdfFg8AD2g5HH/XbE/I8Uc1KYHVYWfhg== + dependencies: + type-detect "4.0.8" + "@stroncium/procfs@^1.0.0": version "1.0.0" resolved "https://registry.yarnpkg.com/@stroncium/procfs/-/procfs-1.0.0.tgz#b7989b3783070e1bc2f25cba7d4eab17e607f770" @@ -327,9 +334,9 @@ "@types/babel__traverse" "*" "@types/babel__generator@*": - version "7.6.0" - resolved "https://registry.yarnpkg.com/@types/babel__generator/-/babel__generator-7.6.0.tgz#f1ec1c104d1bb463556ecb724018ab788d0c172a" - integrity sha512-c1mZUu4up5cp9KROs/QAw0gTeHrw/x7m52LcnvMxxOZ03DmLwPV0MlGmlgzV3cnSdjhJOZsj7E7FHeioai+egw== + version "7.6.1" + resolved "https://registry.yarnpkg.com/@types/babel__generator/-/babel__generator-7.6.1.tgz#4901767b397e8711aeb99df8d396d7ba7b7f0e04" + integrity sha512-bBKm+2VPJcMRVwNhxKu8W+5/zT7pwNEqeokFOmbvVSqGzFneNxYcEBro9Ac7/N9tlsaPYnZLK8J1LWKkMsLAew== dependencies: "@babel/types" "^7.0.0" @@ -369,9 +376,9 @@ "@types/istanbul-lib-report" "*" "@types/jest@^24.0.11": - version "24.0.23" - resolved "https://registry.yarnpkg.com/@types/jest/-/jest-24.0.23.tgz#046f8e2ade026fe831623e361a36b6fb9a4463e4" - integrity sha512-L7MBvwfNpe7yVPTXLn32df/EK+AMBFAFvZrRuArGs7npEWnlziUXK+5GMIUTI4NIuwok3XibsjXCs5HxviYXjg== + version "24.0.25" + resolved "https://registry.yarnpkg.com/@types/jest/-/jest-24.0.25.tgz#2aba377824ce040114aa906ad2cac2c85351360f" + integrity sha512-hnP1WpjN4KbGEK4dLayul6lgtys6FPz0UfxMeMQCv0M+sTnzN3ConfiO72jHgLxl119guHgI8gLqDOrRLsyp2g== dependencies: jest-diff "^24.3.0" @@ -386,9 +393,9 @@ integrity sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA== "@types/node@^12.7.12": - version "12.12.14" - resolved "https://registry.yarnpkg.com/@types/node/-/node-12.12.14.tgz#1c1d6e3c75dba466e0326948d56e8bd72a1903d2" - integrity sha512-u/SJDyXwuihpwjXy7hOOghagLEV1KdAST6syfnOk6QZAMzZuWZqXy5aYYZbh8Jdpd4escVFP0MvftHNDb9pruA== + version "12.12.24" + resolved "https://registry.yarnpkg.com/@types/node/-/node-12.12.24.tgz#d4606afd8cf6c609036b854360367d1b2c78931f" + integrity sha512-1Ciqv9pqwVtW6FsIUKSZNB82E5Cu1I2bBTj1xuIHXLe/1zYLl3956Nbhg2MzSYHVfl9/rmanjbQIb7LibfCnug== "@types/stack-utils@^1.0.1": version "1.0.1" @@ -401,9 +408,9 @@ integrity sha512-gCubfBUZ6KxzoibJ+SCUc/57Ms1jz5NjHe4+dI2krNmU5zCPAphyLJYyTOg06ueIyfj+SaCUqmzun7ImlxDcKg== "@types/yargs@^13.0.0": - version "13.0.3" - resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-13.0.3.tgz#76482af3981d4412d65371a318f992d33464a380" - integrity sha512-K8/LfZq2duW33XW/tFwEAfnZlqIfVsoyRB3kfXdPXYhl0nfM8mmh7GS0jg7WrX2Dgq/0Ha/pR1PaR+BvmWwjiQ== + version "13.0.5" + resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-13.0.5.tgz#18121bfd39dc12f280cee58f92c5b21d32041908" + integrity sha512-CF/+sxTO7FOwbIRL4wMv0ZYLCRfMid2HQpzDRyViH7kSpfoAFiMdGqKIxb1PxWfjtQXQhnQuD33lvRHNwr809Q== dependencies: "@types/yargs-parser" "*" @@ -448,6 +455,11 @@ acorn@^6.0.1: resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.4.0.tgz#b659d2ffbafa24baf5db1cdbb2c94a983ecd2784" integrity sha512-gac8OEcQ2Li1dxIEWGZzsp2BitJxwkwcOm0zHAJLcPJaVvm58FRnk6RkuLRpU1EujipU2ZFODv2P9DLMfnV8mw== +add-stream@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/add-stream/-/add-stream-1.0.0.tgz#6a7990437ca736d5e1288db92bd3266d5f5cb2aa" + integrity sha1-anmQQ3ynNtXhKI25K9MmbV9csqo= + agent-base@^4.3.0: version "4.3.0" resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-4.3.0.tgz#8165f01c436009bccad0b1d122f05ed770efc6ee" @@ -651,7 +663,7 @@ asynckit@^0.4.0: resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" integrity sha1-x57Zf380y48robyXkLzDZkdLS3k= -atob@^2.1.1: +atob@^2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9" integrity sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg== @@ -741,6 +753,13 @@ bcrypt-pbkdf@^1.0.0: dependencies: tweetnacl "^0.14.3" +bindings@^1.5.0: + version "1.5.0" + resolved "https://registry.yarnpkg.com/bindings/-/bindings-1.5.0.tgz#10353c9e945334bc0511a6d90b38fbc7c9c504df" + integrity sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ== + dependencies: + file-uri-to-path "1.0.0" + bitdepth@^7.0.2: version "7.0.2" resolved "https://registry.yarnpkg.com/bitdepth/-/bitdepth-7.0.2.tgz#d9290de0e4b44ce5fc0c29f813c8f49fbdfa2eeb" @@ -1124,10 +1143,11 @@ conventional-changelog-conventionalcommits@^4.2.1: q "^1.5.1" conventional-changelog-core@^4.0.2: - version "4.1.1" - resolved "https://registry.yarnpkg.com/conventional-changelog-core/-/conventional-changelog-core-4.1.1.tgz#956f1a2fb476ef2f66c93f673ac040a4159de167" - integrity sha512-fBre5P6U9n914Da6Cj82vIfRU2DhTLGr1eDPXWA7AamxTpd4cd0jgdS7Aieas5Vn5WXOJNFRDNl6PrYLEonImg== + version "4.1.4" + resolved "https://registry.yarnpkg.com/conventional-changelog-core/-/conventional-changelog-core-4.1.4.tgz#39be27fca6ef20a0f998d7a3a1e97cfa8a055cb6" + integrity sha512-LO58ZbEpp1Ul+y/vOI8rJRsWkovsYkCFbOCVgi6UnVfU8WC0F8K8VQQwaBZWWUpb6JvEiN4GBR5baRP2txZ+Vg== dependencies: + add-stream "^1.0.0" conventional-changelog-writer "^4.0.11" conventional-commits-parser "^3.0.8" dateformat "^3.0.0" @@ -1588,21 +1608,22 @@ error-ex@^1.2.0, error-ex@^1.3.1: dependencies: is-arrayish "^0.2.1" -es-abstract@^1.5.1: - version "1.16.3" - resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.16.3.tgz#52490d978f96ff9f89ec15b5cf244304a5bca161" - integrity sha512-WtY7Fx5LiOnSYgF5eg/1T+GONaGmpvpPdCpSnYij+U2gDTL0UPfWrhDw7b2IYb+9NQJsYpCA0wOQvZfsd6YwRw== +es-abstract@^1.17.0-next.1: + version "1.17.0" + resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.17.0.tgz#f42a517d0036a5591dbb2c463591dc8bb50309b1" + integrity sha512-yYkE07YF+6SIBmg1MsJ9dlub5L48Ek7X0qz+c/CPCHS9EBXfESorzng4cJQjJW5/pB6vDF41u7F8vUhLVDqIug== dependencies: es-to-primitive "^1.2.1" function-bind "^1.1.1" has "^1.0.3" has-symbols "^1.0.1" - is-callable "^1.1.4" - is-regex "^1.0.4" + is-callable "^1.1.5" + is-regex "^1.0.5" object-inspect "^1.7.0" object-keys "^1.1.1" - string.prototype.trimleft "^2.1.0" - string.prototype.trimright "^2.1.0" + object.assign "^4.1.0" + string.prototype.trimleft "^2.1.1" + string.prototype.trimright "^2.1.1" es-to-primitive@^1.2.1: version "1.2.1" @@ -1631,9 +1652,9 @@ escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5: integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= escodegen@^1.9.1: - version "1.12.0" - resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-1.12.0.tgz#f763daf840af172bb3a2b6dd7219c0e17f7ff541" - integrity sha512-TuA+EhsanGcme5T3R0L80u4t8CpbXQjegRmf7+FPTJrtCTErXFeelblRgHQa1FofEzqYYJmJ/OqjTwREp9qgmg== + version "1.12.1" + resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-1.12.1.tgz#08770602a74ac34c7a90ca9229e7d51e379abc76" + integrity sha512-Q8t2YZ+0e0pc7NRVj3B4tSQ9rim1oi4Fh46k2xhJ2qOiEwhQfdjyEQddWdj7ZFaKmU+5104vn1qrcjEPWq+bgQ== dependencies: esprima "^3.1.3" estraverse "^4.2.0" @@ -1794,9 +1815,9 @@ fast-deep-equal@^2.0.1: integrity sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk= fast-json-stable-stringify@2.x, fast-json-stable-stringify@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz#d5142c0caee6b1189f87d3a76111064f86c8bbf2" - integrity sha1-1RQsDK7msRifh9OnYREGT4bIu/I= + version "2.1.0" + resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" + integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== fast-levenshtein@~2.0.6: version "2.0.6" @@ -1822,6 +1843,11 @@ file-type@^11.0.0: resolved "https://registry.yarnpkg.com/file-type/-/file-type-11.1.0.tgz#93780f3fed98b599755d846b99a1617a2ad063b8" integrity sha512-rM0UO7Qm9K7TWTtA6AShI/t7H5BPjDeGVDaNyg9BjHAj3PysKy7+8C8D137R88jnR3rFJZQB/tFgydl5sN5m7g== +file-uri-to-path@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz#553a7b8446ff6f684359c445f1e37a05dacc33dd" + integrity sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw== + filename-reserved-regex@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/filename-reserved-regex/-/filename-reserved-regex-1.0.0.tgz#e61cf805f0de1c984567d0386dc5df50ee5af7e4" @@ -1917,15 +1943,6 @@ fs-access@1.0.1: dependencies: null-check "^1.0.0" -fs-extra@^7.0.0: - version "7.0.1" - resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-7.0.1.tgz#4f189c44aa123b895f722804f55ea23eadc348e9" - integrity sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw== - dependencies: - graceful-fs "^4.1.2" - jsonfile "^4.0.0" - universalify "^0.1.0" - fs-extra@^8.1.0: version "8.1.0" resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-8.1.0.tgz#49d43c45a88cd9677668cb7be1b46efdb8d2e1c0" @@ -1948,12 +1965,12 @@ fs.realpath@^1.0.0: integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8= fsevents@^1.2.7: - version "1.2.9" - resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-1.2.9.tgz#3f5ed66583ccd6f400b5a00db6f7e861363e388f" - integrity sha512-oeyj2H3EjjonWcFjD5NvZNE9Rqe4UW+nQBU2HNeKw0koVLEFIhtyETyAakeAM3de7Z/SW5kcA+fZUait9EApnw== + version "1.2.11" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-1.2.11.tgz#67bf57f4758f02ede88fb2a1712fef4d15358be3" + integrity sha512-+ux3lx6peh0BpvY0JebGyZoiR4D+oYzdPZMKJwkZ+sFkNJzpL7tXc/wehS49gUAxg3tmMHPHZkA8JU2rhhgDHw== dependencies: + bindings "^1.5.0" nan "^2.12.1" - node-pre-gyp "^0.12.0" function-bind@^1.1.1: version "1.1.1" @@ -2032,18 +2049,16 @@ getpass@^0.1.1: assert-plus "^1.0.0" gh-pages@^2.0.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/gh-pages/-/gh-pages-2.1.1.tgz#5be70a92f9cb70404bafabd8bb149c0e9a8c264b" - integrity sha512-yNW2SFp9xGRP/8Sk2WXuLI/Gn92oOL4HBgudn6PsqAnuWT90Y1tozJoTfX1WdrDSW5Rb90kLVOf5mm9KJ/2fDw== + version "2.2.0" + resolved "https://registry.yarnpkg.com/gh-pages/-/gh-pages-2.2.0.tgz#74ebeaca8d2b9a11279dcbd4a39ddfff3e6caa24" + integrity sha512-c+yPkNOPMFGNisYg9r4qvsMIjVYikJv7ImFOhPIVPt0+AcRUamZ7zkGRLHz7FKB0xrlZ+ddSOJsZv9XAFVXLmA== dependencies: async "^2.6.1" commander "^2.18.0" email-addresses "^3.0.1" filenamify-url "^1.0.0" - fs-extra "^7.0.0" + fs-extra "^8.1.0" globby "^6.1.0" - graceful-fs "^4.1.11" - rimraf "^2.6.2" git-raw-commits@2.0.0: version "2.0.0" @@ -2175,9 +2190,9 @@ growly@^1.3.0: integrity sha1-8QdIy+dq+WS3yWyTxrzCivEgwIE= handlebars@^4.1.2, handlebars@^4.4.0, handlebars@^4.5.3: - version "4.5.3" - resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.5.3.tgz#5cf75bd8714f7605713511a56be7c349becb0482" - integrity sha512-3yPecJoJHK/4c6aZhSvxOyG4vJKDshV36VHp0iVCDVh7o9w2vwi3NSnL2MMPj3YdduqaBcu7cGbggJQM0br9xA== + version "4.6.0" + resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.6.0.tgz#33af6c3eda930d7a924f5d8f1c6d8edc3180512e" + integrity sha512-i1ZUP7Qp2JdkMaFon2a+b0m5geE8Z4ZTLaGkgrObkEd+OkUKyRbRWw4KxuFCoHfdETSY1yf9/574eVoNSiK7pw== dependencies: neo-async "^2.6.0" optimist "^0.6.1" @@ -2203,7 +2218,7 @@ has-flag@^3.0.0: resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0= -has-symbols@^1.0.1: +has-symbols@^1.0.0, has-symbols@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.1.tgz#9f5214758a44196c406d9bd76cebf81ec2dd31e8" integrity sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg== @@ -2249,17 +2264,19 @@ has-yarn@^2.1.0: resolved "https://registry.yarnpkg.com/has-yarn/-/has-yarn-2.1.0.tgz#137e11354a7b5bf11aa5cb649cf0c6f3ff2b2e77" integrity sha512-UqBRqi4ju7T+TqGNdqAO0PaSVGsDGJUBQvk9eUWNGRY1CFGDzYhLWoM7JQEemnlvVcv/YEmc2wNW8BC24EnUsw== -has@^1.0.1, has@^1.0.3: +has@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== dependencies: function-bind "^1.1.1" -highlight.js@^9.16.2: - version "9.16.2" - resolved "https://registry.yarnpkg.com/highlight.js/-/highlight.js-9.16.2.tgz#68368d039ffe1c6211bcc07e483daf95de3e403e" - integrity sha512-feMUrVLZvjy0oC7FVJQcSQRqbBq9kwqnYE4+Kj9ZjbHh3g+BisiPgF49NyQbVLNdrL/qqZr3Ca9yOKwgn2i/tw== +highlight.js@^9.17.1: + version "9.17.1" + resolved "https://registry.yarnpkg.com/highlight.js/-/highlight.js-9.17.1.tgz#14a4eded23fd314b05886758bb906e39dd627f9a" + integrity sha512-TA2/doAur5Ol8+iM3Ov7qy3jYcr/QiJ2eDTdRF4dfbjG7AaaB99J5G+zSl11ljbl6cIcahgPY6SKb3sC3EJ0fw== + dependencies: + handlebars "^4.5.3" hosted-git-info@^2.1.4, hosted-git-info@^2.1.5: version "2.8.5" @@ -2426,10 +2443,10 @@ is-buffer@^1.1.5: resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w== -is-callable@^1.1.4: - version "1.1.4" - resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.1.4.tgz#1e1adf219e1eeb684d691f9d6a05ff0d30a24d75" - integrity sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA== +is-callable@^1.1.4, is-callable@^1.1.5: + version "1.1.5" + resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.1.5.tgz#f7e46b596890456db74e7f6e976cb3273d06faab" + integrity sha512-ESKv5sMCJB2jnHTWZ3O5itG+O128Hsus4K4Qh1h2/cgn2vbgnLSVqfV46AeJA9D5EeeLa9w81KUXMtn34zhX+Q== is-ci@^2.0.0: version "2.0.0" @@ -2453,9 +2470,9 @@ is-data-descriptor@^1.0.0: kind-of "^6.0.0" is-date-object@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.1.tgz#9aa20eb6aeebbff77fbd33e74ca01b33581d3a16" - integrity sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY= + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.2.tgz#bda736f2cd8fd06d32844e7743bfa7494c3bfd7e" + integrity sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g== is-descriptor@^0.1.0: version "0.1.6" @@ -2560,12 +2577,12 @@ is-plain-object@^2.0.3, is-plain-object@^2.0.4: dependencies: isobject "^3.0.1" -is-regex@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.0.4.tgz#5517489b547091b0930e095654ced25ee97e9491" - integrity sha1-VRdIm1RwkbCTDglWVM7SXul+lJE= +is-regex@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.0.5.tgz#39d589a358bf18967f726967120b8fc1aed74eae" + integrity sha512-vlKW17SNq44owv5AQR3Cq0bQPEb8+kF3UKZ2fiZNOWtztYE5i0CzCZxFDwO58qAOWtxdBRVO/V5Qin1wjCqFYQ== dependencies: - has "^1.0.1" + has "^1.0.3" is-stream@^1.1.0: version "1.1.0" @@ -3337,9 +3354,11 @@ lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.15: integrity sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A== lolex@^5.1.1: - version "5.1.1" - resolved "https://registry.yarnpkg.com/lolex/-/lolex-5.1.1.tgz#9587144854511d27940ee5e113dcb7de9b0fd666" - integrity sha512-dEwHz1CJ8DsdgfpiimgQQEhEJYOEiJ69a0s4aJDNHajaTqOJuF34vBAWVa/sS0V8aQvt72p+KgQ3pRmEVJM+iA== + version "5.1.2" + resolved "https://registry.yarnpkg.com/lolex/-/lolex-5.1.2.tgz#953694d098ce7c07bc5ed6d0e42bc6c0c6d5a367" + integrity sha512-h4hmjAvHTmd+25JSwrtTIuwbKdwg5NzZVRMLn9saij4SZaepCrTCxPr35H/3bjwfMJtN+t3CX8672UIkglz28A== + dependencies: + "@sinonjs/commons" "^1.7.0" loose-envify@^1.0.0: version "1.4.0" @@ -3435,10 +3454,10 @@ map-visit@^1.0.0: dependencies: object-visit "^1.0.0" -marked@^0.7.0: - version "0.7.0" - resolved "https://registry.yarnpkg.com/marked/-/marked-0.7.0.tgz#b64201f051d271b1edc10a04d1ae9b74bb8e5c0e" - integrity sha512-c+yYdCZJQrsRjTPhUx7VKkApw9bwDkNbHUKo1ovgcfDjb2kc8rLuRbIFyXL5WOEUwzSSKo3IXpph2K6DqB/KZg== +marked@^0.8.0: + version "0.8.0" + resolved "https://registry.yarnpkg.com/marked/-/marked-0.8.0.tgz#ec5c0c9b93878dc52dd54be8d0e524097bd81a99" + integrity sha512-MyUe+T/Pw4TZufHkzAfDj6HarCBWia2y27/bhuYkTaiUnfDYFnCP3KUN+9oM7Wi6JA2rymtVYbQu3spE0GCmxQ== meow@^3.3.0, meow@^3.7.0: version "3.7.0" @@ -3510,17 +3529,17 @@ micromatch@^3.1.10, micromatch@^3.1.4: snapdragon "^0.8.1" to-regex "^3.0.2" -mime-db@1.42.0: - version "1.42.0" - resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.42.0.tgz#3e252907b4c7adb906597b4b65636272cf9e7bac" - integrity sha512-UbfJCR4UAVRNgMpfImz05smAXK7+c+ZntjaA26ANtkXLlOe947Aag5zdIcKQULAiF9Cq4WxBi9jUs5zkA84bYQ== +mime-db@1.43.0: + version "1.43.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.43.0.tgz#0a12e0502650e473d735535050e7c8f4eb4fae58" + integrity sha512-+5dsGEEovYbT8UY9yD7eE4XTc4UwJ1jBYlgaQQF38ENsKR3wj/8q8RFZrF9WIZpB2V1ArTVFUva8sAul1NzRzQ== mime-types@^2.1.12, mime-types@~2.1.19: - version "2.1.25" - resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.25.tgz#39772d46621f93e2a80a856c53b86a62156a6437" - integrity sha512-5KhStqB5xpTAeGqKBAMgwaYMnQik7teQN4IAzC7npDv6kzeU6prfkR67bc87J1kWMPGkoaZSq1npmexMgkmEVg== + version "2.1.26" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.26.tgz#9c921fc09b7e149a65dfdc0da4d20997200b0a06" + integrity sha512-01paPWYgLrkqAyrlDorC1uDwl2p3qZT7yl806vW7DvDoxwXi46jsjFbg+WdwotBIk6/MbEhO/dh5aZ5sNj/dWQ== dependencies: - mime-db "1.42.0" + mime-db "1.43.0" mimic-response@^1.0.0, mimic-response@^1.0.1: version "1.0.1" @@ -3730,10 +3749,10 @@ node-notifier@^5.4.2: shellwords "^0.1.1" which "^1.3.0" -node-pre-gyp@^0.12.0: - version "0.12.0" - resolved "https://registry.yarnpkg.com/node-pre-gyp/-/node-pre-gyp-0.12.0.tgz#39ba4bb1439da030295f899e3b520b7785766149" - integrity sha512-4KghwV8vH5k+g2ylT+sLTjy5wmUOb9vPhnM8NHvRf9dHmnW/CndrFXy2aRPaPST6dugXSdHXfeaHQm77PIz/1A== +node-pre-gyp@*: + version "0.14.0" + resolved "https://registry.yarnpkg.com/node-pre-gyp/-/node-pre-gyp-0.14.0.tgz#9a0596533b877289bcad4e143982ca3d904ddc83" + integrity sha512-+CvDC7ZttU/sSt9rFjix/P05iS43qHCOOGzcr3Ry99bXG7VX953+vFyEuph/tfqoYu8dttBkE86JSKBO2OzcxA== dependencies: detect-libc "^1.0.2" mkdirp "^0.5.1" @@ -3744,7 +3763,7 @@ node-pre-gyp@^0.12.0: rc "^1.2.7" rimraf "^2.6.1" semver "^5.3.0" - tar "^4" + tar "^4.4.2" nopt@^4.0.1: version "4.0.1" @@ -3787,9 +3806,16 @@ normalize-url@^4.1.0: integrity sha512-2s47yzUxdexf1OhyRi4Em83iQk0aPvwTddtFz4hnSSw9dCEsLEGf6SwIO8ss/19S9iBb5sJaOuTvTGDeZI00BQ== npm-bundled@^1.0.1: - version "1.0.6" - resolved "https://registry.yarnpkg.com/npm-bundled/-/npm-bundled-1.0.6.tgz#e7ba9aadcef962bb61248f91721cd932b3fe6bdd" - integrity sha512-8/JCaftHwbd//k6y2rEWp6k1wxVfpFzB6t1p825+cUb7Ym2XQfhwIC5KwhrvzZRJu+LtDE585zVaS32+CGtf0g== + version "1.1.1" + resolved "https://registry.yarnpkg.com/npm-bundled/-/npm-bundled-1.1.1.tgz#1edd570865a94cdb1bc8220775e29466c9fb234b" + integrity sha512-gqkfgGePhTpAEgUsGEgcq1rqPXA+tv/aVBlgEzfXwA1yiUJF7xtEt3CtVwOjNYQOVknDk0F20w58Fnm3EtG0fA== + dependencies: + npm-normalize-package-bin "^1.0.1" + +npm-normalize-package-bin@^1.0.0, npm-normalize-package-bin@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/npm-normalize-package-bin/-/npm-normalize-package-bin-1.0.1.tgz#6e79a41f23fd235c0623218228da7d9c23b8f6e2" + integrity sha512-EPfafl6JL5/rU+ot6P3gRSCpPDW5VmIzX959Ob1+ySFUuuYHWHekXpwdUZcKP5C+DS4GEtdJluwBjnsNDl+fSA== npm-package-arg@^4.2.0: version "4.2.1" @@ -3800,9 +3826,9 @@ npm-package-arg@^4.2.0: semver "^5.1.0" npm-packlist@^1.1.6: - version "1.4.6" - resolved "https://registry.yarnpkg.com/npm-packlist/-/npm-packlist-1.4.6.tgz#53ba3ed11f8523079f1457376dd379ee4ea42ff4" - integrity sha512-u65uQdb+qwtGvEJh/DgQgW1Xg7sqeNbmxYyrvlNznaVTjV3E5P6F/EFjM+BVHXl7JJlsdG8A64M0XI8FI/IOlg== + version "1.4.7" + resolved "https://registry.yarnpkg.com/npm-packlist/-/npm-packlist-1.4.7.tgz#9e954365a06b80b18111ea900945af4f88ed4848" + integrity sha512-vAj7dIkp5NhieaGZxBJB8fF4R0078rqsmhJcAfXZ6O7JJhjhPK96n5Ry1oZcfLXgfun0GWTZPOxaEyqv8GBykQ== dependencies: ignore-walk "^3.0.1" npm-bundled "^1.0.1" @@ -3879,7 +3905,7 @@ object-inspect@^1.7.0: resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.7.0.tgz#f4f6bd181ad77f006b5ece60bd0b6f398ff74a67" integrity sha512-a7pEHdh1xKIAgTySUGgLMx/xwDZskN1Ud6egYYN3EdRW4ZMPNEDUTF+hwy2LUC+Bl+SyLXANnwz/jyh/qutKUw== -object-keys@^1.0.12, object-keys@^1.1.1: +object-keys@^1.0.11, object-keys@^1.0.12, object-keys@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== @@ -3891,13 +3917,23 @@ object-visit@^1.0.0: dependencies: isobject "^3.0.0" -object.getownpropertydescriptors@^2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.0.3.tgz#8758c846f5b407adab0f236e0986f14b051caa16" - integrity sha1-h1jIRvW0B62rDyNuCYbxSwUcqhY= +object.assign@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.0.tgz#968bf1100d7956bb3ca086f006f846b3bc4008da" + integrity sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w== dependencies: define-properties "^1.1.2" - es-abstract "^1.5.1" + function-bind "^1.1.1" + has-symbols "^1.0.0" + object-keys "^1.0.11" + +object.getownpropertydescriptors@^2.0.3: + version "2.1.0" + resolved "https://registry.yarnpkg.com/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.0.tgz#369bf1f9592d8ab89d712dced5cb81c7c5352649" + integrity sha512-Z53Oah9A3TdLoblT7VKJaTDdXdT+lQO+cNpKVnya5JDe9uLvzu1YyY1yFDFrcxrlRgWrEFH0jJtD/IbuwjcEVg== + dependencies: + define-properties "^1.1.3" + es-abstract "^1.17.0-next.1" object.pick@^1.3.0: version "1.3.0" @@ -4001,9 +4037,9 @@ p-limit@^1.1.0: p-try "^1.0.0" p-limit@^2.0.0, p-limit@^2.2.0: - version "2.2.1" - resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.2.1.tgz#aa07a788cc3151c939b5131f63570f0dd2009537" - integrity sha512-85Tk+90UCVWvbDavCLKPOLC9vvY8OwEX/RtKF+/1OADJMVlFfEHOiMTPVyxg7mk/dKa+ipdHm0OUkTvCpMTuwg== + version "2.2.2" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.2.2.tgz#61279b67721f5287aa1c13a9a7fbbc48c9291b1e" + integrity sha512-WGR+xHecKTr7EbUEhyLSh5Dube9JtdiG78ufaeLxTgpudf/20KqyMioIUZJAezlTIi6evxuoUs9YXc11cU+yzQ== dependencies: p-try "^2.0.0" @@ -4261,9 +4297,9 @@ pseudomap@^1.0.2: integrity sha1-8FKijacOYYkX7wqKw0wa5aaChrM= psl@^1.1.24, psl@^1.1.28: - version "1.6.0" - resolved "https://registry.yarnpkg.com/psl/-/psl-1.6.0.tgz#60557582ee23b6c43719d9890fb4170ecd91e110" - integrity sha512-SYKKmVel98NCOYXpkwUqZqh0ahZeeKfmisiLIcEZdsb+WbLv02g/dI5BUmZnIyOe7RzZtLax81nnb2HbvC2tzA== + version "1.7.0" + resolved "https://registry.yarnpkg.com/psl/-/psl-1.7.0.tgz#f1c4c47a8ef97167dea5d6bbf4816d736e884a3c" + integrity sha512-5NsSEDv8zY70ScRnOTn7bK7eanl2MvFrOrS/R6x+dBt5g1ghnj9Zv90kO8GwT8gxcu2ANyFprnFYB85IogIJOQ== pump@^3.0.0: version "3.0.0" @@ -4336,14 +4372,14 @@ read-installed@4.0.3: graceful-fs "^4.1.2" read-package-json@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/read-package-json/-/read-package-json-2.1.0.tgz#e3d42e6c35ea5ae820d9a03ab0c7291217fc51d5" - integrity sha512-KLhu8M1ZZNkMcrq1+0UJbR8Dii8KZUqB0Sha4mOx/bknfKI/fyrQVrG/YIt2UOtG667sD8+ee4EXMM91W9dC+A== + version "2.1.1" + resolved "https://registry.yarnpkg.com/read-package-json/-/read-package-json-2.1.1.tgz#16aa66c59e7d4dad6288f179dd9295fd59bb98f1" + integrity sha512-dAiqGtVc/q5doFz6096CcnXhpYk0ZN8dEKVkGLU0CsASt8SrgF6SF7OTKAYubfvFhWaqofl+Y8HK19GR8jwW+A== dependencies: glob "^7.1.1" json-parse-better-errors "^1.0.1" normalize-package-data "^2.0.0" - slash "^1.0.0" + npm-normalize-package-bin "^1.0.0" optionalDependencies: graceful-fs "^4.1.2" @@ -4399,9 +4435,9 @@ read-pkg@^3.0.0: util-deprecate "^1.0.1" readable-stream@^2.0.6, readable-stream@~2.3.6: - version "2.3.6" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.6.tgz#b11c27d88b8ff1fbe070643cf94b0c79ae1b0aaf" - integrity sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw== + version "2.3.7" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57" + integrity sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw== dependencies: core-util-is "~1.0.0" inherits "~2.0.3" @@ -4571,9 +4607,9 @@ resolve@1.1.7: integrity sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs= resolve@1.x, resolve@^1.1.6, resolve@^1.10.0, resolve@^1.3.2: - version "1.13.1" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.13.1.tgz#be0aa4c06acd53083505abb35f4d66932ab35d16" - integrity sha512-CxqObCX8K8YtAhOBRg+lrcdn+LK+WYOS8tSjqSFbjtrI5PnS63QPhZl4+yKfrU9tdsbMu9Anr/amegT87M9Z6w== + version "1.14.2" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.14.2.tgz#dbf31d0fa98b1f29aa5169783b9c290cb865fea2" + integrity sha512-EjlOBLBO1kxsUxsKjLt7TAECyKW6fOh1VRkykQkKGzcBbjjPIxBqGh0jf7GJ3k/f5mxMqW3htMD3WdTUVtW8HQ== dependencies: path-parse "^1.0.6" @@ -4589,7 +4625,7 @@ ret@~0.1.10: resolved "https://registry.yarnpkg.com/ret/-/ret-0.1.15.tgz#b8a4825d5bdb1fc3f6f53c2bc33f81388681c7bc" integrity sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg== -rimraf@^2.5.4, rimraf@^2.6.1, rimraf@^2.6.2, rimraf@^2.6.3: +rimraf@^2.5.4, rimraf@^2.6.1, rimraf@^2.6.3: version "2.7.1" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec" integrity sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w== @@ -4774,11 +4810,11 @@ sort-keys@^1.0.0: is-plain-obj "^1.0.0" source-map-resolve@^0.5.0: - version "0.5.2" - resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.5.2.tgz#72e2cc34095543e43b2c62b2c4c10d4a9054f259" - integrity sha512-MjqsvNwyz1s0k81Goz/9vRBe9SZdB09Bdw+/zYyO+3CuPk6fouTaxscHkgtE8jKvf01kVfl8riHzERQ/kefaSA== + version "0.5.3" + resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.5.3.tgz#190866bece7553e1f8f267a2ee82c606b5509a1a" + integrity sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw== dependencies: - atob "^2.1.1" + atob "^2.1.2" decode-uri-component "^0.2.0" resolve-url "^0.2.1" source-map-url "^0.4.0" @@ -4984,18 +5020,18 @@ string-width@^3.0.0, string-width@^3.1.0: is-fullwidth-code-point "^2.0.0" strip-ansi "^5.1.0" -string.prototype.trimleft@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/string.prototype.trimleft/-/string.prototype.trimleft-2.1.0.tgz#6cc47f0d7eb8d62b0f3701611715a3954591d634" - integrity sha512-FJ6b7EgdKxxbDxc79cOlok6Afd++TTs5szo+zJTUyow3ycrRfJVE2pq3vcN53XexvKZu/DJMDfeI/qMiZTrjTw== +string.prototype.trimleft@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/string.prototype.trimleft/-/string.prototype.trimleft-2.1.1.tgz#9bdb8ac6abd6d602b17a4ed321870d2f8dcefc74" + integrity sha512-iu2AGd3PuP5Rp7x2kEZCrB2Nf41ehzh+goo8TV7z8/XDBbsvc6HQIlUl9RjkZ4oyrW1XM5UwlGl1oVEaDjg6Ag== dependencies: define-properties "^1.1.3" function-bind "^1.1.1" -string.prototype.trimright@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/string.prototype.trimright/-/string.prototype.trimright-2.1.0.tgz#669d164be9df9b6f7559fa8e89945b168a5a6c58" - integrity sha512-fXZTSV55dNBwv16uw+hh5jkghxSnc5oHq+5K/gXgizHwAvMetdAJlHqqoFC1FSDVPYWLkAKl2cxpUT41sV7nSg== +string.prototype.trimright@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/string.prototype.trimright/-/string.prototype.trimright-2.1.1.tgz#440314b15996c866ce8a0341894d45186200c5d9" + integrity sha512-qFvWL3/+QIgZXVmJBfpHmxLB7xsUXz6HsUmP8+5dRaC3Q7oKUv9Vo6aMCRZC1smrtyECFsIT30PqBJ1gTjAs+g== dependencies: define-properties "^1.1.3" function-bind "^1.1.1" @@ -5105,7 +5141,7 @@ symbol-tree@^3.2.2: resolved "https://registry.yarnpkg.com/symbol-tree/-/symbol-tree-3.2.4.tgz#430637d248ba77e078883951fb9aa0eed7c63fa2" integrity sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw== -tar@^4: +tar@^4.4.2: version "4.4.13" resolved "https://registry.yarnpkg.com/tar/-/tar-4.4.13.tgz#43b364bc52888d555298637b10d60790254ab525" integrity sha512-w2VwSrBoHa5BsSyH+KxEqeQBAllHhccyMFVHtGtdMpF4W7IRWfZjFiQceJPChOeTsSDVUpER2T8FA93pr0L+QA== @@ -5308,9 +5344,9 @@ trim-repeated@^1.0.0: escape-string-regexp "^1.0.2" ts-jest@^24.0.2: - version "24.2.0" - resolved "https://registry.yarnpkg.com/ts-jest/-/ts-jest-24.2.0.tgz#7abca28c2b4b0a1fdd715cd667d65d047ea4e768" - integrity sha512-Yc+HLyldlIC9iIK8xEN7tV960Or56N49MDP7hubCZUeI7EbIOTsas6rXCMB4kQjLACJ7eDOF4xWEO5qumpKsag== + version "24.3.0" + resolved "https://registry.yarnpkg.com/ts-jest/-/ts-jest-24.3.0.tgz#b97814e3eab359ea840a1ac112deae68aa440869" + integrity sha512-Hb94C/+QRIgjVZlJyiWwouYUF+siNJHJHknyspaOcZ+OQAIdFG/UrdQVXw/0B8Z3No34xkUXZJpOTy9alOWdVQ== dependencies: bs-logger "0.x" buffer-from "1.x" @@ -5426,6 +5462,11 @@ type-check@~0.3.2: dependencies: prelude-ls "~1.1.2" +type-detect@4.0.8: + version "4.0.8" + resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c" + integrity sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g== + type-fest@^0.3.0: version "0.3.1" resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.3.1.tgz#63d00d204e059474fe5e1b7c011112bbd1dc29e1" @@ -5436,10 +5477,10 @@ typedarray@^0.0.6: resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c= -typedoc-default-themes@^0.6.1: - version "0.6.1" - resolved "https://registry.yarnpkg.com/typedoc-default-themes/-/typedoc-default-themes-0.6.1.tgz#e2e471188983df995f4f9df49f713044fced6802" - integrity sha512-z5AWKqQDz7igl9WkUuafx8cEm4MPVQGMpbWE+3lwVOaq+U4UoLKBMnpFQWh/4fqQ3bGysXpOstMxy2OOzHezyw== +typedoc-default-themes@^0.6.3: + version "0.6.3" + resolved "https://registry.yarnpkg.com/typedoc-default-themes/-/typedoc-default-themes-0.6.3.tgz#c214ce5bbcc6045558448a8fd422b90e3e9b6782" + integrity sha512-rouf0TcIA4M2nOQFfC7Zp4NEwoYiEX4vX/ZtudJWU9IHA29MPC+PPgSXYLPESkUo7FuB//GxigO3mk9Qe1xp3Q== dependencies: backbone "^1.4.0" jquery "^3.4.1" @@ -5447,26 +5488,26 @@ typedoc-default-themes@^0.6.1: underscore "^1.9.1" typedoc@^0.15.0: - version "0.15.3" - resolved "https://registry.yarnpkg.com/typedoc/-/typedoc-0.15.3.tgz#8f5a038cfc1160f70cbc57e37908653483dca689" - integrity sha512-RGX+dgnm9fyg5KHj81/ZhMiee0FfvJnjBXedhedhMWlrtM4YRv3pn8sYCWRt5TMi1Jli3/JG224pbFo3/3uaGw== + version "0.15.6" + resolved "https://registry.yarnpkg.com/typedoc/-/typedoc-0.15.6.tgz#d99a1c3db8c87a00437a8a89a0df03f9dc1995ad" + integrity sha512-TC3j7HXFfyq0/NyUL9oLgEXhgO4U8Kd7iyRgagkG3XxehgTjn6w20uJ/Hif1KPB/65VQZ8uMYYyxFXNj9um5Ow== dependencies: "@types/minimatch" "3.0.3" fs-extra "^8.1.0" handlebars "^4.5.3" - highlight.js "^9.16.2" + highlight.js "^9.17.1" lodash "^4.17.15" - marked "^0.7.0" + marked "^0.8.0" minimatch "^3.0.0" progress "^2.0.3" shelljs "^0.8.3" - typedoc-default-themes "^0.6.1" + typedoc-default-themes "^0.6.3" typescript "3.7.x" typescript@3.7.x: - version "3.7.3" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.7.3.tgz#b36840668a16458a7025b9eabfad11b66ab85c69" - integrity sha512-Mcr/Qk7hXqFBXMN7p7Lusj1ktCBydylfQM/FZCk5glCNQJrCUKPkMHdo9R0MTFWsC/4kPFvDS0fDPvukfCkFsw== + version "3.7.4" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.7.4.tgz#1743a5ec5fef6a1fa9f3e4708e33c81c73876c19" + integrity sha512-A25xv5XCtarLwXpcDNZzCGvW2D1S3/bACratYBx2sax8PefsFhlYmkQicKHvpYflFS8if4zne5zT5kpJ7pzuvw== typescript@~3.6.4: version "3.6.4" @@ -5474,9 +5515,9 @@ typescript@~3.6.4: integrity sha512-unoCll1+l+YK4i4F8f22TaNVPRHcD9PA3yCuZ8g5e0qGqlVlJ/8FSateOLLSagn+Yg5+ZwuPkL8LFUc0Jcvksg== uglify-js@^3.1.4: - version "3.7.1" - resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.7.1.tgz#35c7de17971a4aa7689cd2eae0a5b39bb838c0c5" - integrity sha512-pnOF7jY82wdIhATVn87uUY/FHU+MDUdPLkmGFvGoclQmeu229eTkbG5gjGGBi3R7UuYYSEeYXY/TTY5j2aym2g== + version "3.7.4" + resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.7.4.tgz#e6d83a1aa32ff448bd1679359ab13d8db0fe0743" + integrity sha512-tinYWE8X1QfCHxS1lBS8yiDekyhSXOO6R66yNOCdUJeojxxw+PX2BHAz/BWyW7PQ7pkiWVxJfIEbiDxyLWvUGg== dependencies: commander "~2.20.3" source-map "~0.6.1" @@ -5487,9 +5528,9 @@ uint-buffer@^0.1.0: integrity sha512-7xjpjCTijFIXAMxN7OMRfykpCMVfbCrlAmAt2RIlihvkHgvkNV5DBFzyc8OpIQeVpRXJkgXBwmKos4hD8DrX1g== underscore@>=1.8.3, underscore@^1.9.1: - version "1.9.1" - resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.9.1.tgz#06dce34a0e68a7babc29b365b8e74b8925203961" - integrity sha512-5/4etnCkd9c8gwgowi5/om/mYO5ajCaOgdzj/oW+0eQV9WxKBDZw5+ycmKmeaTXjInS/W0BzpGLo2xR2aBwZdg== + version "1.9.2" + resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.9.2.tgz#0c8d6f536d6f378a5af264a72f7bec50feb7cf2f" + integrity sha512-D39qtimx0c1fI3ya1Lnhk3E9nONswSKhnffBI0gME9C99fYOkNi04xs8K6pePLhvl1frbDemkaBQ5ikWllR2HQ== union-value@^1.0.0: version "1.0.1" From 97d0522813fccd266b83c51f41a832c9fd85a1d7 Mon Sep 17 00:00:00 2001 From: Julian Waller Date: Tue, 14 Jan 2020 16:07:44 +0000 Subject: [PATCH 63/68] feat: use objects instead of sparse arrays --- src/__tests__/tally/dump.js | 18 +----------------- src/__tests__/util.ts | 2 +- src/lib/tally.ts | 5 +++-- src/state/audio.ts | 2 +- src/state/index.ts | 2 +- src/state/video/index.ts | 2 +- src/state/video/upstreamKeyers.ts | 2 +- 7 files changed, 9 insertions(+), 24 deletions(-) diff --git a/src/__tests__/tally/dump.js b/src/__tests__/tally/dump.js index 587fa558c..49d1202dc 100644 --- a/src/__tests__/tally/dump.js +++ b/src/__tests__/tally/dump.js @@ -21,26 +21,10 @@ function writeJson (fileName, data) { fs.writeFileSync(filePath, JSON.stringify(data, undefined, '\t')) } -function toMap (arr) { - if (!Array.isArray(arr)) { - return arr - } - - const map = {} - for(let i = 0; i < arr.length; i++) { - const val = arr[i] - if (val !== null && val !== undefined) { - map[i] = val - } - } - - return map -} - conn.once('connected', () => { writeJson(`./${args[1]}-state.json`, { video: conn.state.video, - inputs: toMap(conn.state.inputs) // Optimise out the nulls + inputs: conn.state.inputs // Optimise out the nulls }) console.log('Wrote state file') diff --git a/src/__tests__/util.ts b/src/__tests__/util.ts index 2c33e5124..61773ae2e 100644 --- a/src/__tests__/util.ts +++ b/src/__tests__/util.ts @@ -6,7 +6,7 @@ import { AtemVideoState, MixEffect, SuperSource } from '../state/video' function parseAudio (rawState: AtemAudioState) { const state = plainToClass(AtemAudioState, rawState) state.master = state.master - state.channels = state.channels.map(ch => ch) + state.channels = state.channels return state } diff --git a/src/lib/tally.ts b/src/lib/tally.ts index 8b3d24240..dfb95b618 100644 --- a/src/lib/tally.ts +++ b/src/lib/tally.ts @@ -27,11 +27,12 @@ export function listVisibleInputs (mode: 'program' | 'preview', state: AtemState // every time the ATEM's state updates. lastSize = inputs.size Array.from(inputs).slice(lastProcessed).forEach(inputId => { - if (!state.inputs[inputId]) { + const input = state.inputs[inputId] + if (!input) { // Data isn't hydrated yet, we'll get 'em next time. return } - const portType = state.inputs[inputId].internalPortType + const portType = input.internalPortType switch (portType) { case Enums.InternalPortType.SuperSource: const ssrcId = inputId - 6000 diff --git a/src/state/audio.ts b/src/state/audio.ts index bcaf0b608..6f0fb1ae8 100644 --- a/src/state/audio.ts +++ b/src/state/audio.ts @@ -21,6 +21,6 @@ export interface AudioMasterChannel { export class AtemAudioState { public numberOfChannels?: number public hasMonitor?: boolean - public channels: Array = [] + public channels: { [channelId: number]: AudioChannel | undefined } = {} public master?: AudioMasterChannel } diff --git a/src/state/index.ts b/src/state/index.ts index 86e7a2d4c..9dd4b4c28 100644 --- a/src/state/index.ts +++ b/src/state/index.ts @@ -11,7 +11,7 @@ export class AtemState { public video: AtemVideoState = new AtemVideoState() public audio: AtemAudioState = new AtemAudioState() public media: MediaState = new MediaState() - public inputs: Array = [] // TODO should this be `| undefined` or an object? + public inputs: { [inputId: number]: InputChannel | undefined } = {} public macro: MacroState = new MacroState() public settings: SettingsState = new SettingsState() } diff --git a/src/state/video/index.ts b/src/state/video/index.ts index fec74eb6e..1c0c40413 100644 --- a/src/state/video/index.ts +++ b/src/state/video/index.ts @@ -120,7 +120,7 @@ export class MixEffect implements IMixEffect { fillSource: 0, onAir: false, flyEnabled: false, - flyKeyframes: [] + flyKeyframes: [undefined, undefined] } if (!dontCreate) { diff --git a/src/state/video/upstreamKeyers.ts b/src/state/video/upstreamKeyers.ts index 801bf7745..fea14897e 100644 --- a/src/state/video/upstreamKeyers.ts +++ b/src/state/video/upstreamKeyers.ts @@ -90,7 +90,7 @@ export interface UpstreamKeyer extends UpstreamKeyerBase { chromaSettings?: UpstreamKeyerChromaSettings, lumaSettings?: UpstreamKeyerLumaSettings, patternSettings?: UpstreamKeyerPatternSettings, - flyKeyframes: Array, + flyKeyframes: [UpstreamKeyerFlyKeyframe | undefined, UpstreamKeyerFlyKeyframe | undefined], flyProperties?: UpstreamKeyerFlySettings, onAir: boolean } From 9530d79ff9cf264bf113b560672ec9fb157401e9 Mon Sep 17 00:00:00 2001 From: Julian Waller Date: Tue, 14 Jan 2020 16:08:26 +0000 Subject: [PATCH 64/68] chore: update dependencies --- yarn.lock | 243 ++++++++++++++++++++++++++++-------------------------- 1 file changed, 127 insertions(+), 116 deletions(-) diff --git a/yarn.lock b/yarn.lock index 7c1432a95..1cd8cd519 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2,129 +2,130 @@ # yarn lockfile v1 -"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.5.5": - version "7.5.5" - resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.5.5.tgz#bc0782f6d69f7b7d49531219699b988f669a8f9d" - integrity sha512-27d4lZoomVyo51VegxI20xZPuSHusqbQag/ztrBC7wegWoQ1nLREPVSKSW8byhTlzTKyNE4ifaTA6lCp7JjpFw== +"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.8.3.tgz#33e25903d7481181534e12ec0a25f16b6fcf419e" + integrity sha512-a9gxpmdXtZEInkCSHUJDLHZVBgb1QS0jhss4cPP93EW7s+uC5bikET2twEF3KV+7rDblJcmNvTR7VJejqd2C2g== dependencies: - "@babel/highlight" "^7.0.0" + "@babel/highlight" "^7.8.3" "@babel/core@^7.1.0": - version "7.7.7" - resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.7.7.tgz#ee155d2e12300bcc0cff6a8ad46f2af5063803e9" - integrity sha512-jlSjuj/7z138NLZALxVgrx13AOtqip42ATZP7+kYl53GvDV6+4dCek1mVUo8z8c8Xnw/mx2q3d9HWh3griuesQ== - dependencies: - "@babel/code-frame" "^7.5.5" - "@babel/generator" "^7.7.7" - "@babel/helpers" "^7.7.4" - "@babel/parser" "^7.7.7" - "@babel/template" "^7.7.4" - "@babel/traverse" "^7.7.4" - "@babel/types" "^7.7.4" + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.8.3.tgz#30b0ebb4dd1585de6923a0b4d179e0b9f5d82941" + integrity sha512-4XFkf8AwyrEG7Ziu3L2L0Cv+WyY47Tcsp70JFmpftbAA1K7YL/sgE9jh9HyNj08Y/U50ItUchpN0w6HxAoX1rA== + dependencies: + "@babel/code-frame" "^7.8.3" + "@babel/generator" "^7.8.3" + "@babel/helpers" "^7.8.3" + "@babel/parser" "^7.8.3" + "@babel/template" "^7.8.3" + "@babel/traverse" "^7.8.3" + "@babel/types" "^7.8.3" convert-source-map "^1.7.0" debug "^4.1.0" + gensync "^1.0.0-beta.1" json5 "^2.1.0" lodash "^4.17.13" resolve "^1.3.2" semver "^5.4.1" source-map "^0.5.0" -"@babel/generator@^7.4.0", "@babel/generator@^7.7.4", "@babel/generator@^7.7.7": - version "7.7.7" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.7.7.tgz#859ac733c44c74148e1a72980a64ec84b85f4f45" - integrity sha512-/AOIBpHh/JU1l0ZFS4kiRCBnLi6OTHzh0RPk3h9isBxkkqELtQNFi1Vr/tiG9p1yfoUdKVwISuXWQR+hwwM4VQ== +"@babel/generator@^7.4.0", "@babel/generator@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.8.3.tgz#0e22c005b0a94c1c74eafe19ef78ce53a4d45c03" + integrity sha512-WjoPk8hRpDRqqzRpvaR8/gDUPkrnOOeuT2m8cNICJtZH6mwaCo3v0OKMI7Y6SM1pBtyijnLtAL0HDi41pf41ug== dependencies: - "@babel/types" "^7.7.4" + "@babel/types" "^7.8.3" jsesc "^2.5.1" lodash "^4.17.13" source-map "^0.5.0" -"@babel/helper-function-name@^7.7.4": - version "7.7.4" - resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.7.4.tgz#ab6e041e7135d436d8f0a3eca15de5b67a341a2e" - integrity sha512-AnkGIdiBhEuiwdoMnKm7jfPfqItZhgRaZfMg1XX3bS25INOnLPjPG1Ppnajh8eqgt5kPJnfqrRHqFqmjKDZLzQ== +"@babel/helper-function-name@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.8.3.tgz#eeeb665a01b1f11068e9fb86ad56a1cb1a824cca" + integrity sha512-BCxgX1BC2hD/oBlIFUgOCQDOPV8nSINxCwM3o93xP4P9Fq6aV5sgv2cOOITDMtCfQ+3PvHp3l689XZvAM9QyOA== dependencies: - "@babel/helper-get-function-arity" "^7.7.4" - "@babel/template" "^7.7.4" - "@babel/types" "^7.7.4" + "@babel/helper-get-function-arity" "^7.8.3" + "@babel/template" "^7.8.3" + "@babel/types" "^7.8.3" -"@babel/helper-get-function-arity@^7.7.4": - version "7.7.4" - resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.7.4.tgz#cb46348d2f8808e632f0ab048172130e636005f0" - integrity sha512-QTGKEdCkjgzgfJ3bAyRwF4yyT3pg+vDgan8DSivq1eS0gwi+KGKE5x8kRcbeFTb/673mkO5SN1IZfmCfA5o+EA== +"@babel/helper-get-function-arity@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.8.3.tgz#b894b947bd004381ce63ea1db9f08547e920abd5" + integrity sha512-FVDR+Gd9iLjUMY1fzE2SR0IuaJToR4RkCDARVfsBBPSP53GEqSFjD8gNyxg246VUyc/ALRxFaAK8rVG7UT7xRA== dependencies: - "@babel/types" "^7.7.4" + "@babel/types" "^7.8.3" -"@babel/helper-plugin-utils@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.0.0.tgz#bbb3fbee98661c569034237cc03967ba99b4f250" - integrity sha512-CYAOUCARwExnEixLdB6sDm2dIJ/YgEAKDM1MOeMeZu9Ld/bDgVo8aiWrXwcY7OBh+1Ea2uUcVRcxKk0GJvW7QA== +"@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.8.0": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.8.3.tgz#9ea293be19babc0f52ff8ca88b34c3611b208670" + integrity sha512-j+fq49Xds2smCUNYmEHF9kGNkhbet6yVIBp4e6oeQpH1RUs/Ir06xUKzDjDkGcaaokPiTNs2JBWHjaE4csUkZQ== -"@babel/helper-split-export-declaration@^7.7.4": - version "7.7.4" - resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.7.4.tgz#57292af60443c4a3622cf74040ddc28e68336fd8" - integrity sha512-guAg1SXFcVr04Guk9eq0S4/rWS++sbmyqosJzVs8+1fH5NI+ZcmkaSkc7dmtAFbHFva6yRJnjW3yAcGxjueDug== +"@babel/helper-split-export-declaration@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.8.3.tgz#31a9f30070f91368a7182cf05f831781065fc7a9" + integrity sha512-3x3yOeyBhW851hroze7ElzdkeRXQYQbFIb7gLK1WQYsw2GWDay5gAJNw1sWJ0VFP6z5J1whqeXH/WCdCjZv6dA== dependencies: - "@babel/types" "^7.7.4" + "@babel/types" "^7.8.3" -"@babel/helpers@^7.7.4": - version "7.7.4" - resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.7.4.tgz#62c215b9e6c712dadc15a9a0dcab76c92a940302" - integrity sha512-ak5NGZGJ6LV85Q1Zc9gn2n+ayXOizryhjSUBTdu5ih1tlVCJeuQENzc4ItyCVhINVXvIT/ZQ4mheGIsfBkpskg== +"@babel/helpers@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.8.3.tgz#382fbb0382ce7c4ce905945ab9641d688336ce85" + integrity sha512-LmU3q9Pah/XyZU89QvBgGt+BCsTPoQa+73RxAQh8fb8qkDyIfeQnmgs+hvzhTCKTzqOyk7JTkS3MS1S8Mq5yrQ== dependencies: - "@babel/template" "^7.7.4" - "@babel/traverse" "^7.7.4" - "@babel/types" "^7.7.4" + "@babel/template" "^7.8.3" + "@babel/traverse" "^7.8.3" + "@babel/types" "^7.8.3" -"@babel/highlight@^7.0.0": - version "7.5.0" - resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.5.0.tgz#56d11312bd9248fa619591d02472be6e8cb32540" - integrity sha512-7dV4eu9gBxoM0dAnj/BCFDW9LFU0zvTrkq0ugM7pnHEgguOEeOz1so2ZghEdzviYzQEED0r4EAgpsBChKy1TRQ== +"@babel/highlight@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.8.3.tgz#28f173d04223eaaa59bc1d439a3836e6d1265797" + integrity sha512-PX4y5xQUvy0fnEVHrYOarRPXVWafSjTW9T0Hab8gVIawpl2Sj0ORyrygANq+KjcNlSSTw0YCLSNA8OyZ1I4yEg== dependencies: chalk "^2.0.0" esutils "^2.0.2" js-tokens "^4.0.0" -"@babel/parser@^7.1.0", "@babel/parser@^7.4.3", "@babel/parser@^7.7.4", "@babel/parser@^7.7.7": - version "7.7.7" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.7.7.tgz#1b886595419cf92d811316d5b715a53ff38b4937" - integrity sha512-WtTZMZAZLbeymhkd/sEaPD8IQyGAhmuTuvTzLiCFM7iXiVdY0gc0IaI+cW0fh1BnSMbJSzXX6/fHllgHKwHhXw== +"@babel/parser@^7.1.0", "@babel/parser@^7.4.3", "@babel/parser@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.8.3.tgz#790874091d2001c9be6ec426c2eed47bc7679081" + integrity sha512-/V72F4Yp/qmHaTALizEm9Gf2eQHV3QyTL3K0cNfijwnMnb1L+LDlAubb/ZnSdGAVzVSWakujHYs1I26x66sMeQ== "@babel/plugin-syntax-object-rest-spread@^7.0.0": - version "7.7.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.7.4.tgz#47cf220d19d6d0d7b154304701f468fc1cc6ff46" - integrity sha512-mObR+r+KZq0XhRVS2BrBKBpr5jqrqzlPvS9C9vuOf5ilSwzloAl7RPWLrgKdWS6IreaVrjHxTjtyqFiOisaCwg== - dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - -"@babel/template@^7.4.0", "@babel/template@^7.7.4": - version "7.7.4" - resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.7.4.tgz#428a7d9eecffe27deac0a98e23bf8e3675d2a77b" - integrity sha512-qUzihgVPguAzXCK7WXw8pqs6cEwi54s3E+HrejlkuWO6ivMKx9hZl3Y2fSXp9i5HgyWmj7RKP+ulaYnKM4yYxw== - dependencies: - "@babel/code-frame" "^7.0.0" - "@babel/parser" "^7.7.4" - "@babel/types" "^7.7.4" - -"@babel/traverse@^7.1.0", "@babel/traverse@^7.4.3", "@babel/traverse@^7.7.4": - version "7.7.4" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.7.4.tgz#9c1e7c60fb679fe4fcfaa42500833333c2058558" - integrity sha512-P1L58hQyupn8+ezVA2z5KBm4/Zr4lCC8dwKCMYzsa5jFMDMQAzaBNy9W5VjB+KAmBjb40U7a/H6ao+Xo+9saIw== - dependencies: - "@babel/code-frame" "^7.5.5" - "@babel/generator" "^7.7.4" - "@babel/helper-function-name" "^7.7.4" - "@babel/helper-split-export-declaration" "^7.7.4" - "@babel/parser" "^7.7.4" - "@babel/types" "^7.7.4" + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz#60e225edcbd98a640332a2e72dd3e66f1af55871" + integrity sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/template@^7.4.0", "@babel/template@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.8.3.tgz#e02ad04fe262a657809327f578056ca15fd4d1b8" + integrity sha512-04m87AcQgAFdvuoyiQ2kgELr2tV8B4fP/xJAVUL3Yb3bkNdMedD3d0rlSQr3PegP0cms3eHjl1F7PWlvWbU8FQ== + dependencies: + "@babel/code-frame" "^7.8.3" + "@babel/parser" "^7.8.3" + "@babel/types" "^7.8.3" + +"@babel/traverse@^7.1.0", "@babel/traverse@^7.4.3", "@babel/traverse@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.8.3.tgz#a826215b011c9b4f73f3a893afbc05151358bf9a" + integrity sha512-we+a2lti+eEImHmEXp7bM9cTxGzxPmBiVJlLVD+FuuQMeeO7RaDbutbgeheDkw+Xe3mCfJHnGOWLswT74m2IPg== + dependencies: + "@babel/code-frame" "^7.8.3" + "@babel/generator" "^7.8.3" + "@babel/helper-function-name" "^7.8.3" + "@babel/helper-split-export-declaration" "^7.8.3" + "@babel/parser" "^7.8.3" + "@babel/types" "^7.8.3" debug "^4.1.0" globals "^11.1.0" lodash "^4.17.13" -"@babel/types@^7.0.0", "@babel/types@^7.3.0", "@babel/types@^7.4.0", "@babel/types@^7.7.4": - version "7.7.4" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.7.4.tgz#516570d539e44ddf308c07569c258ff94fde9193" - integrity sha512-cz5Ji23KCi4T+YIE/BolWosrJuSmoZeN1EFnRtBwF+KKLi8GG/Z2c2hOJJeCXPk4mwk4QFvTmwIodJowXgttRA== +"@babel/types@^7.0.0", "@babel/types@^7.3.0", "@babel/types@^7.4.0", "@babel/types@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.8.3.tgz#5a383dffa5416db1b73dedffd311ffd0788fb31c" + integrity sha512-jBD+G8+LWpMBBWvVcdr4QysjUE4mU/syrhN17o1u3gx0/WzJB1kwiVZAXRtWbsIPOwW8pF/YJV5+nmetPzepXg== dependencies: esutils "^2.0.2" lodash "^4.17.13" @@ -403,9 +404,9 @@ integrity sha512-l42BggppR6zLmpfU6fq9HEa2oGPEI8yrSPL3GITjfRInppYFahObbIQOQK3UGxEnyQpltZLaPe75046NOZQikw== "@types/yargs-parser@*": - version "13.1.0" - resolved "https://registry.yarnpkg.com/@types/yargs-parser/-/yargs-parser-13.1.0.tgz#c563aa192f39350a1d18da36c5a8da382bbd8228" - integrity sha512-gCubfBUZ6KxzoibJ+SCUc/57Ms1jz5NjHe4+dI2krNmU5zCPAphyLJYyTOg06ueIyfj+SaCUqmzun7ImlxDcKg== + version "15.0.0" + resolved "https://registry.yarnpkg.com/@types/yargs-parser/-/yargs-parser-15.0.0.tgz#cb3f9f741869e20cce330ffbeb9271590483882d" + integrity sha512-FA/BWv8t8ZWJ+gEOnLLd8ygxH/2UFbAvgEonyfN6yWGLKc7zVjbpl2Y4CTjid9h2RfgPP6SEt6uHwEOply00yw== "@types/yargs@^13.0.0": version "13.0.5" @@ -674,9 +675,9 @@ aws-sign2@~0.7.0: integrity sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg= aws4@^1.8.0: - version "1.9.0" - resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.9.0.tgz#24390e6ad61386b0a747265754d2a17219de862c" - integrity sha512-Uvq6hVe90D0B2WEnUqtdgY1bATGz3mw33nH9Y+dmA+w5DHvUmBgkr5rM/KCHpCsiFNRUfokW/szpPPgMK2hm4A== + version "1.9.1" + resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.9.1.tgz#7e33d8f7d449b3f673cd72deb9abdc552dbe528e" + integrity sha512-wMHVg2EOHaMRxbzgFJ9gtjOOCrI80OHLG14rxi28XwOW8ux6IiEbRCGGGqCtdAIg4FQCbW20k9RsT4y3gJlFug== babel-jest@^24.9.0: version "24.9.0" @@ -1518,9 +1519,9 @@ diff-sequences@^24.9.0: integrity sha512-Dj6Wk3tWyTE+Fo1rW8v0Xhwk80um6yFYKbuAxc9c3EZxIHFDYwbi34Uk42u1CdnIiVorvt4RmlSDjIPyzGC2ew== diff@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.1.tgz#0c667cb467ebbb5cea7f14f135cc2dba7780a8ff" - integrity sha512-s2+XdvhPCOF01LRQBC8hf4vhbVmI2CGS5aZnxLJlT5FtdhPCDFq80q++zK2KlrVorVDdL5BOGZ/VfLrVtYNF+Q== + version "4.0.2" + resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d" + integrity sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A== dir-glob@^2.0.0: version "2.2.2" @@ -1991,6 +1992,11 @@ gauge@~2.7.3: strip-ansi "^3.0.1" wide-align "^1.1.0" +gensync@^1.0.0-beta.1: + version "1.0.0-beta.1" + resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.1.tgz#58f4361ff987e5ff6e1e7a210827aa371eaac269" + integrity sha512-r8EC6NO1sngH/zdD9fiRDLdcgnbayXah+mLgManTaIZJqEC1MZstmnox8KpnI2/fxQwrp5OpCOYWLp4rBl4Jcg== + get-caller-file@^2.0.1: version "2.0.5" resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" @@ -2189,10 +2195,10 @@ growly@^1.3.0: resolved "https://registry.yarnpkg.com/growly/-/growly-1.3.0.tgz#f10748cbe76af964b7c96c93c6bcc28af120c081" integrity sha1-8QdIy+dq+WS3yWyTxrzCivEgwIE= -handlebars@^4.1.2, handlebars@^4.4.0, handlebars@^4.5.3: - version "4.6.0" - resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.6.0.tgz#33af6c3eda930d7a924f5d8f1c6d8edc3180512e" - integrity sha512-i1ZUP7Qp2JdkMaFon2a+b0m5geE8Z4ZTLaGkgrObkEd+OkUKyRbRWw4KxuFCoHfdETSY1yf9/574eVoNSiK7pw== +handlebars@^4.4.0, handlebars@^4.5.3, handlebars@^4.7.0: + version "4.7.2" + resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.7.2.tgz#01127b3840156a0927058779482031afe0e730d7" + integrity sha512-4PwqDL2laXtTWZghzzCtunQUTLbo31pcCJrd/B/9JP8XbhVzpS5ZXuKqlOzsd1rtcaLo4KqAn8nl8mkknS4MHw== dependencies: neo-async "^2.6.0" optimist "^0.6.1" @@ -2290,6 +2296,11 @@ html-encoding-sniffer@^1.0.2: dependencies: whatwg-encoding "^1.0.1" +html-escaper@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/html-escaper/-/html-escaper-2.0.0.tgz#71e87f931de3fe09e56661ab9a29aadec707b491" + integrity sha512-a4u9BeERWGu/S8JiWEAQcdrg9v4QArtP9keViQjGMdff20fBdd8waotXaNmODqBe6uZ3Nafi7K/ho4gCQHV3Ig== + http-cache-semantics@^4.0.0: version "4.0.3" resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-4.0.3.tgz#495704773277eeef6e43f9ab2c2c7d259dda25c5" @@ -2704,11 +2715,11 @@ istanbul-lib-source-maps@^3.0.1: source-map "^0.6.1" istanbul-reports@^2.2.6: - version "2.2.6" - resolved "https://registry.yarnpkg.com/istanbul-reports/-/istanbul-reports-2.2.6.tgz#7b4f2660d82b29303a8fe6091f8ca4bf058da1af" - integrity sha512-SKi4rnMyLBKe0Jy2uUdx28h8oG7ph2PPuQPvIAh31d+Ci+lSiEu4C+h3oBPuJ9+mPKhOyW0M8gY4U5NM1WLeXA== + version "2.2.7" + resolved "https://registry.yarnpkg.com/istanbul-reports/-/istanbul-reports-2.2.7.tgz#5d939f6237d7b48393cc0959eab40cd4fd056931" + integrity sha512-uu1F/L1o5Y6LzPVSVZXNOoD/KXpJue9aeLRd0sM9uMXfZvzomB0WxVamWb5ue8kA2vVWEmW7EG+A5n3f1kqHKg== dependencies: - handlebars "^4.1.2" + html-escaper "^2.0.0" jest-changed-files@^24.9.0: version "24.9.0" @@ -5360,15 +5371,15 @@ ts-jest@^24.0.2: yargs-parser "10.x" ts-node@^8.5.4: - version "8.5.4" - resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-8.5.4.tgz#a152add11fa19c221d0b48962c210cf467262ab2" - integrity sha512-izbVCRV68EasEPQ8MSIGBNK9dc/4sYJJKYA+IarMQct1RtEot6Xp0bXuClsbUSnKpg50ho+aOAx8en5c+y4OFw== + version "8.6.2" + resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-8.6.2.tgz#7419a01391a818fbafa6f826a33c1a13e9464e35" + integrity sha512-4mZEbofxGqLL2RImpe3zMJukvEvcO1XP8bj8ozBPySdCUXEcU5cIRwR0aM3R+VoZq7iXc8N86NC0FspGRqP4gg== dependencies: arg "^4.1.0" diff "^4.0.1" make-error "^1.1.1" source-map-support "^0.5.6" - yn "^3.0.0" + yn "3.1.1" tslib@1.9.0: version "1.9.0" @@ -5488,13 +5499,13 @@ typedoc-default-themes@^0.6.3: underscore "^1.9.1" typedoc@^0.15.0: - version "0.15.6" - resolved "https://registry.yarnpkg.com/typedoc/-/typedoc-0.15.6.tgz#d99a1c3db8c87a00437a8a89a0df03f9dc1995ad" - integrity sha512-TC3j7HXFfyq0/NyUL9oLgEXhgO4U8Kd7iyRgagkG3XxehgTjn6w20uJ/Hif1KPB/65VQZ8uMYYyxFXNj9um5Ow== + version "0.15.8" + resolved "https://registry.yarnpkg.com/typedoc/-/typedoc-0.15.8.tgz#d83195445a718d173e0d5c73b5581052cb47d4d9" + integrity sha512-a0zypcvfIFsS7Gqpf2MkC1+jNND3K1Om38pbDdy/gYWX01NuJZhC5+O0HkIp0oRIZOo7PWrA5+fC24zkANY28Q== dependencies: "@types/minimatch" "3.0.3" fs-extra "^8.1.0" - handlebars "^4.5.3" + handlebars "^4.7.0" highlight.js "^9.17.1" lodash "^4.17.15" marked "^0.8.0" @@ -5515,9 +5526,9 @@ typescript@~3.6.4: integrity sha512-unoCll1+l+YK4i4F8f22TaNVPRHcD9PA3yCuZ8g5e0qGqlVlJ/8FSateOLLSagn+Yg5+ZwuPkL8LFUc0Jcvksg== uglify-js@^3.1.4: - version "3.7.4" - resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.7.4.tgz#e6d83a1aa32ff448bd1679359ab13d8db0fe0743" - integrity sha512-tinYWE8X1QfCHxS1lBS8yiDekyhSXOO6R66yNOCdUJeojxxw+PX2BHAz/BWyW7PQ7pkiWVxJfIEbiDxyLWvUGg== + version "3.7.5" + resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.7.5.tgz#278c7c24927ac5a32d3336fc68fd4ae1177a486a" + integrity sha512-GFZ3EXRptKGvb/C1Sq6nO1iI7AGcjyqmIyOw0DrD0675e+NNbGO72xmMM2iEBdFbxaTLo70NbjM/Wy54uZIlsg== dependencies: commander "~2.20.3" source-map "~0.6.1" @@ -5943,7 +5954,7 @@ yargs@~1.2.6: dependencies: minimist "^0.1.0" -yn@^3.0.0: +yn@3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/yn/-/yn-3.1.1.tgz#1e87401a09d767c1d5eab26a6e4c185182d2eb50" integrity sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q== From 2f1dd1adf05489ed45cfca748e8e60c70577bac2 Mon Sep 17 00:00:00 2001 From: Julian Waller Date: Wed, 15 Jan 2020 11:42:59 +0000 Subject: [PATCH 65/68] feat: refactor state to be purely interfaces, to allow for better cloning --- package.json | 1 - src/__tests__/tally.spec.ts | 14 +- src/__tests__/util.ts | 32 +-- src/atem.ts | 18 +- .../DownstreamKeyPropertiesCommand.ts | 4 +- .../DownstreamKeySourcesCommand.ts | 4 +- .../DownstreamKeyStateCommand.ts | 6 +- .../Media/MediaPlayerSourceCommand.ts | 4 +- .../Media/MediaPlayerStatusCommand.ts | 4 +- .../Media/MediaPoolClipDescription.ts | 4 +- .../Media/MediaPoolFrameDescription.ts | 4 +- .../FadeToBlack/FadeToBlackRateCommand.ts | 4 +- .../FadeToBlack/FadeToBlackStateCommand.ts | 4 +- .../Key/MixEffectKeyChromaCommand.ts | 6 +- .../MixEffects/Key/MixEffectKeyDVECommand.ts | 6 +- .../Key/MixEffectKeyFlyKeyframeGetCommand.ts | 6 +- .../MixEffectKeyFlyPropertiesGetCommand.ts | 6 +- .../MixEffects/Key/MixEffectKeyLumaCommand.ts | 6 +- .../Key/MixEffectKeyOnAirCommand.ts | 6 +- .../Key/MixEffectKeyPatternCommand.ts | 6 +- .../Key/MixEffectKeyPropertiesGetCommand.ts | 6 +- .../MixEffects/PreviewInputCommand.ts | 4 +- .../MixEffects/ProgramInputCommand.ts | 4 +- .../Transition/TransitionDVECommand.ts | 4 +- .../Transition/TransitionDipCommand.ts | 4 +- .../Transition/TransitionMixCommand.ts | 4 +- .../Transition/TransitionPositionCommand.ts | 4 +- .../Transition/TransitionPreviewCommand.ts | 4 +- .../Transition/TransitionPropertiesCommand.ts | 4 +- .../Transition/TransitionStingerCommand.ts | 4 +- .../Transition/TransitionWipeCommand.ts | 4 +- .../Settings/MultiViewerSourceCommand.ts | 4 +- .../SuperSourceBoxParametersCommand.ts | 6 +- .../SuperSourcePropertiesCommand.ts | 10 +- src/lib/tally.ts | 6 +- src/state/audio.ts | 10 +- src/state/index.ts | 18 +- src/state/info.ts | 24 +-- src/state/macro.ts | 21 +- src/state/media.ts | 43 +--- src/state/settings.ts | 29 +-- src/state/util.ts | 179 ++++++++++++++++ src/state/video/index.ts | 164 +-------------- src/state/video/superSource.ts | 47 +++++ yarn.lock | 198 +----------------- 45 files changed, 384 insertions(+), 566 deletions(-) create mode 100644 src/state/util.ts create mode 100644 src/state/video/superSource.ts diff --git a/package.json b/package.json index e05bc9f39..11c759bd9 100644 --- a/package.json +++ b/package.json @@ -81,7 +81,6 @@ "@types/jest": "^24.0.11", "@types/lolex": "^5.1.0", "@types/node": "^12.7.12", - "class-transformer": "^0.2.3", "codecov": "^3.2.0", "gh-pages": "^2.0.1", "jest": "^24.8.0", diff --git a/src/__tests__/tally.spec.ts b/src/__tests__/tally.spec.ts index 64b5beb86..a9cb22af8 100644 --- a/src/__tests__/tally.spec.ts +++ b/src/__tests__/tally.spec.ts @@ -3,7 +3,8 @@ import { listVisibleInputs } from '../lib/tally' import { readFileSync } from 'fs' import { resolve } from 'path' -import { parseAtemState, createEmptyState } from './util' +import { AtemStateUtil, AtemState } from '../state' +import { createEmptyState } from './util' function readJson (fileName: string) { const filePath = resolve(__dirname, fileName) @@ -12,13 +13,22 @@ function readJson (fileName: string) { } function loadRawState (file: string) { - const loadedState = parseAtemState(readJson(`./tally/${file}-state.json`)) + const loadedState: AtemState = { + ...AtemStateUtil.Create(), + ...readJson(`./tally/${file}-state.json`) + } if (!loadedState.info.capabilities) { const emptyState = createEmptyState() loadedState.info.capabilities = emptyState.info.capabilities } + // Fix up older video states + if (!loadedState.video.mixEffects) { + const videoState = loadedState.video as any + videoState.mixEffects = videoState.ME + } + return loadedState } function loadTally (file: string) { diff --git a/src/__tests__/util.ts b/src/__tests__/util.ts index 61773ae2e..f9d47c329 100644 --- a/src/__tests__/util.ts +++ b/src/__tests__/util.ts @@ -1,35 +1,7 @@ -import { plainToClass } from 'class-transformer' -import { AtemState } from '..' -import { AtemAudioState } from '../state/audio' -import { AtemVideoState, MixEffect, SuperSource } from '../state/video' - -function parseAudio (rawState: AtemAudioState) { - const state = plainToClass(AtemAudioState, rawState) - state.master = state.master - state.channels = state.channels - - return state -} - -function parseVideo (rawState: AtemVideoState) { - return plainToClass(AtemVideoState, { - ...rawState, - ME: rawState.ME.map(me => plainToClass(MixEffect, me)), - superSources: rawState.superSources.map(ssrc => plainToClass(SuperSource, ssrc)) - }) -} - -/** Note: This is incomplete, and should be filled in as needed */ -export function parseAtemState (rawState: any): AtemState { - const state = plainToClass(AtemState, rawState) - state.audio = parseAudio(state.audio) - state.video = parseVideo(state.video) - - return state -} +import { AtemStateUtil } from '../state' export function createEmptyState () { - const state = new AtemState() + const state = AtemStateUtil.Create() // These should be the maximum supported by any device. // But they can also be whatever is needed to allow the tests to run without error diff --git a/src/atem.ts b/src/atem.ts index 8801fd450..525f4a9f9 100644 --- a/src/atem.ts +++ b/src/atem.ts @@ -1,5 +1,5 @@ import { EventEmitter } from 'events' -import { AtemState } from './state' +import { AtemState, AtemStateUtil } from './state' import { AtemSocket } from './lib/atemSocket' import { ISerializableCommand, IDeserializedCommand } from './commands/CommandBase' import * as Commands from './commands' @@ -11,11 +11,9 @@ import { DVETransitionSettings, MixTransitionSettings, StingerTransitionSettings, - SuperSourceBox, + SuperSource, TransitionProperties, - WipeTransitionSettings, - SuperSourceProperties, - SuperSourceBorder + WipeTransitionSettings } from './state/video' import * as USK from './state/video/upstreamKeyers' import { InputChannel } from './state/input' @@ -73,7 +71,7 @@ export class BasicAtem extends EventEmitter { super() this._log = (options && options.externalLog) || ((...args: any[]) => { console.log(...args) }) - this._state = new AtemState() + this._state = AtemStateUtil.Create() this._status = AtemConnectionStatus.CLOSED this.socket = new AtemSocket({ debug: (options || {}).debug || false, @@ -152,7 +150,7 @@ export class BasicAtem extends EventEmitter { // Is this the start of a new connection? if (commands.find(cmd => cmd.constructor.name === Commands.VersionCommand.name)) { // On start of connection, create a new state object - this._state = new AtemState() + this._state = AtemStateUtil.Create() this._status = AtemConnectionStatus.CONNECTING } @@ -400,13 +398,13 @@ export class Atem extends BasicAtem { return this.sendCommand(command) } - public setSuperSourceBoxSettings (newProps: Partial, box: number = 0, ssrcId: number = 0) { + public setSuperSourceBoxSettings (newProps: Partial, box: number = 0, ssrcId: number = 0) { const command = new Commands.SuperSourceBoxParametersCommand(ssrcId, box) command.updateProps(newProps) return this.sendCommand(command) } - public setSuperSourceProperties (newProps: Partial, ssrcId: number = 0) { + public setSuperSourceProperties (newProps: Partial, ssrcId: number = 0) { if (this.state && this.state.info.apiVersion >= Enums.ProtocolVersion.V8_0) { const command = new Commands.SuperSourcePropertiesV8Command(ssrcId) command.updateProps(newProps) @@ -418,7 +416,7 @@ export class Atem extends BasicAtem { } } - public setSuperSourceBorder (newProps: Partial, ssrcId: number = 0) { + public setSuperSourceBorder (newProps: Partial, ssrcId: number = 0) { if (this.state && this.state.info.apiVersion >= Enums.ProtocolVersion.V8_0) { const command = new Commands.SuperSourceBorderCommand(ssrcId) command.updateProps(newProps) diff --git a/src/commands/DownstreamKey/DownstreamKeyPropertiesCommand.ts b/src/commands/DownstreamKey/DownstreamKeyPropertiesCommand.ts index 9e4e4aea9..4128ba837 100644 --- a/src/commands/DownstreamKey/DownstreamKeyPropertiesCommand.ts +++ b/src/commands/DownstreamKey/DownstreamKeyPropertiesCommand.ts @@ -1,5 +1,5 @@ import { DeserializedCommand } from '../CommandBase' -import { AtemState } from '../../state' +import { AtemState, AtemStateUtil } from '../../state' import { DownstreamKeyerProperties } from '../../state/video/downstreamKeyers' export class DownstreamKeyPropertiesCommand extends DeserializedCommand { @@ -41,7 +41,7 @@ export class DownstreamKeyPropertiesCommand extends DeserializedCommand { @@ -28,7 +28,7 @@ export class DownstreamKeySourcesCommand extends DeserializedCommand { public static readonly rawName = 'FtbC' @@ -44,7 +44,7 @@ export class FadeToBlackRateUpdateCommand extends DeserializedCommand<{ rate: nu throw new Error(`MixEffect ${this.mixEffect} is not valid`) } - const mixEffect = state.video.getMe(this.mixEffect) + const mixEffect = AtemStateUtil.getMixEffect(state, this.mixEffect) mixEffect.fadeToBlack = { isFullyBlack: false, inTransition: false, diff --git a/src/commands/MixEffects/FadeToBlack/FadeToBlackStateCommand.ts b/src/commands/MixEffects/FadeToBlack/FadeToBlackStateCommand.ts index fd31bf184..39a0a100e 100644 --- a/src/commands/MixEffects/FadeToBlack/FadeToBlackStateCommand.ts +++ b/src/commands/MixEffects/FadeToBlack/FadeToBlackStateCommand.ts @@ -1,5 +1,5 @@ import { DeserializedCommand } from '../../CommandBase' -import { AtemState } from '../../../state' +import { AtemState, AtemStateUtil } from '../../../state' export interface FadeToBlackProps { isFullyBlack: boolean @@ -34,7 +34,7 @@ export class FadeToBlackStateCommand extends DeserializedCommand { @@ -71,8 +71,8 @@ export class MixEffectKeyChromaUpdateCommand extends DeserializedCommand { @@ -148,8 +148,8 @@ export class MixEffectKeyDVEUpdateCommand extends DeserializedCommand { @@ -64,8 +64,8 @@ export class MixEffectKeyFlyKeyframeGetCommand extends DeserializedCommand { @@ -33,8 +33,8 @@ export class MixEffectKeyFlyPropertiesGetCommand extends DeserializedCommand { @@ -68,8 +68,8 @@ export class MixEffectKeyLumaUpdateCommand extends DeserializedCommand { public static readonly rawName = 'CKOn' @@ -51,8 +51,8 @@ export class MixEffectKeyOnAirUpdateCommand extends DeserializedCommand<{onAir: throw new Error(`UpstreamKeyer ${this.mixEffect}-${this.upstreamKeyerId} is not valid`) } - const mixEffect = state.video.getMe(this.mixEffect) - const upstreamKeyer = mixEffect.getUpstreamKeyer(this.upstreamKeyerId) + const mixEffect = AtemStateUtil.getMixEffect(state, this.mixEffect) + const upstreamKeyer = AtemStateUtil.getUpstreamKeyer(mixEffect, this.upstreamKeyerId) upstreamKeyer.onAir = this.properties.onAir return `video.ME.${this.mixEffect}.upstreamKeyers.${this.upstreamKeyerId}.onAir` } diff --git a/src/commands/MixEffects/Key/MixEffectKeyPatternCommand.ts b/src/commands/MixEffects/Key/MixEffectKeyPatternCommand.ts index f336b8f86..611296235 100644 --- a/src/commands/MixEffects/Key/MixEffectKeyPatternCommand.ts +++ b/src/commands/MixEffects/Key/MixEffectKeyPatternCommand.ts @@ -1,5 +1,5 @@ import { WritableCommand, DeserializedCommand } from '../../CommandBase' -import { AtemState } from '../../../state' +import { AtemState, AtemStateUtil } from '../../../state' import { UpstreamKeyerPatternSettings } from '../../../state/video/upstreamKeyers' export class MixEffectKeyPatternCommand extends WritableCommand { @@ -78,8 +78,8 @@ export class MixEffectKeyUpdateCommand extends DeserializedCommand { @@ -40,9 +40,9 @@ export class MixEffectKeyPropertiesGetCommand extends DeserializedCommand throw new Error(`MixEffect ${this.mixEffect} is not valid`) } - const mixEffect = state.video.getMe(this.mixEffect) + const mixEffect = AtemStateUtil.getMixEffect(state, this.mixEffect) mixEffect.previewInput = this.properties.source return `video.ME.${this.mixEffect}.previewInput` } diff --git a/src/commands/MixEffects/ProgramInputCommand.ts b/src/commands/MixEffects/ProgramInputCommand.ts index a9a7aee2e..848d07ec6 100644 --- a/src/commands/MixEffects/ProgramInputCommand.ts +++ b/src/commands/MixEffects/ProgramInputCommand.ts @@ -1,5 +1,5 @@ import { BasicWritableCommand, DeserializedCommand } from '../CommandBase' -import { AtemState } from '../../state' +import { AtemState, AtemStateUtil } from '../../state' import { InputSource } from './PreviewInputCommand' export class ProgramInputCommand extends BasicWritableCommand { @@ -46,7 +46,7 @@ export class ProgramInputUpdateCommand extends DeserializedCommand throw new Error(`MixEffect ${this.mixEffect} is not valid`) } - const mixEffect = state.video.getMe(this.mixEffect) + const mixEffect = AtemStateUtil.getMixEffect(state, this.mixEffect) mixEffect.programInput = this.properties.source return `video.ME.${this.mixEffect}.programInput` } diff --git a/src/commands/MixEffects/Transition/TransitionDVECommand.ts b/src/commands/MixEffects/Transition/TransitionDVECommand.ts index 97d0337b3..254ce154b 100644 --- a/src/commands/MixEffects/Transition/TransitionDVECommand.ts +++ b/src/commands/MixEffects/Transition/TransitionDVECommand.ts @@ -1,5 +1,5 @@ import { WritableCommand, DeserializedCommand } from '../../CommandBase' -import { AtemState } from '../../../state' +import { AtemState, AtemStateUtil } from '../../../state' import { DVETransitionSettings } from '../../../state/video' export class TransitionDVECommand extends WritableCommand { @@ -91,7 +91,7 @@ export class TransitionDVEUpdateCommand extends DeserializedCommand { @@ -53,7 +53,7 @@ export class TransitionDipUpdateCommand extends DeserializedCommand { @@ -46,7 +46,7 @@ export class TransitionMixUpdateCommand extends DeserializedCommand { @@ -58,7 +58,7 @@ export class TransitionPropertiesUpdateCommand extends DeserializedCommand { @@ -81,7 +81,7 @@ export class TransitionStingerUpdateCommand extends DeserializedCommand { @@ -82,7 +82,7 @@ export class TransitionWipeUpdateCommand extends DeserializedCommand { @@ -48,7 +48,7 @@ export class MultiViewerSourceUpdateCommand extends DeserializedCommand { @@ -98,7 +98,7 @@ export class SuperSourceBoxParametersUpdateCommand extends DeserializedCommand { @@ -195,7 +195,7 @@ export class SuperSourcePropertiesUpdateCommand extends DeserializedCommand<{ pr throw new Error(`SuperSource 0 is not valid`) } - const supersource = state.video.getSuperSource(0) + const supersource = AtemStateUtil.getSuperSource(state, 0) supersource.properties = this.properties.properties supersource.border = this.properties.border return [ @@ -237,7 +237,7 @@ export class SuperSourcePropertiesUpdateV8Command extends DeserializedCommand { if (box && box.enabled) { inputs.add(box.source) @@ -75,7 +75,7 @@ export function listVisibleInputs (mode: 'program' | 'preview', state: AtemState */ function _calcActiveMeInputs (mode: 'program' | 'preview', state: AtemState, meId: number): number[] { const inputs = new Set() - const meRef = state.video.getMe(meId) + const meRef = AtemStateUtil.getMixEffect(state, meId) if (mode === 'preview') { if (meRef.transitionProperties.selection & 1) { diff --git a/src/state/audio.ts b/src/state/audio.ts index 6f0fb1ae8..2e130f4d6 100644 --- a/src/state/audio.ts +++ b/src/state/audio.ts @@ -18,9 +18,9 @@ export interface AudioMasterChannel { followFadeToBlack: boolean } -export class AtemAudioState { - public numberOfChannels?: number - public hasMonitor?: boolean - public channels: { [channelId: number]: AudioChannel | undefined } = {} - public master?: AudioMasterChannel +export interface AtemAudioState { + numberOfChannels?: number + hasMonitor?: boolean + channels: { [channelId: number]: AudioChannel | undefined } + master?: AudioMasterChannel } diff --git a/src/state/index.ts b/src/state/index.ts index 9dd4b4c28..e52cb89b4 100644 --- a/src/state/index.ts +++ b/src/state/index.ts @@ -6,12 +6,14 @@ import { InputChannel } from './input' import { MacroState } from './macro' import { SettingsState } from './settings' -export class AtemState { - public info = new DeviceInfo() - public video: AtemVideoState = new AtemVideoState() - public audio: AtemAudioState = new AtemAudioState() - public media: MediaState = new MediaState() - public inputs: { [inputId: number]: InputChannel | undefined } = {} - public macro: MacroState = new MacroState() - public settings: SettingsState = new SettingsState() +export { AtemStateUtil } from './util' + +export interface AtemState { + info: DeviceInfo + video: AtemVideoState + audio: AtemAudioState + media: MediaState + inputs: { [inputId: number]: InputChannel | undefined } + macro: MacroState + settings: SettingsState } diff --git a/src/state/info.ts b/src/state/info.ts index cd1551be2..441dd70bb 100644 --- a/src/state/info.ts +++ b/src/state/info.ts @@ -44,16 +44,16 @@ export interface MultiviewerInfo { readonly windowCount: number } -export class DeviceInfo { - public apiVersion: ProtocolVersion = 0 - public capabilities?: AtemCapabilites - public model: Model = Model.Unknown - public productIdentifier?: string - public superSources: Array = [] - public mixEffects: Array = [] - public power: boolean[] = [] - public audioMixer?: AudioMixerInfo - public macroPool?: MacroPoolInfo - public mediaPool?: MediaPoolInfo - public multiviewer?: MultiviewerInfo +export interface DeviceInfo { + apiVersion: ProtocolVersion + capabilities?: AtemCapabilites + model: Model + productIdentifier?: string + superSources: Array + mixEffects: Array + power: boolean[] + audioMixer?: AudioMixerInfo + macroPool?: MacroPoolInfo + mediaPool?: MediaPoolInfo + multiviewer?: MultiviewerInfo } diff --git a/src/state/macro.ts b/src/state/macro.ts index 7c9e26811..429c409f6 100644 --- a/src/state/macro.ts +++ b/src/state/macro.ts @@ -17,21 +17,8 @@ export interface MacroPropertiesState { name: string } -export class MacroState { - public macroPlayer: MacroPlayerState - public macroRecorder: MacroRecorderState - public readonly macroProperties: Array = [] - - constructor () { - this.macroPlayer = { - isRunning: false, - isWaiting: false, - loop: false, - macroIndex: 0 - } - this.macroRecorder = { - isRecording: false, - macroIndex: 0 - } - } +export interface MacroState { + macroPlayer: MacroPlayerState + macroRecorder: MacroRecorderState + readonly macroProperties: Array } diff --git a/src/state/media.ts b/src/state/media.ts index 0dee9858d..9f3780ff3 100644 --- a/src/state/media.ts +++ b/src/state/media.ts @@ -15,45 +15,10 @@ export interface MediaPlayerSource { export type MediaPlayerState = MediaPlayer & MediaPlayerSource -export class MediaState { - public readonly stillPool: Array = [] - public readonly clipPool: Array = [] - public readonly players: Array = [] - - public getMediaPlayer (index: number, dontCreate?: boolean): MediaPlayerState { - let player = this.players[index] - if (!player) { - player = { - playing: false, - loop: false, - atBeginning: false, - clipFrame: 0, - sourceType: Enums.MediaSourceType.Clip, - clipIndex: 0, - stillIndex: 0 - } - - if (!dontCreate) { - this.players[index] = player - } - } - - return player - } - - public getClip (index: number): ClipBank { - const clip = this.clipPool[index] - if (!clip) { - return this.clipPool[index] = { - isUsed: false, - name: '', - frameCount: 0, - frames: [] - } - } - - return clip - } +export interface MediaState { + readonly stillPool: Array + readonly clipPool: Array + readonly players: Array } export interface StillFrame { diff --git a/src/state/settings.ts b/src/state/settings.ts index fff3cfc5a..7998f4e24 100644 --- a/src/state/settings.ts +++ b/src/state/settings.ts @@ -11,29 +11,12 @@ export interface MultiViewerWindowState extends MultiViewerSourceState { // TODO - supports safeTitle & audioMeter? } -export class MultiViewer { - public readonly index: number - public readonly windows: Array = [] - - constructor (index: number) { - this.index = index - } +export interface MultiViewer { + readonly index: number + readonly windows: Array } -export class SettingsState { - public readonly multiViewers: Array = [] - public videoMode: VideoMode - - constructor () { - this.videoMode = 0 - } - - public getMultiViewer (index: number): MultiViewer { - const multiViewer = this.multiViewers[index] - if (!multiViewer) { - return this.multiViewers[index] = new MultiViewer(index) - } - - return multiViewer - } +export interface SettingsState { + readonly multiViewers: Array + videoMode: VideoMode } diff --git a/src/state/util.ts b/src/state/util.ts new file mode 100644 index 000000000..d5fd276c1 --- /dev/null +++ b/src/state/util.ts @@ -0,0 +1,179 @@ +import { AtemState } from '.' +import * as Enums from '../enums' +import { MultiViewer } from './settings' +import { MediaPlayerState, ClipBank } from './media' +import { MixEffect, SuperSource, DSK, USK } from './video' + +export namespace AtemStateUtil { + export function Create (): AtemState { + return { + info: { + apiVersion: 0, + model: Enums.Model.Unknown, + superSources: [], + mixEffects: [], + power: [] + }, + video: { + mixEffects: [], + downstreamKeyers: [], + auxilliaries: [], + superSources: [] + }, + audio: { + channels: {} + }, + media: { + stillPool: [], + clipPool: [], + players: [] + }, + inputs: {}, + macro: { + macroPlayer: { + isRunning: false, + isWaiting: false, + loop: false, + macroIndex: 0 + }, + macroRecorder: { + isRecording: false, + macroIndex: 0 + }, + macroProperties: [] + }, + settings: { + multiViewers: [], + videoMode: 0 + } + } + } + + export function getMultiViewer (state: AtemState, index: number): MultiViewer { + const multiViewer = state.settings.multiViewers[index] + if (!multiViewer) { + return state.settings.multiViewers[index] = { index, windows: [] } + } + + return multiViewer + } + + export function getMediaPlayer (state: AtemState, index: number, dontCreate?: boolean): MediaPlayerState { + let player = state.media.players[index] + if (!player) { + player = { + playing: false, + loop: false, + atBeginning: false, + clipFrame: 0, + sourceType: Enums.MediaSourceType.Clip, + clipIndex: 0, + stillIndex: 0 + } + + if (!dontCreate) { + state.media.players[index] = player + } + } + + return player + } + + export function getClip (state: AtemState, index: number): ClipBank { + const clip = state.media.clipPool[index] + if (!clip) { + return state.media.clipPool[index] = { + isUsed: false, + name: '', + frameCount: 0, + frames: [] + } + } + + return clip + } + + export function getMixEffect (state: AtemState, index: number, dontCreate?: boolean): MixEffect { + let me = state.video.mixEffects[index] + if (!me) { + me = { + index, + programInput: 0, + previewInput: 0, + inTransition: false, + transitionPreview: false, + transitionPosition: 0, + transitionFramesLeft: 0, + transitionProperties: { + style: Enums.TransitionStyle.MIX, + selection: 1, + nextStyle: Enums.TransitionStyle.MIX, + nextSelection: 1 + }, + transitionSettings: {}, + upstreamKeyers: [] + } + + if (!dontCreate) { + state.video.mixEffects[index] = me + } + } + + return me + } + + export function getSuperSource (state: AtemState, index: number, dontCreate?: boolean): SuperSource.SuperSource { + let ssrc = state.video.superSources[index] + if (!ssrc) { + ssrc = { + index, + boxes: [ undefined, undefined, undefined, undefined ] + } + + if (!dontCreate) { + state.video.superSources[index] = ssrc + } + } + + return ssrc + } + + export function getDownstreamKeyer (state: AtemState, index: number, dontCreate?: boolean): DSK.DownstreamKeyer { + let dsk = state.video.downstreamKeyers[index] + if (!dsk) { + dsk = { + isAuto: false, + remainingFrames: 0, + onAir: false, + inTransition: false + } + + if (!dontCreate) { + state.video.downstreamKeyers[index] = dsk + } + } + + return dsk + } + + export function getUpstreamKeyer (mixEffect: MixEffect, index: number, dontCreate?: boolean): USK.UpstreamKeyer { + let usk = mixEffect.upstreamKeyers[index] + if (!usk) { + usk = { + upstreamKeyerId: index, + mixEffectKeyType: 0, + cutSource: 0, + fillSource: 0, + onAir: false, + flyEnabled: false, + flyKeyframes: [undefined, undefined] + } + + if (!dontCreate) { + mixEffect.upstreamKeyers[index] = usk + } + } + + return usk + } +} diff --git a/src/state/video/index.ts b/src/state/video/index.ts index 1c0c40413..7f1305eae 100644 --- a/src/state/video/index.ts +++ b/src/state/video/index.ts @@ -1,8 +1,9 @@ import * as Enum from '../../enums' import * as USK from './upstreamKeyers' import * as DSK from './downstreamKeyers' +import * as SuperSource from './superSource' -export { USK, DSK } +export { USK, DSK, SuperSource } export interface DipTransitionSettings { rate: number @@ -71,7 +72,8 @@ export interface TransitionSettings { wipe?: WipeTransitionSettings } -export interface IMixEffect { +export interface MixEffect { + readonly index: number programInput: number previewInput: number inTransition: boolean @@ -79,111 +81,9 @@ export interface IMixEffect { transitionPosition: number transitionFramesLeft: number fadeToBlack?: FadeToBlackProperties - numberOfKeyers: number transitionProperties: TransitionProperties transitionSettings: TransitionSettings - upstreamKeyers: Array -} - -export class MixEffect implements IMixEffect { - public readonly index: number - public programInput: number = 0 - public previewInput: number = 0 - public inTransition: boolean = false - public transitionPreview: boolean = false - public transitionPosition: number = 0 - public transitionFramesLeft: number = 0 - public fadeToBlack?: FadeToBlackProperties - public numberOfKeyers: number = 0 - public transitionProperties: TransitionProperties - public transitionSettings: TransitionSettings = {} - public readonly upstreamKeyers: Array = [] - - constructor (index: number) { - this.index = index - - this.transitionProperties = { - style: Enum.TransitionStyle.MIX, - selection: 1, - nextStyle: Enum.TransitionStyle.MIX, - nextSelection: 1 - } - } - - public getUpstreamKeyer (index: number, dontCreate?: boolean): USK.UpstreamKeyer { - let usk = this.upstreamKeyers[index] - if (!usk) { - usk = { - upstreamKeyerId: index, - mixEffectKeyType: 0, - cutSource: 0, - fillSource: 0, - onAir: false, - flyEnabled: false, - flyKeyframes: [undefined, undefined] - } - - if (!dontCreate) { - this.upstreamKeyers[index] = usk - } - } - - return usk - } -} - -export interface SuperSourceBox { - enabled: boolean - source: number - x: number - y: number - size: number - cropped: boolean - cropTop: number - cropBottom: number - cropLeft: number - cropRight: number -} - -export interface SuperSourceProperties { - artFillSource: number - artCutSource: number - artOption: Enum.SuperSourceArtOption - artPreMultiplied: boolean - artClip: number - artGain: number - artInvertKey: boolean -} - -export interface SuperSourceBorder { - borderEnabled: boolean - borderBevel: Enum.BorderBevel - borderOuterWidth: number - borderInnerWidth: number - borderOuterSoftness: number - borderInnerSoftness: number - borderBevelSoftness: number - borderBevelPosition: number - borderHue: number - borderSaturation: number - borderLuma: number - borderLightSourceDirection: number - borderLightSourceAltitude: number -} - -export class SuperSource { - public readonly index: number - public readonly boxes: [SuperSourceBox | undefined, SuperSourceBox | undefined, SuperSourceBox | undefined, SuperSourceBox | undefined] - public properties?: SuperSourceProperties - public border?: SuperSourceBorder - - constructor (index: number) { - this.index = index - - this.boxes = [ - undefined, undefined, undefined, undefined - ] - } + readonly upstreamKeyers: Array } export interface FadeToBlackProperties { @@ -193,53 +93,9 @@ export interface FadeToBlackProperties { remainingFrames: number } -export class AtemVideoState { - public readonly ME: Array = [] - public readonly downstreamKeyers: Array = [] - public readonly auxilliaries: Array = [] - public readonly superSources: Array = [] - - public getMe (index: number, dontCreate?: boolean): MixEffect { - let me = this.ME[index] - if (!me) { - me = new MixEffect(index) - - if (!dontCreate) { - this.ME[index] = me - } - } - - return me - } - - public getSuperSource (index: number, dontCreate?: boolean): SuperSource { - let ssrc = this.superSources[index] - if (!ssrc) { - ssrc = new SuperSource(index) - - if (!dontCreate) { - this.superSources[index] = ssrc - } - } - - return ssrc - } - - public getDownstreamKeyer (index: number, dontCreate?: boolean): DSK.DownstreamKeyer { - let dsk = this.downstreamKeyers[index] - if (!dsk) { - dsk = { - isAuto: false, - remainingFrames: 0, - onAir: false, - inTransition: false - } - - if (!dontCreate) { - this.downstreamKeyers[index] = dsk - } - } - - return dsk - } +export interface AtemVideoState { + readonly mixEffects: Array + readonly downstreamKeyers: Array + readonly auxilliaries: Array + readonly superSources: Array } diff --git a/src/state/video/superSource.ts b/src/state/video/superSource.ts new file mode 100644 index 000000000..6e1b9523c --- /dev/null +++ b/src/state/video/superSource.ts @@ -0,0 +1,47 @@ +import * as Enum from '../../enums' + +export interface SuperSourceBox { + enabled: boolean + source: number + x: number + y: number + size: number + cropped: boolean + cropTop: number + cropBottom: number + cropLeft: number + cropRight: number +} + +export interface SuperSourceProperties { + artFillSource: number + artCutSource: number + artOption: Enum.SuperSourceArtOption + artPreMultiplied: boolean + artClip: number + artGain: number + artInvertKey: boolean +} + +export interface SuperSourceBorder { + borderEnabled: boolean + borderBevel: Enum.BorderBevel + borderOuterWidth: number + borderInnerWidth: number + borderOuterSoftness: number + borderInnerSoftness: number + borderBevelSoftness: number + borderBevelPosition: number + borderHue: number + borderSaturation: number + borderLuma: number + borderLightSourceDirection: number + borderLightSourceAltitude: number +} + +export interface SuperSource { + readonly index: number + readonly boxes: [SuperSourceBox | undefined, SuperSourceBox | undefined, SuperSourceBox | undefined, SuperSourceBox | undefined] + properties?: SuperSourceProperties + border?: SuperSourceBorder +} diff --git a/yarn.lock b/yarn.lock index 1cd8cd519..4457decfd 100644 --- a/yarn.lock +++ b/yarn.lock @@ -428,11 +428,6 @@ abab@^2.0.0: resolved "https://registry.yarnpkg.com/abab/-/abab-2.0.3.tgz#623e2075e02eb2d3f2475e49f99c91846467907a" integrity sha512-tsFzPpcttalNjFBCFMqsKYQcWxxen1pgJR56by//QwvJc4/OUS3kPOOttx2tSIfjsylB0pYu7f5D3K1RCxUnUg== -abbrev@1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" - integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q== - acorn-globals@^4.1.0: version "4.3.4" resolved "https://registry.yarnpkg.com/acorn-globals/-/acorn-globals-4.3.4.tgz#9fa1926addc11c97308c4e66d7add0d40c3272e7" @@ -533,24 +528,11 @@ anymatch@^2.0.0: micromatch "^3.1.4" normalize-path "^2.1.1" -aproba@^1.0.3: - version "1.2.0" - resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.2.0.tgz#6802e6264efd18c790a1b0d517f0f2627bf2c94a" - integrity sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw== - archy@1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/archy/-/archy-1.0.0.tgz#f9c8c13757cc1dd7bc379ac77b2c62a5c2868c40" integrity sha1-+cjBN1fMHde8N5rHeyxipcKGjEA= -are-we-there-yet@~1.1.2: - version "1.1.5" - resolved "https://registry.yarnpkg.com/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz#4b35c2944f062a8bfcda66410760350fe9ddfc21" - integrity sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w== - dependencies: - delegates "^1.0.0" - readable-stream "^2.0.6" - arg@^4.1.0: version "4.1.2" resolved "https://registry.yarnpkg.com/arg/-/arg-4.1.2.tgz#e70c90579e02c63d80e3ad4e31d8bfdb8bd50064" @@ -937,21 +919,11 @@ chalk@2.4.2, chalk@^2.0.0, chalk@^2.0.1, chalk@^2.3.0, chalk@^2.4.2: escape-string-regexp "^1.0.5" supports-color "^5.3.0" -chownr@^1.1.1: - version "1.1.3" - resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.3.tgz#42d837d5239688d55f303003a508230fa6727142" - integrity sha512-i70fVHhmV3DtTl6nqvZOnIjbY0Pe4kAUjwHj8z0zAdgBtYrJyYwLKCCuRBQ5ppkyL0AkN7HKRnETdmdp1zqNXw== - ci-info@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-2.0.0.tgz#67a9e964be31a51e15e5010d58e6f12834002f46" integrity sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ== -class-transformer@^0.2.3: - version "0.2.3" - resolved "https://registry.yarnpkg.com/class-transformer/-/class-transformer-0.2.3.tgz#598c92ca71dcca73f91ccb875d74a3847ccfa32d" - integrity sha512-qsP+0xoavpOlJHuYsQJsN58HXSl8Jvveo+T37rEvCEeRfMWoytAyR0Ua/YsFgpM6AZYZ/og2PJwArwzJl1aXtQ== - class-utils@^0.3.5: version "0.3.6" resolved "https://registry.yarnpkg.com/class-utils/-/class-utils-0.3.6.tgz#f93369ae8b9a7ce02fd41faad0ca83033190c463" @@ -1102,11 +1074,6 @@ configstore@^4.0.0: write-file-atomic "^2.0.0" xdg-basedir "^3.0.0" -console-control-strings@^1.0.0, console-control-strings@~1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e" - integrity sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4= - conventional-changelog-angular@^5.0.5: version "5.0.6" resolved "https://registry.yarnpkg.com/conventional-changelog-angular/-/conventional-changelog-angular-5.0.6.tgz#269540c624553aded809c29a3508fdc2b544c059" @@ -1387,7 +1354,7 @@ debug@^2.2.0, debug@^2.3.3: dependencies: ms "2.0.0" -debug@^3.1.0, debug@^3.2.6: +debug@^3.1.0: version "3.2.6" resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.6.tgz#e83d17de16d8a7efb7717edbe5fb10135eee629b" integrity sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ== @@ -1480,21 +1447,11 @@ delayed-stream@~1.0.0: resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" integrity sha1-3zrhmayt+31ECqrgsp4icrJOxhk= -delegates@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a" - integrity sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o= - detect-indent@6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/detect-indent/-/detect-indent-6.0.0.tgz#0abd0f549f69fc6659a254fe96786186b6f528fd" integrity sha512-oSyFlqaTHCItVRGK5RmrmjB+CmaMOW7IaNA/kdxqhoa6d17j/5ce9O9eWXmV/KEdRwqpQA+Vqe8a8Bsybu4YnA== -detect-libc@^1.0.2: - version "1.0.3" - resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-1.0.3.tgz#fa137c4bd698edf55cd5cd02ac559f91a4c4ba9b" - integrity sha1-+hN8S9aY7fVc1c0CrFWfkaTEups= - detect-newline@3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/detect-newline/-/detect-newline-3.0.0.tgz#8ae477c089e51872c264531cd6547719c0b86b2f" @@ -1953,13 +1910,6 @@ fs-extra@^8.1.0: jsonfile "^4.0.0" universalify "^0.1.0" -fs-minipass@^1.2.5: - version "1.2.7" - resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-1.2.7.tgz#ccff8570841e7fe4265693da88936c55aed7f7c7" - integrity sha512-GWSSJGFy4e9GUeCcbIkED+bgAoFyj7XF1mV8rma3QW4NIqX9Kyx79N/PF61H5udOV3aY1IaMLs6pGbH71nlCTA== - dependencies: - minipass "^2.6.0" - fs.realpath@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" @@ -1978,20 +1928,6 @@ function-bind@^1.1.1: resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== -gauge@~2.7.3: - version "2.7.4" - resolved "https://registry.yarnpkg.com/gauge/-/gauge-2.7.4.tgz#2c03405c7538c39d7eb37b317022e325fb018bf7" - integrity sha1-LANAXHU4w51+s3sxcCLjJfsBi/c= - dependencies: - aproba "^1.0.3" - console-control-strings "^1.0.0" - has-unicode "^2.0.0" - object-assign "^4.1.0" - signal-exit "^3.0.0" - string-width "^1.0.1" - strip-ansi "^3.0.1" - wide-align "^1.1.0" - gensync@^1.0.0-beta.1: version "1.0.0-beta.1" resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.1.tgz#58f4361ff987e5ff6e1e7a210827aa371eaac269" @@ -2229,11 +2165,6 @@ has-symbols@^1.0.0, has-symbols@^1.0.1: resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.1.tgz#9f5214758a44196c406d9bd76cebf81ec2dd31e8" integrity sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg== -has-unicode@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9" - integrity sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk= - has-value@^0.3.1: version "0.3.1" resolved "https://registry.yarnpkg.com/has-value/-/has-value-0.3.1.tgz#7b1f58bada62ca827ec0a2078025654845995e1f" @@ -2331,7 +2262,7 @@ humanize-url@^1.0.0: normalize-url "^1.0.0" strip-url-auth "^1.0.0" -iconv-lite@0.4.24, iconv-lite@^0.4.4: +iconv-lite@0.4.24: version "0.4.24" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== @@ -3592,21 +3523,6 @@ minimist@~0.0.1: resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.10.tgz#de3f98543dbf96082be48ad1a0c7cda836301dcf" integrity sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8= -minipass@^2.6.0, minipass@^2.8.6, minipass@^2.9.0: - version "2.9.0" - resolved "https://registry.yarnpkg.com/minipass/-/minipass-2.9.0.tgz#e713762e7d3e32fed803115cf93e04bca9fcc9a6" - integrity sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg== - dependencies: - safe-buffer "^5.1.2" - yallist "^3.0.0" - -minizlib@^1.2.1: - version "1.3.3" - resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-1.3.3.tgz#2290de96818a34c29551c8a8d301216bd65a861d" - integrity sha512-6ZYMOEnmVsdCeTJVE0W9ZD+pVnE8h9Hma/iOwwRDsdQoePpoX56/8B6z3P9VNwppJuBKNRuFDRNRqRWexT9G9Q== - dependencies: - minipass "^2.9.0" - mixin-deep@^1.2.0: version "1.3.2" resolved "https://registry.yarnpkg.com/mixin-deep/-/mixin-deep-1.3.2.tgz#1120b43dc359a785dce65b55b82e257ccf479566" @@ -3615,7 +3531,7 @@ mixin-deep@^1.2.0: for-in "^1.0.2" is-extendable "^1.0.1" -mkdirp@0.x, mkdirp@^0.5.0, mkdirp@^0.5.1: +mkdirp@0.x, mkdirp@^0.5.1: version "0.5.1" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" integrity sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM= @@ -3687,15 +3603,6 @@ natural-compare@^1.4.0: resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" integrity sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc= -needle@^2.2.1: - version "2.4.0" - resolved "https://registry.yarnpkg.com/needle/-/needle-2.4.0.tgz#6833e74975c444642590e15a750288c5f939b57c" - integrity sha512-4Hnwzr3mi5L97hMYeNl8wRW/Onhy4nUKR/lVemJ8gJedxxUyBLm9kkrDColJvoSfwi0jCNhD+xCdOtiGDQiRZg== - dependencies: - debug "^3.2.6" - iconv-lite "^0.4.4" - sax "^1.2.4" - neo-async@^2.6.0: version "2.6.1" resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.1.tgz#ac27ada66167fa8849a6addd837f6b189ad2081c" @@ -3760,30 +3667,6 @@ node-notifier@^5.4.2: shellwords "^0.1.1" which "^1.3.0" -node-pre-gyp@*: - version "0.14.0" - resolved "https://registry.yarnpkg.com/node-pre-gyp/-/node-pre-gyp-0.14.0.tgz#9a0596533b877289bcad4e143982ca3d904ddc83" - integrity sha512-+CvDC7ZttU/sSt9rFjix/P05iS43qHCOOGzcr3Ry99bXG7VX953+vFyEuph/tfqoYu8dttBkE86JSKBO2OzcxA== - dependencies: - detect-libc "^1.0.2" - mkdirp "^0.5.1" - needle "^2.2.1" - nopt "^4.0.1" - npm-packlist "^1.1.6" - npmlog "^4.0.2" - rc "^1.2.7" - rimraf "^2.6.1" - semver "^5.3.0" - tar "^4.4.2" - -nopt@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/nopt/-/nopt-4.0.1.tgz#d0d4685afd5415193c8c7505602d0d17cd64474d" - integrity sha1-0NRoWv1UFRk8jHUFYC0NF81kR00= - dependencies: - abbrev "1" - osenv "^0.1.4" - normalize-package-data@^2.0.0, normalize-package-data@^2.3.0, normalize-package-data@^2.3.2, normalize-package-data@^2.3.4, normalize-package-data@^2.3.5: version "2.5.0" resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.5.0.tgz#e66db1838b200c1dfc233225d12cb36520e234a8" @@ -3816,14 +3699,7 @@ normalize-url@^4.1.0: resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-4.5.0.tgz#453354087e6ca96957bd8f5baf753f5982142129" integrity sha512-2s47yzUxdexf1OhyRi4Em83iQk0aPvwTddtFz4hnSSw9dCEsLEGf6SwIO8ss/19S9iBb5sJaOuTvTGDeZI00BQ== -npm-bundled@^1.0.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/npm-bundled/-/npm-bundled-1.1.1.tgz#1edd570865a94cdb1bc8220775e29466c9fb234b" - integrity sha512-gqkfgGePhTpAEgUsGEgcq1rqPXA+tv/aVBlgEzfXwA1yiUJF7xtEt3CtVwOjNYQOVknDk0F20w58Fnm3EtG0fA== - dependencies: - npm-normalize-package-bin "^1.0.1" - -npm-normalize-package-bin@^1.0.0, npm-normalize-package-bin@^1.0.1: +npm-normalize-package-bin@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/npm-normalize-package-bin/-/npm-normalize-package-bin-1.0.1.tgz#6e79a41f23fd235c0623218228da7d9c23b8f6e2" integrity sha512-EPfafl6JL5/rU+ot6P3gRSCpPDW5VmIzX959Ob1+ySFUuuYHWHekXpwdUZcKP5C+DS4GEtdJluwBjnsNDl+fSA== @@ -3836,14 +3712,6 @@ npm-package-arg@^4.2.0: hosted-git-info "^2.1.5" semver "^5.1.0" -npm-packlist@^1.1.6: - version "1.4.7" - resolved "https://registry.yarnpkg.com/npm-packlist/-/npm-packlist-1.4.7.tgz#9e954365a06b80b18111ea900945af4f88ed4848" - integrity sha512-vAj7dIkp5NhieaGZxBJB8fF4R0078rqsmhJcAfXZ6O7JJhjhPK96n5Ry1oZcfLXgfun0GWTZPOxaEyqv8GBykQ== - dependencies: - ignore-walk "^3.0.1" - npm-bundled "^1.0.1" - npm-run-path@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-1.0.0.tgz#f5c32bf595fe81ae927daec52e82f8b000ac3c8f" @@ -3867,16 +3735,6 @@ npm-scripts-info@0.3.9: meow "^4.0.0" unquote "^1.1.0" -npmlog@^4.0.2: - version "4.1.2" - resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-4.1.2.tgz#08a7f2a8bf734604779a9efa4ad5cc717abb954b" - integrity sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg== - dependencies: - are-we-there-yet "~1.1.2" - console-control-strings "~1.1.0" - gauge "~2.7.3" - set-blocking "~2.0.0" - null-check@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/null-check/-/null-check-1.0.0.tgz#977dffd7176012b9ec30d2a39db5cf72a0439edd" @@ -4010,19 +3868,6 @@ os-locale@^1.4.0: dependencies: lcid "^1.0.0" -os-tmpdir@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" - integrity sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ= - -osenv@^0.1.4: - version "0.1.5" - resolved "https://registry.yarnpkg.com/osenv/-/osenv-0.1.5.tgz#85cdfafaeb28e8677f416e287592b5f3f49ea410" - integrity sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g== - dependencies: - os-homedir "^1.0.0" - os-tmpdir "^1.0.0" - p-cancelable@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-1.1.0.tgz#d078d15a3af409220c886f1d9a0ca2e441ab26cc" @@ -4353,7 +4198,7 @@ quick-lru@^1.0.0: resolved "https://registry.yarnpkg.com/quick-lru/-/quick-lru-1.1.0.tgz#4360b17c61136ad38078397ff11416e186dcfbb8" integrity sha1-Q2CxfGETatOAeDl/8RQW4Ybc+7g= -rc@^1.2.7, rc@^1.2.8: +rc@^1.2.8: version "1.2.8" resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed" integrity sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw== @@ -4445,7 +4290,7 @@ read-pkg@^3.0.0: string_decoder "^1.1.1" util-deprecate "^1.0.1" -readable-stream@^2.0.6, readable-stream@~2.3.6: +readable-stream@~2.3.6: version "2.3.7" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57" integrity sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw== @@ -4636,7 +4481,7 @@ ret@~0.1.10: resolved "https://registry.yarnpkg.com/ret/-/ret-0.1.15.tgz#b8a4825d5bdb1fc3f6f53c2bc33f81388681c7bc" integrity sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg== -rimraf@^2.5.4, rimraf@^2.6.1, rimraf@^2.6.3: +rimraf@^2.5.4, rimraf@^2.6.3: version "2.7.1" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec" integrity sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w== @@ -4712,7 +4557,7 @@ semver@^4.3.6: resolved "https://registry.yarnpkg.com/semver/-/semver-4.3.6.tgz#300bc6e0e86374f7ba61068b5b1ecd57fc6532da" integrity sha1-MAvG4OhjdPe6YQaLWx7NV/xlMto= -set-blocking@^2.0.0, set-blocking@~2.0.0: +set-blocking@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" integrity sha1-BF+XgtARrppoA93TgrJDkrPYkPc= @@ -5014,7 +4859,7 @@ string-width@^1.0.1: is-fullwidth-code-point "^1.0.0" strip-ansi "^3.0.0" -"string-width@^1.0.2 || 2", string-width@^2.1.1: +string-width@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e" integrity sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw== @@ -5152,19 +4997,6 @@ symbol-tree@^3.2.2: resolved "https://registry.yarnpkg.com/symbol-tree/-/symbol-tree-3.2.4.tgz#430637d248ba77e078883951fb9aa0eed7c63fa2" integrity sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw== -tar@^4.4.2: - version "4.4.13" - resolved "https://registry.yarnpkg.com/tar/-/tar-4.4.13.tgz#43b364bc52888d555298637b10d60790254ab525" - integrity sha512-w2VwSrBoHa5BsSyH+KxEqeQBAllHhccyMFVHtGtdMpF4W7IRWfZjFiQceJPChOeTsSDVUpER2T8FA93pr0L+QA== - dependencies: - chownr "^1.1.1" - fs-minipass "^1.2.5" - minipass "^2.8.6" - minizlib "^1.2.1" - mkdirp "^0.5.0" - safe-buffer "^5.1.2" - yallist "^3.0.3" - teeny-request@^3.11.3: version "3.11.3" resolved "https://registry.yarnpkg.com/teeny-request/-/teeny-request-3.11.3.tgz#335c629f7645e5d6599362df2f3230c4cbc23a55" @@ -5749,13 +5581,6 @@ which@^1.2.8, which@^1.2.9, which@^1.3.0: dependencies: isexe "^2.0.0" -wide-align@^1.1.0: - version "1.1.3" - resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.3.tgz#ae074e6bdc0c14a431e804e624549c633b000457" - integrity sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA== - dependencies: - string-width "^1.0.2 || 2" - widest-line@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/widest-line/-/widest-line-2.0.1.tgz#7438764730ec7ef4381ce4df82fb98a53142a3fc" @@ -5873,11 +5698,6 @@ yallist@^2.1.2: resolved "https://registry.yarnpkg.com/yallist/-/yallist-2.1.2.tgz#1c11f9218f076089a47dd512f93c6699a6a81d52" integrity sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI= -yallist@^3.0.0, yallist@^3.0.3: - version "3.1.1" - resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd" - integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g== - yargs-parser@10.x, yargs-parser@^10.0.0: version "10.1.0" resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-10.1.0.tgz#7202265b89f7e9e9f2e5765e0fe735a905edbaa8" From d4f26ee8393c5314ea819d3d935360a4ed85f159 Mon Sep 17 00:00:00 2001 From: Julian Waller Date: Wed, 15 Jan 2020 13:52:16 +0000 Subject: [PATCH 66/68] feat: throw InvalidIdError when trying to applyToState. These are only logged at the debug level. Tidy up the logging to be events emitted from the Atem class. --- README.md | 11 +++++--- .../testUtils/generate-data-transfer-spec.ts | 2 +- examples/upload.ts | 2 +- src/__tests__/atem.spec.ts | 16 ++++++------ src/__tests__/connection.spec.ts | 10 ++++---- src/__tests__/index.spec.ts | 2 +- src/atem.ts | 24 ++++++++++-------- .../DownstreamKeyPropertiesCommand.ts | 4 +-- .../DownstreamKeySourcesCommand.ts | 4 +-- .../DownstreamKeyStateCommand.ts | 6 ++--- .../Media/MediaPlayerSourceCommand.ts | 4 +-- .../Media/MediaPlayerStatusCommand.ts | 4 +-- .../FadeToBlack/FadeToBlackRateCommand.ts | 4 +-- .../FadeToBlack/FadeToBlackStateCommand.ts | 4 +-- .../Key/MixEffectKeyChromaCommand.ts | 4 +-- .../MixEffects/Key/MixEffectKeyDVECommand.ts | 6 ++--- .../Key/MixEffectKeyFlyKeyframeGetCommand.ts | 6 ++--- .../MixEffectKeyFlyPropertiesGetCommand.ts | 4 +-- .../MixEffects/Key/MixEffectKeyLumaCommand.ts | 4 +-- .../Key/MixEffectKeyOnAirCommand.ts | 4 +-- .../Key/MixEffectKeyPatternCommand.ts | 4 +-- .../Key/MixEffectKeyPropertiesGetCommand.ts | 4 +-- .../MixEffects/PreviewInputCommand.ts | 4 +-- .../MixEffects/ProgramInputCommand.ts | 4 +-- .../Transition/TransitionDVECommand.ts | 6 ++--- .../Transition/TransitionDipCommand.ts | 4 +-- .../Transition/TransitionMixCommand.ts | 4 +-- .../Transition/TransitionPositionCommand.ts | 4 +-- .../Transition/TransitionPreviewCommand.ts | 4 +-- .../Transition/TransitionPropertiesCommand.ts | 4 +-- .../Transition/TransitionStingerCommand.ts | 4 +-- .../Transition/TransitionWipeCommand.ts | 4 +-- .../Settings/MultiViewerSourceCommand.ts | 4 +-- .../SuperSourceBoxParametersCommand.ts | 4 +-- .../SuperSourcePropertiesCommand.ts | 8 +++--- src/lib/__tests__/atemSocket.spec.ts | 9 +++---- src/lib/__tests__/socket-child.spec.ts | 2 +- src/lib/atemSocket.ts | 25 +++++++++---------- src/lib/atemSocketChild.ts | 10 ++++---- src/state/index.ts | 15 +++++++++++ 40 files changed, 137 insertions(+), 115 deletions(-) diff --git a/README.md b/README.md index 2c20339a6..b1e01cd59 100644 --- a/README.md +++ b/README.md @@ -32,7 +32,9 @@ If you want to make a contribution, feel free to open a PR. ```javascript const { Atem } = require('atem-connection') -const myAtem = new Atem({ externalLog: console.log }) +const myAtem = new Atem() +myAtem.on('info', console.log) +myAtem.on('error', console.error) myAtem.connect('192.168.168.240') @@ -72,9 +74,12 @@ This should not be relied on in most usage, as the commands can and will have br ## Debug -Set `debug=true` config option in order to see raw packets. This is especially useful for library developers. +Set `debugBuffers=true` config option in order to see raw packets. This is especially useful for library developers. ```javascript -const myAtem = new Atem({ debug: true, externalLog: console.log }) +const myAtem = new Atem({ debugBuffers: true }) +myAtem.on('info', console.log) +myAtem.on('debug', console.log) +myAtem.on('error', console.error) ``` ```sh SEND diff --git a/examples/testUtils/generate-data-transfer-spec.ts b/examples/testUtils/generate-data-transfer-spec.ts index 8e9225996..e7cfa2446 100644 --- a/examples/testUtils/generate-data-transfer-spec.ts +++ b/examples/testUtils/generate-data-transfer-spec.ts @@ -5,7 +5,7 @@ import * as fs from 'fs' const frameBuffer = Buffer.alloc(1920 * 1080 * 4,0) // const wavBuffer = fs.readFileSync('./src/dataTransfer/__tests__/sampleAudio.wav') -const nb = new Atem({ debug: false }) +const nb = new Atem({}) nb.on('error', () => null) nb.on('connected', async () => { diff --git a/examples/upload.ts b/examples/upload.ts index 9416d90d3..08a5412ed 100644 --- a/examples/upload.ts +++ b/examples/upload.ts @@ -12,7 +12,7 @@ const IP = process.argv[2] let uploadNumber = 0 let uploadStarted = Date.now() -const conn = new Atem({ debug: false }) +const conn = new Atem({}) let stuckTimeout: any = null diff --git a/src/__tests__/atem.spec.ts b/src/__tests__/atem.spec.ts index c07b7531f..81acc6e00 100644 --- a/src/__tests__/atem.spec.ts +++ b/src/__tests__/atem.spec.ts @@ -15,7 +15,7 @@ describe('Atem', () => { }) test('constructor test 1', async () => { - const conn = new Atem({ disableMultithreaded: true, externalLog: () => null }) + const conn = new Atem({ disableMultithreaded: true }) try { const socket = (conn as any).socket as AtemSocket @@ -24,7 +24,7 @@ describe('Atem', () => { expect(AtemSocket).toHaveBeenCalledTimes(1) expect(AtemSocket).toHaveBeenCalledWith({ address: '', - debug: false, + debugBuffers: false, disableMultithreaded: true, log: (conn as any)._log, port: DEFAULT_PORT @@ -34,7 +34,7 @@ describe('Atem', () => { } }) test('constructor test 2', async () => { - const conn = new Atem({ debug: true, address: 'test1', port: 23 }) + const conn = new Atem({ debugBuffers: true, address: 'test1', port: 23 }) try { const socket = (conn as any).socket as AtemSocket @@ -43,7 +43,7 @@ describe('Atem', () => { expect(AtemSocket).toHaveBeenCalledTimes(1) expect(AtemSocket).toHaveBeenCalledWith({ address: 'test1', - debug: true, + debugBuffers: true, disableMultithreaded: false, log: (conn as any)._log, port: 23 @@ -54,7 +54,7 @@ describe('Atem', () => { }) test('connect', async () => { - const conn = new Atem({ debug: true, address: 'test1', port: 23 }) + const conn = new Atem({ debugBuffers: true, address: 'test1', port: 23 }) try { const socket = (conn as any).socket as AtemSocket @@ -74,7 +74,7 @@ describe('Atem', () => { }) test('disconnect', async () => { - const conn = new Atem({ debug: true, address: 'test1', port: 23 }) + const conn = new Atem({ debugBuffers: true, address: 'test1', port: 23 }) try { const socket = (conn as any).socket as AtemSocket @@ -95,7 +95,7 @@ describe('Atem', () => { test('sendCommand - good', async () => { (AtemSocket as any).mockImplementation(() => new EventEmitter()) - const conn = new Atem({ debug: true, address: 'test1', port: 23 }) + const conn = new Atem({ debugBuffers: true, address: 'test1', port: 23 }) try { const socket = (conn as any).socket as AtemSocket @@ -137,7 +137,7 @@ describe('Atem', () => { test('sendCommand - send error', async () => { (AtemSocket as any).mockImplementation(() => new EventEmitter()) - const conn = new Atem({ debug: true, address: 'test1', port: 23 }) + const conn = new Atem({ debugBuffers: true, address: 'test1', port: 23 }) try { const socket = (conn as any).socket as AtemSocket diff --git a/src/__tests__/connection.spec.ts b/src/__tests__/connection.spec.ts index 5a611cc24..f47e4d964 100644 --- a/src/__tests__/connection.spec.ts +++ b/src/__tests__/connection.spec.ts @@ -3,6 +3,7 @@ import { resolve } from 'path' import { AtemSocketChild } from '../lib/atemSocketChild' import { ThreadedClass } from 'threadedclass' import { BasicAtem } from '../atem' +import { InvalidIdError } from '../state' jest.mock('../lib/atemSocketChild') // @ts-ignore @@ -37,11 +38,10 @@ export class AtemSocketChildMock implements AtemSocketChild { function createConnection () { return new BasicAtem({ - debug: false, + debugBuffers: false, address: '', port: 890, - disableMultithreaded: true, - externalLog: console.log + disableMultithreaded: true }) } @@ -62,9 +62,9 @@ function runTestMe1 (name: string, filename: string) { expect(child.onCommandsReceived).toBeTruthy() const errors: any[] = [] - conn.on('error', e => { + conn.on('error', (e: any) => { // Ignore any errors that are due to bad ids, as they are 'good' errors - if (!e.indexOf('is not valid')) { + if (!(e instanceof InvalidIdError)) { errors.push(e) } }) diff --git a/src/__tests__/index.spec.ts b/src/__tests__/index.spec.ts index 4093a2ebe..00c58f252 100644 --- a/src/__tests__/index.spec.ts +++ b/src/__tests__/index.spec.ts @@ -14,7 +14,7 @@ test('Simple test', async () => { }) function createConnection (apiVersion: Enums.ProtocolVersion) { - const conn = new Atem({ debug: true, disableMultithreaded: true }) + const conn = new Atem({ debugBuffers: true, disableMultithreaded: true }) // Create a state object const state = createEmptyState() diff --git a/src/atem.ts b/src/atem.ts index 525f4a9f9..00e651a87 100644 --- a/src/atem.ts +++ b/src/atem.ts @@ -1,5 +1,5 @@ import { EventEmitter } from 'events' -import { AtemState, AtemStateUtil } from './state' +import { AtemState, AtemStateUtil, InvalidIdError } from './state' import { AtemSocket } from './lib/atemSocket' import { ISerializableCommand, IDeserializedCommand } from './commands/CommandBase' import * as Commands from './commands' @@ -27,10 +27,8 @@ import { listVisibleInputs } from './lib/tally' export interface AtemOptions { address?: string, port?: number, - debug?: boolean, + debugBuffers?: boolean, disableMultithreaded?: boolean - - externalLog?: (...args: any[]) => void } interface SentCommand { @@ -50,18 +48,21 @@ export const DEFAULT_PORT = 9910 export class BasicAtem extends EventEmitter { private readonly socket: AtemSocket protected readonly dataTransferManager: DT.DataTransferManager - private readonly _log: (...args: any[]) => void private _state: AtemState | undefined private _sentQueue: {[packetId: string]: SentCommand } = {} private _status: AtemConnectionStatus public on!: ((event: 'error', listener: (message: any) => void) => this) & + ((event: 'info', listener: (message: string) => void) => this) & + ((event: 'debug', listener: (message: string) => void) => this) & ((event: 'connected', listener: () => void) => this) & ((event: 'disconnected', listener: () => void) => this) & ((event: 'stateChanged', listener: (state: AtemState, paths: string[]) => void) => this) & ((event: 'receivedCommands', listener: (cmds: IDeserializedCommand[]) => void) => this) public emit!: ((event: 'error', message: any) => boolean) & + ((event: 'info', message: string) => boolean) & + ((event: 'debug', message: string) => boolean) & ((event: 'connected') => boolean) & ((event: 'disconnected') => boolean) & ((event: 'stateChanged', state: AtemState, paths: string[]) => boolean) & @@ -69,13 +70,11 @@ export class BasicAtem extends EventEmitter { constructor (options?: AtemOptions) { super() - this._log = (options && options.externalLog) || ((...args: any[]) => { console.log(...args) }) this._state = AtemStateUtil.Create() this._status = AtemConnectionStatus.CLOSED this.socket = new AtemSocket({ - debug: (options || {}).debug || false, - log: this._log, + debugBuffers: (options || {}).debugBuffers || false, address: (options || {}).address || '', port: (options || {}).port || DEFAULT_PORT, disableMultithreaded: (options || {}).disableMultithreaded || false @@ -87,6 +86,8 @@ export class BasicAtem extends EventEmitter { this._mutateState(commands) }) this.socket.on('commandsAck', trackingIds => this._resolveCommands(trackingIds)) + this.socket.on('info', msg => this.emit('info', msg)) + this.socket.on('debug', msg => this.emit('debug', msg)) this.socket.on('error', e => this.emit('error', e)) this.socket.on('disconnect', () => { this._status = AtemConnectionStatus.CLOSED @@ -167,8 +168,11 @@ export class BasicAtem extends EventEmitter { allChangedPaths.push(...changePaths) } } catch (e) { - // TODO - should we error or warn on this? - this.emit('error', `MutateState failed: ${e}. Command: ${command.constructor.name} ${JSON.stringify(command)}`) + if (e instanceof InvalidIdError) { + this.emit('debug', `Invalid command id: ${e}. Command: ${command.constructor.name} ${JSON.stringify(command)}`) + } else { + this.emit('error', `MutateState failed: ${e}. Command: ${command.constructor.name} ${JSON.stringify(command)}`) + } } } diff --git a/src/commands/DownstreamKey/DownstreamKeyPropertiesCommand.ts b/src/commands/DownstreamKey/DownstreamKeyPropertiesCommand.ts index 4128ba837..9229627dd 100644 --- a/src/commands/DownstreamKey/DownstreamKeyPropertiesCommand.ts +++ b/src/commands/DownstreamKey/DownstreamKeyPropertiesCommand.ts @@ -1,5 +1,5 @@ import { DeserializedCommand } from '../CommandBase' -import { AtemState, AtemStateUtil } from '../../state' +import { AtemState, AtemStateUtil, InvalidIdError } from '../../state' import { DownstreamKeyerProperties } from '../../state/video/downstreamKeyers' export class DownstreamKeyPropertiesCommand extends DeserializedCommand { @@ -38,7 +38,7 @@ export class DownstreamKeyPropertiesCommand extends DeserializedCommand= state.info.capabilities.downstreamKeyers) { - throw new Error(`DownstreamKeyer ${this.downstreamKeyerId} is not valid`) + throw new InvalidIdError('DownstreamKeyer', this.downstreamKeyerId) } AtemStateUtil.getDownstreamKeyer(state, this.downstreamKeyerId).properties = this.properties diff --git a/src/commands/DownstreamKey/DownstreamKeySourcesCommand.ts b/src/commands/DownstreamKey/DownstreamKeySourcesCommand.ts index 9cdec05b1..6b05b4ac1 100644 --- a/src/commands/DownstreamKey/DownstreamKeySourcesCommand.ts +++ b/src/commands/DownstreamKey/DownstreamKeySourcesCommand.ts @@ -1,5 +1,5 @@ import { DeserializedCommand } from '../CommandBase' -import { AtemState, AtemStateUtil } from '../../state' +import { AtemState, AtemStateUtil, InvalidIdError } from '../../state' import { DownstreamKeyer } from '../../state/video/downstreamKeyers' export class DownstreamKeySourcesCommand extends DeserializedCommand { @@ -25,7 +25,7 @@ export class DownstreamKeySourcesCommand extends DeserializedCommand= state.info.capabilities.downstreamKeyers) { - throw new Error(`DownstreamKeyer ${this.downstreamKeyerId} is not valid`) + throw new InvalidIdError('DownstreamKeyer', this.downstreamKeyerId) } AtemStateUtil.getDownstreamKeyer(state, this.downstreamKeyerId).sources = this.properties diff --git a/src/commands/DownstreamKey/DownstreamKeyStateCommand.ts b/src/commands/DownstreamKey/DownstreamKeyStateCommand.ts index cc7191360..5079b7002 100644 --- a/src/commands/DownstreamKey/DownstreamKeyStateCommand.ts +++ b/src/commands/DownstreamKey/DownstreamKeyStateCommand.ts @@ -1,5 +1,5 @@ import { DeserializedCommand } from '../CommandBase' -import { AtemState, AtemStateUtil } from '../../state' +import { AtemState, AtemStateUtil, InvalidIdError } from '../../state' import { DownstreamKeyerBase } from '../../state/video/downstreamKeyers' import { ProtocolVersion } from '../../enums' @@ -28,7 +28,7 @@ export class DownstreamKeyStateCommand extends DeserializedCommand= state.info.capabilities.downstreamKeyers) { - throw new Error(`DownstreamKeyer ${this.downstreamKeyerId} is not valid`) + throw new InvalidIdError('DownstreamKeyer', this.downstreamKeyerId) } state.video.downstreamKeyers[this.downstreamKeyerId] = { @@ -66,7 +66,7 @@ export class DownstreamKeyStateV8Command extends DeserializedCommand= state.info.capabilities.downstreamKeyers) { - throw new Error(`DownstreamKeyer ${this.downstreamKeyerId} is not valid`) + throw new InvalidIdError('DownstreamKeyer', this.downstreamKeyerId) } state.video.downstreamKeyers[this.downstreamKeyerId] = { diff --git a/src/commands/Media/MediaPlayerSourceCommand.ts b/src/commands/Media/MediaPlayerSourceCommand.ts index fd84595bf..c50f5f622 100644 --- a/src/commands/Media/MediaPlayerSourceCommand.ts +++ b/src/commands/Media/MediaPlayerSourceCommand.ts @@ -1,4 +1,4 @@ -import { AtemState, AtemStateUtil } from '../../state' +import { AtemState, AtemStateUtil, InvalidIdError } from '../../state' import { MediaPlayerSource } from '../../state/media' import { WritableCommand, DeserializedCommand } from '../CommandBase' @@ -54,7 +54,7 @@ export class MediaPlayerSourceUpdateCommand extends DeserializedCommand= state.info.capabilities.mediaPlayers) { - throw new Error(`MediaPlayer ${this.mediaPlayerId} is not valid`) + throw new InvalidIdError('MediaPlayer', this.mediaPlayerId) } state.media.players[this.mediaPlayerId] = { diff --git a/src/commands/Media/MediaPlayerStatusCommand.ts b/src/commands/Media/MediaPlayerStatusCommand.ts index 26b20a83b..2b418077e 100644 --- a/src/commands/Media/MediaPlayerStatusCommand.ts +++ b/src/commands/Media/MediaPlayerStatusCommand.ts @@ -1,4 +1,4 @@ -import { AtemState, AtemStateUtil } from '../../state' +import { AtemState, AtemStateUtil, InvalidIdError } from '../../state' import { MediaPlayer } from '../../state/media' import { WritableCommand, DeserializedCommand } from '../CommandBase' @@ -56,7 +56,7 @@ export class MediaPlayerStatusUpdateCommand extends DeserializedCommand= state.info.capabilities.mediaPlayers) { - throw new Error(`MediaPlayer ${this.mediaPlayerId} is not valid`) + throw new InvalidIdError('MediaPlayer', this.mediaPlayerId) } state.media.players[this.mediaPlayerId] = { diff --git a/src/commands/MixEffects/FadeToBlack/FadeToBlackRateCommand.ts b/src/commands/MixEffects/FadeToBlack/FadeToBlackRateCommand.ts index 71726251e..771aa1b13 100644 --- a/src/commands/MixEffects/FadeToBlack/FadeToBlackRateCommand.ts +++ b/src/commands/MixEffects/FadeToBlack/FadeToBlackRateCommand.ts @@ -1,5 +1,5 @@ import { BasicWritableCommand, DeserializedCommand } from '../../CommandBase' -import { AtemState, AtemStateUtil } from '../../../state' +import { AtemState, AtemStateUtil, InvalidIdError } from '../../../state' export class FadeToBlackRateCommand extends BasicWritableCommand<{ rate: number }> { public static readonly rawName = 'FtbC' @@ -41,7 +41,7 @@ export class FadeToBlackRateUpdateCommand extends DeserializedCommand<{ rate: nu public applyToState (state: AtemState) { if (!state.info.capabilities || this.mixEffect >= state.info.capabilities.mixEffects) { - throw new Error(`MixEffect ${this.mixEffect} is not valid`) + throw new InvalidIdError('MixEffect', this.mixEffect) } const mixEffect = AtemStateUtil.getMixEffect(state, this.mixEffect) diff --git a/src/commands/MixEffects/FadeToBlack/FadeToBlackStateCommand.ts b/src/commands/MixEffects/FadeToBlack/FadeToBlackStateCommand.ts index 39a0a100e..374473799 100644 --- a/src/commands/MixEffects/FadeToBlack/FadeToBlackStateCommand.ts +++ b/src/commands/MixEffects/FadeToBlack/FadeToBlackStateCommand.ts @@ -1,5 +1,5 @@ import { DeserializedCommand } from '../../CommandBase' -import { AtemState, AtemStateUtil } from '../../../state' +import { AtemState, AtemStateUtil, InvalidIdError } from '../../../state' export interface FadeToBlackProps { isFullyBlack: boolean @@ -31,7 +31,7 @@ export class FadeToBlackStateCommand extends DeserializedCommand= state.info.capabilities.mixEffects) { - throw new Error(`MixEffect ${this.mixEffect} is not valid`) + throw new InvalidIdError('MixEffect', this.mixEffect) } const mixEffect = AtemStateUtil.getMixEffect(state, this.mixEffect) diff --git a/src/commands/MixEffects/Key/MixEffectKeyChromaCommand.ts b/src/commands/MixEffects/Key/MixEffectKeyChromaCommand.ts index cfbfc5fc9..fdd6b46ac 100644 --- a/src/commands/MixEffects/Key/MixEffectKeyChromaCommand.ts +++ b/src/commands/MixEffects/Key/MixEffectKeyChromaCommand.ts @@ -1,5 +1,5 @@ import { WritableCommand, DeserializedCommand } from '../../CommandBase' -import { AtemState, AtemStateUtil } from '../../../state' +import { AtemState, AtemStateUtil, InvalidIdError } from '../../../state' import { UpstreamKeyerChromaSettings } from '../../../state/video/upstreamKeyers' export class MixEffectKeyChromaCommand extends WritableCommand { @@ -68,7 +68,7 @@ export class MixEffectKeyChromaUpdateCommand extends DeserializedCommand= meInfo.keyCount) { - throw new Error(`UpstreamKeyer ${this.mixEffect}-${this.upstreamKeyerId} is not valid`) + throw new InvalidIdError('UpstreamKeyer', this.mixEffect, this.upstreamKeyerId) } const mixEffect = AtemStateUtil.getMixEffect(state, this.mixEffect) diff --git a/src/commands/MixEffects/Key/MixEffectKeyDVECommand.ts b/src/commands/MixEffects/Key/MixEffectKeyDVECommand.ts index c8ce8d177..982d4e07d 100644 --- a/src/commands/MixEffects/Key/MixEffectKeyDVECommand.ts +++ b/src/commands/MixEffects/Key/MixEffectKeyDVECommand.ts @@ -1,5 +1,5 @@ import { WritableCommand, DeserializedCommand } from '../../CommandBase' -import { AtemState, AtemStateUtil } from '../../../state' +import { AtemState, AtemStateUtil, InvalidIdError } from '../../../state' import { UpstreamKeyerDVESettings } from '../../../state/video/upstreamKeyers' export class MixEffectKeyDVECommand extends WritableCommand { @@ -143,9 +143,9 @@ export class MixEffectKeyDVEUpdateCommand extends DeserializedCommand= meInfo.keyCount) { - throw new Error(`UpstreamKeyer ${this.mixEffect}-${this.upstreamKeyerId} is not valid`) + throw new InvalidIdError('UpstreamKeyer', this.mixEffect, this.upstreamKeyerId) } else if (!state.info.capabilities || !state.info.capabilities.DVEs) { - throw new Error(`DVE is not supported`) + throw new InvalidIdError(`DVE is not supported`) } const mixEffect = AtemStateUtil.getMixEffect(state, this.mixEffect) diff --git a/src/commands/MixEffects/Key/MixEffectKeyFlyKeyframeGetCommand.ts b/src/commands/MixEffects/Key/MixEffectKeyFlyKeyframeGetCommand.ts index 827bc9602..0c421f65c 100644 --- a/src/commands/MixEffects/Key/MixEffectKeyFlyKeyframeGetCommand.ts +++ b/src/commands/MixEffects/Key/MixEffectKeyFlyKeyframeGetCommand.ts @@ -1,5 +1,5 @@ import { DeserializedCommand } from '../../CommandBase' -import { AtemState, AtemStateUtil } from '../../../state' +import { AtemState, AtemStateUtil, InvalidIdError } from '../../../state' import { UpstreamKeyerFlyKeyframe } from '../../../state/video/upstreamKeyers' export class MixEffectKeyFlyKeyframeGetCommand extends DeserializedCommand { @@ -59,9 +59,9 @@ export class MixEffectKeyFlyKeyframeGetCommand extends DeserializedCommand= meInfo.keyCount) { - throw new Error(`UpstreamKeyer ${this.mixEffect}-${this.upstreamKeyerId} is not valid`) + throw new InvalidIdError('UpstreamKeyer', this.mixEffect, this.upstreamKeyerId) } else if (this.keyFrameId <= 0 || this.keyFrameId > 2) { - throw new Error(`KeyFrame ${this.keyFrameId} is not valid`) + throw new InvalidIdError('FlyKeyFrame', this.keyFrameId) } const mixEffect = AtemStateUtil.getMixEffect(state, this.mixEffect) diff --git a/src/commands/MixEffects/Key/MixEffectKeyFlyPropertiesGetCommand.ts b/src/commands/MixEffects/Key/MixEffectKeyFlyPropertiesGetCommand.ts index 7e78d2f40..56afbe874 100644 --- a/src/commands/MixEffects/Key/MixEffectKeyFlyPropertiesGetCommand.ts +++ b/src/commands/MixEffects/Key/MixEffectKeyFlyPropertiesGetCommand.ts @@ -1,5 +1,5 @@ import { DeserializedCommand } from '../../CommandBase' -import { AtemState, AtemStateUtil } from '../../../state' +import { AtemState, AtemStateUtil, InvalidIdError } from '../../../state' import { UpstreamKeyerFlySettings } from '../../../state/video/upstreamKeyers' export class MixEffectKeyFlyPropertiesGetCommand extends DeserializedCommand { @@ -30,7 +30,7 @@ export class MixEffectKeyFlyPropertiesGetCommand extends DeserializedCommand= meInfo.keyCount) { - throw new Error(`UpstreamKeyer ${this.mixEffect}-${this.upstreamKeyerId} is not valid`) + throw new InvalidIdError('UpstreamKeyer', this.mixEffect, this.upstreamKeyerId) } const mixEffect = AtemStateUtil.getMixEffect(state, this.mixEffect) diff --git a/src/commands/MixEffects/Key/MixEffectKeyLumaCommand.ts b/src/commands/MixEffects/Key/MixEffectKeyLumaCommand.ts index 82eccc133..9a1d0e60b 100644 --- a/src/commands/MixEffects/Key/MixEffectKeyLumaCommand.ts +++ b/src/commands/MixEffects/Key/MixEffectKeyLumaCommand.ts @@ -1,5 +1,5 @@ import { WritableCommand, DeserializedCommand } from '../../CommandBase' -import { AtemState, AtemStateUtil } from '../../../state' +import { AtemState, AtemStateUtil, InvalidIdError } from '../../../state' import { UpstreamKeyerLumaSettings } from '../../../state/video/upstreamKeyers' export class MixEffectKeyLumaCommand extends WritableCommand { @@ -65,7 +65,7 @@ export class MixEffectKeyLumaUpdateCommand extends DeserializedCommand= meInfo.keyCount) { - throw new Error(`UpstreamKeyer ${this.mixEffect}-${this.upstreamKeyerId} is not valid`) + throw new InvalidIdError('UpstreamKeyer', this.mixEffect, this.upstreamKeyerId) } const mixEffect = AtemStateUtil.getMixEffect(state, this.mixEffect) diff --git a/src/commands/MixEffects/Key/MixEffectKeyOnAirCommand.ts b/src/commands/MixEffects/Key/MixEffectKeyOnAirCommand.ts index 46f431553..f8a1e7fad 100644 --- a/src/commands/MixEffects/Key/MixEffectKeyOnAirCommand.ts +++ b/src/commands/MixEffects/Key/MixEffectKeyOnAirCommand.ts @@ -1,5 +1,5 @@ import { BasicWritableCommand, DeserializedCommand } from '../../CommandBase' -import { AtemState, AtemStateUtil } from '../../../state' +import { AtemState, AtemStateUtil, InvalidIdError } from '../../../state' export class MixEffectKeyOnAirCommand extends BasicWritableCommand<{ onAir: boolean}> { public static readonly rawName = 'CKOn' @@ -48,7 +48,7 @@ export class MixEffectKeyOnAirUpdateCommand extends DeserializedCommand<{onAir: public applyToState (state: AtemState) { const meInfo = state.info.mixEffects[this.mixEffect] if (!meInfo || this.upstreamKeyerId >= meInfo.keyCount) { - throw new Error(`UpstreamKeyer ${this.mixEffect}-${this.upstreamKeyerId} is not valid`) + throw new InvalidIdError('UpstreamKeyer', this.mixEffect, this.upstreamKeyerId) } const mixEffect = AtemStateUtil.getMixEffect(state, this.mixEffect) diff --git a/src/commands/MixEffects/Key/MixEffectKeyPatternCommand.ts b/src/commands/MixEffects/Key/MixEffectKeyPatternCommand.ts index 611296235..046a53992 100644 --- a/src/commands/MixEffects/Key/MixEffectKeyPatternCommand.ts +++ b/src/commands/MixEffects/Key/MixEffectKeyPatternCommand.ts @@ -1,5 +1,5 @@ import { WritableCommand, DeserializedCommand } from '../../CommandBase' -import { AtemState, AtemStateUtil } from '../../../state' +import { AtemState, AtemStateUtil, InvalidIdError } from '../../../state' import { UpstreamKeyerPatternSettings } from '../../../state/video/upstreamKeyers' export class MixEffectKeyPatternCommand extends WritableCommand { @@ -75,7 +75,7 @@ export class MixEffectKeyUpdateCommand extends DeserializedCommand= meInfo.keyCount) { - throw new Error(`UpstreamKeyer ${this.mixEffect}-${this.upstreamKeyerId} is not valid`) + throw new InvalidIdError('UpstreamKeyer', this.mixEffect, this.upstreamKeyerId) } const mixEffect = AtemStateUtil.getMixEffect(state, this.mixEffect) diff --git a/src/commands/MixEffects/Key/MixEffectKeyPropertiesGetCommand.ts b/src/commands/MixEffects/Key/MixEffectKeyPropertiesGetCommand.ts index 1408c727a..80aec7a6c 100644 --- a/src/commands/MixEffects/Key/MixEffectKeyPropertiesGetCommand.ts +++ b/src/commands/MixEffects/Key/MixEffectKeyPropertiesGetCommand.ts @@ -1,5 +1,5 @@ import { DeserializedCommand } from '../../CommandBase' -import { AtemState, AtemStateUtil } from '../../../state' +import { AtemState, AtemStateUtil, InvalidIdError } from '../../../state' import { UpstreamKeyerBase } from '../../../state/video/upstreamKeyers' export class MixEffectKeyPropertiesGetCommand extends DeserializedCommand { @@ -37,7 +37,7 @@ export class MixEffectKeyPropertiesGetCommand extends DeserializedCommand= meInfo.keyCount) { - throw new Error(`UpstreamKeyer ${this.mixEffect}-${this.upstreamKeyerId} is not valid`) + throw new InvalidIdError('UpstreamKeyer', this.mixEffect, this.upstreamKeyerId) } const mixEffect = AtemStateUtil.getMixEffect(state, this.mixEffect) diff --git a/src/commands/MixEffects/PreviewInputCommand.ts b/src/commands/MixEffects/PreviewInputCommand.ts index a39e75e5e..2eef74624 100644 --- a/src/commands/MixEffects/PreviewInputCommand.ts +++ b/src/commands/MixEffects/PreviewInputCommand.ts @@ -1,5 +1,5 @@ import { BasicWritableCommand, DeserializedCommand } from '../CommandBase' -import { AtemState, AtemStateUtil } from '../../state' +import { AtemState, AtemStateUtil, InvalidIdError } from '../../state' export interface InputSource { source: number @@ -46,7 +46,7 @@ export class PreviewInputUpdateCommand extends DeserializedCommand public applyToState (state: AtemState) { if (!state.info.capabilities || this.mixEffect >= state.info.capabilities.mixEffects) { - throw new Error(`MixEffect ${this.mixEffect} is not valid`) + throw new InvalidIdError('MixEffect', this.mixEffect) } const mixEffect = AtemStateUtil.getMixEffect(state, this.mixEffect) diff --git a/src/commands/MixEffects/ProgramInputCommand.ts b/src/commands/MixEffects/ProgramInputCommand.ts index 848d07ec6..39609787b 100644 --- a/src/commands/MixEffects/ProgramInputCommand.ts +++ b/src/commands/MixEffects/ProgramInputCommand.ts @@ -1,5 +1,5 @@ import { BasicWritableCommand, DeserializedCommand } from '../CommandBase' -import { AtemState, AtemStateUtil } from '../../state' +import { AtemState, AtemStateUtil, InvalidIdError } from '../../state' import { InputSource } from './PreviewInputCommand' export class ProgramInputCommand extends BasicWritableCommand { @@ -43,7 +43,7 @@ export class ProgramInputUpdateCommand extends DeserializedCommand public applyToState (state: AtemState) { if (!state.info.capabilities || this.mixEffect >= state.info.capabilities.mixEffects) { - throw new Error(`MixEffect ${this.mixEffect} is not valid`) + throw new InvalidIdError('MixEffect', this.mixEffect) } const mixEffect = AtemStateUtil.getMixEffect(state, this.mixEffect) diff --git a/src/commands/MixEffects/Transition/TransitionDVECommand.ts b/src/commands/MixEffects/Transition/TransitionDVECommand.ts index 254ce154b..f30c95bce 100644 --- a/src/commands/MixEffects/Transition/TransitionDVECommand.ts +++ b/src/commands/MixEffects/Transition/TransitionDVECommand.ts @@ -1,5 +1,5 @@ import { WritableCommand, DeserializedCommand } from '../../CommandBase' -import { AtemState, AtemStateUtil } from '../../../state' +import { AtemState, AtemStateUtil, InvalidIdError } from '../../../state' import { DVETransitionSettings } from '../../../state/video' export class TransitionDVECommand extends WritableCommand { @@ -86,9 +86,9 @@ export class TransitionDVEUpdateCommand extends DeserializedCommand= state.info.capabilities.mixEffects) { - throw new Error(`MixEffect ${this.mixEffect} is not valid`) + throw new InvalidIdError('MixEffect', this.mixEffect) } else if (!state.info.capabilities.DVEs) { - throw new Error(`DVE is not supported`) + throw new InvalidIdError(`DVE is not supported`) } const mixEffect = AtemStateUtil.getMixEffect(state, this.mixEffect) diff --git a/src/commands/MixEffects/Transition/TransitionDipCommand.ts b/src/commands/MixEffects/Transition/TransitionDipCommand.ts index 9a79271d2..ba8db2ff1 100644 --- a/src/commands/MixEffects/Transition/TransitionDipCommand.ts +++ b/src/commands/MixEffects/Transition/TransitionDipCommand.ts @@ -1,5 +1,5 @@ import { WritableCommand, DeserializedCommand } from '../../CommandBase' -import { AtemState, AtemStateUtil } from '../../../state' +import { AtemState, AtemStateUtil, InvalidIdError } from '../../../state' import { DipTransitionSettings } from '../../../state/video' export class TransitionDipCommand extends WritableCommand { @@ -50,7 +50,7 @@ export class TransitionDipUpdateCommand extends DeserializedCommand= state.info.capabilities.mixEffects) { - throw new Error(`MixEffect ${this.mixEffect} is not valid`) + throw new InvalidIdError('MixEffect', this.mixEffect) } const mixEffect = AtemStateUtil.getMixEffect(state, this.mixEffect) diff --git a/src/commands/MixEffects/Transition/TransitionMixCommand.ts b/src/commands/MixEffects/Transition/TransitionMixCommand.ts index a076218ae..5662a2a19 100644 --- a/src/commands/MixEffects/Transition/TransitionMixCommand.ts +++ b/src/commands/MixEffects/Transition/TransitionMixCommand.ts @@ -1,5 +1,5 @@ import { DeserializedCommand, BasicWritableCommand } from '../../CommandBase' -import { AtemState, AtemStateUtil } from '../../../state' +import { AtemState, AtemStateUtil, InvalidIdError } from '../../../state' import { MixTransitionSettings } from '../../../state/video' export class TransitionMixCommand extends BasicWritableCommand { @@ -43,7 +43,7 @@ export class TransitionMixUpdateCommand extends DeserializedCommand= state.info.capabilities.mixEffects) { - throw new Error(`MixEffect ${this.mixEffect} is not valid`) + throw new InvalidIdError('MixEffect', this.mixEffect) } const mixEffect = AtemStateUtil.getMixEffect(state, this.mixEffect) diff --git a/src/commands/MixEffects/Transition/TransitionPositionCommand.ts b/src/commands/MixEffects/Transition/TransitionPositionCommand.ts index 4fce2ba4e..7685836bb 100644 --- a/src/commands/MixEffects/Transition/TransitionPositionCommand.ts +++ b/src/commands/MixEffects/Transition/TransitionPositionCommand.ts @@ -1,5 +1,5 @@ import { BasicWritableCommand, DeserializedCommand } from '../../CommandBase' -import { AtemState, AtemStateUtil } from '../../../state' +import { AtemState, AtemStateUtil, InvalidIdError } from '../../../state' export interface HandlePositionProps { handlePosition: number // 0...10000 @@ -53,7 +53,7 @@ export class TransitionPositionUpdateCommand extends DeserializedCommand= state.info.capabilities.mixEffects) { - throw new Error(`MixEffect ${this.mixEffect} is not valid`) + throw new InvalidIdError('MixEffect', this.mixEffect) } const mixEffect = AtemStateUtil.getMixEffect(state, this.mixEffect) diff --git a/src/commands/MixEffects/Transition/TransitionPreviewCommand.ts b/src/commands/MixEffects/Transition/TransitionPreviewCommand.ts index 125d5e909..7cd3aa381 100644 --- a/src/commands/MixEffects/Transition/TransitionPreviewCommand.ts +++ b/src/commands/MixEffects/Transition/TransitionPreviewCommand.ts @@ -1,5 +1,5 @@ import { BasicWritableCommand, DeserializedCommand } from '../../CommandBase' -import { AtemState, AtemStateUtil } from '../../../state' +import { AtemState, AtemStateUtil, InvalidIdError } from '../../../state' export interface PreviewProps { preview: boolean @@ -46,7 +46,7 @@ export class PreviewTransitionUpdateCommand extends DeserializedCommand= state.info.capabilities.mixEffects) { - throw new Error(`MixEffect ${this.mixEffect} is not valid`) + throw new InvalidIdError('MixEffect', this.mixEffect) } const mixEffect = AtemStateUtil.getMixEffect(state, this.mixEffect) diff --git a/src/commands/MixEffects/Transition/TransitionPropertiesCommand.ts b/src/commands/MixEffects/Transition/TransitionPropertiesCommand.ts index f456f3ea2..2509f7c47 100644 --- a/src/commands/MixEffects/Transition/TransitionPropertiesCommand.ts +++ b/src/commands/MixEffects/Transition/TransitionPropertiesCommand.ts @@ -1,5 +1,5 @@ import { WritableCommand, DeserializedCommand } from '../../CommandBase' -import { AtemState, AtemStateUtil } from '../../../state' +import { AtemState, AtemStateUtil, InvalidIdError } from '../../../state' import { TransitionProperties } from '../../../state/video' export class TransitionPropertiesCommand extends WritableCommand { @@ -55,7 +55,7 @@ export class TransitionPropertiesUpdateCommand extends DeserializedCommand= state.info.capabilities.mixEffects) { - throw new Error(`MixEffect ${this.mixEffect} is not valid`) + throw new InvalidIdError('MixEffect', this.mixEffect) } const mixEffect = AtemStateUtil.getMixEffect(state, this.mixEffect) diff --git a/src/commands/MixEffects/Transition/TransitionStingerCommand.ts b/src/commands/MixEffects/Transition/TransitionStingerCommand.ts index 6a30ff418..b26263ac3 100644 --- a/src/commands/MixEffects/Transition/TransitionStingerCommand.ts +++ b/src/commands/MixEffects/Transition/TransitionStingerCommand.ts @@ -1,5 +1,5 @@ import { WritableCommand, DeserializedCommand } from '../../CommandBase' -import { AtemState, AtemStateUtil } from '../../../state' +import { AtemState, AtemStateUtil, InvalidIdError } from '../../../state' import { StingerTransitionSettings } from '../../../state/video' export class TransitionStingerCommand extends WritableCommand { @@ -78,7 +78,7 @@ export class TransitionStingerUpdateCommand extends DeserializedCommand= state.info.capabilities.mixEffects) { - throw new Error(`MixEffect ${this.mixEffect} is not valid`) + throw new InvalidIdError('MixEffect', this.mixEffect) } const mixEffect = AtemStateUtil.getMixEffect(state, this.mixEffect) diff --git a/src/commands/MixEffects/Transition/TransitionWipeCommand.ts b/src/commands/MixEffects/Transition/TransitionWipeCommand.ts index d0029002a..e8f439b34 100644 --- a/src/commands/MixEffects/Transition/TransitionWipeCommand.ts +++ b/src/commands/MixEffects/Transition/TransitionWipeCommand.ts @@ -1,5 +1,5 @@ import { WritableCommand, DeserializedCommand } from '../../CommandBase' -import { AtemState, AtemStateUtil } from '../../../state' +import { AtemState, AtemStateUtil, InvalidIdError } from '../../../state' import { WipeTransitionSettings } from '../../../state/video' export class TransitionWipeCommand extends WritableCommand { @@ -79,7 +79,7 @@ export class TransitionWipeUpdateCommand extends DeserializedCommand= state.info.capabilities.mixEffects) { - throw new Error(`MixEffect ${this.mixEffect} is not valid`) + throw new InvalidIdError('MixEffect', this.mixEffect) } const mixEffect = AtemStateUtil.getMixEffect(state, this.mixEffect) diff --git a/src/commands/Settings/MultiViewerSourceCommand.ts b/src/commands/Settings/MultiViewerSourceCommand.ts index 4754284d2..c444c36e0 100644 --- a/src/commands/Settings/MultiViewerSourceCommand.ts +++ b/src/commands/Settings/MultiViewerSourceCommand.ts @@ -1,5 +1,5 @@ import { WritableCommand, DeserializedCommand } from '../CommandBase' -import { AtemState, AtemStateUtil } from '../../state' +import { AtemState, AtemStateUtil, InvalidIdError } from '../../state' import { MultiViewerSourceState } from '../../state/settings' export class MultiViewerSourceCommand extends WritableCommand { @@ -45,7 +45,7 @@ export class MultiViewerSourceUpdateCommand extends DeserializedCommand= state.info.multiviewer.count) { - throw new Error(`MultiViewer ${this.multiViewerId} is not valid`) + throw new InvalidIdError('MultiViewer', this.multiViewerId) } const multiviewer = AtemStateUtil.getMultiViewer(state, this.multiViewerId) diff --git a/src/commands/SuperSource/SuperSourceBoxParametersCommand.ts b/src/commands/SuperSource/SuperSourceBoxParametersCommand.ts index 8295dccd9..74218b62b 100644 --- a/src/commands/SuperSource/SuperSourceBoxParametersCommand.ts +++ b/src/commands/SuperSource/SuperSourceBoxParametersCommand.ts @@ -1,5 +1,5 @@ import { WritableCommand, DeserializedCommand } from '../CommandBase' -import { AtemState, AtemStateUtil } from '../../state' +import { AtemState, AtemStateUtil, InvalidIdError } from '../../state' import { SuperSourceBox } from '../../state/video/superSource' import { ProtocolVersion } from '../../enums' @@ -95,7 +95,7 @@ export class SuperSourceBoxParametersUpdateCommand extends DeserializedCommand= state.info.capabilities.superSources) { - throw new Error(`SuperSource ${this.ssrcId} is not valid`) + throw new InvalidIdError('SuperSource', this.ssrcId) } const supersource = AtemStateUtil.getSuperSource(state, this.ssrcId) diff --git a/src/commands/SuperSource/SuperSourcePropertiesCommand.ts b/src/commands/SuperSource/SuperSourcePropertiesCommand.ts index c5dd7a74d..2ba5bdb14 100644 --- a/src/commands/SuperSource/SuperSourcePropertiesCommand.ts +++ b/src/commands/SuperSource/SuperSourcePropertiesCommand.ts @@ -1,5 +1,5 @@ import { WritableCommand, DeserializedCommand } from '../CommandBase' -import { AtemState, AtemStateUtil } from '../../state' +import { AtemState, AtemStateUtil, InvalidIdError } from '../../state' import { SuperSourceProperties, SuperSourceBorder } from '../../state/video/superSource' import { ProtocolVersion } from '../../enums' @@ -192,7 +192,7 @@ export class SuperSourcePropertiesUpdateCommand extends DeserializedCommand<{ pr public applyToState (state: AtemState) { if (!state.info.capabilities || !state.info.capabilities.superSources) { - throw new Error(`SuperSource 0 is not valid`) + throw new InvalidIdError('SuperSource', 0) } const supersource = AtemStateUtil.getSuperSource(state, 0) @@ -234,7 +234,7 @@ export class SuperSourcePropertiesUpdateV8Command extends DeserializedCommand= state.info.capabilities.superSources) { - throw new Error(`SuperSource ${this.ssrcId} is not valid`) + throw new InvalidIdError('SuperSource', this.ssrcId) } const supersource = AtemStateUtil.getSuperSource(state, this.ssrcId) @@ -280,7 +280,7 @@ export class SuperSourceBorderUpdateCommand extends DeserializedCommand= state.info.capabilities.superSources) { - throw new Error(`SuperSource ${this.ssrcId} is not valid`) + throw new InvalidIdError('SuperSource', this.ssrcId) } const supersource = AtemStateUtil.getSuperSource(state, this.ssrcId) diff --git a/src/lib/__tests__/atemSocket.spec.ts b/src/lib/__tests__/atemSocket.spec.ts index 140e3b903..f492d3473 100644 --- a/src/lib/__tests__/atemSocket.spec.ts +++ b/src/lib/__tests__/atemSocket.spec.ts @@ -86,11 +86,10 @@ describe('AtemSocket', () => { function createSocket () { return new AtemSocket({ - debug: false, + debugBuffers: false, address: '', port: 890, - disableMultithreaded: true, - log: console.log + disableMultithreaded: true }) } @@ -115,7 +114,7 @@ describe('AtemSocket', () => { // New child was constructed expect(AtemSocketChild).toHaveBeenCalledTimes(1) - expect(AtemSocketChild).toHaveBeenCalledWith({ address: '', port: 890, debug: false }, expect.toBeFunction(), expect.toBeFunction(), expect.toBeFunction(), expect.toBeFunction()) + expect(AtemSocketChild).toHaveBeenCalledWith({ address: '', port: 890, debugBuffers: false }, expect.toBeFunction(), expect.toBeFunction(), expect.toBeFunction(), expect.toBeFunction()) }) test('connect initial with params', async () => { const socket = createSocket() @@ -134,7 +133,7 @@ describe('AtemSocket', () => { // New child was constructed expect(AtemSocketChild).toHaveBeenCalledTimes(1) - expect(AtemSocketChild).toHaveBeenCalledWith({ address: 'abc', port: 765, debug: false }, expect.toBeFunction(), expect.toBeFunction(), expect.toBeFunction(), expect.toBeFunction()) + expect(AtemSocketChild).toHaveBeenCalledWith({ address: 'abc', port: 765, debugBuffers: false }, expect.toBeFunction(), expect.toBeFunction(), expect.toBeFunction(), expect.toBeFunction()) }) test('connect change details', async () => { const socket = createSocket() diff --git a/src/lib/__tests__/socket-child.spec.ts b/src/lib/__tests__/socket-child.spec.ts index 0538a6662..8c6c5d1b9 100644 --- a/src/lib/__tests__/socket-child.spec.ts +++ b/src/lib/__tests__/socket-child.spec.ts @@ -38,7 +38,7 @@ function createSocketChild ( { address: ADDRESS, port: DEFAULT_PORT, - debug: false + debugBuffers: false }, onDisconnect || (() => Promise.resolve()), // async msg => { console.log(msg) }, diff --git a/src/lib/atemSocket.ts b/src/lib/atemSocket.ts index ff3683967..280fd1482 100644 --- a/src/lib/atemSocket.ts +++ b/src/lib/atemSocket.ts @@ -9,14 +9,12 @@ import { AtemSocketChild } from './atemSocketChild' export interface AtemSocketOptions { address: string port: number - debug: boolean + debugBuffers: boolean disableMultithreaded: boolean - - log: (...args: any[]) => void } export class AtemSocket extends EventEmitter { - private readonly _debug: boolean + private readonly _debugBuffers: boolean private readonly _disableMultithreaded: boolean private readonly _commandParser: CommandParser = new CommandParser() @@ -26,14 +24,16 @@ export class AtemSocket extends EventEmitter { private _socketProcess: ThreadedClass | undefined private _exitUnsubscribe?: () => void - private readonly log: (args1: any, args2?: any, args3?: any) => void - public on!: ((event: 'disconnect', listener: () => void) => this) & + ((event: 'info', listener: (message: string) => void) => this) & + ((event: 'debug', listener: (message: string) => void) => this) & ((event: 'error', listener: (message: string) => void) => this) & ((event: 'commandsReceived', listener: (cmds: IDeserializedCommand[]) => void) => this) & ((event: 'commandsAck', listener: (trackingIds: number[]) => void) => this) public emit!: ((event: 'disconnect') => boolean) & + ((event: 'info', message: string) => boolean) & + ((event: 'debug', message: string) => boolean) & ((event: 'error', message: string) => boolean) & ((event: 'commandsReceived', cmds: IDeserializedCommand[]) => boolean) & ((event: 'commandsAck', trackingIds: number[]) => boolean) @@ -42,9 +42,8 @@ export class AtemSocket extends EventEmitter { super() this._address = options.address this._port = options.port - this._debug = options.debug + this._debugBuffers = options.debugBuffers this._disableMultithreaded = options.disableMultithreaded - this.log = options.log } public async connect (address?: string, port?: number): Promise { @@ -96,7 +95,7 @@ export class AtemSocket extends EventEmitter { } const payload = cmd.rawCommand.serialize(this._commandParser.version) - if (this._debug) this.log('PAYLOAD', cmd.rawCommand.constructor.name, payload) + if (this._debugBuffers) this.emit('debug', `PAYLOAD ${cmd.rawCommand.constructor.name} ${payload.toString('hex')}`) return { payload: [...payload], @@ -116,10 +115,10 @@ export class AtemSocket extends EventEmitter { { address: this._address, port: this._port, - debug: this._debug + debugBuffers: this._debugBuffers }, async () => { this.emit('disconnect') }, // onDisconnect - async (message: string) => this.log(message), // onLog + async (message: string) => { this.emit('info', message) }, // onLog async (payload: Buffer) => this._parseCommands(Buffer.from(payload)), // onCommandsReceived async (ids: Array<{ packetId: number, trackingId: number }>) => { this.emit('commandsAck', ids.map(id => id.trackingId)) } // onCommandsAcknowledged ], { @@ -168,8 +167,8 @@ export class AtemSocket extends EventEmitter { } catch (e) { this.emit('error', `Failed to deserialize command: ${cmdConstructor.constructor.name}: ${e}`) } - } else if (this._debug) { - this.log(`Unknown command ${name} (${length}b)`) + } else { + this.emit('debug', `Unknown command ${name} (${length}b)`) } // Trim the buffer diff --git a/src/lib/atemSocketChild.ts b/src/lib/atemSocketChild.ts index 00c7add0b..48e107b31 100644 --- a/src/lib/atemSocketChild.ts +++ b/src/lib/atemSocketChild.ts @@ -32,7 +32,7 @@ interface InFlightPacket { } export class AtemSocketChild { - private readonly _debug: boolean + private readonly _debugBuffers: boolean private _connectionState = ConnectionState.Closed private _reconnectTimer: NodeJS.Timer | undefined @@ -57,8 +57,8 @@ export class AtemSocketChild { private readonly onCommandsReceived: (payload: Buffer, packetId: number) => Promise private readonly onCommandsAcknowledged: (ids: Array<{ packetId: number, trackingId: number }>) => Promise - constructor (options: { address: string, port: number, debug: boolean }, onDisconnect: () => Promise, onLog: (message: string) => Promise, onCommandReceived: (payload: Buffer, packetId: number) => Promise, onCommandAcknowledged: (ids: Array<{ packetId: number, trackingId: number }>) => Promise) { - this._debug = options.debug + constructor (options: { address: string, port: number, debugBuffers: boolean }, onDisconnect: () => Promise, onLog: (message: string) => Promise, onCommandReceived: (payload: Buffer, packetId: number) => Promise, onCommandAcknowledged: (ids: Array<{ packetId: number, trackingId: number }>) => Promise) { + this._debugBuffers = options.debugBuffers this._address = options.address this._port = options.port @@ -207,7 +207,7 @@ export class AtemSocketChild { } private _receivePacket (packet: Buffer, rinfo: RemoteInfo) { - if (this._debug) this.log(`RECV ${packet.toString('hex')}`) + if (this._debugBuffers) this.log(`RECV ${packet.toString('hex')}`) this._lastReceivedAt = Date.now() const length = packet.readUInt16BE(0) & 0x07ff if (length !== rinfo.size) return @@ -277,7 +277,7 @@ export class AtemSocketChild { } private _sendPacket (packet: Buffer) { - if (this._debug) this.log(`SEND ${packet.toString('hex')}`) + if (this._debugBuffers) this.log(`SEND ${packet.toString('hex')}`) this._socket.send(packet, 0, packet.length, this._port, this._address) } diff --git a/src/state/index.ts b/src/state/index.ts index e52cb89b4..f50dfb999 100644 --- a/src/state/index.ts +++ b/src/state/index.ts @@ -17,3 +17,18 @@ export interface AtemState { macro: MacroState settings: SettingsState } + +export class InvalidIdError extends Error { + constructor (message: string, ...ids: number[]) { + super(InvalidIdError.BuildErrorString(message, ids)) + Object.setPrototypeOf(this, new.target.prototype) + } + + private static BuildErrorString (message: string, ids: number[]) { + if (ids && ids.length > 0) { + return `${message} ${ids.join('-')} is not valid` + } else { + return message + } + } +} From 77ef0d164df68f4f2340ab732cd8c5d7c96818c2 Mon Sep 17 00:00:00 2001 From: Julian Waller Date: Wed, 15 Jan 2020 13:54:23 +0000 Subject: [PATCH 67/68] fix: do a todo --- src/lib/atemSocketChild.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lib/atemSocketChild.ts b/src/lib/atemSocketChild.ts index 48e107b31..40f3c0267 100644 --- a/src/lib/atemSocketChild.ts +++ b/src/lib/atemSocketChild.ts @@ -17,7 +17,7 @@ export enum ConnectionState { export enum PacketFlag { AckRequest = 0x01, - Connect = 0x02, // TODO - 'new session id'? or something like that + NewSessionId = 0x02, IsRetransmit = 0x04, RetransmitRequest = 0x08, AckReply = 0x10 @@ -217,7 +217,7 @@ export class AtemSocketChild { const remotePacketId = packet.readUInt16BE(10) // Send hello answer packet when receive connect flags - if (flags & PacketFlag.Connect) { + if (flags & PacketFlag.NewSessionId) { this._connectionState = ConnectionState.Established this._lastReceivedPacketId = remotePacketId this._sendAck(remotePacketId) From cdad157063f1ca744ecb228c97fa105eb8dae679 Mon Sep 17 00:00:00 2001 From: Balte de Wit Date: Fri, 17 Jan 2020 11:55:19 +0100 Subject: [PATCH 68/68] chore: add test case for TVS HD 8.1 --- src/__tests__/connection.spec.ts | 1 + src/__tests__/connection/tvshd-v8.1.0.data | 5 +++++ 2 files changed, 6 insertions(+) create mode 100644 src/__tests__/connection/tvshd-v8.1.0.data diff --git a/src/__tests__/connection.spec.ts b/src/__tests__/connection.spec.ts index f47e4d964..a5ced58f8 100644 --- a/src/__tests__/connection.spec.ts +++ b/src/__tests__/connection.spec.ts @@ -89,6 +89,7 @@ describe('connection', () => { runTestMe1('ps4k v7.2', 'ps4k-v7.2') runTestMe1('4me4k v7.5.2', '4me4k-v7.5.2') runTestMe1('tvshd v8.0.0', 'tvshd-v8.0.0') + runTestMe1('tvshd v8.1.0', 'tvshd-v8.1.0') runTestMe1('constellation v8.0.2', 'constellation-v8.0.2') runTestMe1('2me v8.1', '2me-v8.1') runTestMe1('mini v8.1', 'mini-v8.1') diff --git a/src/__tests__/connection/tvshd-v8.1.0.data b/src/__tests__/connection/tvshd-v8.1.0.data new file mode 100644 index 000000000..3e0e7dc31 --- /dev/null +++ b/src/__tests__/connection/tvshd-v8.1.0.data @@ -0,0 +1,5 @@ +000c7ffd5f7665720002001d003400005f70696e4154454d2054656c65766973696f6e2053747564696f204844000000001000004d50727000460000080000000020fffe5f746f70011802010402010401000001010400000001010101000000000c00065f4d654300010000000c00005f6d706c14007270001400005f4d7643010a01010000010101000000000c00005f414d430a00017000c200005f564d43000e6c430050727000000080000000000001496e4d0000004000000000000200001000000080000000000003000000000000400000000000040000000000001000000000000519020800000020000000000006004d500000004000000000000700100000000080000000000008000000000001000000000000090000000000020000000000000a7000550000044000000000000b4d50720000088000000000000c10ffff0000144000000000000d000000000028800000000000000c00005f4d4143646e4d50002000595f44564500000011101112131415161718191a1b1c1d1e1f22fd4d50000c005b506f777201000010000c4d505669644d06000000000c00105633736c0070005d000c000054634c6b00004d50002c005e496e50720000426c61636b007270005f00000000000000100000426c6b0001600100010001001301002c4d50496e50720001547279206d65206e6f770070006200000000000043616d3100500002000200001301002c000c496e5072000243616d65726120320050744d01507270000c000043616d3201000002000200701301002c0000496e5072000343616d657261203300000000001000004d50727043616d3301000002000200431301002c0011496e5072000443616d657261203400120000000000000010ffff43616d3401130002000200001301002c4d50496e5072000543616d657261203500507270001500000000000043616d3501500001000100001301002c0010496e5072000643617370617243472046756c6c0072700018000046756c6c00100001000100701301002c0000496e5072000743617370617243472046696c6c0070504d50727043472d4600000001000100001301002c001c496e507200084361737061724347204b6579000000000010000043472d4b001e0001000100001301002c4d50496e507203e8436f6c6f722042617273007000200000000000004261727301500100010002001301002c0010496e507207d1436f6c6f72203100001000004d50727000230000436f6c3101100100010003700301002c0000496e507207d2436f6c6f7220320000000000001050744d507270436f6c3201000100010003530301002c0027496e50720bc24d6564696120506c6179657220310000001001004d50310001290100010004001301002c4d50496e50720bc34d6564696120506c617965722031204b657900004d50314b01500100010005001301002c0010496e50720bcc4d6564696120506c6179657220320070002e00004d50320001100100010004701301002c0000496e50720bcd4d6564696120506c617965722032204b657900704d50324b01000100010005021301002c0032496e50720faa4b65792031204d61736b000504000000040000004d314b3101550100010082000300002c803e496e5072139244534b2031204d61736b000010b4010228550605444b314d01000100010082020300002c6102496e5072139c44534b2032204d61736b0000010000005c230102444b324d013f0100010082020300002c0000496e5072271a50726f6772616d000000000062020b027864697550676d0001490100010080000300002c6d61496e5072271b5072657669657700e427190200000000f0df00025076770001000100010080000300002c0000496e50721b59436c65616e20466565642031000aadde0a0aadde4366643101110100010080020300 +002c7ffd496e50721b5a436c65616e20466565642032004d2054656c657643666432012001000100806f0300002c0000496e50721f41417578696c69617279203100fffe5f746f7001184175783101040100010081040200000c01014d76564d00070006000c65434d76564d01060000000c706c4d76564d02070000000c76434d76564d03060101000c00004d76564d04044d43000c01704d76564d05054d43000c6c434d76564d06060080000c00004d76564d07070000000c00004d76564d08080000000c00004d76564d09090000000c40004d76564d0a060000000c00104d76564d0b071902000c00004d76564d0c060600000c00004d76564d0d070007000c00004d765072000c0000001000004d76496e0000271b00010000000c000256754d4300000070000c000053614d770000000b001072004d76496e0001271a0100ffff000c144056754d4300010100000c002853614d770001000c00105f4d4d76496e0002000101005f44000c000056754d4300020015000c181953614d77000200fd0010000c4d76496e000300020100000c000c566956754d430003000c000c563353614d770003000c001054634d76496e000400030100496e000c000056754d4300040070000c000053614d770004000000106b004d76496e000500040100002c000c496e56754d4300050020000c206e53614d7700050000001000004d76496e00061f4101000000000c002c56754d4300060002000c6d6553614d770006004d001072704d76496e0007000601000002000c007056754d430007016e000c000353614d7700070033001000004d76496e0008000701006d33000c000256754d430008012c000c496e53614d7700080065001020344d76496e000900080100ffff000c6d3456754d4300090000000c002c53614d7700090005000c6d6556754d6f00647270000c000050726749006100000010000150727649000100000010496e0010000654725353000001000146756c000c72705472507200006c6c00100001547250730000192c0000496e000c0007544d785000194347000c696c5444705000190000001c2d46545770500019010000000000138800001388138800007370001c4347544476500019191b00000000000000000000000000010000001c002c54537450000100e800000000002000020049002200050000000c00004b654f6e00000000001c02004b65425000000001010000000000006f0000000000000000001472704b654c6d0000003100000000000003700014002c4b65436b000000000000000000000000001800004b6550740000007000001388000001f401f400530044002c4b65445600000bc200000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000017965720010204b4b6546530000000000500000003c05004b4b46500000016e000003e8000003e8000000000000000000000000000000000000000000100000000003e80168192c0000000000000000003c64694b4b465000000272000003e8000003e8000000000000000000000000000000000000000000720000000003e80168196100000000000000000010000044736b420055000700088200001c002c44736b5000001900000000000000000000000000000001020010060544736b5300000000011982020010002c44736b420172000000004b20001c4d6144736b5001001900000000000000000000000000000082020010002c44736b530100000001196f67000c6d004674625000190b02000c6975467462530000001900108000436f6c56006101f403e801f400106576436f6c560127010e03e801f4000c00024175785300001b59002880004d5066650000000001c359bf3a0000000000000000000000000a00067465737420306431 +00287ffd4d506665005a000101c359bf3a0000000000000000000000007600067465737420360100002003004d506665006e00020000000000000000000000000000000000740000002041754d5066650000000300000000000000000000000000000000000c00000020564d4d506665000c00040000000000000000000000000000000000060000002000004d506665000400050000000000000000000000000000000000760000002000804d5066650076000600000000000000000000000000000000000c00000020564d4d506665000c00070000000000000000000000000000000000070000002000004d506665000600080000000000000000000000000000000000760000002000004d506665007600090000000000000000000000000000000000000000002000004d5066650000000a00000000000000000000000000000000000c000000204d434d506665000c000b000000000000000000000000000000000002000000205f444d5066650075000c00000000000000000000000000000000001000000020496e4d5066650000000d00000000000000000000000000000000006100000020000c4d5066650076000e0000000000000000000000000000000000040000002000004d5066650004000f00000000000000000000000000000000000c000000204d434d506665000c00100000000000000000000000000000000000060000002000004d5066650075001100000000000000000000000000000000001000000020496e4d506665000000120000000000000000000000000000000000610000002000334d506665007600130000000000000000000000000000000000080000000c496e4d50434500010000000c20344d50434501010100001cffff52584d5300004d43c0a8016f0007012c0008017700020005001c6d655258435000000100000c000000000000000000000000000100287649525853530000496e00000000ffffffff000000000046756c000000000000000000006c6c000c0001525843430000002c001c496e52584d53000178500a00012c0000006c0000015000020000001c2d4652584350000101000000000000000000000000000000737000284347525853530001191b00000000ffffffff00000000000100000000000000000000000000e8000c00005258434300010022001c000052584d5300024f6e00000000000000000000005000020001001c000052584350000201000000000000000000000000000000003100280000525853530002002c00000000ffffffff0000000000000000000000000000000000000070000c13885258434300020053001c002c52584d5300030bc200000000000000000000000000020000001c000052584350000301000000000000000000000000000000000000280000525853530003657200000000ffffffff000000000050000000000000000000000000016e000c03e85258434300030000000c0000414d50500000000000180000414d4950000100e800010002000080000000000000186469414d49500002007200020002000080000000000000180000414d49500003000000030002007280000000000000181961414d49500004000000040002007380000000000000188200414d49500005005000050001000080000000000000180000414d4950000600050006000100008000000000000018002c414d49500007000000070001001c80000000000000181900414d49500008000000080001000080000000000000186b53414d49500515026700000200007400000000000000186975414d495003e9021900010020016f800000000100001001f4414d4d4f800000000027010e002801f4414d546c000a00010000020000030000040000050000060000070000080005150003e90100100000414d485040000000287a287a000c010041544d5000000100 +00107ffd544d4950005a0005010100bf00100000544d4950000000060101000600107374544d4950002000070101006500100002544d49500000000801010000001400004d4d4f50000103000150000501000003001400004d4d4f500101030001000006010000000014564d4d4d4f50020103000100000701000000001400004d4d4f50030103000120000801000065000c00054c4b535400000000001000005f546c43000100000820008000146665546c496e00080000000000000000000000540000546c5372001800000300010000020000030000040000050000060000070000080003e80007d10007d2000bc2000bc3000bcc000bcd000faa00139200139c00271a00271b001b59001b5a001f4100000900240000546c466300080001000002000003000004000005000006000007000008000000000c00004d5250720000ffff000c00004d526353005000000010000b4d5072700000000000000000001c00004d50727000010100000900006661646520746f2031000000001000004d5072700002000000000000001066654d5072700003000000000000001000004d5072700004000000000000001066654d5072700005000000000000001000004d5072700006000000000000001066654d5072700007000000000000001000004d5072700008000000000000001066654d5072700009000000000000001000004d507270000a000000000000001066654d507270000b000000000000001000004d507270000c000000000000001066654d507270000d000000000000001000004d507270000e000000000000001066654d507270000f000000000000002800004d507270001001000009000e456e7465722048454c547765656e20696e746f2048454cff00284d534d5072700011010000080010457869742048454c547765656e206f7574206f662048454c001000004d5072700012000000000000001053534d5072700013000000000000001000004d507270001400000000000000106c6c4d50727000150000000000000010496e4d50727000160000000000000010006c4d5072700017000000000000001043504d5072700018000000000000001000004d50727000190000000000000010191b4d507270001a000000000000001000004d507270001b000000000000001000004d507270001c00000000000000104d534d507270001d000000000000001000504d507270001e000000000000001001004d507270001f000000000000001000314d5072700020000000000000001000004d5072700021000000000000001000004d5072700022000000000000001043434d507270002300000000000000100bc24d5072700024000000000000001000004d5072700025000000000000001000004d5072700026000000000000001000004d50727000270000000000000010ffff4d5072700028000000000000001000004d5072700029000000000000001000004d507270002a000000000000001000004d507270002b000000000000001080004d507270002c000000000000001000724d507270002d000000000000001000004d507270002e000000000000001080004d507270002f000000000000001000004d5072700030000000000000001082004d5072700031000000000000001080004d5072700032000000000000001000054d50727000330000000000000010002c4d5072700034000000000000001080004d5072700035000000000000001000004d507270003600000000000000106b534d5072700037000000000000001000004d5072700038000000000000001002194d5072700039000000000000001001f44d507270003a000000000000001001f44d507270003b000000000000001000004d507270003c000000000000001005154d507270003d000000000000001000004d507270003e000000000000 +00107ffd4d507270003f000000000000001000004d5072700040000000000000001073744d5072700041000000000000001000024d5072700042000000000000001000004d5072700043000000000000001000034d5072700044000000000000001000064d5072700045000000000000001003004d507270004600000000000000104f504d5072700047000000000000001000054d507270004800000000000000106c434d50727000490000000000000010496e4d507270004a000000000000001000004d507270004b000000000000001000004d507270004c000000000000001000084d507270004d0000000000000010c3004d507270004e000000000000001000274d507270004f000000000000001000094d5072700050000000000000001002004d5072700051000000000000001000004d50727000520000000000000010ffff4d50727000530000000000000010000b4d5072700054000000000000001000004d5072700055000000000000001064654d5072700056000000000000001072704d5072700057000000000000001072704d5072700058000000000000001072704d5072700059000000000000001072704d507270005a000000000000001072704d507270005b000000000000001072704d507270005c000000000000001072704d507270005d000000000000001072704d507270005e000000000000001072704d507270005f000000000000001072704d5072700060000000000000001072704d5072700061000000000000001072704d5072700062000000000000001072704d5072700063000000000000000c72704343737400001388000c00005350744d01100100000c000e53505a5300009600000c7765505a435300746f20000c4cff496e436d01507270 \ No newline at end of file