This library allows to parse and work with data sent by the Paradigma pelletti oven.

Files at this revision

API Documentation at this revision

Comitter:
leihen
Date:
Sat Jun 22 10:59:05 2013 +0000
Child:
1:9c48326ad8c9
Commit message:
Fixes

Changed in this revision

ParadigmaBase.h Show annotated file Show diff for this revision Revisions of this file
ParadigmaData.cpp Show annotated file Show diff for this revision Revisions of this file
ParadigmaData.h Show annotated file Show diff for this revision Revisions of this file
ParadigmaDateTime.h Show annotated file Show diff for this revision Revisions of this file
ParadigmaTemperature.h Show annotated file Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ParadigmaBase.h	Sat Jun 22 10:59:05 2013 +0000
@@ -0,0 +1,48 @@
+#ifndef __PARADIGMABASE_H__
+#define __PARADIGMABASE_H__
+
+
+typedef unsigned char byte;
+typedef short word;
+typedef unsigned short uword;
+typedef unsigned long ulong;
+
+
+__packed class ParadigmaDword
+{
+    protected:
+        unsigned long   m_data;
+        
+    public:
+        ParadigmaDword()    :   m_data(0)   {}
+        
+        /** On the MBED we need to swap the high and lowbytes after reading from stream. 
+          * this function will be called from reading routine.
+          */
+        void    adjustEndiness()        { m_data = ((m_data>>24)&0xFF) | ((m_data>>8)&0x0000FF00) | ((m_data<<8)&0x00FF0000) | ((m_data<<24)&0xFF000000); }
+        
+        ParadigmaDword&         operator=(ulong d)              { m_data = d; return *this; }
+        ParadigmaDword&         operator=(ParadigmaDword d)     { m_data = d.m_data; return *this; }
+        
+        operator ulong() const                                  { return m_data; }
+};
+
+__packed class ParadigmaWord
+{
+    protected:
+        unsigned short  m_data;
+        
+    public:
+        ParadigmaWord() :   m_data(0)   {}
+        
+        /** On the MBED we need to swap the high and lowbytes after reading from stream. 
+          * this function will be called from reading routine.
+          */
+        void    adjustEndiness()        { m_data = ((m_data&0xFF)<<8) | ((m_data>>8)&0xFF); }
+           
+        ParadigmaWord&          operator=(word d)               { m_data = d; return *this; }
+        ParadigmaWord&          operator=(ParadigmaWord d)      { m_data = d.m_data; return *this; }
+        
+        operator word() const                                   { return m_data; }
+};
+#endif // __PARADIGMABASE_H__
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ParadigmaData.cpp	Sat Jun 22 10:59:05 2013 +0000
@@ -0,0 +1,171 @@
+#include "ParadigmaData.h"
+
+#define DEBUG
+#include "debug.h"
+
+
+
+ParadigmaMonitorData& ParadigmaMonitorData::operator<<(char c)
+{
+    int nLen = 0;
+    if (m_activeDataBlock != Invalid) {
+        //  The actual data block had been detected already, so write into the data block
+        m_Buffer[m_actualPos++] = c;
+        //  Build checksum on the fly
+        m_checksum += c;
+        //  Now check if all bytes have been received already
+        if (m_activeDataBlock == ParadigmaMonitorDataset1) {
+            // for datablock 1
+            nLen = sizeof(m_Data1);
+            if (nLen == m_actualPos) {
+                //   all bytes received, so reset counter and check if checksum is matching
+                if (m_checksum != 0) {
+                    ERR("Data corruption error. Received invalid data ! (checksum is %02x)", m_checksum);
+                } else {
+                    memcpy(&m_Data1, m_Buffer, nLen);
+                    m_Data1.Aussentemp.adjustEndiness();
+                    m_Data1.Warmwassertemp.adjustEndiness();
+                    m_Data1.Kesselvorlauf.adjustEndiness();
+                    m_Data1.Kesselruecklauf.adjustEndiness();
+                    m_Data1.RaumtemperaturHK1.adjustEndiness();
+                    m_Data1.RaumtemperaturHK2.adjustEndiness();
+                    m_Data1.VorlauftemperaturHK1.adjustEndiness();
+                    m_Data1.VorlauftemperaturHK2.adjustEndiness();
+                    m_Data1.RuecklauftemperaturHK1.adjustEndiness();
+                    m_Data1.RuecklauftemperaturHK2.adjustEndiness();
+                    m_Data1.PuffertemperaturOben.adjustEndiness();
+                    m_Data1.PuffertemperaturUnten.adjustEndiness();
+                    m_Data1.Zirkulationstemperatur.adjustEndiness();
+                    INFO("*********************** received new data !");
+                    callBack();
+                }
+                invalidateHeader();
+            }
+        } else {
+            //  for datablock 2
+            nLen = sizeof(m_Data2);
+            if (nLen == m_actualPos) {
+                //   all bytes received, so reset counter and check if checksum is matching
+                if (m_checksum != 0) {
+                    ERR("Data corruption error. Received invalid data ! (checksum is %02x)", m_checksum);
+                } else {
+                    memcpy(&m_Data2, m_Buffer, nLen);
+                    m_Data2.RaumsollHK1.adjustEndiness();
+                    m_Data2.RaumsollHK2.adjustEndiness();
+                    m_Data2.VorlaufsollHK1.adjustEndiness();
+                    m_Data2.VorlaufsollHK2.adjustEndiness();
+                    m_Data2.Warmwassersolltemp.adjustEndiness();
+                    m_Data2.Puffersolltemp.adjustEndiness();
+                    m_Data2.BetriebsstundenKessel.adjustEndiness();
+                    m_Data2.AnzahlKesselstarts.adjustEndiness();
+                    m_Data2.StoercodeKessel.adjustEndiness();
+                    INFO("*********************** received new data !");
+                    callBack();
+                }
+                invalidateHeader();
+            }
+        }
+    } else {
+        //  Still trying to detect a valid data block, check to see if a valid address-part is here
+        switch (m_actualPos) {
+            case 0 :        // block type
+                if ( (c== ParadigmaParameters) || (c== ParadigmaVariables)) {
+                    m_Header.block_type = (ParadigmaBlockType_t)c;
+                    m_actualPos++;
+                    m_checksum = c;
+                    INFO("Block start !\n");
+                }
+                break;
+                
+            case 1 :        //  length
+                m_Header.block_length = c;
+                m_actualPos++;
+                m_checksum += c;
+                    INFO("Block len !\n");
+                break;
+                
+            case 2 :        //  Message ID
+                if ( c == ParadigmaMessage ) {
+                    m_Header.message_id = (ParadigmaMessageID_t)c;
+                    m_actualPos++;
+                    m_checksum += c;
+                } else {
+                    invalidateHeader();
+                    INFO("Rejected due to incorrect Message ID %d\n", c);
+                }
+                break;
+                
+            case 3 :        //
+                if ( (c == ParadigmaMonitorDataset1) || (c == ParadigmaMonitorDataset2)) {
+                    m_Header.dataset_type = (ParadigmaDatasetType_t)c;
+                    m_actualPos = 0;
+                    m_checksum += c;
+                    m_activeDataBlock = (ParadigmaDatasetType_t)c;
+                    INFO("Dataset Number !\n");
+                } else {
+                    invalidateHeader();
+                    INFO("Rejected due to incorrect Dataset number %d\n", c);
+                }
+                break;
+            
+            default:
+                invalidateHeader();
+                break;
+        }
+    }
+    return *this;
+}
+
+/** Function will reset all header and actual position information so that search for valid header
+ *  will be reset and starting from beginning with receival of next character.
+ *
+ *  Will have to clearup the header itsself and the checksum. Also the actual data block information
+ *  needs to be invalidated. Actual position will also be reset
+ */
+void ParadigmaMonitorData::invalidateHeader()
+{
+    //  Invalidate Header information
+    memset(&m_Header, 0, sizeof(m_Header)); 
+    //  Set active data block information to invalid
+    m_activeDataBlock = (ParadigmaDatasetType_t)Invalid; 
+    //  Reset actual position with in Buffer so that next char starts from beginning
+    m_actualPos = 0;
+    //  Reset the checksum, because it will be calculated on the fly.
+    m_checksum = 0;
+}
+
+/** Function will let user select which temperature to retrieve */
+ParadigmaTemperature ParadigmaMonitorData::getTemperature(ParadigmaTemperatureSelector_t sel)
+{
+    ParadigmaTemperature    temp;
+    switch(sel) {
+        //  Temperatures from Monitor Data 1
+        case T_aussen :             temp = m_Data1.Aussentemp; break;
+        case T_warm_wasser :        temp = m_Data1.Warmwassertemp; break;
+        case T_kessel_vorlauf :     temp = m_Data1.Kesselvorlauf; break;
+        case T_kessel_ruecklauf :   temp = m_Data1.Kesselruecklauf; break;
+        case T_HK1_raum :           temp = m_Data1.RaumtemperaturHK1; break;
+        case T_HK2_raum :           temp = m_Data1.RaumtemperaturHK2; break;
+        case T_HK1_vorlauf :        temp = m_Data1.VorlauftemperaturHK1; break;
+        case T_HK2_vorlauf :        temp = m_Data1.VorlauftemperaturHK2; break;
+        case T_HK1_ruecklauf :      temp = m_Data1.RuecklauftemperaturHK1; break;
+        case T_HK2_ruecklauf :      temp = m_Data1.RuecklauftemperaturHK2; break;
+        case T_puffer_oben :        temp = m_Data1.PuffertemperaturOben; break;
+        case T_puffer_unten :       temp = m_Data1.PuffertemperaturUnten; break;
+        case T_zirkulation :        temp = m_Data1.Zirkulationstemperatur; break;
+        
+        //  Temperatures form Monitor Data 2
+        case T_HK1_raum_soll :      temp = m_Data2.RaumsollHK1; break;
+        case T_HK2_raum_soll :      temp = m_Data2.RaumsollHK2; break;
+        case T_HK1_vorlauf_soll :   temp = m_Data2.VorlaufsollHK1; break;
+        case T_HK2_vorlauf_soll :   temp = m_Data2.VorlaufsollHK2; break;
+        case T_warm_wasser_soll :   temp = m_Data2.Warmwassersolltemp; break;
+        case T_puffer_soll :        temp = m_Data2.Puffersolltemp; break;
+        
+        default:    // Invalid selecion !
+            ERR("**** An unknown selection for the temperature was made !");
+            break;
+    }
+    
+    return temp;
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ParadigmaData.h	Sat Jun 22 10:59:05 2013 +0000
@@ -0,0 +1,211 @@
+#ifndef __PARADIGMA_DATA_H__
+#define __PARADIGMA_DATA_H__
+
+#include "mbed.h"
+#include "ParadigmaBase.h"
+#include "ParadigmaTemperature.h"
+#include "ParadigmaDateTime.h"
+
+#include <string>
+using namespace std;
+
+/** ParadigmaBlockType_t enumerates valid values for the block type. The block type is always the first 
+  * data byte in a response from paradigma. There are currently two known values.
+  */
+typedef __packed enum {
+    ParadigmaVariables = 0xFC,
+    ParadigmaParameters = 0xFD,
+} ParadigmaBlockType_t;
+
+/** ParadigmaMessageID_t specifies the content of the transmitted object. Currently only one valid value
+  * is known which indicates a valuid variable or parameter block is being transmitted */
+typedef __packed enum {
+    ParadigmaMessage = 0x0C,
+} ParadigmaMessageID_t;
+
+/** ParadigmaDatasetType_t specifies which type of information is contained in the datablock. Currently 
+  * known values are : Dataset1 and Dataset2 for Variables, and Parameters for different settings which
+  * can be changed and queried by the user.
+  */
+typedef __packed enum {
+    ParadigmaMonitorDataset1 = 0x01,
+    ParadigmaMonitorDataset2 = 0x02,
+    ParadigmaParameterset = 0x03,
+    ParadigmaUnknown1 = 0x14,
+    Invalid = 0xFF
+} ParadigmaDatasetType_t;
+
+typedef char ParadigmaParameterAddress_t[3];
+
+const ParadigmaParameterAddress_t ParadigmaAdresses[] = {
+    {0x00, 0x02, 0x2A},      //  Heizkreis 1
+    {0x01, 0x88, 0x2A},      //  Heizkreis 2
+    {0x03, 0x0E, 0x09},      //  Warmwasser
+    {0x03, 0xF7, 0x0F},      //  Anlagendaten Kessel/Puffer und Zirkulation
+    {0x03, 0xE6, 0x12},      //  Wartung Telefonnummer
+    {0x03, 0x17, 0x70},      //  Warmwasserprogramm 1
+    {0x03, 0x87, 0x70},      //  Warmwasserprogramm 2
+    {0x04, 0x06, 0x70},      //  Zirkulationszeitprogramm 1
+    {0x04, 0x76, 0x70},      //  Zirkulationszeitprogramm 2
+    {0x00, 0x2C, 0x70},      //  Heizzeitprogramm 1 HK1
+    {0x00, 0x9C, 0x70},      //    Heizzeitprogramm 2 HK1
+    {0x01, 0x0C, 0x70},     // Heizzeitprogramm 3 HK1
+    {0x01, 0xB2, 0x70},     // Heizzeitprogramm 1 HK2
+    {0x02, 0x22, 0x70},     //  Heizzeitprogramm 2 HK2
+    {0x02, 0x92, 0x70},     //  Heizzeitprogramm 3 HK2
+    {0x05, 0x08, 0x03}      //  Anlagendaten Kessel/Puffer 2
+};
+
+/** ParadigmaBlockHeader_t represents the header of any sent block by paradigma. */
+typedef __packed struct {
+    ParadigmaBlockType_t        block_type;         // 0xFC for normal observable variables, 0xFD for parameter blocks
+    unsigned char               block_length;
+    ParadigmaMessageID_t        message_id;         // always 0x0C
+    ParadigmaDatasetType_t      dataset_type;  
+} ParadigmaBlockHeader_t;
+
+typedef __packed struct {
+    ParadigmaDateTime           DateTime;
+    ParadigmaTemperature        Aussentemp;             //  (in 0,1 Grad Schritten)
+    ParadigmaTemperature        Warmwassertemp;         //  (in 0,1 Grad Schritten)
+    ParadigmaTemperature        Kesselvorlauf;          //  (in 0,1 Grad Schritten)
+    ParadigmaTemperature        Kesselruecklauf;        //  (in 0,1 Grad Schritten)
+    
+    ParadigmaTemperature        RaumtemperaturHK1;      //  (in 0,1 Grad Schritten)
+    ParadigmaTemperature        RaumtemperaturHK2;      //  (in 0,1 Grad Schritten)
+    ParadigmaTemperature        VorlauftemperaturHK1;   //  (in 0,1 Grad Schritten)
+    ParadigmaTemperature        VorlauftemperaturHK2;   //  (in 0,1 Grad Schritten)
+    ParadigmaTemperature        RuecklauftemperaturHK1; //  (in 0,1 Grad Schritten)
+    ParadigmaTemperature        RuecklauftemperaturHK2; //  (in 0,1 Grad Schritten)
+    ParadigmaTemperature        PuffertemperaturOben;   //  (in 0,1 Grad Schritten)
+    ParadigmaTemperature        PuffertemperaturUnten;  //  (in 0,1 Grad Schritten)
+    ParadigmaTemperature        Zirkulationstemperatur; //  (in 0,1 Grad Schritten)
+
+    byte                        Checksumme;
+} MonDta1_t;
+
+typedef __packed struct {
+    ParadigmaTemperature        RaumsollHK1;
+    ParadigmaTemperature        RaumsollHK2;
+    ParadigmaTemperature        VorlaufsollHK1;
+    ParadigmaTemperature        VorlaufsollHK2;
+    ParadigmaTemperature        Warmwassersolltemp;
+    ParadigmaTemperature        Puffersolltemp;
+    __packed struct {
+        word    PHK1:1;
+        word    PHK2:1;
+        word    PK:1;
+        word    Mischer1Auf:1;
+        word    Mischer1Zu:1;
+        word    Mischer2Auf:1;
+        word    Mischer2Zu:1;
+        word    ULV:1;
+        word    PZ:1;
+        word    B1:1;
+        word    Taster:1;
+        word    LONModul:1;
+        word    OTModul:1;
+        word    reserver:3;
+    }           ZustandAusgaenge;
+    ParadigmaDword              BetriebsstundenKessel;
+    ParadigmaDword              AnzahlKesselstarts;
+    ParadigmaWord               StoercodeKessel;
+    byte                        StoercodeFuehler;
+    byte                        BetriebsartHK1;
+    byte                        NiveauHK1;
+    byte                        BetriebsartHK2;
+    byte                        NiveauHK2;
+    byte                        LeistungPHK1;
+    byte                        LeistungPHK2;
+    byte                        LeistungPK;
+    
+    byte                        Checksumme;        
+} MonDta2_t;
+
+
+/** Class ParadigmaMonitorData encapsulates the data representation and parsing of the
+  * data blocks that are being sent by the paradigma heater. The class also provides
+  * a stream type functionality to detect and parse the data from a stream of chars.
+  */
+class ParadigmaMonitorData
+{
+        FunctionPointer         m_Callback;
+        
+        MonDta1_t               m_Data1;
+        MonDta2_t               m_Data2;
+        
+        char                    m_Buffer[50];
+        ParadigmaBlockHeader_t  m_Header;
+        ParadigmaDatasetType_t  m_activeDataBlock;
+        int                     m_actualPos;
+        char                    m_checksum;
+        
+        void                    invalidateHeader();
+        void                    callBack()  { m_Callback.call(); }
+        word                    swapWord(word d) { return ((d&0xFF)<<8) | ((d>>8)&0xFF); }
+        ulong                   swapDWord(ulong d) { return ((d>>24)&0xFF) | ((d>>8)&0x0000FF00) | ((d<<8)&0x00FF0000) | ((d<<24)&0xFF000000); }
+    public:
+        /** Public constructor. Will initialize all internal data and variables. */
+        ParadigmaMonitorData(): m_checksum(0)  {  memset(&m_Data1, 0, sizeof(m_Data1)); memset(&m_Data2, 0, sizeof(m_Data2)); invalidateHeader(); }
+        /** Access function to get the transmitted date time object.
+          * @returns : the date and time objects of the transmitted data.
+          */
+        ParadigmaDateTime getDateTime()                     { return m_Data1.DateTime; }
+        /** Access function to the Outside air temperature (AUSSENTEMP).
+          * @returns : the outside air temperature.
+          */
+        ParadigmaTemperature getAussentemp()                { return m_Data1.Aussentemp; }
+        /** Access function to the warm water temperature (WARMWASSERTEMP).
+          * @returns : the warm water temperature.
+          */
+        ParadigmaTemperature getWarmwassertemp()            { return m_Data1.Warmwassertemp; }
+        /** Access function to the 'kessel vorlauf' temperature.
+          * @returns : the temperature of the 'kessel vorlauf'.
+          */
+        ParadigmaTemperature getKesselvorlauf()             { return m_Data1.Kesselvorlauf; }
+        /** Access function to the 'kessel ruecklauf' temperature.
+          * @returns : the temperature of the 'kessel ruecklauf'.
+          */
+        ParadigmaTemperature getKesselruecklauf()           { return m_Data1.Kesselruecklauf; }
+        /** Access function to the room temperature of heating circuit 1.
+          * @returns : the room temperature of heating circuit 1.
+          */
+        ParadigmaTemperature getRaumtemperaturHK1()         { return m_Data1.RaumtemperaturHK1; }
+        /** Access function to the room temperature of heating circuit 2.
+          * @returns : the room temperature of heating circuit 2.
+          */
+        ParadigmaTemperature getRaumtemperaturHK2()         { return m_Data1.RaumtemperaturHK2; }
+        ParadigmaTemperature getVorlauftemperaturHK1()      { return m_Data1.VorlauftemperaturHK1; }
+        ParadigmaTemperature getVorlauftemperaturHK2()      { return m_Data1.VorlauftemperaturHK2; }
+        ParadigmaTemperature getRuecklauftemperaturHK1()    { return m_Data1.RuecklauftemperaturHK1; }
+        ParadigmaTemperature getRuecklauftemperaturHK2()    { return m_Data1.RuecklauftemperaturHK2; }
+        ParadigmaTemperature getPuffertemperaturOben()      { return m_Data1.PuffertemperaturOben; }
+        ParadigmaTemperature getPuffertemperaturUnten()     { return m_Data1.PuffertemperaturUnten; }
+        ParadigmaTemperature getZirkulationstemperatur()    { return m_Data1.Zirkulationstemperatur; }
+        
+        ParadigmaTemperature getRaumsollHK1()               { return m_Data2.RaumsollHK1;}
+        ParadigmaTemperature getRaumsollHK2()               { return m_Data2.RaumsollHK2;}
+        ParadigmaTemperature getVorlaufsollHK1()            { return m_Data2.VorlaufsollHK1;}
+        ParadigmaTemperature getVorlaufsollHK2()            { return m_Data2.VorlaufsollHK2;}
+        ParadigmaTemperature getWarmwassersolltemp()        { return m_Data2.Warmwassersolltemp;}
+        ParadigmaTemperature getPuffersolltemp()            { return m_Data2.Puffersolltemp;}
+        
+        /** Function will let the user select the temperature to be returned.
+          * @param sel : Will specify which temperature value to return.
+          * @returns : the temperature object as selected by param sel.
+          */
+        ParadigmaTemperature getTemperature(ParadigmaTemperatureSelector_t sel);
+        
+        ulong               getBetriebsstundenKessel()      { return (ulong)m_Data2.BetriebsstundenKessel; }
+        ulong               getAnzahlKesselstarts()         { return (ulong)m_Data2.AnzahlKesselstarts; }
+        word                getStoercodeKessel()            { return (word)m_Data2.StoercodeKessel; }
+        byte                getStoercodeFuehler()           { return (byte)m_Data2.StoercodeFuehler; }
+        
+        
+        ParadigmaMonitorData& operator<<( char c );
+        ParadigmaMonitorData& operator<<( char Buffer[] );
+        
+        void attach( void (*fct)(void) )    { m_Callback.attach(fct);}
+};
+
+#endif
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ParadigmaDateTime.h	Sat Jun 22 10:59:05 2013 +0000
@@ -0,0 +1,32 @@
+#ifndef __PARADIGMADATETIME_H__
+#define __PARADIGMADATETIME_H__
+
+#include <string>
+
+__packed class ParadigmaDateTime
+{
+    protected:
+        int                 bcdToDec(char n) const { return (((unsigned)n)>>4)*10 + (n&0x0f); }
+
+    private:
+        unsigned char       m_Date;
+        unsigned char       m_Month;
+        unsigned char       m_Minute;
+        unsigned char       m_Hour;
+        
+
+    public:
+        ParadigmaDateTime()  : m_Date(0), m_Month(0), m_Minute(0), m_Hour(0) {}
+        
+        operator string() const                 { char Buffer[15]; sprintf(Buffer, "%02d.%02d, %02d:%02d", getDate(), getMonth(), getHour(), getMinute()); return Buffer; }
+        
+        std::string         getDateString()     { char Buffer[15]; sprintf(Buffer, "%02d.%02d", getDate(), getMonth()); return Buffer; }
+        std::string         getTimeString()     { char Buffer[15]; sprintf(Buffer, "%02d:%02d", getHour(), getMinute()); return Buffer; }
+        
+        unsigned char       getDate() const     { return bcdToDec(m_Date); }
+        unsigned char       getMonth() const    { return bcdToDec(m_Month); }
+        unsigned char       getMinute() const   { return bcdToDec(m_Minute); }
+        unsigned char       getHour() const     { return bcdToDec(m_Hour); }
+};
+
+#endif // __PARADIGMADATETIME_H__
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ParadigmaTemperature.h	Sat Jun 22 10:59:05 2013 +0000
@@ -0,0 +1,55 @@
+#ifndef __PARADIGMATEMPERATURE_H__
+#define __PARADIGMATEMPERATURE_H__
+
+#include <string>
+#include "ParadigmaBase.h"
+
+
+
+typedef enum {
+    //  Temperatures from Monitor Data 1
+    T_aussen,
+    T_warm_wasser,
+    T_kessel_vorlauf,
+    T_kessel_ruecklauf,
+    T_HK1_raum,
+    T_HK2_raum,
+    T_HK1_vorlauf,
+    T_HK2_vorlauf,
+    T_HK1_ruecklauf,
+    T_HK2_ruecklauf,
+    T_puffer_oben,
+    T_puffer_unten,
+    T_zirkulation,
+    //  Temperatures form Monitor Data 2
+    T_HK1_raum_soll,
+    T_HK2_raum_soll,
+    T_HK1_vorlauf_soll,
+    T_HK2_vorlauf_soll,
+    T_warm_wasser_soll,
+    T_puffer_soll
+} ParadigmaTemperatureSelector_t;
+
+
+__packed class ParadigmaTemperature 
+{
+    unsigned short m_temp;
+    
+    public:
+        ParadigmaTemperature() : m_temp(0) {}
+        
+        operator string() const { char Buffer[14]; sprintf(Buffer, "%3d,%1d C", m_temp/10, m_temp%10); return Buffer; }
+        operator float() const { return ((float)m_temp)/10.0f; }
+        
+        ParadigmaTemperature& operator=(float f) { m_temp = (int)ceil(f*10.0f); return *this; }
+        ParadigmaTemperature& operator=(ParadigmaTemperature &p) { m_temp = p.m_temp; return *this; }
+        
+    public:
+        
+        /** On the MBED we need to swap the high and lowbytes after reading from stream. 
+          * this function will be called from reading routine.
+          */
+        void    adjustEndiness()        { m_temp = ((m_temp&0xFF)<<8) | ((m_temp>>8)&0xFF); }
+};
+
+#endif
\ No newline at end of file