A JNIOR application for setting the Volume on the Control Panel

The JNIOR Control Panel is shipped with a ‘click’ sound that plays when a switch is pressed. This gives immediate feedback to the user that the panel has power and that the software is running normally and is ready to accept the press. There are times when the panel is used in a situation where the ‘click’ may not want to be heard. In this situation we may want to turn off that sound. The following application will accomplish this goal.


To run this application you need to download it from the button and load it on your JNIOR. Applications are generally loaded in the flash directory. To run it simply type the command as you see it above.

  ControlPanel Application JAR [ Mar 27 2019, 7 KB, MD5: c573b4c989ea0380729fecae5283e937 ]

In the following code you will notice two classes. The main class of interest here is the ControlPanel class. This class will load the arguments into a ParameterGroup class so that we can process different commands at some point as well as there specific options. For now our command line is pretty simple but we set this application up for the future.


package com.integ;

import com.integpg.sensor.SensorPort;
import com.integpg.system.JANOS;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.Hashtable;

/**
 * This application will allow you to set the volume of the control panel click
 */
public class ControlPanel {

    private static final String USAGE_STRING = "CONTROLPANEL\n\n"
            + "Options:\r\n"
            + "  -VOLUME volume     Sets the volume level to a value between 0% and 100%\n"
            + "\n"
            + "Set options for the control panel";



    public static void main(String[] args) {
        // load the arguments into our parameters class
        ParameterGroups parameters = new ParameterGroups(args);

        // if the paremters are empty or there is a -help parameter then print the usage string and exit
        if (parameters.isEmpty() || parameters.containsParameterGroup("help")) {
            System.out.println(USAGE_STRING);
            return;
        }

        // go through each parameter and process it
        while (parameters.hasMoreParameters()) {
            String parameterGroupName = parameters.getNextParameterGroup();
            ArrayList parameterOptions = parameters.getParameterOptions(parameterGroupName);

            switch (parameterGroupName) {
                case "volume":
                    try {
                        // process set volume
                        processSetVolume(parameterOptions);
                    } catch (Exception ex) {
                        System.out.println(ex.getMessage());
                    }
                    break;

                default:
                    System.out.println("unknown parameter: " + parameterGroupName);
                    return;

            }
        }

    }



    private static void processSetVolume(ArrayList options) {
//        ArrayList volumeArguments = _parameters.get("volume");
        if (0 == options.size())
            throw new RuntimeException("must specify a volume parameter between 0% and 100%.");

        int volume;
        try {
            // get the volume from the arguments.  allow the user to enter a double but 
            // save the integer part
            volume = Double.valueOf(options.get(0)).intValue();
            if (0 > volume || 100 < volume) throw new Exception();
        } catch (Exception ex) {
            throw new RuntimeException("invalid volume specified: '" + options.get(0)
                    + "', volume parameter must be between 0% and 100%.");
        }

        // go through the external devices and set the volume for any connected control panels
        for (long externalModuleAddress : getExternalAddresses()) {
            // get a string representation of the address
            String addressString = getAddressString(externalModuleAddress).toUpperCase();

            // determine the type of module and handle accordingly
            if (0xfa == (externalModuleAddress & 0xff)) {

                try {
                    byte[] writeBlock = getSetVolumeWriteBlock((int) (volume * 2.55));
                    SensorPort.writeDeviceBlock(externalModuleAddress, writeBlock);

                    // lets print the result to the screen as well as the syslog
                    String result = String.format("Panel at %s set volume to %d percent", addressString, volume);
                    System.out.println(result);
                    JANOS.syslog(result);
                } catch (IOException ex) {
                    throw new RuntimeException(
                            String.format("unable to write to the control panel: %s.", addressString));
                }
            }
        }

    }



    private static long[] getExternalAddresses() {
        try {
            // query the unit for an array of external module addresses
            return SensorPort.externalDeviceList();
        } catch (IOException ex) {
            throw new RuntimeException("unable to get external device list.");
        }
    }



    private static String getAddressString(long address) {
        String addressString = "0000000000000000" + Long.toHexString(address);
        return addressString.substring(addressString.length() - 16);
    }



    private static byte[] getSetVolumeWriteBlock(int volume) {
        // the write block for the control panel is 20 bytes
        byte[] bytes = new byte[20];

        // to set the volume we only need to set the command byte and the audio volume byte
        bytes[10] = 4; // set audio volume command
        bytes[11] = (byte) volume; // audio volume level

        return bytes;
    }
}


/**
 * A class for interpreting command line arguments into parameter groups
 */
class ParameterGroups {

    private final Hashtable> _parameters = new Hashtable<>();
    private Enumeration _enumeration;



    public ParameterGroups(String[] args) {
        // parse the arguments
        ArrayList options = null;
        for (int i = 0; i < args.length; i++) {
            String arg = args[i].toLowerCase();

            if (arg.charAt(0) == '-') {
                while (arg.charAt(0) == '-') {
                    arg = arg.substring(1);
                }
                options = new ArrayList<>();
                _parameters.put(arg, options);

            } else if (options != null) {
                options.add(arg);

            } else {
                System.out.println("Illegal parameter usage");
                return;

            }
        }
        _enumeration = _parameters.keys();
    }



    public boolean isEmpty() {
        return 0 == _parameters.size();
    }



    public boolean containsParameterGroup(String paramterGroup) {
        return _parameters.containsKey(paramterGroup);
    }



    public String getNextParameterGroup() {
        if (null == _enumeration) _enumeration = _parameters.keys();
        if (_enumeration.hasMoreElements()) {
            return _enumeration.nextElement();
        } else {
            return null;
        }
    }



    ArrayList getParameterOptions(String parameterGroupName) {
        return _parameters.get(parameterGroupName);
    }



    boolean hasMoreParameters() {
        return _enumeration.hasMoreElements();
    }

}


Once the ParameterGroups class has been instantiated with our command line arguments we loop through each parameter group. When we find the “volume” parameter group we call processSetVolume() and pass in the parameter options.

        // go through each parameter group and process it
        while (parameters.hasMoreParameters()) {
            String parameterGroupName = parameters.getNextParameterGroup();
            ArrayList<String> parameterOptions = parameters.getParameterOptions(parameterGroupName);

            switch (parameterGroupName) {
                case "volume":
                    try {
                        // process set volume
                        processSetVolume(parameterOptions);
                    } catch (Exception ex) {
                        System.out.println(ex.getMessage());
                    }
                    break;

                default:
                    System.out.println("unknown parameter: " + parameterGroupName);
                    return;

            }
        }

Now that we are inside the processSetVolume() method we need to validate the options provided. We make sure that a volume was provided and that it is a valid number between 0% and 100%.




    private static void processSetVolume(ArrayList<String> options) {
//        ArrayList<String> volumeArguments = _parameters.get("volume");
        if (0 == options.size())
            throw new RuntimeException("must specify a volume parameter between 0% and 100%.");

        int volume;
        try {
            // get the volume from the arguments.  allow the user to enter a double but 
            // save the integer part
            volume = Double.valueOf(options.get(0)).intValue();
            if (0 > volume || 100 < volume) throw new Exception();
        } catch (Exception ex) {
            throw new RuntimeException("invalid volume specified: '" + options.get(0)
                    + "', volume parameter must be between 0% and 100%.");
        }

...


Now that the options have been validated and we processed the assigned volume we are ready to write to the connected control panels. We loop through each connected panel and check to make sure it is a Control Panel which is type 0xFA. If it is a Control Panel we can get the write block and send it to the Sensor Port.


        // go through the external devices and set the volume for any connected control panels
        for (long externalModuleAddress : getExternalAddresses()) {
            // get a string representation of the address
            String addressString = getAddressString(externalModuleAddress).toUpperCase();

            // determine the type of module and handle accordingly
            if (0xfa == (externalModuleAddress & 0xff)) {

                try {
                    byte[] writeBlock = getSetVolumeWriteBlock((int) (volume * 2.55));
                    SensorPort.writeDeviceBlock(externalModuleAddress, writeBlock);

                    // lets print the result to the screen as well as the syslog
                    String result = String.format("Panel at %s set volume to %d percent", addressString, volume);
                    System.out.println(result);
                    JANOS.syslog(result);
                } catch (IOException ex) {
                    throw new RuntimeException(
                            String.format("unable to write to the control panel: %s.", addressString));
                }
            }
        }
By | On March 27, 2019 2:28 pm | No Comments | Categorized in: , ,