Skip to content

Commit

Permalink
feat: refactor the async handlers to be chosen more dynamically
Browse files Browse the repository at this point in the history
  • Loading branch information
Julusian committed Oct 12, 2018
1 parent 8acf897 commit 0605108
Show file tree
Hide file tree
Showing 9 changed files with 102 additions and 77 deletions.
9 changes: 9 additions & 0 deletions src/asyncHandlers/iHandler.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { AsynchronousCode } from '../codes'
import { ResponseMessage } from '../message'

export interface IHandler {
responseCode: AsynchronousCode
eventName: string

deserialize (msg: ResponseMessage): any
}
3 changes: 3 additions & 0 deletions src/asyncHandlers/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export * from './iHandler'
export * from './slotInfo'
export * from './transportInfo'
29 changes: 29 additions & 0 deletions src/asyncHandlers/slotInfo.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { SlotId, VideoFormat, SlotStatus } from '../enums'
import { ResponseMessage } from '../message'
import { parseIntIfDefined } from '../util'
import { IHandler } from './iHandler'
import { AsynchronousCode } from '../codes'

export interface SlotInfoChangeResponse {
SlotId: SlotId
Status?: SlotStatus
VolumeName?: string
RecordingTime?: number
VideoFormat?: VideoFormat
}

export class SlotInfoChange implements IHandler {
responseCode = AsynchronousCode.SlotInfo
eventName = 'notify.transport'

deserialize (msg: ResponseMessage) {
const res: SlotInfoChangeResponse = {
SlotId: parseInt(msg.Params['slot id'], 10),
Status: msg.Params['status'] as SlotStatus,
VolumeName: msg.Params['volume name'],
RecordingTime: parseIntIfDefined(msg.Params['recording time']),
VideoFormat: msg.Params['video format'] as VideoFormat
}
return res
}
}
37 changes: 37 additions & 0 deletions src/asyncHandlers/transportInfo.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { TransportStatus, SlotId, VideoFormat } from '../enums'
import { ResponseMessage } from '../message'
import { parseIdOrNone, parseIntIfDefined, parseBool } from '../util'
import { IHandler } from './iHandler'
import { AsynchronousCode } from '../codes'

export interface TransportInfoChangeResponse {
Status?: TransportStatus
Speed?: number
SlotId?: SlotId | null
ClipId?: number | null
SingleClip?: boolean
DisplayTimecode?: string
Timecode?: string
VideoFormat?: VideoFormat
Loop?: boolean
}

export class TransportInfoChange implements IHandler {
responseCode = AsynchronousCode.TransportInfo
eventName = 'notify.transport'

deserialize (msg: ResponseMessage) {
const res: TransportInfoChangeResponse = {
Status: msg.Params['status'] as TransportStatus,
Speed: parseIntIfDefined(msg.Params['speed']),
SlotId: parseIdOrNone(msg.Params['slot id']),
ClipId: parseIdOrNone(msg.Params['clip id']),
SingleClip: parseBool(msg.Params['single clip']),
DisplayTimecode: msg.Params['display timecode'],
Timecode: msg.Params['timecode'],
VideoFormat: msg.Params['video format'] as VideoFormat,
Loop: parseBool(msg.Params['loop'])
}
return res
}
}
2 changes: 1 addition & 1 deletion src/commands/notify.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { SynchronousCode } from '../codes'
import { ResponseMessage, NamedMessage } from '../message'
import { AbstractCommandBase, AbstractCommandBaseNoResponse } from './abstractCommand'
import { SetBoolIfDefined } from './util'
import { SetBoolIfDefined } from '../util'

export interface NotifyCommandResponse {
Remote: boolean
Expand Down
23 changes: 0 additions & 23 deletions src/commands/slotInfo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import { SynchronousCode } from '../codes'
import { SlotId, VideoFormat, SlotStatus } from '../enums'
import { ResponseMessage, NamedMessage } from '../message'
import { AbstractCommandBase } from './abstractCommand'
import { parseIntIfDefined } from './util'

export interface SlotInfoCommandResponse {
SlotId: SlotId
Expand Down Expand Up @@ -34,25 +33,3 @@ export class SlotInfoCommand extends AbstractCommandBase<SlotInfoCommandResponse
return res
}
}

export interface SlotInfoChangeResponse {
SlotId: SlotId
Status?: SlotStatus
VolumeName?: string
RecordingTime?: number
VideoFormat?: VideoFormat
}

export class SlotInfoChange {

deserialize (msg: ResponseMessage) {
const res: SlotInfoChangeResponse = {
SlotId: parseInt(msg.Params['slot id'], 10),
Status: msg.Params['status'] as SlotStatus,
VolumeName: msg.Params['volume name'],
RecordingTime: parseIntIfDefined(msg.Params['recording time']),
VideoFormat: msg.Params['video format'] as VideoFormat
}
return res
}
}
32 changes: 1 addition & 31 deletions src/commands/transportInfo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { SynchronousCode } from '../codes'
import { TransportStatus, SlotId, VideoFormat } from '../enums'
import { ResponseMessage, NamedMessage } from '../message'
import { AbstractCommandBase } from './abstractCommand'
import { parseIdOrNone, parseIntIfDefined, parseBool } from './util'
import { parseIdOrNone, parseBool } from '../util'

export interface TransportInfoCommandResponse {
Status: TransportStatus
Expand Down Expand Up @@ -42,33 +42,3 @@ export class TransportInfoCommand extends AbstractCommandBase<TransportInfoComma
return res
}
}

export interface TransportInfoChangeResponse {
Status?: TransportStatus
Speed?: number
SlotId?: SlotId | null
ClipId?: number | null
SingleClip?: boolean
DisplayTimecode?: string
Timecode?: string
VideoFormat?: VideoFormat
Loop?: boolean
}

export class TransportInfoChange {

deserialize (msg: ResponseMessage) {
const res: TransportInfoChangeResponse = {
Status: msg.Params['status'] as TransportStatus,
Speed: parseIntIfDefined(msg.Params['speed']),
SlotId: parseIdOrNone(msg.Params['slot id']),
ClipId: parseIdOrNone(msg.Params['clip id']),
SingleClip: parseBool(msg.Params['single clip']),
DisplayTimecode: msg.Params['display timecode'],
Timecode: msg.Params['timecode'],
VideoFormat: msg.Params['video format'] as VideoFormat,
Loop: parseBool(msg.Params['loop'])
}
return res
}
}
42 changes: 21 additions & 21 deletions src/hyperdeck.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@ import { EventEmitter } from 'events'
import { Socket } from 'net'

import { ResponseCodeType, GetResponseCodeType, AsynchronousCode } from './codes'
import { AbstractCommand, TransportInfoChange, SlotInfoChange } from './commands'
import { AbstractCommand } from './commands'
import * as AsyncHandlers from './asyncHandlers'
import { ResponseMessage } from './message'
import { DummyConnectCommand, WatchdogPeriodCommand, PingCommand } from './commands/internal'
import { parseResponse, buildMessageStr } from './parser'
Expand All @@ -26,6 +27,7 @@ export class Hyperdeck extends EventEmitter {
private _pingPeriod: number = 5000
private _pingInterval: NodeJS.Timer | null = null
private _lastCommandTime: number = 0
private _asyncHandlers: {[key: number]: AsyncHandlers.IHandler} = {}

constructor (options?: HyperdeckOptions) {
super()
Expand All @@ -49,14 +51,23 @@ export class Hyperdeck extends EventEmitter {
this.emit('disconnected')
}) // TODO - should this be on close?
this.socket.on('data', (d) => this._handleData((d as any) as string)) // TODO - fix this casting mess

for (const h in AsyncHandlers) {
try {
const handler: AsyncHandlers.IHandler = new (AsyncHandlers as any)[h]()
this._asyncHandlers[handler.responseCode] = handler
} catch (e) {
// ignore as likely not a class
}
}
}

connect (address: string, port?: number) {
// TODO - ensure not already connected

const connCommand = new DummyConnectCommand()
connCommand.then(c => {
if (c.ProtocolVersion !== 1.5) {
if (c.ProtocolVersion !== 1.6) {
throw new Error('unknown protocol version: ' + c.ProtocolVersion)
}

Expand Down Expand Up @@ -207,28 +218,17 @@ export class Hyperdeck extends EventEmitter {
}

private _handleAsyncResponse (msg: ResponseMessage) {
// TODO - refactor to pick the handler dynamically
switch (msg.Code) {
case AsynchronousCode.ConnectionInfo:
// Only received at startup, and handled by a command
break
case AsynchronousCode.TransportInfo:
{
const handler = new TransportInfoChange()
const r = handler.deserialize(msg)
this.emit('notify.transport', r)
break
}
case AsynchronousCode.SlotInfo:
{
const handler = new SlotInfoChange()
const r = handler.deserialize(msg)
this.emit('notify.slot', r)
break
}
default:
this._log('unknown async response:', msg)
break
return
}

const h = this._asyncHandlers[msg.Code]
if (h) {
this.emit(h.eventName, h.deserialize(msg))
} else {
this._log('unknown async response:', msg)
}
}
}
2 changes: 1 addition & 1 deletion src/commands/util.ts → src/util.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { NamedMessage } from '../message'
import { NamedMessage } from './message'

export function SetBoolIfDefined (msg: NamedMessage, name: string, val: boolean | undefined) {
if (val !== undefined) {
Expand Down

0 comments on commit 0605108

Please sign in to comment.