package OpenDis7Examples; import java.io.*; import java.net.*; import java.util.*; import edu.nps.moves.dis7.*; import edu.nps.moves.dis7.enumerations.*; /** * This is an example that sends many/most types of PDUs. Useful for testing standards * compliance or getting a full set of PDUs. It also writes the generated PDUs to an XML file. * Adapted from OpenDIS library example package edu.nps.moves.examples * * @author DMcG * @version $Id:$ */ public class AllPduSender { /** Default multicast group address we send on. */ public static final String DEFAULT_MULTICAST_ADDRESS = "239.1.2.3"; /** Default multicast port used, matches Wireshark DIS capture default */ public static final int DEFAULT_MULTICAST_PORT = 3000; private int port; InetAddress multicastAddress; public AllPduSender(int port, String multicast) { try { this.port = port; multicastAddress = InetAddress.getByName(multicast); if (!multicastAddress.isMulticastAddress()) { System.out.println("Not a multicast address: " + multicast); } } catch (UnknownHostException e) { System.out.println("Unable to open socket: " + e); } } public void run() { System.out.println("DisExamplesOpenDis7.AllPduSender started..."); try { System.out.println("Generate PDUs and note issues, if any..."); List<Pdu> generatedPdusList = new ArrayList<>(); // Loop through all the enumerated PDU types, create a PDU for each type, // add that PDU to generatedPdusList, and send each one for (DISPDUType pdu : DISPDUType.values()) { // System.out.println("PDU " + pdu.getValue() + " " + pdu.name() + " " + pdu.getDescription()); // diagnostic Pdu aPdu = null; // edu.nps.moves7.dis.PDU superclass for all PDUs, in preparation for custom assignment try { switch (pdu) // using enumeration values from edu.nps.moves.dis7.enumerations.DISPDUType { case OTHER: // 0 System.out.println ("*** Note: DISPDUType." + pdu.name() + " not supported"); // TODO why was this received? // nothing to send break; case ENTITY_STATE: // 1 aPdu = new EntityStatePdu(); EntityStatePdu espdu = (EntityStatePdu) aPdu; EntityMarking entityMarking = new EntityMarking (); entityMarking.setCharacters("AllPduSender".getBytes()); //entityMarking.setCharacters(Byte.valueOf("0")); // 11 characters max? espdu.setMarking(entityMarking); Vector3Double espduLocation = new Vector3Double(); espduLocation.setX(1.0); espduLocation.setY(2.0); espduLocation.setZ(3.0); espdu.setEntityLocation(espduLocation); // it is important to identify questions as you think of them // TODO how to set azimuth, i.e. course direction over ground? break; case FIRE: // 2 aPdu = new FirePdu(); break; case DETONATION: // 3 aPdu = new DetonationPdu(); break; case COLLISION: // 4 aPdu = new CollisionPdu(); break; case SERVICE_REQUEST: // 5 aPdu = new ServiceRequestPdu(); break; case RESUPPLY_OFFER: // 6 aPdu = new ResupplyOfferPdu(); break; case RESUPPLY_RECEIVED: // 7 aPdu = new ResupplyReceivedPdu(); break; case RESUPPLY_CANCEL: //8 aPdu = new ResupplyCancelPdu(); break; case REPAIR_COMPLETE: // 9 aPdu = new RepairCompletePdu(); break; case REPAIR_RESPONSE: // 10 aPdu = new RepairResponsePdu(); break; case CREATE_ENTITY: // 11 aPdu = new CreateEntityPdu(); break; case REMOVE_ENTITY: // 12 aPdu = new RemoveEntityPdu(); break; case START_RESUME: // 13 aPdu = new StartResumePdu(); break; case STOP_FREEZE: // 14 aPdu = new StopFreezePdu(); break; case ACKNOWLEDGE: // 15 aPdu = new AcknowledgePdu(); break; case ACTION_REQUEST: // 16 aPdu = new ActionRequestPdu(); break; case ACTION_RESPONSE: // 17 aPdu = new ActionResponsePdu(); break; case DATA_QUERY: // 18 aPdu = new DataQueryPdu(); break; case SET_DATA: // 19 aPdu = new SetDataPdu(); break; case DATA: // 20 aPdu = new DataPdu(); break; case EVENT_REPORT: // 21 aPdu = new EventReportPdu(); break; case ELECTROMAGNETIC_EMISSION: // 23 aPdu = new ElectromagneticEmissionPdu(); break; case DESIGNATOR: // 24 aPdu = new DesignatorPdu(); break; case TRANSMITTER: // 25 aPdu = new TransmitterPdu(); break; case SIGNAL: // 26 aPdu = new SignalPdu(); break; case RECEIVER: // 27 aPdu = new ReceiverPdu(); break; case IDENTIFICATION_FRIEND_OR_FOE: // 28 aPdu = new IdentificationFriendOrFoePdu(); break; case UNDERWATER_ACOUSTIC: // 29 aPdu = new UnderwaterAcousticPdu(); break; case SUPPLEMENTAL_EMISSION_ENTITY_STATE: // 30 aPdu = new SupplementalEmissionEntityStatePdu(); break; case INTERCOM_SIGNAL: // 31 aPdu = new IntercomSignalPdu(); break; case INTERCOM_CONTROL: // 32 aPdu = new IntercomControlPdu(); break; case AGGREGATE_STATE: // 33 aPdu = new AggregateStatePdu(); break; case ISGROUPOF: // 34 aPdu = new IsGroupOfPdu(); break; case TRANSFER_OWNERSHIP: // 35 aPdu = new TransferOwnershipPdu(); break; case ISPARTOF: // 36 aPdu = new IsPartOfPdu(); break; case MINEFIELD_STATE: // 37 aPdu = new MinefieldStatePdu(); break; case MINEFIELD_QUERY: // 38 aPdu = new MinefieldQueryPdu(); break; case MINEFIELD_DATA: // 39 aPdu = new MinefieldDataPdu(); break; case MINEFIELD_RESPONSE_NACK: // 40 aPdu = new MinefieldResponseNACKPdu(); break; case ENVIRONMENTAL_PROCESS: // 41 aPdu = new EnvironmentalProcessPdu(); break; case GRIDDED_DATA: // 42 aPdu = new GriddedDataPdu(); break; case POINT_OBJECT_STATE: // 43 aPdu = new PointObjectStatePdu(); break; case LINEAR_OBJECT_STATE: // 44 aPdu = new LinearObjectStatePdu(); break; case AREAL_OBJECT_STATE: // 45 aPdu = new ArealObjectStatePdu(); break; case TIME_SPACE_POSITION_INFORMATION: // 46 aPdu = new TimeSpacePositionInformationPdu(); break; case APPEARANCE: // 47 aPdu = new AppearancePdu(); break; case ARTICULATED_PARTS: // 48 aPdu = new ArticulatedPartsPdu(); break; case LIVE_ENTITY_FIRE: // 49 aPdu = new LiveEntityFirePdu(); break; case LIVE_ENTITY_DETONATION: // 50 aPdu = new LiveEntityDetonationPdu(); break; case CREATE_ENTITY_RELIABLE: // 51 aPdu = new CreateEntityReliablePdu(); break; case REMOVE_ENTITY_RELIABLE: // 52 aPdu = new RemoveEntityReliablePdu(); break; case START_RESUME_RELIABLE: // 53 aPdu = new StartResumeReliablePdu(); break; case STOP_FREEZE_RELIABLE: // 54 aPdu = new StopFreezeReliablePdu(); break; case ACKNOWLEDGE_RELIABLE: // 55 aPdu = new AcknowledgeReliablePdu(); break; case ACTION_REQUEST_RELIABLE: // 56 aPdu = new ActionRequestReliablePdu(); break; case ACTION_RESPONSE_RELIABLE: // 57 aPdu = new ActionResponseReliablePdu(); break; case DATA_QUERY_RELIABLE: // 58 aPdu = new DataQueryReliablePdu(); break; case SET_DATA_RELIABLE: // 59 aPdu = new SetDataReliablePdu(); break; case DATA_RELIABLE: // 60 aPdu = new DataReliablePdu(); break; case EVENT_REPORT_RELIABLE: // 61 aPdu = new EventReportReliablePdu(); break; case COMMENT_RELIABLE: // 62 aPdu = new CommentReliablePdu(); break; case RECORD_RELIABLE: // 63 aPdu = new RecordReliablePdu(); break; case SET_RECORD_RELIABLE: // 64 aPdu = new SetRecordReliablePdu(); break; case RECORD_QUERY_RELIABLE: // 65 aPdu = new RecordQueryReliablePdu(); break; case COLLISION_ELASTIC: // 66 aPdu = new CollisionElasticPdu(); break; case ENTITY_STATE_UPDATE: // 67 aPdu = new EntityStateUpdatePdu(); break; case DIRECTED_ENERGY_FIRE: // 68 aPdu = new DirectedEnergyFirePdu(); break; case ENTITY_DAMAGE_STATUS: // 69 aPdu = new EntityDamageStatusPdu(); break; case INFORMATION_OPERATIONS_ACTION: // 70 aPdu = new InformationOperationsActionPdu(); break; case INFORMATION_OPERATIONS_REPORT: // 71 aPdu = new InformationOperationsReportPdu(); break; case ATTRIBUTE: // 72 aPdu = new AttributePdu(); break; case COMMENT: // aPdu = new CommentPdu(); // default for this switch logic // see Garrett Loffelman and Pete Severson's code for OpenDis version 4 example // https://gitlab.nps.edu/Savage/NetworkedGraphicsMV3500/tree/master/assignments/src/MV3500Cohort2018JulySeptember/projects/LoeffelmanSeverson CommentPdu newCommentPdu = new CommentPdu(); ArrayList<VariableDatum> payloadList = new ArrayList<VariableDatum>(); ArrayList<String> commentsList = new ArrayList<>(); commentsList.add("Hello CommentPDU"); commentsList.add("Here is a new message"); if (!commentsList.isEmpty()) System.out.println("Preparing CommentPDU:"); for (String comment : commentsList) { VariableDatum newVariableDatum = new VariableDatum(); newVariableDatum.setVariableDatumValue (comment.getBytes()); // conversion newVariableDatum.setVariableDatumLength(comment.getBytes().length * 8); // bits, not bytes, see spec and javadoc // alternatively, you do not need to set this and the marshaller will figure it out from the byte array // (see javadoc for VariableDatum.setVariableDatumLength()) payloadList.add(newVariableDatum); System.out.println(" \"" + comment + "\""); } newCommentPdu.setVariableDatums(payloadList); aPdu = newCommentPdu; // hand off for sending break; default: System.out.println("*** Warning: PDU " + pdu.getValue() + " " + pdu + " not supported, created or sent "); // code generation block for this class follows: // System.out.println(" case " + pdu + ": // " + pdu.getValue()); // System.out.println(" aPdu = new " + pdu.getDescription().replace(" ","").replace("-","").replace("/","") + // "Pdu();"); // System.out.println(" break;"); // System.out.println(); } if (aPdu != null) { generatedPdusList.add(aPdu); } } catch (Exception e) { System.out.print("Exception thrown for PDU " + pdu.getValue() + " " + pdu); System.out.print(Arrays.toString(e.getStackTrace())); // continue looping } } // Send the PDUs we created System.out.println("Send the " + generatedPdusList.size() + " PDUs we created..."); InetAddress localMulticastAddress = InetAddress.getByName(DEFAULT_MULTICAST_ADDRESS); MulticastSocket socket = new MulticastSocket(DEFAULT_MULTICAST_PORT); socket.joinGroup(localMulticastAddress); for (int idx = 0; idx < generatedPdusList.size(); idx++) { ByteArrayOutputStream baos = new ByteArrayOutputStream(); DataOutputStream dos = new DataOutputStream(baos); byte[] buffer; Pdu aPdu = generatedPdusList.get(idx); try { aPdu.marshal(dos); buffer = baos.toByteArray(); DatagramPacket packet = new DatagramPacket(buffer, buffer.length, localMulticastAddress, DEFAULT_MULTICAST_PORT); socket.send(packet); try { Thread.sleep(100L); } catch (InterruptedException ex) { } String currentPduTypeValuePadded = String.format("%2s", aPdu.getPduType().getValue()); String currentPduTypePadded = String.format("%-34s", aPdu.getPduType()); // - indicates right padding of whitespace System.out.print ("Sent DIS PDU " + currentPduTypeValuePadded + " " + currentPduTypePadded ); System.out.println(" of type " + aPdu.getClass().getName()); } catch (Exception ex) { System.out.println("Marshaling error" + ex); } } // write the PDUs out to an XML file. //PduContainer container = new PduContainer(); //container.setPdus(generatedPdus); //container.marshallToXml("examplePdus.xml"); } catch (IOException e) { System.out.println(e); } } public static void main(String args[]) { if (args.length == 2) { AllPduSender sender = new AllPduSender(Integer.parseInt(args[0]), args[1]); sender.run(); } else { System.out.println("Usage: AllPduSender <port> <multicast group>"); System.out.println("Default: AllPduSender " + DEFAULT_MULTICAST_PORT + " " + DEFAULT_MULTICAST_ADDRESS); AllPduSender sender = new AllPduSender(DEFAULT_MULTICAST_PORT, DEFAULT_MULTICAST_ADDRESS); sender.run(); } System.out.println("DisExamplesOpenDis7.AllPduSender complete."); } }