// Path: osgi.enroute.trains.api/src/osgi/enroute/trains/cloud/api/Segment.java
// public class Segment extends DTO {
// 
// 	public enum Type {
// 		STRAIGHT, CURVED, SWITCH, SIGNAL, LOCATOR, BLOCK;
// 	}
// 	
// 
// 	/**
// 	 * Our Identity
// 	 */
// 	public String id;
// 	
// 	/**
// 	 * Type of the segment
// 	 */
//  	public Type type;
// 
// 	/**
//  	* Name of the track.This is the name required to get permission 
//  	* from the Track Manager. If this name starts with X then no admission is required. This 
//  	* is generally for switches.
//  	*/
//  	public String track;
//  	
// 	/**
// 	 * Sequence of the segment in the track
// 	 */
// 	public int sequence;
// 
// 	/**
// 	 * Length of the segment in millimeters, can be zero. It an be zero because
// 	 * the relation between the controllers and the switches and the signals is
// 	 * not always 1:1 mappable to controllers. Therefore zero sized segments can
// 	 * be used to map correctly.
// 	 */
// 	public int length;
// 
// 	/**
// 	 * Short code for RFID tag attached to this segment, or 0 for none.
// 	 */
// 	public int tagCode;
// 
// 	/**
// 	 * The associated controller
// 	 */
// 	public int controller = -1;
// 
// 	/**
// 	 * The next segment. Only a switch can have an additional to. The second to
// 	 * is the one selected if the switch is set to its alternative.
// 	 */
// 	public String to[];
// 	
// 	/**
// 	 * The previous segment. Only a switch can have an additional from. The second from
// 	 * is the one selected if the switch is set to its alternative.
// 	 */
// 	public String from[];
// 
// }
// 
// Path: osgi.enroute.trains.api/src/osgi/enroute/trains/cloud/api/TrackForSegment.java
// public interface TrackForSegment extends TrackInfo {
// 
// 	/**
// 	 * Send when a train has been identified at a locator segment
// 	 * 
// 	 * @param rfid
// 	 *            The RFID for the train
// 	 * @param segment
// 	 *            The name of the segment
// 	 */
// 	void locatedTrainAt(String rfid, String segment);
// 
// 	/**
// 	 * Indicate that a switch has been set
// 	 * 
// 	 * @param segment
// 	 *            the name of the switch segment
// 	 * @param alternative
// 	 *            defines the normal or alternative track
// 	 */
// 	void switched(String segment, boolean alternative);
// 	
// 	/**
// 	 * Indicate that a signal changed color
// 	 * 
// 	 * @param segment
// 	 *            the name of the signal segment
// 	 * @param color
// 	 *            the new signal color
// 	 */
// 	void signal(String segment, Color color);
// 	
// 	/**
// 	 * External indication that a segment is broken 
// 	 */
// 	
// 	void blocked(String segment, String reason, boolean blocked);
// }
// 
// Path: osgi.enroute.trains.api/src/osgi/enroute/trains/controller/api/TrainLocator.java
// public interface TrainLocator {
// 
// 	/**
// 	 * get train location. Promise is resolved when train passes next location.
// 	 * @return colon separated string "trainId:segmentName"
// 	 */
// 	Promise<String> nextLocation();
// }


import java.io.ByteArrayInputStream;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.BiFunction;
import java.util.stream.Collectors;
import org.eclipse.paho.client.mqttv3.IMqttDeliveryToken;
import org.eclipse.paho.client.mqttv3.MqttCallback;
import org.eclipse.paho.client.mqttv3.MqttClient;
import org.eclipse.paho.client.mqttv3.MqttConnectOptions;
import org.eclipse.paho.client.mqttv3.MqttException;
import org.eclipse.paho.client.mqttv3.MqttMessage;
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.ConfigurationPolicy;
import org.osgi.service.component.annotations.Deactivate;
import org.osgi.service.component.annotations.Reference;
import org.osgi.service.metatype.annotations.Designate;
import org.osgi.util.promise.Deferred;
import org.osgi.util.promise.Promise;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import osgi.enroute.dto.api.DTOs;
import osgi.enroute.trains.cloud.api.Segment;
import osgi.enroute.trains.cloud.api.TrackForSegment;
import osgi.enroute.trains.controller.api.TrainLocator;
package osgi.enroute.trains.location.provider;




@Designate(ocd = LocationConfig.class)
@Component(name = LocationConfig.LOCATION_CONFIG_PID,
        configurationPolicy = ConfigurationPolicy.REQUIRE,
        immediate = true)
// Path: osgi.enroute.trains.api/src/osgi/enroute/trains/cloud/api/Segment.java
// public class Segment extends DTO {
// 
// 	public enum Type {
// 		STRAIGHT, CURVED, SWITCH, SIGNAL, LOCATOR, BLOCK;
// 	}
// 	
// 
// 	/**
// 	 * Our Identity
// 	 */
// 	public String id;
// 	
// 	/**
// 	 * Type of the segment
// 	 */
//  	public Type type;
// 
// 	/**
//  	* Name of the track.This is the name required to get permission 
//  	* from the Track Manager. If this name starts with X then no admission is required. This 
//  	* is generally for switches.
//  	*/
//  	public String track;
//  	
// 	/**
// 	 * Sequence of the segment in the track
// 	 */
// 	public int sequence;
// 
// 	/**
// 	 * Length of the segment in millimeters, can be zero. It an be zero because
// 	 * the relation between the controllers and the switches and the signals is
// 	 * not always 1:1 mappable to controllers. Therefore zero sized segments can
// 	 * be used to map correctly.
// 	 */
// 	public int length;
// 
// 	/**
// 	 * Short code for RFID tag attached to this segment, or 0 for none.
// 	 */
// 	public int tagCode;
// 
// 	/**
// 	 * The associated controller
// 	 */
// 	public int controller = -1;
// 
// 	/**
// 	 * The next segment. Only a switch can have an additional to. The second to
// 	 * is the one selected if the switch is set to its alternative.
// 	 */
// 	public String to[];
// 	
// 	/**
// 	 * The previous segment. Only a switch can have an additional from. The second from
// 	 * is the one selected if the switch is set to its alternative.
// 	 */
// 	public String from[];
// 
// }
// 
// Path: osgi.enroute.trains.api/src/osgi/enroute/trains/cloud/api/TrackForSegment.java
// public interface TrackForSegment extends TrackInfo {
// 
// 	/**
// 	 * Send when a train has been identified at a locator segment
// 	 * 
// 	 * @param rfid
// 	 *            The RFID for the train
// 	 * @param segment
// 	 *            The name of the segment
// 	 */
// 	void locatedTrainAt(String rfid, String segment);
// 
// 	/**
// 	 * Indicate that a switch has been set
// 	 * 
// 	 * @param segment
// 	 *            the name of the switch segment
// 	 * @param alternative
// 	 *            defines the normal or alternative track
// 	 */
// 	void switched(String segment, boolean alternative);
// 	
// 	/**
// 	 * Indicate that a signal changed color
// 	 * 
// 	 * @param segment
// 	 *            the name of the signal segment
// 	 * @param color
// 	 *            the new signal color
// 	 */
// 	void signal(String segment, Color color);
// 	
// 	/**
// 	 * External indication that a segment is broken 
// 	 */
// 	
// 	void blocked(String segment, String reason, boolean blocked);
// }
// 
// Path: osgi.enroute.trains.api/src/osgi/enroute/trains/controller/api/TrainLocator.java
// public interface TrainLocator {
// 
// 	/**
// 	 * get train location. Promise is resolved when train passes next location.
// 	 * @return colon separated string "trainId:segmentName"
// 	 */
// 	Promise<String> nextLocation();
// }


// Path: osgi.enroute.trains.location.provider/src/osgi/enroute/trains/location/provider/TrainLocationClient.java
import java.io.ByteArrayInputStream;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.BiFunction;
import java.util.stream.Collectors;
import org.eclipse.paho.client.mqttv3.IMqttDeliveryToken;
import org.eclipse.paho.client.mqttv3.MqttCallback;
import org.eclipse.paho.client.mqttv3.MqttClient;
import org.eclipse.paho.client.mqttv3.MqttConnectOptions;
import org.eclipse.paho.client.mqttv3.MqttException;
import org.eclipse.paho.client.mqttv3.MqttMessage;
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.ConfigurationPolicy;
import org.osgi.service.component.annotations.Deactivate;
import org.osgi.service.component.annotations.Reference;
import org.osgi.service.metatype.annotations.Designate;
import org.osgi.util.promise.Deferred;
import org.osgi.util.promise.Promise;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import osgi.enroute.dto.api.DTOs;
import osgi.enroute.trains.cloud.api.Segment;
import osgi.enroute.trains.cloud.api.TrackForSegment;
import osgi.enroute.trains.controller.api.TrainLocator;

package osgi.enroute.trains.location.provider;




@Designate(ocd = LocationConfig.class)
@Component(name = LocationConfig.LOCATION_CONFIG_PID,
        configurationPolicy = ConfigurationPolicy.REQUIRE,
        immediate = true)
public class TrainLocationClient implements TrainLocator {