OSDN Git Service

若干整理。
[gokigen/A01d.git] / app / src / main / java / net / osdn / gokigen / a01d / camera / ptpip / wrapper / status / PtpIpStatusChecker.java
1 package net.osdn.gokigen.a01d.camera.ptpip.wrapper.status;
2
3 import android.app.Activity;
4 import android.util.Log;
5
6 import androidx.annotation.NonNull;
7
8 import net.osdn.gokigen.a01d.camera.ICameraStatus;
9 import net.osdn.gokigen.a01d.camera.ICameraStatusWatcher;
10 import net.osdn.gokigen.a01d.camera.ptpip.wrapper.command.IPtpIpCommand;
11 import net.osdn.gokigen.a01d.camera.ptpip.wrapper.command.IPtpIpCommandCallback;
12 import net.osdn.gokigen.a01d.camera.ptpip.wrapper.command.IPtpIpCommandPublisher;
13 import net.osdn.gokigen.a01d.camera.ptpip.wrapper.command.IPtpIpMessages;
14 import net.osdn.gokigen.a01d.camera.ptpip.wrapper.command.messages.specific.InitEventRequest;
15 import net.osdn.gokigen.a01d.liveview.ICameraStatusUpdateNotify;
16
17 import java.io.BufferedReader;
18 import java.io.DataOutputStream;
19 import java.io.InputStream;
20 import java.net.Socket;
21 import java.util.ArrayList;
22 import java.util.Arrays;
23 import java.util.List;
24
25 import static net.osdn.gokigen.a01d.camera.utils.SimpleLogDumper.dump_bytes;
26
27 public class PtpIpStatusChecker implements IPtpIpCommandCallback, ICameraStatusWatcher, ICameraStatus
28 {
29     private final String TAG = toString();
30
31     private static final int BUFFER_SIZE = 1024 * 1024 + 8;
32     private static final int STATUS_MESSAGE_HEADER_SIZE = 14;
33     private int sleepMs;
34     private final IPtpIpCommandPublisher issuer;
35     private ICameraStatusUpdateNotify notifier = null;
36     private PtpIpStatusHolder statusHolder;
37     private boolean whileFetching = false;
38     private boolean logcat = false;
39     private final String ipAddress;
40     private final int portNumber;
41
42     private Socket socket = null;
43     private DataOutputStream dos = null;
44     private BufferedReader bufferedReader = null;
45     private int eventConnectionNumber = 0;
46
47     public PtpIpStatusChecker(@NonNull Activity activity, @NonNull IPtpIpCommandPublisher issuer, @NonNull String ip, int portNumber)
48     {
49         this.issuer = issuer;
50         this.statusHolder = new PtpIpStatusHolder();
51         this.ipAddress = ip;
52         this.portNumber = portNumber;
53         Log.v(TAG, "POLLING WAIT : " + sleepMs);
54     }
55
56     @Override
57     public void onReceiveProgress(int currentBytes, int totalBytes, byte[] body)
58     {
59         Log.v(TAG, " " + currentBytes + "/" + totalBytes);
60     }
61
62     @Override
63     public boolean isReceiveMulti()
64     {
65         return (false);
66     }
67
68     @Override
69     public void receivedMessage(int id, byte[] data)
70     {
71         try
72         {
73             logcat("receivedMessage : " + id + ", length: " + data.length);
74             if (id == IPtpIpMessages.SEQ_EVENT_INITIALIZE)
75             {
76                 // 終わる
77                 Log.v(TAG, " ----- PTP-IP Connection is ESTABLISHED. -----");
78                 return;
79             }
80             if (data.length < STATUS_MESSAGE_HEADER_SIZE)
81             {
82                 Log.v(TAG, "received status length is short. (" + data.length + " bytes.)");
83                 return;
84             }
85
86             int nofStatus = (data[13] * 256) + data[12];
87             int statusCount = 0;
88             int index = STATUS_MESSAGE_HEADER_SIZE;
89             while ((statusCount < nofStatus)&&(index < data.length))
90             {
91                 int dataId = ((((int)data[index + 1]) & 0xff) * 256) + (((int) data[index]) & 0xff);
92                 statusHolder.updateValue(notifier, dataId, data[index + 2], data[index + 3], data[index +4], data[index + 5]);
93                 index = index + 6;
94                 statusCount++;
95             }
96         }
97         catch (Exception e)
98         {
99             e.printStackTrace();
100         }
101     }
102
103     @Override
104     public List<String> getStatusList(String key)
105     {
106         try
107         {
108             if (statusHolder == null)
109             {
110                 return (new ArrayList<>());
111             }
112             return (statusHolder.getAvailableItemList(key));
113         }
114         catch (Exception e)
115         {
116             e.printStackTrace();
117         }
118         return (new ArrayList<>());
119     }
120
121     @Override
122     public String getStatus(String key)
123     {
124         try
125         {
126             if (statusHolder == null)
127             {
128                 return ("");
129             }
130             return (statusHolder.getItemStatus(key));
131         }
132         catch (Exception e)
133         {
134             e.printStackTrace();
135         }
136         return ("");
137     }
138
139     @Override
140     public void setStatus(String key, String value)
141     {
142         try
143         {
144             if (logcat)
145             {
146                 Log.v(TAG, "setStatus(" + key + ", " + value + ")");
147             }
148
149             // ここで設定を行う。
150         }
151         catch (Exception e)
152         {
153             e.printStackTrace();
154         }
155     }
156
157     @Override
158     public void startStatusWatch(@NonNull ICameraStatusUpdateNotify notifier)
159     {
160         if (whileFetching)
161         {
162             Log.v(TAG, "startStatusWatch() already starting.");
163             return;
164         }
165         try
166         {
167             this.notifier = notifier;
168             whileFetching = true;
169
170             // セッションをオープンする
171             boolean isConnect = connect();
172             if (!isConnect)
173             {
174                 Log.v(TAG, "  CONNECT FAIL...(EVENT) : " + ipAddress + "  " + portNumber);
175             }
176             issueCommand(new InitEventRequest(this, eventConnectionNumber));
177         }
178         catch (Exception e)
179         {
180             e.printStackTrace();
181         }
182     }
183
184     @Override
185     public void stopStatusWatch()
186     {
187         Log.v(TAG, "stoptStatusWatch()");
188         whileFetching = false;
189         this.notifier = null;
190     }
191
192     private void logcat(String message)
193     {
194         if (logcat)
195         {
196             Log.v(TAG, message);
197         }
198     }
199
200     private boolean connect()
201     {
202         try
203         {
204             socket = new Socket(ipAddress, portNumber);
205             return (true);
206         }
207         catch (Exception e)
208         {
209             e.printStackTrace();
210             socket = null;
211         }
212         return (false);
213     }
214
215     private void disconnect()
216     {
217         // ストリームを全部閉じる
218         try
219         {
220             if (dos != null)
221             {
222                 dos.close();
223             }
224         }
225         catch (Exception e)
226         {
227             e.printStackTrace();
228         }
229         dos = null;
230
231         try
232         {
233             if (bufferedReader != null)
234             {
235                 bufferedReader.close();
236             }
237         }
238         catch (Exception e)
239         {
240             e.printStackTrace();
241         }
242         bufferedReader = null;
243
244         try
245         {
246             if (socket != null)
247             {
248                 socket.close();
249             }
250         }
251         catch (Exception e)
252         {
253             e.printStackTrace();
254         }
255         socket = null;
256         System.gc();
257     }
258
259     public void setEventConnectionNumber(int connectionNumber)
260     {
261         eventConnectionNumber = connectionNumber;
262     }
263
264     private void issueCommand(@NonNull IPtpIpCommand command)
265     {
266         try
267         {
268             //Log.v(TAG, "issueCommand : " + command.getId());
269             byte[] commandBody = command.commandBody();
270             if (commandBody != null)
271             {
272                 // コマンドボディが入っていた場合には、コマンド送信(入っていない場合は受信待ち)
273                 send_to_camera(command.dumpLog(), commandBody);
274             }
275             receive_from_camera(command.dumpLog(), command.getId(), command.responseCallback(), command.receiveAgainShortLengthMessage(), command.receiveDelayMs());
276         }
277         catch (Exception e)
278         {
279             e.printStackTrace();
280         }
281     }
282
283     /**
284      *    カメラにコマンドを送信する(メイン部分)
285      *
286      */
287     private void send_to_camera(boolean isDumpReceiveLog, byte[] byte_array)
288     {
289         try
290         {
291             dos = new DataOutputStream(socket.getOutputStream());  // ここにいたらいけない?
292
293             // メッセージボディを加工: 最初に4バイトのレングス長をつける
294             byte[] sendData = new byte[byte_array.length + 4];
295
296             sendData[0] = (byte) (byte_array.length + 4);
297             sendData[1] = 0x00;
298             sendData[2] = 0x00;
299             sendData[3] = 0x00;
300             System.arraycopy(byte_array,0,sendData,4, byte_array.length);
301
302             if (isDumpReceiveLog)
303             {
304                 // ログに送信メッセージを出力する
305                 dump_bytes("SEND[" + sendData.length + "] ", sendData);
306             }
307
308             // (データを)送信
309             dos.write(sendData);
310             dos.flush();
311         }
312         catch (Exception e)
313         {
314             e.printStackTrace();
315         }
316     }
317
318
319     /**
320      *    カメラからにコマンドの結果を受信する(メイン部分)
321      *
322      */
323     private void receive_from_camera(boolean isDumpReceiveLog, int id, IPtpIpCommandCallback callback, boolean receiveAgain, int delayMs) {
324         try {
325             sleep(delayMs);
326
327             boolean isFirstTime = true;
328             int totalReadBytes;
329             int receive_message_buffer_size = BUFFER_SIZE;
330             byte[] byte_array = new byte[receive_message_buffer_size];
331             InputStream is = socket.getInputStream();
332             if (is != null) {
333                 int read_bytes = is.read(byte_array, 0, receive_message_buffer_size);
334                 byte[] receive_body;
335                 if (read_bytes > 4) {
336                     if (receiveAgain) {
337                         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);
338                         if (length > receive_message_buffer_size) {
339                             Log.v(TAG, "+++++ TOTAL RECEIVE MESSAGE SIZE IS " + length + " +++++");
340                         }
341                         totalReadBytes = read_bytes;
342                         while ((length > totalReadBytes) || ((length == read_bytes) && ((int) byte_array[4] == 0x02))) {
343                             // データについて、もう一回受信が必要な場合...
344                             if (isDumpReceiveLog) {
345                                 Log.v(TAG, "--- RECEIVE AGAIN --- [" + length + "(" + read_bytes + ") " + byte_array[4] + "] ");
346                             }
347                             sleep(delayMs);
348                             int read_bytes2 = is.read(byte_array, read_bytes, receive_message_buffer_size - read_bytes);
349                             if (read_bytes2 > 0) {
350                                 read_bytes = read_bytes + read_bytes2;
351                                 totalReadBytes = totalReadBytes + read_bytes2;
352                             } else {
353                                 // よみだし終了。
354                                 Log.v(TAG, "FINISHED RECEIVE... ");
355                                 break;
356                             }
357                             if (callback != null) {
358                                 if (callback.isReceiveMulti()) {
359                                     int offset = 0;
360                                     if (isFirstTime) {
361                                         // 先頭のヘッダ部分をカットして送る
362                                         offset = 12;
363                                         isFirstTime = false;
364                                         //Log.v(TAG, " FIRST TIME : " + read_bytes + " " + offset);
365                                     }
366                                     callback.onReceiveProgress(read_bytes - offset, length, Arrays.copyOfRange(byte_array, offset, read_bytes));
367                                     read_bytes = 0;
368                                 } else {
369                                     callback.onReceiveProgress(read_bytes, length, null);
370                                 }
371                             }
372                         }
373                     }
374                     receive_body = Arrays.copyOfRange(byte_array, 0, read_bytes);
375                 } else {
376                     receive_body = new byte[1];
377                 }
378                 if (isDumpReceiveLog) {
379                     // ログに受信メッセージを出力する
380                     Log.v(TAG, " receive_from_camera() : " + read_bytes + " bytes.");
381                     dump_bytes("RECV[" + receive_body.length + "] ", receive_body);
382                 }
383                 if (callback != null) {
384                     if (callback.isReceiveMulti()) {
385                         callback.receivedMessage(id, null);
386                     } else {
387                         callback.receivedMessage(id, receive_body);
388                         //callback.receivedMessage(id, Arrays.copyOfRange(receive_body, 0, receive_body.length));
389                     }
390                 }
391             }
392         } catch (Throwable e) {
393             e.printStackTrace();
394         }
395     }
396
397     private void sleep(int delayMs)
398     {
399         try
400         {
401             Thread.sleep(delayMs);
402         }
403         catch (Exception e)
404         {
405             e.printStackTrace();
406         }
407     }
408
409 }