Commit 0cfa56b6debb5b8c4bbc862cedbcbe7a064455d8

Authored by Emilio Soca Herrera
1 parent 041e3945

--no commit message

Project/applications/smartcities/include/ntp.h 0 → 100644
  1 +#ifndef NTP_H
  2 +#define NTP_H
  3 +
  4 +#include "libwismart.h"
  5 +#include "lwip/opt.h"
  6 +#include "lwip/tcp.h"
  7 +#include "lwip/udp.h"
  8 +#include "lwip/sys.h"
  9 +#include "lwip/api.h"
  10 +#include "ch.h"
  11 +
  12 +#define NTP_PACKET_LENGTH 48
  13 +//char* remoteIpString ="81.184.154.182";
  14 +//const uint16_t remotePort = 123;
  15 +
  16 +
  17 +typedef struct {
  18 + int second;
  19 + int minute;
  20 + int hour;
  21 + int day;
  22 + int month;
  23 + int year;
  24 +}Date;
  25 +
  26 +#define LEAP_YEAR(Y) (((1970+Y)>0) && !((1970+Y)%4) && (((1970+Y)%100) || !((1970+Y)%400)))
  27 +//const unsigned long seventyYears = 2208988800UL;
  28 +//const int timeZone = 2; //Time offset from GMT
  29 +//unsigned long daysPerMonth[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
  30 +
  31 +void udpNTP_Setup(void);
  32 +unsigned long getSecsSince1900(void);
  33 +Date getDate(void);
  34 +
  35 +void udpNtp_test(void);
  36 +
  37 +void udpNtp_init(void);
  38 +void udpNtp_send(void);
  39 +void udpNtp_dataReceivedCb(void * arg, struct udp_pcb * upcb,struct pbuf * firstPbuf,struct ip_addr * addr, u16_t port);
  40 +uint32_t udpNtp_setupConnection(void);
  41 +uint32_t udpNtp_setupConnectionL(void);
  42 +uint32_t read32(char* buffer, int offset);
  43 +
  44 +
  45 +#endif
Project/applications/smartcities/ntp.c 0 → 100644
  1 +#include <stdio.h>
  2 +#include <time.h>
  3 +#include <string.h>
  4 +#include <stdlib.h>
  5 +#include <unistd.h>
  6 +#include <errno.h>
  7 +#include <math.h>
  8 +#include <sys/time.h>
  9 +
  10 +#include "ntp.h"
  11 +
  12 +#define DBG(fmt,...) if(1){printf("[NTP] "fmt"\r\n", ##__VA_ARGS__);}else{({});}
  13 +#define DBG_WARNING(fmt,...) if(1){printf("[NTP_WARNING] "fmt"\r\n", ##__VA_ARGS__);}else{({});}
  14 +
  15 +//define LEAP_YEAR(Y) (((1970+Y)>0) && !((1970+Y)%4) && (((1970+Y)%100) || !((1970+Y)%400)))
  16 +//const unsigned long seventyYears = 2208988800UL;
  17 +//const int timeZone = 2; //Time offset from GMT
  18 +//unsigned long daysPerMonth[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
  19 +unsigned long secsSince1900=0;
  20 +int flag=0;
  21 +
  22 +struct udp_pcb* udpConnectionHandler= NULL;
  23 +uint8_t udpNtpOnline = 0;
  24 +
  25 +
  26 +/*----------------------------------------------------------------------------------------------------------------------------------------
  27 +INITIALIZATION/PROCESSING FUNCTIONS
  28 +-----------------------------------------------------------------------------------------------------------------------------------------*/
  29 +void udpNtp_init(){
  30 + udpConnectionHandler= NULL;
  31 + udpNtpOnline = 0;
  32 + secsSince1900=0;
  33 + flag=0;
  34 +}
  35 +
  36 +/*
  37 +* Check if the connection handler has been initialized,
  38 +* and if so send a new message
  39 +*/
  40 +void udpNtp_process(){
  41 + while(udpNtpOnline==0){
  42 + DBG("TX abandonned! [Not connected]\r\n");
  43 + chThdSleepMilliseconds(500);
  44 + }
  45 + udpNtp_send();
  46 +}
  47 +
  48 +/*----------------------------------------------------------------------------------------------------------------------------------------
  49 +UDP TRANSMISSION HANDLING FUNCTIONS
  50 +-----------------------------------------------------------------------------------------------------------------------------------------*/
  51 +/*
  52 +* Sends a new message to the remote peer
  53 +*/
  54 +void udpNtp_send(){
  55 + char* remoteIpString ="81.184.154.182";/*"192.168.43.83";"165.193.126.229";*/
  56 + uint16_t remotePort = 123;
  57 + char packetBuffer[NTP_PACKET_LENGTH];
  58 + static uint32_t messageCount = 0;
  59 + memset (packetBuffer,0,NTP_PACKET_LENGTH);
  60 + packetBuffer[0] =0x1B;//0b11100011; // LI, Version, Mode
  61 + packetBuffer[1] = 0; // Stratum, or type of clock
  62 + packetBuffer[2] = 6; // Polling Interval
  63 + packetBuffer[3] = 0xEC; // Peer Clock Precision
  64 + // 8 bytes of zero for Root Delay & Root Dispersion
  65 + packetBuffer[12] = 49;
  66 + packetBuffer[13] = 0x4E;
  67 + packetBuffer[14] = 49;
  68 + packetBuffer[15] = 52;
  69 + struct pbuf *pbuffer;
  70 + ip_addr_t addr;
  71 + uint32_t ipaddr;
  72 +
  73 + err_t err;
  74 +
  75 + //Convert the IP address from string to lwip format
  76 + ipaddr = ipaddr_addr(remoteIpString);
  77 + ip4_addr_set_u32((&addr), ipaddr);
  78 +
  79 + /*
  80 + * Allocate a pbuf which we are going to fill with the transmitted data.
  81 + * We use libwismart_LwIP_lock() here because we are making a LWIP call
  82 + */
  83 +libwismart_LwIP_lock();
  84 + pbuffer = pbuf_alloc(PBUF_TRANSPORT, NTP_PACKET_LENGTH, PBUF_POOL);
  85 +libwismart_LwIP_unlock();
  86 + if(pbuffer == NULL){
  87 + DBG_WARNING("pbuf_alloc() FAILED!\r\n");
  88 + return;
  89 + }
  90 +
  91 + /*
  92 + * Fill the payload of the pbuf with the message to be transmitted
  93 + * NOTE: Because pbuffer->payload has type (void*), we have to cast it (else we may have undefined behaviour)
  94 + */
  95 + memcpy((uint8_t*)pbuffer->payload, packetBuffer, NTP_PACKET_LENGTH);
  96 +
  97 + /*
  98 + * Send the packet and release the allocated pbuf.
  99 + * We use libwismart_LwIP_lock() here because we are making a LWIP call
  100 + */
  101 + libwismart_LwIP_lock();
  102 + err = udp_sendto(udpConnectionHandler, pbuffer, &addr, remotePort);
  103 + libwismart_LwIP_unlock();
  104 +
  105 + /*
  106 + * Release the allocated pbuf
  107 + * We use libwismart_LwIP_lock() here because we are making a LWIP call
  108 + */
  109 + libwismart_LwIP_lock();
  110 + pbuf_free(pbuffer);
  111 + libwismart_LwIP_unlock();
  112 +
  113 + if(err != ERR_OK){
  114 + DBG_WARNING("udp_sendto() FAILED!");
  115 + return;
  116 + }
  117 +
  118 + DBG("Message #%u sent!",messageCount++);
  119 +}
  120 +
  121 +/*----------------------------------------------------------------------------------------------------------------------------------------
  122 +UDP RECEPTION HANDLING FUNCTIONS
  123 +-----------------------------------------------------------------------------------------------------------------------------------------*/
  124 +void udpNtp_dataReceivedCb(void * arg, struct udp_pcb * upcb,struct pbuf * firstPbuf,struct ip_addr * addr, u16_t port){
  125 + unsigned char *payload;
  126 + unsigned int payloadLen;
  127 + struct pbuf *currentPbuf;
  128 +
  129 + currentPbuf = firstPbuf;
  130 + while(currentPbuf != NULL){
  131 +
  132 + /*
  133 + * It is important to cast the pbufNow->payload because its type is (void*)
  134 + */
  135 + payload = (unsigned char *)currentPbuf->payload;
  136 + payloadLen = currentPbuf->len;
  137 +
  138 + DBG("New message [%u bytes] received!\r\n", payloadLen);
  139 +
  140 + currentPbuf = currentPbuf->next;
  141 + };
  142 +
  143 + uint32_t temp=read32(payload, 40);
  144 + secsSince1900=(unsigned long) temp;
  145 + flag=1;
  146 +
  147 + /*
  148 + * Free the pbuf list.
  149 + */
  150 + pbuf_free(firstPbuf);
  151 +
  152 +}
  153 +
  154 +/*----------------------------------------------------------------------------------------------------------------------------------------
  155 +UDP CONNECTION SETUP FUNCTIONS
  156 +-----------------------------------------------------------------------------------------------------------------------------------------*/
  157 +/*
  158 +* Setups a new udp connection handler
  159 +*/
  160 +uint32_t udpNtp_setupConnection(){
  161 + uint32_t error;
  162 +
  163 +libwismart_LwIP_lock();
  164 + error = udpNtp_setupConnectionL();
  165 +libwismart_LwIP_unlock();
  166 +
  167 + return error;
  168 +}
  169 +
  170 +/*
  171 +* Setups a new udp connection handler (Locked version of udpNTP_setupConnection)
  172 +*/
  173 +uint32_t udpNtp_setupConnectionL(){
  174 + uint16_t localPort = 5004;
  175 + err_t err;
  176 +
  177 + /*
  178 + * Create a new udp connection handler
  179 + */
  180 + udpConnectionHandler = udp_new();
  181 + if(udpConnectionHandler == NULL){
  182 + DBG_WARNING("udp_new() FAILED!\r\n");
  183 + return 1;
  184 + }
  185 +
  186 + /*
  187 + * Bind the connection to a local port. By giving 0
  188 + * as third argument(port), you can say to lwip to bind the connection
  189 + * to any available port of our system.
  190 + */
  191 + err = udp_bind(udpConnectionHandler, IP_ADDR_ANY, localPort);
  192 + if(err != ERR_OK){
  193 + DBG_WARNING("udp_bind() FAILED!\r\n");
  194 + udp_remove(udpConnectionHandler);
  195 + return 2;
  196 + }
  197 + /*
  198 + * Set the callback function when udp data are received.
  199 + * Since we only transmit, we should set this to NULL(second argument).
  200 + * For demonstration reasons only we provide a callback function
  201 + * that will be called each time a packet is received at port 'localPort'
  202 + */
  203 + udp_recv(udpConnectionHandler, udpNtp_dataReceivedCb, NULL);
  204 +
  205 + udpNtpOnline = 1;
  206 +
  207 + return 0;
  208 +}
  209 +
  210 +uint32_t read32(char* buffer, int offset) {
  211 + char b0 = buffer[offset];
  212 + char b1 = buffer[offset+1];
  213 + char b2 = buffer[offset+2];
  214 + char b3 = buffer[offset+3];
  215 +
  216 + // convert signed bytes to unsigned values
  217 + uint32_t i0 = ((b0 & 0x80) == 0x80 ? (b0 & 0x7F) + 0x80 : b0);
  218 + uint32_t i1 = ((b1 & 0x80) == 0x80 ? (b1 & 0x7F) + 0x80 : b1);
  219 + uint32_t i2 = ((b2 & 0x80) == 0x80 ? (b2 & 0x7F) + 0x80 : b2);
  220 + uint32_t i3 = ((b3 & 0x80) == 0x80 ? (b3 & 0x7F) + 0x80 : b3);
  221 +
  222 + uint32_t v = (i0 << 24) + (i1 << 16) + (i2 << 8) + i3;
  223 + return v;
  224 +}
  225 +
  226 +unsigned long getSecsSince1900(){
  227 + while(flag==0){
  228 + DBG("in function getSecsSince1900: waiting for NTP procces\n");
  229 + chThdSleepMilliseconds(500);
  230 + }
  231 + return secsSince1900;
  232 +}
  233 +
  234 +Date getDate(){
  235 + while(flag==0){
  236 + DBG("in function getDate: waiting for NTP procces\n");
  237 + chThdSleepMilliseconds(500);
  238 + }
  239 +
  240 +
  241 + const unsigned long seventyYears = 2208988800UL;
  242 + const int timeZone = 2; //Time offset from GMT
  243 + unsigned long daysPerMonth[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
  244 +
  245 + unsigned long epoch = secsSince1900 - seventyYears;
  246 +
  247 + int second = epoch % 60;
  248 + epoch /= 60;
  249 + int minute = epoch % 60;
  250 + epoch /= 60;
  251 + int hour = ((epoch % 24) + timeZone) % 24;
  252 + epoch /= 24;
  253 + int year = 0;
  254 + unsigned long days = 0;
  255 +
  256 + while((unsigned)(days += (LEAP_YEAR(year) ? 366 : 365)) <= epoch){
  257 + year++;
  258 + }
  259 + days -= LEAP_YEAR(year) ? 366 : 365;
  260 + epoch -= days;
  261 +
  262 + int j=0;
  263 + int cont=0;
  264 + int aux=epoch;
  265 + if(LEAP_YEAR(year)){
  266 + daysPerMonth[1]=29;
  267 + }
  268 +
  269 + while (daysPerMonth[j]<sizeof(daysPerMonth)){
  270 +
  271 + cont+=daysPerMonth[j];
  272 + if(epoch<cont){
  273 + break;
  274 + }
  275 + aux-=daysPerMonth[j];
  276 + j++;
  277 + }
  278 +
  279 + int day=++aux;
  280 + int month=++j;
  281 + year+=1970;
  282 +
  283 + Date date;
  284 + date.second=second;
  285 + date.minute=minute;
  286 + date.hour=hour;
  287 + date.day=day;
  288 + date.month=month;
  289 + date.year=year;
  290 +
  291 + return date;
  292 +}
  293 +
  294 +void udpNTP_Setup(){
  295 + DBG("start_init\r\n");
  296 + udpNtp_init();
  297 +
  298 + DBG("start_Setup_Connection\r\n");
  299 + udpNtp_setupConnectionL();
  300 +
  301 + DBG("start_Procces\r\n");
  302 + udpNtp_process();
  303 +}
  304 +
  305 +
  306 +/*Funcion para testeo del resto de funciones relacionadas con NTP. En el main() el orden de ejecución debe ser el siguiente.
  307 +1ro: udpNTP_Setup
  308 +2do: getSecsSince1900() o getDate()
  309 +si se quiere actualizar la fecha actual, debemos llamar primeramente a UdpNTP_Setup.*/
  310 +/*void udpNtp_test(){
  311 +
  312 + udpNTP_Setup();
  313 + //unsigned long var1=getSecsSince1900();
  314 + Date var2=getDate();
  315 +
  316 + //DBG("seconds since 1900: %lu\r\n", var1);
  317 +
  318 + DBG("Hora:%i:%i:%i\r\n", var2.hour, var2.minute, var2.second);
  319 + DBG("Fecha:%i|%i|%i\r\n", var2.day,var2.month,var2.year);
  320 +}*/
0 \ No newline at end of file 321 \ No newline at end of file