package org.lejos.ev3.statetwister;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Timer;
import java.util.TimerTask;
import lejos.hardware.Brick;
import lejos.hardware.BrickFinder;
import lejos.hardware.Button;
import lejos.hardware.device.DeviceIdentifier;
import lejos.hardware.lcd.TextLCD;
import lejos.hardware.motor.NXTRegulatedMotor;
/**
* @author Jarema Czajkowski
* @created 28-03-2018
* @license GNU General Public License
*
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*
*
* Buttons:
* ESC Exit from tool on nearest interval
* ENTER Exit from tool immediately
*
*/
class KeyListenerThread extends Thread {
private boolean canceled;
private static final KeyListenerThread _localStorage = new KeyListenerThread();
private KeyListenerThread() {
setCanceled(false);
}
public boolean isCanceled() {
return canceled;
}
public void setCanceled(boolean canceled) {
this.canceled = canceled;
}
public void run() {
for(;;) {
switch(Button.readButtons()) {
case Button.ID_ESCAPE:
setCanceled(true);
return;
case Button.ID_ENTER:
System.exit(0);
return;
}
}
}
public static KeyListenerThread getInstance(){
return _localStorage;
}
}
class StateTwisterTask extends TimerTask {
private final Entry paramEntry;
private int stackIndex;
private int stackMax;
private int motorState;
private String motorLetter;
private NXTRegulatedMotor motor;
public StateTwisterTask(Entry objEntry) {
this.paramEntry = objEntry;
this.stackIndex = 1;
this.stackMax = paramEntry.getValue().length -1;
this.motorState = 0;
this.motorLetter = String.valueOf(paramEntry.getKey());
this.motor = new NXTRegulatedMotor(StateTwisterClient.EV3Brick.getPort(this.motorLetter));
}
@Override
public void run() {
//Called at every interval...
if (KeyListenerThread.getInstance().isCanceled()) { this.cancel(); System.exit(0); }
// ...you can do anything you want with paramEntry
stackIndex = stackIndex < stackMax ? stackIndex+1 : 1;
int state = Integer.valueOf(paramEntry.getValue()[stackIndex]);
if (state != motorState) {
motor.rotate(180);
motorState = state;
}
}
}
public class StateTwisterClient {
//Place where user must put definition files
protected static final String PROGRAMS_DIR = "/home/lejos/programs/";
//What files should be considered for existence ?
protected static final String FILENAME_PREFIX = "statetwister_motor_";
//Motor's synonym
protected static final char[] MOTOR_LETTERS = {'A' ,'B' ,'C' ,'D'};
//Position on Y axis to draw text
private static int messageY = 0;
//Get access to EV3 brick
static final Brick EV3Brick = BrickFinder.getDefault();
static final TextLCD EV3LCD = EV3Brick.getTextLCD();
//Holding necessary data
protected static final Map existedConnections = new HashMap();
public static void main(String[] args) {
boolean ifAny = false;
drawMessage("Working...");
for (char letter : MOTOR_LETTERS) {
String label = String.valueOf(letter);
final DeviceIdentifier motor = new DeviceIdentifier(EV3Brick.getPort(label));
//If device is exist and ready to work
if (motor.getPortType() != 126) {
final File fileObj = new File(PROGRAMS_DIR +FILENAME_PREFIX +label.toLowerCase() +".txt");
//If corresponded file exist
if (fileObj.exists()) {
drawMessage(String.format("Get data - port %s ...", letter) );
String[] response = new String[0];
try {
response = NIOFileRead(fileObj);
} catch (IOException ex) {
drawMessage(ex.getLocalizedMessage());
response = new String[0];
} finally {
if (response.length > 0) { existedConnections.put(letter, response); ifAny = true; }
}
}
}
motor.close();
}
if (ifAny) {
//Start separate thread to manage actions assigned to physical buttons
drawMessage("Start listener...");
KeyListenerThread.getInstance().start();
//Processing
drawMessage("Processing...");
for (final Entry objEntry: existedConnections.entrySet()) {
//Declare the timer
final Timer myTimer = new Timer();
int timerInterval = Integer.valueOf(objEntry.getValue()[0]);
//Set the schedule function and rate
myTimer.scheduleAtFixedRate(new StateTwisterTask(objEntry),
//Set the amount of time before first execution (in milliseconds)
timerInterval *1000,
//Set the amount of time between each execution (in milliseconds)
timerInterval *1000);
}
}
}
private static void drawMessage(String text) {
EV3LCD.drawString(text, 1, messageY);
messageY = messageY + 1;
}
private static String[] NIOFileRead(File fileObj) throws IOException {
BufferedReader b = new BufferedReader(new FileReader(fileObj));
String readLine = "";
List temps = new ArrayList();
while ((readLine = b.readLine()) != null) {
temps.add(readLine);
}
b.close();
return temps.toArray(new String[0]);
}
}