int main(void) { uint8_t aes_key_nr; uint8_t loop = 0; uint8_t loop2 = 0; // delay 1s to avoid further communication with uart or RFM12 when my programmer resets the MC after 500ms... _delay_ms(1000); util_init(); check_eeprom_compatibility(DEVICETYPE_BASESTATION); request_queue_init(); // read packetcounter, increase by cycle and write back packetcounter = e2p_generic_get_packetcounter() + PACKET_COUNTER_WRITE_CYCLE; e2p_generic_set_packetcounter(packetcounter); // read device specific config aes_key_count = e2p_basestation_get_aeskeycount(); device_id = e2p_generic_get_deviceid(); uart_init(); UART_PUTS("\r\n"); UART_PUTF4("smarthomatic Base Station v%u.%u.%u (%08lx)\r\n", VERSION_MAJOR, VERSION_MINOR, VERSION_PATCH, VERSION_HASH); UART_PUTS("(c) 2012..2014 Uwe Freese, www.smarthomatic.org\r\n"); UART_PUTF("Device ID: %u\r\n", device_id); UART_PUTF("Packet counter: %lu\r\n", packetcounter); UART_PUTF("AES key count: %u\r\n", aes_key_count); UART_PUTS("Waiting for incoming data. Press h for help.\r\n\r\n"); led_blink(500, 500, 3); rfm12_init(); sei(); // ENCODE TEST (Move to unit test some day...) /* uint8_t testlen = 32; uint8_t aes_key_num = 0; memset(&bufx[0], 0, sizeof(bufx)); bufx[0] = 0xff; bufx[1] = 0xb0; bufx[2] = 0xa0; bufx[3] = 0x3f; bufx[4] = 0x01; bufx[5] = 0x70; bufx[6] = 0x00; bufx[7] = 0x0c; bufx[8] = 0xa8; bufx[9] = 0x00; bufx[10] = 0x20; bufx[20] = 0x20; eeprom_read_block (aes_key, (uint8_t *)(EEPROM_AESKEYS_BYTE + aes_key_num * 32), 32); UART_PUTS("Using AES key "); print_bytearray((uint8_t *)aes_key, 32); UART_PUTS("Before encryption: "); print_bytearray(bufx, testlen); uint8_t aes_byte_count = aes256_encrypt_cbc(bufx, testlen); UART_PUTF("byte count = %u\r\n", aes_byte_count); UART_PUTS("After encryption: "); print_bytearray(bufx, aes_byte_count); aes256_decrypt_cbc(bufx, aes_byte_count); UART_PUTS("After decryption: "); print_bytearray(bufx, testlen); while(1); */ while (42) { if (rfm12_rx_status() == STATUS_COMPLETE) { uint8_t len = rfm12_rx_len(); if ((len == 0) || (len % 16 != 0)) { UART_PUTF("Received garbage (%u bytes not multiple of 16): ", len); print_bytearray(bufx, len); } else // try to decrypt with all keys stored in EEPROM { bool crcok = false; for (aes_key_nr = 0; aes_key_nr < aes_key_count ; aes_key_nr++) { memcpy(bufx, rfm12_rx_buffer(), len); /*if (aes_key_nr == 0) { UART_PUTS("Before decryption: "); print_bytearray(bufx, len); }*/ e2p_basestation_get_aeskey(aes_key_nr, aes_key); //UART_PUTS("Trying AES key 2 "); //print_bytearray((uint8_t *)aes_key, 32); aes256_decrypt_cbc(bufx, len); //UART_PUTS("Decrypted bytes: "); //print_bytearray(bufx, len); crcok = pkg_header_check_crc32(len); if (crcok) { //UART_PUTS("CRC correct, AES key found!\r\n"); UART_PUTF("Received (AES key %u): ", aes_key_nr); print_bytearray(bufx, len); decode_data(len); break; } } if (!crcok) { UART_PUTS("Received garbage (CRC wrong after decryption): "); memcpy(bufx, rfm12_rx_buffer(), len); print_bytearray(bufx, len); } UART_PUTS("\r\n"); } //uart_hexdump((char *)bufcontents, rfm12_rx_len()); //UART_PUTS("\r\n"); // tell the implementation that the buffer can be reused for the next data. rfm12_rx_clear(); } // send data, if waiting in send buffer if (send_data_avail) { uint8_t i; // set AES key nr aes_key_nr = hex_to_uint8((uint8_t *)cmdbuf, 1); //UART_PUTF("AES KEY = %u\r\n", aes_key_nr); // init packet buffer memset(&bufx[0], 0, sizeof(bufx)); // set message type uint8_t message_type = hex_to_uint8((uint8_t *)cmdbuf, 3); pkg_header_set_messagetype(message_type); pkg_header_adjust_offset(); //UART_PUTF("MessageType = %u\r\n", message_type); uint8_t string_offset_data = 0; /* UART_PUTS("sKK00RRRRGGMM.............Get\r\n"); UART_PUTS("sKK01RRRRGGMMDD...........Set\r\n"); UART_PUTS("sKK02RRRRGGMMDD...........SetGet\r\n"); UART_PUTS("sKK08GGMMDD...............Status\r\n"); UART_PUTS("sKK09SSSSPPPPPPEE.........Ack\r\n"); UART_PUTS("sKK0ASSSSPPPPPPEEGGMMDD...AckStatus\r\n"); */ // set header extension fields to the values given as hex string in the user input switch (message_type) { case MESSAGETYPE_GET: case MESSAGETYPE_SET: case MESSAGETYPE_SETGET: pkg_headerext_common_set_receiverid(hex_to_uint16((uint8_t *)cmdbuf, 5)); pkg_headerext_common_set_messagegroupid(hex_to_uint8((uint8_t *)cmdbuf, 9)); pkg_headerext_common_set_messageid(hex_to_uint8((uint8_t *)cmdbuf, 11)); string_offset_data = 12; break; case MESSAGETYPE_STATUS: pkg_headerext_common_set_messagegroupid(hex_to_uint8((uint8_t *)cmdbuf, 5)); pkg_headerext_common_set_messageid(hex_to_uint8((uint8_t *)cmdbuf, 7)); string_offset_data = 8; break; case MESSAGETYPE_ACK: pkg_headerext_common_set_acksenderid(hex_to_uint16((uint8_t *)cmdbuf, 5)); pkg_headerext_common_set_ackpacketcounter(hex_to_uint24((uint8_t *)cmdbuf, 9)); pkg_headerext_common_set_error(hex_to_uint8((uint8_t *)cmdbuf, 15)); // fallthrough! case MESSAGETYPE_ACKSTATUS: pkg_headerext_common_set_messagegroupid(hex_to_uint8((uint8_t *)cmdbuf, 17)); pkg_headerext_common_set_messageid(hex_to_uint8((uint8_t *)cmdbuf, 19)); string_offset_data = 20; break; } uint8_t data_len_raw = 0; // copy message data, which exists in all packets except in Get and Ack packets if ((message_type != MESSAGETYPE_GET) && (message_type != MESSAGETYPE_ACK)) { uint8_t data_len_raw = (strlen(cmdbuf) - 1 - string_offset_data) / 2; //UART_PUTF("Data bytes = %u\r\n", data_len_raw); uint8_t start = __HEADEROFFSETBITS / 8; uint8_t shift = __HEADEROFFSETBITS % 8; // copy message data, using __HEADEROFFSETBITS value and string_offset_data for (i = 0; i < data_len_raw; i++) { uint8_t val = hex_to_uint8((uint8_t *)cmdbuf, string_offset_data + 2 * i + 1); array_write_UIntValue(start + i, shift, 8, val, bufx); } } // round packet length to x * 16 bytes uint8_t packet_len = ((uint16_t)__HEADEROFFSETBITS + (uint16_t)data_len_raw * 8) / 8; packet_len = ((packet_len - 1) / 16 + 1) * 16; // send packet which doesn't require an acknowledge immediately if ((message_type != MESSAGETYPE_GET) && (message_type != MESSAGETYPE_SET) && (message_type != MESSAGETYPE_SETGET)) { send_packet(aes_key_nr, packet_len); } else // enqueue request (don't send immediately) { // header size = 9 bytes! if (queue_request(pkg_headerext_common_get_receiverid(), message_type, aes_key_nr, bufx + 9, packet_len - 9)) { UART_PUTF("Request added to queue (%u bytes packet).\r\n", packet_len); } else { UART_PUTS("Warning! Request queue full. Packet will not be sent.\r\n"); } print_request_queue(); } // clear cmdbuf to receive more input from UART send_data_avail = false; rfm12_tick(); led_blink(200, 0, 1); } // flash LED every second to show the device is alive if (loop == 50) { led_blink(10, 10, 1); loop = 0; request_t* request = find_request_to_repeat(packetcounter + 1); if (request != 0) // if request to repeat was found in queue { UART_PUTS("Repeating request.\r\n"); send_packet((*request).aes_key, (*request).data_bytes + 9); // header size = 9 bytes! print_request_queue(); } // Auto-send something for debugging purposes... if (loop2 == 50) { //strcpy(cmdbuf, "s000102828300"); //send_data_avail = true; loop2 = 0; } else { loop2++; } } else { _delay_ms(20); } rfm12_tick(); loop++; process_rxbuf(); if (uart_timeout > 0) { uart_timeout--; if (uart_timeout == 0) { UART_PUTS("*** UART user timeout. Input was ignored. ***\r\n"); } } } // never called // aes256_done(&aes_ctx); }
// Show info about the received packets. // This is only for debugging and only few messages are supported. The definition // of all packets must be known at the PC program that's processing the data. void decode_data(uint8_t len) { uint32_t u32, messagegroupid, messageid; uint16_t u16; pkg_header_adjust_offset(); uint16_t senderid = pkg_header_get_senderid(); uint32_t packetcounter = pkg_header_get_packetcounter(); MessageTypeEnum messagetype = pkg_header_get_messagetype(); UART_PUTF("Packet Data: SenderID=%u;", senderid); UART_PUTF("PacketCounter=%lu;", packetcounter); UART_PUTF("MessageType=%u;", messagetype); // show ReceiverID for all requests if ((messagetype == MESSAGETYPE_GET) || (messagetype == MESSAGETYPE_SET) || (messagetype == MESSAGETYPE_SETGET)) { uint16_t receiverid = pkg_headerext_common_get_receiverid(); UART_PUTF("ReceiverID=%u;", receiverid); } uint16_t acksenderid = 65000; uint32_t ackpacketcounter = 0; // show AckSenderID, AckPacketCounter and Error for "Ack" and "AckStatus" if ((messagetype == MESSAGETYPE_ACK) || (messagetype == MESSAGETYPE_ACKSTATUS)) { acksenderid = pkg_headerext_common_get_acksenderid(); ackpacketcounter = pkg_headerext_common_get_ackpacketcounter(); uint8_t error = pkg_headerext_common_get_error(); UART_PUTF("AckSenderID=%u;", acksenderid); UART_PUTF("AckPacketCounter=%lu;", ackpacketcounter); UART_PUTF("Error=%u;", error); } // show MessageGroupID and MessageID for all MessageTypes except "Ack" if (messagetype != MESSAGETYPE_ACK) { messagegroupid = pkg_headerext_common_get_messagegroupid(); messageid = pkg_headerext_common_get_messageid(); UART_PUTF("MessageGroupID=%u;", messagegroupid); UART_PUTF("MessageID=%u;", messageid); } // show raw message data for all MessageTypes with data (= all except "Get" and "Ack") if ((messagetype != MESSAGETYPE_GET) && (messagetype != MESSAGETYPE_ACK)) { uint8_t i; uint8_t start = __HEADEROFFSETBITS / 8; uint8_t shift = __HEADEROFFSETBITS % 8; uint16_t count = (((uint16_t)len * 8) - __HEADEROFFSETBITS + 7) / 8; //UART_PUTF4("\r\n\r\nLEN=%u, START=%u, SHIFT=%u, COUNT=%u\r\n\r\n", len, start, shift, count); UART_PUTS("MessageData="); for (i = start; i < start + count; i++) { UART_PUTF("%02x", array_read_UIntValue8(i, shift, 8, 0, 255, bufx)); } UART_PUTS(";"); // additionally decode the message data for a small number of messages switch (messagegroupid) { case MESSAGEGROUP_GENERIC: switch (messageid) { case MESSAGEID_GENERIC_VERSION: UART_PUTF("Major=%u;", msg_generic_version_get_major()); UART_PUTF("Minor=%u;", msg_generic_version_get_minor()); UART_PUTF("Patch=%u;", msg_generic_version_get_patch()); UART_PUTF("Hash=%08lx;", msg_generic_version_get_hash()); break; case MESSAGEID_GENERIC_BATTERYSTATUS: UART_PUTF("Percentage=%u;", msg_generic_batterystatus_get_percentage()); break; /*DateTime Status: UART_PUTS("Command Name=DateTime Status;"); UART_PUTF3("Date=%u-%02u-%02u;", bufx[6] + 2000, bufx[7], bufx[8]); UART_PUTF3("Time=%02u:%02u:%02u", bufx[9], bufx[10], bufx[11]);*/ default: break; } break; case MESSAGEGROUP_WEATHER: switch (messageid) { case MESSAGEID_WEATHER_TEMPERATURE: UART_PUTS("Temperature="); print_signed(msg_weather_temperature_get_temperature()); UART_PUTS(";"); break; case MESSAGEID_WEATHER_HUMIDITYTEMPERATURE: u16 = msg_weather_humiditytemperature_get_humidity(); UART_PUTF2("Humidity=%u.%u;Temperature=", u16 / 10, u16 % 10); print_signed(msg_weather_humiditytemperature_get_temperature()); UART_PUTS(";"); break; case MESSAGEID_WEATHER_BAROMETRICPRESSURETEMPERATURE: u32 = msg_weather_barometricpressuretemperature_get_barometricpressure(); UART_PUTF("Pressure=%ld;Temperature=", u32); print_signed(msg_weather_barometricpressuretemperature_get_temperature()); UART_PUTS(";"); break; default: break; } break; case MESSAGEGROUP_POWERSWITCH: switch (messageid) { case MESSAGEID_POWERSWITCH_SWITCHSTATE: UART_PUTF("On=%u;", msg_powerswitch_switchstate_get_on()); UART_PUTF("TimeoutSec=%u;", msg_powerswitch_switchstate_get_timeoutsec()); break; default: break; } break; default: break; } } UART_PUTS("\r\n"); // Detect and process Acknowledges to base station, whose requests have to be removed from the request queue if ((messagetype == MESSAGETYPE_ACK) || (messagetype == MESSAGETYPE_ACKSTATUS)) { if (acksenderid == device_id) // request sent from base station { remove_request(senderid, device_id, ackpacketcounter); } } }
void process_packet(uint8_t len) { pkg_header_adjust_offset(); UART_PUTS("Received: "); print_bytearray(bufx, len); // check SenderID uint32_t senderID = pkg_header_get_senderid(); UART_PUTF("SenderID:%u;", senderID); if (senderID != 0) { UART_PUTS("\r\nERR: Illegal SenderID.\r\n"); return; } // check PacketCounter // TODO: Reject if packet counter lower than remembered!! uint32_t packcnt = pkg_header_get_packetcounter(); UART_PUTF("PacketCounter:%lu;", packcnt); if (0) // packcnt <= station_packetcounter ?? { UART_PUTF("\r\nERR: Received PacketCounter < %lu.\r\n", station_packetcounter); return; } // write received counter station_packetcounter = packcnt; e2p_dimmer_set_basestationpacketcounter(station_packetcounter); // check MessageType MessageTypeEnum messagetype = pkg_header_get_messagetype(); UART_PUTF("MessageType:%u;", messagetype); if ((messagetype != MESSAGETYPE_GET) && (messagetype != MESSAGETYPE_SET) && (messagetype != MESSAGETYPE_SETGET)) { UART_PUTS("\r\nERR: Unsupported MessageType.\r\n"); return; } // check device id uint8_t rcv_id = pkg_headerext_common_get_receiverid(); UART_PUTF("ReceiverID:%u;", rcv_id); if (rcv_id != device_id) { UART_PUTS("\r\nWRN: DeviceID does not match.\r\n"); return; } // check MessageGroup + MessageID uint32_t messagegroupid = pkg_headerext_common_get_messagegroupid(); uint32_t messageid = pkg_headerext_common_get_messageid(); UART_PUTF("MessageGroupID:%u;", messagegroupid); if (messagegroupid != MESSAGEGROUP_DIMMER) { UART_PUTS("\r\nERR: Unsupported MessageGroupID.\r\n"); return; } UART_PUTF("MessageID:%u;", messageid); switch (messageid) { case MESSAGEID_DIMMER_BRIGHTNESS: process_brightness(messagetype); break; case MESSAGEID_DIMMER_ANIMATION: process_animation(messagetype); break; default: UART_PUTS("\r\nERR: Unsupported MessageID.\r\n"); break; } }