OSDN Git Service

ConnectionMethodの違いで背景画像を変更した。
authorMRSa <mrsa@myad.jp>
Sat, 9 Jan 2021 15:34:11 +0000 (00:34 +0900)
committerMRSa <mrsa@myad.jp>
Sat, 9 Jan 2021 15:34:11 +0000 (00:34 +0900)
wear/src/main/java/jp/sfjp/gokigen/a01c/MainActivity.java
wear/src/main/java/jp/sfjp/gokigen/a01c/liveview/CameraLiveImageView.java
wear/src/main/java/jp/sfjp/gokigen/a01c/utils/SimpleHttpClient.kt [new file with mode: 0644]
wear/src/main/java/jp/sfjp/gokigen/a01c/utils/SimpleLiveviewSlicer.java [new file with mode: 0644]
wear/src/main/java/jp/sfjp/gokigen/a01c/utils/SimpleLogDumper.java [new file with mode: 0644]
wear/src/main/java/jp/sfjp/gokigen/a01c/utils/XmlElement.java [new file with mode: 0644]
wear/src/main/res/values-ja/strings.xml
wear/src/main/res/values/strings.xml

index 1006d9c..14d7f9c 100644 (file)
@@ -821,7 +821,6 @@ public class MainActivity extends AppCompatActivity implements  IChangeScene, IS
             {
                 liveView.hideDialog();
                 listener.setEnableOperation(operation.ENABLE);
-
             }
         }
         catch (Exception e)
@@ -830,6 +829,20 @@ public class MainActivity extends AppCompatActivity implements  IChangeScene, IS
         }
     }
 
+    private void updateConnectionMethodMessage()
+    {
+        try
+        {
+            String connectionMethod = preferences.getString(IPreferenceCameraPropertyAccessor.CONNECTION_METHOD, IPreferenceCameraPropertyAccessor.CONNECTION_METHOD_DEFAULT_VALUE);
+            int methodId = (connectionMethod.contains(IPreferenceCameraPropertyAccessor.CONNECTION_METHOD_THETA)) ? R.string.connection_method_theta : R.string.connection_method_opc;
+            setMessage(IShowInformation.AREA_5, Color.MAGENTA, getString(methodId));
+        }
+        catch (Exception e)
+        {
+            e.printStackTrace();
+        }
+    }
+
     private void updateConnectionMethod(String parameter, ICameraController method)
     {
         try
@@ -845,7 +858,7 @@ public class MainActivity extends AppCompatActivity implements  IChangeScene, IS
     }
 
     /**
-     *   接続方式を変更するか確認する
+     *   接続方式を変更するか確認する (OPC ⇔ THETA)
      *
      */
     private void changeConnectionMethod()
@@ -882,6 +895,7 @@ public class MainActivity extends AppCompatActivity implements  IChangeScene, IS
                                 // 接続方式を Theta に切り替える
                                 updateConnectionMethod(IPreferenceCameraPropertyAccessor.CONNECTION_METHOD_THETA, olyAirCoordinator);  // thetaCoordinator
                             }
+                            updateConnectionMethodMessage();
                         }
                     });
                 }
index 16d3f93..3f0b13f 100644 (file)
@@ -120,7 +120,20 @@ public class CameraLiveImageView extends View implements IImageDataReceiver, IAu
         // ダミーのビットマップデータ読み込み...画面表示のテスト用ロジック
         try
         {
-            imageBitmap = BitmapFactory.decodeResource(context.getResources(), R.drawable.momonga);
+            int imageId = R.drawable.momonga;
+            try
+            {
+                String connectionMethod = preferences.getString(IPreferenceCameraPropertyAccessor.CONNECTION_METHOD, IPreferenceCameraPropertyAccessor.CONNECTION_METHOD_DEFAULT_VALUE);
+                if (connectionMethod != null)
+                {
+                    imageId = (connectionMethod.contains(IPreferenceCameraPropertyAccessor.CONNECTION_METHOD_THETA)) ? R.drawable.kamakura : R.drawable.momonga;
+                }
+            }
+            catch (Throwable tt)
+            {
+                tt.printStackTrace();
+            }
+            imageBitmap = BitmapFactory.decodeResource(context.getResources(), imageId);
         }
         catch (Throwable t)
         {
diff --git a/wear/src/main/java/jp/sfjp/gokigen/a01c/utils/SimpleHttpClient.kt b/wear/src/main/java/jp/sfjp/gokigen/a01c/utils/SimpleHttpClient.kt
new file mode 100644 (file)
index 0000000..3e81231
--- /dev/null
@@ -0,0 +1,524 @@
+package jp.sfjp.gokigen.a01c.utils
+
+import android.graphics.Bitmap
+import android.graphics.BitmapFactory
+import android.util.Log
+import java.io.*
+import java.net.HttpURLConnection
+import java.net.URL
+
+class SimpleHttpClient()
+{
+    /**
+     *
+     *
+     *
+     */
+    fun httpGet(url: String, timeoutMs: Int): String
+    {
+        var inputStream : InputStream? = null
+        var replyString = ""
+        var timeout = timeoutMs
+        if (timeoutMs < 0)
+        {
+            timeout = DEFAULT_TIMEOUT
+        }
+
+        //  HTTP GETメソッドで要求を投げる
+        try
+        {
+            val httpConn = URL(url).openConnection() as HttpURLConnection
+            try
+            {
+                httpConn.requestMethod = "GET"
+                httpConn.connectTimeout = timeout
+                httpConn.readTimeout = timeout
+                httpConn.connect()
+                val responseCode = httpConn.responseCode
+                if (responseCode == HttpURLConnection.HTTP_OK)
+                {
+                    inputStream = httpConn.inputStream
+                }
+                if (inputStream == null)
+                {
+                    Log.w(TAG, "httpGet: Response Code Error: $responseCode: $url")
+                    return ("")
+                }
+            }
+            catch (ee : Exception)
+            {
+                Log.w(TAG, "httpGet: " + url + "  " + ee.message)
+                ee.printStackTrace()
+                httpConn.disconnect()
+                return ("")
+            }
+        }
+        catch (e: Exception)
+        {
+            Log.w(TAG, "httpGet(2): " + url + "  " + e.message)
+            e.printStackTrace()
+            return ("")
+        }
+
+        // 応答を確認する
+        try
+        {
+            val responseBuf = StringBuilder()
+            val reader = BufferedReader(InputStreamReader(inputStream))
+            var c: Int
+            while (reader.read().also { c = it } != -1)
+            {
+                responseBuf.append(c.toChar())
+            }
+            replyString = responseBuf.toString()
+            reader.close()
+        }
+        catch (e: Exception)
+        {
+            Log.w(TAG, "httpGet: exception: " + e.message)
+            e.printStackTrace()
+        }
+        finally
+        {
+            try
+            {
+                inputStream.close()
+            }
+            catch (e: Exception)
+            {
+                e.printStackTrace()
+            }
+        }
+        return (replyString)
+    }
+
+    /**
+     *
+     *
+     *
+     */
+    fun httpGetBytes(url: String, setProperty: Map<String, String>?, timeoutMs: Int, callback: IReceivedMessageCallback)
+    {
+        httpCommandBytes(url, "GET", null, setProperty, null, timeoutMs, callback)
+    }
+
+    /**
+     *
+     *
+     *
+     */
+    fun httpPostBytes(url: String, postData: String?, setProperty: Map<String, String>?, timeoutMs: Int, callback: IReceivedMessageCallback)
+    {
+        httpCommandBytes(url, "POST", postData, setProperty, null, timeoutMs, callback)
+    }
+
+    private fun httpCommandBytes(url: String, requestMethod: String, postData: String?, setProperty: Map<String, String>?, contentType: String?, timeoutMs: Int, callback: IReceivedMessageCallback)
+    {
+        var inputStream: InputStream? = null
+        var timeout = timeoutMs
+        if (timeoutMs < 0)
+        {
+            timeout = DEFAULT_TIMEOUT
+        }
+
+        //  HTTP メソッドで要求を送出
+        try
+        {
+            val httpConn = URL(url).openConnection() as HttpURLConnection
+            httpConn.requestMethod = requestMethod
+            if (setProperty != null)
+            {
+                for (key in setProperty.keys)
+                {
+                    val value = setProperty[key]
+                    httpConn.setRequestProperty(key, value)
+                }
+            }
+            if (contentType != null)
+            {
+                httpConn.setRequestProperty("Content-Type", contentType)
+            }
+            httpConn.connectTimeout = timeout
+            httpConn.readTimeout = timeout
+            if (postData == null)
+            {
+                httpConn.connect()
+            }
+            else
+            {
+                httpConn.doInput = true
+                httpConn.doOutput = true
+                val outputStream = httpConn.outputStream
+                val writer = OutputStreamWriter(outputStream, "UTF-8")
+                writer.write(postData)
+                writer.flush()
+                writer.close()
+                outputStream.close()
+            }
+            val responseCode = httpConn.responseCode
+            if (responseCode == HttpURLConnection.HTTP_OK)
+            {
+                inputStream = httpConn.inputStream
+            }
+            if (inputStream == null)
+            {
+                Log.w(TAG, " http $requestMethod Response Code Error: $responseCode: $url")
+                callback.onErrorOccurred(NullPointerException())
+                callback.onCompleted()
+                return
+            }
+
+            // 応答を確認する
+            try
+            {
+                var contentLength = httpConn.contentLength
+                if (contentLength < 0)
+                {
+                    // コンテンツ長が取れない場合の処理...
+                    try
+                    {
+                        val headers = httpConn.headerFields
+                        // コンテンツ長さが取れない場合は、HTTP応答ヘッダから取得する
+                        val valueList = headers["X-FILE_SIZE"]
+                        try
+                        {
+                            if (valueList != null)
+                            {
+                                contentLength = getValue(valueList).toInt()
+                            }
+                        }
+                        catch (ee: Exception)
+                        {
+                            ee.printStackTrace()
+                        }
+                    }
+                    catch (e: Exception)
+                    {
+                        e.printStackTrace()
+                    }
+                }
+                val buffer = ByteArray(BUFFER_SIZE)
+                var readBytes = 0
+                var readSize = inputStream.read(buffer, 0, BUFFER_SIZE)
+                while (readSize != -1)
+                {
+                    callback.onReceive(readBytes, contentLength, readSize, buffer)
+                    readBytes += readSize
+                    readSize = inputStream.read(buffer, 0, BUFFER_SIZE)
+                }
+                Log.v(TAG, "RECEIVED $readBytes BYTES. (contentLength : $contentLength)")
+                inputStream.close()
+            }
+            catch (e: Exception)
+            {
+                Log.w(TAG, "httpGet: exception: " + e.message)
+                e.printStackTrace()
+                callback.onErrorOccurred(e)
+            }
+            finally
+            {
+                try
+                {
+                    inputStream.close()
+                }
+                catch (e: Exception)
+                {
+                    e.printStackTrace()
+                }
+            }
+        }
+        catch (e: Exception)
+        {
+            Log.w(TAG, "http " + requestMethod + " " + url + "  " + e.message)
+            e.printStackTrace()
+            callback.onErrorOccurred(e)
+            callback.onCompleted()
+            return
+        }
+        callback.onCompleted()
+    }
+
+
+    private fun getValue(valueList: List<String>): String
+    {
+        // 応答ヘッダの値切り出し用...
+        var isFirst = true
+        val values = StringBuilder()
+        for (value in valueList)
+        {
+            values.append(value)
+            if (isFirst)
+            {
+                isFirst = false
+            }
+            else
+            {
+                values.append(" ")
+            }
+        }
+        return values.toString()
+    }
+
+    fun httpGetBitmap(url: String, setProperty: Map<String, String>?, timeoutMs: Int): Bitmap?
+    {
+        return (httpCommandBitmap(url, "GET", null, setProperty, null, timeoutMs))
+    }
+
+    /**
+     *
+     *
+     *
+     */
+    fun httpPostBitmap(url: String, postData: String?, timeoutMs: Int): Bitmap?
+    {
+        return (httpCommandBitmap(url, "POST", postData, null, null, timeoutMs))
+    }
+
+    /**
+     *
+     *
+     *
+     */
+    private fun httpCommandBitmap(url: String, requestMethod: String, postData: String?, setProperty: Map<String, String>?, contentType: String?, timeoutMs: Int): Bitmap?
+    {
+        //var httpConn: HttpURLConnection? = null
+        var inputStream: InputStream? = null
+        //var outputStream: OutputStream? = null
+        //var writer: OutputStreamWriter? = null
+        var bmp: Bitmap? = null
+        var timeout = timeoutMs
+        if (timeoutMs < 0)
+        {
+            timeout = DEFAULT_TIMEOUT
+        }
+
+        //  HTTP メソッドで要求を送出
+        try
+        {
+            val httpConn = URL(url).openConnection() as HttpURLConnection
+            httpConn.requestMethod = requestMethod
+            if (setProperty != null)
+            {
+                for (key in setProperty.keys)
+                {
+                    val value = setProperty[key]
+                    httpConn.setRequestProperty(key, value)
+                }
+            }
+            if (contentType != null)
+            {
+                httpConn.setRequestProperty("Content-Type", contentType)
+            }
+            httpConn.connectTimeout = timeout
+            httpConn.readTimeout = timeout
+            if (postData == null)
+            {
+                httpConn.connect()
+            }
+            else
+            {
+                httpConn.doInput = true
+                httpConn.doOutput = true
+                val outputStream = httpConn.outputStream
+                val writer = OutputStreamWriter(outputStream, "UTF-8")
+                writer.write(postData)
+                writer.flush()
+                writer.close()
+                outputStream.close()
+            }
+            val responseCode = httpConn.responseCode
+            if (responseCode == HttpURLConnection.HTTP_OK)
+            {
+                inputStream = httpConn.inputStream
+                if (inputStream != null)
+                {
+                    bmp = BitmapFactory.decodeStream(inputStream)
+                }
+            }
+            if (inputStream == null)
+            {
+                Log.w(TAG, "http: ($requestMethod) Response Code Error: $responseCode: $url")
+                return (null)
+            }
+            inputStream.close()
+        }
+        catch (e: Exception)
+        {
+            Log.w(TAG, "http: (" + requestMethod + ") " + url + "  " + e.message)
+            e.printStackTrace()
+            return (null)
+        }
+        return (bmp)
+    }
+
+    /**
+     *
+     *
+     *
+     */
+    fun httpPost(url: String, postData: String?, timeoutMs: Int): String?
+    {
+        return (httpCommand(url, "POST", postData, null, null, timeoutMs))
+    }
+
+    /**
+     *
+     *
+     *
+     */
+    fun httpGetWithHeader(url: String, headerMap: Map<String, String>?, contentType: String?, timeoutMs: Int): String?
+    {
+        return (httpCommand(url, "GET", null, headerMap, contentType, timeoutMs))
+    }
+
+    /**
+     *
+     *
+     *
+     */
+    fun httpPostWithHeader(url: String, postData: String?, headerMap: Map<String, String>?, contentType: String?, timeoutMs: Int): String?
+    {
+        return (httpCommand(url, "POST", postData, headerMap, contentType, timeoutMs))
+    }
+
+    /**
+     *
+     *
+     *
+     */
+    fun httpPutWithHeader(url: String, putData: String?, headerMap: Map<String, String>?, contentType: String?, timeoutMs: Int): String?
+    {
+        return (httpCommand(url, "PUT", putData, headerMap, contentType, timeoutMs))
+    }
+
+    /**
+     *
+     *
+     *
+     */
+    fun httpPut(url: String, postData: String?, timeoutMs: Int): String?
+    {
+        return (httpCommand(url, "PUT", postData, null, null, timeoutMs))
+    }
+
+    /**
+     *
+     *
+     *
+     */
+    fun httpOptions(url: String, optionsData: String?, timeoutMs: Int): String?
+    {
+        return (httpCommand(url, "OPTIONS", optionsData, null, null, timeoutMs))
+    }
+
+    /**
+     *
+     *
+     *
+     */
+    private fun httpCommand(url: String, requestMethod: String, postData: String?, setProperty: Map<String, String>?, contentType: String?, timeoutMs: Int): String?
+    {
+        var inputStream: InputStream? = null
+        var timeout = timeoutMs
+        if (timeoutMs < 0)
+        {
+            timeout = DEFAULT_TIMEOUT
+        }
+
+        //  HTTP メソッドで要求を送出
+        try
+        {
+            val httpConn = URL(url).openConnection() as HttpURLConnection
+            httpConn.requestMethod = requestMethod
+            if (setProperty != null)
+            {
+                for (key in setProperty.keys)
+                {
+                    val value = setProperty[key]
+                    httpConn.setRequestProperty(key, value)
+                }
+            }
+            if (contentType != null)
+            {
+                httpConn.setRequestProperty("Content-Type", contentType)
+            }
+            httpConn.connectTimeout = timeout
+            httpConn.readTimeout = timeout
+            if (postData == null)
+            {
+                httpConn.connect()
+            }
+            else
+            {
+                httpConn.doInput = true
+                httpConn.doOutput = true
+                val outputStream = httpConn.outputStream
+                val writer = OutputStreamWriter(outputStream, "UTF-8")
+                writer.write(postData)
+                writer.flush()
+                writer.close()
+                outputStream.close()
+            }
+            val responseCode = httpConn.responseCode
+            if (responseCode == HttpURLConnection.HTTP_OK)
+            {
+                inputStream = httpConn.inputStream
+            }
+            if (inputStream == null)
+            {
+                Log.w(TAG, "http $requestMethod : Response Code Error: $responseCode: $url")
+                return ""
+            }
+        }
+        catch (e: Exception)
+        {
+            Log.w(TAG, "http " + requestMethod + " : IOException: " + e.message)
+            e.printStackTrace()
+            return ("")
+        }
+
+        // 応答の読み出し
+        return readFromInputStream(inputStream)
+    }
+
+    private fun readFromInputStream(inputStream: InputStream?): String
+    {
+        //var reader: BufferedReader? = null
+        var replyString = ""
+        if (inputStream == null)
+        {
+            return ""
+        }
+        try
+        {
+            val responseBuf = StringBuilder()
+            val reader = BufferedReader(InputStreamReader(inputStream))
+            var c: Int
+            while (reader.read().also { c = it } != -1)
+            {
+                responseBuf.append(c.toChar())
+            }
+            replyString = responseBuf.toString()
+            reader.close()
+        }
+        catch (e: Exception)
+        {
+            e.printStackTrace()
+        }
+        return replyString
+    }
+
+    interface IReceivedMessageCallback
+    {
+        fun onCompleted()
+        fun onErrorOccurred(e: Exception?)
+        fun onReceive(readBytes: Int, length: Int, size: Int, data: ByteArray?)
+    }
+
+    companion object
+    {
+        private val TAG = SimpleHttpClient::class.java.simpleName
+        private const val DEFAULT_TIMEOUT = 10 * 1000 // [ms]
+        private const val BUFFER_SIZE = 131072 * 2 // 256kB
+    }
+}
diff --git a/wear/src/main/java/jp/sfjp/gokigen/a01c/utils/SimpleLiveviewSlicer.java b/wear/src/main/java/jp/sfjp/gokigen/a01c/utils/SimpleLiveviewSlicer.java
new file mode 100644 (file)
index 0000000..e966102
--- /dev/null
@@ -0,0 +1,404 @@
+package jp.sfjp.gokigen.a01c.utils;
+
+
+import android.util.Log;
+
+import androidx.annotation.NonNull;
+
+import java.io.ByteArrayOutputStream;
+import java.io.EOFException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.net.HttpURLConnection;
+import java.net.URL;
+
+public class SimpleLiveviewSlicer
+{
+    private static final String TAG = SimpleLiveviewSlicer.class.getSimpleName();
+    public static final class Payload
+    {
+        // jpeg data container
+        final byte[] jpegData;
+
+        // padding data container
+        final byte[] paddingData;
+
+        /**
+         * Constructor
+         */
+        private Payload(byte[] jpeg, byte[] padding)
+        {
+            this.jpegData = jpeg;
+            this.paddingData = padding;
+        }
+        public byte[] getJpegData()
+        {
+            return (jpegData);
+        }
+    }
+
+    private static final int CONNECTION_TIMEOUT = 2000; // [msec]
+    private int[] mJpegStartMarker = { 0x0d, 0x0a, 0x0d, 0x0a, 0xff, 0xd8 };
+    private HttpURLConnection mHttpConn;
+    private InputStream mInputStream;
+
+    public void setMJpegStartMarker(@NonNull int[] startMarker)
+    {
+        mJpegStartMarker = startMarker;
+    }
+
+/*
+    public void open(InputStream inputStream)
+    {
+            mInputStream = inputStream;
+    }
+*/
+
+    public void open(String liveviewUrl, String postData, String contentType)
+    {
+        OutputStream outputStream = null;
+        OutputStreamWriter writer = null;
+        try
+        {
+            if ((mInputStream != null)||(mHttpConn != null))
+            {
+                Log.v(TAG, "Slicer is already open.");
+                return;
+            }
+
+            final URL urlObj = new URL(liveviewUrl);
+            mHttpConn = (HttpURLConnection) urlObj.openConnection();
+            mHttpConn.setRequestMethod("POST");
+            mHttpConn.setConnectTimeout(CONNECTION_TIMEOUT);
+            if (contentType != null)
+            {
+                mHttpConn.setRequestProperty("Content-Type", contentType);
+            }
+            {
+                mHttpConn.setDoInput(true);
+                mHttpConn.setDoOutput(true);
+                outputStream = mHttpConn.getOutputStream();
+                //noinspection CharsetObjectCanBeUsed
+                writer = new OutputStreamWriter(outputStream, "UTF-8");
+                writer.write(postData);
+                writer.flush();
+                writer.close();
+                writer = null;
+                outputStream.close();
+                outputStream = null;
+            }
+            if (mHttpConn.getResponseCode() == HttpURLConnection.HTTP_OK)
+            {
+                mInputStream = mHttpConn.getInputStream();
+            }
+        }
+        catch (Exception e)
+        {
+            e.printStackTrace();
+        }
+        finally
+        {
+            try
+            {
+                if (writer != null)
+                {
+                    writer.close();
+                }
+            }
+            catch (Exception e)
+            {
+                e.printStackTrace();
+            }
+            try
+            {
+                if (outputStream != null)
+                {
+                    outputStream.close();
+                }
+            }
+            catch (IOException e)
+            {
+                e.printStackTrace();
+            }
+        }
+    }
+
+    public void open(String liveviewUrl)
+    {
+        try
+        {
+            if ((mInputStream != null)||(mHttpConn != null))
+            {
+                Log.v(TAG, "Slicer is already open.");
+                return;
+            }
+
+            final URL urlObj = new URL(liveviewUrl);
+            mHttpConn = (HttpURLConnection) urlObj.openConnection();
+            mHttpConn.setRequestMethod("GET");
+            mHttpConn.setConnectTimeout(CONNECTION_TIMEOUT);
+            mHttpConn.connect();
+            if (mHttpConn.getResponseCode() == HttpURLConnection.HTTP_OK)
+            {
+                mInputStream = mHttpConn.getInputStream();
+            }
+        }
+        catch (Exception e)
+        {
+            e.printStackTrace();
+        }
+    }
+
+    public void close()
+    {
+        try
+        {
+            if (mInputStream != null)
+            {
+                mInputStream.close();
+                mInputStream = null;
+            }
+        }
+        catch (Exception e)
+        {
+            e.printStackTrace();
+        }
+        try
+        {
+            if (mHttpConn != null)
+            {
+                mHttpConn.disconnect();
+                mHttpConn = null;
+            }
+        }
+        catch (Exception e)
+        {
+            e.printStackTrace();
+        }
+    }
+
+    public Payload nextPayload()
+    {
+        Payload payload = null;
+        try
+        {
+            while ((mInputStream != null)&&(payload == null))
+            {
+                // Common Header
+                int readLength = 1 + 1 + 2 + 4;
+                byte[] commonHeader = readBytes(mInputStream, readLength);
+                if ((commonHeader == null)||(commonHeader.length != readLength))
+                {
+                    Log.v(TAG, "Cannot read stream for common header.");
+                    payload = null;
+                    break;
+                }
+                if (commonHeader[0] != (byte) 0xFF)
+                {
+                    Log.v(TAG, "Unexpected data format. (Start byte)");
+                    payload = null;
+                    break;
+                }
+                switch (commonHeader[1])
+                {
+                    case (byte) 0x12:
+                        // This is information header for streaming. skip this packet.
+                        readLength = 4 + 3 + 1 + 2 + 118 + 4 + 4 + 24;
+                        //commonHeader = null;
+                        readBytes(mInputStream, readLength);
+                        break;
+
+                    case (byte) 0x01:
+                    case (byte) 0x11:
+                        payload = readPayload();
+                        break;
+
+                    default:
+                        break;
+                }
+            }
+        }
+        catch (Exception e)
+        {
+            e.printStackTrace();
+            System.gc();
+        }
+        return (payload);
+    }
+
+    private Payload readPayload()
+    {
+        try
+        {
+            if (mInputStream != null)
+            {
+                // Payload Header
+                int readLength = 4 + 3 + 1 + 4 + 1 + 115;
+                byte[] payloadHeader = readBytes(mInputStream, readLength);
+                if ((payloadHeader == null)||(payloadHeader.length != readLength))
+                {
+                    throw new EOFException("Cannot read stream for payload header.");
+                }
+                if (payloadHeader[0] != (byte) 0x24 || payloadHeader[1] != (byte) 0x35
+                        || payloadHeader[2] != (byte) 0x68
+                        || payloadHeader[3] != (byte) 0x79)
+                {
+                    throw new EOFException("Unexpected data format. (Start code)");
+                }
+                int jpegSize = bytesToInt(payloadHeader, 4, 3);
+                int paddingSize = bytesToInt(payloadHeader, 7, 1);
+
+                // Payload Data
+                byte[] jpegData = readBytes(mInputStream, jpegSize);
+                byte[] paddingData = readBytes(mInputStream, paddingSize);
+
+                return (new Payload(jpegData, paddingData));
+            }
+        }
+        catch (EOFException eo)
+        {
+            eo.printStackTrace();
+            close();
+        }
+        catch (Exception e)
+        {
+            e.printStackTrace();
+        }
+        return (null);
+    }
+
+    private static int bytesToInt(byte[] byteData, int startIndex, int count)
+    {
+        int ret = 0;
+        try
+        {
+            for (int i = startIndex; i < startIndex + count; i++)
+            {
+                ret = (ret << 8) | (byteData[i] & 0xff);
+            }
+        }
+        catch (Exception e)
+        {
+            e.printStackTrace();
+        }
+        return (ret);
+    }
+
+    private static byte[] readBytes(InputStream in, int length)
+    {
+        byte[] ret;
+        try
+        {
+            ByteArrayOutputStream tmpByteArray = new ByteArrayOutputStream();
+            byte[] buffer = new byte[1024];
+            while (true)
+            {
+                int trialReadlen = Math.min(buffer.length, length - tmpByteArray.size());
+                int readlen = in.read(buffer, 0, trialReadlen);
+                if (readlen < 0)
+                {
+                    break;
+                }
+                tmpByteArray.write(buffer, 0, readlen);
+                if (length <= tmpByteArray.size())
+                {
+                    break;
+                }
+            }
+            ret = tmpByteArray.toByteArray();
+            tmpByteArray.close();
+        }
+        catch (Exception e)
+        {
+            e.printStackTrace();
+            ret = null;
+        }
+        return (ret);
+    }
+
+    /**
+     *   先頭のjpegマーカーが出てくるまで読み飛ばす
+     *
+     */
+    private void skipJpegMarkStart(InputStream stream)
+    {
+        int searchIndex = 0;
+        while (true)
+        {
+            try
+            {
+                int data = stream.read();
+                if (data == mJpegStartMarker[searchIndex])
+                {
+                    searchIndex++;
+                    if (searchIndex >= mJpegStartMarker.length)
+                    {
+                        break;
+                    }
+                }
+            }
+            catch (Exception e)
+            {
+                e.printStackTrace();
+                return;
+            }
+        }
+    }
+
+    /**
+     *
+     *
+     */
+    public Payload nextPayloadForMotionJpeg()
+    {
+        int searchIndex = 0;
+        int[] endmarker = { 0xff, 0xd9 };
+        Payload payload = null;
+        try
+        {
+            while ((mInputStream != null)&&(payload == null))
+            {
+                skipJpegMarkStart(mInputStream);
+                ByteArrayOutputStream tmpByteArray = new ByteArrayOutputStream();
+                // 先頭にJPEGのマークを詰める
+                tmpByteArray.write(0xff);
+                tmpByteArray.write(0xd8);
+                while (true)
+                {
+                    try
+                    {
+                        // 1byteづつの読み込み... 本当は複数バイト読み出しで処理したい
+                        int data = mInputStream.read();
+                        tmpByteArray.write(data);
+                        if (data == endmarker[searchIndex])
+                        {
+                            searchIndex++;
+                            if (searchIndex >= endmarker.length)
+                            {
+                                break;
+                            }
+                        }
+                        else
+                        {
+                            searchIndex = 0;
+                        }
+                    }
+                    catch (Throwable e)
+                    {
+                        Log.v(TAG, "INPUT STREAM EXCEPTION : " + e.getLocalizedMessage());
+                        // e.printStackTrace();
+                        return (null);
+                    }
+                }
+                payload = new Payload(tmpByteArray.toByteArray(), null);
+            }
+        }
+        catch (Exception e)
+        {
+            e.printStackTrace();
+        }
+        return (payload);
+    }
+}
diff --git a/wear/src/main/java/jp/sfjp/gokigen/a01c/utils/SimpleLogDumper.java b/wear/src/main/java/jp/sfjp/gokigen/a01c/utils/SimpleLogDumper.java
new file mode 100644 (file)
index 0000000..def8fa0
--- /dev/null
@@ -0,0 +1,78 @@
+package jp.sfjp.gokigen.a01c.utils;
+
+import android.app.Activity;
+import android.os.Environment;
+import android.util.Log;
+
+import androidx.annotation.NonNull;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.text.SimpleDateFormat;
+import java.util.Calendar;
+import java.util.Locale;
+
+import jp.sfjp.gokigen.a01c.R;
+
+public class SimpleLogDumper
+{
+    private static final String TAG = SimpleLogDumper.class.getSimpleName();
+
+    /**
+     *   デバッグ用:ログにバイト列を出力する
+     *
+     */
+    public static void dump_bytes(String header, byte[] data)
+    {
+        if (data == null)
+        {
+            Log.v(TAG, "DATA IS NULL");
+            return;
+        }
+        if (data.length > 8192)
+        {
+            Log.v(TAG, " --- DUMP DATA IS TOO LONG... " + data.length + " bytes.");
+            return;
+        }
+
+        int index = 0;
+        StringBuffer message;
+        message = new StringBuffer();
+        for (byte item : data)
+        {
+            index++;
+            message.append(String.format("%02x ", item));
+            if (index >= 16)
+            {
+                Log.v(TAG, header + " " + message);
+                index = 0;
+                message = new StringBuffer();
+            }
+        }
+        if (index != 0)
+        {
+            Log.v(TAG, header + " " + message);
+        }
+        System.gc();
+    }
+
+    public static void binaryOutputToFile(@NonNull Activity activity, String fileNamePrefix, byte[] rx_body)
+    {
+        try
+        {
+            Calendar calendar = Calendar.getInstance();
+            String extendName = new SimpleDateFormat("yyyyMMdd-HHmmss", Locale.getDefault()).format(calendar.getTime());
+            final String directoryPath = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM).getPath() + "/" + activity.getString(R.string.app_name2) + "/";
+            String outputFileName = fileNamePrefix + "_" + extendName + ".bin";
+            String filepath = new File(directoryPath.toLowerCase(), outputFileName.toLowerCase()).getPath();
+            FileOutputStream outputStream = new FileOutputStream(filepath);
+            outputStream.write(rx_body, 0, rx_body.length);
+            outputStream.flush();
+            outputStream.close();
+        }
+        catch (Exception e)
+        {
+            e.printStackTrace();
+        }
+    }
+}
diff --git a/wear/src/main/java/jp/sfjp/gokigen/a01c/utils/XmlElement.java b/wear/src/main/java/jp/sfjp/gokigen/a01c/utils/XmlElement.java
new file mode 100644 (file)
index 0000000..04d4449
--- /dev/null
@@ -0,0 +1,183 @@
+package jp.sfjp.gokigen.a01c.utils;
+
+import android.util.Log;
+import android.util.Xml;
+
+import org.xmlpull.v1.XmlPullParser;
+import java.io.StringReader;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+
+import androidx.annotation.NonNull;
+
+public class XmlElement
+{
+    private static final String TAG = XmlElement.class.getSimpleName();
+    private static final XmlElement NULL_ELEMENT = new XmlElement();
+
+    private String tagName = "";
+    private String tagValue;
+
+    private final LinkedList<XmlElement> childElements;
+    private final Map<String, String> attributes;
+    private XmlElement parentElement;
+
+    private XmlElement()
+    {
+        //Log.v(TAG, "XmlElement()");
+        parentElement = null;
+        childElements = new LinkedList<>();
+        attributes = new HashMap<>();
+        tagValue = "";
+    }
+
+    public XmlElement getParent()
+    {
+        return (parentElement);
+    }
+    public String getTagName()
+    {
+        //Log.v(TAG, "XmlElement Tag [" + tagName + "]");
+        return (tagName);
+    }
+
+    private void setTagName(String name)
+    {
+        tagName = name;
+    }
+
+    public String getValue()
+    {
+        //Log.v(TAG, "XmlElement Value [" + tagValue + "]");
+        return (tagValue);
+    }
+    private void setValue(String value)
+    {
+        tagValue = value;
+    }
+
+    private void putChild(XmlElement childItem)
+    {
+        childElements.add(childItem);
+        childItem.setParent(this);
+    }
+
+    public XmlElement findChild(String name)
+    {
+        for (final XmlElement child : childElements)
+        {
+            if (child.getTagName().equals(name))
+            {
+                return (child);
+            }
+        }
+        return (new XmlElement());
+    }
+
+    public List<XmlElement> findChildren(String name)
+    {
+        final List<XmlElement> tagItemList = new ArrayList<>();
+        for (final XmlElement child : childElements)
+        {
+            if (child.getTagName().equals(name))
+            {
+                tagItemList.add(child);
+            }
+        }
+        return (tagItemList);
+    }
+
+    private void setParent(XmlElement parent)
+    {
+        parentElement = parent;
+    }
+
+    private void putAttribute(String name, String value)
+    {
+        attributes.put(name, value);
+    }
+
+    public String getAttribute(String name, String defaultValue)
+    {
+        String ret = attributes.get(name);
+        if (ret == null)
+        {
+            ret = defaultValue;
+        }
+        return (ret);
+    }
+
+    private static XmlElement parse(XmlPullParser xmlPullParser)
+    {
+        XmlElement rootElement = XmlElement.NULL_ELEMENT;
+        try
+        {
+            XmlElement parsingElement = XmlElement.NULL_ELEMENT;
+            MAINLOOP:
+            while (true)
+            {
+                switch (xmlPullParser.next())
+                {
+                    case XmlPullParser.START_DOCUMENT:
+                        Log.v(TAG, "------- START DOCUMENT -----");
+                        break;
+                    case XmlPullParser.START_TAG:
+                        final XmlElement childItem = new XmlElement();
+                        childItem.setTagName(xmlPullParser.getName());
+                        if (parsingElement == XmlElement.NULL_ELEMENT) {
+                            rootElement = childItem;
+                        } else {
+                            parsingElement.putChild(childItem);
+                        }
+                        parsingElement = childItem;
+
+                        // Set Attribute
+                        for (int i = 0; i < xmlPullParser.getAttributeCount(); i++)
+                        {
+                            parsingElement.putAttribute(xmlPullParser.getAttributeName(i), xmlPullParser.getAttributeValue(i));
+                        }
+                        break;
+
+                    case XmlPullParser.TEXT:
+                        parsingElement.setValue(xmlPullParser.getText());
+                        break;
+
+                    case XmlPullParser.END_TAG:
+                        parsingElement = parsingElement.getParent();
+                        break;
+
+                    case XmlPullParser.END_DOCUMENT:
+                        Log.v(TAG, "------- END DOCUMENT -------");
+                        break MAINLOOP;
+
+                    default:
+                        break MAINLOOP;
+                }
+            }
+        }
+        catch (Exception e)
+        {
+            e.printStackTrace();
+            rootElement = XmlElement.NULL_ELEMENT;
+        }
+        return (rootElement);
+    }
+
+    public static XmlElement parse(@NonNull String xmlStr)
+    {
+        try
+        {
+            XmlPullParser xmlPullParser = Xml.newPullParser();
+            xmlPullParser.setInput(new StringReader(xmlStr));
+            return parse(xmlPullParser);
+        }
+        catch (Exception e)
+        {
+            e.printStackTrace();
+        }
+        return (new XmlElement());
+    }
+}
index 664ef12..2264523 100644 (file)
@@ -1,6 +1,7 @@
 <?xml version="1.0" encoding="utf-8"?>
 <resources>
     <string name="app_name">A01c</string>
+    <string name="app_name2">A01c</string>
     <string name="hello_round">Hello Round World!</string>
     <string name="hello_square">Hello Square World</string>
 
@@ -70,4 +71,7 @@
     <string name="change_title_from_theta_to_opc">OPCに接続</string>
     <string name="change_message_from_theta_to_opc">接続方式をOPCにしますか?</string>
 
+    <string name="connection_method_opc">OPC</string>
+    <string name="connection_method_theta">THETA</string>
+
 </resources>
index 96dc574..22bac36 100644 (file)
@@ -1,5 +1,6 @@
 <resources>
     <string name="app_name">A01c</string>
+    <string name="app_name2">A01c</string>
     <string name="hello_round">Hello Round World!</string>
     <string name="hello_square">Hello Square World!</string>
 
@@ -68,4 +69,7 @@
     <string name="change_title_from_theta_to_opc">Change To OPC</string>
     <string name="change_message_from_theta_to_opc">Change To OPC, OK?</string>
 
+    <string name="connection_method_opc">OPC</string>
+    <string name="connection_method_theta">THETA</string>
+
 </resources>