Package cnadeau.driver

Source Code of cnadeau.driver.CM19ADevice

package cnadeau.driver;

import java.io.UnsupportedEncodingException;
import java.util.LinkedList;

import javax.usb.UsbEndpoint;
import javax.usb.UsbException;
import javax.usb.UsbInterface;
import javax.usb.UsbPipe;

import org.apache.log4j.Logger;

import cnadeau.driver.exceptions.CM19AException;
import cnadeau.driver.protocol.CM19AProtocol;
import cnadeau.driver.threads.ReceiverThread;
import cnadeau.driver.threads.TransmitterThread;
import cnadeau.enums.AvailableLoggers;

/**
* User space driver for the CM19a X10 RF transceiver
*
* @author Jan Roberts
*
*/

public class CM19ADevice extends Thread
{
  private final Logger logger = Logger.getLogger(AvailableLoggers.Driver.toString());

  private final UsbInterface usbInterface = null;
  private final CM19AProtocol protocol;
  private LinkedList<byte[]> outQueue = null;

  private final UsbInterfaceInfos usbInterfaceInfos;

  private final CM19AInputReader cm19aInputReader;

  private boolean running;

  public CM19ADevice(CM19AUsbDeviceLookup cm19aUsbDevideLookup, CM19AInputReader cm19aInputReader, CM19AProtocol protocol) throws CM19AException,
      UnsupportedEncodingException, UsbException
  {
    this.cm19aInputReader = cm19aInputReader;
    this.protocol = protocol;
    this.outQueue = new LinkedList<byte[]>();
    this.usbInterfaceInfos = cm19aUsbDevideLookup.findCM19ADevice();
    this.setName(getClass().getSimpleName() + " input reader thread");

    StringBuilder info = new StringBuilder("Using usb device lookup ");
    info.append(cm19aUsbDevideLookup.getClass().getSimpleName());
    info.append(",  input reader");
    info.append(cm19aInputReader.getClass().getSimpleName());
    info.append(", protocol ");
    info.append(protocol.getClass().getSimpleName());
    logger.info(info.toString());
  }

  protected CM19AProtocol getProtocol()
  {
    return protocol;
  }

  public UsbInterfaceInfos getUsbDeviceInfos()
  {
    return usbInterfaceInfos;
  }

  /**
   * Formats the incoming command to be consistent with what is expected, which is a single uppercased word, e.g. A1OFF. Commands can then be entered as
   * reader friendly way, such as a1 off, A1 Off, etc.
   *
   * @param command
   *            the incoming x10 command
   * @return the correctly formatted string
   * @throws CM19AException
   *             If the incoming string is blank or empty
   * @author Jan Roberts
   *
   */

  public String formatCommand(String command) throws CM19AException
  {

    /* remove any spaces in the command */
    String[] words = command.split("\\s+");
    if (words.length == 0)
      throw new CM19AException("Command is blank or empty");
    String spacelessCommand = words[0].trim();

    /* scrunch the string back together without the spaces */
    if (words.length > 1)
    {
      for (int i = 1; i < words.length; i++)
      {
        spacelessCommand = spacelessCommand.concat(words[i].trim());

      }
    }

    return spacelessCommand.toUpperCase();
  }

  /**
   * Sends the incoming command to the CM19a.
   *
   * @param command
   *            A properly formatted x10 command
   * @return is the driver should be closed or not
   * @author Jan Roberts
   *
   */
  public boolean send(String command)
  {
    byte[] rfTransmittal = getRFTransmittal(command);

    if (rfTransmittal != null)
    {
      send(rfTransmittal);
    }

    return rfTransmittal == CM19AProtocol.CLOSE_DRIVER_BYTES;
  }

  /**
   * Retrieves the actual bytes to transmit to the CM19a.
   *
   * Retrieves the bytes to transmit to the CM19a. They're originally stored in a single string which has to be broken up and converted to a byte array.
   *
   * @param command
   *            A properly formatted x10 command
   * @return The byte array to be transmitted or null if not found
   * @author Jan Roberts
   *
   */

  public byte[] getRFTransmittal(String command)
  {
    return getProtocol().convertCommandToRfTransmitterString(command);
  }

  /**
   * Notify the transmitter that there is a message to be sent
   *
   * @param rfTransmittal
   *            The bytes to be sent to the CM19a
   * @author Jan Roberts
   *
   */
  protected void send(byte[] rfTransmittal)
  {
    synchronized (getOutQueue())
    {
      getOutQueue().add(rfTransmittal);
      getOutQueue().notify();
    }
  }

  /**
   * Stops running threads and releases the CM19a
   *
   * @throws CM19AException
   *             If there was a problem releasing the CM19a
   * @author Jan Roberts
   */
  public void releaseDevice() throws CM19AException
  {
    getOutQueue().notify();

    /* Release the interface */
    try
    {
      usbInterface.release();
    }
    catch (UsbException e)
    {
      throw new CM19AException("Failed to release device: " + e.getMessage());
    }
  }

  public ReceiverThread createReceiverThread(UsbInterfaceInfos cm19aDeviceInfos) throws CM19AException
  {
    logger.info("Starting receiver thread... ");
    UsbPipe inPipe = openPipe(cm19aDeviceInfos.getInEndpoint());
    ReceiverThread receiver = new ReceiverThread(inPipe);
    return receiver;
  }

  public TransmitterThread createTransmitterThread(UsbInterfaceInfos cm19aDeviceInfos) throws CM19AException
  {
    logger.info("Starting transmitter thread... ");
    UsbPipe outPipe = openPipe(cm19aDeviceInfos.getOutEndpoint());
    TransmitterThread transmitter = new TransmitterThread(this, outPipe);
    return transmitter;
  }

  private UsbPipe openPipe(UsbEndpoint endPoint) throws CM19AException
  {
    UsbPipe outPipe = null;
    try
    {
      outPipe = endPoint.getUsbPipe();
      outPipe.open();
    }
    catch (NullPointerException e)
    {
      try
      {
        endPoint.getUsbPipe().close();
        endPoint.getUsbInterface().release();
        throw new CM19AException("pipe is null; interface released");
      }
      catch (UsbException ue)
      {
        throw new CM19AException("pipe is null; interface not released " + ue.getMessage());
      }
    }
    catch (UsbException ue2)
    {
      try
      {
        endPoint.getUsbPipe().close();
        endPoint.getUsbInterface().release();
        throw new CM19AException("Usb exception on pipe " + ue2.getMessage() + "; interface released");
      }
      catch (UsbException ue)
      {
        throw new CM19AException("Usb exception on pipe " + ue2.getMessage() + "; interface not released " + ue.getMessage());
      }
    }

    return outPipe;
  }

  public LinkedList<byte[]> getOutQueue()
  {
    return outQueue;
  }

  @Override
  public void run()
  {
    running = true;

    // Restart driver automatically when any error occurs until explicitly stopped
    while (running)
    {
      logger.info("Starting driver... ");

      UsbInterfaceInfos cm19aDeviceInfos = getUsbDeviceInfos();
      ReceiverThread receiverThread = createReceiverThread(cm19aDeviceInfos);
      TransmitterThread transmitterThread = createTransmitterThread(cm19aDeviceInfos);

      logger.info("Driver started!");
      try
      {
        receiverThread.start();
        transmitterThread.start();
        while (running)
        {
          byte[] buffer = new byte[16];

          int readCount = cm19aInputReader.read(buffer);
          if (readCount > 0)
          {
            String string = new String(buffer);

            if (send(string.trim()))
            {
              // explicitly closing the driver
              running = false;
            }
          }
          else
          {
            Thread.sleep(250);
          }
        }
      }
      catch (Exception e)
      {
        logger.error(e);
      }
      finally
      {
        if (receiverThread != null)
        {
          receiverThread.quit();
        }
        if (transmitterThread != null)
        {
          transmitterThread.quit();
        }
        logger.info("Driver stopped");
      }
    }
  }

  public void quit()
  {
    logger.info("Closing driver");
    cm19aInputReader.close();

    try
    {
      usbInterface.release();
    }
    catch (Exception e)
    {}
    logger.info("Driver closed");
  }
}
TOP

Related Classes of cnadeau.driver.CM19ADevice

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.