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

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?

UserRevisionLine numberNew contents of line
acesrobertm 0:a56239ae90c2 1 /* NTPClient.cpp */
acesrobertm 0:a56239ae90c2 2 /* Copyright (C) 2012 mbed.org, MIT License
acesrobertm 0:a56239ae90c2 3 *
acesrobertm 0:a56239ae90c2 4 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
acesrobertm 0:a56239ae90c2 5 * and associated documentation files (the "Software"), to deal in the Software without restriction,
acesrobertm 0:a56239ae90c2 6 * including without limitation the rights to use, copy, modify, merge, publish, distribute,
acesrobertm 0:a56239ae90c2 7 * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
acesrobertm 0:a56239ae90c2 8 * furnished to do so, subject to the following conditions:
acesrobertm 0:a56239ae90c2 9 *
acesrobertm 0:a56239ae90c2 10 * The above copyright notice and this permission notice shall be included in all copies or
acesrobertm 0:a56239ae90c2 11 * substantial portions of the Software.
acesrobertm 0:a56239ae90c2 12 *
acesrobertm 0:a56239ae90c2 13 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
acesrobertm 0:a56239ae90c2 14 * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
acesrobertm 0:a56239ae90c2 15 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
acesrobertm 0:a56239ae90c2 16 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
acesrobertm 0:a56239ae90c2 17 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
acesrobertm 0:a56239ae90c2 18 */
acesrobertm 0:a56239ae90c2 19
acesrobertm 0:a56239ae90c2 20 #if 1
acesrobertm 0:a56239ae90c2 21 //Enable debug
acesrobertm 0:a56239ae90c2 22 #define __DEBUG__
acesrobertm 0:a56239ae90c2 23 #include <cstdio>
acesrobertm 0:a56239ae90c2 24 #define DBG(x, ...) std::printf("[NTPClient : DBG]"x"\r\n", ##__VA_ARGS__);
acesrobertm 0:a56239ae90c2 25 #define WARN(x, ...) std::printf("[NTPClient : WARN]"x"\r\n", ##__VA_ARGS__);
acesrobertm 0:a56239ae90c2 26 #define ERR(x, ...) std::printf("[NTPClient : ERR]"x"\r\n", ##__VA_ARGS__);
acesrobertm 0:a56239ae90c2 27
acesrobertm 0:a56239ae90c2 28 #else
acesrobertm 0:a56239ae90c2 29 //Disable debug
acesrobertm 0:a56239ae90c2 30 #define DBG(x, ...)
acesrobertm 0:a56239ae90c2 31 #define WARN(x, ...)
acesrobertm 0:a56239ae90c2 32 #define ERR(x, ...)
acesrobertm 0:a56239ae90c2 33 #endif
acesrobertm 0:a56239ae90c2 34
acesrobertm 0:a56239ae90c2 35 #include "NTPClient.h"
acesrobertm 0:a56239ae90c2 36
acesrobertm 0:a56239ae90c2 37 #include "mbed.h" //time() and set_time()
acesrobertm 0:a56239ae90c2 38
acesrobertm 0:a56239ae90c2 39 NTPClient::NTPClient() : m_sock()
acesrobertm 0:a56239ae90c2 40 {
acesrobertm 0:a56239ae90c2 41 reset();
acesrobertm 0:a56239ae90c2 42
acesrobertm 0:a56239ae90c2 43 mQuerySent = false;
acesrobertm 0:a56239ae90c2 44 mResponseReceived = false;
acesrobertm 0:a56239ae90c2 45 mConversationComplete = true;
acesrobertm 0:a56239ae90c2 46 mStartTime = 0;
acesrobertm 0:a56239ae90c2 47 }
acesrobertm 0:a56239ae90c2 48
acesrobertm 0:a56239ae90c2 49 void NTPClient::reset()
acesrobertm 0:a56239ae90c2 50 {
acesrobertm 0:a56239ae90c2 51 if (outEndpoint)
acesrobertm 0:a56239ae90c2 52 {
acesrobertm 0:a56239ae90c2 53 delete outEndpoint;
acesrobertm 0:a56239ae90c2 54 }
acesrobertm 0:a56239ae90c2 55 if (inEndpoint)
acesrobertm 0:a56239ae90c2 56 {
acesrobertm 0:a56239ae90c2 57 delete inEndpoint;
acesrobertm 0:a56239ae90c2 58 }
acesrobertm 0:a56239ae90c2 59 outEndpoint = NULL;
acesrobertm 0:a56239ae90c2 60 inEndpoint = NULL;
acesrobertm 0:a56239ae90c2 61
acesrobertm 0:a56239ae90c2 62 m_sock.close();
acesrobertm 0:a56239ae90c2 63 }
acesrobertm 0:a56239ae90c2 64
acesrobertm 0:a56239ae90c2 65 void NTPClient::process_result()
acesrobertm 0:a56239ae90c2 66 {
acesrobertm 0:a56239ae90c2 67 //Correct Endianness
acesrobertm 0:a56239ae90c2 68 pkt.refTm_s = ntohl( pkt.refTm_s );
acesrobertm 0:a56239ae90c2 69 pkt.refTm_f = ntohl( pkt.refTm_f );
acesrobertm 0:a56239ae90c2 70 pkt.origTm_s = ntohl( pkt.origTm_s );
acesrobertm 0:a56239ae90c2 71 pkt.origTm_f = ntohl( pkt.origTm_f );
acesrobertm 0:a56239ae90c2 72 pkt.rxTm_s = ntohl( pkt.rxTm_s );
acesrobertm 0:a56239ae90c2 73 pkt.rxTm_f = ntohl( pkt.rxTm_f );
acesrobertm 0:a56239ae90c2 74 pkt.txTm_s = ntohl( pkt.txTm_s );
acesrobertm 0:a56239ae90c2 75 pkt.txTm_f = ntohl( pkt.txTm_f );
acesrobertm 0:a56239ae90c2 76
acesrobertm 0:a56239ae90c2 77 //Compute offset, see RFC 4330 p.13
acesrobertm 0:a56239ae90c2 78 uint32_t destTm_s = (NTP_TIMESTAMP_DELTA + time(NULL));
acesrobertm 0:a56239ae90c2 79 int64_t offset = ( (int64_t)( pkt.rxTm_s - pkt.origTm_s ) + (int64_t) ( pkt.txTm_s - destTm_s ) ) / 2; //Avoid overflow
acesrobertm 0:a56239ae90c2 80 DBG("Received @%ul", pkt.txTm_s);
acesrobertm 0:a56239ae90c2 81 DBG("Offset: %lld", offset);
acesrobertm 0:a56239ae90c2 82 //Set time accordingly
acesrobertm 0:a56239ae90c2 83 set_time( time(NULL) + offset );
acesrobertm 0:a56239ae90c2 84
acesrobertm 0:a56239ae90c2 85 #ifdef __DEBUG__
acesrobertm 0:a56239ae90c2 86 time_t ctTime;
acesrobertm 0:a56239ae90c2 87 ctTime = time(NULL);
acesrobertm 0:a56239ae90c2 88 DBG("Time is now (UTC): %s", ctime(&ctTime));
acesrobertm 0:a56239ae90c2 89 #endif
acesrobertm 0:a56239ae90c2 90 }
acesrobertm 0:a56239ae90c2 91
acesrobertm 0:a56239ae90c2 92 int NTPClient::update()
acesrobertm 0:a56239ae90c2 93 {
acesrobertm 0:a56239ae90c2 94 int ntp_result = NTP_WAIT;
acesrobertm 0:a56239ae90c2 95 bool conversationComplete = true;
acesrobertm 0:a56239ae90c2 96
acesrobertm 0:a56239ae90c2 97 if (mQuerySent && !mConversationComplete)
acesrobertm 0:a56239ae90c2 98 {
acesrobertm 0:a56239ae90c2 99 // Listen for a response from the NTP server.
acesrobertm 0:a56239ae90c2 100 int ret = m_sock.recvfrom( inEndpoint, (char*)&pkt, sizeof(NTPPacket) ); //FIXME need a DNS Resolver to actually compare the incoming address with the DNS name
acesrobertm 0:a56239ae90c2 101
acesrobertm 0:a56239ae90c2 102 if (ret == NSAPI_ERROR_WOULD_BLOCK)
acesrobertm 0:a56239ae90c2 103 {
acesrobertm 0:a56239ae90c2 104 //DBG("Waiting...");
acesrobertm 0:a56239ae90c2 105
acesrobertm 0:a56239ae90c2 106 // Check for response timeout.
acesrobertm 0:a56239ae90c2 107 if ((time(NULL) - mStartTime) < mTimeout)
acesrobertm 0:a56239ae90c2 108 {
acesrobertm 0:a56239ae90c2 109 conversationComplete = false;
acesrobertm 0:a56239ae90c2 110 }
acesrobertm 0:a56239ae90c2 111 else
acesrobertm 0:a56239ae90c2 112 {
acesrobertm 0:a56239ae90c2 113 DBG("Timeout.\n");
acesrobertm 0:a56239ae90c2 114 ntp_result = NTP_TIMEOUT;
acesrobertm 0:a56239ae90c2 115 }
acesrobertm 0:a56239ae90c2 116 }
acesrobertm 0:a56239ae90c2 117 else if(ret < 0)
acesrobertm 0:a56239ae90c2 118 {
acesrobertm 0:a56239ae90c2 119 ERR("Could not receive packet");
acesrobertm 0:a56239ae90c2 120 ntp_result = NTP_CONN;
acesrobertm 0:a56239ae90c2 121 }
acesrobertm 0:a56239ae90c2 122 else if(ret < sizeof(NTPPacket)) //TODO: Accept chunks
acesrobertm 0:a56239ae90c2 123 {
acesrobertm 0:a56239ae90c2 124 ERR("Received packet size does not match");
acesrobertm 0:a56239ae90c2 125 ntp_result = NTP_PRTCL;
acesrobertm 0:a56239ae90c2 126 }
acesrobertm 0:a56239ae90c2 127 else if( pkt.stratum == 0) //Kiss of death
acesrobertm 0:a56239ae90c2 128 {
acesrobertm 0:a56239ae90c2 129 ERR("Kissed to death!");
acesrobertm 0:a56239ae90c2 130 ntp_result = NTP_PRTCL;
acesrobertm 0:a56239ae90c2 131 }
acesrobertm 0:a56239ae90c2 132 else
acesrobertm 0:a56239ae90c2 133 {
acesrobertm 0:a56239ae90c2 134 process_result();
acesrobertm 0:a56239ae90c2 135 ntp_result = NTP_OK;
acesrobertm 0:a56239ae90c2 136 }
acesrobertm 0:a56239ae90c2 137
acesrobertm 0:a56239ae90c2 138 if (conversationComplete)
acesrobertm 0:a56239ae90c2 139 {
acesrobertm 0:a56239ae90c2 140 reset();
acesrobertm 0:a56239ae90c2 141 mConversationComplete = true;
acesrobertm 0:a56239ae90c2 142 }
acesrobertm 0:a56239ae90c2 143 }
acesrobertm 0:a56239ae90c2 144
acesrobertm 0:a56239ae90c2 145 return ntp_result;
acesrobertm 0:a56239ae90c2 146 }
acesrobertm 0:a56239ae90c2 147
acesrobertm 0:a56239ae90c2 148 NTPResult NTPClient::setTime(EthernetInterface* stack, const char* host, uint16_t port, uint32_t timeout)
acesrobertm 0:a56239ae90c2 149 {
acesrobertm 0:a56239ae90c2 150 mQuerySent = false;
acesrobertm 0:a56239ae90c2 151 mResponseReceived = false;
acesrobertm 0:a56239ae90c2 152 mConversationComplete = false;
acesrobertm 0:a56239ae90c2 153
acesrobertm 0:a56239ae90c2 154 mStartTime = time(NULL);
acesrobertm 0:a56239ae90c2 155 mTimeout = timeout;
acesrobertm 0:a56239ae90c2 156
acesrobertm 0:a56239ae90c2 157 #ifdef __DEBUG__
acesrobertm 0:a56239ae90c2 158 time_t ctTime;
acesrobertm 0:a56239ae90c2 159 ctTime = time(NULL);
acesrobertm 0:a56239ae90c2 160 DBG("Time is set to (UTC): %s", ctime(&ctTime));
acesrobertm 0:a56239ae90c2 161 #endif
acesrobertm 0:a56239ae90c2 162
acesrobertm 0:a56239ae90c2 163 //Create & bind socket
acesrobertm 0:a56239ae90c2 164 m_sock.open(stack);
acesrobertm 0:a56239ae90c2 165 DBG("Binding socket: %d", m_sock.bind(NTP_CLIENT_PORT)); //Bind to a random port
acesrobertm 0:a56239ae90c2 166 m_sock.set_blocking(false); //Set not blocking
acesrobertm 0:a56239ae90c2 167
acesrobertm 0:a56239ae90c2 168 //Now ping the server and wait for response
acesrobertm 0:a56239ae90c2 169 DBG("Ping");
acesrobertm 0:a56239ae90c2 170 //Prepare NTP Packet:
acesrobertm 0:a56239ae90c2 171 pkt.li = 0; //Leap Indicator : No warning
acesrobertm 0:a56239ae90c2 172 pkt.vn = 4; //Version Number : 4
acesrobertm 0:a56239ae90c2 173 pkt.mode = 3; //Client mode
acesrobertm 0:a56239ae90c2 174 pkt.stratum = 0; //Not relevant here
acesrobertm 0:a56239ae90c2 175 pkt.poll = 0; //Not significant as well
acesrobertm 0:a56239ae90c2 176 pkt.precision = 0; //Neither this one is
acesrobertm 0:a56239ae90c2 177
acesrobertm 0:a56239ae90c2 178 pkt.rootDelay = 0; //Or this one
acesrobertm 0:a56239ae90c2 179 pkt.rootDispersion = 0; //Or that one
acesrobertm 0:a56239ae90c2 180 pkt.refId = 0; //...
acesrobertm 0:a56239ae90c2 181
acesrobertm 0:a56239ae90c2 182 pkt.refTm_s = 0;
acesrobertm 0:a56239ae90c2 183 pkt.origTm_s = 0;
acesrobertm 0:a56239ae90c2 184 pkt.rxTm_s = 0;
acesrobertm 0:a56239ae90c2 185 pkt.txTm_s = htonl( NTP_TIMESTAMP_DELTA + time(NULL) ); //WARN: We are in LE format, network byte order is BE
acesrobertm 0:a56239ae90c2 186
acesrobertm 0:a56239ae90c2 187 pkt.refTm_f = pkt.origTm_f = pkt.rxTm_f = pkt.txTm_f = 0;
acesrobertm 0:a56239ae90c2 188
acesrobertm 0:a56239ae90c2 189 outEndpoint = new SocketAddress(host, port);
acesrobertm 0:a56239ae90c2 190 inEndpoint = new SocketAddress(host, 0);
acesrobertm 0:a56239ae90c2 191
acesrobertm 0:a56239ae90c2 192 //Set timeout, non-blocking and wait using select
acesrobertm 0:a56239ae90c2 193 DBG("Send packet to %s:%d", host, port);
acesrobertm 0:a56239ae90c2 194 int ret = m_sock.sendto(*outEndpoint, (void*)&pkt, sizeof(NTPPacket));
acesrobertm 0:a56239ae90c2 195 if (ret < 0 )
acesrobertm 0:a56239ae90c2 196 {
acesrobertm 0:a56239ae90c2 197 ERR("Could not send packet %d\n", ret);
acesrobertm 0:a56239ae90c2 198 m_sock.close();
acesrobertm 0:a56239ae90c2 199 return NTP_CONN;
acesrobertm 0:a56239ae90c2 200 }
acesrobertm 0:a56239ae90c2 201 DBG("Sent...");
acesrobertm 0:a56239ae90c2 202
acesrobertm 0:a56239ae90c2 203 mQuerySent = true;
acesrobertm 0:a56239ae90c2 204
acesrobertm 0:a56239ae90c2 205 return NTP_OK;
acesrobertm 0:a56239ae90c2 206 }
acesrobertm 0:a56239ae90c2 207
acesrobertm 0:a56239ae90c2 208