2019年9月9日月曜日

Build TensorFlow Lite on Raspberry Pi 4

TesorFlow Lite Raspberry Pi 用の libtensorflow-lite.a を作る
TensorFlowの当該のページ通りにすればよい。
他のページは見ない方が良い
About 40 minutes.

Build TensorFlow Lite for Raspberry Pi

cd ~/prj
git clone https://github.com/tensorflow/tensorflow.git
cd tensorflow
./tensorflow/lite/tools/make/download_dependencies.sh
./tensorflow/lite/tools/make/build_rpi_lib.sh
ls -al tensorflow/lite/tools/make/gen/rpi_armv7l/lib
   drwxr-xr-x 2 root root     4096 Sep  9 02:32 .
   drwxr-xr-x 5 root root     4096 Sep  9 02:32 ..
   -rw-r--r-- 1 root root 12164884 Sep  9 02:32 benchmark-lib.a
   -rw-r--r-- 1 root root  5796642 Sep  9 02:32 libtensorflow-lite.a

上記のページでは
tensorflow/lite/tools/make/gen/lib/rpi_armv7/libtensorflow-lite.a
ちょっと違う(笑)

Peace!!

Build Bazel(0.29.0) on Raspberry Pi 4

Bazel 0.26.0, 0.29.0のbuildです。

1.準備

sudo apt install openjdk-8-jdk

jdk は下記では8がサポート対象となっている
8にしないとエラーが発生する。このような対応不能なエラーが発生した。
#
# A fatal error has been detected by the Java Runtime Environment:
#
#  Internal Error (g1ConcurrentMark.cpp:1666), pid=5210, tid=5234
#  fatal error: Overflow during reference processing, can not continue. Please increase MarkStackSizeMax (current value: 2097152) and restart.
#
# JRE version: OpenJDK Runtime Environment (11.0.3+7) (build 11.0.3+7-post-Raspbian-5)

https://docs.bazel.build/versions/master/install-compile-source.html

もし違う場合には、確認して変更またはインストールする
下の例は0だったので、2に変更した後に、再度確認した画面
sudo update-alternatives --config javac

There are 2 choices for the alternative javac (providing /usr/bin/javac).



  Selection    Path                                          Priority   Status
------------------------------------------------------------
  0            /usr/lib/jvm/java-11-openjdk-armhf/bin/javac   1111      auto mode
  1            /usr/lib/jvm/java-11-openjdk-armhf/bin/javac   1111      manual mode
* 2            /usr/lib/jvm/java-8-openjdk-armhf/bin/javac    1081      manual mode

Press <enter> to keep the current choice[*], or type selection number:

2. ソースのダウンロード

mkdir ~/prj/bazel;cd ~/prj/bazel
$ wget https://github.com/bazelbuild/bazel/releases/download/0.29.0/bazel-0.29.1-dist.zip
$ unzip bazel-0.29.0-dist.zip

3. build前の設定と変更

環境変数追加
$ EXTRA_BAZEL_ARGS="--host_javabase=@local_jdk//:jdk"

2つのファイルを変更
compile.sh
before
bazel_build "src:bazel_nojdk${EXE_EXT}" \
  --action_env=PATH \
  --host_platform=@bazel_tools//platforms:host_platform \
  --platforms=@bazel_tools//platforms:target_platform \
  || fail "Could not build Bazel"

after
bazel_build "src:bazel_nojdk${EXE_EXT}" \
  --host_javabase=@local_jdk//:jdk \
  --action_env=PATH \
  --host_platform=@bazel_tools//platforms:host_platform \
  --platforms=@bazel_tools//platforms:target_platform \
  || fail "Could not build Bazel"

scripts/bootstrap/compile.sh
before
  run "${JAVAC}" -classpath "${classpath}" -sourcepath "${sourcepath}" \
      -d "${output}/classes" -source "$JAVA_VERSION" -target "$JAVA_VERSION" \
      -encoding UTF-8 ${BAZEL_JAVAC_OPTS} "@${paramfile}"

after
  run "${JAVAC}" -classpath "${classpath}" -sourcepath "${sourcepath}" \
      -d "${output}/classes" -source "$JAVA_VERSION" -target "$JAVA_VERSION" \
      -encoding UTF-8 ${BAZEL_JAVAC_OPTS} "@${paramfile}" -J-Xmx1024M

で、Go!!!
time comple.sh

この文字列が出ればOK
Build successful! Binary is here: /home/pi/tmp/output/bazel

次にコピーして完了
sudo cp output/bazel /usr/local/bin

tころで、こんなエラーがでた。
これは、上記の一番目の変更をしなかったから。。。
ERROR: /tmp/bazel_SwJ5aUhR/out/external/bazel_tools/tools/jdk/BUILD:492:14: Configurable attribute "actual" doesn't match this configuration: Could not find a JDK for host execution environment, please explicitly provide one using `--host_javabase.`

Peace!!

2019年8月31日土曜日

OpenCV4 Stereo matching

Stereo matchingは古くからある重要な手法。
僕も、いろいろな場面で使っている。
OpenCV4をセットアップしたあと、cpp ディレクトリーに移動

g++  `pkg-config opencv4 --cflags --libs` stereo_match.cpp -o stereo_match -std=c++11 -latomic

stereo_match ../data/aloeL.jpg ../data/aloeR.jpg --algorithm=sgbm --blocksize=3 --max-disparity=128

こんな感じでbuild とコンパイル

で、いろいろパラメータ変えるとこんな感じ


更にフィルターをかけて、、

 pip3 install scikit-learn
 sudo apt install python3-sklearn

import numpy as np
from sklearn.preprocessing import normalize
import cv2

print('loading images...')
imgL = cv2.imread('../data/aloeLs.jpg')  # downscale images for faster processing if you like
imgR = cv2.imread('../data/aloeRs.jpg')

# SGBM Parameters -----------------
window_size = 3
left_matcher = cv2.StereoSGBM_create(
    minDisparity=0,
    numDisparities=80,
    blockSize=1,
    P1=8 * 3 * window_size ** 2,
    P2=32 * 3 * window_size ** 2,
    disp12MaxDiff=1,
    uniquenessRatio=15,
    speckleWindowSize=0,
    speckleRange=2,
    preFilterCap=63,
    mode=cv2.STEREO_SGBM_MODE_SGBM_3WAY
)
right_matcher = cv2.ximgproc.createRightMatcher(left_matcher)

# FILTER Parameters
lmbda = 80000
sigma = 1.2
visual_multiplier = 1.0
wls_filter = cv2.ximgproc.createDisparityWLSFilter(matcher_left=left_matcher)
wls_filter.setLambda(lmbda)
wls_filter.setSigmaColor(sigma)

print('computing disparity...')
displ = left_matcher.compute(imgL, imgR)  # .astype(np.float32)/16
dispr = right_matcher.compute(imgR, imgL)  # .astype(np.float32)/16
displ = np.int16(displ)
dispr = np.int16(dispr)
filteredImg = wls_filter.filter(displ, imgL, None, dispr)  # important to put "imgL" here!!!

filteredImg = cv2.normalize(src=filteredImg, dst=filteredImg, beta=0, alpha=255, norm_type=cv2.NORM_MINMAX);
filteredImg = np.uint8(filteredImg)
cv2.imshow('Disparity Map', filteredImg)
cv2.waitKey()
cv2.destroyAllWindows()

Peace!!


stm1 imgKittyl.bmp imgKitty.bmp  --algorithm=sgbm --blocksize=1 --max-disparity=64


stm1 imgKittyl.bmp imgKitty.bmp  --algorithm=sgbm --blocksize=1 --max-disparity=80

stm1 imgKittyl.bmp imgKitty.bmp  --algorithm=sgbm --blocksize=9 --max-disparity=64


2019年8月21日水曜日

Oracle SQL*Plus。MinGW32は癖がある (笑)

Oracle SQL*Plusを使うなんて20年ぶり
Windows環境で実行させて、結果をLinux環境に送り別の処理をする。

例えば、前日に新規登録されたデータだけを、翌日に抽出する場合。
Linux環境では、localtime_rで比較的簡単に日付指定の文字列を作れる。
ところが、Windows環境のMinGWは基本的にWindowsに依存しているので、
同じgccを使っても、localtime*は使用できない。
gccでも、違うんだぁ

Msys MinGWは、その環境で作った実行モジュールをWindowsのコマンドプロンプトで実行できない。
それをするなら、MinGWだけをインストールする必要がある。
MinGW | Minimalist GNU for Windows

でも、MinGWはWindowsに依存しているのでLinuxとの違いが発生する。
多分、今回のlocaltime*だけだと思うけど、、、

まぁ、やるといろいろ起こります。勉強勉強

で、今回のソースをドーンと

Peace!!


SQL*Plusを起動するバッチ

@ECHO OFF
:START
ECHO ---------------------------------------------------
ECHO 前日新規に登録された品目情報を出力します。
ECHO ---------------------------------------------------
CD %~dp0
DEL hinsabun.csv
hinsabun.exe > hinsabun.sql
@ECHO SQLを実行中です。しばらくお待ち下さい..
@ECHO -------------------------------
sqlplus /nolog @"hinsabun.sql" USER PASSWORD 192.168.XXX.XXX/ORCL
@ECHO -------------------------------
@ECHO 完了しました。
EXIT

localtime_r を使わない処理

#include <stdio.h>
#include <string.h>
#include <time.h>

#define PRS(A)  printf("%s\n", A)
char    *mn[]= {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};

int main(int argc, char* argv[]){
    char    szTime[15];
    char    szBuf[256], szBuf1[64];
    char    szMn[4], szDmy[10];
    int     n = 1, iDay, i, iMn, iYr;
    struct tm tm;
    time_t t;
    
    time(&t);
    t -= (86400 * n);
    strcpy(szBuf1, ctime(&t));
    strcpy(szDmy, strtok(szBuf1, " "));
    strcpy(szMn, strtok(NULL, " "));
    iDay = atoi(strtok(NULL, " "));
    strcpy(szDmy, strtok(NULL, " "));
    iYr = atoi(strtok(NULL, " "));
    for (i = 0; i < 12; i++) {
        if (strcmp(szMn, mn[i]) == 0){
            iMn = i + 1;
            break;
        }
    }
    sprintf(szTime, "%04d%02d%02d", iYr, iMn, iDay);

    //localtime_r(&t, &tm);
    //sprintf(szTime, "%04d%02d%02d%02d%02d%02d",
    //        tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
    //        tm.tm_hour, tm.tm_min, tm.tm_sec);
    //sprintf(szTime, "%04d%02d%02d",
    //          tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday);
    
    PRS("connect &&1/&&2@&&3");
    PRS("spool off");
    PRS("set echo off");
    PRS("set heading off");
    PRS("set termout off");
    PRS("set pause off");
    PRS("set pagesize 0");
    PRS("set linesize 10000");
    PRS("--set trimout on");
    PRS("set trimspool on");
    PRS("set feedback off");
    PRS("set verify off");
    PRS("set colsep '|'");
    PRS("spool hinsabun.csv");
    sprintf(szBuf, "SELECT ITEM_CD, ITEM_DIV, ITEM_NAME1, ITEM_NAME2, STD_UNIT, STD_UNITPRICE, UNIT2, UNIT_CONV_RATE,ITEM_NAME4,REGIST_DATE, UPDATE_DATE from DFW_M040M where REGIST_DATE >= to_date('%s', 'yyyymmdd');", szTime);
    PRS(szBuf);
    PRS("spool off");
    PRS("exit");
    
    return 0;
}

Peace!!

2019年8月11日日曜日

AsyncTaskによるDB非同期処理をListenerを使ってクラス化

Android ActivityでDBを頻繁に使うプログラムを開発する場合に、
前項のようなコードをActivity内に組込むのはやめたい。
クラス化にあたっての課題は、処理の結果を呼び出したクラスに渡すか?
非同期処理処理を踏まえてどうするか。。。
で、先人の知恵を借りてListenerを使って呼び出し側で非同期処理の終了を
解るようにして、一件落着
ますます、便利になった。
Peace!!

ソースの先頭には、使い方を書いた。
サーバーサイドのDBプログラムは別途必要です。
ソースコード、どーんと(笑)

/***********************************************************
 * AsyncTask<型1, 型2,型3>
 *   型1 … Activityからスレッド処理へ渡したい変数の型
 *          ※ Activityから呼び出すexecute()の引数の型
 *          ※ doInBackground()の引数の型
 *   型2 … 進捗度合を表示する時に利用したい型
 *          ※ onProgressUpdate()の引数の型
 *   型3 … バックグラウンド処理完了時に受け取る型
 *          ※ doInBackground()の戻り値の型
 *          ※ onPostExecute()の引数の型
 *   ※ それぞれ不要な場合は、Voidを設定すれば良い
 * --------------------------------------------------------------
 * 呼び出す側に以下を追加する
 ********************************************************************************
 * 汎用DBアクセスクラス SqlOpeAsyncTask を使う場合のListener設定
 * クラスを使う側で設定する。
 * onDestroyは、使うクラス側で重ならなければ使えるかも。未確認
 * @return
 * /
    private SqlOpeAsyncTask.Listener createListener(){
        return new SqlOpeAsyncTask.Listener(){
            @Override
            public void onSuccess(String ret){
                // 以下は個々のプログラム毎に記述
                etKata.setText(ret);
            }
        };
    }
    @Override
    protected void onDestroy() {
        SqlOpeAsyncTask.setListener(null);
        super.onDestroy();
    }

    // 呼び出し例
        String in1 =  getResources().getString(R.string.url_srv_gets1);
        String in2 =  "?100:select kata,tana,hinc,kazu from zaiko where hinc = '15916-1' and tana <> 'REFER' order by tana DESC; ";
        SqlOpeAsyncTask retAsyn = new SqlOpeAsyncTask();
        retAsyn.setListener(createListener());
        String inStr = in1 + in2;
        Log.d(TAG, "before Async execute");
        retAsyn.execute(inStr);
 ***********************************************************************/

package com.futureagri.app.thn.hd.java;

import android.nfc.Tag;
import android.os.AsyncTask;
import android.util.Log;
import android.widget.TextView;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;

/******************************************************************
 * 非同期でデータベース処理をするクラス。
 ******************************************************************/
public  class SqlOpeAsyncTask  extends AsyncTask<String, Void, String> {
    private Listener listener;

    private static final String TAG = "SqlOpeAsyncTask";
    private String retString = "";
    private TextView textView;

    /********************************************************************
     * メインスレッドとは別のスレッドで実行されます。
     * 非同期で処理したい内容を記述します。
     * このメソッドだけは必ず実装する必要があります
     * @param data
     * @return
     */
    @Override
    //protected String doInBackground(Object[] data) {
    public String doInBackground(String... data) {
        // target URL
        String urlStr = (String)data[0];
        Log.d(TAG, "doInBackground: " + "input sql=" + urlStr);
        // Variable of set result texts
        //StringBuilder result = new StringBuilder();
        String result = "";
        //http接続を行うHttpURLConnectionオブジェクトを宣言。finallyで確実に解放するためにtry外で宣言。
        HttpURLConnection con = null;
        //http接続のレスポンスデータとして取得するInputStreamオブジェクトを宣言。同じくtry外で宣言。
        InputStream is = null;
        int i = 10;
        try {
            //URLオブジェクトを生成。
            URL url = new URL(urlStr);
            //URLオブジェクトからHttpURLConnectionオブジェクトを取得。
            con = (HttpURLConnection) url.openConnection();
            //http接続メソッドを設定。
            con.setRequestMethod("GET");
            //接続。
            con.connect();
            final int   status = con.getResponseCode();
            if (status == HttpURLConnection.HTTP_OK) {
                // Success HTTP GET method
                is = con.getInputStream();
                result = is2String(is);
                is.close();
            }else {
                Log.d(TAG, "doInBackground: HTTP response error");
            }
        } catch (MalformedURLException ex) {
            ex.printStackTrace();
            //} catch (ProtocolException ex) {
            //ex.printStackTrace();
            Log.d(TAG, "doInBackground: HTTP MalformedURLException");
        } catch (IOException ex) {
            ex.printStackTrace();
            Log.d(TAG, "doInBackground: HTTP IOException");
        } finally {
            // HttpURLConnectionオブジェクトがnullでないなら解放。
            if (con != null) {
                con.disconnect();
            }
            // InputStreamオブジェクトがnullでないなら解放。
            if (is != null) {
                try {
                    is.close();
                } catch (IOException ex) {
                    Log.d(TAG,"doInBackground: HTTP close is IOException");
                }
            }
        }
        // 非同期で取得したデータをセットする
        if ( i == 0) {
            Log.d(TAG, "doInBackground: HTTP return : error end");
            return "-99999";
        }else {
            //return result.toString();
            retString = result;
            return result;
        }
    }
    /*****************************************************************************
     * doInBackgroundメソッドの実行後にメインスレッドで実行されます。
     * doInBackgroundメソッドの戻り値をこのメソッドの引数として受け取り、
     * その結果を画面に反映させることができます
     * @param result
     */
    @Override
    public void onPostExecute(String result) {
        //toastMake(result, 0, -200);
        Log.d(TAG, "onPostExecute: result :" + result);
        String[] ret = result.split("\\|");  // Mac \ -> (option + ¥)
        int iMode = Integer.parseInt(ret[0]);   // 呼び出した処理番号
        int cnt  = Integer.parseInt(ret[1]);    // 検索数
        int retu = Integer.parseInt(ret[2]);    // 列数
        Log.d(TAG, "onPostExecute: mode:cnt:retu=" + iMode + ":" + cnt + ":" + retu);
        //-------------------------------------------------------------
        //  mode=100 kata,tana,hinc,kazu
        //-------------------------------------------------------------
        if (iMode == 100) {
            retString = iMode + "|" + cnt + "|" + retu + "|";
            for (int i = 0; i < cnt * retu; i++) {
                retString = retString + ret[3 + i] + "|";
            }
        }
        if (listener != null) {
            listener.onSuccess(retString);
        }
    }
    /*****************************************************************************
     * InputStreamオブジェクトを文字列に変換するメソッド。変換文字コードはUTF-8。
     *
     * @param is 変換対象のInputStreamオブジェクト。
     * @return 変換された文字列。
     * @throws IOException 変換に失敗した時に発生。
     */
    private String is2String(InputStream is) throws IOException {
        BufferedReader reader = new BufferedReader(new InputStreamReader(is, "UTF-8"));
        StringBuffer sb = new StringBuffer();
        char[] b = new char[2048];
        int line;
        while(0 <= (line = reader.read(b))) {
            sb.append(b, 0, line);
        }
        return sb.toString();
    }
    /************************************************************
     * Listener 処理を定義する
     * 
     * @param listener
     */
    void setListener(Listener listener) {
        this.listener = listener;
    }
    interface Listener {
        void onSuccess(String  count);
    }
}

2019年8月2日金曜日

Android 非同期処理でサーバサービスを利用する

スマフォからデータベース処理する方法のメモ
至る所に掲載されているので、あくまでも自分のメモ

基本的にデータ量が少ないのでGETメソッドで説明
ちなみに、com.squareup.okhttp3:okhttp:3.12.1 を使っています。

1.基本的な流れ

・スマフォ側で、起動するサーバサイドのサービスの定義と渡す情報の設定
・非同期処理部分(AsyncTask)の記述。
   基本部分は一度書けば使いまわし。
   大事なのは、onPostExecuteの部分。
   この部分にサーバから戻ってきたデータに対する処理を記述する。
   この投稿では、データをチェックしたあと、Intentで別のActivity起動している

2. スマフォ側でサーバプログラム起動の準備

オブジェクト作成と、起動サービス、引数の設定
非同期処理のHTTPサービスのオブジェクトを作成して実行

Object[] data = new Object[3];
data[0] = getResources().getString(R.string.url_srv_reg_payout);
// 引数を設定する
data[1] =

hdPartsActivity.SqlSelectReciever receiver =
               new hdPartsActivity.SqlSelectReciever();
receiver.execute(qq);

3.非同期処理(AsyncTask)を担当する本体部分

   private class SqlSelectReciever extends AsyncTask<String, String, String> {
        public SqlSelectReciever() {
        }
        @Override
        public String doInBackground(String... params) {
            // target URL
            String urlStr = (String)params[0];
            Log.d(TAG, " SqlSelectReciever: " + "sql=" + urlStr);
            // Variable of set result texts
            //StringBuilder result = new StringBuilder();
            String result = "";
            //http接続を行うHttpURLConnectionオブジェクトを宣言。finallyで確実に解放するためにtry外で宣言。
            HttpURLConnection con = null;
            //http接続のレスポンスデータとして取得するInputStreamオブジェクトを宣言。同じくtry外で宣言。
            InputStream is = null;
            int i = 10;
            try {
                //URLオブジェクトを生成。
                URL url = new URL(urlStr);
                //URLオブジェクトからHttpURLConnectionオブジェクトを取得。
                con = (HttpURLConnection) url.openConnection();

                //http接続メソッドを設定。
                con.setRequestMethod("GET");
                //接続。
                con.connect();
                final int   status = con.getResponseCode();
                if (status == HttpURLConnection.HTTP_OK) {
                    // Success HTTP GET method
                    is = con.getInputStream();
                    result = is2String(is);
                    Log.d(TAG, " HTTP connect result=" + result);
                    is.close();
                }else {
                    Log.d(TAG, "HTTP response error");
                }
            } catch (MalformedURLException ex) {
                ex.printStackTrace();
                //} catch (ProtocolException ex) {
                //ex.printStackTrace();
                Log.d(TAG, "HTTP MalformedURLException");
            } catch (IOException ex) {
                ex.printStackTrace();
                Log.d(TAG, "HTTP IOException");
            } finally {
                // HttpURLConnectionオブジェクトがnullでないなら解放。
                if (con != null) {
                    Log.d(TAG, "HTTP not null");
                    con.disconnect();
                }
                // InputStreamオブジェクトがnullでないなら解放。
                if (is != null) {
                    Log.d(TAG,"HTTP close InputStream");
                    try {
                        is.close();
                    } catch (IOException ex) {
                        Log.d(TAG,"HTTP close is IOException");
                    }
                }
            }
            //JSON文字列を返す。
            if ( i == 0) {
                Log.d(TAG, "HTTP return : error");
                return "error";
            }else {
                //Log.d("doInBackground:return:", result.toString());
                //return result.toString();
                //Log.d(TAG, "HTTP return : normal");
                return result;
            }
        }
        //=================================================
// サーバから戻ってきた戻り値に対する処理
// ここの部分が大事。
// Activityの中で複数の非同期処理をする時もここにを書く。
// 因みに僕は戻り値の最初の情報cntとretuを使って複数対応している。
//=================================================
        @Override
        public void onPostExecute(String result) {
            String[] ret = result.split("\\|");  // Mac \ -> (option + ¥)
            int cnt  = Integer.parseInt(ret[0]);  // 1行目:検索数
            int retu = Integer.parseInt(ret[1]);  // 1行目:列数
            Log.d(TAG, "cnt:retu=" + cnt + ":" + retu);
                 ・
                 ・ ここにいろいろ処理を書く、
                 ・
            Intent intent = new Intent(hdPartsActivity.this, SqlGetList2.class);
            // intentへ添え字付で値を保持させる
            intent.putExtra( "hdkey", hks);
            // 返却したい結果ステータスをセットする
            setResult( SqlGetList2.RESULT_OK, intent );
            //startActivity(new Intent(hdSeibanListActivity.this, SqlGetList2.class));
            startActivity(intent);
            //Log.d(TAG, " Intent after : startActivity(intent)");
            return;
        }
        /**
         * InputStream objectを文字列に変換するmethod。変換文字codeはUTF-8。
         *
         * @param is 変換対象のInputStreamオブジェクト。
         * @return 変換された文字列。
         * @throws IOException 変換に失敗した時に発生。
         */
        private String is2String(InputStream is) throws IOException {
            BufferedReader reader = new BufferedReader(new InputStreamReader(is, "UTF-8"));
            StringBuffer sb = new StringBuffer();
            char[] b = new char[1024];
            int line;
            while(0 <= (line = reader.read(b))) {
                sb.append(b, 0, line);
            }
            return sb.toString();
        }
    }

Peace!!

2019年7月22日月曜日

MySQL 自動バックアップ

MySQLバックアップの忘備録

1.バックアップ用シェル

#!/bin/sh

# Set mask for other user cann't read
#umask 077

# backup file
# Retention period
period=31

# directory for backup files
dirpath='/home/pi/backup/mysql'

# backup file naming
filename=`/bin/date +%y%m%d%H`

# excute
/usr/bin/mysqldump --opt --all-databases --events --default-character-set=binary -u root --password=xxxxx| /bin/gzip > $dirpath/$filename.sql.gz
#/usr/bin/mysqldump --opt --all-databases --events --default-character-set=binary -u root --password=xxxxx > /tmp/filename.sql

/bin/cp $dirpath/$filename.sql.gz $dirpath/today

# delete old backup files
oldfile=`/bin/date --date "$period days ago" +%y%m%d%H`
/bin/rm -f $dirpath/$oldfile.sql.gz

2.crontabの設定

0 2 * * *  /home/pi/prj/sql/mysql_backup.sh > /tmp/cron-bk.stdout 2 > /tmp/cron-bk.stderr || [ $? -eq 1 ]
15 12 * * *  /home/pi/prj/sql/mysql_backup.sh > /tmp/cron-bk.stdout 2 > /tmp/cron-bk.stderr || [ $? -eq 1 ]

Peace!!

2019年7月15日月曜日

テスト用DBを一発で初期化するbash

自分の忘備録

開発しているときは、テスト用DBを繰返し初期化する。
そのシェル。でも、僕以外にはほとんど利用価値はないかも、、、
ポイントは、DBにインポートするデータを集めたdirectoryを指定し
その中から、ファイル名だけを抽出してDB登録するシェルに渡す処理かも

自分用だから、説明はなし。

Peace!!

#!/bin/bash

# テスト用データのディレクトリー
files="../../data/*"
fileary=()
dirary=()

DB=DB名称
USER=ユーザ名
PW=パスワード

# DBのデータを削除して初期化する
mysql -u$USER $DB -p$PW << EOS
truncate hd;
truncate seibans;
update counters set value=0 where name='seibans';
EOS


for filepath in $files; do
    if [ -f $filepath ] ; then
        fileary+=("$filepath")
    elif [ -d $filepath ] ; then
        dirary+=("$filepath")
    fi
done

#echo "ファイル一覧"
for i in ${fileary[@]}; do
    qq=$i
    # pathを削除
    qqq="${qq##*/}"
    # ファイル名の拡張子を取る
    FILE=${qqq%.*}
    # テストデータDB登録
    ./reg.sh $FILE
done

#echo "ディレクトリ一覧"
#for i in ${dirary[@]}; do
#    echo $i
#done

2019年7月13日土曜日

Android studio 小ネタ

Android studio の備忘録、特に小ネタ
メモ代わりに追加していきます。

(1)既存のProject/Packageを利用して新しいPackageのProjectを作る


(2)既存のProjectを、OneDriveにコピーして利用する

Android Studioで開いて、build > Clean Project
そのまますると、スマフォへのインストール時に、古いWindows Pathを使おうとする。
そのエラーでインストールできなかったけど、このを実行したあとはインストールできた。コンソールに出るメッセージでも変わった事は確認できた。
これで、OneDriveを介して複数のPC間でプロジェクトを共有可能となった。
便利便利 (^^)/

Peace!!


2019年7月12日金曜日

Firebase ML KitのSample Package名を、新たなPackage名に変更する

あくまでも、忘備録

何を言っているかというと、、、まぁ、うまく伝えられないので、、、
簡単にいうと自分のPackage名(com.futureagri. )にしたい。
com.google.firebase.samples.apps.mlkit というながーいPackage名
それに、google さんのsamplesと入るのは、嫌だなぁ

Firebaseのプロジェクトもっており、アプリの登録もできるている事



ベタベタだけど、、、

(1) Package 名を決める
com.futureagri.app.xxx.hd
その名前で、Firebaseにアプリの登録を済ませる。

(2)ソースコードの修正
quickstart-android\mlkit\app\src\main\java\com\google\firebase\samples\apps\mlkit
のmlkitをコピーする。
この中にあるソースコードのPackage名を変更する。

com.google.firebase.samples.apps.mlkit を
com.futureagri.app.xxx.hd  に変更する。

(3) Android Studioで新規プロジェクトを作る
Start a new Android Studio project  を選び
Activityは、Add No Activity
次の画面にPackageの情報を入れれば取り合えず終わり。
Package名で指定したディレクトリーができている。

(4) 編集したソースコードをコピー
上記で出来たディレクトリーに(2)で編集したソースコードを入れる。

(5) いろいろなファイルのコピー
元々のmlkitのモノが使える。package名に対応した変更は必要。
ただし、mlkitのモノをそのまま全部入れない。
AndroidManifest.xml、\res以下のリソースファイルを確認しながら内容や、ファイルをコピーした。

(6) Android Studio立上げ
syncやBuildなどを行う。エラーがでてくるのでよく見ると、
比較的容易に集積できる。
build.gradle は2つあるが、それぞれの確認も必要です。

ここは少し時間がかった。エラー修正を少し繰り返し30分程度試行錯誤。

(7)BuildとInstall
数回繰り返して、Android デバイスにインストール。
File > Invalidate Cashes /Restart.... も行い。
Buildしなおして、OK

obsolete とwarningがでるけど、、、なんでだろう?

packageを変える方法は、他にもWebに載っているので、、、

これで、楽しい事がいろいろできる。(^^)/

Peace!!


2019年7月11日木曜日

MariaDB 思いっきりドーンとtable 作成


#!/bin/bash

DB=DB名
USER=ユーザ名
PW=パスワード

#CLMS1="tana, date, hinc, kata, katad"
#select count(*) from $TBL1 where $1 like "$2";
#select $CLMS1 from $TBL1 where $1 like "$2";
#show columns from zaiko;

mysql -u$USER $DB -p$PW << EOS
create table counters (name char(16), value int);
create table seibans (
seiban_id int,
seiban char(8),
seiban_name varchar(120),
hd_kpn int,
hd_end_id char(5),
hd_end_at char(14),
person_id char(5),
create_at char(14));
create table units (part_number int,rev_cnt int,hinc char(32),hink char(3),updata_header_count int,update_data_count int,drawing_name char(30),parts_numbers int,effect_records int,model_name varchar(120),unit_name varchar(120),model_code char(12),target_roth char(10),drawing_number_old char(30),quantity int,approval_id char(5),approval_at char(14),update_design_id char(5),update_design_at char(14),drawer_id char(5),update_drawing_at char(14),start_at char(14),end_at char(14),disabled_at char(14),regist_id char(5),regist_at char(14),update_id char(5),update_at char(14),delete_id char(5),delete_at char(14));
create table hd (
seiban char(8),
seiban_id int,
pos int,
update_info varchar(120),
code char(10),
layout_no varchar(120),
sharp varchar(6),
name varchar(120),
kata varchar(120),
spec varchar(120),
maker varchar(60),
members int,
total_members int,
payout_flag char(1),
remarks varchar(120),
update_reason varchar(120),
del_flag char(1),
kpn int,
tana char(32),
part_number int,
hinc char(32),
hink char(3),
regist_id char(5),
regist_at char(14));
insert into counters values('payouts', 0);
insert into counters values('seibans', 0);

EOS

Peace!!



unit 無い場合 changed 190722


#!/bin/bash

DB=DB名
USER=ユーザ名
PW=パスワード

#CLMS1="tana, date, hinc, kata, katad"
#select count(*) from $TBL1 where $1 like "$2";
#select $CLMS1 from $TBL1 where $1 like "$2";
#show columns from zaiko;

mysql -u$USER $DB -p$PW << EOS
drop table counters, seibans, hd;
create table counters (name char(16), value int);
create table seibans (
seiban_id int,
seiban char(8),
seiban_name varchar(120),
hd_kpn int,
hd_quantity int,
hd_dest char(64),
hd_fjkn char(4),
hd_end_id char(5),
hd_end_at char(14),
person_id int,
create_at char(14));
create table hd (
seiban char(8),
seiban_id int,
pos int,
update_info varchar(120),
code char(10),
layout_no varchar(120),
sharp varchar(6),
name varchar(120),
kata varchar(120),
spec varchar(120),
maker varchar(60),
members int,
total_members int,
payout_flag char(1),
remarks varchar(120),
update_reason varchar(120),
del_flag char(1),
kpn int,
tana char(32),
part_number int,
hinc char(32),
hink char(3),
regist_id char(5),
regist_at char(14),
regist_end_at char(14));
insert into counters values('payouts', 1);
insert into counters values('seibans', 1);
EOS



Shell scripts for MariaDB


1.mariaDBをログインしないでShell Scriptで使う例


#!/bin/bash

# variable check
if [ $# -ne 2 ]; then
    echo -n "Usage: "
    echo -n `basename $0`
    echo  " target-clolumn target-word"
    exit 1
fi

DB=データベース名
USER=ユーザ
PW=パスワード
TBL1=テーブル名
#CLMS1="tana, date, hinc, kata, katad"
CLMS1="tana, hinc, kata, katad"

mysql -u $USER -p$PW $DB << EOS
#select count(*) from $TBL1 where $1 like "$2";
select $CLMS1 from $TBL1 where $1 like "$2";
#show columns from zaiko;
EOS

上記を呼び出して使うShell Script

#!/bin/bash

DT=`cat ./target1.txt`
while read line
do
    #echo -------------------------------------------------
    tt=$line
    echo ">>> $tt"
    ./slct01.sh kata $tt
    #echo $line
done << FILE
$DT
FILE

2.バックアップ用のShell script

#!/bin/sh
# Set mask for other user cann't read
umask 077

# backup file
# Retention period
period=31

# directory for backup files
dirpath='/home/pi/backup/mysql'

# backup file naming
filename=`date +%y%m%d`

#DB=データベース名
USER=ユーザ
PW=パスワード

# excute
mysqldump --opt --all-databases --events --default-character-set=binary -u$USER --password=$PW | gzip > $dirpath/$filename.sql.gz

# delete old backup files
oldfile=`date --date "$period days ago" +%y%m%d`
rm -f $dirpath/$oldfile.sql.gz

3.テストデータを insert する時の例

例は、2つのテーブルにテスト用の値を設定している。
テーブルのデータを削除するのは、

truncate seibans;
truncate  counters;

#!/bin/bash

DB=データベース名
USER=ユーザ
PW=パスワード
TBL1=seibans
TBL2=counters

# 配列宣言(-a)
declare -a sbn=()
# 初期化
declare -a sbn=("11111-11" "12345-76" "88888-99" "12345-56" "12345-89" "99999-00" "12345-66" "19625-01" "12345-67" "19625-02")

i=0
j=0
for e in ${sbn[@]}; do
    #echo "sbn[$i] = ${e}"
    let i++
    let j++
    aa=`date '+%s' | awk '{print strftime("%Y%m%d%H%M%S", $1)}'`
mysql -u $USER -p$PW $DB << EOS
insert into $TBL1 values ($j, '${e}', '${e}', 0, '11111', '$aa', '11111', '$aa');
EOS
done

mysql -u $USER -p$PW $DB << EOS
insert into $TBL2 values ('payouts', 1);
insert into $TBL2 values ("seibans", 1);
EOS

Peace!!

MyLife

僕の趣味は、こんな感じ、、、
この為に、働いているのだぁ、、、はず (^^)
Kayak, Climbing, Music, Skateboard, Airplane

Kayak

いきててよかった。良い子は真似しないようにね。

ハンドロール

2019年 春遠征

古い写真

2014/9 奈良吉 増水

Climbing

前穂高岳登頂(徳沢ー奥又白池泊ーA沢ー前穂高岳)

僕が前穂高岳に登った理由など、、、(^^)

Music

Please wait!!

Skateboard

Please Wait!!

Air Plane

Soon!!

Peace!!

Robotics

僕が開発してるロボットについて、要素技術も含めてまとめ?
いえ、自分の整理用

1.開発ポリシー、概要

自律搬送クローラロボットの開発情報のまとめページ

2013年に最初に書いたロボットの 考え方
基本は変わっていません。

2.RDCS


3.要素技術

3.1 SLAM関係
Raspberry Piで、低コスト Lidar SLAMTEC RPLIDAR A2 を使う

3.2 OpenCV


An Installation of OpenCV4 on Raspberry Pi 3B+ & 4B

Java がインストールされている事が前提。

LD_PRELOAD=/usr/lib/arm-linux-gnueabihf/libatomic.so.1.2.0 python3


Peace!!