de.audiogrid.devices.rs232.service.SerialIO.java Source code

Java tutorial

Introduction

Here is the source code for de.audiogrid.devices.rs232.service.SerialIO.java

Source

package de.audiogrid.devices.rs232.service;/*
                                           * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
                                           *
                                           *       THIS MATERIAL IS PROPRIETARY  TO  EDUARD VAN DEN BONGARD
                                           *       AND IS  NOT TO BE REPRODUCED, USED OR  DISCLOSED  EXCEPT
                                           *       IN ACCORDANCE  WITH  PROGRAM  LICENSE  OR  UPON  WRITTEN
                                           *       AUTHORIZATION  OF  EDUARD VAN DEN BONGARD
                                           *
                                           *       COPYRIGHT (C) 2013 EDUARD VAN DEN BONGARD
                                           *
                                           * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
                                           */

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

import de.audiogrid.devices.rs232.framework.BaseSerialIO;
import de.audiogrid.devices.rs232.framework.NoPortConnectedException;
import de.audiogrid.devices.rs232.framework.SerialPortDetector;
import de.audiogrid.devices.rs232.model.RS232Device;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

public class SerialIO extends BaseSerialIO {

    private int delay = 750;
    Log log = LogFactory.getLog(getClass());

    HashMap<String, RS232Device> model = new HashMap<String, RS232Device>();
    ArrayList<String> ids = new ArrayList<String>();

    static SerialIO instance;

    static {
        instance = new SerialIO();
    }

    public static SerialIO getInstance() {
        return instance;
    }

    public static void destroyInstance() {
        instance.closeConnection();
        instance = null;
    }

    private SerialIO() {
        SerialPortDetector detector = new SerialPortDetector();
        try {
            setPortId(detector.checkForDevice(new RS232Configuration(null)));
            if (!isOpen())
                openConnection();
        } catch (NoPortConnectedException ex) {
            log.debug("No device found");
        } catch (Exception e) {
            log.error("unable to open connection", e);
        }
    }

    public int getDelay() {
        return delay;
    }

    public void setDelay(int delay) {
        this.delay = delay;
    }

    public void prepare() {
        sendData("$STANDBY OFF$\r\n");
    }

    public ArrayList<RS232Device> getIDs() {
        prepare();

        try {

            Thread.sleep(delay);
        } catch (InterruptedException ex) {
            //do stuff
        }

        String deviceIdentifier = sendData("$ID ?$\r\n");

        // check if an ID is pollable
        if (deviceIdentifier.contains("KINOS") || deviceIdentifier.contains("UNIDISK")) {
            log.info("found id that can be polled, " + deviceIdentifier);
            poll(null);
        } else if (deviceIdentifier.contains("LR2")) {
            // there can only on RoomAmp2 per serial connection, so we reduce it to LR2
            log.info("found id that can be NOT polled, " + deviceIdentifier);
            //String processedDeviceIdentifier = trimIDs(deviceIdentifier);
            ids.add("LR2");
            RS232Device d = createDevice("LR2", false);
            model.put("LR2", d);

        } else if (deviceIdentifier.contains("IRT")) {
            // some Roomamps do have 2 IDs, there can only on RoomAmp2 per serial connection, so we reduce it to LR2
            log.info("found id that can be NOT polled, " + deviceIdentifier);
            //String processedDeviceIdentifier = trimIDs(deviceIdentifier);
            ids.add("LR2");
            RS232Device d = createDevice("LR2", false);
            model.put("LR2", d);

        } else {
            log.info("found and unknown id, " + deviceIdentifier);
            String processedDeviceIdentifier = trimIDs(deviceIdentifier);
            ids.add(processedDeviceIdentifier);
            RS232Device d = createDevice(processedDeviceIdentifier, false);
            model.put(processedDeviceIdentifier, d);
        }

        // now we need to check if we have UNIDISK SC's connected. It's not possible to do that during polling,
        // as additional commands are not allowed.
        if (model.keySet().contains("UNIDISK")) {
            log.info("found an UNIDISK in the chain");
            RS232Device tmpDevice = model.get("UNIDISK");
            //assuming that there is only one UNIDISK in the chain
            if (isUNIDISKSC()) {
                log.info("UNIDISK device is an UNIDISKSC, removing old one, adding new one");
                tmpDevice.setIdentifier("UNIDISKSC");
                model.remove("UNIDISK");

                model.put("UNIDISKSC", tmpDevice);
            }
        }
        // populate devices first
        getDevices();

        return new ArrayList<RS232Device>(model.values());
    }

    public void poll(String currentDevice) {
        if (currentDevice == null) {
            log.info(sendData("$POLL START$\r\n"));
            String deviceIdentifier = sendData("$POLL ID$\r\n");
            deviceIdentifier = trimIDs(deviceIdentifier);
            log.info(deviceIdentifier);
            if (deviceIdentifier == null || deviceIdentifier.length() == 0)
                deviceIdentifier = "NO_MORE_POLLING";
            else {
                log.info("adding device to ids");
                ids.add(deviceIdentifier);
                RS232Device d = createDevice(deviceIdentifier, true);
                model.put(deviceIdentifier, d);
            }

            poll(deviceIdentifier);
        } else if (currentDevice.equalsIgnoreCase("NO_MORE_POLLING")) {
            log.info(sendData("$POLL DONE$\r\n"));
        } else {
            log.info(sendData("@" + currentDevice + "@$POLL SLEEP$\r\n"));
            String deviceIdentifier = sendData("$POLL ID$\r\n");
            deviceIdentifier = trimIDs(deviceIdentifier);
            log.info(deviceIdentifier);
            // if result is empty, then there is no device left to be polled
            if (deviceIdentifier == null || deviceIdentifier.length() == 0)
                deviceIdentifier = "NO_MORE_POLLING";
            else {
                log.info("adding device to ids");
                ids.add(deviceIdentifier);
                RS232Device d = createDevice(deviceIdentifier, true);
                model.put(deviceIdentifier, d);
            }

            poll(deviceIdentifier);
        }
    }

    private boolean isUNIDISKSC() {
        // only UNIDISKSC responds with data, UNDISK will fail
        String result = sendData("@UNIDISK@$VOL ?$\r\n");
        log.info("isUNIDISKSC:" + result);
        if (result.contains("FAIL"))
            return false;
        else
            return true;
    }

    private RS232Device createDevice(String deviceIdentifier, boolean isPollable) {
        log.info("creating RS232Device for id " + deviceIdentifier);
        RS232Device d;

        d = new RS232Device();

        d.setIdentifier(deviceIdentifier);

        if (isPollable) {
            d.setDaisyChain(true);
            //need to set path to UNIDISK
            if (deviceIdentifier.contains("UNIDISK"))
                d.setPath("@UNIDISK@");
            else
                d.setPath("@" + deviceIdentifier + "@");
        } else {
            d.setDaisyChain(false);
            d.setPath("");
        }
        return d;
    }

    public ArrayList<RS232Device> getDevices() {
        //getIDs();

        for (String s : model.keySet()) {
            RS232Device d = populateDevice(s);
            log.info(d);
            model.put(s, d);
        }
        return new ArrayList<RS232Device>(model.values());
    }

    public RS232Device getDeviceByID(String deviceIdentifier) {
        log.info("get device for " + deviceIdentifier + " is " + model.get(deviceIdentifier));
        // the device is not yet filled here, so we need to query the device first.
        return model.get(deviceIdentifier);
    }

    /**
     * @todo need to parse response correctly and return correct status
     */
    public int issueCommand(String deviceIdentifier, String command, String value, String zone, boolean iseql) {
        String data;
        RS232Device device = model.get(deviceIdentifier);
        String response = sendData("$STANDBY OFF$\r\n");
        log.info(response);
        // setting zone
        // This is only needed for roomamp 2
        if (zone != null && zone.trim().length() > 0) {
            response = sendData("$ORIGIN " + zone + "$\r\n");
            log.info(response);
            try {

                Thread.sleep(delay);
            } catch (InterruptedException ex) {
                //do stuff
            }
        }

        String eql;
        if (iseql)
            eql = " = ";
        else
            eql = " ";

        data = device.getPath() + "$" + command + eql + value + "$\r\n";

        response = sendData(data);

        HashMap<String, String> formattedResult = responseParser(response);
        setDeviceData(device, formattedResult);
        model.put(deviceIdentifier, device);

        return 0;
    }

    public RS232Device queryDevice(String deviceIdentifier, String command) {
        String data, response;
        RS232Device device = model.get(deviceIdentifier);

        data = device.getPath() + "$" + command + " ?$\r\n";

        response = sendData(data);
        HashMap<String, String> formattedData = responseParser(response);
        setDeviceData(device, formattedData);
        model.put(deviceIdentifier, device);

        return device;

    }

    public RS232Device populateDevice(String deviceIdentifier) {
        log.info("trying to find device for id " + deviceIdentifier + " in " + model);
        RS232Device device = model.get(deviceIdentifier);

        String result = "";
        ArrayList<String> commands = getType(deviceIdentifier);

        for (String command : commands) {
            try {

                Thread.sleep(delay);
            } catch (InterruptedException ex) {
                //do stuff
            }
            if (device.isDaisyChain())
                result = sendData(device.getPath() + command);
            else
                result = sendData(command);

            HashMap<String, String> formattedResult = responseParser(result);

            setDeviceData(device, formattedResult);
        }

        return device;
    }

    public ArrayList<String> getType(String deviceIdentifier) {
        if (deviceIdentifier.equalsIgnoreCase("KINOS"))
            return commandsForKINOS_STATUS();
        else if (deviceIdentifier.equalsIgnoreCase("UNIDISK"))
            return commandsForUNIDISK_STATUS();
        else if (deviceIdentifier.equalsIgnoreCase("UNIDISKSC"))
            return commandsForUNIDISKSC_STATUS();
        else if (deviceIdentifier.equalsIgnoreCase("LR2"))
            return commandsForLR2_STATUS();
        else
            return commandsForLR2_STATUS();
    }

    private final static ArrayList<String> commandsForAMP_STATUS() {
        ArrayList<String> commands = new ArrayList<String>();
        commands.add("$VOL ?$\r\n");
        commands.add("$BAL ?$\r\n");
        commands.add("$BAS ?$\r\n");
        commands.add("$TRB ?$\r\n");
        commands.add("$MUTE ?$\r\n");
        return commands;
    }

    private final static ArrayList<String> commandsForVERSION_STATUS() {
        ArrayList<String> commands = new ArrayList<String>();
        commands.add("$VERSION SOFTWARE ?$\r\n");
        commands.add("$VERSION HARDWARE ?$\r\n");
        return commands;
    }

    private ArrayList<String> commandsForLR2_STATUS() {
        log.info("returning commands for RoomAmp2");
        ArrayList<String> commands = new ArrayList<String>();

        commands.addAll(commandsForVERSION_STATUS());

        commands.add("$ORIGIN ?$\r\n");
        commands.add("$LISTEN ?$\r\n");
        commands.add("$COUNTER POWER$\r\n");
        commands.add("$COUNTER MAINS$\r\n");
        commands.add("$STATUS$\r\n");

        commands.addAll(commandsForAMP_STATUS());

        return commands;
    }

    private ArrayList<String> commandsForKINOS_STATUS() {
        log.info("returning commands for KINOS");
        ArrayList<String> commands = new ArrayList<String>();
        commands.add("$IR ?$\r\n");
        commands.add("$OSG ?$\r\n");
        commands.add("$QUIET ?$\r\n");

        commands.addAll(commandsForVERSION_STATUS());

        commands.add("$VOLUME LIMITS$\r\n");
        commands.add("$[BALANCE|BALANCE_LR] ?$\r\n");
        commands.add("$[BALANCE|BALANCE_LR] LIMITS$\r\n");
        commands.add("$LIPSYNC ?$\r\n");
        commands.add("$ LIPSYNC LIMITS$\r\n");
        commands.add("$SPEAKER SIZE speaker ?$\r\n");
        commands.add("$SPEAKER CALIBRATE speaker ?$\r\n");
        commands.add("$SPEAKER CALIBRATE LIMITS$\r\n");
        commands.add("$SPEAKER TRIM speaker ?$\r\n");
        commands.add("$SPEAKER TRIM LIMITS$\r\n");
        commands.add("$SURROUND ?$\r\n");
        commands.add("$INPUT PROFILE ?$\r\n");
        commands.add("$INPUT PROFILE LIMITS$\r\n");
        commands.add("$INPUT AUDIO ?$\r\n");
        commands.add("$INPUT VIDEO ?$\r\n");
        commands.add("$VIDEO PROGRESSIVE_SCAN [?|mode]$\r\n");
        commands.add("$VIDEO WATCH_DEFAULT [?|mode]$\r\n");
        commands.add("$RECORD ?$\r\n");
        commands.add("$PINKNOISE ?$\r\n");
        commands.add("$SYSTEM VOLUME ?$\r\n");
        commands.add("$SYSTEM STATUS$\r\n");
        commands.add("$COUNTER POWER ?$\r\n");
        commands.add("$COUNTER MAINS ?$\r\n");
        commands.add("$12V_TRIGGER number ?$\r\n");
        commands.add("$FAN ?$\r\n");

        commands.addAll(commandsForAMP_STATUS());

        return commands;
    }

    private ArrayList<String> commandsForUNIDISK_STATUS() {
        log.info("returning commands for UNIDISK");
        ArrayList<String> commands = new ArrayList<String>();
        commands.add("$IR ?$\r\n");

        commands.addAll(commandsForVERSION_STATUS());

        commands.add("$MODE?$\r\n");
        commands.add("$TRACK ?$\r\n");
        commands.add("$TRACK TOT$\r\n");
        commands.add("$CHAPTER ?$\r\n");
        commands.add("$CHAPTER TOT$\r\n");
        commands.add("DISCINFO ?$\r\n");
        commands.add("NAMEINFO ?$\r\n");
        commands.add("NAMEINFO TRACK ?$\r\n");
        commands.add("NAMEINFO ARTIST ?$\r\n");
        commands.add("NAMEINFO ALBUM ?$\r\n");
        commands.add("$TIME ?$\r\n");
        commands.add("$PROGRAM ?$\r\n");
        commands.add("$REPEAT ?$\r\n");
        commands.add("$LAYER ?$\r\n");
        commands.add("$DISCID ?$\r\n");
        commands.add("$DISCTOC ?$\r\n");
        commands.add("$OPTION DISPLAY ?$\r\n");
        commands.add("$COUNTER POWER ?$\r\n");
        commands.add("$COUNTER MAINS ?$\r\n");

        commands.add("$OPTION IR_COMMANDS ?$\r\n");
        commands.add("$OPTION IR_RC5_OUT ?$\r\n");
        commands.add("$OPTION RC5_IN_OUT ?$\r\n");

        commands.add("$STATUS$\r\n");
        return commands;
    }

    private ArrayList<String> commandsForUNIDISKSC_STATUS() {
        log.info("returning commands for UNIDISK SC");
        ArrayList<String> commands = new ArrayList<String>();
        commands.add("$IR ?$\r\n");

        commands.addAll(commandsForVERSION_STATUS());

        commands.add("$MODE$\r\n");
        commands.add("$TRACK ?$\r\n");
        commands.add("$TRACK TOT$\r\n");
        commands.add("$CHAPTER ?$\r\n");
        commands.add("$CHAPTER TOT$\r\n");
        commands.add("DISCINFO ?$\r\n");
        commands.add("NAMEINFO ?$\r\n");
        commands.add("NAMEINFO TRACK ?$\r\n");
        commands.add("NAMEINFO ARTIST ?$\r\n");
        commands.add("NAMEINFO ALBUM ?$\r\n");
        commands.add("$TIME DISC TOT$\r\n");
        commands.add("$TIME TRACK TOT$\r\n");
        commands.add("$TIME ?$\r\n");
        commands.add("$PROGRAM ?$\r\n");
        commands.add("$REPEAT ?$\r\n");
        commands.add("$LAYER ?$\r\n");
        commands.add("$DISCID$\r\n");
        commands.add("$DISCTOC$\r\n");

        commands.add("$COUNTER POWER ?$\r\n");
        commands.add("$COUNTER MAINS ?$\r\n");
        commands.add("$STATUS$\r\n");
        commands.add("$OPTION RS232_EVENTS ?$\r\n");
        commands.add("$OPTION RS232_STARTUP_MESSAGE ?$\r\n");

        // only SC
        commands.add("$LISTEN ?$\r\n");

        commands.addAll(commandsForAMP_STATUS());

        commands.add("$SURROUND ?$\r\n");
        commands.add("$TV TYPE ?$\r\n");
        commands.add("$SPEAKER SIZE FRONT ?$\r\n");
        commands.add("$SPEAKER SIZE CENTRE ?$\r\n");
        commands.add("$SPEAKER SIZE SURROUND ?$\r\n");
        commands.add("$SPEAKER SIZE SUBWOOFER ?$\r\n");
        commands.add("$SPEAKER TRIM FRONT_LEFT ?$\r\n");
        commands.add("$SPEAKER TRIM FRONT_RIGHT ?$\r\n");
        commands.add("$SPEAKER TRIM CENTRE ?$\r\n");
        commands.add("$SPEAKER TRIM SURROUND_LEFT ?$\r\n");
        commands.add("$SPEAKER TRIM SURROUND_RIGHT ?$\r\n");
        commands.add("$SPEAKER TRIM SUBWOOFER ?$\r\n");
        commands.add("$ASPECTRATIO ?$\r\n");
        commands.add("$NTSCTYPE ?$\r\n");
        commands.add("$CHANNELSETUP ?$\r\n");
        commands.add("$SPDIFOUTPUT ?$\r\n");
        commands.add("$PRIMARYDISPLAYDEVICE ?$\r\n");
        commands.add("$CLOSEDCAPTIONS ?$\r\n");
        commands.add("$DOWNMIX ?$\r\n");
        commands.add("$LPCMOUTPUT ?$\r\n");
        commands.add("$DUALMONO ?$\r\n");
        commands.add("$MIDNIGHTMOVIE ?$\r\n");

        //Knekt
        commands.add("$OPTION KNEKT_MODE ?$\r\n");
        commands.add("$OPTION KNEKT_AUDIO ?$\r\n");
        // returns only failures
        //commands.add("$OPTION KNEKT_LFE ?$\r\n");

        return commands;
    }

    private void setDeviceData(RS232Device device, HashMap<String, String> formattedResult) {
        for (Map.Entry<String, String> entry : formattedResult.entrySet()) {
            String key = entry.getKey();
            String value = entry.getValue();
            device.addContent(key, value);
        }
    }

    private String trimIDs(String id) {
        String[] b = id.split("\n");
        for (String c : b) {
            if (c != null && c.trim().length() > 1) {
                if (c.startsWith("!$ID") || c.startsWith("!$POLL ID")) // found ID Line
                {
                    //!$ID KINOS$
                    //!$POLL ID KINOS$
                    //!$POLL ID UNIDISK$
                    c = c.replace("!$ID", "");
                    c = c.replace("!$POLL ID", "");
                    c = c.replace("$", "");
                    log.info(c);
                    return c.trim();
                }
            }
        }
        return "";

        /*
         !
            
        !$STANDBY OFF$
            
        !
            
        !$ID KINOS$
            
            
         */
        /*
        !
            
        !$POLL START$
            
        !
            
        !$POLL ID KINOS$
            
            
         */
        /*
         #KINOS#!
            
        #KINOS#!$POLL SLEEP$
            
        !
            
        !$POLL ID UNIDISK$
            
            
            
         */
    }

    private HashMap<String, String> responseParser(String response) {
        /*
        #KINOS#!
            
        #KINOS#!$SYSTEM VOLUME 100$
            
            
         */
        /*
        #KINOS#!$FAIL 16 3$
        #KINOS#!$INPUT VIDEO SVIDEO1$
        #KINOS#!$INPUT PROFILE 0 11$
        #UNIDISK#!$IGNORED CHAPTER PLAY_STOPPED$
         */
        /*
        @UNIDISK@$OPTION DISPLAY ?$
        is #UNIDISK#!
            
        #UNIDISK#!$DISCTOC TOTAL 8$
            
        #UNIDISK#$DISCTOC ENTRIES 713 478 637 663 480 493 388 512$
            
         */
        /*
        response for : @UNIDISK@$Mode?$
         is #UNIDISK#!
            
        #UNIDISK#!$VERSION HARDWARE PCAS317L2R2 B60000018E854614$
            
        #UNIDISK#!$VERSION HARDWARE PCAS546L1R1 5500000263351014$
            
        #UNIDISK#!$VERSION HARDWARE PCAS297L1R12 B50000011756B814$
            
            
         */
        /*
        response for : @UNIDISK@$VERSION HARDWARE ?$
         is #UNIDISK#!
            
        #UNIDISK#!$VERSION SOFTWARE H8 S1150210 ESS S1520208 MECH 03.03.00.00$
            
            
         */
        /*
        !$MUTE OFF$
         */
        ArrayList<String> content = new ArrayList<String>();
        HashMap<String, String> target = new HashMap<String, String>();

        String a = response;

        String[] b = a.split("\n");
        for (String c : b) {
            if (c != null && c.trim().length() > 1) {
                if (c.startsWith("#") && c.endsWith("#!"))
                    continue;
                if (c.contains("POLL"))
                    continue;

                log.info("working on " + c);
                if (c.contains("#!$"))
                    c = c.substring(c.indexOf("#!$") + 1, c.length() - 1);
                if (c.contains("#$"))
                    c = c.substring(c.indexOf("#$") + 1, c.length() - 1);

                log.info("removed device, rest " + c);
                c = c.replace("!", "");
                c = c.replace("$", "");
                content.add(c);
                log.info("added to content: " + c);
            }
        }

        for (String line : content) {
            String[] d = line.split(" ");

            if (d.length == 8 && d[0].startsWith("VERSION"))
            //e.g.   VERSION SOFTWARE H8 S1150210 ESS S1520208 MECH 03.03.00.00
            {
                log.info(d[0] + " " + d[1] + " " + d[2] + ":" + d[3]);
                log.info(d[0] + " " + d[1] + " " + d[4] + ":" + d[5]);
                log.info(d[0] + " " + d[1] + " " + d[6] + ":" + d[7]);
                target.put(d[0] + " " + d[1] + " " + d[2], d[3]);
                target.put(d[0] + " " + d[1] + " " + d[4], d[5]);
                target.put(d[0] + " " + d[1] + " " + d[6], d[7]);
            } else if (d.length == 4 && d[0].startsWith("VERSION"))
            //e.g.   VERSION HARDWARE PCAS317L2R2 B60000018E854614
            {
                log.info(d[0] + " " + d[1] + ":" + d[2] + " " + d[3]);
                target.put(d[0] + " " + d[1], d[2] + " " + d[3]);
            } else if (d.length == 3)
            //e.g.   COUNTER MAINS 0:897:23:17
            {
                log.info(d[0] + " " + d[1] + ":" + d[2]);
                target.put(d[0] + " " + d[1], d[2]);
            } else if (d.length == 2)
            // e.g. BAL -2
            {
                log.info(d[0] + ":" + d[1]);
                target.put(d[0], d[1]);
            } else {
                log.warn("cannot process line " + line);
            }
        }
        return target;
    }

    protected void finalize() {
        try {
            super.finalize();
        } catch (Throwable throwable) {
            log.error(throwable);
        }
        closeConnection();
    }
}