/*
* 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.nxt;
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.nxt.sensors.NXTSensor;
import org.catrobat.catroid.devices.mindstorms.nxt.sensors.NXTSensorService;
import org.catrobat.catroid.formulaeditor.Sensors;
import java.util.UUID;
public class LegoNXTImpl implements LegoNXT, NXTSensorService.OnSensorChangedListener {
private static final UUID LEGO_NXT_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
private static final String TAG = LegoNXTImpl.class.getSimpleName();
protected MindstormsConnection mindstormsConnection;
protected Context context;
private boolean isInitialized = false;
private NXTMotor motorA;
private NXTMotor motorB;
private NXTMotor motorC;
private NXTSensor sensor1;
private NXTSensor sensor2;
private NXTSensor sensor3;
private NXTSensor sensor4;
private NXTSensorService sensorService;
public LegoNXTImpl(Context applicationContext) {
this.context = applicationContext;
}
@Override
public String getName() {
return "Lego NXT";
}
@Override
public Class<? extends BluetoothDevice> getDeviceType() {
return BluetoothDevice.LEGO_NXT;
}
@Override
public void setConnection(BluetoothConnection btConnection) {
this.mindstormsConnection = new MindstormsConnectionImpl(btConnection);
}
@Override
public UUID getBluetoothDeviceUUID() {
return LEGO_NXT_UUID;
}
@Override
public void disconnect() {
if (mindstormsConnection.isConnected()) {
this.stopAllMovements();
if (sensorService != null) {
sensorService.deactivateAllSensors(mindstormsConnection);
sensorService.destroy();
}
mindstormsConnection.disconnect();
}
}
@Override
public boolean isAlive() {
try {
tryGetKeepAliveTime();
return true;
} catch (MindstormsException e) {
return false;
}
}
@Override
public void playTone(int frequencyInHz, int durationInMs) {
if (durationInMs <= 0) {
return;
}
if (frequencyInHz > 14000) {
frequencyInHz = 14000;
} else if (frequencyInHz < 200) {
frequencyInHz = 200;
}
Command command = new Command(CommandType.DIRECT_COMMAND, CommandByte.PLAY_TONE, false);
command.append((byte) (frequencyInHz & 0x00FF));
command.append((byte) ((frequencyInHz & 0xFF00) >> 8));
command.append((byte) (durationInMs & 0x00FF));
command.append((byte) ((durationInMs & 0xFF00) >> 8));
try {
mindstormsConnection.send(command);
} catch (MindstormsException e) {
Log.e(TAG, e.getMessage());
}
}
@Override
public int getKeepAliveTime() {
try {
return tryGetKeepAliveTime();
} catch (NXTException e) {
return -1;
} catch (MindstormsException e) {
return -1;
}
}
private int tryGetKeepAliveTime() {
Command command = new Command(CommandType.DIRECT_COMMAND, CommandByte.KEEP_ALIVE, true);
byte[] alive = mindstormsConnection.sendAndReceive(command);
NXTReply reply = new NXTReply(mindstormsConnection.sendAndReceive(command));
NXTError.checkForError(reply, 7);
byte[] aliveTimeToInt = new byte[4];
aliveTimeToInt[0] = alive[3];
aliveTimeToInt[1] = alive[4];
aliveTimeToInt[2] = alive[5];
aliveTimeToInt[3] = alive[6];
int aliveTime = java.nio.ByteBuffer.wrap(aliveTimeToInt).order(java.nio.ByteOrder.LITTLE_ENDIAN).getInt();
return aliveTime;
}
@Override
public int getBatteryLevel() {
try {
return tryGetBatteryLevel();
} catch (NXTException e) {
return -1;
} catch (MindstormsException e) {
return -1;
}
}
private int tryGetBatteryLevel() {
Command command = new Command(CommandType.DIRECT_COMMAND, CommandByte.GET_BATTERY_LEVEL, true);
NXTReply reply = new NXTReply(mindstormsConnection.sendAndReceive(command));
NXTError.checkForError(reply, 5);
byte[] batByte = mindstormsConnection.sendAndReceive(command);
byte[] batValues = new byte[2];
batValues[0] = batByte[3];
batValues[1] = batByte[4];
int millivolt = java.nio.ByteBuffer.wrap(batValues).order(java.nio.ByteOrder.LITTLE_ENDIAN).getShort();
return millivolt;
}
@Override
public NXTMotor getMotorA() {
return motorA;
}
@Override
public NXTMotor getMotorB() {
return motorB;
}
@Override
public NXTMotor getMotorC() {
return motorC;
}
@Override
public void stopAllMovements() {
motorA.stop();
motorB.stop();
motorC.stop();
}
@Override
public synchronized int getSensorValue(Sensors sensor) {
switch (sensor) {
case NXT_SENSOR_1:
if (getSensor1() == null) {
return 0;
}
return getSensor1().getLastSensorValue();
case NXT_SENSOR_2:
if (getSensor2() == null) {
return 0;
}
return getSensor2().getLastSensorValue();
case NXT_SENSOR_3:
if (getSensor3() == null) {
return 0;
}
return getSensor3().getLastSensorValue();
case NXT_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;
}
@Override
public void onSensorChanged() {
assignSensorsToPorts();
}
private NXTSensorService getSensorService() {
if (sensorService == null) {
sensorService = new NXTSensorService(context, mindstormsConnection);
sensorService.registerOnSensorChangedListener(this);
}
return sensorService;
}
@Override
public synchronized void initialise() {
if (isInitialized) {
return;
}
mindstormsConnection.init();
motorA = new NXTMotor(0, mindstormsConnection);
motorB = new NXTMotor(1, mindstormsConnection);
motorC = new NXTMotor(2, mindstormsConnection);
assignSensorsToPorts();
isInitialized = true;
}
private synchronized void assignSensorsToPorts() {
NXTSensorService 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);
}
}