Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save toshi3221/7a9429379cb366a94a74 to your computer and use it in GitHub Desktop.
Save toshi3221/7a9429379cb366a94a74 to your computer and use it in GitHub Desktop.
require 'socket'
require './ruby_ptp_ip/ptp.rb'
require './ruby_ptp_ip/ptp_ip.rb'
# THETAのIPアドレスとPTP-IPのポート番号
ADDR = "192.168.1.1"
PORT = 15740
# THETAに送るレスポンダ情報
NAME = "Ruby_THETA_Shutter"
GUID = "ab653fb8-4add-44f0-980e-939b5f6ea266"
PROTOCOL_VERSION = 65536
class PtpInitiator
def initialize addr=ADDR, port=PORT, guid=GUID, name=NAME, protocol_version=PROTOCOL_VERSION
@transaction_id = 1
@addr = addr
@port = port
@guid = guid
@name = name
@protocol_version = protocol_version
end
# GUID文字列を整数の配列にする関数
def str2guid(str)
hexes = str.scan /([a-fA-F0-9]{2})-*/
hexes.flatten!
raise "Invalid GUID" if hexes.length != 16
hexes.map do |s|
s.hex
end
end
# パケットを書き込む関数
def write_packet(sock, pkt)
sock.send(pkt.to_data.pack("C*"), 0)
end
# パケットを読み込む関数
def read_packet(sock)
data = []
data += sock.read(PTPIP_packet::MIN_PACKET_SIZE).unpack("C*")
len = PTPIP_packet.parse_length(data)
data += sock.read(len-PTPIP_packet::MIN_PACKET_SIZE).unpack("C*")
PTPIP_packet.new(data)
end
# データフェイズの読み込み関数
def recv_data(sock, transaction_id)
recv_pkt = read_packet(sock)
raise "Invalid Packet : #{recv_pkt.to_s}" if recv_pkt.type != PTPIP_PT_StartDataPacket
raise "Invalid Transaction ID" if recv_pkt.payload.transaction_id != transaction_id
data_len = recv_pkt.payload.total_data_length_low
data = []
while recv_pkt.type != PTPIP_PT_EndDataPacket
recv_pkt = read_packet(sock)
raise "Invalid Packet : #{recv_pkt.to_s}" if recv_pkt.type != PTPIP_PT_DataPacket && recv_pkt.type != PTPIP_PT_EndDataPacket
raise "Invalid Transaction ID" if recv_pkt.payload.transaction_id != transaction_id
data += recv_pkt.payload.data_payload
end
raise "Invalid Data Size" unless data_len == data.length
return data
end
# コマンドコネクション初期化関数
def init_command
init_command_payload = PTPIP_payload_INIT_CMD_PKT.new()
init_command_payload.guid = str2guid(@guid)
init_command_payload.friendly_name = NAME
init_command_payload.protocol_version = PROTOCOL_VERSION
init_command = PTPIP_packet.create(init_command_payload)
write_packet(@command_sock, init_command)
read_packet(@command_sock)#ACK
end
# イベントコネクション初期化関数
def init_event
init_event_payload = PTPIP_payload_INIT_EVENT_REQ_PKT.new()
init_event_payload.conn_number = @conn_number
init_event = PTPIP_packet.create(init_event_payload);
write_packet(@event_sock, init_event)
read_packet(@event_sock)
end
def wait_event
read_packet @event_sock
end
# データフェイズのあるオペレーションコード実行関数
def data_operation(operation_code, parameters = [])
transaction_id = @transaction_id
@transaction_id += 1
op_payload = PTPIP_payload_OPERATION_REQ_PKT.new()
op_payload.data_phase_info = PTPIP_payload_OPERATION_REQ_PKT::NO_DATA_OR_DATA_IN_PHASE
op_payload.operation_code = operation_code
op_payload.transaction_id = transaction_id
op_payload.parameters = parameters
op_pkt = PTPIP_packet.create(op_payload)
write_packet(@command_sock, op_pkt)
data = recv_data(@command_sock, transaction_id)
recv_pkt = read_packet(@command_sock)
return recv_pkt, data
end
# シンプルなオペレーションコードの実行関数
def simple_operation(operation_code, parameters = [])
transaction_id = @transaction_id
@transaction_id += 1
op_payload = PTPIP_payload_OPERATION_REQ_PKT.new()
op_payload.data_phase_info = PTPIP_payload_OPERATION_REQ_PKT::NO_DATA_OR_DATA_IN_PHASE
op_payload.operation_code = operation_code
op_payload.transaction_id = transaction_id
op_payload.parameters = parameters
op_pkt = PTPIP_packet.create(op_payload)
write_packet(@command_sock, op_pkt)
read_packet(@command_sock)
end
def open
TCPSocket.open(@addr, @port) do |s|
@command_sock = s
# コマンドコネクション
recv_pkt = init_command
raise "Initialization Failed (Command) #{recv_pkt.payload.reason}" if recv_pkt.type == PTPIP_PT_InitFailPacket
p @conn_number = recv_pkt.payload.conn_number
p @guid = recv_pkt.payload.guid
p @name = recv_pkt.payload.friendly_name
p @protocol_version = recv_pkt.payload.protocol_version
TCPSocket.open(@addr, @port) do |es|
@event_sock = es
# イベントコネクション
recv_pkt = init_event
raise "Initialization Failed (Event) #{recv_pkt.payload.reason}" if recv_pkt.type == PTPIP_PT_InitFailPacket
print "Command/Event Connections are established.\n"
yield self
end
end
end
end
#
# ここから処理
#
PtpInitiator.new.open do |initiator|
session_id = 1
# DeviceInfoの取得とパースと表示
recv_pkt, data = initiator.data_operation(PTP_OC_GetDeviceInfo)
dev_info = PTP_DeviceInfo.create(data)
print "Device Info :\n"
p dev_info.to_s
raise "GetDeviceInfo Failed #{recv_pkt.payload.response_code}" if recv_pkt.payload.response_code != PTP_RC_OK
# セッション開始
recv_pkt = initiator.simple_operation(PTP_OC_OpenSession, [session_id])
raise "Open Session Failed #{recv_pkt.payload.response_code}" if recv_pkt.payload.response_code != PTP_RC_OK
# キャプチャ開始
# [0,0]はストレージIDとキャプチャフォーマット
# それぞれ0の時はデバイス側が判断する.
recv_pkt = initiator.simple_operation(PTP_OC_InitiateCapture, [0,0])
raise "Initiate Capture Failed #{recv_pkt.payload.response_code}" if recv_pkt.payload.response_code != PTP_RC_OK
@event_transaction_id = recv_pkt.payload.transaction_id
print "Capturing...\r"
# ObjectAddedイベントの待機
recv_pkt = initiator.wait_event
raise "Invalid Event Packet" unless recv_pkt.type == PTPIP_PT_EventPacket
raise "Invalid Event Code" unless recv_pkt.payload.event_code == PTP_EC_ObjectAdded
print "Object Added!\n"
# CaptureCompletedイベントの待機
recv_pkt = initiator.wait_event
raise "Invalid Event Packet" unless recv_pkt.type == PTPIP_PT_EventPacket
raise "Invalid Event Code" unless recv_pkt.payload.event_code == PTP_EC_CaptureComplete
print "Capture Completed!\n"
# セッション終了
recv_pkt = initiator.simple_operation(PTP_OC_CloseSession)
raise "Close Session Failed #{recv_pkt.payload.response_code}" if recv_pkt.payload.response_code != PTP_RC_OK
end
RICOH THETAで撮った写真をPTP-IPで取得する - stoikheia(@3xv)の日記 http://d.hatena.ne.jp/stoikheia/20131201
ここにあるサンプル、Socketが生書きなのでラッピングをこころみてる
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment