/*
* 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.sensors;
import android.util.Log;
import org.catrobat.catroid.devices.mindstorms.MindstormsConnection;
import org.catrobat.catroid.devices.mindstorms.MindstormsException;
import org.catrobat.catroid.devices.mindstorms.MindstormsSensor;
import org.catrobat.catroid.devices.mindstorms.ev3.EV3Command;
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.EV3CommandByte.EV3CommandVariableScope;
import org.catrobat.catroid.devices.mindstorms.ev3.EV3CommandType;
import org.catrobat.catroid.devices.mindstorms.ev3.EV3Reply;
import java.math.BigInteger;
import java.util.Locale;
public abstract class EV3Sensor implements MindstormsSensor {
public enum Sensor {
NO_SENSOR,
TOUCH,
COLOR,
COLOR_AMBIENT,
COLOR_REFLECT,
INFRARED;
public static String[] getSensorCodes() {
String[] valueStrings = new String[values().length];
for (int i = 0; i < values().length; i++) {
valueStrings[i] = values()[i].name();
}
return valueStrings;
}
public String getSensorCode() {
return getSensorCode(this);
}
public static String getSensorCode(EV3Sensor.Sensor sensor) {
return sensor.name();
}
public static EV3Sensor.Sensor getSensorFromSensorCode(String sensorCode) {
if (sensorCode == null) {
return Sensor.NO_SENSOR;
}
try {
return valueOf(sensorCode);
} catch (IllegalArgumentException e) {
return Sensor.NO_SENSOR;
}
}
}
protected final int port;
protected final EV3SensorType sensorType;
protected final EV3SensorMode sensorMode;
protected final int updateInterval = 250;
protected final MindstormsConnection connection;
protected boolean hasInit;
protected int lastValidValue = 0;
public static final String TAG = EV3Sensor.class.getSimpleName();
public EV3Sensor(int port, EV3SensorType sensorType, EV3SensorMode sensorMode, MindstormsConnection connection) {
this.port = port;
this.sensorType = sensorType;
this.sensorMode = sensorMode;
this.connection = connection;
}
protected void setMode(EV3SensorMode mode) {
int commandCount = connection.getCommandCounter();
EV3Command command = new EV3Command(connection.getCommandCounter(), EV3CommandType.DIRECT_COMMAND_REPLY,
1, 0, EV3CommandOpCode.OP_INPUT_READ_SI);
connection.incCommandCounter();
int chainLayer = 0;
int type = 0; // don't change type
int samples = 0; // request 0 samples
command.append(EV3CommandParamFormat.PARAM_FORMAT_SHORT, chainLayer);
command.append(EV3CommandParamFormat.PARAM_FORMAT_SHORT, this.port);
command.append(EV3CommandParamFormat.PARAM_FORMAT_SHORT, type);
command.append(EV3CommandParamFormat.PARAM_FORMAT_SHORT, mode.getByte());
command.append(EV3CommandVariableScope.PARAM_VARIABLE_SCOPE_GLOBAL, samples);
try {
EV3Reply reply = new EV3Reply(connection.sendAndReceive(command));
if (!reply.isValid(commandCount)) {
throw new MindstormsException("Reply not valid!");
}
} catch (MindstormsException e) {
Log.e(TAG, e.getMessage());
}
}
protected void initialize() {
if (connection != null && connection.isConnected()) {
setMode(sensorMode);
int commandCount = connection.getCommandCounter();
EV3Command command = new EV3Command(connection.getCommandCounter(), EV3CommandType.DIRECT_COMMAND_REPLY,
1, 0, EV3CommandOpCode.OP_INPUT_DEVICE);
connection.incCommandCounter();
command.append(EV3CommandByteCode.INPUT_DEVICE_READY_RAW.getByte());
int chainLayer = 0;
int type = 0; // don't change type
int mode = -1; // don't change mode
int returnValue = 1; // request 1 return value
int returnValueIndex = 0;
command.append(EV3CommandParamFormat.PARAM_FORMAT_SHORT, chainLayer);
command.append(EV3CommandParamFormat.PARAM_FORMAT_SHORT, this.port);
command.append(EV3CommandParamFormat.PARAM_FORMAT_SHORT, type);
command.append(EV3CommandParamFormat.PARAM_FORMAT_SHORT, mode);
command.append(EV3CommandParamFormat.PARAM_FORMAT_SHORT, returnValue);
command.append(EV3CommandVariableScope.PARAM_VARIABLE_SCOPE_GLOBAL, returnValueIndex);
try {
EV3Reply reply = new EV3Reply(connection.sendAndReceive(command));
if (!reply.isValid(commandCount)) {
throw new MindstormsException("Reply not valid!");
} else {
hasInit = true;
}
} catch (MindstormsException e) {
hasInit = false;
Log.e(TAG, e.getMessage());
}
} else {
hasInit = false;
}
}
public int getPercentValue() {
int percentValue = 0;
if (!hasInit) {
initialize();
} else {
int commandCount = connection.getCommandCounter();
EV3Command command = new EV3Command(connection.getCommandCounter(), EV3CommandType.DIRECT_COMMAND_REPLY,
1, 0, EV3CommandOpCode.OP_INPUT_READ);
connection.incCommandCounter();
int chainLayer = 0;
int type = 0; // don't change type
int mode = -1; // don't change mode
int returnValueIndex = 0;
command.append(EV3CommandParamFormat.PARAM_FORMAT_SHORT, chainLayer);
command.append(EV3CommandParamFormat.PARAM_FORMAT_SHORT, this.port);
command.append(EV3CommandParamFormat.PARAM_FORMAT_SHORT, type);
command.append(EV3CommandParamFormat.PARAM_FORMAT_SHORT, mode);
command.append(EV3CommandVariableScope.PARAM_VARIABLE_SCOPE_GLOBAL, returnValueIndex);
try {
EV3Reply reply = new EV3Reply(connection.sendAndReceive(command));
if (!reply.isValid(commandCount)) {
throw new MindstormsException("Reply not valid!");
}
percentValue = reply.getByte(3); // first 2 bytes(reply length) not saved
} catch (MindstormsException e) {
Log.e(TAG, e.getMessage());
}
}
return percentValue;
}
public int getRawValue() {
int rawValue = 0;
if (!hasInit) {
initialize();
} else {
int commandCount = connection.getCommandCounter();
EV3Command command = new EV3Command(connection.getCommandCounter(), EV3CommandType.DIRECT_COMMAND_REPLY,
1, 0, EV3CommandOpCode.OP_INPUT_DEVICE);
connection.incCommandCounter();
int chainLayer = 0;
int returnValueIndex = 0;
command.append(EV3CommandByteCode.INPUT_DEVICE_GET_RAW);
command.append(EV3CommandParamFormat.PARAM_FORMAT_SHORT, chainLayer);
command.append(EV3CommandParamFormat.PARAM_FORMAT_SHORT, this.port);
command.append(EV3CommandVariableScope.PARAM_VARIABLE_SCOPE_GLOBAL, returnValueIndex);
try {
EV3Reply reply = new EV3Reply(connection.sendAndReceive(command));
if (!reply.isValid(commandCount)) {
throw new MindstormsException("Reply not valid!");
}
int offset = 3;
int replyLength = reply.getLength();
byte[] valueBytes = reply.getData(offset, replyLength - offset);
BigInteger intValue = new BigInteger(valueBytes);
rawValue = intValue.intValue();
} catch (MindstormsException e) {
Log.e(TAG, e.getMessage());
}
}
return rawValue;
}
@Override
public int getUpdateInterval() {
return updateInterval;
}
@Override
public void updateLastSensorValue() {
try {
lastValidValue = getValue();
} catch (MindstormsException e) {
Log.e(TAG, e.getMessage());
}
}
@Override
public int getLastSensorValue() {
return lastValidValue;
}
@Override
public String getName() {
return String.format(Locale.getDefault(), "%s_%s_%d", TAG, sensorType.name(), port);
}
@Override
public int getConnectedPort() {
return port;
}
}