/* * Catroid: An on-device visual programming system for Android devices * Copyright (C) 2010-2016 The Catrobat Team * (<http://developer.catrobat.org/credits>) * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * An additional term exception under section 7 of the GNU Affero * General Public License, version 3, is available at * http://developer.catrobat.org/license_additional_term * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package org.catrobat.catroid.devices.mindstorms.ev3; import android.content.Context; import android.util.Log; import org.catrobat.catroid.bluetooth.base.BluetoothConnection; import org.catrobat.catroid.bluetooth.base.BluetoothDevice; import org.catrobat.catroid.devices.mindstorms.MindstormsConnection; import org.catrobat.catroid.devices.mindstorms.MindstormsConnectionImpl; import org.catrobat.catroid.devices.mindstorms.MindstormsException; import org.catrobat.catroid.devices.mindstorms.MindstormsSensor; import org.catrobat.catroid.devices.mindstorms.ev3.EV3CommandByte.EV3CommandByteCode; import org.catrobat.catroid.devices.mindstorms.ev3.EV3CommandByte.EV3CommandOpCode; import org.catrobat.catroid.devices.mindstorms.ev3.EV3CommandByte.EV3CommandParamFormat; import org.catrobat.catroid.devices.mindstorms.ev3.sensors.EV3Sensor; import org.catrobat.catroid.devices.mindstorms.ev3.sensors.EV3SensorService; import org.catrobat.catroid.formulaeditor.Sensors; import java.util.UUID; public class LegoEV3Impl implements LegoEV3, EV3SensorService.OnSensorChangedListener { private static final UUID LEGO_EV3_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB"); private static final String TAG = LegoEV3Impl.class.getSimpleName(); private static final int KEEP_ALIVE_TIME = 5; private static final int NUMBER_VOLUME_LEVELS = 13; private static final int VOLUME_LEVEL_INCR = 8; private boolean isInitialized = false; protected MindstormsConnection mindstormsConnection; protected Context context; private EV3Motor motorA; private EV3Motor motorB; private EV3Motor motorC; private EV3Motor motorD; private EV3Sensor sensor1; private EV3Sensor sensor2; private EV3Sensor sensor3; private EV3Sensor sensor4; private EV3SensorService sensorService; public LegoEV3Impl(Context applicationContext) { this.context = applicationContext; } @Override public String getName() { return "Lego EV3"; } @Override public Class<? extends BluetoothDevice> getDeviceType() { return BluetoothDevice.LEGO_EV3; } @Override public void playTone(int frequencyInHz, int durationInMs, int volumeInPercent) { if (volumeInPercent > 100) { volumeInPercent = 100; } else if (volumeInPercent < 0) { volumeInPercent = 0; } if (durationInMs <= 0 | volumeInPercent == 0) { return; } //different sources suggest different min./max. values if (frequencyInHz > 10000) { frequencyInHz = 10000; } else if (frequencyInHz < 250) { frequencyInHz = 250; } int volumeLevel = NUMBER_VOLUME_LEVELS; for (int volLevel = 0; volLevel < NUMBER_VOLUME_LEVELS; volLevel++) { if (volumeInPercent > (volLevel * VOLUME_LEVEL_INCR)) { volumeLevel = volLevel + 1; } } EV3Command command = new EV3Command(mindstormsConnection.getCommandCounter(), EV3CommandType.DIRECT_COMMAND_NO_REPLY, 0, 0, EV3CommandOpCode.OP_SOUND); mindstormsConnection.incCommandCounter(); command.append(EV3CommandByteCode.SOUND_PLAY_TONE); command.append(EV3CommandParamFormat.PARAM_FORMAT_SHORT, volumeLevel); command.append(EV3CommandParamFormat.PARAM_FORMAT_LONG, frequencyInHz); command.append(EV3CommandParamFormat.PARAM_FORMAT_LONG, durationInMs); try { mindstormsConnection.send(command); } catch (MindstormsException e) { Log.e(TAG, e.getMessage()); } } @Override public EV3Motor getMotorA() { return motorA; } @Override public EV3Motor getMotorB() { return motorB; } @Override public EV3Motor getMotorC() { return motorC; } @Override public EV3Motor getMotorD() { return motorD; } @Override public void onSensorChanged() { assignSensorsToPorts(); } @Override public void setConnection(BluetoothConnection btConnection) { this.mindstormsConnection = new MindstormsConnectionImpl(btConnection); } @Override public boolean isAlive() { try { sendKeepAlive(); return true; } catch (MindstormsException e) { return false; } } private void sendKeepAlive() throws MindstormsException { EV3Command command = new EV3Command(mindstormsConnection.getCommandCounter(), EV3CommandType.DIRECT_COMMAND_NO_REPLY, 0, 0, EV3CommandOpCode.OP_KEEP_ALIVE); mindstormsConnection.incCommandCounter(); command.append(EV3CommandParamFormat.PARAM_FORMAT_SHORT, KEEP_ALIVE_TIME); try { mindstormsConnection.send(command); } catch (MindstormsException e) { Log.e(TAG, e.getMessage()); } } public void moveMotorStepsSpeed(byte outputField, int chainLayer, int speed, int step1Tacho, int step2Tacho, int step3Tacho, boolean brake) { EV3Command command = new EV3Command(mindstormsConnection.getCommandCounter(), EV3CommandType.DIRECT_COMMAND_NO_REPLY, 0, 0, EV3CommandOpCode.OP_OUTPUT_STEP_SPEED); mindstormsConnection.incCommandCounter(); command.append(EV3CommandParamFormat.PARAM_FORMAT_SHORT, chainLayer); command.append(EV3CommandParamFormat.PARAM_FORMAT_SHORT, outputField); command.append(EV3CommandParamFormat.PARAM_FORMAT_LONG, speed); command.append(EV3CommandParamFormat.PARAM_FORMAT_LONG, step1Tacho); command.append(EV3CommandParamFormat.PARAM_FORMAT_LONG, step2Tacho); command.append(EV3CommandParamFormat.PARAM_FORMAT_LONG, step3Tacho); command.append(EV3CommandParamFormat.PARAM_FORMAT_SHORT, (brake ? 0x01 : 0x00)); try { mindstormsConnection.send(command); } catch (MindstormsException e) { Log.e(TAG, e.getMessage()); } } public void moveMotorSpeed(byte outputField, int chainLayer, int speed) { EV3Command setSpeedCommand = new EV3Command(mindstormsConnection.getCommandCounter(), EV3CommandType.DIRECT_COMMAND_NO_REPLY, 0, 0, EV3CommandOpCode.OP_OUTPUT_SPEED); mindstormsConnection.incCommandCounter(); setSpeedCommand.append(EV3CommandParamFormat.PARAM_FORMAT_SHORT, chainLayer); setSpeedCommand.append(EV3CommandParamFormat.PARAM_FORMAT_SHORT, outputField); setSpeedCommand.append(EV3CommandParamFormat.PARAM_FORMAT_SHORT, speed); EV3Command startMotorCommand = new EV3Command(mindstormsConnection.getCommandCounter(), EV3CommandType .DIRECT_COMMAND_NO_REPLY, 0, 0, EV3CommandOpCode.OP_OUTPUT_START); mindstormsConnection.incCommandCounter(); startMotorCommand.append(EV3CommandParamFormat.PARAM_FORMAT_SHORT, chainLayer); startMotorCommand.append(EV3CommandParamFormat.PARAM_FORMAT_SHORT, outputField); try { mindstormsConnection.send(setSpeedCommand); mindstormsConnection.send(startMotorCommand); } catch (MindstormsException e) { Log.e(TAG, e.getMessage()); } } public void stopMotor(byte outputField, int chainLayer, boolean brake) { EV3Command command = new EV3Command(mindstormsConnection.getCommandCounter(), EV3CommandType.DIRECT_COMMAND_NO_REPLY, 0, 0, EV3CommandOpCode.OP_OUTPUT_STOP); mindstormsConnection.incCommandCounter(); command.append((byte) chainLayer); command.append(outputField); command.append((byte) (brake ? 0x01 : 0x00)); try { mindstormsConnection.send(command); } catch (MindstormsException e) { Log.e(TAG, e.getMessage()); } } public void setLed(int ledStatus) { EV3Command command = new EV3Command(mindstormsConnection.getCommandCounter(), EV3CommandType.DIRECT_COMMAND_NO_REPLY, 0, 0, EV3CommandOpCode.OP_UI_WRITE); mindstormsConnection.incCommandCounter(); command.append(EV3CommandByteCode.UI_WRITE_LED); command.append(EV3CommandParamFormat.PARAM_FORMAT_LONG, ledStatus); try { mindstormsConnection.send(command); } catch (MindstormsException e) { Log.e(TAG, e.getMessage()); } } @Override public int getSensorValue(Sensors sensor) { switch (sensor) { case EV3_SENSOR_1: if (getSensor1() == null) { return 0; } return getSensor1().getLastSensorValue(); case EV3_SENSOR_2: if (getSensor2() == null) { return 0; } return getSensor2().getLastSensorValue(); case EV3_SENSOR_3: if (getSensor3() == null) { return 0; } return getSensor3().getLastSensorValue(); case EV3_SENSOR_4: if (getSensor4() == null) { return 0; } return getSensor4().getLastSensorValue(); } return -1; } @Override public MindstormsSensor getSensor1() { return sensor1; } @Override public MindstormsSensor getSensor2() { return sensor2; } @Override public MindstormsSensor getSensor3() { return sensor3; } @Override public MindstormsSensor getSensor4() { return sensor4; } private EV3SensorService getSensorService() { if (sensorService == null) { sensorService = new EV3SensorService(context, mindstormsConnection); sensorService.registerOnSensorChangedListener(this); } return sensorService; } @Override public synchronized void initialise() { if (isInitialized) { return; } mindstormsConnection.init(); motorA = new EV3Motor(0); motorB = new EV3Motor(1); motorC = new EV3Motor(2); motorD = new EV3Motor(3); assignSensorsToPorts(); isInitialized = true; } private synchronized void assignSensorsToPorts() { EV3SensorService sensorService = getSensorService(); sensor1 = sensorService.createSensor1(); sensor2 = sensorService.createSensor2(); sensor3 = sensorService.createSensor3(); sensor4 = sensorService.createSensor4(); } @Override public void start() { initialise(); assignSensorsToPorts(); sensorService.resumeSensorUpdate(); } @Override public void pause() { stopAllMovements(); sensorService.pauseSensorUpdate(); } @Override public void destroy() { sensorService.deactivateAllSensors(mindstormsConnection); } @Override public void stopAllMovements() { stopMotor((byte) 0x0F, 0, true); } @Override public void disconnect() { if (mindstormsConnection.isConnected()) { this.stopAllMovements(); //sensorService.destroy(); mindstormsConnection.disconnect(); } } @Override public UUID getBluetoothDeviceUUID() { return LEGO_EV3_UUID; } }