Skip to content

Commit

Permalink
Add OemGatewaySerialListener
Browse files Browse the repository at this point in the history
OemGatewaySerialListener is a simple listener that monitors a serial port
for data of the form 'NodeID Val1 Val2 ... \r\n'.

Code refactoring:
- OemGatewayRFM2PiListener inherits OemGatewaySerialListener.
- Processing of the generic data form defined in OemGatewayListener.
  • Loading branch information
Jérôme Lafréchoux committed Jul 23, 2013
1 parent f96d0d5 commit c785455
Show file tree
Hide file tree
Showing 2 changed files with 108 additions and 46 deletions.
28 changes: 26 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ To use the emoncms GUI, pass the --config-emoncms flag.

### Configuration file

To use a config file, pass --config-file CONFIG_FILE.
Use the --config-file argument to specify a file path.

To create a config file, copy oemgateway.conf.dist and customize.

Expand All @@ -52,7 +52,27 @@ The logging level is a config parameter.

# Listeners

Listeners derive the OemGatewayListener class.
Listeners derive the OemGatewayListener class:

OemGatewayListener
|
|-- OemGatewaySerialListener
| |
| |-- OemGatewayRFM2PiListener
|
|-- OemGatewaySocketListener

## OemGatewaySerialListener

Receives data on the serial port.

### Init settings

* com_port: path to the COM port (e.g. /dev/ttyAMA0)

### Runtime settings

None

## OemGatewayRFM2PiListener

Expand Down Expand Up @@ -91,6 +111,10 @@ None

Buffers derive the OemGatewayBuffer class.

OemGatewayBuffer
|
|-- OemGatewayEmoncmsBuffer

## OemGatewayEmoncmsBuffer

Send data to an emoncms server. If connection is lost, the data is buffered
Expand Down
126 changes: 82 additions & 44 deletions oemgatewaylistener.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,43 @@ def read(self):
"""
pass

def _process_frame(self, f):
"""Process a frame of data
f (string): 'NodeID val1 val2 ...'
This function splits the string into integers and checks their
validity.
'NodeID val1 val2 ...' is the generic data format. If the source uses
a different format, override this method.
Return data as a list: [NodeID, val1, val2]
"""

# Log data
self._log.info("Serial RX: " + f)

# Get an array out of the space separated string
received = f.strip().split(' ')

# Discard if frame not of the form [node, val1, ...]
# with number of elements at least 2
if (len(received) < 2):
self._log.warning("Misformed RX frame: " + str(received))

# Else, process frame
else:
try:
received = [int(val) for val in received]
except Exception:
self._log.warning("Misformed RX frame: " + str(received))
else:
self._log.debug("Node: " + str(received[0]))
self._log.debug("Values: " + str(received[1:]))
return received

def set(self, **kwargs):
"""Set configuration parameters.
Expand All @@ -57,19 +94,17 @@ def run(self):
"""
pass

"""class OemGatewaySerialListener

"""class OemGatewayRFM2PiListener
Monitors the serial port for data from RFM2Pi
Monitors the serial port for data
"""
class OemGatewayRFM2PiListener(OemGatewayListener):
class OemGatewaySerialListener(OemGatewayListener):

def __init__(self, com_port):

# Initialization
super(OemGatewayRFM2PiListener, self).__init__()
super(OemGatewaySerialListener, self).__init__()

# Serial port
self._log.debug('Opening serial port: %s', com_port)
Expand All @@ -83,13 +118,6 @@ def __init__(self, com_port):
# Initialize RX buffer
self._rx_buf = ''

# Initialize settings
self._settings = {'baseid': '', 'frequency': '', 'sgroup': '',
'sendtimeinterval': ''}

# Initialize time updata timestamp
self._time_update_timestamp = 0

def close(self):
"""Close socket."""

Expand All @@ -99,7 +127,7 @@ def close(self):
self._ser.close()

def read(self):
"""Read data from socket and process if complete line received.
"""Read data from serial port and process if complete line received.
Return data as a list: [NodeID, val1, val2]
Expand All @@ -112,19 +140,50 @@ def read(self):
if '\r\n' not in self._rx_buf:
return

# Otherwise, process line:

# Remove CR,LF
self._rx_buf = self._rx_buf[:-2]
f = self._rx_buf[:-2]

# Reset buffer
self._rx_buf = ''

# Process data frame
return self._process_frame(f)

"""class OemGatewayRFM2PiListener
Monitors the serial port for data from RFM2Pi
"""
class OemGatewayRFM2PiListener(OemGatewaySerialListener):

def __init__(self, com_port):

# Initialization
super(OemGatewayRFM2PiListener, self).__init__(com_port)

# Initialize settings
self._settings = {'baseid': '', 'frequency': '', 'sgroup': '',
'sendtimeinterval': ''}

# Initialize time updata timestamp
self._time_update_timestamp = 0

def _process_frame(self, f):
"""Process a frame of data
f (string): 'NodeID val1_lsb val1_msb val2_lsb val2_msb ...'
This function recombines the integers and checks their validity.
Return data as a list: [NodeID, val1, val2]
"""

# Log data
self._log.info("Serial RX: " + self._rx_buf)
self._log.info("Serial RX: " + f)

# Get an array out of the space separated string
received = self._rx_buf.strip().split(' ')

# Empty serial_rx_buf
self._rx_buf = ''
received = f.strip().split(' ')

# If information message, discard
if ((received[0] == '>') or (received[0] == '->')):
Expand Down Expand Up @@ -288,28 +347,7 @@ def read(self):

# Otherwise, process first frame in buffer:
f, self._rx_buf = self._rx_buf.split('\r\n', 1)

# Log data
self._log.info("Serial RX: " + f)

# Get an array out of the space separated string
received = f.strip().split(' ')

# Discard if frame not of the form [node val1 ...]
# with number of elements at least 2
if (len(received) < 2):
self._log.warning("Misformed RX frame: " + str(received))

# Else, process frame
else:
try:
received = [int(val) for val in received]
except Exception:
self._log.warning("Misformed RX frame: " + str(received))
else:
self._log.debug("Node: " + str(received[0]))
self._log.debug("Values: " + str(received[1:]))
return received
return self._process_frame(f)

"""class OemGatewayListenerInitError
Expand Down

0 comments on commit c785455

Please sign in to comment.