stella.ow
Class PythonClient

java.lang.Object
  extended by util.PropertyContainer
      extended by util.PropertyResources
          extended by util.PropertyBundles
              extended by io.AbstractDriver
                  extended by stella.ow.PythonClient
All Implemented Interfaces:
Driver, Cloneable, OneWireDriver, ExitCleaning, Initializable, LocalizedSupplying, PropertySupplying, ResourceSupplying

public class PythonClient
extends AbstractDriver
implements ExitCleaning, OneWireDriver

This is a work-around to get the one-wire sensors to work. The python client talks via socket to a python server that is responible for issuing the one-wire commands. It uses a very simple ASCII-protocol that understands only three commands, LIST, READ, WRITE, or STOP.
On startup, the client connects to the server on port KEY_PYTHONPORT and keeps the connection open until closed. On init, it sends a list of readable sensors to the server. During normal operation, i.e. when sensors query the client, a read command is issued and the python server returns in plain ascii the most current value of the sensor it has in its cache. If the path issued to the python server was not sent to it previously with a list command, this method returns OneWireDriver.INVALID. Writing of the one-wire switches is accomplished in a similar way by issuing a write command to the python server. These write commands are normally not cached, but forwarded driectly to the underlying onw-wire system. The result returned is writtn by the python server to this python client. Protocol (\n means new-line):


Nested Class Summary
static class PythonClient.Test
          A test class.
 
Nested classes/interfaces inherited from class util.PropertyResources
PropertyResources.URLResource
 
Field Summary
static String ADD
          The add command string.
private static String COMMANDSEPARATOR
          The separator string between multi-part commands.
private static long DEFCOOLDOWN
          The default cooldown in ms.
private static String DEFDRIVERNAME
          The default python driver name, a serial port name under linux
private static String DEFPYTHONHOST
          The default one-wire server name, a serial port name under linux
private static int DEFPYTHONPORT
          The default python server's listening port.
private static String DEFSENSORPATH
          The default list of sensors.
private static long DEFTIMEOUT
          The default timeout in ms.
private  BufferedReader in
          The input reader derived from the client socket.
static String KEY_COOLDOWN
          The default time-out after writing in ms
static String KEY_PYTHONHOST
          The name of the host the python server runs on.
static String KEY_PYTHONPORT
          The port the python server is listening at.
static String KEY_SENSORPATH
          The default list of sensor devices to read as a comma-separated list.
static String KEY_TIMEOUT
          The default time-out for reading in ms
static String LIST
          The list command string.
private  Socket open
          The client socket opened on PropertyResources.init().
private  BufferedWriter out
          The output writer derived from the client socket.
static String READ
          The read command string.
private  boolean stalled
          Gets true if reading produced a time-out.
static String STOP
          The stop command string.
static String WRITE
          The write command string.
 
Fields inherited from class io.AbstractDriver
KEY_DRIVERNAME
 
Fields inherited from class util.PropertyBundles
KEY_LOCALECOUNTRY, KEY_LOCALELANGUAGE, KEY_RESOURCEBUNDLES
 
Fields inherited from class util.PropertyResources
KEY_NOINITONCREATE, localurl, locate, POSTFIX_DIR, POSTFIX_EXT, POSTFIX_FILE, POSTFIX_LIST, POSTFIX_URL, urlset
 
Fields inherited from class util.PropertyContainer
KEY_LISTSEPARATOR, KEY_MAPKEYVALUECHAR, KEY_MAPSEPARATOR
 
Fields inherited from interface stella.ow.OneWireDriver
INVALID, OK, VALID
 
Fields inherited from interface util.ResourceSupplying
KEY_URLRESOURCES, KEY_URLUSECONFIG, KEY_URLUSECURRENT, KEY_URLUSEHOME
 
Fields inherited from interface util.PropertySupplying
CONFIG, KEY_CLASS
 
Constructor Summary
PythonClient(Map prop)
          Constructs a new python driver.
 
Method Summary
 boolean close()
          Closes the driver.
private  boolean closeSocket()
          Closes the socket without sending a stop to the Python server.
 void exit()
          On exit we close the client socket to the server and do not care about any possible failures.
 boolean isOpen()
          Checks if the connection is open.
 int issue(String sensorpath, String what)
          Sends a write command to the python server.
 boolean open()
          Initializes the driver.
private  boolean openSocket()
          Opens the socket connetion, but does not send any sensor lists.
private  String readLine()
          Reads a line from the input stream, and blocks if no bytes are available.
 String retrieve(String sensorpath)
          Send a read command to the python server.
 boolean sendList(List sensorlist)
          Send a list to the python server.
 boolean sendStop()
          Sends the stop command.
private  boolean writeLine(String what)
          Sends the given line to the socket's output stream.
 
Methods inherited from class io.AbstractDriver
createDriver, equals, getDriverName, hashCode
 
Methods inherited from class util.PropertyBundles
clone, getLocalized, getLocalized, getLocalizedString, getLocalizedString, loadResource
 
Methods inherited from class util.PropertyResources
createFrom, createFrom, createFrom, getApplet, getAsResources, getLocalClassLoader, getPropertiesToKey, getPropertiesToKey, getResource, getResourceAsStream, getResourceFromKey, getResources, init, keyCreate, keyCreate, reload, setApplet
 
Methods inherited from class util.PropertyContainer
augment, augment, augment, defaultBoolean, defaultChar, defaultDouble, defaultFloat, defaultInt, defaultLong, defaultObject, defaultObject, defaultProperties, defaultProperty, getAsBoolean, getAsChar, getAsDouble, getAsEnums, getAsFloat, getAsInt, getAsList, getAsLong, getAsMap, getAsMap, getAsObject, getAsObject, getProperties, getProperty, has, isNew, parseObject, reload, removeProperty, rescanned, setObject, setProperties, setProperty, stringProperties, toString
 
Methods inherited from class java.lang.Object
finalize, getClass, notify, notifyAll, wait, wait, wait
 
Methods inherited from interface io.Driver
getDriverName
 
Methods inherited from interface util.ResourceSupplying
getResource, getResourceAsStream, getResources
 
Methods inherited from interface util.PropertySupplying
defaultBoolean, defaultChar, defaultDouble, defaultFloat, defaultInt, defaultLong, defaultObject, defaultObject, defaultProperties, defaultProperty, getAsBoolean, getAsChar, getAsDouble, getAsFloat, getAsInt, getAsList, getAsLong, getAsMap, getAsObject, getAsObject, getProperties, getProperty, has, parseObject, removeProperty, setObject, setProperty, stringProperties
 
Methods inherited from interface util.Initializable
init
 

Field Detail

KEY_PYTHONHOST

public static final String KEY_PYTHONHOST
The name of the host the python server runs on.

See Also:
Constant Field Values

KEY_PYTHONPORT

public static final String KEY_PYTHONPORT
The port the python server is listening at.

See Also:
Constant Field Values

KEY_SENSORPATH

public static final String KEY_SENSORPATH
The default list of sensor devices to read as a comma-separated list.

See Also:
Constant Field Values

KEY_COOLDOWN

public static final String KEY_COOLDOWN
The default time-out after writing in ms

See Also:
Constant Field Values

KEY_TIMEOUT

public static final String KEY_TIMEOUT
The default time-out for reading in ms

See Also:
Constant Field Values

DEFDRIVERNAME

private static final String DEFDRIVERNAME
The default python driver name, a serial port name under linux

See Also:
Constant Field Values

DEFPYTHONHOST

private static final String DEFPYTHONHOST
The default one-wire server name, a serial port name under linux

See Also:
Constant Field Values

DEFPYTHONPORT

private static final int DEFPYTHONPORT
The default python server's listening port.

See Also:
Constant Field Values

DEFSENSORPATH

private static final String DEFSENSORPATH
The default list of sensors.

See Also:
Constant Field Values

DEFCOOLDOWN

private static final long DEFCOOLDOWN
The default cooldown in ms.

See Also:
Constant Field Values

DEFTIMEOUT

private static final long DEFTIMEOUT
The default timeout in ms.

See Also:
Constant Field Values

LIST

public static final String LIST
The list command string.

See Also:
Constant Field Values

ADD

public static final String ADD
The add command string.

See Also:
Constant Field Values

READ

public static final String READ
The read command string.

See Also:
Constant Field Values

WRITE

public static final String WRITE
The write command string.

See Also:
Constant Field Values

STOP

public static final String STOP
The stop command string.

See Also:
Constant Field Values

COMMANDSEPARATOR

private static final String COMMANDSEPARATOR
The separator string between multi-part commands.

See Also:
Constant Field Values

open

private Socket open
The client socket opened on PropertyResources.init().


in

private BufferedReader in
The input reader derived from the client socket.


out

private BufferedWriter out
The output writer derived from the client socket.


stalled

private boolean stalled
Gets true if reading produced a time-out.

Constructor Detail

PythonClient

public PythonClient(Map prop)
Constructs a new python driver. Initially, only the sensor pathes described in the list KEY_SENSORPATH are sent to the python server.

Method Detail

open

public boolean open()
             throws IOException
Initializes the driver. This requires that the python server is up and running. On init, we open a socket connection to the python server on port KEY_PYTHONPORT. If the open is successful, we parse the initial list of sensors to query and send it to the server.

Specified by:
open in interface Driver
Returns:
True if initialization was successful.
Throws:
IOException

openSocket

private boolean openSocket()
                    throws IOException
Opens the socket connetion, but does not send any sensor lists. This method may be used on re-opening.

Throws:
IOException

closeSocket

private boolean closeSocket()
                     throws IOException
Closes the socket without sending a stop to the Python server.

Throws:
IOException

isOpen

public boolean isOpen()
Checks if the connection is open. We consider everything o.k. if we have the I/O streams and the client socket.

Specified by:
isOpen in interface Driver
Returns:
True, if a previous initialization was successful

close

public boolean close()
Closes the driver. We send a STOP to the python server and then close the socket's I/O-streams and the socket itself. If anything in this process fails, we return false. If the socket was already closed, we return true.

Specified by:
close in interface Driver
Returns:
True if clean-up was successful.

exit

public void exit()
On exit we close the client socket to the server and do not care about any possible failures.

Specified by:
exit in interface ExitCleaning

sendList

public boolean sendList(List sensorlist)
Send a list to the python server. The connection must be open for success. On receive, this list is cached for re-opening re-sends.


retrieve

public String retrieve(String sensorpath)
Send a read command to the python server. The argument must be a valid sensor path, i.e. a sensor that is in the python server's cache.

Specified by:
retrieve in interface OneWireDriver
Parameters:
sensorpath - The path to the one-wire sensor.

issue

public int issue(String sensorpath,
                 String what)
Sends a write command to the python server. The sensor path is not bound to be in the python server's cache, but it should nevertheless be a valid one. The python server's return, which is an int as a string is returned and must be interpreted from the caller's side.

Specified by:
issue in interface OneWireDriver
Parameters:
sensorpath - The path to the one-wire sensor.
what - The command to send to the one-wire sensor.

sendStop

public boolean sendStop()
Sends the stop command. This will block further updating of the cache in the python server until a new list was sent with LIST.


writeLine

private boolean writeLine(String what)
Sends the given line to the socket's output stream. The connection is NOT checked for openess, this must be ensured by the caller if desired. After each write we wait a KEY_COOLDOWN time to ensure that reading the line is possible immediately as the write returns. This is no elegant solution, but there is actually no case where we write and not read immediately afterwards.

We had mysterious dissappearance of sensor threads, which I believe is a buffer overflow in the out stream. Thus, on occasions where we're stalled, we re-open the connection, not really hoping for a cure, but trying to keep the thing alive.

Returns:
true if writing was successful.

readLine

private String readLine()
Reads a line from the input stream, and blocks if no bytes are available.