Commit 0cfa56b6debb5b8c4bbc862cedbcbe7a064455d8
1 parent
041e3945
--no commit message
Showing
2 changed files
with
365 additions
and
0 deletions
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 | 321 | \ No newline at end of file | ... | ... |