diff --git a/programs/umnp-rhtp.py b/programs/umnp-rhtp.py
index 68c8c8006aabbc40a0cbd5afa7a25fb43f333969..6f0518e2bc9b7ddeb44b1d06dd72f4c055f9c46e 100644
--- a/programs/umnp-rhtp.py
+++ b/programs/umnp-rhtp.py
@@ -1,10 +1,12 @@
 import sys
 
+from umnp.devices import DEVICE_TYPE_RHTP
 from umnp.microcontroller.devices.network.ethernet_w5500 import EthernetW5500
 from umnp.microcontroller.measurementdevice import MeasurementDevice
 from umnp.microcontroller.sensors.lps28dfw import LPS28DFW
 from umnp.microcontroller.sensors.sht45 import SHT45
 from umnp.microcontroller.tasks.periodictask import PeriodicTask
+from umnp.protocol.data_message import DataMessage
 
 if sys.implementation.name == "micropython":
     # noinspection PyUnresolvedReferences
@@ -20,15 +22,17 @@ async def aggregate_and_send(
     device: MeasurementDevice, sht45: SHT45, p_sensor: LPS28DFW
 ):
     comm = device.communicator
+
     t, rh = await sht45.measure()
     p, p_t = await p_sensor.measure()
     data = f"{t},{rh},{p},{p_t}"
-    await comm.send_data_message(data)
+    msg = DataMessage(data, device.identifier_raw, device.device_type)
+    await comm.send_message(msg)
 
 
 async def main():
     # configure network
-    device = MeasurementDevice()
+    device = MeasurementDevice(device_type=DEVICE_TYPE_RHTP)
     spi = machine.SPI(
         0, 2_000_000, mosi=machine.Pin(19), miso=machine.Pin(16), sck=machine.Pin(18)
     )
diff --git a/umnp/devices/__init__.py b/umnp/devices/__init__.py
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..1be4e0a26df5111a5d10d35d36b1e887fffcac57 100644
--- a/umnp/devices/__init__.py
+++ b/umnp/devices/__init__.py
@@ -0,0 +1,2 @@
+DEVICE_TYPE_UNKNOWN = 0
+DEVICE_TYPE_RHTP = 1
diff --git a/umnp/microcontroller/communication/udp_communicator.py b/umnp/microcontroller/communication/udp_communicator.py
index c099ef72830112f60f0e7d77c7cdf46e3540d592..33508394cb65500c147cbf7b204e179129ffb4de 100644
--- a/umnp/microcontroller/communication/udp_communicator.py
+++ b/umnp/microcontroller/communication/udp_communicator.py
@@ -3,6 +3,7 @@ import time
 
 from umnp.microcontroller.devices.network.udp import UDPSender, UDPReceiver
 from umnp.microcontroller.tasks.periodictask import PeriodicTask
+from umnp.protocol.message import Message
 
 if sys.implementation.name == "micropython":
     # noinspection PyUnresolvedReferences
@@ -12,12 +13,19 @@ if sys.implementation.name == "micropython":
     import machine
 else:
     import asyncio
-    from umnp.microcontroller.umock import machine
+    from typing import TYPE_CHECKING
+
+    if TYPE_CHECKING:
+        from umnp.microcontroller.measurementdevice import MeasurementDevice
 
 
 class UDPCommunicator:
     def __init__(
-        self, sender: UDPSender, receiver: UDPReceiver, device_id, max_msgs: int = 10
+        self,
+        sender: UDPSender,
+        receiver: UDPReceiver,
+        device: "MeasurementDevice",
+        max_msgs: int = 10,
     ):
         self._receive_lock = asyncio.Lock()
         self._send_lock = asyncio.Lock()
@@ -28,7 +36,7 @@ class UDPCommunicator:
         self._sender = sender
         self._receiver = receiver
         self._tasks = {}
-        self._device_id = device_id
+        self._device = device
 
     async def queue_incoming_message(self, msg, source):
         async with self._receive_lock:
@@ -49,43 +57,30 @@ class UDPCommunicator:
             await asyncio.sleep(0.500)
 
     async def send_task(self):
-        device_id = self._device_id
-        rtc = machine.RTC()
-
         while True:
             msg = None
             async with self._send_lock:
                 if len(self._messages_send_queue) > 0:
                     msg = self._messages_send_queue.pop()
 
-            if msg is not None:
-                msg = msg.replace(",", ";")
-                now = rtc.datetime()
-                now = "%04d-%02d-%02dT%02d:%02d:%02d" % (
-                    now[0],
-                    now[1],
-                    now[2],
-                    now[4],
-                    now[5],
-                    now[6],
-                )
-                await self._sender.broadcast("%s,%s,%s" % (device_id, now, msg))
+            if msg is None:
+                await asyncio.sleep(0.5)
+                continue
+
+            if isinstance(msg, Message):
+                await self._sender.broadcast(msg.encode())
 
             await asyncio.sleep(0.5)
 
-    async def send_data_message(self, data: str):
-        async with self._send_lock:
-            self._messages_send_queue.append(data)
+    async def send_message(self, msg: Message):
+        self._messages_send_queue.append(msg)
 
     async def control_task(self):
         while True:
             async with self._receive_lock:
-                # print("Control: %d" % len(self.msgs))
                 msg = await self.get_newest_message()
                 if msg is not None:
                     pass
-                # print("Controll::msg::", msg)
-
             await asyncio.sleep(0.5)
 
     async def start(self):
diff --git a/umnp/microcontroller/measurementdevice.py b/umnp/microcontroller/measurementdevice.py
index 3e00519c85013978158f2ede5c34a937544a5b07..45330d15ae4430ee2339cbad36f947c31cd02fe6 100644
--- a/umnp/microcontroller/measurementdevice.py
+++ b/umnp/microcontroller/measurementdevice.py
@@ -2,6 +2,7 @@ import binascii
 import sys
 import time
 
+from umnp.devices import DEVICE_TYPE_UNKNOWN
 from umnp.microcontroller.communication.udp_communicator import UDPCommunicator
 from umnp.microcontroller.devices.network.udp import (
     UDPSender,
@@ -19,7 +20,7 @@ else:
 
 
 class MeasurementDevice:
-    def __init__(self):
+    def __init__(self, device_type: int = DEVICE_TYPE_UNKNOWN):
         self._boot_time = time.time()
         self._identifier_raw = machine.unique_id()
         self._identifier = binascii.hexlify(self.identifier_raw).decode(
@@ -29,6 +30,11 @@ class MeasurementDevice:
         self._sender = None
         self._receiver = None
         self._communicator = None
+        self._type = device_type
+
+    @property
+    def device_type(self):
+        return self._type
 
     @property
     def boot_time(self):
diff --git a/umnp/protocol/__init__.py b/umnp/protocol/__init__.py
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..6ef410d6c535a3cd42e03fc3be65d2031a3fa9ff 100644
--- a/umnp/protocol/__init__.py
+++ b/umnp/protocol/__init__.py
@@ -0,0 +1,5 @@
+from umnp.protocol.data_message import DataMessage
+from umnp.protocol.messagetype import MessageType
+from umnp.protocol.register_messages import register_messages
+
+register_messages(MessageType.MSG_DEVICE_DATA, DataMessage)
diff --git a/umnp/protocol/message.py b/umnp/protocol/message.py
index b3d5822958ed131fa20cafa4712ff120ebed36d0..17330f8b8130d0cfe7268be930affccba4f1805a 100644
--- a/umnp/protocol/message.py
+++ b/umnp/protocol/message.py
@@ -49,8 +49,8 @@ class Message:
     @classmethod
     def add_message_type(cls, msg_type: int, msg: typing.Type["Message"]):
         if msg_type in cls._registered_types:
-            logging.info(f"Already registered {msg_type}")
             return
+        print(f"Registering message type {msg_type}")
         cls._registered_types[msg_type] = msg
 
     @classmethod