-
Notifications
You must be signed in to change notification settings - Fork 0
/
test.js
133 lines (110 loc) · 4.99 KB
/
test.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
const net = require('net')
const port = 15740
const host = '192.168.1.132'
const PTPPacketType = {
Invalid: 0,
InitCommandRequest: 1,
InitCommandAck: 2,
InitEventRequest: 3,
InitEventAck: 4,
InitFail: 5,
OperationRequest: 6,
OperationResponse: 7,
Event: 8,
StartDataPacket: 9,
DataPacket: 10,
CancelTransaction: 11,
EndDataPacket: 12,
Ping: 13,
Pong: 14,
}
const PTPVersion = Buffer.from([0x00, 0x00, 0x01, 0x00])
const PTPPacketGenerator = {
initCommandRequest (guid, hostname) {
// allocate buffer with space for length, type, guid, hostname, and version
const payload = Buffer.alloc(4 + 4 + 16 + (hostname.length * 2 + 2) + 4)
payload.writeInt32LE(payload.length, 0)
payload.writeInt32LE(PTPPacketType.InitCommandRequest, 4)
payload.fill(guid, 8, 24, 'hex')
payload.fill(hostname, 24, 24 + hostname.length * 2, 'utf16le')
payload.fill(PTPVersion, 24 + hostname.length * 2 + 2) // +2 leaves null reference character to indicate end of hostname
return payload
},
InitEventRequest (connectionNumber) {
// allocate buffer with length, type, and command connection number
const payload = Buffer.alloc(12)
payload.writeInt32LE(payload.length, 0)
payload.writeInt32LE(PTPPacketType.InitEventRequest, 4)
payload.writeInt32LE(connectionNumber, 8)
return payload
}
}
const commandClient = new net.Socket()
const eventClient = new net.Socket()
commandClient.connect(port, host, function () {
console.log('Command Connected')
const payload = PTPPacketGenerator.initCommandRequest('ffffffffffffffffffffffffffffffff', 'PTPIP Test')
commandClient.write(payload)
})
commandClient.on('data', function (data) {
const typeInt = data.readUInt16LE(4)
const type = Object.keys(PTPPacketType).find(key => PTPPacketType[key] === typeInt)
console.log(`Received Command Packet of type ${type}`)
switch (typeInt) {
case PTPPacketType.InitCommandAck:
const connectionNumber = data.readUInt16LE(8)
const guid = data.toString('hex', 12, 28)
const hostname = data.toString('utf16le', 28, data.length - 6)
console.log(`Received: ${type} | Connection #: ${connectionNumber} | ${guid} | ${hostname}`)
eventClient.connect(port, host, function () {
console.log('Event Connected')
const payload = PTPPacketGenerator.InitEventRequest(connectionNumber)
eventClient.write(payload)
})
break
}
})
commandClient.on('close', function () {
console.log('Command Connection Closed')
eventClient.destroy() // kill client on close..?
commandClient.destroy() // kill client on close..?
})
eventClient.on('data', function (data) {
const typeInt = data.readUInt16LE(4)
const type = Object.keys(PTPPacketType).find(key => PTPPacketType[key] === typeInt)
console.log(`Received Event Packet of type ${type}`)
switch (typeInt) {
// If the init was successful then extend the lens and start the intervalometer
case PTPPacketType.InitEventAck:
// OpenSession (not sure what this is or if needed... taken from wireshark)
commandClient.write(Buffer.from('16000000060000000100000002100000000041000000', 'hex'))
// Needed to prevent camera connection timeout
setTimeout(function () {
// Operation Code: CANON_EOS_SetRemoteMode (0x9114)
commandClient.write(Buffer.from('16000000060000000100000014910100000015000000', 'hex'))
}, 1000)
setTimeout(function () {
// G7X extend lens. From what I can tell this is a non-standard PTP packet, and
// there is some additional data in the "End Data Packet" that wireshark doesn't
// recognize (the data starting at c000000b0d1000008000000).
commandClient.write(Buffer.from('120000000600000002000000109101000000', 'hex')) //Operation Code: CANON_EOS_SetDevicePropValueEx (0x9110)
commandClient.write(Buffer.from('1400000009000000010000000c00000000000000', 'hex')) //Packet Type: Start Data Packet (0x00000009)
commandClient.write(Buffer.from('180000000c000000930000000c000000b0d1000008000000', 'hex')) //Packet Type: End Data Packet (0x0000000c)
// Trigger shutter & release every X sec
setInterval(function () {
commandClient.write(Buffer.from('1a000000060000000100000028919a0100000300000001000000', 'hex')) // trigger shutter [Operation Code: CANON_EOS_RemoteReleaseOn (0x9128)]
commandClient.write(Buffer.from('16000000060000000100000029919c01000003000000', 'hex')) // release shutter [Operation Code: CANON_EOS_RemoteReleaseOff (0x9129)]
}, 3000)
// Send keepalive packet X sec
setInterval(function () {
commandClient.write(Buffer.from('1200000006000000010000002f9013000000', 'hex')) // keepalive?
}, 5000)
}, 2000)
break
}
})
eventClient.on('close', function () {
console.log('Event Connection Closed')
eventClient.destroy() // kill client on close..?
commandClient.destroy() // kill client on close..?
})