Test program to send MAX!-Messages with a RFM22-Module

Dependencies:   RF22 TextLCD TextLCDScroll mbed RF22Max

Revision:
3:4254b4c3557e
Parent:
2:941c46d37d7e
Child:
4:6c72714f5886
--- a/main.cpp	Tue Aug 20 20:22:43 2013 +0000
+++ b/main.cpp	Mon Sep 09 19:47:45 2013 +0000
@@ -1,8 +1,10 @@
-// Testprogramm for RFM22B with RF22-Library to read ELV MAX! window Shutter-Contacts
+// Testprogramm for RFM22B with RF22-Library to read ELV MAX! window Shutter-Contacts and PushBottons
+// Quick and dirty code!!!!!!
+// needs refactoring
+
 
 #include "mbed.h"
 #include <RF22.h>
-
 #include "TextLCDScroll.h"
 
 
@@ -10,6 +12,9 @@
 
 Serial pc(USBTX, USBRX);
 
+//Freebus-RS-Interface connected to serial
+Serial knxrs(p9, p10);  // tx, rx
+
 //TextLCDScroll lcd(p30, p29, p28, p27, p26, p25, TextLCD::LCD16x2); // rs, e, d4-d7
 TextLCDScroll lcd(p30, p29, p28, p27, p26, p25, TextLCD::LCD16x2); // rs, e, d4-d7
 
@@ -19,6 +24,30 @@
 DigitalOut led3(LED3);
 DigitalOut led4(LED4);
 
+struct max_knx_mapping_t {
+    uint32_t         device_id;
+    char             knx_adr[255];
+};
+
+#define MAX_KNX_MAPPINGS 10
+
+// a message from the max!-Device
+struct max_message {
+    uint8_t    len;                //message-length
+    uint8_t    cnt;                //message-counter
+    uint8_t    flags;              // ??
+    uint8_t    type;               //message-type
+    char       type_str[50];       // type in text
+    uint32_t   frm_adr;            // unique address of device
+    uint32_t   to_adr;             // unique address of device
+    uint8_t    groupid;            //groupid
+    uint8_t    payload[50];        // data
+    uint16_t   crc;                // crc fro the message
+    char       state[50];          // state of the device: open, closed, auto, eco,...
+    char       battery_state[50];  // Battery-state of the device : good, low
+};
+
+
 
 // Singleton instance of the radio
 //rf22(PinName slaveSelectPin , PinName mosi, PinName miso, PinName sclk, PinName interrupt );
@@ -232,15 +261,22 @@
 }
 
 
-void max_rx_loop()
+max_message max_rx_msg()
 {
     uint8_t buf[RF22_MAX_MESSAGE_LEN];
+
     uint8_t len = sizeof(buf);
+    uint8_t sbuf[RF22_MAX_MESSAGE_LEN];
+    uint8_t slen = 0;
+
+    max_message message;               // holds a message from the max device
+
+    message.len = 0;
 
     if (rf22.recv(buf, &len)) {
         pc.printf("Recv: ");
         pc.printf("len: %i\n\r",len);
-        len = 30;  // limit message to 30 Bytes as device receives all 255 Bytes
+        len = 50;  // limit message to 50 Bytes as device receives all 255 Bytes
 
         //pc.printf("buf: >%s<\n\r",(char*)buf);
         printHex(buf, len, true);
@@ -255,7 +291,7 @@
 
         if (len < 3 || len > lengthof(pn9)) {
             pc.printf("Packet length too short/long (%i)\n\r",len);
-            return;
+            return message;
         }
         pc.printf("dewhiten: ");
         printHex(buf, len, true);
@@ -263,15 +299,27 @@
         /* Calculate CRC (but don't include the CRC itself) */
         uint16_t crc = calc_crc(buf, len - 2);
         if (buf[len - 1] != (crc & 0xff) || buf[len - 2] != (crc >> 8)) {
-            pc.printf("CRC error\n\r");
-            return;
+            pc.printf("CRC error: CRC: %04X\n\r",crc);
+            //return;
         }
 
         /* Don't use the CRC as data */
         len -= 2;
 
         uint8_t type = buf[3];
-#if 1
+
+        message.len     = len;                   //message-length
+        message.cnt     = buf[1];                //message-counter
+        message.flags   = buf[2];
+        message.type    = type;
+        strcpy(message.type_str,type_str(type));
+        message.frm_adr = buf[4]<<16 | buf[5]<<8| buf[6];            // unique address of device
+        message.to_adr  = buf[7]<<16 | buf[8]<<8| buf[9]; ;             // unique address of device
+        message.groupid = buf[10];            //groupid
+        memcpy( (void *) message.payload, (void *) buf[11],len-11);               // data
+        message.crc     = buf[len-2]<<8 | buf[len-1];                // crc for the message
+
+
         pc.printf("Message count: ");
         printHex(buf + 1, 1, true);
         pc.printf("Flags:         ");
@@ -289,27 +337,97 @@
         printHex(buf + 10, 1, true);
         pc.printf("Payload:       ");
         printHex(buf + 11, len-11, true);
+        //pc.printf("Payload:      >%s<\n\r",(char*)buf+11);
 
+        lcd.setLine(1,"");
         if (type == 0x30 && len >= 11) { //ShutterContactState
             bool baterry_low = (buf[11] >> 7) & 0x1;
             bool state = (buf[11]>>1) & 0x1;
+
             pc.printf("State:      ");
             if (state) {
+                strcpy(message.state,"open");
                 pc.printf("open\n\r");
                 lcd.setLine(1,"open   ");
             } else {
+                strcpy(message.state,"closed");
                 pc.printf("closed\n\r");
                 lcd.setLine(1,"closed ");
             }
             pc.printf("Battery:    ");
             if (baterry_low) {
                 pc.printf("low\n\r");
+                strcpy(message.battery_state,"low");
             } else {
                 pc.printf("good\n\r");
+                strcpy(message.battery_state,"good");
+            }
+        }
+
+        if (type == 0x50 && len >= 11) { //PushButtonState
+            bool baterry_low = (buf[11] >> 7) & 0x1;    // to validate!!!
+            bool state = (buf[12]) & 0x1;
+
+            pc.printf("State:      ");
+            if (state) {
+                strcpy(message.state,"auto");
+                pc.printf("auto\n\r");
+                lcd.setLine(1,"auto");
+            } else {
+                strcpy(message.state,"eco");
+                pc.printf("eco\n\r");
+                lcd.setLine(1,"eco");
+            }
+            pc.printf("Battery:    ");
+            if (baterry_low) {
+                pc.printf("low\n\r");
+                strcpy(message.battery_state,"low");
+            } else {
+                pc.printf("good\n\r");
+                strcpy(message.battery_state,"good");
             }
 
         }
 
+
+
+#if 0
+        if (type == 0x00 && len >= 11) { //PairPing
+            char serial[20]="";
+            strncpy(serial,(char*)buf+14,10); //10 Characters for Seial Number
+            serial[11] = '\0';
+            pc.printf("Serial:        %s\n\r",serial);
+
+            // try to send PairPong
+            // wait some time
+            wait_ms(10);
+            sbuf[0] = 11; // MsgLen
+            sbuf[1] = buf[1]+1 &0xFF; // MsgCount ??
+            sbuf[2] = 0x00; // Flag
+            sbuf[3] = 0x01; // Type = Cmd = PairPong
+            sbuf[4] = 0x11; // From Fake Address
+            sbuf[5] = 0x11; // From
+            sbuf[6] = 0x11; // From
+            sbuf[7] = buf[4] ; // To Address = From address of Windowcontact
+            sbuf[8] = buf[5] ;
+            sbuf[9] = buf[6] ;
+            sbuf[10] = 0x00; // GroupId
+            sbuf[11] = 0x00;  //Payload is 0x00 for pairpong?
+            slen = 12+2; //+2Byte CRC????
+            /* Calculate CRC */
+            uint16_t scrc = calc_crc(sbuf, slen - 2);
+            sbuf[12] = crc >> 8;
+            sbuf[13] = crc & 0xff;
+
+
+            if (rf22.send(sbuf,slen)) {
+                pc.printf("Send PairPong OK\n\r");
+            } else {
+                pc.printf("Send PairPong NOT OK\n\r");
+            }
+
+        }
+#endif
         /*
                 else if (type == 0x60 && len >= 13) { // ThermostatState
                     uint8_t mode = buf[11] & 0x3;
@@ -374,24 +492,54 @@
                     pc.println("");
                 }
         */
+
         pc.printf("\n\r");
-#endif
     }
+    return message;
 }
 
+
 int main()
 {
 
+    char group[255];                          // the KNX-Group-address
+    char command[255];                        // a command to send to the freebus rs-interface
+    char lcdline[255];
+
+    max_message MyMessage;
+    int  i;
+
+
+
+    max_knx_mapping_t max_knx_map[MAX_KNX_MAPPINGS];
+
+    //Mapping of MAX!-Device-IDs to KNX-Group-addresses
+    max_knx_map[0].device_id = 0x04B5F7;      // MAX!-Pushbutton
+    strcpy(max_knx_map[0].knx_adr,"3/1/1");   // PushButton01 = Licht Büro
+
+    max_knx_map[1].device_id = 0x04B5B9;      // MAX!-Pushbutton
+    sprintf(max_knx_map[1].knx_adr, "3/1/2"); // Pushbutton 02 = Licht Carina
+
+
+
     pc.baud(115200);
 
     pc.printf("\n\rConnected to mbed\n\r");
 
 
-    char version_str [80] = "RF22-MAX!-V1.1";
+    char version_str [80] = "RF22-MAX!-V2.5";
     lcd.cls();
     lcd.setLine(0,version_str);
     pc.printf("%s\n\r",version_str);
 
+
+    // initialize freebus-rs-interface
+    // 115.200 Baud,n,8,1
+    knxrs.baud(115200);
+
+    knxrs.printf("fbecho=0\r");   //switch off echo
+
+
     pc.printf("Pre-init|");
     if (!rf22.init())
         pc.printf("RF22 init failed\n\r");
@@ -415,18 +563,50 @@
     rf22.spiWrite(RF22_REG_35_PREAMBLE_DETECTION_CONTROL1, (0x4 << 3));
     /* Send 8 bytes of preamble */
     rf22.setPreambleLength(8); // in nibbles
-    rf22.spiWrite(RF22_REG_3E_PACKET_LENGTH, 20);
+    rf22.spiWrite(RF22_REG_3E_PACKET_LENGTH, 30); // maximum length of a MAX!-packet
 
 
     rf22.setModeRx();
 
 
 
-    //wait forever and see if interrrupt  occurs(led1)
+    //wait forever and see what comes in
     while (1) {
 
-        max_rx_loop();
-    };
+        // look for a message
+        MyMessage = max_rx_msg();
+        // did we get a MAX!-Message?
+        if (MyMessage.len > 0) {
+            // we got a message
+            pc.printf("Got Message type: %s Msg-Nr:%i from Device-ID:%06X State:%s Battery %s\n\r", MyMessage.type_str,MyMessage.cnt, MyMessage.frm_adr, MyMessage.state, MyMessage.battery_state);
+
+            // should we send an KNX-command?
+            strcpy(group ,"");
+            for (i=0; i< MAX_KNX_MAPPINGS; i++) {
+                if (max_knx_map[i].device_id == MyMessage.frm_adr) {
+                    strcpy(group ,max_knx_map[i].knx_adr);
+                }
+            }
+
+            if (strlen(group) > 0) {
+                sprintf(command, "fbs01/%s=%s\r",group,(strcmp(MyMessage.state,"auto")) ? "0" : "1");  // EIS01 on Group-address group : auto=1 eco=0
+                // Send a KNX-Telegramm
+                knxrs.printf("%s",command);
+                pc.printf("%s\n\r",command);
+                sprintf(lcdline,"Got Message type: %s Msg-Nr:%i from Device-ID:%06X State:%s Battery %s. Sending to KNX:%s",
+                              MyMessage.type_str,MyMessage.cnt, MyMessage.frm_adr, MyMessage.state, MyMessage.battery_state,command);
+                lcd.setLine(1,lcdline);
+            } else {
+                // device not found in mapping
+                pc.printf("new unknown device!\n\r");
+                sprintf(lcdline,"Got Message type: %s Msg-Nr:%i from Device-ID:%06X State:%s Battery %s. Unknown New Device",
+                              MyMessage.type_str,MyMessage.cnt, MyMessage.frm_adr, MyMessage.state, MyMessage.battery_state);
+                lcd.setLine(1,lcdline);
+            }
+
+        }
+
+    }
 }