DMX requires RS485 communication at 500K baud.  The JNIOR 412 DMX handles this inherently.  The JNIOR 410 has the ability to handle RS485.  An additional application must be loaded to get the DMX data to be streamed out the AUX port.  You can read about using the JNIOR 410 and a 412 DMX Alternative.  The downside of this is that there is additional overhead on the JNIOR and that the AUX port is not properly isolated.  In most cases the lack of isolation is not an issue but it could be given certain circumstances.

At the time of writing this article, in 2022, we have found it hard to acquire the components needed to build the 412DMX unit due to supply chain issues and chip shortages.

While using the 410 as a DMX alternative would work, some people like the IO mix on the 412.  So we decided to look at what it would take to use the 412 as a DMX alternative.  It turns out that an RS232 to RS485 adapter with a NULL modem will do the trick.  Here are links to the components that we tested an commanded DMX fixtures with here in the office.

DTECH RS232 to RS485 / RS422 Serial Communication Data Converter Adapter Mini-Size

DB9 Null Modem Adapter Male to Male

The 410 has 8 inputs and 8 outputs, the 412 and 412DMX have 4 inputs and 12 outputs, and the 414 has 12 inputs and 4 outputs. Each digital input can accept AC or DC voltage sources in the 0 – 30 V range. The input voltage must be greater than 2 VDC for the input to register as “on” and then less than 1 VDC to register as “off”. The JNIOR uses a 2-piece terminal connector system for all power and I/O wiring connections allowing for easy installation and/or removal of the JNIOR. Digital Inputs are Optically Isolated.  

Controlling Digital Inputs

When controlling the JNIOR’s I/O, the JANOS class can be used to get/manipulate their statuses. In the following example the JANOS class is used to invert an input and print the input state mask, manipulate an input counter, and check an input’s usage meter.

View on GitHub

I put the built jar file of this example application into the JNIOR’s flash folder and ran it from the Web UI’s console tab. As you can see it displays different data about the inputs at the time of the application running.

Getting Inputs from the IO Log

Another way to interact with the I/O on the JNIOR is via the Iolog Monitor. The Iolog Monitor is an object that can be checked for I/O events that have occurred on the JNIOR. There is the IoEvent class and Iolog class. An IoEvent is when an input or output state changed on the JNIOR, and the Iolog is an object that contains all the IoEvents from a certain timestamp. The example below inverts an input, and then shows how the Iolog has recorded that input pulse as an IoEvent.

View on GitHub

I put the built jar file of this example application into the JNIOR’s flash folder and ran it from the Web UI’s console tab. As you can see it recorded the input change where input 1 turned on and again when it turned back off.

When creating an application, being able to send emails from it may be something a User wants to do. JNIORs have email blocks in their configuration that can be setup to send emails.

Setting Up JNIOR Email

To properly setup an email for the JNIOR to use, you’ll want to use the JNIOR’s Web UI and navigate to the Email Account section under Configuration. Here you’ll want to include the Mail Server, From Address, and SMTP Username your JNIOR will use to send the email. These are required in order to send emails from the JNIOR.

Next, in the Network section you’ll want to make sure you have a DNS Address declared. For our examples we use 8.8.8.8, which is Google’s.

Lastly, we’ll want to make sure we give the address we are sending to to the Mail-Profiles section. Only a ToAddress is needed, but additional information can be entered to be used as a default. This is used for the JANOS.sendmail() class.

Now that this is setup, we can now create an application that can use these settings to send an email. The following example shows two different ways that an email can be sent from an application. The first way uses the JANOS class, and the other uses the MailComposer class.

View on GitHub

I put the built jar file of this example application into the JNIOR’s flash folder and ran it from the Web UI’s console tab. Once its run an email should be sent to the address, subject, and message you declared.

Series 4 JNIOR’s have a file directory that can be interacted with via a command line connection or from the Web UI. Being able to interact with the file directory and read/write files to it can be a useful tool when creating applications, from recording versioning numbers to writing data to reference later. Below is a small example below that writes and then reads to a file.

Directories and File Interaction

To start a file object is declared with the directory of the temp folder and the name of the file we are creating which is “test.log”. We also create another file object called directory and we are going to use this to display all the files located under the flash directory in the JNIOR by. We get the files in the flash directory by assigning the value ‘/flash’ to it, and then using the .list() function we can return a string array of all the files under that directory. We declare a local string array called files and populate it with the file names we just got. Then we go through and print out the name of each one. After this we declare a BufferedWriter to create a FileWriter. The FileWriter is then used to write a string to the test.log file we just declared. Next a BufferedReader is declared to create a FileReader. The FileReader is used to the read whatever data is on the file as a string, and since we just wrote to it, it will print out what we’ve writer to the file.

View on GitHub

Filing Example

I put the built jar file of this example application into the JNIOR’s flash folder and ran it from the Web UI’s console tab. As you can see it, application runs and prints out the text that was written to the file. You can also see the test.log file is created in the temp folder.

There could be a want for an application that performs different functionality, completing multiple operations at the same time. The JNIOR accomplishes this with threading. A thread is a sequence of instructions within a program that can be executed independently of other code. The JNIOR is able to handle threading via the default JAVA library. Below are two quick examples of threading, with one of them using synchronization. 

Non-Synchronized Threading

In this first example, there is a main method that creates two threads, each supplying it an array of words that will be used to create sentences and print them out. Each new thread calls a function called slowStringBuffer, taking the words in their string array’s they’ve been supplied and adding them to the string buffer in that function. Since the threads run at the same time, they add their words to the string buffer simultaneously. This results in nonsense being printed out for the sentences, showing that synchronization in our next example is useful in avoiding this issue.

View on GitHub

I put the built jar file of this example application into the JNIOR’s flash folder and ran it from the Web UI’s console tab. As you can see it, the threads compete against each other to build their sentences, resulting in nonsense being printed out.

Synchronized Threading

In this second example, the only change that is made is that the slowStringBuffer function is made synchronized. This results in one thread taking control first, making sure it prints out its sentence completely before the next thread can start its sentence. This results in two complete sentences being generated.

View on GitHub

I put the built jar file of this example application into the JNIOR’s flash folder and ran it from the Web UI’s console tab. In this example two complete sentences are formed and printed.

JNIORs can connect with other devices via Ethernet connections. Defining a port and IP, the JNIOR can listen or send to a device with those Ethernet settings using the IO and Net classes of the JANOS Runtime library. Receiving data uses a DataInputStream and sending data uses a DataOutputStream. 

TCP

Below is a very short example, that shows a quick reference to the IO class to create a socket to open a DataOutputStream. Once that is open I can send a message to an external device. The socket only requires the IP address and the port number. In this example the IP is 10.0.0.17 and the port is 9222. Once the DataOutputStream is created using the socket, I send a string out it. I use a TCP server I created that listens on that IP and port number to see if it receives the data sent.

View on GitHub

I put the built jar file of this example application into the JNIOR’s flash folder and ran it from the Web UI’s console tab. After it has successfully run, I check my TCP server and see that the information was successfully received.

UDP

Another example of Ethernet control uses a UDP connection versus a TCP connection. Another example is below, using the Datagram Socket and Packet classes from the Java.net package. This creates a UDP connection from the JNIOR to any UDP server listening and sends it a string. 

View on GitHub

Just like before, I put the built jar file of this example application into the JNIOR’s flash folder and ran it from the Web UI’s console tab. After it has successfully run, I check a UDP server I created  and see that the information was successfully received.

Applications can log information they are generating into a .log file to view. This feature can be crucial to some users, letting them be able to monitor data that constantly needs supervision. Log files can roll over as well, which happens when a log file runs out of space. When this occurs, a new empty file with the same name is created to log more data, while the old file that has no more space gets a .bat extension added to the end of the file name. This allows for data to be retained longer before being overwritten. 

To use logging in a software application on the JNIOR, you will need to use the JANOS class of the JANOS runtime library. With it you can define a log file name and what you want to log to it. If the log file exists at the location you specify, it will add what enter to it. If the log file doesn’t exist, it will create the log file, and then log what you enter to it. Below is a short example of creating/adding to a log file that exists in the temp folder of the JNIOR.

View on GitHub

I put the built jar file of this example application into the JNIOR’s flash folder and ran it from the Web UI’s console tab. As you can see after running it, going to the temp directory of the JNIOR shows the loggingExample.log file.

Series 4 JNIORs have a varying amount of inputs and outputs depending on what model you have. The 410 has 8 inputs and 8 outputs, the 412 and 412DMX have 4 inputs and 12 outputs, and the 414 has 12 inputs and 4 outputs. Each relay contact rating is 1A @ 24VDC and the voltage source must be in the range of 5 – 30V AC or DC. The JNIOR uses a 2-piece terminal connector system for all power and I/O wiring connections allowing for easy installation and/or removal of the JNIOR.

Controlling Relay Outputs

When controlling the JNIOR’s I/O, the JANOS class can be used to get/manipulate their statuses. In the following example the JANOS class is used to pulse outputs, get the output states mask, check the status of an output, and check an outputs usage meter.

View on GitHub

I put the built jar file of this example application into the JNIOR’s flash folder and ran it from the Web UI’s console tab. As you can see it displays different data about the outputs at the time of the application running.

Getting Outputs from the IO Log

Another way to interact with the I/O on the JNIOR is via the Iolog Monitor. The Iolog Monitor is an object that can be checked for I/O events that have occurred on the JNIOR. There is the IoEvent class and Iolog class. An IoEvent is when an input or output state changed on the JNIOR, and the Iolog is an object that contains all the IoEvents from a certain timestamp. The example below pulses an output, and then shows how the Iolog has recorded that output pulse as an IoEvent.

View on GitHub

I put the built jar file of this example application into the JNIOR’s flash folder and ran it from the Web UI’s console tab. As you can see it recorded the output change where output 8 turned on and again when it turned back off.

Excluding the 412DMX, each JNIOR model has a COM port (labelled RS-232) and an AUX port (labelled AUX Serial). Both are DB-9F Female 9-pin D-sub connectors. The AUX port has 4 active signals and the COM port 2. The pin assignments are as follows:

2 >> RS232 TX / RS485 TX-
3 << RS232 RX / RS485 RX-
5    GND
7 << RS232 RTS / RS485 RX+
8 >> RS232 CTS / RS485 TX+

Each port provides at least a 3-wire RS-232 interface. A 3-wire connection contains only the Transmit (Tx), Receive (Rx) and Signal Ground (GND) circuits. The  COM port is used for diagnostics, but the AUX port on the 410 is RS-485 capable. These ports can be taken over to send and receive messages from these ports.

Creating a Serial Connection

When creating applications to control a serial port, the Comm and IO classes are what can be used to control them from the JANOS runtime library. Using this class you can create Input and Output streams for either the AUX or COM ports to receive or send out data via the serial ports. Below is a very short example, that shows a quick reference to the Comm class to open the AUX serial port and after establishing an Output Stream sends out a string. I opened a serial connection from my computer using command line and connected to the AUX port of the JNIOR to see if the data went through successfully.

View on GitHub

I put the built jar file of this example application into the JNIOR’s flash folder and ran it from the Web UI’s console tab. After it has successfully run, I checked my serial connection to the AUX port of that JNIOR and saw the message went through.

Serial Connection Output

NOTE: AUX and COM ports can’t be opened more then one time, if they are then a PortInUseException error is thrown. An example of this happening is shown below where a serial port was opened twice.

The available expansion modules for the JNIOR are as follows: the Control Panel, Temperature Probe, Environmental Sensor, 4 Relay Output, 10volt, 4-20ma, and 3 Channel LED Dimmer. These expansion modules all have ways to be manipulated through the JANOS runtime library. Each Expansion Module works on any JNIOR logic controller model and contains the following key features:

  • On-board microprocessor for rapid, effective analog signal sampling
  • Automatic recognition of the module by the main JNIOR logic controller
  • Flexibility to utilize a mix of modules
  • Can be used in addition to the JNIOR temperature sensors
  • Web-based configuration via the main JNIOR web page
  • Easily integrated into all the JNIOR communication methods
  • No separate power supply necessary – all power received via the Sensor Port
  • 2-year warranty

Controlling I/O and Reporting Data

When creating applications to control expansion modules, the SensorPort and JANOS classes are what can be used to control them from the JANOS runtime library. Using this class you can get an expansion modules type, check their inputs, check/set their outputs, get the temperature, set LEDs, and check the external device list of expansion modules. Below is an example, that gets each module connected to the JNIOR, and then reports on their data. 

View on GitHub

I put the built jar file of this example application into the JNIOR’s flash folder and ran it from the Web UI’s console tab. As you can see it prints the expansion modules connected along with info about the data they are reporting.

To update JANOS, the JNIOR Series 4 Operating System, you will need to do two things.

  1. Get the UPD file on the JNIOR in the /temp directory.
  2. Execute the jupdate command. To force the update to happen immediately upon entering this command we will type jrupdate -fup /temp/janos_filename.upd

The easiest way to update the unit remotely is using the DCP The DCP is most likely to be available on a remote JNIOR because it uses a single port for all of the features. Without the DCP you might need port 23 for telnet, port 21 for FTP commands, and many other ports for FTP data.

If the DCP is available follow this procedure.

  1. Once the DCP is open, navigate to the Console tab.
  2. Login to the command console.
  3. Drag and drop the JANOS .upd file into the console window. This automatically stores the file in the /temp directory.
  1. Issue the jrupdate command. Like above, to force the update to happen immediately upon entering this command we will type jrupdate -fup /temp/janos_filename.upd

This post goes over an application that reads inputs being activated as a pattern using their state mask. However many times inputs are triggered within a certain amount of milliseconds between them, those inputs state masks are added to the pattern already there. This continues until there is an input not within the set amount of milliseconds. Then it prints the pattern and begins creating a new one.

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.

After setting up the project, it will require two files. This first one we create is called MultiplexSample, which calls the run function we will create in the second file.

//function runs the application
public class MultiplexSample {

    public static void main(String[] args) {
        
        InputMultiplexer inputMultiplex = new InputMultiplexer();
        inputMultiplex.run();
        
    }
    
}

After that we begin creating the second file called InputMultiplexer. The first thing we include in the project is the import statements. The two imports we use are for IoEvents and the Iolog. We will use these to get the input’s information and process them as patterns.

We then declare the global variables. The first one we declare is the _iolog object. The Iolog keeps track of all IoEvents, including inputs. We will use the IoEvents from the Iolog to grab the information of the inputs when they are activated.

After this is _eventCaptureTime which grabs the start of when the IoEvents are grabbed at the start of each loop through the application.

We then need a long value called _startOfPatternTime. This is the current time of each new input that comes in. We need this because the program loops every 500 seconds, and if 1 input happens right after the loop ends we’ll miss it. The _startOfPatternTime is subtracted from the _eventCaptureTime which helps us check if that input should keep the pattern going.

The _refreshTimestamp value helps us only grab new IoEvents from the Iolog by only grabbing events past its value.

Next is the IoEvent array _ioEvents which contains the inputs we are processing from the Iolog for the current pattern.

We then have the pattern value, which is the pattern we are constantly building from the IoEvents state mask.

Lastly is PATTERN_WINDOW_DURATION which is the value in milliseconds we are looking to see pass between inputs to determine if they are close enough to combine into a new pattern or process as separate ones.

import com.integpg.system.IoEvent;
import com.integpg.system.Iolog;

public class InputMultiplexer implements Runnable {

    //grabs the Iolog to get IoEvents
    private Iolog _iolog = new Iolog();
    //time of the first input to find the start of the input pattern
    private long _startOfPatternTime = 0;
    //time where Iolog is refreshed as to not look at old IoEvents
    private long _refreshTimestamp = _startOfPatternTime;
    //array of IoEvents to evaluate from the Iolog
    private IoEvent[] _ioEvents;
    //value for checking pattern has more IoEvents to process
    private long _eventCaptureTime = 0;
    //input pattern to log
    private int _pattern = 0;
    //duration between inputs required to continue a pattern
    private static final int PATTERN_WINDOW_DURATION = 100;

Next is the run function, which sets the _eventCaptureTime value, calls the other functions we are about to create, and permanently loops the program every 500 seconds. This makes it so the application is constantly checking the Iolog for new IoEvents.

    //function calls other functions to log input pattern in a infinite loop
    @Override
    public void run() {

        while (true) {

            _eventCaptureTime = System.currentTimeMillis();
            getIoEvents();

            lookForIoPattern();

            try {
                Thread.sleep(500);
            } catch (InterruptedException ex) {

            }

        }

    }

Next is the lookForIoPattern function. This function starts with a for loop that will go through all recent IoEvents from the Iolog and processes their states to begin creating a new pattern.

Next the IoEvent states and mask values have an & operation done to get which states have turned high. Next the _startOfPatternTime was set if this was the first input in the pattern. After that _startOfPatternTime would be compared with either the current IoEvent’s timestamp or the _eventCaptureTime value to determine if more inputs need to be added to the pattern. _startOfPatternTime is compared to currentIoEvent’s timestamp to check if timestamps of inputs were within PATTERN_WINDOW_DURATION milliseconds of each other, which in this example is 100 milliseconds. If the 500 milliseconds that the program is looping in ends as another input comes in, then its compared to the _eventCaptureTime value to check if another input came in within 100 milliseconds of the last input, even if the loop ended. This would prevent patterns from getting cut of from one another because of the 500 millisecond loop.

//function checks the IoEvents of the Iolog and evaluates an input pattern
    private void lookForIoPattern() {

        //grabs the IoEvents of the Iolog
        for (int index = _ioEvents.length - 1; index >= 0; index--) {

            IoEvent currentIoEvent = _ioEvents[index];

            System.out.println(currentIoEvent.timestamp);

            //This value shows the state total for the IoEvent
            System.out.println("This is the current I/O state: " + currentIoEvent.states);
            //This value shows which input values were activated for the IoEvent
            int statesTurnedHigh = currentIoEvent.states & currentIoEvent.mask;
            System.out.println("This is the value of statesTurnedHigh: " + statesTurnedHigh + "\n");

            //grabs the start of the input pattern if its hasn't been assigned yet and if enough time passes between IoEvents it evaluates the pattern,
            //otherwise the pattern has an or statement performed on it with the current IO event
            if (statesTurnedHigh != 0) {

                if (_startOfPatternTime == 0) {
                    _startOfPatternTime = currentIoEvent.timestamp;
                    System.out.println("Start of pattern found.");
                }
                if (currentIoEvent.timestamp - _startOfPatternTime > PATTERN_WINDOW_DURATION) {
                    evaluatePattern(_pattern);
                    _startOfPatternTime = currentIoEvent.timestamp;
                    _pattern = currentIoEvent.states;

                } else {
                    _pattern = currentIoEvent.states | _pattern;
                }

            }

        }

        //checks if the pattern is done or if the loop needs to grab more IoEvents
        if (_startOfPatternTime != 0) {

            if (_eventCaptureTime - _startOfPatternTime > PATTERN_WINDOW_DURATION) {

                evaluatePattern(_pattern);
                _startOfPatternTime = 0;
                _pattern = 0;

            }
        }
    }

The last two functions are the evaluatePattern function and the getIoEvents function. The evaluatePattern function simply grabs the pattern created from the lookForIoPattern function and prints it. The getIoEvents function is what is called to grab the most recent IoEvents from the IoLog.

 //prints out the Input Pattern
    private void evaluatePattern(int createdPattern) {

        System.out.println("Pattern is " + createdPattern);

    }



    //grabs IoEvents and puts them into a class level array
    private void getIoEvents() {

        _iolog.refresh(_refreshTimestamp);
        _ioEvents = _iolog.getInputEvents();

    }

}

After adding those last functions, you should now have program that grabs all the inputs activating on the JNIOR, and creates a state pattern depending on how close each input’s timestamp is. Below is the code for the full application. Make sure you set the MultiplexSample file as the main function of your project.

//function runs the application
public class MultiplexSample {

    public static void main(String[] args) {
        
        InputMultiplexer inputMultiplex = new InputMultiplexer();
        inputMultiplex.run();
        
    }
    
}
import com.integpg.system.IoEvent;
import com.integpg.system.Iolog;

public class InputMultiplexer implements Runnable {

    //grabs the Iolog to get IoEvents
    private Iolog _iolog = new Iolog();
    //time of the first input to find the start of the input pattern
    private long _startOfPatternTime = 0;
    //time where Iolog is refreshed as to not look at old IoEvents
    private long _refreshTimestamp = _startOfPatternTime;
    //array of IoEvents to evaluate from the Iolog
    private IoEvent[] _ioEvents;
    //value for checking pattern has more IoEvents to process
    private long _eventCaptureTime = 0;
    //input pattern to log
    private int _pattern = 0;
    //duration between inputs required to continue a pattern
    private static final int PATTERN_WINDOW_DURATION = 100;



    //function calls other functions to log input pattern in a infinite loop
    @Override
    public void run() {

        while (true) {

            _eventCaptureTime = System.currentTimeMillis();
            getIoEvents();

            lookForIoPattern();

            try {
                Thread.sleep(500);
            } catch (InterruptedException ex) {

            }

        }

    }



    //function checks the IoEvents of the Iolog and evaluates an input pattern
    private void lookForIoPattern() {

        //grabs the IoEvents of the Iolog
        for (int index = _ioEvents.length - 1; index >= 0; index--) {

            IoEvent currentIoEvent = _ioEvents[index];

            System.out.println(currentIoEvent.timestamp);

            //This value shows the state total for the IoEvent
            System.out.println("This is the current I/O state: " + currentIoEvent.states);
            //This value shows which input values were activated for the IoEvent
            int statesTurnedHigh = currentIoEvent.states & currentIoEvent.mask;
            System.out.println("This is the value of statesTurnedHigh: " + statesTurnedHigh + "\n");

            //grabs the start of the input pattern if its hasn't been assigned yet and if enough time passes between IoEvents it evaluates the pattern,
            //otherwise the pattern has an or statement performed on it with the current IO event
            if (statesTurnedHigh != 0) {

                if (_startOfPatternTime == 0) {
                    _startOfPatternTime = currentIoEvent.timestamp;
                    System.out.println("Start of pattern found.");
                }
                if (currentIoEvent.timestamp - _startOfPatternTime > PATTERN_WINDOW_DURATION) {
                    evaluatePattern(_pattern);
                    _startOfPatternTime = currentIoEvent.timestamp;
                    _pattern = currentIoEvent.states;

                } else {
                    _pattern = currentIoEvent.states | _pattern;
                }

            }

        }

        //checks if the pattern is done or if the loop needs to grab more IoEvents
        if (_startOfPatternTime != 0) {

            if (_eventCaptureTime - _startOfPatternTime > PATTERN_WINDOW_DURATION) {

                evaluatePattern(_pattern);
                _startOfPatternTime = 0;
                _pattern = 0;

            }
        }
    }



    //prints out the Input Pattern
    private void evaluatePattern(int createdPattern) {

        System.out.println("Pattern is " + createdPattern);

    }



    //grabs IoEvents and puts them into a class level array
    private void getIoEvents() {

        _iolog.refresh(_refreshTimestamp);
        _ioEvents = _iolog.getInputEvents();

    }

}

There has been an update to the Update Project for OS 4.8.

Name Version Release Date Size MD5
Series 3 All-In-One v4.8 Nov 11 2019 251.7 KB ef6a2613188b70725b155c9c026064b3

Browsers no longer support Java Applets.  Therefore, the web files have been removed from the JNIOR in this update. This fixes flash space issues. The applets can still be loaded from within the JNIOR Support Tool.  To load the Applets, right click on the JNIOR  in the Beacon Tab.  Then go to Tools -> Open Classic Monitor, Configure, Control Application.

Sometimes the JNIOR doesn’t appear to be working but follow these steps and you might be able to determine why. There are a few steps that you can take before contacting INTEG or declaring that the JNIOR is not functioning. Hopefully the steps below will help save some time.

The number one way for INTEG to help provide support is to send us a Snapshot using the Support Tool. We can use the Snapshot to look at logs, analyze your configuration and to look at network interactions. Snapshots are most effective when taken soon after the issue is noticed. If too much time has passed the logs and network information may no longer contain relevant information pertaining to the time of the issue.

Power

The JNIOR requires 12 – 24v DC. We recommend a power supply capable of 1 Amp.

The very first thing to check is to make sure the unit has power. No, I don’t mean “did you plug the JNIOR in?” We need to make sure that the internal power supply is functioning and that the wires going in to the connector on the outside of the JNIOR have not broken.

To check the internal power supply we need to verify that the BLUE LED is illuminated next to the power connector.

If the BLUE LED is not illuminated then we want to make sure the wires have not been broken. This can easily happen if there is stress put on the wires during installation or if the connector was not securely fastened before being shipped.

Operating System

Is the OS running? To check this remove power. Upon applying power the amber light next to the BLUE power LED should come on for two or three seconds and then go out. Another thing we can check is to unplug the Ethernet cable. As of JANOS v1.8 the Status LED will blink Morse code indicating the value of the last octet of the IP Address when the Ethernet cable is unplugged.

Ethernet

The first thing to check regarding Ethernet connectivity is that the lights on the Ethernet port are lit. If they are not, please check both end of the cable to make sure it is connected. If the cable appears to be properly connected and the lights are not lit, please try a different cable.

Check Beacon to see that the JNIOR is on the network. Beacon is a feature on the JNIOR that uses UDP to broadcast itself on the network. The JNIOR Support Tool implements beacon and will query the network for any JNIORs. Any JNIOR that hears the query will respond. Because this feature uses UDP a valid working IP Address is not necessary.

If the cable, lights and beacon all appear to be in working order then the last thing to check here is the IpConfig/Allow setting. That will need to be done using the serial port. You can read about that procedure in the Dangers of IpConfig/Allow.

As of JANOS v1.8 the Status LED will blink Morse code indicating the value of the last octet of the IP Address when the Ethernet cable is unplugged.

Serial Port

The serial port can be used to diagnose JNIOR issues. Most of the time the Ethernet connection will be used to do this but in the case that the Ethernet connection is suspect we will need to use the serial port. There are two serial ports on the JNIOR but the RS-232 port is the is the port that facilitates the command line functionality. To connect to the JNIOR for command line use you will need to use the following settings. 115200 baud, 8 data bits, 1 stop bit and no parity. Once the cable is connected and you launched your favorite serial application you will need to press enter to see the login prompt. You could also reboot the JNIOR to observe the banner.

Configuration

If the hardware steps above do not alert you to the issue you are having then configuration is most likely to blame. Please contact us INTEG for further assistance. We can walk you through configuration issues, connect to your computer via TeamViewer, or determine if your unit needs to be replaced.

Depending on the application, something going wrong and stopping it from running could lead to big complications. Thankfully, a watchdog can monitor your application and react how you want it to using the Watchdog class. The watchdog can stop, restart, and report on applications not responding to it and more. Watchdogs have configurable timeframes, and when they aren’t updated before the time frame expires they trigger.

The watchdog is a very powerful concept. Wikipedia says:

watchdog timer (sometimes called a computer operating properly or COP timer, or simply a watchdog) is an electronic timer that is used to detect and recover from computer malfunctions. During normal operation, the computer regularly resets the watchdog timer to prevent it from elapsing, or “timing out”. If, due to a hardware fault or program error, the computer fails to reset the watchdog, the timer will elapse and generate a timeout signal. The timeout signal is used to initiate corrective action or actions. The corrective actions typically include placing the computer system in a safe state and restoring normal system operation.

Usage

The example below is very basic. You will need to adjust the duration and location of the watchdog for your application.

View on GitHub

This is what we see in the log after the unit has come back up.

01/15/19 08:37:36.361, FTP/10.0.0.27:62888 uploaded /flash/WatchdogExample.jar [115.3 kbps] 
01/15/19 08:37:44.081, WatchdogExample started 
01/15/19 08:37:44.203, WatchdogExample activated 
01/15/19 08:38:14.307, WatchdogExample loop finished 
01/15/19 08:38:18.451, ** Assertion: WatchdogExample watchdog triggered reboot (Line 1278) 
01/15/19 08:38:18.483, ** Terminating: System 
01/15/19 08:38:20.971, ** Reboot on assertion: WatchdogExample watchdog triggered reboot (Line 1278) 
01/15/19 08:38:20.997, -- JANOS 410 v1.7.1 initialized (POR: 1546)

Here are the options that are available to choose from when the watchdog expires.  You see that we assign the action in the setAction() method above.  watchdog.setAction(Watchdog.WDT_REBOOT);

WDT_REBOOT

This is the default action. Expiration of the watchdog timer causes the unit to reboot.

WDT_APPLICATION

This action indicates that a watchdog timer expiration is to be handled by the application itself. The system takes no action.

WDT_TERMINATE

When the watchdog timer expires the system will terminate the application.

WDT_BREAK

This interrupts the current application (similar to Ctrl-C interruption) when the watchdog timer expires.

WDT_RESTART

When the watchdog timer expires this will interrupt the current application and restart it.

WDT_MESSAGE

When the watchdog timer expires a WM_WATCHDOG (0x11) message will be sent through the system message pump. The content contains the text associated with the watchdog.

WDT_EVENT

Watchdog timer expiration will notify the first thread in the application that is waiting  for notification using waitOnWatchdogNotify().

This sample shows you how to use the Immutable class. The immutable class represents persistent storage that can be accessed at the low level as an array of primitive types. This information will withstand reboots and application terminations. You can view Immutable data by typing the ‘nv’ command in the command line of a JNIOR. If using only one data type, you can express to create an immutable array of that data type, but if you want your array to have mixed data types inside it, you have to use a byte array. 

Using Immutable Blocks

This example shows the use of an array of longs. The long values in this application are date values that represent when the application was started. The long array is part of an Immutable block, therefore the application start times don’t go away until overwritten or manual removed. This application holds up to the last five application start times.

View on GitHub

I put the built jar file of this example application into the JNIOR’s flash folder and ran it from the Web UI’s console tab. After it has successfully run, I run the application multiple times, and it shows each time it runs a new application start time added to its immutable array.

JANOS supplies a Message Pump wherein messages of various types may circulate between processes.

 

JANOS supplies a Message Pump wherein messages of various types may be circulated between processes or application. These messages may be user defined.
Message numbers below 1024 (0x400) are RESERVED by the system.
The following are the system defined message types.

SM_SHUTDOWN (0x01)

This message is generated by the system prior to shutdown. When received applications MUST forward the message by returning it to the pump and exit in an expeditious fashion. The JNIOR is about to reboot.

SM_PROBE (0x02)

This message is generated by the system periodically. When receive applications MUST forward the message by returning it to the pump. This is used to detect listeners that are no longer responding or that are not properly forwarding messages. The system expects to see this message return to it in a prompt fashion.

SM_GCRUN (0x10)

This message indicates that the Garbage Collection (GC) has completed. When received applications MUST forward the message by returning it to the pump.

SM_WATCHDOG (0x11)

This message is generated by a application watchdog configured to send then message on timer expiration.

SM_SYSLOGMSG (0x12)

System log messages can be sent to an external Syslog Server. This message also passes the log information to listening applications.

SM_PWRLOST (0x20)

When Ride-Thru Power support is available this indicates the lost of external power.

SM_PWRGOOD (0x21)

When Ride-Thru Power support is available this indicates that external power has been restored.

SM_PWRREADY (0x22)

When Ride-Thru Power support is available this indicates that the supply is fully charged and ready to provide maximum holding capacity.

SM_REGUPDATE (0x40)

This message is generated whenever a registry entry is updated or removed. When received application MUST forward the message by returning it to the pump.

SM_WEBSTARTUP (0x60)

Message sent when the Web Server process is activated.

SM_WEBSHUTDOWN (0x61)

Message sent when the Web Server process is terminated.

SM_PROTCMDMSG (0x70)

This message is generated when the JNIOR Protocol receives a custom command message. When received an application MUST either forward the message or provide a SM_PROTCMDRESP response.

SM_PROTCMDRESP (0x71)

This message is generated by an application in response to a SM_PROTCMDMSG command message. It is intended for the JNIOR Protocol server. When received applications MUST forward the message by returning it to the pump.

SM_PIPEOPEN (0x80)

This message is sent by the Web Server when a piped websocket connection has been established. The message contains the client IP Address and Port as well as the target message number.

SM_PIPECLOSE (0x81)

This message is sent by the Web Server when a piped websocket connection has terminated. The message contains the client IP Address and Port as well as the original targeted message number.

SM_USER (0x400)

Lowest allowed user defined message number. Applications that intend to exchange messages SHOULD attempt to define globally unique message identifiers. These must be values from 1024 and up. Message numbers below SM_USER are RESERVED by the system.

INTEG supports the customers’ ability to private label after the sale.  We do not (except under rare special arrangement) handle private labeling for you. This is limited to the front label.  Any removal or alteration to labels on the back of the JNIOR will violate product certifications (TuV, CE, FCC, etc.) and violate our warranties. All labels on the back of the product and internally, including serial numbers and part numbers, must remain in place.  INTEG identification in firmware and in applications developed by INTEG (not under contract) cannot be altered.

The content of any labeling added by customers after the sale is the sole responsibility of the customer. INTEG cannot be held responsible or liable for any concerns that might arise, legal or otherwise, from any modifications made independently by the customer.

To replace the front label you can pop out the 18 light pipes.  These are only press-fit into place and easy to remove by hand. The existing label can be pulled off from any of the corners.  We use a good adhesive but it can be overcome.  Carefully locate your label paying attention to align with each and every light pipe hole. The light pipes can then be pressed by hand back into place.  You may replace the front label with one of your own design that needs no approval from INTEG. The dimensions, especially for the light pipe locations, are critical and it will help to make those holes in the label oversized.  A dimensional drawing is available.

Note that the light pipes generally need only be secure enough to not fall out if the JNIOR is turned upside down and tapped on the table.  If they appear loose and that would be of concern, you can use an extremely tiny drop of glue on the inside of the cover where the light pipe passes through the hole. We used to glue these routinely but have not done so for several years.

Our housings have been updated.  The new housings support a new and improved DIN rail mounting option.  The label area, and therefore the label, has not been changed.  These dimensions are described in the document at the link below.

Just a side note if you use a form of super glue based upon a cyanoacrylate do not place the unit in a sealed bag for 24 hours. The gases from this chemical emitted during the curing process are used to render fingerprints visible. If bagged you will later be able to determine who has handled your JNIOR. We found this out the hard way.

The following PDF details the required label dimensions:

https://jnior.com/download/jnior-front-label-dimensions

 

 

Some devices in a cinema’s ecosystem use HTTP Requests for communication. The JNIOR’s Cinema application can send GET and POST Requests to these devices by defining them in the Macro and Device files. This post will go over how to declare a HTTP Device in Cinema and send commands to it. If this is your first time creating Macro and Device files for the Cinema application, please check out this post first that goes over creating Macro and Device files in general. 

To start, you’ll want to open the JNIOR Support Tool and navigate to the Device Tab. You’ll start by going to the bottom left of the Support Tool and select ‘Add’. This will add a new device configuration to the Device Tab. Here you are then going to declare an HTTP Request device that will represent the device you are going to send HTTP Requests to. For this example I’m going to name it HTTP_Example (The name can’t have any spaces). The device type should be HTTP Request, the IP should be the whatever your device’s IP is set to (I used IP 10.0.0.201 for this example), and the port number should be 80. Once all this is set you should have the following device configuration:

Once you have this, you’ll save this device configuration on your computer (it should automatically open to a directory for you to save it in, but if you change the location make sure you remember where you save it), and then you’ll publish it to the JNIOR you want your HTTP device to receive commands from. Once you do that, you’ll then navigate to the Macro Tab.

On the Macro Tab, the first thing you must do is link your Device file with the Macro file you are going to create, so you can reference the Device you just declared in your Macros. This can be done by selecting the ‘Link Devices’ button at the top of the Macro Tab, and then selecting the Device file wherever you saved it on your computer. You’ll then need to create macros that will execute our actions. Macros can be added to the Macro View by clicking the ‘Add’ button at the bottom left of the Macro Tab. In this example I create two, one for doing a GET called HTTP Get, and one for doing a POST called HTTP Post. Once you have your macros, you’ll then need to create the actions the macros will execute to send to your HTTP device. You’ll add actions using the ‘Add’ button at the bottom of the Macro Tab under the Action View. In this example I name them after the HTTP Requests they are going to perform, one being GET, and one being POST. For these actions, you then set the Device for the actions to the HTTP_Example device you created from your Device file. For the GET action, it should be GET, and for the POST action it should be POST. Lastly for the actions, you enter the commands you need to send to your HTTP device in the Data field. Now that you have your macros and the actions you need them to perform, you just need to add the actions to your macros. To do this, select one of your macros so that it is highlighted, then do the same for the action you want to add to it. Once they both are highlighted, hit the arrow in-between the Macro View and Action View, and it should add the action to the macro. Do this for the other macro and your configuration should look like this:

Now save and publish this Macro file to the JNIOR that should be sending to your HTTP Device. Now when these macros are executed on your JNIOR, they should send the commands you defined to your HTTP device!

This example shows how to connect to a junior using the JnrWebsocket library. It also shows a simple use of the connection listeners.

View on GitHub

The Outputs on the JNIOR can be controlled via the JnrWebsocket protocol.  These commands are sent using the Control Message.

Each “Control” message must contain a “Command” member which may be one of the following valid values:

  • “Toggle”
  • “Close”
  • “Open”
  • “Reset Latch”
  • “Reset Counter”
  • “Reset Usage”

Each “Control” Message must contain a numeric “Channel” member specifying the input/output channel. This parameter is 1-based where the number ‘1’ specifies either the first Digital Input or first Relay Output. This depends on the specific “Command”.

There is no formal response to these command messages although a “Monitor” message will invariably follow some for obvious reasons.

Toggle Command

Close Command

Open Command

Sometimes, most times, things don’t work the first time we code them. We need to dig in to find out what we did wrong. Sometimes it’s as simple as a typo. Sometimes it’s complex logic that needs a little work. The browser has great tools to help you out. Press F12 on your keyboard to open the Developer Tools.

Debugger / Sources

Here is a view of a Firefox browser showing the code for an example that Reads a Registry Key.   You’ll first notice there is nothing on the HTML page.  You need to select the example HTML file in the Debugger tab or Sources in Chrome.

Console

Clicking on Console will show you what output there is from JavaScript.

The built-in functions are great, but sometimes you want to have custom logic running on the JNIOR.  This is a huge benefit of the JNIOR and being able to communicate directly with those applications from a web interface is uniquely powerful.  To take advantage of this feature we must have a unique ID assigned to the application we wish to communicate with.  The web application must make the first communication attempt to that application ID using the Post Message command.  Once that command has been sent, JANOS will subscribe this connection to receive further Reply Message messages from the Java application.  Application IDs must be greater than 1024 and must be unique.

Post Message

We use Post Message to send data from the Web Application to the Java Application.  JANOS will place the Content of the message on the internal Message Pump.  Each Java Application running on the JNIOR will examine the application ID associated with the message.  If the application owns the ID then the application will process the message.

    var message = { Message: 'status.get' };
    jnrwbsocket.postMessage(2010, message);

The above is an example of getting the status from the application when the web application first launches.  Again, this message will cause JANOS to subscribe the WebSocket connection to receive future Reply Messages from this application ID.

Note: You will receive all Reply Message messages from this application.  Even if it is a reply to another WebSocket connections message.  care must be given if you don’t want this to happen.

{{ctrl.getFunctions()}}

Functions

Here is an overview of the available Registry Functions:

  • readRegistryKey (keyName, callback) – Executes the callback when the given registry key’s value is retrieved from the JNIOR
  • value = readRegistryKeyAsync (keyName) – Gets the value of a registry key.  Since this function is a async function, it will wait for the result before returning.
  • readRegistryKeys ([keyArray], callback) – Executes the callback when the given registry key’s values are retrieved from the JNIOR
  • registrySubscription (key, callback) – Executes the callback when the given registry key’s value is retrieved from the JNIOR. The callback is also executed any time there is an update to that registry key value

Read Registry Key

Reading a Registry Key is an asynchronous operation.  We don’t want our page to wait for the response, even though it will be quick.  So again, we need to supply a callback.  Our method syntax is readRegistry(keyName, callback);

This may cause you to structure your application differently if you are waiting for one key’s value before executing another code.

Syntax

// With Callback Function
readRegistryKey (keyName, callbackFn)

// With Inline Callback 
readRegistryKey (keyName, function(keyName, value){ /* ... */ })

Parameters

keyNamestring – The name of the registry key that we want the value of

callbackFnfunction – The function to execute when the value is returned. This can be a reference to a function or an inline anonymous function.

        keyNamestring – The name of the registry key being returned

        valuestring – The value of the registry key being returned

Return Value

None

Example

    jnrWebsocket.readRegistry( '$SerialNumber', function (keyName, value) {
        this.serialNumber = value;
        alert('The Serial Number is: ' + this.serialNumber);
    });

Read Registry Key Async

It would be easier if we could wait for the response without supplying a callback.  Well, now we can for a single key request.  We will call the readRegistryKeyAsync() method.  But it does involve a little more care.  The use of async / await will help us do that.  The await operator must be used in a async method.  It cannot be used in a normal method.  Here is how we would do that.

Syntax

value = readRegistryKeyAsync (keyName)

Parameters

keyNamestring – The name of the registry key that we want the value of

Return Value

valuestring – The value of the registry key being returned.  Applies to the Async version only.

Example

        var getJniorInfo = async function () {
            console.log('serial: ' + await jnrwebsocket.readRegistryKeyAsync('$serialnumber'));
            console.log('model: ' + await jnrwebsocket.readRegistryKeyAsync('$model'));
            console.log('boot time: ' + await jnrwebsocket.readRegistryKeyAsync('$boottime'));
        };

        jnrwebsocket.addOnLoggedInListener(getJniorInfo);

Read Registry Keys

More than likely you will need to read more than one key.  Currently, we have the following code where an array of registry keys is supplied.  The callback is then executed for each key and value returned. 

    var registryKeys = ['$serialnumber', '$model', '$boottime'];
    jnrwebsocket.readRegistryKeys(registryKeys, function (key, value) {
        if ('$serialnumber' == key) SerialNumber = value;
        else if ('$model' == key) Model = value;
        else if ('$boottime' == key) BootTime = value;
    });

In this case, the callback gives you the value but you have work to do to assign or use it correctly.  The real benefit comes in when thought is given to the jnior and the amount of communication that goes on.  It is better to send one request and get one response.  The savings go up with the number of keys requested.

Can this be handled better on the client side?  I’m sure it can.  But how?

What if the callback returned an object of key : value pairs?

    var registryKeys = ['$serialnumber', '$model', '$boottime'];
    jnrwebsocket.readRegistryKeys(registryKeys, function (keys) {
        SerialNumber = keys['$serialnumber'];
        Model = keys['$model'];
        BootTime = keys['$boottime'];
    });

Registry Subscription

Hey, a registry key may change sometime in the future.  I want to know when that happens.  Do I have to keep asking to find out if this happens?

No, you don’t.  You need to only subscribe to the registry key.  Let JANOS and the JNIOR do the rest.  JANOS will keep track of the connection that cares about the registry update and alert it accordingly.

The method declaration and use mimic that of the readRegistryKey() method with the only change being that the callback will get called any time that the registry key changes.

Example HTML File

<html>

<head>
    <script src="Integ/comm.js"></script>
    <script src="Integ/md5.js"></script>
    <script src="Integ/base64.js"></script>
    <script src="Integ/jnrWebsocket.js"></script>

    <script>
        var jnrwebsocket = new JnrWebsocket();
        jnrwebsocket.connect('ws://10.0.0.155');
        jnrwebsocket.enableCommLogging();
        jnrwebsocket.addOnLoggedInListener(function () {

            /** Below is an example of using a callback function called readRegistryKey that gets
            executed when the result of the registry is read from the JNIOR. The parameter for this
            function is the name of the registry key you wish to read. The value returned is the
            value of the registry key. This example reads the registry key $SerialNumber from the
            JNIOR. */
            jnrwebsocket.readRegistryKey('$SerialNumber', function (keyName, value) {
                var serialNumber = value;
                console.log(serialNumber);
            });

            /** Below is an example of using a callback function called readRegistryKeys that gets
            executed when the result of mulitple registry keys are read from the JNIOR. The parameter
            for this function is and array of registry keys you wish to read. The values returned are
            the values of the registry keys. This example reads the registry keys $SerialNumber,
            $Model, and $BootTime from the JNIOR. */
            var registryKeys = ['$SerialNumber', '$Model', '$BootTime'];
            jnrwebsocket.readRegistryKeys(registryKeys, function (keys) {
                console.log(keys['$serialnumber']);
                console.log(keys['$model']);
                console.log(keys['$boottime']);
            });

            /** Below is an example of using a Async function called readRegistryKeyAsync that blocks
            and waits to execute until the result of mulitple registry keys are read from the JNIOR. 
            The parameter for this function is and array of registry keys you wish to read. The values
            returned are the values of the registry keys. This example reads the registry keys 
            $SerialNumber, $Model, and $BootTime from the JNIOR. */
            (async function () {
                console.log('serial: ' + await jnrwebsocket.readRegistryKeyAsync('$SerialNumber'));
                console.log('model: ' + await jnrwebsocket.readRegistryKeyAsync('$Model'));
                console.log('boot time: ' + await jnrwebsocket.readRegistryKeyAsync('$BootTime'));
            });

        });
    </script>
</head>

</html>

All WebSocket connections must be authenticated. The Web Server has a login as part of its functionality. The WebSockets use that login state since the WebSockets is part of the web server. If the login was handled separately we would see a double login. One login to load the html and another to access the websocket connection.

So, if a WebSocket connection is initialized from a page that was fetched from the protected area in the web server and the user logged in, then the WebSocket GET response will contain an AUTH cookie

If an additional login is required then the WebSocket connection will return a 401 Unauthorized response. The JnrWebsocket library will attempt to log in with the default credentials. If you do not want that to happen then please change the default credentials. That is strongly recommended anyway.  You can also remove the default credentials from the javascript library by issuing the setCredentials(username, password) method.  Calling this method and providing undefined for either or both arguments with disable the use of the default login.

    jnrwebsocket.setCredentials(undefined, undefined);

The OnLoggedIn listener is where you should do any initial work that you want to get done when the connection is established. For example, if you want to read some registry keys when the page loads, you will do it when the JnrWebsocket gets authenticated. The reads would fail if you tried to perform them before the connection has authenticated.

The web browser helps make a WebSocket connection easy.

Built-in WebSocket Service

Once a connection to a configured Web Server port (default 80 and 443) is made and upgraded from the default HTTP Protocol to the WebSocket Protocol, traffic must conform to the WebSocket specification. Except in the case discussed in Section 3.2 the JANOS Web Server uses a built-in server to handle all WebSocket messages then received. These must use the JSON format and the connection must be authenticated.

To initialize communications the client should send a blank or empty message. The following is acceptable.

{
  "Message":"" 
}

The connection will proceed depending on the authentication requirements established by the JNIOR configuration and the environment making the connection (browser, application, etc.).

Default Permissions

The Series 3 JNIOR (Models 310, 312, and 314) were shipped where by default web pages were not protected by login. The login requirement encountered when running the applets was the result of security in the JNIOR Protocol. Access to web pages could be controlled by permissions set on individual files or folders. For instance, removing the read attribute (R) from the /flash/www folder would force the browser to ask for login credentials and thus protect the pages. Unfortunately, a second login would then be required by the JNIOR Protocol which has to be separately protected since control and configuration were possible through it. Modifying folder permissions involved a console command (CHMOD) which tended to be unfamiliar to everyone.

The Series 4 JNIOR (Models 410, 412, and 414) use a new Registry key WebServer/Login to control web page access. This key by default is set to TRUE. The dynamic configuration pages therefore also request login credentials but a second login is not required due to the Websocket Protocol implementation which will be discussed in a moment. The WebSocket Protocol replaces the JNIOR Protocol just as the dynamic configuration pages replace the applets that have been dropped. You may still control access to areas of the JANOS website using file and folder permissions if desired. That would only be necessary should you disable the WebServer/Login requirement.

WebServer Login Enabled

With the Web Server Login requirement enabled any access to the JANOS website is challenged using the standard 401 Unauthorized response. The JANOS Web Server provides the necessary parameters so the browser can request the user’s login credentials. If the proper credentials are entered and verified by JANOS the page is promptly served. A session ID is assigned.

Subsequently, the Authorization information is supplied with requests for other pages required from the website. The JANOS Web Server recognizes the association between those credentials and the original login and therefore doesn’t challenge every page. When the browser then moves to open a WebSocket connection it uses the temporary session ID for authentication. A second is not required. This can be done because all of these connections are handled by the Web Server. This is unlike the JNIOR Protocol which is a separate server entirely and cannot be passed shared authentication information.

Once you have authenticated for the website, you can create WebSocket connections in the browser session without an additional login step. Immediately after opening the WebSocket connection, you will receive a “Monitor” message and you are good to go.

WebServer Login Disabled

If you set the WebServer/Login key to FALSE and assuming that permissions on files and folders have not been modified retaining the default Read Access flag, the browser will not need to request your login credentials. When a WebSocket is then made there are no preauthorized credentials. The login handshake in the WebSocket connection will be required before you may proceed using the WebSocket. This behavior assumes that the Websocket/Anonymous registry key has not been defined or is set to 0.

Upon opening the connection a “monitor” message will not be provided. The application needs to send a blank message and will receive the 401 Unauthorized error. The application will then need to request the user’s credentials and calculate the Auth-Digest response on its own. This is the same procedure performed by the browser. The dynamic configuration pages supplied with the JNIOR provide for this requirement. The Javascript can be used for reference.

Once the user credentials are processed the handshake can be completed and will proceed as follows.

{
  "Message":"" 
}

{
  "Message":"Error",
  "Text":"401 Unauthorized",
  "Nonce":"5d894efb48e1c3bc074fe78e7a5f" 
}

{
  "Auth-Digest":"jnior:65f2d1cb66ef63f7d17a764f3a2f2508" 
}

{
  "Message":"Authenticated",
  "Administrator":true,
  "Control":true
}

A “Monitor” message will likely immediately follow. This might even be received before the “Authenticated” message. That is the asynchronous nature of the connection. Please feel free to contact INTEG for assistance in implementing the digest calculation.

Anonymous Operation

If the Websocket/Anonymous registry key is set to a valid user ID (1 is generally the JNIOR Administrator’s ID), then no login will be required. The USERS console command can be used to determine the available user IDs. This, however, is extremely dangerous. Any application can then make a fully functional WebSocket connection. This gives anyone access to the unit with the ability to raise havoc with controls and to modify JNIOR configuration. This is not recommended. If there is physical security, meaning that access is only available to personnel on the local network and all those can be trusted, then this setting may be of use. Otherwise, you are allowing anonymous access to this connection at your own risk.

It is important to note that even if you have WebServer/Login set to TRUE and have to enter a username and password to bring up the website, the WebSocket interface is not secure if anonymous access is enabled. A separate application or copy of the website can get full control of your JNIOR.

With the anonymous key set to a valid user ID, the WebSocket connection will not require login. Immediately after making the connection you will receive the “Monitor” message. The connection is then available for full use.

The JNIOR Web-socket JavaScript Library depends on the INTEG comm.js file. The comm.js file also relies on 2 other JavaScript files. The md5.js file is required for calculating the authentication hash and the base64.js file is required for encoding and decoding file contents.

Your <head> section must include the following lines. The example shows putting the integ files in an integ folder.

<html>
    <head>
        ...

        <script src="integ/base64.js" type="text/javascript"></script>
        <script src="integ/md5.js" type="text/javascript"></script>
        <script src="integ/comm.js" type="text/javascript"></script>
        <script src="integ/jnrwebsocket.js" type="text/javascript"></script>

...

To use the JnrWebsocket we must instantiate an JnrWebsocket object and call connect().

    var jnrWebsocket = new JnrWebsocket();
    jnrWebsocket.connect();

By default the connect() call will build the ws:// URI with the hostname from the server where the code is being hosted. If you want to connect to other JNIORs and not just the one hosting the web app then you can pass in the IP Address of the target JNIOR.

    var jnrWebsocket = new JnrWebsocket();
    jnrWebsocket.connect(ipAddress);

Now What?

Okay? Great, I’m connected to the JNIOR WebSocket Server. Now what can I do?

The short answer: Probably Nothing.

Not what you wanted to hear but it’s only because most likely you need to log in. We find that out by adding an onLoggedIn listener.

There are two ways of doing this which are identical. You can call addEventListener() and supply the type of listener and the callback.

    jnrWebsocket.addEventListener('onLoggedIn', function (json) {
        alert("we're logged in!");
    });

Callback? What is a callback?

You just saw the use of the OnLoggedInListener callback.  So what is a callback?

A callback is, as Mozilla MDN Web Docs says, “A callback function is a function passed into another function as an argument, which is then invoked inside the outer function to complete some kind of routine or action.”

In simple terms, it is a piece of code that gets alerted of an event.  In the case above, the code was alerted when the login was successful.  There are other callback events such as when the login fails, when there was an update to a registry key, when I/O changes, when any message was received from the Web Server, and when there was a reply message from a Java application.

Above you saw the use of the addEventListener() where the type was supplied as well as the callback that will get called.  Note that this is an “add” method and not a “set”.  Multiple callbacks can be defined per event.  So the syntax of the addEventListener is addEventListener( type, callback ).

The addEventListener uses the type to call the correct add*Listener function.  Those are available to you as well.  Here are the available types and the associated add*Listener function that is called.

  • onLoggedIn calls addOnLoggedInListener(callback)
  • onIOChange calls addOnIOChangeListener(callback)
  • onMessage calls addOnMessageListener(listener)
  • onReplyMessage calls addOnReplyMessageListener(listener)

You’ll notice the absence of the registry listener that was mentioned above.  This is because you add the callback to get called specifically for the registry key that was requested.

Easily create your own Web Apps to interact with the JNIOR! The JNIOR WebSockets JavaScript Library is just what the name suggests. It is a library written in Javascript that will aid you in interacting with the JNIOR’s WebSocket Server. The WebSocket server provides access to all of the internal features on the JNIOR including access to the I/O, registry, and file system. You can even pump messages directly to Java applications running on the JNIOR.

The JANOS Web Server listens for connections from clients that are running one of the many popular browser programs. Typically ports 80 and 443 (for secure TLS/SSL communications) are open for connection although those are configurable through the JNIOR Registry. In addition to the default HTTP Protocol a connection may also utilize the Websocket Protocol as described in this document. The Web Server ports are shared by these two protocols. This provides for access to status information and control commands that previously were only available through the JNIOR Protocol. While the JNIOR Protocol remains a viable option for these functions the Websocket approach offers seamless integration into the dynamic web page environment. This capability is new to the Series 4 JNIOR products (Models 410, 412, and 414).

The library discussed below is designed to help you interact with the JNIOR WebSocket server more easily and at a higher level. You can write the web-socket code yourself if you like.

Background

To remotely control the JNIOR you need the ability to obtain I/O status and to affect changes in I/O condition. In the earlier Series 3 JNIOR, this was accomplished through the JNIOR Protocol made available through a TCP/IP connection typically on port 9200. This is a documented binary protocol that requires special programming external to the JNIOR for its use. Care is also required to allow access to the specific port through routers and firewalls. Once successfully implemented the JNIOR Protocol not only provided I/O status and control mechanisms. It also opened access to the JNIOR Registry and thereby the ability to configure and manage the product.

In addition to the JNIOR Protocol, it was also necessary to access the JNIOR Command Line through Telnet. Care again is required to allow access to the Telnet port (Port 23) through routers and firewalls. The Command Line is also accessible using a serial connection to the RS-232 port on the JNIOR. This Console connection provides tools for monitoring I/O status and affecting I/O conditions as well as the use of various kinds of diagnostics. Furthermore, in this environment, the product can be fully configured in all aspects including the network parameters. In addition, this is where application programs can be executed which extend the functionality of the JNIOR product.

Management of the JNIOR also requires the manipulation of files in the local file system. While files may be manipulated through a Console connection transfer to/from an external system is done using FTP. Again care must be taken to allow access to the FTP command port (Port 21) through routers and firewalls. FTP typically opens/accepts data connections which must also be accommodated by the network.

With the introduction of the Series 4 JNIOR running the JANOS operating system, the various I/O and management requirements covered by these other protocols can be additionally handled through a single Web Server connection. Access to the Web Server is typically through ports 80 and 443. The latter connection provides for TLS/SSL up to 256-bit security. While these ports would also need to be accommodated by routers and firewalls this is a much more standard requirement and often routine request for IT personnel. This consolidation of functionality is accomplished using the WebSocket Protocol as specified by the Internet Engineering Task Force (IETF) in combination with JANOS server-side scripting. This can result in a fully functional browser-based dynamic website providing JNIOR monitoring and control. The example is the configuration pages provided with the product. These Javascript[TM] based dynamic web pages have replaced the Java-based applets used by the Series 3 JNIOR products.

Protocol Overview

Most computer languages today accommodate programmatic connection to Web Servers in one fashion or another. It makes sense since the majority of applications developed today involve networking and therefore access to the vast range of data available through the Internet. These web applications needed some form of bi-directional communication between the client and server. For a time programmers attempted to get the job done through an abuse of the HTTP Protocol. A simpler solution has been provided in the form of a WebSocket API which has been quickly accommodated. As a result, most web-based programming environments support Websocket connections and the programmer can utilize them as easily as any other web protocol.

Briefly, the client makes a connection to a JANOS Web Server port. This port expects a valid HTTP connection but is also shared by the WebSocket protocol. Transparently behind the scenes, the connection issues the appropriate HTTP headers requesting an ‘upgrade’ to the WebSocket protocol. When the handshake is complete the connection will be ready to handle bi-directional WebSocket messaging. The JANOS Web Server supports a built-in WebSocket service with messaging that can be used to monitor, control, and manage the Series 4 JNIOR. The built-in service employs JSON message formatting.

To provide additional flexibility the JANOS WebSocket connection can, through a parameter in the URL, be redirected to an application running on the JNIOR. In this case, WebSocket messages are routed through the JANOS inter-process messaging mechanism to the application program. The program uses the same messaging system to provide replies and messages outward through the WebSocket connection. In this fashion, a completely custom messaging system can be implemented.

Security

Any protocol providing control and management functions must employ some form of security preventing unauthorized access and disturbance. In addition to being available through a TLS/SSL secure connection, the built-in JANOS Websocket implementation requires authentication. The authentication handshake must be completed before any operations for monitoring, control, and management will be allowed. This login uses active JANOS user accounts and subsequent operations adhere to the account permissions assigned by the administrator.

To facilitate the seamless use of the WebSocket protocol in the implementation of dynamic web pages a mechanism is provided that utilizes any website authentication completed by the browser to pre-authorize the WebSocket connection. This ensures that only a single entry of login credentials is required to bring up a fully functional and secure dynamic website served by the JNIOR. Note that custom applications running on the JNIOR that serve WebSocket connections are free to implement or ignore any kind of authentication requirement.

The DMX Control Program can receive the command ‘go script_name’ from one or more clients and the DMX Control Program will immediately execute that script.

Port 10000 is ‘listening’ on the JNIOR to receive the command to execute a script. Multiple connections can be made to this port.

A termination string must be sent by the sending device at the end of the command. The termination string required is \r\n – which is a carriage return (0D), line feed (0A)

Below is an example of a device sending a command to the DMX Control Program that makes the connection to port 10000 and maintains the connection.

Here are the commands that can be sent to DMX:

go script_name                              – where script_name is the name of the script to execute

go script_name –r #                       – where ‘r’ means repeat the script # times

go script_name –f                          – where ‘f’ means repeat the script forever

abort script_name                          – stops script_name from running (stops immediately not at end)

abort                                              – stops all scripts that are running

Name Version Release Date Size MD5
JANOS - UPD v2.4.2 Jan 18 2024 969.2 KB b7f240e6fba1075dd1088af9b0ef8087
Series 4 All-In-One Update Project v2.4.2 Jan 18 2024 1.8 MB 293c415caba1ff6d9b9a404be3430cc2
Core JANOS Update Project v2.4.2 Jan 18 2024 1.3 MB a9f55f4bd5dcffbbae9bea07a166534f
JANOS Release Notes v2.4.2 Jan 04 2024 484.7 KB 6db6268661a5caf7294663798282cf52
  • Corrected JANOS runtime resetInputCounter issue
  • Fixed issue with renaming folders with a longer name
  • Improved Flash storage wear-leveling
  • Corrected handling of strings in PHP that contain NUL characters
  • Added PHP chr() function
  • Utilize Gateway as fallback DNS server
  • Fixed JANOS.resetInputCounter() method
  • Performs HTTP redirect if SSL/Required enabled
  • added Ctrl-U foreign language accent substitution

JANOS 2.4.1 Release September 1, 2023

Name Version Release Date Size MD5
JANOS - UPD v2.4.2 Jan 18 2024 969.2 KB b7f240e6fba1075dd1088af9b0ef8087
Series 4 All-In-One Update Project v2.4.2 Jan 18 2024 1.8 MB 293c415caba1ff6d9b9a404be3430cc2
Core JANOS Update Project v2.4.2 Jan 18 2024 1.3 MB a9f55f4bd5dcffbbae9bea07a166534f
JANOS Release Notes v2.4.2 Jan 04 2024 484.7 KB 6db6268661a5caf7294663798282cf52
  • Resolved HELP manual generation paging issue
  • Enhanced TAB auto-fill to work when editing a line
  • Allow you to force context for auto-fill using Ctrl-F and Ctrl-R
  • Fix memory ownership issue with cstring_t
  • Fixed DATE command problem introduced with v2.4
  • Increased ARP database size
  • Corrected issue with Thread.interrupt use before the thread starts
  • Added network performance information to NETSTAT
  • Added bandwidth information to NETSTAT -A
  • Added PS -H showing a history of operation.
  • Added shutdown messages to the system log file.

JANOS 2.4 Release May 3, 2023

  • Added hysteresis to garbage collection to eliminate GC storming
  • Fixed web server memory leak
  • Enhanced command line RM/DEL command to override confirmation on wildcard use
  • Allow multiple commands on a single command line using separators like ';'
  • Implemented command line '|' piping capability
  • Enhanced CAT command with HEAD and TAIL usage to support piping
  • Implemented command line conditional execution && and || syntax
  • Enhanced GC -M and GC -B memory analysis to report Java class information
  • Applications can optionally log to external SYSLOG server
  • Hostname in SYSLOG report includes jrS/N Birthname
  • Corrected direct JMP connection not forwarding console output
  • Corrected direct JMP connection File Read failure
  • Fixed issue with Java Sockets SoTimeout exceptions
  • Improved inter-process messaging to avoid queue assertions
  • Added command line real-time network sniffer with filtering
  • Added Email queue management
  • Corrected REGEX matching issue
  • Eliminated memory leak with JSON decode
  • Fixed Web Authentication. No longer gets stuck in loop.
  • Expanded command line history to 200 commands
  • Eliminated dormant message queue issues
  • Fixed FTPClient class issue with retrieving data
  • Corrected buffer overrun by command line parameters
  • Eliminated null pointer issue in network race condition
  • Enhanced MANIFEST to use optional database
  • Prevent illegal IP address settings blocking network use
  • Corrected buffer overrun caused by security scanners
  • Eliminated Resource Deadlock after assertion

JANOS 2.3 Release February 2, 2023

The release fixed an issue with the Ethernet becoming "locked up". The JNIOR could become unresponsive while servicing the network on busy networks.

Build 1.0

  • Corrected memory issue with KILL and message loop use
  • Corrected garbage collection issue with static classes in the JVM
  • Corrected memory issue with serial port buffer resizing
  • Delayed Java Thread startup to insure completion of initialization
  • Added KILL -A feature to terminate all applications

 

Initial (January 25 2023)

  • Initialized the Working Directory for command line scripting
  • Increased network frame buffers to improve throughput
  • Increased number of available application watchdogs from 8 to 16
  • Added WDT_SILENT so watchdogs can be used to schedule programs and not logged as triggered
  • Updated PS process listings to display pending watchdogs as scheduled execution
  • Improved PING statistics
  • Eliminated assertion in loading classes using InvokeDynamic
  • Eliminated memory leak in JVM class caching
  • Corrected IO signature performance with IO changes
  • Corrected TAB auto-complete issue with second parameter
  • PHP Registry lists now sorted by name
  • Eliminated chance of socket deadlock that would require a hard reboot
  • Added check for network during boot logging to avoid reboot loop

JANOS 2.2 Release June 28, 2022

This release was issued to support manufacturing and component changes forced by supply chain issues. Because of this, an update to the OS was required to handle this change. Units made June 22nd, 2022 or later will NOT be able to roll back to earlier version of JANOS.

  • Corrected bug in creating multidimensional arrays
  • Improved DEFLATE compression performance with binary files
  • Corrected issue with '%' sign when logging to the syslog
  • Fixed dropped serial character when port is closed
  • Added experimental debugging tools

JANOS 2.1.1 Release December 15, 2021

  • This release was issued to support manufacturing and component changes forced by supply chain issues and COVID

JANOS 2.1 Release August 10, 2021

All New Help system. Use the [Help Search] link in the lower right on the JNIOR Web UI.

  • Eliminated external SYSLOG Server related memory leak
  • Corrected Regex issue with the OR operation
  • Corrected PHP ereg() and eregi() functions
  • Implemented a greatly expanded Help System
  • Added PDF MIME type to the WebServer and Email systems
  • Corrected JRMON latched input [R]eset command, no longer affects relays
  • PHP read file access expanded to include ZIP virtual folders
  • Corrected PHP issues with JSON arrays
  • Corrected Order of Precedence issue with PHP mathematical expressions
  • Corrected the operation of Regex '*' and '+' quantifiers when used following a group
  • Corrected RENAME behavior when attempting to alter case of a filename
  • Enabled PHP logical string comparisons ==, !=, <, <=, >, and >=
  • Enhanced security for JANOS-Session-Id cookies
  • Corrected JANOS-Session-Id handling when multiple cookies are present
  • Improved non-volatile aspect of command line history
  • Corrected issue with network capture completion
  • Fixed issue introduced in v2.0 with IpConfig/Allow
  • Corrected issue with using EXIT in the Console tab of the WebUI
  • Added SHA256 (SHA2) to the MANIFEST database
  • Fixed issue resulting in blank Registry keys being displayed
  • Introduced new expanded Help System

JANOS 2.0 Release March 4, 2021

  • Improved serial diagnostics during boot
  • Added DST rules for New Zealand timezones
  • Added File Sharing. Disabled by default
  • Logs prior Registry key values along with changes
  • Enabled NetBIOS name resolution and disabled LLMNR
  • Allow product "Birthname" such as jr817120068 to be always valid in name resolution
  • Corrected Websockets login issue
  • Fixed issue with HTML Email content
  • Added SHA384 and SHA512
  • Added text form of IP address to certificate to appease Microsoft IE
  • Enhanced Registry key settings to inform as to reboot requirements
  • Improved Email error reporting
  • Added Galois/Counter Mode (GCM) to TLS security suites
  • Removed legacy Registry editor
  • JANOS renews its own self-signed certificates
  • Added JSON support to PHP
  • Added Command Line text editor
  • Added Elliptic Curve TLS suites
  • Added BAT file enhancements and scripting support
  • Added the ability to retrieve files from remote servers to JRUPDATE
  • IP address filtering overridden by SAFE MODE
  • Add capture filter information to pcapng capture file
  • PHP scandir() changed to return absolute file path
  • Issue with /etc folder content in scandir() corrected
  • Corrected issue with nested PHP foreach loops
  • Added PHP date and time formatting function date()
  • Console command line history search and selection enhancements
  • Added PING Flood Mode and addressing validation option
  • Corrected issue with ZIP/JAR decompression failing with some large binary files
  • Added support for the standard loopback address range
  • Default WebServer/Path is now /flash/www/config allowing relocation of the default configuration pages
  • Corrected Registry issue with of Type 10 temperature sensors
  • Batch parameter %0 now returns the command from the command line
  • Corrected runtime issue with PHP replacing existing array content
  • Addressed differences in Linux based terminal sessions
  • Extended the ECHO command for use in scripting
  • Added JMP Protocol port for use in defining capture filters
  • Added JMP port and BuildTag to Beacon protocol
  • Corrected PHP @strrpos()@ and syntax shortcomings
  • Enhanced ARC/ZIP/JAR command
  • Improved compatibility with Linux terminal emulators

JANOS 1.9 Release February 3, 2020

Release Notes

We have released JANOS v1.9 which has several changes and bug fixes. Most notably with TCP packet generation. While it is not wrong to send data in multiple TCP packets, many devices incorrectly implement TCP clients and fail when this case arises. This version adjusted the release of socket data to reduce the chances that a message might be split across separate TCP packets. This had been a recent issue with some MODBUS client devices.

  • Added support for Reverse LLMNR allowing network scanners to label IP addresses with hostnames
  • Adjusted the release of socket data to reduce the chances that a message might be split across separate TCP packets
  • Corrected Sockets race condition that caused occasional reception delays and blocking
  • Fixed the incorrect signed display of large input counter values in JRMON and JMP Protocol
  • Adds a BEACON announcement in the event of an IP conflict
  • Improved NONCE management eliminating possible issues in the presence of port scanners
  • Eliminated chance of buffer overrun occurring in FTP transfer
  • Beacon REBOOT now works in all cases
  • Eliminated potential difficulty in obtaining network capture file

JANOS 1.8 Released June 17, 2019

Release Notes

We have released JANOS v1.8 which adds the JMP Protocol. The JANOS Management Protocol (JMP) is essentially the JSON message interface utilized by JANOS Websockets. The JMP Protocol has been exposed on its own TCP/IP port. This encloses the JSON messaging in a JSON array along with the JSON Object length making reception of the messages easy. The JMP Protocol will be used by the QSC Q-SYS JNIOR component.

  • Implements the JANOS Management Protocol JMP
  • Adds "Block" command to JSON interfaces
  • Web Server limits the effects of extremely slow connections.

JANOS 1.7.1 Released December 3, 2018

Release Notes

  • Watchdog no longer causes reboot from foreground execution
  • REGEX Alternation '|' has been corrected to properly work in Group
  • Corrected NULL Pointer write issue when a Group which employs alternation appears at the start of a REGEX expression
  • Resolved message pump memory issue relating to process termination
  • Expand the channel range for setOutputRelay() from 0-11 to 0-15
  • Corrected network capture filtering when an IP address is to be excluded
  • Supports networks using Jumbo Frames
  • Eliminated assertion associated with improper use of '%n' in System.out.printf.

JANOS 1.7 Released July 26, 2018

Release Notes

  • Added ability to load single CA Certificate to be supplied on TLS connection
  • Support TLS Client Certificate Verification on outgoing connections
  • Added legacy PKCS1 support for externally generated certificates
  • Corrected array issue with processing of deferred email transmissions
  • Corrected memory issue with TAB use on the Command Line

JANOS 1.6.5 Released May 22, 2018

  • Corrected FTP listing issue created by the v1.6.4 release
  • Corrected getRegistryList method memory leak
  • Corrected 412DMX light Flickering
  • Corrected 412DMX NAND Flash processing issue
  • Corrected FTP transfer restart issue

Installing the JNIOR Supporter requires a Java Runtime Environment in order to run. To avoid running into any trouble when installing the JNIOR Supporter Tool, we’ve prepared different ways to install the application based off your operating system, so that it will hopefully make it easier to setup. 

Windows

Name Version Release Date Size MD5
JniorSupporterInstaller v1.0 Jan 04 2024 38.9 MB cfa86a8521ed798f5eb37aad3383a644

For Windows, we’ve created an installer that should setup an .exe application and a JRE for it to reference. You’ll download and proceed through the installer, and once finished the Java Supporter should be ready to launch.

When launching the installer, the you’ll first be prompted if want to create a desktop shortcut. This is recommended to make launching the tool easier in the future.

Once that is finished, clicking next will ask you to begin the install. Clicking next will start it.

Once the install is finished, you’ll be given the option to launch the JNIOR Supporter tool immediately after finishing its install. After that, you’ll now have the JNIOR Supporter Tool installed and ready to use.

Linux

Name Version Release Date Size MD5
JNIOR Supporter v1.0 Jan 08 2024 2.3 MB cff040d0e79f9e6b3d45ea59c02c8ef1

With Linux, after downloading the jniorsupport.jar file from above, the commands below can be run in a Linux terminal that will install a valid version of Java.

sudo apt update
sudo apt install default-jdk

Once this is done, we’ll now want to set the execution bit for the .jar file we downloaded. The command below will make the jniorsupport.jar file runnable when you double click it.

chmod +x /path/to/your/file/JniorSupporter-1.0-1.jar

You can also launch the jar file by directly running it from a terminal with the following command.

/path/to/your/file/java -jar JniorSupporter-1.0-1.jar

Name Version Release Date Size MD5
Cinema.jar - Update Project v6.9 Jan 03 2024 545.1 KB 0a2c670e461116768b75288e652c5253
  • [!] Added holdtime to logic to ensure that signals remain in the desired state before executing their configured action.
  • [!] Reimplemented watchdog enabled key.
  • [!] Fix for combining output actions.  A fix in an unreleased 6.7 version did not account for more than 2 outputs.
  • [!] Debugged thread worker issues.
  • [+] Added BarcoSeries4 as a send command: allows device commands to be sent using a raw ethernet device and the send command with the ‘command:’ prefix.

Go to the Cinema.jar Application page for more information. The Cinema Knowledge-base has helpful information on how to use the features in Cinema.jar.

Cinema.jar 6.4 March 28, 2023

Name Version Release Date Size MD5
Cinema.jar - Update Project v6.4 Apr 25 2023 538.7 KB 1ed87c8c86a9f6f5f2ccfaa04daa1918
  • [!] External outputs as triggers beyond output 16
  • [!] Attempted fix for QSC DCP300.  Was sending ZEROS after each command and confusing the QSC when multiple commands were sent.
  • [!] Issue with logging to the errors log
  • [!] Fixed close pulse issue.  this was an issue reading the macro file.
  • [+] Added flush() to raw ethernet

Go to the Cinema.jar Application page for more information. The Cinema Knowledge-base has helpful information on how to use the features in Cinema.jar.

Cinema.jar 6.0 August 8, 2022

Name Version Release Date Size MD5
Cinema.jar - Update Project v6.0 Apr 25 2023 541.1 KB 7d422aae79bbe4d01eaa428a7f423b5e
  • [!] Handle ROUT 17 - 24 as internal macro action
  • [!] Only start the iolog monitors if we have listeners configured
  • [+] Add Doremi as a device
  • [+] Allow device commands to be sent using a raw ethernet device and the send command with the 'command:' prefix

Go to the Cinema.jar Application page for more information. The Cinema Knowledge-base has helpful information on how to use the features in Cinema.jar.

Cinema.jar 5.0 March 30, 2022

Name Version Release Date Size MD5
Cinema.jar - Update Project v5.0 Mar 30 2022 547.3 KB 6a1f8c4c9f470ccd303133aa10401579
  • [!] Ignoring white-space around schedule keys.
  • [!] Schedule keys no longer require a reboot when changed or added. removed schedules will require a reboot
  • [!] Fixing an issue with embedding quotes in macro action data field
  • [!] Allow comma delimited list of macros for input triggers
  • [!] A macro in a macro list can be delayed since the start of executing the list or the execution of the last macro
  • [!] Updating the http request to handle https responses better
  • [+] Added a UDP Client listener
  • [+] Added a device test event handler
  • [+] Added Web Pages for Cinema to make testing macros and editing registry keys easier.  Access by going to http://JNIOR_IP/cinema

Go to the Cinema.jar Application page for more information. The Cinema Knowledge-base has helpful information on how to use the features in Cinema.jar.

Cinema.jar 4.5 December 21, 2020

Name Version Release Date Size MD5
Cinema.jar - Update Project v6.9 Jan 03 2024 545.1 KB 0a2c670e461116768b75288e652c5253

4.0, 4 oct 2019

  • [+] added code to detect barco series 4 device and launch the barco pulse rpc application.

4.1, 03 dec 2019

  • [!] trim unwanted spaces.

4.2, 04 mar 2020

  • [!] fixed cp+8=1000 signed issue.

4.3, 29 apr 2020

  • [!] changing the logging to use .bak files.  the addition of the logarchiver application will compress the .bak files into zip archives.
  • [!] forcing cinema_ prefix on all log files"),

 4.4, 17 nov 2020

  • [!] Modified the macro web handler to get the list of loaded macros"),
                

4.5, 10 dec 2020

  • [!] Fixed issue working with outputs > 20.
  • [+] rolled the barco pulse api into cinema.jar.

Go to the Cinema.jar Application page for more information. The Cinema Knowledge-base has helpful information on how to use the features in Cinema.jar.

Cinema.jar 3.6 August 14, 2019

Name Version Release Date Size MD5
Cinema.jar - Update Project v3.6 Aug 14 2019 334.6 KB d96d4ae9b9adc4f0b8cdaf9bd87518f3

+ Adding web handlers for getDevice without a device for internal io getAll.

Cinema.jar 3.5 June 2, 2019

Name Version Release Date Size MD5
Cinema.jar - Update Project v3.5 Jun 02 2019 327.0 KB 57a834f2c5ac177b7b19b6dec52350ce

+ Added HTTP POST method to Macro Actions.

+ Added the ability the use HTTPS for GETs and POSTs

Cinema.jar 3.4.1 May 29, 2019

  Cinema.jar - Update Project v3.4.1 [ May 28 2019, 320.47 KB, MD5: 74f51ea7ccb40962eb2118bf16457c50 ]

  • Released May 28 2019

! Fixed a bug where the watchdog was no longer working. If the Cinema application crashed it would not be restarted.

 

Cinema.jar 3.4.0 May 16, 2019

  Cinema.jar - Update Project v3.4 [ May 16 2019, 320.36 KB, MD5: 63b627ede9c8a79710ddb3d7fd3ca852 ]

  • Released May 16 2019

+ Allow you to query the temperature sensor via a HTTP Request.  A JSON representation of the device will be returned.

As of now the only available devices are Type28 and Type7E...

Type28 is the temperature probe and Type7E is the environmental sensor.

To enable this you will need to set the AppData/Cinema/WebServer/Port registry key. The JNIOR will need to be rebooted after this key has been changed. In this example I chose 8081. Port 80 or 443 is normally the default web server port. This web server port is an additional web server that cinema is hosting to handle these types of requests.

When configuring JNIORs, how you should configure them depends on what Series JNIOR you have. You’ll want to use the JNIOR Web Page for Series 4 JNIORs, and the Java Applet for Series 3 JNIORs.

JNIOR Web Page
Java Applet

The Java Applet is a local Java application that can be launched from the Support Tool for each Series 3 JNIOR, while the JNIOR Web Page is a browser accessible configuration for Series 4 JNIORs.  Series 3 JNIORs can’t open the JNIOR Web Page because they don’t support the necessary web files required to run the JNIOR Web Page from it. The Java Applet at one point was accessible from a browser, but due to security risks it was changed to be a separate application. Series 4 JNIORs do have the necessary files to open both the Java Applet and the JNIOR Web Page, but you should not use the Java Applet for Series 4 JNIORs. The applets cannot properly configure a Series 4 as the registry settings for many configuration settings are different than what the Series 3 used.

All JNIORs have the ability to boot into a state called Safe Mode. Safe Mode enables the default ‘jnior’ ‘jnior’ username and password for logging in, and disables all applications from running on boot. This is extremely useful in situations where you either forgot your JNIOR log-in, or have an application that is locking up your JNIOR before you can access it. Here is how to boot your JNIOR in Safe Mode.

NOTE: Do not leave your JNIOR in Safe Mode after you are done using it. Safe Mode’s features can interrupt the JNIOR’s functionality when left on.

Power Off and Disconnect the JNIOR

Before attempting to boot your JNIOR in Safe Mode, make sure your JNIOR is disconnected, and that no power is being supplied to it. This helps ensure the JNIOR is not damaged, and leads into rebooting the JNIOR after we enabled Safe Mode.

Locate A Jumper From Outputs 1 or 2

The first thing we need to do is grab a Jumper off of the JNIOR. You’ll start by unscrewing the JNIOR’s lid and locating the Jumpers on outputs 1 and 2. These outputs have Jumpers on them because they are able to be set to normally opened or closed. You’ll want to vertically pull one of these Jumpers off the output pins they are attached to. (These should just pull off by grabbing the plastic ends sticking out off the Jumpers.)

Locate Hole for Safe Mode Jumper

Every JNIOR has a small opening between its Ethernet port and RS-232 serial port. In this small opening are two pins that can have a jumper placed on them to force the JNIOR to boot in Safe Mode.

Plug Jumper Into Safe Mode Pins

Now taking the Jumper, you are going to slide it into the hole, and plug the Jumper into the two pins on the board in front of the small opening. Once the Jumper is in place, and resupply power to it.

Check if JNIOR is in Safe Mode

Once the JNIOR is powered back on, the only way to check if the JNIOR is successfully in Safe Mode is by making a command line connection to the JNIOR, and seeing if it says *SAFE MODE in the boot dialog. If this gets displayed, you have successfully booted the JNIOR in Safe Mode!

Once you are finished making changes in Safe Mode, make sure disconnect power to the JNIOR again, move the Jumper you used back to the output it was taken from, and screw the lid back on the JNIOR.

What is an escape sequence?

From Wikipedia, an escape sequence is a combination of characters that has a meaning other than the literal characters contained therein.  Ab Escape Sequence starts with a backslash (\) and is followed by a character.  The most common Escape Sequences would be \r for carriage return and \n for linefeed.  These are usually used to denote a break between commands.  Some Escape Sequences can require additional information to be included in the sequence.

It is important to understand that these escape sequences get converted before sending the bytes.  The escape sequences differ from device to device and the correct sequence is defined by the device you are sending from.  One device might want a carriage return entered as \r, like the JNIOR, and another might want it entered as \0d

What Escape Sequences are available?

\0: NULL
\r: Carriage Return
\n: Linefeed
\b: Backspace
\t: Tab
\\: Backslash
\”: Double Quote
\x##: HEX value

Here we see the example where the \x requires two more digits to be entered following the \x.  These digits are hexadecimal digits (0-9, a-f, A-F).  Capitalization does not matter.  Any value can be entered as a HEX value.  For instance, \r has a decimal value of 13 or a hexadecimal value of 0d and can be entered as \x0d.  The lowercase letter k has a hexadecimal value of 6b and can be entered as \x6b.  It is much easier to use printable characters where you can.  Printable characters and escape sequences can be intermixed.

Sometimes a double quote (“) cannot be entered because it has another meaning.  For example, when declaring a string we start and end that string with a double quote.  Entering a double quote in the middle of that string would confuse the code about where the string should actually end.  In this case, we can escape that interior double quote.

Special Note about Commas

Commas in Cinema Actions are special.  Unfortunately, the macro file is stored in CSV format.  That means all fields are separated by commas.  Entering a comma in the data field for an action will confuse the whole macro file.  The prevent confusion you should escape the comma and use the hexadecimal value \x2c.

Special Note about Double Quotes

Double quotes are also special in Cinema Actions.  At one time they were used as in the above example to define strings.  Double quotes should always be escaped.  There is a special escape sequence for double quotes, \",  where there are not for commas.

The Cinema Migration Tool is an application that copies a Cinema Setup from a Series 3 JNIOR and loads it on a Series 4 JNIOR. All that’s needed is a snapshot from the Series 3 JNIOR, and the Cinema Migration Tool will use the configuration files inside it to format that Series 3 JNIOR’s Cinema setup on a Series 4 JNIOR. This tool should make moving Cinema setups from Series 3 JNIORs to Series 4 JNIORs much easier. Here is a brief walkthrough on how to use the Cinema Migration Tool.

Name Version Release Date Size MD5
Cinema Migration Tool v1.0 Nov 09 2023 536.3 KB 2433b01bbc7cf107c9e5c275f271aca3

Load the Series 3 Snapshot

To start, once you’ve downloaded the zip file, you’ll want to open it and run the cinema-series3-upgrade.exe application within it. (Don’t unzip). Then as mentioned previously, the Cinema Migration Tool requires that you take a Snapshot of the Series 3 JNIOR whose configuration you are trying to copy over. Once you have the snapshot, you’ll then select the Open Series 3 Snapshot button, where you’ll navigate to the snapshot on your PC and open it in the Cinema Migration Tool.

NOTE: When opened, the device file, macro file, and jnior.ini file should say they are found in the Cinema Migration Tool. If they are not found, this means the pathing to the files in the snapshot isn’t incorrect. Make sure not to unzip or alter snapshots after they’ve been taken.

Publish Configuration to Target Series 4 JNIOR

Once the snapshot is loaded, next you’ll want to enter the IP of the JNIOR you are trying to publish this configuration to. Make sure this JNIOR is on the same network as your PC. Once entered, hitting run will start the Cinema Migration Tool in publishing the Cinema configuration to the Series 4 JNIOR. 

The Cinema Migration Tool will state when it is done at the bottom of its dialog. Once finished, the Cinema Migration Tool can be immediately run again to publish to another JNIOR.

Confirm Your Setup

To make sure this has worked, you can check by going to your Series 4 JNIOR’s web page and navigating to the Folder tab. Once there, check that your root folder contains the device and macro file from your Series 3 Snapshot, along with making sure the Cinema.jar application exists in the flash folder. If this is the case, then you’ve successfully moved your configuration from the Series 3 to the Series 4 JNIOR! If this isn’t the case, INTEG support would like to help you out. You can reach out to us by joining our online chat, or by emailing our support at support@integpg.com.