An access controller for man doors at our facility. It receives Wiegand signals from a keypad/card reader and activates a relay to open the door. Access codes are stored in EEPROM. The active code list is updated from TFTP on a local server.

Dependencies:   24LCxx_I2C CardReader USBHOST

Revision:
0:a56239ae90c2
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/TFTPClient.cpp	Mon Sep 25 19:02:40 2017 +0000
@@ -0,0 +1,143 @@
+
+#include "TFTPClient.h"
+
+bool TFTPClient::readFile(char* data, const char* host, const char* filename, const uint16_t port, const uint32_t timeout)
+{
+    printf("TFTP read file\n");
+    m_data = data;
+    
+    if (m_tftp_addr)
+    {
+        delete m_tftp_addr;
+        m_tftp_addr = NULL;
+    }
+    m_tftp_addr = new SocketAddress(host, port);
+    
+    printf("IP: %d\n", m_eth);
+    
+    m_sock.open(m_eth);
+    printf("TFTP before blocking\n");
+    m_sock.set_blocking(false);
+    printf("TFTP before bind\n");
+    m_sock.bind(0);
+    
+    printf("TFTP port bound\n");
+    
+    char chunk[TFTP_MAX_PACKET_SIZE];
+    uint16_t tftp_opcode = htons(RRQ);
+    char tftp_mode[] = "octet";
+    
+    // Construct read request packet
+    memcpy(chunk, &tftp_opcode, 2);
+    memcpy(chunk + 2, filename, strlen(filename) + 1);
+    memcpy(chunk + 2 + (strlen(filename) + 1), tftp_mode, strlen(tftp_mode) + 1);
+    int packet_size = 2 + strlen(filename) + 1 + strlen(tftp_mode) + 1;
+    
+    // Debug output request data.
+    printf("TFTP RRQ packet: ");
+    fwrite(chunk, 1, packet_size, stdout);
+    printf("\n");
+    
+    // Send read request
+    m_bytes_received = 0;
+    m_block_number = 1;
+    m_bytes_sent = m_sock.sendto(*m_tftp_addr, chunk, packet_size);
+    
+    if (m_bytes_sent == packet_size)
+    {
+        m_download_in_progress = true;
+    }
+    else
+    {
+        printf("TFTP read request failed. %d\n", m_bytes_sent);
+    }
+    
+    m_next_data_byte_index = 0;
+    
+    return m_download_in_progress;
+}
+
+int TFTPClient::update()
+{
+    int return_value = -1;
+    char chunk[TFTP_MAX_PACKET_SIZE];
+    
+    if (m_download_in_progress)
+    {
+        // Get data packet from the TFTP server
+        m_bytes_received = m_sock.recvfrom(m_tftp_addr, chunk, TFTP_MAX_PACKET_SIZE);
+        if (m_bytes_received <= 0)
+        {
+            return_value = m_bytes_received; // UDP packet recevie failed.
+        }
+        else
+        {
+            // Convert the opcode and block back into host endian format.
+            uint16_t temp_opcode, temp_block;
+            memcpy(&temp_opcode, chunk, 2);
+            memcpy(&temp_block, chunk + 2, 2);
+            temp_opcode = ntohs(temp_opcode);
+            temp_block = ntohs(temp_block);
+            
+            if (temp_opcode == ERR)
+            {
+                printf("  TFTP Error: %u, %s\n", temp_block, chunk + 4);
+                return_value = -2; // Error response from server.
+            }
+            else if (temp_opcode == DATA)
+            {
+                if (temp_block == m_block_number)
+                {
+                    int chunk_size = m_bytes_received - 4;
+                    // Debug output for incoming chunks of data.
+                    //printf("  TFTP Chunk Received: %u\n", chunk_size);
+                    //fwrite(chunk, 1, m_bytes_received, stdout);
+                    
+                    // Strip the TFTP info from the beginning of the data buffer.
+                    memcpy(m_data + m_next_data_byte_index, chunk + 4, chunk_size);
+                    m_next_data_byte_index += chunk_size;
+                    // Terminate the data string.
+                    m_data[m_next_data_byte_index] = 0;
+                    
+                    // Send an ACK for the current data block
+                    uint16_t tftp_opcode = htons(ACK);
+                    temp_block = htons(temp_block);
+                    memcpy(chunk, &tftp_opcode, 2);
+                    memcpy(chunk + 2, &temp_block, 2);
+                    int m_bytes_sent = m_sock.sendto(*m_tftp_addr, chunk, 4); // Send
+                    
+                    m_block_number++;
+                }
+                else
+                {
+                    return_value = -3; // Incorrect data block number.
+                    m_download_in_progress = false;
+                }
+            }
+            else
+            {
+                return_value = -4; // Wrong opcode
+                m_download_in_progress = false;
+            }
+            
+            if (m_bytes_received != TFTP_MAX_PACKET_SIZE)
+            {
+                m_download_in_progress = false;
+                
+                if (m_bytes_received > 0)
+                {
+                    // Finished download.
+                    return_value = 1;
+                }
+            }
+        }
+    }
+    
+    if (!m_download_in_progress)
+    {
+        m_sock.close();
+    }
+    
+    return return_value;
+}
+    
\ No newline at end of file