diff --git a/doc/classes.txt b/doc/classes.txt
index 0fca1fe..b9a77e4 100644
--- a/doc/classes.txt
+++ b/doc/classes.txt
@@ -253,6 +253,71 @@
 
 
 --------------------------------------------------------------------------------
+DESIGN NOTES - registry data store
+
+REQUIREMENT: I want a simple persistent kvp database with the following features:
+
+1. A file format that is portable across all platforms
+
+   so that a single registry file could be copied from a tutorial onto
+   any machine and it would just work
+
+2. A file format that is human readable and easily editable
+
+   so that users could create or edit the file just like a config file
+
+3. A simple read and write key/value abstraction in python
+   with a full CRUD lifecycle
+
+   so that new kvp's can be created, read, updated and deleted.
+
+4. Doesn't have to be hugely efficient or store very large data sets
+
+   it's mostly used for configuration data that rarely changes,
+   or last known values that tend to be quite small.
+
+5. MIT licence
+
+   so that it can be just embedded in an existing project
+
+6. A single python file
+
+   so it is easy to embed
+
+7. Works out of the box with no changes on Python 2 and Python 3
+
+   so it doesn't have to be configured or changed and does not limit
+   or dictate a specific python version.
+
+Additionally, it might:
+
+8. A option to add multi process locking later if required, but not
+   included by default
+
+   so that it could be used as a simple central database for multiple
+   programs sharing the same data set.
+
+9. understand read only and read/write intents better
+
+   when using configuration data and last known values, it is useful
+   to keep them in the same single file, so it is easy to copy
+   to other machines. Some data is naturally 'write once' and
+   very configuration based. Some data is naturally 'write often'.
+   It might be nice if these two types of data could appear in the same
+   file, but the locking/performance and resilience issues be handled
+   differently for the two classes of data - e.g. perhaps having
+   two connections to the same database file, one in read only mode
+   for config records, and one in read/write mode for last use data.
+   There might also be different namespace prefixes in the file
+   so that the key sets are separate, or there may be a way to
+   link them so that when you read a record you get both the static
+   config data and the fast changing last use data as a single
+   record. But this then implies when you do an update, you
+   probably want to update part of a record rather than the
+   whole record.
+
+
+--------------------------------------------------------------------------------
 DESIGN NOTES - discovery process
 
 a way to sequence transmit messages to allow legacy devices to learn a code.
diff --git a/src/energenie/Devices.py b/src/energenie/Devices.py
index 3ed6a59..a0fc436 100644
--- a/src/energenie/Devices.py
+++ b/src/energenie/Devices.py
@@ -113,9 +113,6 @@
         self.air_interface = air_interface
         class Config(): pass
         self.config = Config()
-        self.manufacturer_id = None
-        self.product_id = None
-        self.device_id = None
 
     def has_switch(self):
         return False
@@ -129,35 +126,13 @@
     def get_radio_config(self):
         return self.config
 
-
-    #TODO: no manufacturerid, productid, deviceid for legacy devices?
-    # so does this move into MiHomeDevice?
-
-    def get_manufacturer_id(self): # -> id:int
-        return self.manufacturer_id
-
-    def get_product_id(self): # -> id:int
-        return self.product_id
-
-    def get_device_id(self): # -> id:int
-        return self.device_id
-
-
     def get_last_receive_time(self): # ->timestamp
+        """The timestamp of the last time any message was received by this device"""
         return self.last_receive_time
 
-    def get_last_send_time(self): # -> timestamp
-        return self.last_send_time
-
     def get_next_receive_time(self): # -> timestamp
+        """An estimate of the next time we expect a message from this device"""
         pass
-        #TODO this should probably be calculated
-        #TODO not sure yet if this lives here
-
-    def get_next_send_time(self): # -> timestamp
-        pass
-        #TODO this should probably be calculated
-        #TODO not sure yet if this lives here
 
     def incoming_message(self, payload):
         # incoming_message (OOK or OpenThings as appropriate, stripped of header? decrypted, decoded to pydict)
@@ -166,6 +141,8 @@
 
     def send_message(self, payload):
         if self.air_interface != None:
+            #TODO: might want to send the config, either as a send parameter,
+            #or by calling air_interface.configure() first?
             self.air_interface.send(payload)
         else:
             m = self.manufacturer_id
@@ -175,9 +152,12 @@
 
 
 class EnergenieDevice(Device):
-    def __init__(self, air_interface):
+    def __init__(self, air_interface, device_id=None):
         Device.__init__(self, air_interface)
-        self.manufacturer_id = MFRID_ENERGENIE
+        self.device_id = device_id
+
+    def get_device_id(self): # -> id:int
+        return self.device_id
 
 
 class LegacyDevice(EnergenieDevice):
@@ -189,18 +169,27 @@
 
 
 class MiHomeDevice(EnergenieDevice):
-    def __init__(self, air_interface):
-        EnergenieDevice.__init__(self, air_interface)
+    def __init__(self, air_interface, device_id=None):
+        EnergenieDevice.__init__(self, air_interface, device_id)
         self.config.frequency  = 433.92
         self.config.modulation = "FSK"
         self.config.codec      = "OpenThings"
+        self.manufacturer_id   = MFRID_ENERGENIE
+        self.product_id        = None
+
         #Different devices might have different PIP's
         #if we are cycling codes on each message?
         #self.config.encryptPID = CRYPT_PID
         #self.config.encryptPIP = CRYPT_PIP
 
+    def get_manufacturer_id(self): # -> id:int
+        return self.manufacturer_id
 
-class ENER002(LegacyDevice):
+    def get_product_id(self): # -> id:int
+        return self.product_id
+
+
+class ENER002(LegacyDevice): # Green button switch
     def __init__(self, air_interface=None, device_id=None):
         LegacyDevice.__init__(self, air_interface)
         #NOTE: tuple of (house_address, device_index)
diff --git a/src/energenie/radio.py b/src/energenie/radio.py
index 7b04b83..2d3c214 100644
--- a/src/energenie/radio.py
+++ b/src/energenie/radio.py
@@ -232,28 +232,29 @@
     return rxlist # Python len(rxlist) tells us how many bytes including length byte if present
 
 
-@untested
-def receive_len(size):
-    """Receive a fixed payload size"""
-
-    bufsize = size
-
-    Buffer = ctypes.c_ubyte * bufsize
-    rxbuf  = Buffer()
-    buflen = ctypes.c_ubyte(bufsize)
-    #RADIO_RESULT radio_get_payload_len(uint8_t* buf, uint8_t buflen)
-
-    result = radio_get_payload_len_fn(rxbuf, buflen)
-
-    if result != 0: # RADIO_RESULT_OK
-        raise RuntimeError("Receive failed, error code %s" % hex(result))
-
-    # turn buffer into a list of bytes, using 'size' as the counter
-    rxlist = []
-    for i in range(size):
-        rxlist.append(rxbuf[i])
-
-    return rxlist # Python len(rxlist) tells us how many bytes including length byte if present
+#TODO: Placeholder for when we do OOK receive
+#@untested
+#def receive_len(size):
+#    """Receive a fixed payload size"""
+#
+#    bufsize = size
+#
+#    Buffer = ctypes.c_ubyte * bufsize
+#    rxbuf  = Buffer()
+#    buflen = ctypes.c_ubyte(bufsize)
+#    #RADIO_RESULT radio_get_payload_len(uint8_t* buf, uint8_t buflen)
+#
+#    result = radio_get_payload_len_fn(rxbuf, buflen)
+#
+#    if result != 0: # RADIO_RESULT_OK
+#        raise RuntimeError("Receive failed, error code %s" % hex(result))
+#
+#    # turn buffer into a list of bytes, using 'size' as the counter
+#    rxlist = []
+#    for i in range(size):
+#        rxlist.append(rxbuf[i])
+#
+#    return rxlist # Python len(rxlist) tells us how many bytes including length byte if present
 
 
 def standby():