1 package net.osdn.gokigen.a01d.camera.fujix.wrapper.command;
3 import android.util.Log;
5 import androidx.annotation.NonNull;
7 import java.io.BufferedReader;
8 import java.io.DataOutputStream;
9 import java.io.InputStream;
10 import java.net.Socket;
11 import java.util.ArrayDeque;
12 import java.util.Arrays;
13 import java.util.Queue;
15 public class FujiXCommandIssuer implements IFujiXCommandIssuer, IFujiXCommunication
17 private final String TAG = toString();
19 private static final int SEQUENCE_START_NUMBER = 1;
20 private static final int BUFFER_SIZE = 1024 * 1024 + 8;
21 private static final int COMMAND_SEND_RECEIVE_DURATION_MS = 50;
22 private static final int COMMAND_SEND_RECEIVE_DURATION_MAX = 1000;
23 private static final int COMMAND_POLL_QUEUE_MS = 150;
25 private final String ipAddress;
26 private final int portNumber;
28 private boolean isStart = false;
29 private Socket socket = null;
30 private DataOutputStream dos = null;
31 private BufferedReader bufferedReader = null;
32 private int sequenceNumber = SEQUENCE_START_NUMBER;
33 private Queue<IFujiXCommand> commandQueue;
36 public FujiXCommandIssuer(@NonNull String ip, int portNumber)
39 this.portNumber = portNumber;
40 this.commandQueue = new ArrayDeque<>();
45 public boolean isConnected()
47 return (socket != null);
51 public boolean connect()
55 socket = new Socket(ipAddress, portNumber);
67 public void disconnect()
82 bufferedReader.close();
88 bufferedReader = null;
99 sequenceNumber = SEQUENCE_START_NUMBER;
108 // すでにコマンドのスレッド動作中なので抜ける
112 Thread thread = new Thread(new Runnable()
123 IFujiXCommand command = commandQueue.poll();
126 issueCommand(command);
128 Thread.sleep(COMMAND_POLL_QUEUE_MS);
138 Log.v(TAG, "<<<<< IP : " + ipAddress + " port : " + portNumber + " >>>>>");
157 commandQueue.clear();
161 public boolean enqueueCommand(@NonNull IFujiXCommand command)
165 //Log.v(TAG, "Enqueue : " + command.getId());
166 return (commandQueue.offer(command));
175 private void issueCommand(@NonNull IFujiXCommand command)
179 //Log.v(TAG, "issueCommand : " + command.getId());
180 byte[] commandBody = command.commandBody();
181 if (commandBody != null)
183 // コマンドボディが入っていた場合には、コマンド送信(入っていない場合は受信待ち)
184 send_to_camera(command.dumpLog(), commandBody, command.useSequenceNumber());
185 byte[] commandBody2 = command.commandBody2();
186 if (commandBody2 != null)
188 // コマンドボディの2つめが入っていた場合には、コマンドを連続送信する
189 send_to_camera(command.dumpLog(), commandBody2, command.useSequenceNumber());
191 if (command.isIncrementSeqNumber())
197 int delayMs = command.receiveDelayMs();
198 if ((delayMs < 0)||(delayMs > COMMAND_SEND_RECEIVE_DURATION_MAX))
200 delayMs = COMMAND_SEND_RECEIVE_DURATION_MS;
202 receive_from_camera(command.dumpLog(), command.getId(), command.responseCallback(), command.receiveAgainShortLengthMessage(), delayMs);
211 * カメラにコマンドを送信する(メイン部分)
214 private void send_to_camera(boolean isDumpReceiveLog, byte[] byte_array, boolean useSequenceNumber)
218 dos = new DataOutputStream(socket.getOutputStream());
220 // メッセージボディを加工: 最初に4バイトのレングス長をつける
221 byte[] sendData = new byte[byte_array.length + 4];
223 sendData[0] = (byte) (byte_array.length + 4);
227 System.arraycopy(byte_array,0,sendData,4, byte_array.length);
229 if (useSequenceNumber)
231 // Sequence Number を反映させる
232 sendData[8] = (byte) ((0x000000ff & sequenceNumber));
233 sendData[9] = (byte) (((0x0000ff00 & sequenceNumber) >>> 8) & 0x000000ff);
234 sendData[10] = (byte) (((0x00ff0000 & sequenceNumber) >>> 16) & 0x000000ff);
235 sendData[11] = (byte) (((0xff000000 & sequenceNumber) >>> 24) & 0x000000ff);
236 if (isDumpReceiveLog)
238 Log.v(TAG, "SEQ No. : " + sequenceNumber);
243 dump_bytes(isDumpReceiveLog,"SEND[" + sendData.length + "] ", sendData);
255 private void sleep(int delayMs)
259 Thread.sleep(delayMs);
268 * カメラからにコマンドの結果を受信する(メイン部分)
271 private void receive_from_camera(boolean isDumpReceiveLog, int id, IFujiXCommandCallback callback, boolean receiveAgain, int delayMs)
276 byte[] byte_array = new byte[BUFFER_SIZE];
277 InputStream is = socket.getInputStream();
280 int read_bytes = is.read(byte_array, 0, BUFFER_SIZE);
286 int length = ((((int) byte_array[3]) & 0xff) << 24) + ((((int) byte_array[2]) & 0xff) << 16) + ((((int) byte_array[1]) & 0xff) << 8) + (((int) byte_array[0]) & 0xff);
287 if ((length > read_bytes)||((length == read_bytes)&&((int) byte_array[4] == 0x02)))
289 // データについて、もう一回受信が必要な場合...
290 Log.v(TAG, "--- RECEIVE AGAIN --- [" + length + "(" + read_bytes + ") " + byte_array[4]+ "] ");
292 int read_bytes2 = is.read(byte_array, read_bytes, BUFFER_SIZE - read_bytes);
295 read_bytes = read_bytes + read_bytes2;
299 receive_body = Arrays.copyOfRange(byte_array, 0, read_bytes);
303 receive_body = new byte[1];
305 if (isDumpReceiveLog)
308 Log.v(TAG, "receive_from_camera() : " + read_bytes + " bytes.");
309 dump_bytes(isDumpReceiveLog, "RECV[" + receive_body.length + "] ", receive_body);
311 if (callback != null)
313 callback.receivedMessage(id, receive_body);
327 private void dump_bytes(boolean isDumpReceiveLog, String header, byte[] data)
329 if (!isDumpReceiveLog)
336 StringBuffer message;
337 message = new StringBuffer();
338 for (byte item : data)
341 message.append(String.format("%02x ", item));
344 Log.v(TAG, header + " " + message);
346 message = new StringBuffer();
351 Log.v(TAG, header + " " + message);