// Path: src/main/java/com/bortbort/arduino/FiloFirmata/Parser/CommandBytes.java
// public enum CommandBytes {
//     DIGITAL_MESSAGE         (0x90),
//     REPORT_ANALOG_PIN       (0xC0),
//     REPORT_DIGITAL_PIN      (0xD0),
//     ANALOG_MESSAGE          (0xE0),
//     START_SYSEX             (0xF0), // Start of SYSEX packet. Used by SysexCommandParser.
//     SET_PIN_MODE            (0xF4),
//     SET_DIGITAL_PIN_VALUE   (0xF5),
//     END_SYSEX               (0xF7), // End of SYSEX packet. Used by SysexCommandParser.
//     PROTOCOL_VERSION        (0xF9),
//     SYSTEM_RESET            (0xFF);
// 
//     /**
//      * Command Byte representing the CommandBytes enum value.
//      */
//     byte commandByte;
// 
//     /**
//      * Construct enum with the provided commandByte.
//      *
//      * @param commandByte int representing the Firmata protocol command byte.
//      */
//     CommandBytes(int commandByte) {
//         this.commandByte = (byte) commandByte;
//     }
// 
//     /**
//      * Command Byte representing the CommandBytes enum value.
//      *
//      * @return Byte representing the CommandBytes enum value.
//      */
//     public Byte getCommandByte() {
//         return commandByte;
//     }
// }
// 
// Path: src/main/java/com/bortbort/arduino/FiloFirmata/Parser/SysexCommandBytes.java
// public enum SysexCommandBytes {
//     ENCODER_DATA                (0x61), // reply with encoders current positions
//     ANALOG_MAPPING_QUERY        (0x69), // ask for mapping of analog to pin numbers
//     ANALOG_MAPPING_RESPONSE     (0x6A), // reply with mapping info
//     CAPABILITY_QUERY            (0x6B), // ask for supported modes and resolution of all pins
//     CAPABILITY_RESPONSE         (0x6C), // reply with supported modes and resolution
//     PIN_STATE_QUERY             (0x6D), // ask for a pin's current mode and state (different than value)
//     PIN_STATE_RESPONSE          (0x6E), // reply with a pin's current mode and state (different than value)
//     EXTENDED_ANALOG             (0x6F), // analog write (PWM, Servo, etc) to any pin
//     SERVO_CONFIG                (0x70), // pin number and min and max pulse
//     STRING_DATA                 (0x71), // a string message with 14-bits per char
//     STEPPER_DATA                (0x72), // control a stepper motor
//     ONEWIRE_DATA                (0x73), // send an OneWire read/write/reset/select/skip/search request
//     SHIFT_DATA                  (0x75), // shiftOut config/data message (reserved - not yet implemented)
//     I2C_REQUEST                 (0x76), // I2C request messages from a host to an I/O board
//     I2C_REPLY                   (0x77), // I2C reply messages from an I/O board to a host
//     I2C_CONFIG                  (0x78), // Enable I2C and provide any configuration settings
//     REPORT_FIRMWARE             (0x79), // report name and version of the firmware
//     SAMPLEING_INTERVAL          (0x7A), // the interval at which analog input is sampled (default = 19ms)
//     SCHEDULER_DATA              (0x7B), // send a createtask/deletetask/addtotask/schedule/querytasks/querytask request to the scheduler
//     SYSEX_NON_REALTIME          (0x7E), // MIDI Reserved for non-realtime messages
//     SYSEX_REALTIME              (0x7F); // MIDI Reserved for realtime messages
// 
//     /**
//      * Sysex Command Byte representing the SysexCommandBytes enum value.
//      */
//     private byte sysexCommandByte;
// 
//     /**
//      * Construct enum with the provided sysexCommandByte.
//      *
//      * @param sysexCommandByte int representing the Firmata protocol sysex command byte.
//      */
//     SysexCommandBytes(int sysexCommandByte) {
//         this.sysexCommandByte = (byte) sysexCommandByte;
//     }
// 
//     /**
//      * Sysex Command Byte representing the SysexCommandBytes enum value
//      *
//      * @return Byte representing the SysexCommandBytes enum value.
//      */
//     public Byte getSysexCommandByte() {
//         return sysexCommandByte;
//     }
// }


import com.bortbort.arduino.FiloFirmata.Parser.CommandBytes;
import com.bortbort.arduino.FiloFirmata.Parser.SysexCommandBytes;
import java.io.ByteArrayOutputStream;
package com.bortbort.arduino.FiloFirmata.Messages;



/**
 * Transmittable Sysex Message
 * Enables transmitting of a Firmata Sysex command. Handles serialization of the root command byte for Sysex,
 * and the Sysex command byte that the message is for.
 * Supplies a system for serializing the Sysex message into a byte array to be sent over the wire.
 */
public abstract class TransmittableSysexMessage extends TransmittableMessage {
    /**
     * SysexCommandByte used to identify this sysex message over the SerialPort communications line.
     */
    Byte sysexCommandByte;

    /**
     * Construct a new TransmittableSysexMessage using a pre-defined Firmata SysexCommandByte.
     *
     * @param sysexCommandByte SysexCommandBytes sysexCommandByte identifying the sysex command
     *                         that this sysex message is for.
     */
    public TransmittableSysexMessage(SysexCommandBytes sysexCommandByte) {
        this(sysexCommandByte.getSysexCommandByte());
    }

    /**
     * Construct a new TransmittableSysexMessage using a SysexCommandByte.
     *
     * @param sysexCommandByte SysexCommandByte identifying the sysex command that this sysex message is for.
     */
    public TransmittableSysexMessage(Byte sysexCommandByte) {
        super(CommandBytes.START_SYSEX);
        this.sysexCommandByte = sysexCommandByte;
    }

    /**
     * Combine the SysexCommandByte and the serialized sysex message packet together to form a Firmata supported
     * sysex byte packet to be sent over the SerialPort.
     *
     * @return byte[] array representing the full Firmata sysex command packet to be sent to the Firmata device.
     */
    @Override
    public byte[] toByteArray() {
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream(16);

        outputStream.write(commandByte);
        outputStream.write(sysexCommandByte);

// Path: src/main/java/com/bortbort/arduino/FiloFirmata/Parser/CommandBytes.java
// public enum CommandBytes {
//     DIGITAL_MESSAGE         (0x90),
//     REPORT_ANALOG_PIN       (0xC0),
//     REPORT_DIGITAL_PIN      (0xD0),
//     ANALOG_MESSAGE          (0xE0),
//     START_SYSEX             (0xF0), // Start of SYSEX packet. Used by SysexCommandParser.
//     SET_PIN_MODE            (0xF4),
//     SET_DIGITAL_PIN_VALUE   (0xF5),
//     END_SYSEX               (0xF7), // End of SYSEX packet. Used by SysexCommandParser.
//     PROTOCOL_VERSION        (0xF9),
//     SYSTEM_RESET            (0xFF);
// 
//     /**
//      * Command Byte representing the CommandBytes enum value.
//      */
//     byte commandByte;
// 
//     /**
//      * Construct enum with the provided commandByte.
//      *
//      * @param commandByte int representing the Firmata protocol command byte.
//      */
//     CommandBytes(int commandByte) {
//         this.commandByte = (byte) commandByte;
//     }
// 
//     /**
//      * Command Byte representing the CommandBytes enum value.
//      *
//      * @return Byte representing the CommandBytes enum value.
//      */
//     public Byte getCommandByte() {
//         return commandByte;
//     }
// }
// 
// Path: src/main/java/com/bortbort/arduino/FiloFirmata/Parser/SysexCommandBytes.java
// public enum SysexCommandBytes {
//     ENCODER_DATA                (0x61), // reply with encoders current positions
//     ANALOG_MAPPING_QUERY        (0x69), // ask for mapping of analog to pin numbers
//     ANALOG_MAPPING_RESPONSE     (0x6A), // reply with mapping info
//     CAPABILITY_QUERY            (0x6B), // ask for supported modes and resolution of all pins
//     CAPABILITY_RESPONSE         (0x6C), // reply with supported modes and resolution
//     PIN_STATE_QUERY             (0x6D), // ask for a pin's current mode and state (different than value)
//     PIN_STATE_RESPONSE          (0x6E), // reply with a pin's current mode and state (different than value)
//     EXTENDED_ANALOG             (0x6F), // analog write (PWM, Servo, etc) to any pin
//     SERVO_CONFIG                (0x70), // pin number and min and max pulse
//     STRING_DATA                 (0x71), // a string message with 14-bits per char
//     STEPPER_DATA                (0x72), // control a stepper motor
//     ONEWIRE_DATA                (0x73), // send an OneWire read/write/reset/select/skip/search request
//     SHIFT_DATA                  (0x75), // shiftOut config/data message (reserved - not yet implemented)
//     I2C_REQUEST                 (0x76), // I2C request messages from a host to an I/O board
//     I2C_REPLY                   (0x77), // I2C reply messages from an I/O board to a host
//     I2C_CONFIG                  (0x78), // Enable I2C and provide any configuration settings
//     REPORT_FIRMWARE             (0x79), // report name and version of the firmware
//     SAMPLEING_INTERVAL          (0x7A), // the interval at which analog input is sampled (default = 19ms)
//     SCHEDULER_DATA              (0x7B), // send a createtask/deletetask/addtotask/schedule/querytasks/querytask request to the scheduler
//     SYSEX_NON_REALTIME          (0x7E), // MIDI Reserved for non-realtime messages
//     SYSEX_REALTIME              (0x7F); // MIDI Reserved for realtime messages
// 
//     /**
//      * Sysex Command Byte representing the SysexCommandBytes enum value.
//      */
//     private byte sysexCommandByte;
// 
//     /**
//      * Construct enum with the provided sysexCommandByte.
//      *
//      * @param sysexCommandByte int representing the Firmata protocol sysex command byte.
//      */
//     SysexCommandBytes(int sysexCommandByte) {
//         this.sysexCommandByte = (byte) sysexCommandByte;
//     }
// 
//     /**
//      * Sysex Command Byte representing the SysexCommandBytes enum value
//      *
//      * @return Byte representing the SysexCommandBytes enum value.
//      */
//     public Byte getSysexCommandByte() {
//         return sysexCommandByte;
//     }
// }


// Path: src/main/java/com/bortbort/arduino/FiloFirmata/Messages/TransmittableSysexMessage.java
import com.bortbort.arduino.FiloFirmata.Parser.CommandBytes;
import com.bortbort.arduino.FiloFirmata.Parser.SysexCommandBytes;
import java.io.ByteArrayOutputStream;

package com.bortbort.arduino.FiloFirmata.Messages;



/**
 * Transmittable Sysex Message
 * Enables transmitting of a Firmata Sysex command. Handles serialization of the root command byte for Sysex,
 * and the Sysex command byte that the message is for.
 * Supplies a system for serializing the Sysex message into a byte array to be sent over the wire.
 */
public abstract class TransmittableSysexMessage extends TransmittableMessage {
    /**
     * SysexCommandByte used to identify this sysex message over the SerialPort communications line.
     */
    Byte sysexCommandByte;

    /**
     * Construct a new TransmittableSysexMessage using a pre-defined Firmata SysexCommandByte.
     *
     * @param sysexCommandByte SysexCommandBytes sysexCommandByte identifying the sysex command
     *                         that this sysex message is for.
     */
    public TransmittableSysexMessage(SysexCommandBytes sysexCommandByte) {
        this(sysexCommandByte.getSysexCommandByte());
    }

    /**
     * Construct a new TransmittableSysexMessage using a SysexCommandByte.
     *
     * @param sysexCommandByte SysexCommandByte identifying the sysex command that this sysex message is for.
     */
    public TransmittableSysexMessage(Byte sysexCommandByte) {
        super(CommandBytes.START_SYSEX);
        this.sysexCommandByte = sysexCommandByte;
    }

    /**
     * Combine the SysexCommandByte and the serialized sysex message packet together to form a Firmata supported
     * sysex byte packet to be sent over the SerialPort.
     *
     * @return byte[] array representing the full Firmata sysex command packet to be sent to the Firmata device.
     */
    @Override
    public byte[] toByteArray() {
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream(16);

        outputStream.write(commandByte);
        outputStream.write(sysexCommandByte);

        if (serialize(outputStream)) {