Multiplexing Application February 12, 2020

This post goes over how to handle needing more then 4 inputs, when there are only 4 on the JNIOR (This application creates three new inputs). Using multiple inputs being activated at the same time, we can count them as new inputs. This application will be able to send macros using these additional inputs we create.

Below is the code for the full application. Make sure to have properly setup the project before using this code, to learn how to setup a custom java application on the JNIOR, a link is here.

import com.integpg.system.IoEvent;
import com.integpg.system.Iolog;
import com.integpg.system.JANOS;
import java.io.DataOutputStream;
import java.net.Socket;
import java.util.ArrayList;
import java.util.Date;

public class TestProject {

    //Used to get List of IO events
    public static Iolog _iolog = new Iolog();
    //Used to keep track of when to refresh Iolog
    public static long refresh_timestamp = 0;
    //Tracks commands that have the correct states to send a macro
    public static int timesCalled;
    //String Array for loading symbol
    public static String[] loadSymbol = {"|", "/", "-", "\\"};
    //loadSymbol's tracker
    public static int loadTracker = 0;

    public static long timeCheck = System.currentTimeMillis();
    
    public static ArrayList<IoEvent> ioevents = new ArrayList<>();

    public static ArrayList<EventInfo> ioEventClass = new ArrayList<>();

    public static class EventInfo {

        int macronumber;
        long timestamp;
        int mask;
        int inputstates;

        EventInfo(int macroNumber, long timeStamp, int Mask, int state) {
            // initialize the input variable from main 
            // function to the global variable of the class 
            macronumber = macroNumber;
            timestamp = timeStamp;
            mask = Mask;
            inputstates = state;
        }
        
        void setMacroNumber(int macroNumberChange) {
            
            if (macroNumberChange == 1) {
                macronumber = 1;
            } else if (macroNumberChange == 2) {
                macronumber = 2;
            } else if (macroNumberChange == 4) {
                macronumber = 3;
            } else if (macroNumberChange == 8) {
                macronumber = 4;
            } else if (macroNumberChange == 3) {
                macronumber = 5;
            } else if (macroNumberChange == 6) {
                macronumber = 6;
            } else if (macroNumberChange == 12) {
                macronumber = 7;
            }
            

            
        }



    }

    public static void createConnectionAndSendMacro(String address, int port) throws InterruptedException {

        String macro = "";
        byte[] macroToBytes;

        try {
            Socket socket = new Socket(address, port);
            DataOutputStream out = new DataOutputStream(socket.getOutputStream());
            System.out.print("Connected " + new Date() + " ");

            for (int index = 0; ioEventClass.size() > index;) {
                
                System.out.println("timeCheck: " + timeCheck + " - Event timestampe " + ioEventClass.get(index).timestamp + " = " + (ioEventClass.get(index).timestamp -  timeCheck));

                if ((ioEventClass.get(index).timestamp -  timeCheck) >= 50) {
                    
                    timeCheck = System.currentTimeMillis();

                    if (ioEventClass.get(index).macronumber > 0 && ioEventClass.get(index).macronumber < 8) {
                        macro = "run Input " + ioEventClass.get(index).macronumber;
                        System.out.println(" " + macro);
                        macroToBytes = macro.getBytes();
                        out.write(macroToBytes);
                        ioEventClass.remove(index);
                        ioevents.remove(index);
                    } else {
                        System.out.println("Macro number invalid, no execution");
                        ioEventClass.remove(index);
                        ioevents.remove(index);
                    }
                } else {

                    System.out.println("Macro is too new, holding info in ioEventClass to get complete macro.");
                    break;
                    
                }
            }

            out.flush();
            out.close();
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    public static void getEventInfo() {

        _iolog.refresh(refresh_timestamp);
        IoEvent[] ioEvents = _iolog.getInputEvents();

        //loop to send macros if their states match correct input states
        for (int index = ioEvents.length - 1; index >= 0; index--) {

            IoEvent ioEvent = ioEvents[index];

            if (ioEvent.states >= 0 && ioEvent.states < 13) {
                int statesTurnedHigh = ioEvent.states & ioEvent.mask;

                if (0 != statesTurnedHigh) {

                    System.out.println("statesTurnedHigh; " + statesTurnedHigh);
                    if (0 < ioevents.size()) {
                        System.out.println("path 1");
                        IoEvent lastIoEvent = ioevents.get(ioevents.size() - 1);
                        long elapsedtime = ioEvent.timestamp - lastIoEvent.timestamp;
                        System.out.println("elapsedtime; " + elapsedtime);
                        if (elapsedtime >= 20) {
                            System.out.println("path 1-1");
                            ioevents.add(ioEvent);
                            addEventInfoToList(ioevents.get(ioevents.size() - 1));
                        } else {
                            System.out.println("path 1-2");
                            lastIoEvent.states |= statesTurnedHigh;
                            ioEventClass.get(0).setMacroNumber(lastIoEvent.states | statesTurnedHigh);
                        }
                    } else {
                        System.out.println("path 2");
                        ioevents.add(ioEvent);
                        addEventInfoToList(ioevents.get(ioevents.size() - 1));
                    }
                }

                refresh_timestamp = ioEvents[0].timestamp;

            }
        }

        if (!ioevents.isEmpty()) {

            System.out.println("ioevents; " + ioevents.size());
            for (int increment = 0; increment < ioevents.size(); increment++) {
                System.out.println("ioevents info " + ioevents.get(increment).states + " " + ioevents.get(increment).timestamp);
            }

        }

    }

    public static void addEventInfoToList(IoEvent iologEvent) {
        int macroNumber = 0;

        if (iologEvent.states == 1) {
            macroNumber = 1;
        } else if (iologEvent.states == 2) {
            macroNumber = 2;
        } else if (iologEvent.states == 4) {
            macroNumber = 3;
        } else if (iologEvent.states == 8) {
            macroNumber = 4;
        } else if (iologEvent.states == 3) {
            macroNumber = 5;
        } else if (iologEvent.states == 6) {
            macroNumber = 6;
        } else if (iologEvent.states == 12) {
            macroNumber = 7;
        } else {
            System.out.println("Macro number not correct");
        }

        EventInfo eventInfoPlaceholder = new EventInfo(macroNumber, iologEvent.timestamp, iologEvent.mask, iologEvent.states);
        ioEventClass.add(eventInfoPlaceholder);

    }

    public static void main(String[] args) throws InterruptedException {

        //Making sure all lists are cleared of previous information
        _iolog.refresh();
        ioevents.clear();
        ioevents.clear();
        
        //Making sure that Registry keys are set to make socket connection
        String IP = JANOS.getRegistryString("IpConfig/IPAddress", "Went to default");
        int portNumber = JANOS.getRegistryInt("AppData/Cinema/CinemaServerClient/TcpPort", 5000);
        if (portNumber == -1) {
            System.out.println("TcpPort number not set properly, closing application.");
            System.exit(0);
        }
        System.out.println(IP);
        System.out.println(portNumber + "\n");

        while (true) {

            System.out.print("\r                                                                                                            ");
            if (loadTracker > 3) {
                loadTracker = 0;
            }
            System.out.print("\r" + loadSymbol[loadTracker]);
            loadTracker++;
            System.out.print(" [" + timesCalled + "] ");
            timesCalled++;

            Thread.sleep(300);
            getEventInfo();
            if (ioevents.isEmpty() == false) {
                createConnectionAndSendMacro(IP, portNumber);
            }

        }

    }

}

After setting up the project, the first part of the project is calling the right imports and setting the global variables. The _iolog is where to get our list of IOevents to see what inputs are being selected at any time. The refresh_timestamp is so that when we call the _iolog, its only getting the list from the last time we called the _iolog and not the entire list every time its called. The timesCalled is to track how many successful macros have been sent. The loadSymbol is used to create a a loading symbol as the JNIOR waits for inputs to be triggered. Lastly, the loadTracker is to show when the end of the loadSymbol list has been reached to rest it.

import com.integpg.system.IoEvent;
import com.integpg.system.Iolog;
import com.integpg.system.JANOS;
import java.io.DataOutputStream;
import java.net.Socket;
import java.util.ArrayList;
import java.util.Date;

public class TestProject {

    //Used to get List of IO events
    public static Iolog _iolog = new Iolog();
    //Used to keep track of when to refresh Iolog
    public static long refresh_timestamp = 0;
    //Tracks commands that have the correct states to send a macro
    public static int timesCalled;
    //String Array for loading symbol
    public static String[] loadSymbol = {"|", "/", "-", "\\"};
    //loadSymbol's tracker
    public static int loadTracker = 0;

    public static long timeCheck = System.currentTimeMillis();
    
    public static ArrayList<IoEvent> ioevents = new ArrayList<>();

    public static ArrayList<EventInfo> ioEventClass = new ArrayList<>();

Moving on we have multiple functions, starting with EventInfo.

The EventInfo constructor grabs all the _iolog information along with the states of the inputs being converted from 1 to 7 . The function setMacroNumber grabs the current state of the inputs on the JNIOR and converts it to the input number 1 – 7

        EventInfo(int macroNumber, long timeStamp, int Mask, int state) {
            // initialize the input variable from main 
            // function to the global variable of the class 
            macronumber = macroNumber;
            timestamp = timeStamp;
            mask = Mask;
            inputstates = state;
        }

        void setMacroNumber(int macroNumberChange) {
            
            if (macroNumberChange == 1) {
                macronumber = 1;
            } else if (macroNumberChange == 2) {
                macronumber = 2;
            } else if (macroNumberChange == 4) {
                macronumber = 3;
            } else if (macroNumberChange == 8) {
                macronumber = 4;
            } else if (macroNumberChange == 3) {
                macronumber = 5;
            } else if (macroNumberChange == 6) {
                macronumber = 6;
            } else if (macroNumberChange == 12) {
                macronumber = 7;
            }
                        
        }

The next function is createConnectionAndSendMacro. This function takes the address and port number you specify and create a tcp connection on it. This will be connected to the Cinema application to create the macros from the inputs triggered. This function goes through the list of IOevents and sends through the tcp connection any of the 1 – 7 states its looking for. Then it closes the connection.

 public static void createConnectionAndSendMacro(String address, int port) throws InterruptedException {

        String macro = "";
        byte[] macroToBytes;

        try {
            Socket socket = new Socket(address, port);
            DataOutputStream out = new DataOutputStream(socket.getOutputStream());
            System.out.print("Connected " + new Date() + " ");

            for (int index = 0; ioEventClass.size() > index;) {
                
                System.out.println("timeCheck: " + timeCheck + " - Event timestampe " + ioEventClass.get(index).timestamp + " = " + (ioEventClass.get(index).timestamp -  timeCheck));

                if ((ioEventClass.get(index).timestamp -  timeCheck) >= 50) {
                    
                    timeCheck = System.currentTimeMillis();

                    if (ioEventClass.get(index).macronumber > 0 && ioEventClass.get(index).macronumber < 8) {
                        macro = "run Input " + ioEventClass.get(index).macronumber;
                        System.out.println(" " + macro);
                        macroToBytes = macro.getBytes();
                        out.write(macroToBytes);
                        ioEventClass.remove(index);
                        ioevents.remove(index);
                    } else {
                        System.out.println("Macro number invalid, no execution");
                        ioEventClass.remove(index);
                        ioevents.remove(index);
                    }
                } else {

                    System.out.println("Macro is too new, holding info in ioEventClass to get complete macro.");
                    break;
                    
                }
            }

            out.flush();
            out.close();
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

Next is the getEventInfo function. This function creates a list of IOevents from the _iolog. Then by going through the list and seeing which values are not within 20 milliseconds of each other and depending on where they are in the list, grab those values from the IOevent and use them in other functions to determine which macro to run.

    public static void getEventInfo2() {

        _iolog.refresh(refresh_timestamp);
        IoEvent[] ioEvents = _iolog.getInputEvents();

        //loop to send macros if their states match correct input states
        for (int index = ioEvents.length - 1; index >= 0; index--) {

            IoEvent ioEvent = ioEvents[index];

            if (ioEvent.states >= 0 && ioEvent.states < 13) {
                int statesTurnedHigh = ioEvent.states & ioEvent.mask;

                if (0 != statesTurnedHigh) {

                    System.out.println("statesTurnedHigh; " + statesTurnedHigh);
                    if (0 < ioevents.size()) {
                        System.out.println("path 1");
                        IoEvent lastIoEvent = ioevents.get(ioevents.size() - 1);
                        long elapsedtime = ioEvent.timestamp - lastIoEvent.timestamp;
                        System.out.println("elapsedtime; " + elapsedtime);
                        if (elapsedtime >= 20) {
                            System.out.println("path 1-1");
                            ioevents.add(ioEvent);
                            addEventInfoToList(ioevents.get(ioevents.size() - 1));
                        } else {
                            System.out.println("path 1-2");
                            lastIoEvent.states |= statesTurnedHigh;
                            ioEventClass.get(0).setMacroNumber(lastIoEvent.states | statesTurnedHigh);
                        }
                    } else {
                        System.out.println("path 2");
                        ioevents.add(ioEvent);
                        addEventInfoToList(ioevents.get(ioevents.size() - 1));
                    }
                }

                refresh_timestamp = ioEvents[0].timestamp;

            }
        }

        if (!ioevents.isEmpty()) {

            System.out.println("ioevents; " + ioevents.size());
            for (int increment = 0; increment < ioevents.size(); increment++) {
                System.out.println("ioevents info " + ioevents.get(increment).states + " " + ioevents.get(increment).timestamp);
            }

        }

    }

The addEventInfoList converts the current input states to an input number 1 – 7 similar to setMacroNumber, but returning all the IOevent information unlike setMacroNumber does.

public static void addEventInfoToList(IoEvent iologEvent) {
        int macroNumber = 0;

        if (iologEvent.states == 1) {
            macroNumber = 1;
        } else if (iologEvent.states == 2) {
            macroNumber = 2;
        } else if (iologEvent.states == 4) {
            macroNumber = 3;
        } else if (iologEvent.states == 8) {
            macroNumber = 4;
        } else if (iologEvent.states == 3) {
            macroNumber = 5;
        } else if (iologEvent.states == 6) {
            macroNumber = 6;
        } else if (iologEvent.states == 12) {
            macroNumber = 7;
        } else {
            System.out.println("Macro number not correct");
        }

        EventInfo eventInfoPlaceholder = new EventInfo(macroNumber, iologEvent.timestamp, iologEvent.mask, iologEvent.states);
        ioEventClass.add(eventInfoPlaceholder);

    }

Lastly, the main function of the program starts by choosing which IP and tcp port number need to be connected to, by having it set in the registry. Then after the loadingSymbol is setup, the functions getEventInfo and createConnectionAndSendMacro get called.

 public static void main(String[] args) throws InterruptedException {

        //Making sure all lists are cleared of previous information
        _iolog.refresh();
        ioevents.clear();
        ioevents.clear();
        
        //Making sure that Registry keys are set to make socket connection
        String IP = JANOS.getRegistryString("IpConfig/IPAddress", "Went to default");
        int portNumber = JANOS.getRegistryInt("AppData/Cinema/CinemaServerClient/TcpPort", 5000);
        if (portNumber == -1) {
            System.out.println("TcpPort number not set properly, closing application.");
            System.exit(0);
        }
        System.out.println(IP);
        System.out.println(portNumber + "\n");

        while (true) {

            System.out.print("\r                                                                                                            ");
            if (loadTracker > 3) {
                loadTracker = 0;
            }
            System.out.print("\r" + loadSymbol[loadTracker]);
            loadTracker++;
            System.out.print(" [" + timesCalled + "] ");
            timesCalled++;

            Thread.sleep(300);
            getEventInfo2();
            if (ioevents.isEmpty() == false) {
                createConnectionAndSendMacro(IP, portNumber);
            }

        }

    }
By | On February 12, 2020 3:52 pm | No Comments | Categorized in: , ,