Index: /trunk/L_EnOceanESP3.lua
===================================================================
--- /trunk/L_EnOceanESP3.lua	(revision 1)
+++ /trunk/L_EnOceanESP3.lua	(revision 3)
@@ -7,6 +7,7 @@
 -------------------------------------------------------------------------------
 
-local DEBUG_MODE = true
-
+local DEBUG_MODE          = true
+local WAIT_FOR_RESPONSE   = false -- If this is 'true', no further messages will be sent
+local SENDING_IN_PROGRESS = false
 
 -------------------------------------------------------------------------------
@@ -15,9 +16,11 @@
 
 -- Services
-local ENOCEAN_SID   = "urn:enocean-com:serviceId:EnoceanGatewayESP3"
-local SES_SID       = "urn:micasaverde-com:serviceId:SecuritySensor1"
+local SID = {
+	ENOCEAN = "urn:micasaverde-com:serviceId:EnoceanGatewayESP3",
+	SES     = "urn:micasaverde-com:serviceId:SecuritySensor1"
+}
 
 -- Message types
-local TASK = {
+local SYS_MESSAGE_TYPES = {
 	BUSY    =  1,
 	ERROR   =  2,
@@ -25,15 +28,34 @@
 }
 
--------------------------------------------------------------------------------
+-- Delays for luup.delay, in seconds
+local DELAYS = {
+	PROCESS_PACKET    = 1,
+	SEND_NEXT_MESSAGE = 2
+}
+
+-------------------------------------------------------------------------------
+
+local SYNC_BYTE = string.char(0x55)
 
 local STATE = {
-	["GET_SYNC_STATE"]    = 0,
-	["GET_HEADER_STATE"]  = 1,
-	["CHECK_CRC8H_STATE"] = 2,
-	["GET_DATA_STATE"]    = 3,
-	["CHECK_CRC8D_STATE"] = 4
-}
-
-local SYNC_BYTE = string.char(0x55)
+	GET_SYNC_STATE    = 0,
+	GET_HEADER_STATE  = 1,
+	CHECK_CRC8H_STATE = 2,
+	GET_DATA_STATE    = 3,
+	CHECK_CRC8D_STATE = 4
+}
+
+local PACKET_TYPES = {
+	RADIO          = string.char(0x1),
+	RESPONSE       = string.char(0x2),
+	EVENT          = string.char(0x4),
+	COMMON_COMMAND = string.char(0x5)
+}
+
+local TELEGRAM_TYPES = {
+	["RPS"] = string.char(0xF6),
+	["1BS"] = string.char(0xD5),
+	["4BS"] = string.char(0xA5)
+}
 
 local CRC8_TABLE = {
@@ -80,11 +102,7 @@
 
 local g_taskHandle = -1
-local g_lastTask = 0 -- Timestamp of the last status message.
-
-local g_partitions = {}
-local g_zones = {}
-
-local messageQueue = {}
-local sendAttempt = 0
+local g_lastSysMessage = 0 -- Timestamp of the last status message.
+
+local g_messageQueue = {}
 
 
@@ -95,43 +113,29 @@
 local log      = luup.log
 local getinfo  = debug.getinfo -- Get the 'getinfo' function from the 'debug' module before overwriting the 'debug' keyword.
-
-local function debug (text)
-	if (DEBUG_MODE == true) then
-		log(text)
+local function debug() end
+
+
+local function showSysMessage (message, mode, critical)
+	log("(EnOceanPlugin::showSysMessage/"..(getinfo(2).name or "N/A")..") message='".. message .."', mode=".. mode ..", critical=".. critical)
+
+	luup.task(text, mode, "EnOcean Plugin", g_taskHandle)
+	g_lastSysMessage = tostring(os.time())
+
+	if (not critical) then
+		luup.call_delay("clearSysMessage", 30, g_lastSysMessage) -- Clear the previous system message, since it's transient.
+	else
+		luup.set_failure(true, lug_device)
+	end
+end
+
+
+function clearSysMessage (messageTime)
+	-- 'messageTime' is nil if the function is called by the user.
+	if (messageTime == g_lastSysMessage or messageTime == nil) then
+		luup.task("Clearing...", SYS_MESSAGE_TYPES.SUCCESS, "EnOcean Plugin", g_taskHandle)
 	end
 end
 
 --[[
-local function task (text, mode)
-
-	local messageType
-	if (mode == TASK_ERROR or mode == TASK_ERROR_PERM) then
-		messageType = "ERROR"
-	else
-		messageType = "STATUS"
-	end
-	debug("(EnOceanPlugin::task/"..(getinfo(2).name or "N/A")..") "..messageType..": "..text)
-
-	g_lastTask = os.time()
-
-	if (mode == TASK_ERROR_PERM) then
-		luup.task(text, TASK_ERROR, "Concord Plugin", g_taskHandle)
-	elseif (mode == TASK_BUSY_PERM) then
-		luup.task(text, TASK_BUSY, "Concord Plugin", g_taskHandle)
-	else
-		luup.task(text, mode, "Concord Plugin", g_taskHandle)
-		luup.call_delay("clearTask", 30, tostring(g_lastTask)) -- Clear the previous message, since it's transient.
-	end
-end
-
-
-function clearTask (taskTime)
-	if (taskTime ~= nil and tostring(g_lastTask) ~= taskTime) then
-		return
-	end
-	luup.task("Clearing...", TASK_SUCCESS, "Concord Plugin", g_taskHandle)
-end
-
-
 local function padLeft (s, length, c)
 	s = tostring(s)
@@ -172,93 +176,125 @@
 -------------------------------------------------------------------------------
 
-local function computeCrc (data, dataLen)
+local function computeCrc (data, start, length)
+	start = start or 1
+	length = length or #data
+
 	local crc = 0
-	for i = 1, dataLen do
+	for i = start, start + length - 1 do
 		crc = CRC8_TABLE[bit.bxor(crc, string.byte(data[i])) + 1]
 	end
-	log("(EnOceanPlugin::computeCrc) crc=".. crc)
-	return crc
-end
-
-
---[[
-local function addToQueue(s)
-	local length = padLeft(#s / 2 + 1)
-	s = CHAR_LF .. length .. s .. string.format("%02X", checksum(length .. s))
-	table.insert(messageQueue, s)
-	if (#messageQueue == 1) then -- This is the only message in the queue. Start the 'send' chain.
-		sendMessage()
-	end
-end
-
-
-function sendMessage()
-	if (#messageQueue > 0) then
-		s = messageQueue[1]
+	debug("(EnOceanPlugin::computeCrc) crc=".. crc)
+	return string.char(crc)
+end
+
+
+local function addToSendQueue (packetType, data, optData, waitForResponse)
+	local insert = table.insert
+	local char   = string.char
+
+	local packet = { SYNC_BYTE }             -- The sync byte
+
+	insert(packet, char(#data / 0x100))      -- First byte of the data length
+	insert(packet, char(#data % 0x100))      -- Seconds byte of the data length
+	insert(packet, char(#optData))           -- Length of the optional data
+	insert(packet, packetType)               -- The packet type
+	insert(packet, computeCrc(packet, 2, 4)) -- The header CRC8
+
+	insert(packet, data)                     -- The user data
+	insert(packet, optData)                  -- The optional user data
+	insert(packet, computeCrc(packet, 7, #data + #optData)) -- The data CRC8
+
+	table.insert(g_messageQueue, {content = table.concat(packet), waitForResponse = (waitForResponse or false)})
+	if (not SENDING_IN_PROGRESS) then
+		sendPacket()
+	end
+end
+
+
+function sendPacket()
+	SENDING_IN_PROGRESS = true
+
+	if (WAIT_FOR_RESPONSE == true) then
+		g_triesCount = g_triesCount + 1
+		if(g_triesCount < 3) then
+			debug("(EnOceanPlugin::sendPacket) WAIT_FOR_RESPONSE flag is set, g_triesCount=".. g_triesCount .."; try again in ".. DELAYS.SEND_NEXT_MESSAGE .." seconds.")
+			luup.call_delay("sendPacket", DELAYS.SEND_NEXT_MESSAGE)
+			return
+		else
+			log("(EnOceanPlugin::sendPacket) Didn't receive response for the last message. Stop waiting for response.")
+			WAIT_FOR_RESPONSE = false
+			g_triesCount = 0
+		end
+	end
+
+	local message
+	if (#g_messageQueue > 0) then
+		message = g_messageQueue[1]
 	else
 		return
 	end
 
-	sendAttempt = sendAttempt + 1
-	if (sendAttempt == 3) then
-		-- Send CR/LF to reset the automation module's message queue.
-		if (not luup.io.write(CHAR_CR .. s)) then
-			task("Failed to send message", TASK_ERROR_PERM)
-			return
-		end
-		-- Remove the message from the queue, because there's a chance that the message is wrong.
-		sendAttempt = 0
-		table.remove(messageQueue, 1)
-	elseif (not luup.io.write(s)) then
-		-- Send the message normally.
-		task("Failed to send message", TASK_ERROR_PERM)
+	debug("(EnOceanPlugin::sendPacket) Wait for response: ".. message.waitForResponse)
+
+	if (not luup.io.write(message.content)) then
+		showSysMessage("Failed to send message", SYS_MESSAGE_TYPES.ERROR)
+		luup.variable_set(SID.ENOCEAN, "CommFailure", "1", lug_device)
 		return
 	end
 
+	WAIT_FOR_RESPONSE = message.waitForResponse
+	table.remove(g_messageQueue, 1)
+
 	-- Send the next message in the queue.
-	if (#messageQueue > 0) then
-		luup.call_delay("sendMessage", SEND_DELAY)
-	end
-end
-
-
-local function sendChar (c)
-	if (not luup.io.write(c)) then
-		task("Failed to send message", TASK_ERROR_PERM)
-	end
-end
-
-
-local function decodeName (s)
-	if (s == nil or s == "") then
-		return "N/A"
-	end
-
-	s = s:gsub("(%x%x)", TOKENS)
-
-	-- Trim leading and trailing whitespace.
-	return s:match("^%s*(.-)%s*$")
-end
-
-
--- Expands a number, e.g. 21 -> 0201
-local function expand (nr)
-	if (nr == nil) then
-		return ""
-	end
-
-	local expNr = ""
-	for i = 1, #nr do
-		local d = nr:sub(i, i)
-		expNr = expNr .. padLeft(d)
-	end
-
-	return expNr
-end
-]]
-
--------------------------------------------------------------------------------
--- Message handler functions
--------------------------------------------------------------------------------
+	if (#g_messageQueue > 0) then
+		luup.call_delay("sendPacket", DELAYS.SEND_NEXT_MESSAGE)
+	else
+		SENDING_IN_PROGRESS = false
+	end
+end
+
+
+-------------------------------------------------------------------------------
+-- Radio telegram handlers
+-------------------------------------------------------------------------------
+
+local RADIO_TELEGRAM_HANDLERS = {
+	-- RPS
+	[TELEGRAM_TYPES.RPS] = function (data)
+		debug("(EnOceanPlugin::RPS) RPS telegram handler")
+	end,
+
+	-- 1BS
+	[TELEGRAM_TYPES["1BS"]] = function (data)
+		debug("(EnOceanPlugin::1BS) 1BS telegram handler")
+
+	end,
+
+	-- 4BS
+	[TELEGRAM_TYPES.4BS] = function (data)
+		debug("(EnOceanPlugin::4BS) 4BS telegram handler")
+	end
+}
+
+
+-------------------------------------------------------------------------------
+-- Packet handler functions
+-------------------------------------------------------------------------------
+
+function handleRadioTelegram (data)
+	debug("(EnOceanPlugin::handleRadioTelegram) Handle radio telegram")
+	RADIO_TELEGRAM_HANDLERS[string.byte(data:sub(1, 1))](data:sub(2))
+end
+
+
+function handleResponse (data)
+	debug("(EnOceanPlugin::handleResponse) Handle response")
+end
+
+
+local PACKET_HANDLERS = {
+	[PACKET_TYPES.RADIO]    = "handleRadioTelegram",
+	[PACKET_TYPES.RESPONSE] = "handleResponse"
+}
 
 
@@ -267,5 +303,13 @@
 -------------------------------------------------------------------------------
 
--- 0x55 0x0 0xa 0x7 0x1 0xeb 0xa5 0xce 0x79 0x0 0xf 0x0 0x81 0x1 0x75 0x0 0x1 0xff 0xff 0xff 0xff 0x44 0x0 0x6e
+-- 4BS
+-- 0x55 | 0x0 0xa 0x7 0x1 | 0xeb | 0xa5 - 0xce 0x79 0x0 0xf - 0x0 0x81 0x1 0x75 - 0x0 | 0x1 0xff 0xff 0xff 0xff 0x44 0x0 | 0x6e
+-- 0x55 | 0x0 0xa 0x7 0x1 | 0xeb | 0xa5 - 0xc6 0x79 0x0 0xf - 0x0 0x81 0x1 0x75 - 0x0 | 0x1 0xff 0xff 0xff 0xff 0x43 0x0 | 0x15
+-- 0x55 | 0x0 0xa 0x7 0x1 | 0xeb | 0xa5 - 0xc6 0x79 0x0 0xf - 0x0 0x81 0x1 0x75 - 0x0 | 0x1 0xff 0xff 0xff 0xff 0x43 0x0 | 0x15
+
+-- 1BS
+-- 0x55 | 0x0 0x7 0x7 0x1 | 0x7a | 0xd5 - 0x8 - 0x0 0x1 0x8a 0xbb - 0x0 | 0x1 0xff 0xff 0xff 0xff 0x3a 0x0 | 0xbc
+-- 0x55 | 0x0 0x7 0x7 0x1 | 0x7a | 0xd5 - 0x8 - 0x0 0x0 0x85 0xe - 0x0 | 0x1 0xff 0xff 0xff 0xff 0x37 0x0 | 0x3a
+
 
 local state        = STATE.GET_SYNC_STATE -- The current state
@@ -274,4 +318,5 @@
 local rxDataLen    = 0  -- The length of the data field
 local rxOptDataLen = 0  -- The length of the optional data field
+local rxPacketType = 0  -- The packet type
 
 -- State machine to load incoming packet bytes
@@ -279,7 +324,7 @@
 
 	-- Waiting for packet sync byte 0x55
-	[STATE.GET_SYNC_STATE] = function (byte)
-		if (byte == SYNC_BYTE) then
-			log("(EnOceanPlugin::GET_SYNC_STATE) Got sync byte, go to GET_HEADER_STATE")
+	[STATE.GET_SYNC_STATE] = function (rxByte)
+		if (rxByte == SYNC_BYTE) then
+			debug("(EnOceanPlugin::GET_SYNC_STATE) Got sync byte, go to GET_HEADER_STATE")
 			state = STATE.GET_HEADER_STATE
 			crc   = 0
@@ -289,11 +334,11 @@
 
 	-- Read the header bytes.
-	[STATE.GET_HEADER_STATE] = function (byte)
+	[STATE.GET_HEADER_STATE] = function (rxByte)
 		-- Add the received byte in the buffer.
 		rxCount = rxCount + 1
-		rxBuf[rxCount] = byte
+		rxBuf[rxCount] = rxByte
 		-- All the header bytes received?
 		if(rxCount == 4) then
-			log("(EnOceanPlugin::GET_HEADER_STATE) Received all header bytes, go to CHECK_CRC8H_STATE")
+			debug("(EnOceanPlugin::GET_HEADER_STATE) Received all header bytes, go to CHECK_CRC8H_STATE")
 			state = STATE.CHECK_CRC8H_STATE
 		end
@@ -301,8 +346,8 @@
 
 	-- Check the header checksum & try to resynchronize if and error occured.
-	[STATE.CHECK_CRC8H_STATE] = function (byte)
+	[STATE.CHECK_CRC8H_STATE] = function (rxByte)
 		-- Header CRC correct?
-        if (computeCrc(rxBuf, rxCount) ~= string.byte(byte)) then
-			log("(EnOceanPlugin::CHECK_CRC8H_STATE) Incorrect header crc")
+        if (computeCrc(rxBuf, 1, rxCount) ~= rxByte) then
+			debug("(EnOceanPlugin::CHECK_CRC8H_STATE) Incorrect header crc")
 			-- No. Check if there is a sync byte (0x55) in the header.
 			local pos = -1
@@ -315,13 +360,13 @@
 			end
 
-			if (pos == -1 and byte ~= SYNC_BYTE) then
+			if (pos == -1 and rxByte ~= SYNC_BYTE) then
 				-- Neither the header nor the CRC8H contain the sync byte
-				log("(EnOceanPlugin::CHECK_CRC8H_STATE) Neither the header nor the CRC8H contain the sync byte, go to GET_SYNC_STATE")
+				debug("(EnOceanPlugin::CHECK_CRC8H_STATE) Neither the header nor the CRC8H contain the sync byte, go to GET_SYNC_STATE")
 				state = STATE.GET_SYNC_STATE
 				return
-			elseif (pos == -1 and byte == SYNC_BYTE) then
+			elseif (pos == -1 and rxByte == SYNC_BYTE) then
 				-- The header does not contain the sync byte but the CRC8H does
 				-- The sync byte could be the beginning of a packet
-				log("(EnOceanPlugin::CHECK_CRC8H_STATE) The header does not contain the sync byte but the CRC8H does, go to GET_HEADER_STATE")
+				debug("(EnOceanPlugin::CHECK_CRC8H_STATE) The header does not contain the sync byte but the CRC8H does, go to GET_HEADER_STATE")
 				state = STATE.GET_HEADER_STATE
 				rxCount = 0
@@ -339,12 +384,12 @@
 			-- Copy the received byte to buffer
 			rxCount = rxCount + 1
-			rxBuf[rxCount] = byte
+			rxBuf[rxCount] = rxByte
 
 			if (rxCount < 4) then
-				log("(EnOceanPlugin::CHECK_CRC8H_STATE) There are still header bytes to receive, go to GET_HEADER_STATE")
+				debug("(EnOceanPlugin::CHECK_CRC8H_STATE) There are still header bytes to receive, go to GET_HEADER_STATE")
 				state = STATE.GET_HEADER_STATE
 			end
 
-			log("(EnOceanPlugin::CHECK_CRC8H_STATE) All header bytes received, stay in CHECK_CRC8H_STATE")
+			debug("(EnOceanPlugin::CHECK_CRC8H_STATE) All header bytes received, stay in CHECK_CRC8H_STATE")
 			return
         end
@@ -353,10 +398,10 @@
 		rxDataLen = string.byte(rxBuf[1]) * 256 + string.byte(rxBuf[2])
 		rxOptDataLen = string.byte(rxBuf[3])
-		log("(EnOceanPlugin::CHECK_CRC8H_STATE) Header crc correct, rxDataLen=".. rxDataLen ..", rxOptDataLen=".. rxOptDataLen)
+		debug("(EnOceanPlugin::CHECK_CRC8H_STATE) Header crc correct, rxDataLen=".. rxDataLen ..", rxOptDataLen=".. rxOptDataLen)
 		if ((rxDataLen + rxOptDataLen) == 0) then
 			-- No. Sync byte received?
-			if (byte == SYNC_BYTE) then
+			if (rxByte == SYNC_BYTE) then
 				-- Yes
-				log("(EnOceanPlugin::CHECK_CRC8H_STATE) Header crc incorrect, sync byte not received, go to GET_HEADER_STATE")
+				debug("(EnOceanPlugin::CHECK_CRC8H_STATE) Header crc incorrect, sync byte not received, go to GET_HEADER_STATE")
 				state = STATE.GET_HEADER_STATE
 				rxCount = 0
@@ -365,24 +410,25 @@
 
 			-- Packet with correct CRC8H, but wrong length fields
-			log("(EnOceanPlugin::CHECK_CRC8H_STATE) Packet with correct CRC8H, but wrong length fields, go to GET_SYNC_STATE")
+			debug("(EnOceanPlugin::CHECK_CRC8H_STATE) Packet with correct CRC8H, but wrong length fields, go to GET_SYNC_STATE")
 			state = STATE.GET_SYNC_STATE
-			log("(EnOceanPlugin::CHECK_CRC8H_STATE) Error: invalid packet")
+			debug("(EnOceanPlugin::CHECK_CRC8H_STATE) Error: invalid packet")
 			return
 		end
 
 		-- Correct header CRC8. Go to the reception of data.
-		log("(EnOceanPlugin::CHECK_CRC8H_STATE) Correct header CRC8, go to GET_DATA_STATE")
+		debug("(EnOceanPlugin::CHECK_CRC8H_STATE) Correct header CRC8, go to GET_DATA_STATE")
 		state = STATE.GET_DATA_STATE
 		rxCount = 0
+		rxPacketType = string.byte(rxBuf[4])
 	end,
 
 	-- Copy the information bytes.
-	[STATE.GET_DATA_STATE] = function (byte)
+	[STATE.GET_DATA_STATE] = function (rxByte)
 		rxCount = rxCount + 1
-		rxBuf[rxCount] = byte
+		rxBuf[rxCount] = rxByte
 
 		-- When all the expected bytes are received, go to calculate data checksum.
 		if (rxCount == (rxDataLen + rxOptDataLen)) then
-			log("(EnOceanPlugin::GET_DATA_STATE) All expected bytes received, go to CHECK_CRC8D_STATE")
+			debug("(EnOceanPlugin::GET_DATA_STATE) All expected bytes received, go to CHECK_CRC8D_STATE")
 			state = STATE.CHECK_CRC8D_STATE
 		end
@@ -390,12 +436,16 @@
 
 	-- Check the data CRC8
-	[STATE.CHECK_CRC8D_STATE] = function (byte)
+	[STATE.CHECK_CRC8D_STATE] = function (rxByte)
 		-- In all cases the state returns to the first state: waiting for next sync byte.
 		state = STATE.GET_SYNC_STATE
 
-		if (computeCrc(rxBuf, rxCount) == string.byte(byte)) then
+		if (computeCrc(rxBuf, 1, rxCount) == rxByte) then
 			-- Correct packet received
-			log("(EnOceanPlugin::CHECK_CRC8D_STATE) Correct packet received, go to GET_SYNC_STATE")
-			-- TODO: DO SOMETHING WITH THE DATA (use luup.call_delay)
+			debug("(EnOceanPlugin::CHECK_CRC8D_STATE) Correct packet received, schedule the packet handler function and go to GET_SYNC_STATE")
+			if (PACKET_HANDLERS[rxPacketType] ~= nil) then
+				luup.call_delay(PACKET_HANDLERS[rxPacketType], DELAYS.PROCESS_PACKET, table.concat(rxBuf, "", 1, rxCount))
+			else
+				debug("(EnOceanPlugin::CHECK_CRC8D_STATE) Unhandled packet type ".. rxPacketType)
+			end
 			return
 		end
@@ -403,6 +453,6 @@
 		-- Incorrect CRC8
 		-- If the received byte is the sync byte, then it could be the sync byte for next packet.
-		if (byte == SYNC_BYTE) then
-			log("(EnOceanPlugin::CHECK_CRC8D_STATE) Incorrect CRC8, the received byte is the sync byte, go to GET_HEADER_STATE")
+		if (rxByte == SYNC_BYTE) then
+			debug("(EnOceanPlugin::CHECK_CRC8D_STATE) Incorrect CRC8, the received byte is the sync byte, go to GET_HEADER_STATE")
 			state = STATE.GET_HEADER_STATE
 			rxCount = 0
@@ -416,5 +466,5 @@
 
 function handleIncoming (lul_data)
-	log("state=".. state ..", byte=".. (string.byte(lul_data) or "nil"))
+	log("state=".. state ..", rxByte=".. (string.byte(lul_data) or "nil"))
 	if (STATE_MACHINE[state] ~= nil) then
 		STATE_MACHINE[state](lul_data)
@@ -430,4 +480,9 @@
 -------------------------------------------------------------------------------
 
+function setTarget (device, newTargetValue)
+	--local
+end
+
+
 -----------------------------------------------------------------------------
 -- Init
@@ -437,38 +492,28 @@
 	log("(EnOceanPlugin::init) EnOcean ESP3 Gateway plugin")
 
+	-- Get the root device.
 	lug_device = lul_device
 
+	-- Get a handle for system messages.
 	g_taskHandle = luup.task("Starting up...", 1, "EnOcean plugin", -1)
 
-	--[[
-	-- Check if Debug Mode is enabled.
+	-- Reset our CommFailure variable.
+	luup.variable_set(SID.ENOCEAN, "CommFailure", "0", lul_device)
+
+	-- Update the Debug Mode.
 	local debugMode = luup.variable_get(ENOCEAN_SID, "DebugMode", lul_device) or ""
 	if (debugMode == "") then
-		debugMode = DEBUG_MODE and "1" or "0"
-		luup.variable_set(ENOCEAN_SID, "DebugMode", debugMode, lul_device)
+		luup.variable_set(ENOCEAN_SID, "DebugMode", (DEBUG_MODE and "1" or "0"), lul_device)
 	else
 		DEBUG_MODE = (debugMode == "1") and true or false
 	end
 
-	-- Check if the panel is connected through the serial port, or via Ethernet.
-	local attr_ip = luup.devices[lul_device].ip or ""
-	if (attr_ip == "") then
-		debug ("(EnOceanPlugin::init) Running on Serial.")
-	else
-		local ip, port = attr_ip:match("^([%d.]+):?(%d*)$")
-		debug("(EnOceanPlugin::init) ip = '".. (ip or "nil") .."', port = '".. (port or "nil") .."'.")
-
-		-- Validate the IP.
-		if (ip:match("^%d+%.%d+%.%d+%.%d+$") ~= nil) then
-			if (port == nil or port == "") then
-				port = 5000
-			end
-			debug("(EnOceanPlugin::init) Running on Ethernet. IP = ".. ip ..", port = ".. port ..".")
-			luup.io.open(lul_device, ip, port)
-		else
-			debug("(EnOceanPlugin::init) Invalid IP. Running on Serial.")
-		end
-	end
-]]
+	if (DEBUG_MODE) then
+		debug = log
+	end
+
+	-- Get the sender ID of the TCM300.
+	addToSendQueue(PACKET_TYPES.COMMON_COMMAND, COMMON_COMMAND.CO_RD_IDBASE, "", true)
+
 	debug("(EnOceanPlugin::init) Success: startup successful")
 	return true, "startup successful", "EnOcean plugin"
Index: /trunk/I_EnOceanESP3.xml
===================================================================
--- /trunk/I_EnOceanESP3.xml	(revision 1)
+++ /trunk/I_EnOceanESP3.xml	(revision 3)
@@ -10,6 +10,6 @@
 
 			-- Callbacks
-			clearTask = enoceanPlugin.clearTask
-			sendMessage = enoceanPlugin.sendMessage
+			handleRadioTelegram = enoceanPlugin.handleRadioTelegram
+			handleEventMessage = enoceanPlugin.handleEventMessage
 
 			return enoceanPlugin.init(lul_device)
