/** * Adapter control port implementation for dynamic interactions with Test Adapter * * @author ETSI / STF424 * @version $URL$ * $Id$ * */ package org.etsi.its.adapter.ports; import org.etsi.adapter.GnssSupportFactory; import org.etsi.adapter.IGnssSupport; import org.etsi.adapter.TERFactory; import org.etsi.common.ByteHelper; import org.etsi.its.adapter.Management; import org.etsi.ttcn.tci.BooleanValue; import org.etsi.ttcn.tri.TriStatus; /** This class implements behaviour for Adapter controller port * */ public class AdapterControlPort extends AdapterPort implements IPort, IObservable { /* AdapterControl Primitives */ private static final byte AcGnPrimitive = 0; private static final byte AcGn6Primitive = 1; private static final byte AcGnssPrimitive = 2; private static final byte AcSecPrimitive = 3; /* AdapterControl Response */ private static final byte AcGnResponse = 0; //private static final byte AcGn6Response = 1; public static final byte AcGnssResponse = 2; public static final byte AcGnssDistanceCovered = 3; public static final byte AcSecResponse = 4; /* GN Commands */ private static final byte AcStartBeaconing = 0; private static final byte AcStopBeaconing = 1; private static final byte AcStartPassBeaconing = 2; private static final byte AcStopPassBeaconing = 3; private static final byte AcStartBeaconingMultipleNeighbour = 4; private static final byte AcStopBeaconingMultipleNeighbour = 5; private static final byte AcGetLongPosVector = 6; /* GN Responses */ protected static final byte AcGnResponseFailure = 0; protected static final byte AcLongPosVector = 6; /* SCENARIO commands */ private static final byte AcLoadScenario = 0x70; private static final byte AcStartScenario = 0x71; private static final byte AcStopScenario = 0x72; private static final byte AcAwaitDistanceToCover = 0x73; private static final byte AcChangeSpead = 0x74; private static final byte AcChangeHeading = 0x75; /* Set the certificate to be used by the Test Adapter */ private static final byte AcEnableSecurity = 0x7a; private static final byte AcDisableSecurity = 0x7b; public static final byte AcTrue = 0x01; public static final byte AcFalse = 0x00; private static final String GNSS_SCENARIO_SUPPORT = "GnssScenarioSupport"; private IGnssSupport GNSS; private boolean isScenarioStarted = false; private boolean gnssScenarioSupport; /** * Constructor * @param portName Name of the port * @param componentName Name of the component owning this port instance */ public AdapterControlPort(final String portName, final String componentName) { super(portName, componentName); try { gnssScenarioSupport = ((BooleanValue) TERFactory.getInstance().getTaParameter(GNSS_SCENARIO_SUPPORT)).getBoolean(); } catch (Throwable th) { gnssScenarioSupport = false; } if (gnssScenarioSupport) { GNSS = GnssSupportFactory.getInstance(); } } @Override public boolean send(final byte[] message) { boolean result = true; try { // Decode non protocol part switch(message[0]) { case AcGnPrimitive: { byte[] data = ByteHelper.extract(message, 2, message.length - 2); switch (message[1]) { case AcGetLongPosVector: ProcessAcGetLongPosVector(data); break; case AcStartBeaconing: Management.getInstance(getComponentName()).startBeaconing(data); break; case AcStopBeaconing: Management.getInstance(getComponentName()).stopBeaconing(); break; case AcStartPassBeaconing: ProcessAcStartPassBeaconing(data); break; case AcStopPassBeaconing: Management.getInstance(getComponentName()).stopEnqueueingBeacons(); break; case AcStartBeaconingMultipleNeighbour: // TODO break; case AcStopBeaconingMultipleNeighbour: // TODO break; } } break; case AcGn6Primitive: /* FIXME try { byte[] buf = new byte[4096]; DatagramSocket remoteAdapterSocket = new DatagramSocket(); InetAddress remoteAdapterAddress = InetAddress.getByName(((CharstringValue)TERFactory.getInstance().getTaParameter("Gn6RemoteAdapterIp")).getString()); int remoteAdapterPort = Integer.decode(((CharstringValue)TERFactory.getInstance().getTaParameter("Gn6RemoteAdapterPort")).getString()); DatagramPacket command = new DatagramPacket(new byte[] {CMD_IFACES}, 1, remoteAdapterAddress, remoteAdapterPort); DatagramPacket response = new DatagramPacket(buf, buf.length); remoteAdapterSocket.send(command); remoteAdapterSocket.receive(response); byte[] data = ByteHelper.extract(response.getData(), response.getOffset(), response.getLength()); if(data[0] == RPL_IFACES) { // enqueue response... byte[] buffer = impl.Encode(TestAdapterMessageTypeEnum.AcGn6Response, ByteHelper.extract(data, 1, data.length - 1), new Date().getTime()); setChanged(); notifyObservers(new PortEvent(buffer, getPortName(), getComponentName())); } } catch (SocketException e) { e.printStackTrace(); } catch (UnknownHostException e) { e.printStackTrace(); } */ break; case AcGnssPrimitive: if (gnssScenarioSupport) { byte[] data = ByteHelper.extract(message, 2, message.length - 2); switch (message[1]) { case AcLoadScenario: LoadScenario(ByteHelper.byteArrayToShort(data)); break; case AcStartScenario: StartScenario(); break; case AcStopScenario: StopScenario(); break; case AcAwaitDistanceToCover: Float distance = ByteHelper.byteArrayToFloat(data); AwaitDistanceToCover(distance); break; case AcChangeSpead: // ChangeSpeed(speed); break; case AcChangeHeading: // ChangeHeading(heading); break; } } else { TERFactory.getInstance().getTriStatus(TriStatus.TRI_OK, "AcGnssPrimitive cannot be handled as the " + GNSS_SCENARIO_SUPPORT + " is set to false!"); result = false; } break; case AcSecPrimitive: switch (message[1]) { case AcEnableSecurity: byte[] data = ByteHelper.extract(message, 2, message.length - 2); ProcessAcEnableSecurity(data); break; case AcDisableSecurity: ProcessAcDisableSecurity(); break; } // End of 'switch' statement break; default: ByteHelper.dump("Unsupported AC primitive", message); break; } // End of 'switch' statement return result; } catch (Exception e) { e.printStackTrace(); } return false; } // End of method send /** * Processes AcGetLongPosVector command * @param data */ private void ProcessAcGetLongPosVector(final byte[] gnAddress) { new Thread(new Runnable() { @Override public void run() { byte[] response = null; byte[] responseHdr = {(byte)AcGnResponse, (byte)0x00}; byte[] longPosVector = Management.getInstance(getComponentName()).getLongPositionVector(gnAddress); if((longPosVector == null) || (longPosVector.length == 0)) { responseHdr[1] = (byte)AcGnResponseFailure; response = ByteHelper.concat(responseHdr, new byte[]{AcTrue}); } else { responseHdr[1] = (byte)AcLongPosVector; response = ByteHelper.concat(responseHdr, longPosVector); } setChanged(); notifyObservers(new PortEvent(response, getPortName(), getComponentName())); } }).start(); } private void ProcessAcStartPassBeaconing(final byte[] beacon) { byte[] response = {(byte)AcGnResponse, (byte)AcGnResponseFailure, (byte)AcFalse}; Management.getInstance(getComponentName()).startEnqueueingBeacons(beacon); setChanged(); notifyObservers(new PortEvent(response, getPortName(), getComponentName())); } private void LoadScenario(final int scenario) { new Thread(new Runnable() { @Override public void run() { boolean result = GNSS.loadScenario(scenario); byte[] response = {(byte)AcGnssResponse, (byte)(result?AcTrue:AcFalse)}; setChanged(); notifyObservers(new PortEvent(response, getPortName(), getComponentName())); } }).start(); } private void StartScenario() { new Thread(new Runnable() { @Override public void run() { isScenarioStarted = GNSS.startScenario(); byte[] response = {(byte)AcGnssResponse, (byte)(isScenarioStarted?AcTrue:AcFalse)}; setChanged(); notifyObservers(new PortEvent(response, getPortName(), getComponentName())); } }).start(); } private void StopScenario() { new Thread(new Runnable() { @Override public void run() { boolean result = GNSS.stopScenario(); isScenarioStarted = !result; byte[] response = {(byte)AcGnssResponse, (byte)(isScenarioStarted?AcFalse:AcTrue)}; setChanged(); notifyObservers(new PortEvent(response, getPortName(), getComponentName())); } }).start(); } private void AwaitDistanceToCover(final double distance) { new Thread(new Runnable() { @Override public void run() { boolean result = GNSS.awaitDistanceToCover(AdapterControlPort.this, distance); byte[] response = {(byte)AcGnssResponse, (byte)(result?AcFalse:AcTrue)}; setChanged(); notifyObservers(new PortEvent(response, getPortName(), getComponentName())); } }).start(); } private void ProcessAcEnableSecurity(final byte[] data) { new Thread(new Runnable() { @Override public void run() { Management.getInstance(getComponentName()).setSecuredMode(data); byte[] response = {(byte)AcSecResponse, (byte)AcTrue }; setChanged(); notifyObservers(new PortEvent(response, getPortName(), getComponentName())); } }).start(); } private void ProcessAcDisableSecurity() { new Thread(new Runnable() { @Override public void run() { Management.getInstance(getComponentName()).unsetSecuredMode(); byte[] response = {(byte)AcSecResponse, (byte)AcTrue }; setChanged(); notifyObservers(new PortEvent(response, getPortName(), getComponentName())); } }).start(); } @Override public void dispose() { if (gnssScenarioSupport) { if (GNSS!=null) { if (isScenarioStarted) { GNSS.stopScenario(); } GNSS.dispose(); } GNSS = null; } } } // End of class AdapterControlPort