LEGO Mindstorms EV3 を Android端末からコントロールする（その4）

LEGO MINDSTORMS EV3 を Android端末でコントロールするために必要な開発環境の構築方法を備忘録も兼ねて記録します。

前回までに、[LEGO MINDSTORMS EV3をBluetoothで接続するまで](http://qiita.com/karubeita/items/6dfbceac72b8bceb9126)を紹介しました。
 今回は、LEGO Mindstorms EV3 のセンサー値を確認します。

#1. 部品の配置

まず、センサーの値を表示するための部品類を、activity_main.xml に記述します。

    <TableLayout
        android:id="@+id/tb.sensors"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" >

        <TableRow
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" >
            
            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Sensors"
                android:textAppearance="?android:attr/textAppearanceLarge" />
        </TableRow>

        <TableRow
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" >

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="1: " />

            <TextView
                android:id="@+id/tv.sensorName1"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="1" />
            
            <TextView
                android:id="@+id/tv.sensor1"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="1" />

            <Button
                android:id="@+id/bt.percent1"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="@string/percent" />

            <Button
                android:id="@+id/bt.si1"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="@string/si_unit" />
        </TableRow>

        <TableRow
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" >

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="2: " />

            <TextView
                android:id="@+id/tv.sensorName2"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="1" />
            
            <TextView
                android:id="@+id/tv.sensor2"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="1" />
            
            <Button
                android:id="@+id/bt.percent2"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="@string/percent" />

            <Button
                android:id="@+id/bt.si2"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="@string/si_unit" />
        </TableRow>

        <TableRow
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" >

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="3: " />

            <TextView
                android:id="@+id/tv.sensorName3"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="1" />
            
            <TextView
                android:id="@+id/tv.sensor3"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="1" />

            <Button
                android:id="@+id/bt.percent3"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="@string/percent" />

            <Button
                android:id="@+id/bt.si3"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="@string/si_unit" />
        </TableRow>

        <TableRow
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" >

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="4: " />

            <TextView
                android:id="@+id/tv.sensorName4"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="1" />
            
            <TextView
                android:id="@+id/tv.sensor4"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="1" />
            
            <Button
                android:id="@+id/bt.percent4"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="@string/percent" />

            <Button
                android:id="@+id/bt.si4"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="@string/si_unit" />
        </TableRow>

        <TableRow
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" >

            <Button
                android:id="@+id/bt.connect"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:text="@string/connect" />
            
        </TableRow>
    </TableLayout>


#2. 部品の実装

次に、MainActivityに次の様な記述を追加します。

    import ev3command.ev3.SensorPort;

センサーの値を表示するためのテキストや、ボタンを実装します。

    private TextView[] mSensorNameTexts = new TextView[4];
    private TextView[] mSensorValueTexts = new TextView[4];
    private Button[] mGetPercentValueButtons = new Button[4];
    private Button[] mGetSiUnitValueButtons = new Button[4];
    private UnidentifiedSensor[] mSensors = new UnidentifiedSensor[4];

表示用メソッドを実装します。

    private void setUpEV3() {       
        // If you know specified sensors are connected, you can use
        // TouchSensor, SoundSensor etc. instead of UnidentifiedSensor.
        mSensors[0] = new UnidentifiedSensor(SensorPort.S1);
        mSensors[1] = new UnidentifiedSensor(SensorPort.S2);
        mSensors[2] = new UnidentifiedSensor(SensorPort.S3);
        mSensors[3] = new UnidentifiedSensor(SensorPort.S4);
    }

    private void findViews() {
        for (int i = 0; i < 4; i++) {           
            mSensorNameTexts[i] = (TextView) findViewById(getResources().getIdentifier("tv.sensorName" + (i + 1), "id", getPackageName()));
            mSensorValueTexts[i] = (TextView) findViewById(getResources().getIdentifier("tv.sensor" + (i + 1), "id", getPackageName()));
            mGetPercentValueButtons[i] = (Button) findViewById(getResources().getIdentifier("bt.percent" + (i + 1), "id", getPackageName()));
            mGetSiUnitValueButtons[i] = (Button) findViewById(getResources().getIdentifier("bt.si" + (i + 1), "id", getPackageName()));
        }
        mConnectButton = (Button) findViewById(R.id.bt_connect);
    }
    
    private int getIndex(View v, View[] vs) {
        for (int i = 0; i < 4; i++) {
            if (v.equals(vs[i])) return i;
        }
        return -1;
    }

次に、ボタンを押したら、センサー値を取得できるように、ボタン用のメソッドを実装します。

    private void setUpButtons() {
        for (int i = 0; i < 4; i++) {
            
            mGetPercentValueButtons[i].setOnClickListener(new OnClickListener() {
                @Override
                public void onClick(View v) {
                    int index = getIndex(v, mGetPercentValueButtons);
                    int result = mSensors[index].getPercentValue();
                    mSensorValueTexts[index].setText("Percent: " + result);
                }
            });
            mGetSiUnitValueButtons[i].setOnClickListener(new OnClickListener() {
                @Override
                public void onClick(View v) {
                    int index = getIndex(v, mGetSiUnitValueButtons);
                    float result = mSensors[index].getSiValue();
                    mSensorValueTexts[index].setText("Si unit: " + result);
                }
            });
        }
        
        mConnectButton.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                findEV3Device(); // Show the device list
            }
        });
    }

各種ボタンは、最初は使用不可にしておくメソッドを実装します。

    private void setUiEnabled(boolean enabled) {
        for (int i = 0; i < 4; i++) {
            mGetPercentValueButtons[i].setEnabled(enabled);
            mGetSiUnitValueButtons[i].setEnabled(enabled);
        }
    }

LEGO MINDSTORMS EV3と繋がったら、各種ボタンを使用可にするために、connected メソッドに、setUiEnabled(true) を実装し、
disconnect メソッドに、setUiEnabled(false)を実装します。


次に、onCreate メソッドで、それぞれのメソッドを呼び出します。

    setUpEV3();
    findViews();
    setUpButtons();
    setUiEnabled(false);

プロジェクトを実行して、接続した　LEGO Mindstorms EV3 の各種センサーの値を表示されることを確認してみましょう。

今回は、LEGO MINDSTORMS EV3 のセンサー値を確認するまでを紹介しました。

次は、AndroidからLEGO MINDSTORMS EV3 のモーターをコントロールしてみたいと思います。