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
ConfigurationManager.cpp@0:a56239ae90c2, 2017-09-25 (annotated)
- Committer:
- acesrobertm
- Date:
- Mon Sep 25 19:02:40 2017 +0000
- Revision:
- 0:a56239ae90c2
in process of moving networking code to non-blocking format
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
acesrobertm | 0:a56239ae90c2 | 1 | |
acesrobertm | 0:a56239ae90c2 | 2 | #include "ConfigurationManager.h" |
acesrobertm | 0:a56239ae90c2 | 3 | |
acesrobertm | 0:a56239ae90c2 | 4 | void ConfigurationManager::remove_all_chars(char* str, char c) { |
acesrobertm | 0:a56239ae90c2 | 5 | char *pr = str, *pw = str; |
acesrobertm | 0:a56239ae90c2 | 6 | while (*pr) { |
acesrobertm | 0:a56239ae90c2 | 7 | *pw = *pr++; |
acesrobertm | 0:a56239ae90c2 | 8 | pw += (*pw != c); |
acesrobertm | 0:a56239ae90c2 | 9 | } |
acesrobertm | 0:a56239ae90c2 | 10 | *pw = '\0'; |
acesrobertm | 0:a56239ae90c2 | 11 | } |
acesrobertm | 0:a56239ae90c2 | 12 | |
acesrobertm | 0:a56239ae90c2 | 13 | bool ConfigurationManager::isValidIpString(char* ip) |
acesrobertm | 0:a56239ae90c2 | 14 | { |
acesrobertm | 0:a56239ae90c2 | 15 | bool isValid = false; |
acesrobertm | 0:a56239ae90c2 | 16 | int strLength = strlen(ip); |
acesrobertm | 0:a56239ae90c2 | 17 | int numPeriods = 0; |
acesrobertm | 0:a56239ae90c2 | 18 | |
acesrobertm | 0:a56239ae90c2 | 19 | // Verify that the length is within bounds. |
acesrobertm | 0:a56239ae90c2 | 20 | if (strLength >= IP_STRING_MIN_LENGTH && strLength <= IP_STRING_MAX_LENGTH) |
acesrobertm | 0:a56239ae90c2 | 21 | { |
acesrobertm | 0:a56239ae90c2 | 22 | // Verify that there are three periods in the string. |
acesrobertm | 0:a56239ae90c2 | 23 | for (int charIndex = 0; charIndex < strLength; charIndex++) |
acesrobertm | 0:a56239ae90c2 | 24 | { |
acesrobertm | 0:a56239ae90c2 | 25 | numPeriods += (ip[charIndex] == '.'); |
acesrobertm | 0:a56239ae90c2 | 26 | } |
acesrobertm | 0:a56239ae90c2 | 27 | |
acesrobertm | 0:a56239ae90c2 | 28 | isValid = (numPeriods == 3); |
acesrobertm | 0:a56239ae90c2 | 29 | } |
acesrobertm | 0:a56239ae90c2 | 30 | |
acesrobertm | 0:a56239ae90c2 | 31 | return isValid; |
acesrobertm | 0:a56239ae90c2 | 32 | } |
acesrobertm | 0:a56239ae90c2 | 33 | |
acesrobertm | 0:a56239ae90c2 | 34 | int ConfigurationManager::parse_tftp_config(char* data) |
acesrobertm | 0:a56239ae90c2 | 35 | { |
acesrobertm | 0:a56239ae90c2 | 36 | int dataLength = strlen(data); |
acesrobertm | 0:a56239ae90c2 | 37 | int paramStart = 0; |
acesrobertm | 0:a56239ae90c2 | 38 | int paramNameLength = 0; |
acesrobertm | 0:a56239ae90c2 | 39 | int paramValueLength = 0; |
acesrobertm | 0:a56239ae90c2 | 40 | char paramName[CONFIG_PARAM_NAME_MAX_LENGTH + 1] = ""; |
acesrobertm | 0:a56239ae90c2 | 41 | char paramValue[CONFIG_PARAM_VALUE_MAX_LENGTH + 1] = ""; |
acesrobertm | 0:a56239ae90c2 | 42 | bool paramComplete = false; |
acesrobertm | 0:a56239ae90c2 | 43 | |
acesrobertm | 0:a56239ae90c2 | 44 | // Get the parameter name |
acesrobertm | 0:a56239ae90c2 | 45 | for (int charIndex = 0; charIndex <= dataLength; charIndex++) |
acesrobertm | 0:a56239ae90c2 | 46 | { |
acesrobertm | 0:a56239ae90c2 | 47 | // Check for end of the parameter name. |
acesrobertm | 0:a56239ae90c2 | 48 | if (data[charIndex] == '=') |
acesrobertm | 0:a56239ae90c2 | 49 | { |
acesrobertm | 0:a56239ae90c2 | 50 | paramNameLength = charIndex - paramStart; |
acesrobertm | 0:a56239ae90c2 | 51 | } |
acesrobertm | 0:a56239ae90c2 | 52 | |
acesrobertm | 0:a56239ae90c2 | 53 | // Check for the end of the parameter value. |
acesrobertm | 0:a56239ae90c2 | 54 | if (data[charIndex] == '\r' || data[charIndex] == '\n' || data[charIndex] == ' ' || charIndex == dataLength) |
acesrobertm | 0:a56239ae90c2 | 55 | { |
acesrobertm | 0:a56239ae90c2 | 56 | int paramValueStart = (paramStart + paramNameLength + 1); |
acesrobertm | 0:a56239ae90c2 | 57 | paramValueLength = charIndex - paramValueStart; |
acesrobertm | 0:a56239ae90c2 | 58 | |
acesrobertm | 0:a56239ae90c2 | 59 | // Handle oversized input strings. |
acesrobertm | 0:a56239ae90c2 | 60 | if (paramNameLength > CONFIG_PARAM_NAME_MAX_LENGTH || paramValueLength > CONFIG_PARAM_VALUE_MAX_LENGTH) |
acesrobertm | 0:a56239ae90c2 | 61 | { |
acesrobertm | 0:a56239ae90c2 | 62 | paramComplete = true; |
acesrobertm | 0:a56239ae90c2 | 63 | } |
acesrobertm | 0:a56239ae90c2 | 64 | |
acesrobertm | 0:a56239ae90c2 | 65 | if (!paramComplete && paramNameLength > 0 && paramValueLength > 0) |
acesrobertm | 0:a56239ae90c2 | 66 | { |
acesrobertm | 0:a56239ae90c2 | 67 | // Get the name and value strings. |
acesrobertm | 0:a56239ae90c2 | 68 | memcpy(paramName, data + paramStart, paramNameLength); |
acesrobertm | 0:a56239ae90c2 | 69 | paramName[paramNameLength] = 0; |
acesrobertm | 0:a56239ae90c2 | 70 | memcpy(paramValue, data + paramValueStart, paramValueLength); |
acesrobertm | 0:a56239ae90c2 | 71 | paramValue[paramValueLength] = 0; |
acesrobertm | 0:a56239ae90c2 | 72 | |
acesrobertm | 0:a56239ae90c2 | 73 | printf(" %s=%s\n", paramName, paramValue); |
acesrobertm | 0:a56239ae90c2 | 74 | |
acesrobertm | 0:a56239ae90c2 | 75 | // Store the parameter value. |
acesrobertm | 0:a56239ae90c2 | 76 | if (!strcmp(paramName, configName_enableAccess)) |
acesrobertm | 0:a56239ae90c2 | 77 | { |
acesrobertm | 0:a56239ae90c2 | 78 | config_enableAccess = (paramValue[0] == '1'); |
acesrobertm | 0:a56239ae90c2 | 79 | } |
acesrobertm | 0:a56239ae90c2 | 80 | else if (!strcmp(paramName, configName_ipAddress) && isValidIpString(paramValue)) |
acesrobertm | 0:a56239ae90c2 | 81 | { |
acesrobertm | 0:a56239ae90c2 | 82 | strcpy(config_ipAddress, paramValue); |
acesrobertm | 0:a56239ae90c2 | 83 | } |
acesrobertm | 0:a56239ae90c2 | 84 | else if (!strcmp(paramName, configName_netMask) && isValidIpString(paramValue)) |
acesrobertm | 0:a56239ae90c2 | 85 | { |
acesrobertm | 0:a56239ae90c2 | 86 | strcpy(config_netMask, paramValue); |
acesrobertm | 0:a56239ae90c2 | 87 | } |
acesrobertm | 0:a56239ae90c2 | 88 | else if (!strcmp(paramName, configName_gateway) && isValidIpString(paramValue)) |
acesrobertm | 0:a56239ae90c2 | 89 | { |
acesrobertm | 0:a56239ae90c2 | 90 | strcpy(config_gateway, paramValue); |
acesrobertm | 0:a56239ae90c2 | 91 | } |
acesrobertm | 0:a56239ae90c2 | 92 | else if (!strcmp(paramName, configName_codeFileName) && strlen(paramValue) <= CONFIG_PARAM_VALUE_MAX_LENGTH) |
acesrobertm | 0:a56239ae90c2 | 93 | { |
acesrobertm | 0:a56239ae90c2 | 94 | strcpy(config_codeFileName, paramValue); |
acesrobertm | 0:a56239ae90c2 | 95 | } |
acesrobertm | 0:a56239ae90c2 | 96 | else if (!strcmp(paramName, configName_ntpServer) && isValidIpString(paramValue)) |
acesrobertm | 0:a56239ae90c2 | 97 | { |
acesrobertm | 0:a56239ae90c2 | 98 | strcpy(config_ntpServer, paramValue); |
acesrobertm | 0:a56239ae90c2 | 99 | } |
acesrobertm | 0:a56239ae90c2 | 100 | else if (!strcmp(paramName, configName_usbBaud)) |
acesrobertm | 0:a56239ae90c2 | 101 | { |
acesrobertm | 0:a56239ae90c2 | 102 | config_usbBaud = atoi(paramValue); |
acesrobertm | 0:a56239ae90c2 | 103 | } |
acesrobertm | 0:a56239ae90c2 | 104 | } |
acesrobertm | 0:a56239ae90c2 | 105 | |
acesrobertm | 0:a56239ae90c2 | 106 | paramComplete = true; |
acesrobertm | 0:a56239ae90c2 | 107 | } |
acesrobertm | 0:a56239ae90c2 | 108 | |
acesrobertm | 0:a56239ae90c2 | 109 | // Reset for the next parameter. |
acesrobertm | 0:a56239ae90c2 | 110 | if (data[charIndex] == '\n') |
acesrobertm | 0:a56239ae90c2 | 111 | { |
acesrobertm | 0:a56239ae90c2 | 112 | paramStart = charIndex + 1; |
acesrobertm | 0:a56239ae90c2 | 113 | paramNameLength = 0; |
acesrobertm | 0:a56239ae90c2 | 114 | paramValueLength = 0; |
acesrobertm | 0:a56239ae90c2 | 115 | paramName[0] = 0; |
acesrobertm | 0:a56239ae90c2 | 116 | paramValue[0] = 0; |
acesrobertm | 0:a56239ae90c2 | 117 | paramComplete = false; |
acesrobertm | 0:a56239ae90c2 | 118 | } |
acesrobertm | 0:a56239ae90c2 | 119 | } |
acesrobertm | 0:a56239ae90c2 | 120 | |
acesrobertm | 0:a56239ae90c2 | 121 | return 0; |
acesrobertm | 0:a56239ae90c2 | 122 | } |
acesrobertm | 0:a56239ae90c2 | 123 | |
acesrobertm | 0:a56239ae90c2 | 124 | int ConfigurationManager::parse_tftp_codes(char* tftp_data) |
acesrobertm | 0:a56239ae90c2 | 125 | { |
acesrobertm | 0:a56239ae90c2 | 126 | unsigned short codeList[CODE_TABLE_SIZE / 2] = {0}; |
acesrobertm | 0:a56239ae90c2 | 127 | unsigned int dataLength = strlen(tftp_data); |
acesrobertm | 0:a56239ae90c2 | 128 | int codeStart = 0; |
acesrobertm | 0:a56239ae90c2 | 129 | int codeLength = 0; |
acesrobertm | 0:a56239ae90c2 | 130 | int codeIndex = 0; |
acesrobertm | 0:a56239ae90c2 | 131 | char codeString[ACCESS_CODE_MAX_LENGTH + 1] = ""; |
acesrobertm | 0:a56239ae90c2 | 132 | bool codeComplete = true; |
acesrobertm | 0:a56239ae90c2 | 133 | |
acesrobertm | 0:a56239ae90c2 | 134 | // Get the parameter name |
acesrobertm | 0:a56239ae90c2 | 135 | for (int charIndex = 0; charIndex <= dataLength; charIndex++) |
acesrobertm | 0:a56239ae90c2 | 136 | { |
acesrobertm | 0:a56239ae90c2 | 137 | if (tftp_data[charIndex] >= '0' && tftp_data[charIndex] <= '9') |
acesrobertm | 0:a56239ae90c2 | 138 | { |
acesrobertm | 0:a56239ae90c2 | 139 | if (codeComplete) |
acesrobertm | 0:a56239ae90c2 | 140 | { |
acesrobertm | 0:a56239ae90c2 | 141 | codeStart = charIndex; |
acesrobertm | 0:a56239ae90c2 | 142 | codeLength = 0; |
acesrobertm | 0:a56239ae90c2 | 143 | } |
acesrobertm | 0:a56239ae90c2 | 144 | |
acesrobertm | 0:a56239ae90c2 | 145 | codeLength += 1; |
acesrobertm | 0:a56239ae90c2 | 146 | codeComplete = false; |
acesrobertm | 0:a56239ae90c2 | 147 | } |
acesrobertm | 0:a56239ae90c2 | 148 | else // not a number character |
acesrobertm | 0:a56239ae90c2 | 149 | { |
acesrobertm | 0:a56239ae90c2 | 150 | codeComplete = true; |
acesrobertm | 0:a56239ae90c2 | 151 | |
acesrobertm | 0:a56239ae90c2 | 152 | // Ensure that the code is of the correct size. |
acesrobertm | 0:a56239ae90c2 | 153 | if (codeIndex < (CODE_TABLE_SIZE / 2) && codeLength >= ACCESS_CODE_MIN_LENGTH && codeLength <= ACCESS_CODE_MAX_LENGTH) |
acesrobertm | 0:a56239ae90c2 | 154 | { |
acesrobertm | 0:a56239ae90c2 | 155 | memcpy(codeString, tftp_data + codeStart, codeLength); |
acesrobertm | 0:a56239ae90c2 | 156 | codeString[codeLength] = 0; |
acesrobertm | 0:a56239ae90c2 | 157 | unsigned short codeValue = atoi(codeString); |
acesrobertm | 0:a56239ae90c2 | 158 | |
acesrobertm | 0:a56239ae90c2 | 159 | // Store the code in a temporary list to use when updating the EEPROM. |
acesrobertm | 0:a56239ae90c2 | 160 | codeList[codeIndex] = codeValue; |
acesrobertm | 0:a56239ae90c2 | 161 | |
acesrobertm | 0:a56239ae90c2 | 162 | // Format and print the list of access codes with multiple codes per line. |
acesrobertm | 0:a56239ae90c2 | 163 | //printf(ACCESS_CODE_PRINT_FORMAT, codeValue); |
acesrobertm | 0:a56239ae90c2 | 164 | codeIndex++; |
acesrobertm | 0:a56239ae90c2 | 165 | |
acesrobertm | 0:a56239ae90c2 | 166 | // New line of access codes |
acesrobertm | 0:a56239ae90c2 | 167 | if (codeIndex % ACCESS_CODE_NUM_COLS == 0) |
acesrobertm | 0:a56239ae90c2 | 168 | { |
acesrobertm | 0:a56239ae90c2 | 169 | //printf("\n"); |
acesrobertm | 0:a56239ae90c2 | 170 | } |
acesrobertm | 0:a56239ae90c2 | 171 | } |
acesrobertm | 0:a56239ae90c2 | 172 | } |
acesrobertm | 0:a56239ae90c2 | 173 | } |
acesrobertm | 0:a56239ae90c2 | 174 | |
acesrobertm | 0:a56239ae90c2 | 175 | printf("Downloaded %d codes.\n\n", codeIndex); |
acesrobertm | 0:a56239ae90c2 | 176 | |
acesrobertm | 0:a56239ae90c2 | 177 | // Update the EEPROM with the current network list of codes. |
acesrobertm | 0:a56239ae90c2 | 178 | mCodeMem->SyncAccessCodes(codeList, codeIndex); |
acesrobertm | 0:a56239ae90c2 | 179 | |
acesrobertm | 0:a56239ae90c2 | 180 | return 0; |
acesrobertm | 0:a56239ae90c2 | 181 | } |
acesrobertm | 0:a56239ae90c2 | 182 | |
acesrobertm | 0:a56239ae90c2 | 183 | // Set the IP address options from the configuration parameters and connect to the network. |
acesrobertm | 0:a56239ae90c2 | 184 | int ConfigurationManager::connectEthernet(char* mac_addr, char* ip_addr, const bool withDhcp, const bool printStats) |
acesrobertm | 0:a56239ae90c2 | 185 | { |
acesrobertm | 0:a56239ae90c2 | 186 | int connectResult; |
acesrobertm | 0:a56239ae90c2 | 187 | |
acesrobertm | 0:a56239ae90c2 | 188 | mEth->set_dhcp(withDhcp); |
acesrobertm | 0:a56239ae90c2 | 189 | |
acesrobertm | 0:a56239ae90c2 | 190 | // Reconfigure the network for a static address if specified. |
acesrobertm | 0:a56239ae90c2 | 191 | if (!withDhcp && isValidIpString(config_ipAddress) && isValidIpString(config_netMask) && (strlen(config_gateway) == 0 || isValidIpString(config_gateway))) |
acesrobertm | 0:a56239ae90c2 | 192 | { |
acesrobertm | 0:a56239ae90c2 | 193 | mEth->set_network(config_ipAddress, config_netMask, config_gateway); |
acesrobertm | 0:a56239ae90c2 | 194 | } |
acesrobertm | 0:a56239ae90c2 | 195 | |
acesrobertm | 0:a56239ae90c2 | 196 | // Attempt network connection |
acesrobertm | 0:a56239ae90c2 | 197 | connectResult = mEth->connect(); |
acesrobertm | 0:a56239ae90c2 | 198 | |
acesrobertm | 0:a56239ae90c2 | 199 | if (connectResult >= 0) |
acesrobertm | 0:a56239ae90c2 | 200 | { |
acesrobertm | 0:a56239ae90c2 | 201 | strcpy(mac_addr, mEth->get_mac_address()); |
acesrobertm | 0:a56239ae90c2 | 202 | strcpy(ip_addr, mEth->get_ip_address()); |
acesrobertm | 0:a56239ae90c2 | 203 | |
acesrobertm | 0:a56239ae90c2 | 204 | if (printStats) |
acesrobertm | 0:a56239ae90c2 | 205 | { |
acesrobertm | 0:a56239ae90c2 | 206 | printf("Network Connected:\n"); |
acesrobertm | 0:a56239ae90c2 | 207 | printf(" mac: %s\n", mac_addr); |
acesrobertm | 0:a56239ae90c2 | 208 | printf(" ip: %s\n", ip_addr); |
acesrobertm | 0:a56239ae90c2 | 209 | printf(" mask: %s\n", mEth->get_netmask()); |
acesrobertm | 0:a56239ae90c2 | 210 | printf(" gate: %s\n", mEth->get_gateway()); |
acesrobertm | 0:a56239ae90c2 | 211 | } |
acesrobertm | 0:a56239ae90c2 | 212 | } |
acesrobertm | 0:a56239ae90c2 | 213 | else |
acesrobertm | 0:a56239ae90c2 | 214 | { |
acesrobertm | 0:a56239ae90c2 | 215 | printf("Failed to connect to the network. %d\n", connectResult); |
acesrobertm | 0:a56239ae90c2 | 216 | } |
acesrobertm | 0:a56239ae90c2 | 217 | |
acesrobertm | 0:a56239ae90c2 | 218 | return connectResult; |
acesrobertm | 0:a56239ae90c2 | 219 | } |
acesrobertm | 0:a56239ae90c2 | 220 | |
acesrobertm | 0:a56239ae90c2 | 221 | void ConfigurationManager::updateClock() |
acesrobertm | 0:a56239ae90c2 | 222 | { |
acesrobertm | 0:a56239ae90c2 | 223 | // Set the real time clock using NTP |
acesrobertm | 0:a56239ae90c2 | 224 | printf("\nSending NTP query to %s...\n", config_ntpServer); |
acesrobertm | 0:a56239ae90c2 | 225 | int ntp_result = _ntp.setTime(mEth, config_ntpServer); |
acesrobertm | 0:a56239ae90c2 | 226 | if (ntp_result < 0) |
acesrobertm | 0:a56239ae90c2 | 227 | { |
acesrobertm | 0:a56239ae90c2 | 228 | printf("Failed to send.\n"); |
acesrobertm | 0:a56239ae90c2 | 229 | } |
acesrobertm | 0:a56239ae90c2 | 230 | |
acesrobertm | 0:a56239ae90c2 | 231 | lastUpdatedTimeSeconds = time(NULL); |
acesrobertm | 0:a56239ae90c2 | 232 | return; |
acesrobertm | 0:a56239ae90c2 | 233 | } |
acesrobertm | 0:a56239ae90c2 | 234 | |
acesrobertm | 0:a56239ae90c2 | 235 | void ConfigurationManager::setupNetwork() |
acesrobertm | 0:a56239ae90c2 | 236 | { |
acesrobertm | 0:a56239ae90c2 | 237 | printf("\nEstablishing DHCP network connection...\n"); |
acesrobertm | 0:a56239ae90c2 | 238 | |
acesrobertm | 0:a56239ae90c2 | 239 | // Ethernet Setup: Connect to the netowrk using DHCP |
acesrobertm | 0:a56239ae90c2 | 240 | _tftp = new TFTPClient(mEth); |
acesrobertm | 0:a56239ae90c2 | 241 | int connectResult = connectEthernet(_mac_addr, _ip_addr); |
acesrobertm | 0:a56239ae90c2 | 242 | if (connectResult >= 0) |
acesrobertm | 0:a56239ae90c2 | 243 | { |
acesrobertm | 0:a56239ae90c2 | 244 | // Reconfigure the network settings for a temporary static IP address |
acesrobertm | 0:a56239ae90c2 | 245 | // This is required to free port 68 for the DHCP option query in the next step. |
acesrobertm | 0:a56239ae90c2 | 246 | strcpy(config_ipAddress, mEth->get_ip_address()); |
acesrobertm | 0:a56239ae90c2 | 247 | strcpy(config_netMask, mEth->get_netmask()); |
acesrobertm | 0:a56239ae90c2 | 248 | strcpy(config_gateway, mEth->get_gateway()); |
acesrobertm | 0:a56239ae90c2 | 249 | mEth->disconnect(); |
acesrobertm | 0:a56239ae90c2 | 250 | |
acesrobertm | 0:a56239ae90c2 | 251 | connectResult = connectEthernet(_mac_addr, _ip_addr, 0, 1); |
acesrobertm | 0:a56239ae90c2 | 252 | |
acesrobertm | 0:a56239ae90c2 | 253 | // Get the IP address of the TFTP server via DHCP offer message. |
acesrobertm | 0:a56239ae90c2 | 254 | printf("\nGetting the TFTP server address via DHCP...\n"); |
acesrobertm | 0:a56239ae90c2 | 255 | DHCPOptions ops(mEth); |
acesrobertm | 0:a56239ae90c2 | 256 | int optionResult = ops.getOptions(config_tftpServer, _mac_addr); |
acesrobertm | 0:a56239ae90c2 | 257 | |
acesrobertm | 0:a56239ae90c2 | 258 | if (optionResult >= 0) |
acesrobertm | 0:a56239ae90c2 | 259 | { |
acesrobertm | 0:a56239ae90c2 | 260 | //updateConfiguration(); |
acesrobertm | 0:a56239ae90c2 | 261 | } |
acesrobertm | 0:a56239ae90c2 | 262 | else |
acesrobertm | 0:a56239ae90c2 | 263 | { |
acesrobertm | 0:a56239ae90c2 | 264 | printf("Failed to get options from DHCP: %d\n", optionResult); |
acesrobertm | 0:a56239ae90c2 | 265 | } |
acesrobertm | 0:a56239ae90c2 | 266 | } |
acesrobertm | 0:a56239ae90c2 | 267 | else if (connectResult == NSAPI_ERROR_DHCP_FAILURE) |
acesrobertm | 0:a56239ae90c2 | 268 | { |
acesrobertm | 0:a56239ae90c2 | 269 | // Retry DHCP until it works. |
acesrobertm | 0:a56239ae90c2 | 270 | // If the error is not due to DHCP, then continue without network features. |
acesrobertm | 0:a56239ae90c2 | 271 | printf("Resetting...\n"); |
acesrobertm | 0:a56239ae90c2 | 272 | wait(RESET_PAUSE_SECONDS); |
acesrobertm | 0:a56239ae90c2 | 273 | NVIC_SystemReset(); |
acesrobertm | 0:a56239ae90c2 | 274 | } |
acesrobertm | 0:a56239ae90c2 | 275 | } |
acesrobertm | 0:a56239ae90c2 | 276 | |
acesrobertm | 0:a56239ae90c2 | 277 | void ConfigurationManager::update() |
acesrobertm | 0:a56239ae90c2 | 278 | { |
acesrobertm | 0:a56239ae90c2 | 279 | // Periodically update the controller configuration from TFTP. |
acesrobertm | 0:a56239ae90c2 | 280 | if ((time(NULL) - lastUpdatedConfigSeconds) > CONFIG_UPDATE_INTERVAL_SECS) |
acesrobertm | 0:a56239ae90c2 | 281 | { |
acesrobertm | 0:a56239ae90c2 | 282 | mUpdateStep = UPDATE_STEP_INITIATE; |
acesrobertm | 0:a56239ae90c2 | 283 | lastUpdatedConfigSeconds = time(NULL); |
acesrobertm | 0:a56239ae90c2 | 284 | } |
acesrobertm | 0:a56239ae90c2 | 285 | |
acesrobertm | 0:a56239ae90c2 | 286 | if (mUpdateStep == UPDATE_STEP_INITIATE) |
acesrobertm | 0:a56239ae90c2 | 287 | { |
acesrobertm | 0:a56239ae90c2 | 288 | // Build TFTP filename from the MAC address. |
acesrobertm | 0:a56239ae90c2 | 289 | char tftp_filename[MAC_STRING_LENGTH + 1] = ""; |
acesrobertm | 0:a56239ae90c2 | 290 | strcpy(tftp_filename, _mac_addr); |
acesrobertm | 0:a56239ae90c2 | 291 | remove_all_chars(tftp_filename, ':'); |
acesrobertm | 0:a56239ae90c2 | 292 | strcat(tftp_filename, ".cnf"); |
acesrobertm | 0:a56239ae90c2 | 293 | printf("Getting config file %s from %s...\n", tftp_filename, config_tftpServer); |
acesrobertm | 0:a56239ae90c2 | 294 | |
acesrobertm | 0:a56239ae90c2 | 295 | int tftpResult = _tftp->readFile(_tftp_data, config_tftpServer, tftp_filename); |
acesrobertm | 0:a56239ae90c2 | 296 | if (tftpResult < 0) |
acesrobertm | 0:a56239ae90c2 | 297 | { |
acesrobertm | 0:a56239ae90c2 | 298 | printf(" TFTP config file request failed: %d\n", tftpResult); |
acesrobertm | 0:a56239ae90c2 | 299 | } |
acesrobertm | 0:a56239ae90c2 | 300 | else |
acesrobertm | 0:a56239ae90c2 | 301 | { |
acesrobertm | 0:a56239ae90c2 | 302 | mUpdateStep = UPDATE_STEP_CONFIG_FILE_REQUEST_SENT; |
acesrobertm | 0:a56239ae90c2 | 303 | } |
acesrobertm | 0:a56239ae90c2 | 304 | } |
acesrobertm | 0:a56239ae90c2 | 305 | else if (mUpdateStep == UPDATE_STEP_CONFIG_FILE_REQUEST_SENT) |
acesrobertm | 0:a56239ae90c2 | 306 | { |
acesrobertm | 0:a56239ae90c2 | 307 | // Wait for the TFTP response from the server. |
acesrobertm | 0:a56239ae90c2 | 308 | int tftp_result = _tftp->update(); |
acesrobertm | 0:a56239ae90c2 | 309 | if (tftp_result == 1) |
acesrobertm | 0:a56239ae90c2 | 310 | { |
acesrobertm | 0:a56239ae90c2 | 311 | printf("TFTP Success.\n\n"); |
acesrobertm | 0:a56239ae90c2 | 312 | mUpdateStep = UPDATE_STEP_CONFIG_FILE_RECEIVED; |
acesrobertm | 0:a56239ae90c2 | 313 | } |
acesrobertm | 0:a56239ae90c2 | 314 | else |
acesrobertm | 0:a56239ae90c2 | 315 | { |
acesrobertm | 0:a56239ae90c2 | 316 | printf(" Failed to retrieve configuration file: %d\n", tftp_result); |
acesrobertm | 0:a56239ae90c2 | 317 | } |
acesrobertm | 0:a56239ae90c2 | 318 | } |
acesrobertm | 0:a56239ae90c2 | 319 | else if (mUpdateStep == UPDATE_STEP_CONFIG_FILE_RECEIVED) // retrieve file succeeded |
acesrobertm | 0:a56239ae90c2 | 320 | { |
acesrobertm | 0:a56239ae90c2 | 321 | int currentUsbBaud = config_usbBaud; |
acesrobertm | 0:a56239ae90c2 | 322 | |
acesrobertm | 0:a56239ae90c2 | 323 | parse_tftp_config(_tftp_data); |
acesrobertm | 0:a56239ae90c2 | 324 | |
acesrobertm | 0:a56239ae90c2 | 325 | if (config_usbBaud > 0 && config_usbBaud != currentUsbBaud) |
acesrobertm | 0:a56239ae90c2 | 326 | { |
acesrobertm | 0:a56239ae90c2 | 327 | printf("\nSetting USB Serial Baud: %d\n \n", config_usbBaud); // Leave extra space because setting baud rate deletes some characters. |
acesrobertm | 0:a56239ae90c2 | 328 | //usbUART.baud(config_usbBaud); |
acesrobertm | 0:a56239ae90c2 | 329 | } |
acesrobertm | 0:a56239ae90c2 | 330 | |
acesrobertm | 0:a56239ae90c2 | 331 | printf("\nConfiguring static network connection...\n"); |
acesrobertm | 0:a56239ae90c2 | 332 | mEth->disconnect(); |
acesrobertm | 0:a56239ae90c2 | 333 | connectEthernet(_mac_addr, _ip_addr, 0, 1); |
acesrobertm | 0:a56239ae90c2 | 334 | |
acesrobertm | 0:a56239ae90c2 | 335 | printf("\nGetting code list file %s from %s...\n", config_codeFileName, config_tftpServer); |
acesrobertm | 0:a56239ae90c2 | 336 | // Get list of access codes from the specified file on the TFTP server. |
acesrobertm | 0:a56239ae90c2 | 337 | int tftpResult = _tftp->readFile(_tftp_data, config_tftpServer, config_codeFileName); |
acesrobertm | 0:a56239ae90c2 | 338 | if (tftpResult < 0) |
acesrobertm | 0:a56239ae90c2 | 339 | { |
acesrobertm | 0:a56239ae90c2 | 340 | printf("Failed to send config file request.\n"); |
acesrobertm | 0:a56239ae90c2 | 341 | } |
acesrobertm | 0:a56239ae90c2 | 342 | else |
acesrobertm | 0:a56239ae90c2 | 343 | { |
acesrobertm | 0:a56239ae90c2 | 344 | mUpdateStep = UPDATE_STEP_CODES_FILE_REQUEST_SENT; |
acesrobertm | 0:a56239ae90c2 | 345 | } |
acesrobertm | 0:a56239ae90c2 | 346 | } |
acesrobertm | 0:a56239ae90c2 | 347 | else if (mUpdateStep == UPDATE_STEP_CODES_FILE_REQUEST_SENT) |
acesrobertm | 0:a56239ae90c2 | 348 | { |
acesrobertm | 0:a56239ae90c2 | 349 | // Wait for the TFTP response from the server. |
acesrobertm | 0:a56239ae90c2 | 350 | int tftp_result = _tftp->update(); |
acesrobertm | 0:a56239ae90c2 | 351 | if (tftp_result == 1) |
acesrobertm | 0:a56239ae90c2 | 352 | { |
acesrobertm | 0:a56239ae90c2 | 353 | printf("TFTP Success.\n\n"); |
acesrobertm | 0:a56239ae90c2 | 354 | mUpdateStep = UPDATE_STEP_CODES_FILE_RECEIVED; |
acesrobertm | 0:a56239ae90c2 | 355 | } |
acesrobertm | 0:a56239ae90c2 | 356 | else |
acesrobertm | 0:a56239ae90c2 | 357 | { |
acesrobertm | 0:a56239ae90c2 | 358 | printf(" Failed to retrieve code list: %d\n", tftp_result); |
acesrobertm | 0:a56239ae90c2 | 359 | } |
acesrobertm | 0:a56239ae90c2 | 360 | } |
acesrobertm | 0:a56239ae90c2 | 361 | else if (mUpdateStep == UPDATE_STEP_CODES_FILE_RECEIVED) |
acesrobertm | 0:a56239ae90c2 | 362 | { |
acesrobertm | 0:a56239ae90c2 | 363 | parse_tftp_codes(_tftp_data); |
acesrobertm | 0:a56239ae90c2 | 364 | mUpdateStep = UPDATE_STEP_IDLE; |
acesrobertm | 0:a56239ae90c2 | 365 | } |
acesrobertm | 0:a56239ae90c2 | 366 | |
acesrobertm | 0:a56239ae90c2 | 367 | |
acesrobertm | 0:a56239ae90c2 | 368 | |
acesrobertm | 0:a56239ae90c2 | 369 | // Periodically update the RTC via NTP. |
acesrobertm | 0:a56239ae90c2 | 370 | if ((time(NULL) - lastUpdatedTimeSeconds) > TIME_UPDATE_INTERVAL_SECS) |
acesrobertm | 0:a56239ae90c2 | 371 | { |
acesrobertm | 0:a56239ae90c2 | 372 | updateClock(); |
acesrobertm | 0:a56239ae90c2 | 373 | } |
acesrobertm | 0:a56239ae90c2 | 374 | |
acesrobertm | 0:a56239ae90c2 | 375 | // Check the status of any ongoing NTP updates. |
acesrobertm | 0:a56239ae90c2 | 376 | int ntp_result = _ntp.update(); |
acesrobertm | 0:a56239ae90c2 | 377 | if (ntp_result < 0) |
acesrobertm | 0:a56239ae90c2 | 378 | { |
acesrobertm | 0:a56239ae90c2 | 379 | printf("NTP query failed.\n\n"); |
acesrobertm | 0:a56239ae90c2 | 380 | } |
acesrobertm | 0:a56239ae90c2 | 381 | else if (ntp_result > 0) |
acesrobertm | 0:a56239ae90c2 | 382 | { |
acesrobertm | 0:a56239ae90c2 | 383 | unsigned int ctTime = time(NULL); |
acesrobertm | 0:a56239ae90c2 | 384 | printf("Time is now (UTC): %s\n\n", ctime(&ctTime)); |
acesrobertm | 0:a56239ae90c2 | 385 | } |
acesrobertm | 0:a56239ae90c2 | 386 | } |