Skip to content
Snippets Groups Projects
AllPduSender.java 19.54 KiB
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.");
    }
}