/*
 *****************************************************************************
 *                                                                           *
 *              IMPINJ CONFIDENTIAL AND PROPRIETARY                          *
 *                                                                           *
 * This source code is the sole property of Impinj, Inc. Reproduction or     *
 * utilization of this source code in whole or in part is forbidden without  *
 * the prior written consent of Impinj, Inc.                                 *
 *                                                                           *
 * (c) Copyright Impinj, Inc. 2014. All rights reserved.                     *
 *                                                                           *
 *****************************************************************************/
package com.impinj.stpexamples;

import com.impinj.stp.*;
import com.impinj.stp.Helpers;
import com.impinj.stp.StpApi.*;

public class GpioEncodeConsole {
    final static String DEVICE_NAME = "speedwayr-XX-XX-XX";    // Please edit
    String epc =     "3074257BF7191E4000000000";               // Please edit
    String epcMask = "FFFFFFFFFFFFFFFFFFFFFFFF";
    final boolean debug = false;
    Device device;
    public GpioEncodeConsole(String devStr) {
         try {
            System.out.println("GPIO sample app");
            System.out.println("Run for 1 minute.");
         //      Uncomment to capture Debug fdd or rdd stream
         //   DebugStreamGrabber dsg = new DebugStreamGrabber(devStr, DebugStreamGrabber.StreamType.FDD);
         //   dsg.startPumperThread("StpDebugStream.fdd");
         //   DebugStreamGrabber dsg = new DebugStreamGrabber(devStr, DebugStreamGrabber.StreamType.RDD);
         //   dsg.startPumperThread("StpDebugStream.rdd");

            // Open network connection
            device = new Device(devStr);
            device.setDebug(debug);
            // setup event listeners
            device.addTagOperationReportListener(new MyTagOperationReportListener());
            device.addOperationSummaryReportListener(new MyOperationSummaryReportListener());
            device.addDeviceEventReportListener(new MyDeviceEventReportListener());

            for (Version v : device.getVersions())
                System.out.println("Version:"+v.getVersionID()+"  Major="+v.getMajor()+ "  Minor="+v.getMinor()+ "  Maintance="+v.getMaintenance()+"  Build="+v.getBuild());
            // Device Config
            device.runSetDeviceConfigCommand(
                 SetDeviceConfigCommand.newBuilder()
                     .setDeviceConfig(
                         DeviceConfig.newBuilder()
                             .setTriggerConfig(
                                  TriggerConfig.newBuilder()
                                     .setStartTriggerConfig(
                                         StartTriggerConfig.newBuilder()
                                             .setEnableGpiStartTrigger(true)
                                         )
                                         .setStopTriggerConfig(
                                             StopTriggerConfig.newBuilder()
                                                 .setEnableGpiStopTrigger(false)
                                                 .setTimeout(35)
                                         )
                               )
                               .setGPIConfig(
                                   GPIConfig.newBuilder()
                                       .setSignalingMode(GPIOSignalMode.GPIO_SIGNAL_MODE_COMBINED)
                                       .setGPI1Polarity(GPIOPolarity.GPIO_POLARITY_ACTIVE_HIGH)
                                       .setGPI2Polarity(GPIOPolarity.GPIO_POLARITY_ACTIVE_HIGH)
                                       .setGPI3Polarity(GPIOPolarity.GPIO_POLARITY_ACTIVE_HIGH)
                               )
                               .setGPOConfig(
                                   GPOConfig.newBuilder()
                                       .setSignalingMode(GPIOSignalMode.GPIO_SIGNAL_MODE_SEPARATE)
                                       .setGPO1Polarity(GPIOPolarity.GPIO_POLARITY_ACTIVE_HIGH)
                                       .setGPO2Polarity(GPIOPolarity.GPIO_POLARITY_ACTIVE_HIGH)
                                       .setGPO3Polarity(GPIOPolarity.GPIO_POLARITY_ACTIVE_HIGH)
                                       .setEnableOperationResultGpo(true)
                                       .setGPOPulseDuration(1)
                               )
                               .setDeviceMode(DeviceMode.DEVICE_MODE_ENCODE)
                               .setOperationMode(OperationMode.OPERATION_MODE_SINGLE)
                               .setReportConfig(
                                   ReportConfig.newBuilder()
                                       .setDeviceEventConfig(
                                           DeviceEventConfig.newBuilder()
                                               .setEnableGPIEvents(true)
                                       )
                                       .setOperationSummaryReportConfig(
                                           OperationSummaryReportConfig.newBuilder()
                                              .setEnableOperationSummaryReports(true)
                                       )
                                       .setTagOperationReportConfig(
                                           TagOperationReportConfig.newBuilder()
                                               .setTagOperationReportTrigger(
                                                    TagOperationReportTrigger.TAG_OPERATION_REPORT_TRIGGER_IMMEDIATE)
                                               .setEnableTagOperationReports(true)
                                               .setEnableTagOperationRetryReports(false)
                                               .setEnableEpcInSerialReport(false)
                                               .setEnableReportingOverSerialPort(false)
                                               .setSendSerialReportAfterGPODeassert(false)
                                       )
                               )
                        ).build()
                    );
            // Setup Antenna parameters
            device.runSetAntennaConfigCommand(
                SetAntennaConfigCommand.newBuilder()
                    .setAntennasConfig(
                         AntennasConfig.newBuilder()
                             .addAntennaConfig(
                                 AntennaConfig.newBuilder()
                                     .setAntennaID(1)
                                     .setGen2Mode(Gen2Mode.GEN2_MODE_MAX_THROUGHPUT)
                                     .setInventorySearchMode(InventorySearchMode.INVENTORY_SEARCH_MODE_SINGLE_TARGET_A_TO_B)
                                     .setGen2Session(Gen2Session.GEN2_SESSION_0)
                                     .setTagPopulationEstimate(5)
                                     .setTransmitPower(2000)
                                     .setReceiveSensitivity(-5500)
                                     .setTagPopulationEstimate(0)
                             )
                      ).build()
                );
             // Setup Serialization Job
             device.runAddSerializationJobCommand(
                 AddSerializationJobCommand.newBuilder()
                    .setSerializationJob(
                        SerializationJob.newBuilder()
                            .setJobId(1)
                            .setJobType(SerializationJobType.SERIALIZATION_JOB_TYPE_STATIC)
                            .setJobCompletionCriteria(SerializationJobCompletionCriteria.SERIALIZATION_JOB_COMPLETION_CRITERIA_NONE)
                            .setEPCMemory(
                                EPCMemory.newBuilder()
                                    .setData(Helpers.stringToByteString(epc))
                                    .setMask(Helpers.stringToByteString(epcMask))
                                    .setSerialization(
                                        Serialization.newBuilder()
                                            .setSerializationBits(38)
                                            .setMonzaSelfSerialization(
                                                MonzaSelfSerialization.newBuilder()
                                                   .setSerializationPrefix("101")
                                             )
                                    )
                            )
                   ).build()
             );
             device.engage();
             device.start();

             Helpers.sleepMS(60000);  // Run for 1 minute then close up and quit.

             device.stop();
             device.disengage();
             // Stop capture
             //dsg.Close();
         } catch(Exception ex) {
             System.out.println("Main: "+ex.getMessage());
         } finally {
             device.stpClose();
         }
     }

     public static void main(String[] args) {
         if (args.length == 1)
             new GpioEncodeConsole(args[0]);
         else
             new GpioEncodeConsole(DEVICE_NAME);
     }

     class MyTagOperationReportListener implements Device.TagOperationReportListener {
         public void reportEvent(TagOperationReport report) {
              System.out.println("EPC: "+Helpers.byteStringToString(report.getEPC()));
         }
     }
     class MyOperationSummaryReportListener implements Device.OperationSummaryReportListener {
         public void reportEvent(OperationSummaryReport report) {
             System.out.println("Summary: Pass="+ report.getTagOperationPassCount() +
                   "  Fail="+report.getTagOperationFailCount() +
                   "  Total=" + report.getTagOperationTotalCount());
         }
     }
     class MyDeviceEventReportListener implements Device.DeviceEventReportListener {
         public void reportEvent(DeviceEventReport report) {
             if (report.hasGPIEvent())
                 System.out.println("GPI: state="+ report.getGPIEvent().getGpiState());
             if (report.hasOperationEvent())
                 System.out.println("Operation: EventType="+ report.getOperationEvent().getOperationEventType().name());
         }
     }
}
