diff --git a/pom.xml b/pom.xml
index bb93f28..90e46c1 100644
--- a/pom.xml
+++ b/pom.xml
@@ -4,7 +4,7 @@
 	<modelVersion>4.0.0</modelVersion>
 	<groupId>de.srsoftware</groupId>
 	<artifactId>web4rail</artifactId>
-	<version>0.5.6</version>
+	<version>0.6.1</version>
 	<name>Web4Rail</name>
 	<packaging>jar</packaging>
 	<description>Java Model Railway Control</description>
diff --git a/src/main/java/de/srsoftware/web4rail/Application.java b/src/main/java/de/srsoftware/web4rail/Application.java
index 8221df1..cb7df2e 100644
--- a/src/main/java/de/srsoftware/web4rail/Application.java
+++ b/src/main/java/de/srsoftware/web4rail/Application.java
@@ -15,6 +15,7 @@ import java.nio.charset.Charset;
 import java.nio.charset.StandardCharsets;
 import java.nio.file.Files;
 import java.util.HashMap;
+import java.util.concurrent.CompletableFuture;
 
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -73,6 +74,23 @@ public class Application {
 		if (response instanceof Page) {
 			html = ((Page)response).html().toString().getBytes(UTF8);
 			client.getResponseHeaders().add("content-type", "text/html");
+		} else if (response instanceof CompletableFuture) {
+			CompletableFuture<?> promise = (CompletableFuture<?>) response;
+			promise.thenAccept(object -> {
+				try {
+					send(client,object);
+				} catch (IOException e) {
+					LOG.warn("Was not able to send {}!",object);
+				}
+			}).exceptionally(ex -> {
+				try {
+					send(client,ex.getMessage());
+				} catch (IOException e) {
+					LOG.warn("Was not able to send {}!",ex);
+				}
+				throw new RuntimeException(ex);
+			});
+			return;
 		} else {
 			html = (response == null ? "" : response.toString()).getBytes(UTF8);	
 			client.getResponseHeaders().add("content-type", "text/plain");	
diff --git a/src/main/java/de/srsoftware/web4rail/Command.java b/src/main/java/de/srsoftware/web4rail/Command.java
new file mode 100644
index 0000000..9cbc943
--- /dev/null
+++ b/src/main/java/de/srsoftware/web4rail/Command.java
@@ -0,0 +1,24 @@
+package de.srsoftware.web4rail;
+
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.TimeUnit;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class Command extends CompletableFuture<ControlUnit.Reply> {
+
+	private static final Logger LOG = LoggerFactory.getLogger(Command.class);
+	private String command;
+	
+	public Command(String command) {
+		this.command = command;
+		this.orTimeout(500, TimeUnit.MILLISECONDS);
+		LOG.debug("Created new Command({}).",command);
+	}
+
+	@Override
+	public String toString() {
+		return command;
+	}
+}
diff --git a/src/main/java/de/srsoftware/web4rail/ControlUnit.java b/src/main/java/de/srsoftware/web4rail/ControlUnit.java
index be1b787..a67e4d4 100644
--- a/src/main/java/de/srsoftware/web4rail/ControlUnit.java
+++ b/src/main/java/de/srsoftware/web4rail/ControlUnit.java
@@ -33,7 +33,7 @@ public class ControlUnit extends Thread implements Constants{
 	private static final String PORT = "port";
 	private static final String BUS = "bus";
 	
-	private class Reply{
+	public class Reply{
 		private long secs;
 		private int milis;
 		private int code;
@@ -47,11 +47,19 @@ public class ControlUnit extends Thread implements Constants{
 			message = scanner.nextLine().trim();
 			LOG.info("recv {}.{} {} {}.",secs,milis,code,message);
 		}
+		
+		public String message() {
+			return message;
+		}
 
 		@Override
 		public String toString() {
 			return "Reply("+secs+"."+milis+" / "+code+" / "+message+")";
 		}
+
+		public boolean is(int code) {
+			return code == this.code;
+		}
 	}
 	
 	
@@ -60,7 +68,7 @@ public class ControlUnit extends Thread implements Constants{
 	private int port = DEFAULT_PORT;
 	private int bus = 0;
 	private boolean stopped = true;
-	private LinkedList<String> queue = new LinkedList<String>();
+	private LinkedList<Command> queue = new LinkedList<Command>();
 	private Socket socket;
 	private Scanner scanner;
 	private boolean power = false;
@@ -156,8 +164,10 @@ public class ControlUnit extends Thread implements Constants{
 		return win;
 	}
 
-	public void queue(String command) {
-		queue.add(command);
+	public Command queue(String command) {
+		Command promise = new Command(command);
+		queue.add(promise);
+		return promise;
 	}
 	
 	/**
@@ -176,7 +186,10 @@ public class ControlUnit extends Thread implements Constants{
 			try {	
 				if (queue.isEmpty()) {
 					Thread.sleep(10);
-				} else send(queue.poll());
+				} else {
+					Command command = queue.pop();
+					command.complete(send(command));
+				}
 			} catch (InterruptedException | IOException e) {
 				e.printStackTrace();
 			}
@@ -200,9 +213,9 @@ public class ControlUnit extends Thread implements Constants{
 	 * @return 
 	 * @throws IOException 
 	 */
-	private Reply send(String command) throws IOException {
+	private Reply send(Command command) throws IOException {
 		if (command == null) return null;
-		writeln(command);
+		writeln(command.toString());
 		return new Reply(scanner);
 	}
 	
diff --git a/src/main/java/de/srsoftware/web4rail/Plan.java b/src/main/java/de/srsoftware/web4rail/Plan.java
index a1bc0f3..e40e40e 100644
--- a/src/main/java/de/srsoftware/web4rail/Plan.java
+++ b/src/main/java/de/srsoftware/web4rail/Plan.java
@@ -13,6 +13,7 @@ import java.util.Map;
 import java.util.Map.Entry;
 import java.util.Stack;
 import java.util.Vector;
+import java.util.concurrent.CompletableFuture;
 
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -426,8 +427,9 @@ public class Plan implements Constants{
 		return false;
 	}
 	
-	public void place(Tile tile) throws IOException {
+	public Tile place(Tile tile) throws IOException {
 		stream("place "+tile.tag(null));
+		return tile;
 	}
 
 	private Object planAction(HashMap<String, String> params) throws ClassNotFoundException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException, IOException {
@@ -580,7 +582,7 @@ public class Plan implements Constants{
 		stream(t("Warning: {}",t("Ghost train @ {}",contact)));
 	}
 
-	public void queue(String command) {
-		controlUnit.queue(command);		
+	public CompletableFuture<ControlUnit.Reply> queue(String command) {
+		return controlUnit.queue(command);		
 	}
 }
diff --git a/src/main/java/de/srsoftware/web4rail/Route.java b/src/main/java/de/srsoftware/web4rail/Route.java
index b2c2218..80e951e 100644
--- a/src/main/java/de/srsoftware/web4rail/Route.java
+++ b/src/main/java/de/srsoftware/web4rail/Route.java
@@ -12,6 +12,7 @@ import java.util.List;
 import java.util.Map;
 import java.util.Map.Entry;
 import java.util.Vector;
+import java.util.concurrent.CompletableFuture;
 
 import org.json.JSONArray;
 import org.json.JSONException;
@@ -21,6 +22,7 @@ import org.slf4j.LoggerFactory;
 
 import de.keawe.tools.translations.Translation;
 import de.srsoftware.tools.Tag;
+import de.srsoftware.web4rail.ControlUnit.Reply;
 import de.srsoftware.web4rail.Plan.Direction;
 import de.srsoftware.web4rail.actions.Action;
 import de.srsoftware.web4rail.actions.ActivateRoute;
@@ -290,15 +292,35 @@ public class Route implements Constants{
 		file.close();
 	}
 	
-	public Route lock(Train train) throws IOException {
-		this.train = train;
-		for (Entry<Turnout, State> entry : turnouts.entrySet()) {
-			entry.getKey().state(entry.getValue());
+	public CompletableFuture<Reply> lock(Train train) throws IOException {
+		Vector<Tile> locked = new Vector<Tile>();
+		try {
+			for (Tile tile : path) locked.add(tile.lock(this)); // try to lock all tiles along the path
+		} catch (Exception e) { // if something fails: unlock all tiles locked so far
+			for (Tile tile : locked) try {
+				tile.unlock();
+			} catch (IOException ex) {
+				LOG.warn("Problem while unlocking {}",ex);
+			}
+			throw e;
 		}
-		for (Tile tile : path) tile.lock(this);
-		return this;
+		CompletableFuture<Reply> promise = null;
+		for (Entry<Turnout, State> entry : turnouts.entrySet()) {// try to switch all turnouts of this route
+			CompletableFuture<Reply> reply = entry.getKey().state(entry.getValue());  // switching a turnout is an asynchronous process, so it returns a CompletableFuture here
+			promise = promise == null ? reply : promise.thenCombine(reply, (a,b) -> a);				
+		}
+		promise.exceptionally(ex -> {
+				for (Tile tile : locked) try {
+					tile.unlock();
+				} catch (IOException e) {
+					LOG.warn("Problem while unlocking {}",e);
+				}
+				throw new RuntimeException(ex);
+			}).thenRun(() -> this.train = train);
+		
+		return promise;		
 	}
-
+	
 	public List<Route> multiply(int size) {
 		Vector<Route> routes = new Vector<Route>();
 		for (int i=0; i<size; i++) routes.add(i==0 ? this : this.clone());
diff --git a/src/main/java/de/srsoftware/web4rail/moving/Train.java b/src/main/java/de/srsoftware/web4rail/moving/Train.java
index 1f089dc..dbebadc 100644
--- a/src/main/java/de/srsoftware/web4rail/moving/Train.java
+++ b/src/main/java/de/srsoftware/web4rail/moving/Train.java
@@ -12,6 +12,7 @@ import java.util.HashSet;
 import java.util.Map.Entry;
 import java.util.Random;
 import java.util.Vector;
+import java.util.concurrent.CompletableFuture;
 
 import org.json.JSONObject;
 import org.slf4j.Logger;
@@ -331,8 +332,8 @@ public class Train implements Constants {
 		this.speed = v;
 	}
 	
-	public String start() throws IOException {
-		if (block == null) return t("{} not in a block",this); 
+	public CompletableFuture<String> start() throws IOException {
+		if (block == null) return CompletableFuture.failedFuture(new RuntimeException(t("{} not in a block",this)));
 		if (route != null) route.unlock().setSignals(Signal.STOP);
 		HashSet<Route> routes = block.routes();
 		Vector<Route> availableRoutes = new Vector<Route>();
@@ -351,12 +352,18 @@ public class Train implements Constants {
 			availableRoutes.add(rt);
 		}
 		Random rand = new Random();
-		if (availableRoutes.isEmpty()) return t("No free routes from {}",block);
-		int sel = rand.nextInt(availableRoutes.size());
-		route = availableRoutes.get(sel).lock(this).setSignals(null);
-		if (direction != route.startDirection) turn();
-		setSpeed(100);
-		return t("started {}",this); 
+		if (availableRoutes.isEmpty()) return CompletableFuture.failedFuture(new RuntimeException(t("No free routes from {}",block)));
+		route = availableRoutes.get(rand.nextInt(availableRoutes.size()));
+		return route.lock(this).thenApply(reply -> {
+			try {
+				route.setSignals(null);
+				if (direction != route.startDirection) turn();
+				setSpeed(100);
+				return t("started {}",this);
+			} catch (Exception e) {
+				throw new RuntimeException(e);
+			}
+		});
 	}
 	
 	private Object stop() {
@@ -375,7 +382,11 @@ public class Train implements Constants {
 	}
 	
 	private void turn() throws IOException {
-		if (direction != null) direction = direction.inverse();
+		LOG.debug("train.turn()");
+		if (direction != null) {
+			direction = direction.inverse();
+			for (Locomotive loco : locos) loco.turn(); 
+		}
 		if (block != null) block.train(this); 
 	}
 
diff --git a/src/main/java/de/srsoftware/web4rail/tiles/Tile.java b/src/main/java/de/srsoftware/web4rail/tiles/Tile.java
index 81eee5a..28f9a9e 100644
--- a/src/main/java/de/srsoftware/web4rail/tiles/Tile.java
+++ b/src/main/java/de/srsoftware/web4rail/tiles/Tile.java
@@ -155,9 +155,10 @@ public abstract class Tile implements Constants{
 		return this;
 	}
 	
-	public void lock(Route route) throws IOException {
-		this.route = route;
-		plan.place(this);
+	public Tile lock(Route lockingRoute) throws IOException {
+		if (route != null && route != lockingRoute) throw new IllegalStateException(this.toString());
+		route = lockingRoute;
+		return plan.place(this);
 	}
 	
 	public Plan plan() {
diff --git a/src/main/java/de/srsoftware/web4rail/tiles/Turnout.java b/src/main/java/de/srsoftware/web4rail/tiles/Turnout.java
index 72d3f2a..8c47050 100644
--- a/src/main/java/de/srsoftware/web4rail/tiles/Turnout.java
+++ b/src/main/java/de/srsoftware/web4rail/tiles/Turnout.java
@@ -3,10 +3,12 @@ package de.srsoftware.web4rail.tiles;
 import java.io.IOException;
 import java.util.HashMap;
 import java.util.Map;
+import java.util.concurrent.CompletableFuture;
 
 import org.json.JSONObject;
 
 import de.srsoftware.tools.Tag;
+import de.srsoftware.web4rail.ControlUnit.Reply;
 import de.srsoftware.web4rail.Device;
 import de.srsoftware.web4rail.Protocol;
 import de.srsoftware.web4rail.tags.Fieldset;
@@ -35,29 +37,8 @@ public abstract class Turnout extends Tile implements Device{
 	@Override
 	public Object click() throws IOException {
 		LOG.debug("Turnout.click()");
-		Object o = super.click();
-		if (address != 0 && !initialized) {
-			String p = null;
-			switch (protocol) {
-			case DCC14:
-			case DCC27:
-			case DCC28:
-			case DCC128:
-				p = "N";
-				break;
-			case MOTO:
-				p = "M";
-				break;
-			case SELECTRIX:
-				p = "S";
-				break;
-			default:
-				p = "P";
-			}
-			plan.queue("INIT {} GA "+address+" "+p);
-			initialized = true;
-		}
-		return o;
+		init();
+		return super.click();
 	}
 	
 	protected void init() {
@@ -119,7 +100,7 @@ public abstract class Turnout extends Tile implements Device{
 		return state;
 	}
 	
-	public abstract void state(State newState) throws IOException;
+	public abstract CompletableFuture<Reply> state(State newState) throws IOException;
 
 	@Override
 	public Tag tag(Map<String, Object> replacements) throws IOException {
diff --git a/src/main/java/de/srsoftware/web4rail/tiles/Turnout3E.java b/src/main/java/de/srsoftware/web4rail/tiles/Turnout3E.java
index e64971d..e0a02fb 100644
--- a/src/main/java/de/srsoftware/web4rail/tiles/Turnout3E.java
+++ b/src/main/java/de/srsoftware/web4rail/tiles/Turnout3E.java
@@ -3,8 +3,10 @@ package de.srsoftware.web4rail.tiles;
 import java.io.IOException;
 import java.util.HashMap;
 import java.util.Map;
+import java.util.concurrent.CompletableFuture;
 
 import de.srsoftware.web4rail.Connector;
+import de.srsoftware.web4rail.ControlUnit.Reply;
 import de.srsoftware.web4rail.Plan.Direction;
 
 public class Turnout3E extends Turnout{
@@ -29,8 +31,9 @@ public class Turnout3E extends Turnout{
 	}
 
 	@Override
-	public void state(State newState) throws IOException {
+	public CompletableFuture<Reply> state(State newState) throws IOException {
 		// TODO Auto-generated method stub
 		LOG.warn("Turnout3E.state({}) not implemented, yet!",newState);
+		return null;
 	}
 }
diff --git a/src/main/java/de/srsoftware/web4rail/tiles/TurnoutL.java b/src/main/java/de/srsoftware/web4rail/tiles/TurnoutL.java
index c522425..0e207f2 100644
--- a/src/main/java/de/srsoftware/web4rail/tiles/TurnoutL.java
+++ b/src/main/java/de/srsoftware/web4rail/tiles/TurnoutL.java
@@ -2,8 +2,10 @@ package de.srsoftware.web4rail.tiles;
 
 import java.io.IOException;
 import java.util.HashMap;
+import java.util.concurrent.CompletableFuture;
 
 import de.srsoftware.tools.Tag;
+import de.srsoftware.web4rail.ControlUnit.Reply;
 import de.srsoftware.web4rail.tags.Fieldset;
 import de.srsoftware.web4rail.tags.Input;
 import de.srsoftware.web4rail.tags.Label;
@@ -18,7 +20,13 @@ public class TurnoutL extends Turnout {
 		Object o = super.click();
 		if (route != null) {
 			plan.stream(t("{} is locked by {}!",this,route)); 
-		} else state(state == State.STRAIGHT ? State.LEFT : State.STRAIGHT);
+		} else {
+			CompletableFuture<Reply> promise = state(state == State.STRAIGHT ? State.LEFT : State.STRAIGHT);
+			promise.exceptionally(ex -> {
+				LOG.warn("Failed to toggle turnout: ",ex);
+				throw new RuntimeException(ex);
+			}).thenAccept(reply -> LOG.debug("Success: {}",reply));
+		}
 		return o;
 	}
 	
@@ -45,21 +53,25 @@ public class TurnoutL extends Turnout {
 	}
 	
 	@Override
-	public void state(State newState) throws IOException {
+	public CompletableFuture<Reply> state(State newState) throws IOException {
 		init();
-		LOG.debug("Setting {} to {}",this,newState);
-		int p = 0;
+		LOG.debug("Requesting to set {} to {}",this,newState);
+		CompletableFuture<Reply> result;
 		switch (newState) {
 		case LEFT:
-			p = portB;
+			result = plan.queue("SET {} GA "+address+" "+portB+" 1 "+delay);
 			break;
 		case STRAIGHT:
-			p = portA;
+			result = plan.queue("SET {} GA "+address+" "+portA+" 1 "+delay);
 			break;
 		default:
+			throw new IllegalStateException();
 		}
-		if (p != 0) plan.queue("SET {} GA "+address+" "+p+" 1 "+delay);
-		state = newState;
-		plan.stream("place "+tag(null));
+		return result.thenApply(reply -> {
+			LOG.debug("{} received {}",TurnoutL.this,reply);
+			if (!reply.is(200)) throw new RuntimeException(reply.message()); 
+			state = newState;
+			return reply;
+		});
 	}
 }
diff --git a/src/main/java/de/srsoftware/web4rail/tiles/TurnoutR.java b/src/main/java/de/srsoftware/web4rail/tiles/TurnoutR.java
index bd488b3..4b0d76f 100644
--- a/src/main/java/de/srsoftware/web4rail/tiles/TurnoutR.java
+++ b/src/main/java/de/srsoftware/web4rail/tiles/TurnoutR.java
@@ -2,8 +2,10 @@ package de.srsoftware.web4rail.tiles;
 
 import java.io.IOException;
 import java.util.HashMap;
+import java.util.concurrent.CompletableFuture;
 
 import de.srsoftware.tools.Tag;
+import de.srsoftware.web4rail.ControlUnit.Reply;
 import de.srsoftware.web4rail.tags.Fieldset;
 import de.srsoftware.web4rail.tags.Input;
 import de.srsoftware.web4rail.tags.Label;
@@ -45,21 +47,24 @@ public class TurnoutR extends Turnout {
 	}
 	
 	@Override
-	public void state(State newState) throws IOException {
+	public CompletableFuture<Reply> state(State newState) throws IOException {
 		init();
 		LOG.debug("Setting {} to {}",this,newState);
-		int p = 0;
+		CompletableFuture<Reply> result;
 		switch (newState) {
 		case RIGHT:
-			p = portB;
+			result = plan.queue("SET {} GA "+address+" "+portB+" 1 "+delay);
 			break;
 		case STRAIGHT:
-			p = portA;
+			result = plan.queue("SET {} GA "+address+" "+portA+" 1 "+delay);
 			break;
 		default:
+			throw new IllegalStateException();
 		}
-		if (p != 0) plan.queue("SET {} GA "+address+" "+p+" 1 "+delay);
-		state = newState;
-		plan.stream("place "+tag(null));
+		return result.thenApply(reply -> {
+			LOG.debug("{} received {}",reply);
+			if (reply.is(200)) state = newState;
+			return reply;
+		});
 	}
 }