/*
* 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.uitest.devices.phiro;
import android.widget.ListView;
import org.catrobat.catroid.R;
import org.catrobat.catroid.bluetooth.ConnectBluetoothDeviceActivity;
import org.catrobat.catroid.common.LookData;
import org.catrobat.catroid.common.ScreenValues;
import org.catrobat.catroid.common.bluetooth.BluetoothTestUtils;
import org.catrobat.catroid.common.bluetooth.ConnectionDataLogger;
import org.catrobat.catroid.common.firmata.FirmataMessage;
import org.catrobat.catroid.common.firmata.FirmataUtils;
import org.catrobat.catroid.content.Project;
import org.catrobat.catroid.content.Script;
import org.catrobat.catroid.content.SingleSprite;
import org.catrobat.catroid.content.Sprite;
import org.catrobat.catroid.content.StartScript;
import org.catrobat.catroid.content.WhenScript;
import org.catrobat.catroid.content.bricks.PhiroMotorMoveForwardBrick;
import org.catrobat.catroid.content.bricks.PhiroMotorStopBrick;
import org.catrobat.catroid.content.bricks.SetLookBrick;
import org.catrobat.catroid.content.bricks.WaitBrick;
import org.catrobat.catroid.io.StorageHandler;
import org.catrobat.catroid.stage.StageActivity;
import org.catrobat.catroid.ui.MainMenuActivity;
import org.catrobat.catroid.ui.ProjectActivity;
import org.catrobat.catroid.uitest.annotation.Device;
import org.catrobat.catroid.uitest.util.BaseActivityInstrumentationTestCase;
import org.catrobat.catroid.uitest.util.UiTestUtils;
import java.io.File;
import java.util.ArrayList;
public class PhiroTest extends BaseActivityInstrumentationTestCase<MainMenuActivity> {
public PhiroTest() {
super(MainMenuActivity.class);
}
private static final int PIN_LEFT_MOTOR_BACKWARD = 10;
private static final int PIN_LEFT_MOTOR_FORWARD = 11;
private static final int MIN_PWM_PIN = 3;
private static final int MAX_PWM_PIN = 13;
private static final int MIN_SENSOR_PIN = 0;
private static final int MAX_SENSOR_PIN = 5;
private static final int PWM_MODE = 3;
private static final int SET_PIN_MODE_COMMAND = 0xF4;
private static final int REPORT_ANALOG_PIN_COMMAND = 0xC0;
private static final int IMAGE_FILE_ID = org.catrobat.catroid.test.R.raw.icon;
private final String projectName = UiTestUtils.PROJECTNAME1;
private static final String LOCAL_BLUETOOTH_TEST_DUMMY_DEVICE_NAME = "dummy_device";
private final String spriteName = "testSprite";
private static final int MOTOR_MOVE = 0;
private static final int MOTOR_STOP = 1;
private ConnectionDataLogger logger;
private FirmataUtils firmataUtils;
@Override
public void setUp() throws Exception {
super.setUp();
UiTestUtils.prepareStageForTest();
logger = ConnectionDataLogger.createLocalConnectionLogger();
firmataUtils = new FirmataUtils(logger);
}
@Override
protected void tearDown() throws Exception {
logger.disconnectAndDestroy();
super.tearDown();
}
@Device
public void testPhiroFunctionality() {
ArrayList<int[]> commands = createTestproject(projectName);
BluetoothTestUtils.enableBluetooth();
solo.clickOnText(solo.getString(R.string.main_menu_continue));
solo.waitForActivity(ProjectActivity.class.getSimpleName());
UiTestUtils.clickOnBottomBar(solo, R.id.button_play);
solo.sleep(1000);
solo.assertCurrentActivity("Not in BTConnectDeviceActivity", ConnectBluetoothDeviceActivity.class);
// use this only, if ConnectionDataLogger is in local mode (localProxy)
BluetoothTestUtils.addPairedDevice(LOCAL_BLUETOOTH_TEST_DUMMY_DEVICE_NAME,
(ConnectBluetoothDeviceActivity) solo.getCurrentActivity(), getInstrumentation());
ListView deviceList = solo.getCurrentViews(ListView.class).get(0);
String connectedDeviceName = null;
for (int i = 0; i < deviceList.getCount(); i++) {
String deviceName = (String) deviceList.getItemAtPosition(i);
if (deviceName.startsWith(LOCAL_BLUETOOTH_TEST_DUMMY_DEVICE_NAME)) {
connectedDeviceName = deviceName;
break;
}
}
solo.clickOnText(connectedDeviceName);
solo.sleep(2000);
solo.assertCurrentActivity("Not in stage - connection to bluetooth-device failed", StageActivity.class);
doTestFirmataInitialization();
solo.clickOnScreen(ScreenValues.SCREEN_WIDTH / 2, ScreenValues.SCREEN_HEIGHT / 2);
FirmataMessage m;
for (int[] item : commands) {
switch (item[0]) {
case MOTOR_MOVE:
m = firmataUtils.getAnalogMesageData();
assertEquals("Wrong pin", item[1], m.getPin());
assertEquals("Wrong speed", percentToSpeed(item[2]), m.getData());
break;
case MOTOR_STOP:
m = firmataUtils.getAnalogMesageData();
assertEquals("Wrong pin", item[1], m.getPin());
assertEquals("Wrong speed", 0, m.getData());
m = firmataUtils.getAnalogMesageData();
assertEquals("Wrong pin", item[2], m.getPin());
assertEquals("Wrong speed", 0, m.getData());
break;
}
}
solo.goBack();
solo.goBack();
}
private ArrayList<int[]> createTestproject(String projectName) {
ArrayList<int[]> commands = new ArrayList<int[]>();
Sprite firstSprite = new SingleSprite(spriteName);
Script startScript = new StartScript();
Script whenScript = new WhenScript();
SetLookBrick setLookBrick = new SetLookBrick();
PhiroMotorMoveForwardBrick phiro = new PhiroMotorMoveForwardBrick(
PhiroMotorMoveForwardBrick.Motor.MOTOR_LEFT, 100);
commands.add(new int[] { MOTOR_MOVE, PIN_LEFT_MOTOR_FORWARD, 100 });
WaitBrick firstWaitBrick = new WaitBrick(100);
PhiroMotorStopBrick phiroMotorStopBrick = new PhiroMotorStopBrick(
PhiroMotorStopBrick.Motor.MOTOR_LEFT);
commands.add(new int[] { MOTOR_STOP, PIN_LEFT_MOTOR_FORWARD, PIN_LEFT_MOTOR_BACKWARD });
whenScript.addBrick(phiro);
whenScript.addBrick(firstWaitBrick);
whenScript.addBrick(phiroMotorStopBrick);
startScript.addBrick(setLookBrick);
firstSprite.addScript(startScript);
firstSprite.addScript(whenScript);
ArrayList<Sprite> spriteList = new ArrayList<Sprite>();
spriteList.add(firstSprite);
Project project = UiTestUtils.createProject(projectName, spriteList, getActivity());
String imageName = "image";
File image = UiTestUtils.saveFileToProject(projectName, project.getDefaultScene().getName(), imageName, IMAGE_FILE_ID, getInstrumentation()
.getContext(), UiTestUtils.FileTypes.IMAGE);
LookData lookData = new LookData();
lookData.setLookFilename(image.getName());
lookData.setLookName(imageName);
setLookBrick.setLook(lookData);
firstSprite.getLookDataList().add(lookData);
StorageHandler.getInstance().saveProject(project);
return commands;
}
private void doTestFirmataInitialization() {
for (int i = MIN_PWM_PIN; i <= MAX_PWM_PIN; ++i) {
FirmataMessage m = firmataUtils.getSetPinModeMessage();
assertEquals("Wrong Command, SET_PIN_MODE command expected", SET_PIN_MODE_COMMAND, m.getCommand());
assertEquals("Wrong pin used to set pin mode", i, m.getPin());
assertEquals("Wrong pin mode is used", PWM_MODE, m.getData());
}
testReportAnalogPin(true);
}
private void testReportAnalogPin(boolean enable) {
for (int i = MIN_SENSOR_PIN; i <= MAX_SENSOR_PIN; ++i) {
FirmataMessage m = firmataUtils.getReportAnalogPinMessage();
assertEquals("Wrong Command, REPORT_ANALOG_PIN command expected", REPORT_ANALOG_PIN_COMMAND, m.getCommand());
assertEquals("Wrong pin used to set pin mode", i, m.getPin());
assertEquals("Wrong pin mode is used", enable ? 1 : 0, m.getData());
}
}
private int percentToSpeed(int percent) {
if (percent <= 0) {
return 0;
}
if (percent >= 100) {
return 255;
}
return (int) (percent * 2.55);
}
}