Paparazzi UAS  v5.2.2_stable-0-gd6b9f29
Paparazzi is a free software Unmanned Aircraft System.
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
gsm.c
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2009 ENAC, Arnaud Quintard, Pascal Brisset
3  *
4  * This file is part of paparazzi.
5  *
6  * paparazzi is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2, or (at your option)
9  * any later version.
10  *
11  * paparazzi is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with paparazzi; see the file COPYING. If not, write to
18  * the Free Software Foundation, 59 Temple Place - Suite 330,
19  * Boston, MA 02111-1307, USA.
20  *
21  */
22 
23 /*
24 http://www.telit.com/en/products/gsm-gprs.php?p_ac=show&p=12#downloads
25 
26 Init:
27  Out: ATE0
28  In: OK
29  Out: AT+CMGF=1
30  In: OK
31  Out: AT+CNMI=1,1,0,0,0
32  In: OK
33  Out : AT+CPMS=\"SM\"
34  In: +CPMS:
35 
36 Reporting:
37  Out: AT+CSQ
38  In: +CSQ: <rssi>,<ber>
39  In: OK
40  Out: AT+CMGS=\"GCS_NUMBER\"
41  In: >
42  Out: gps.utm_pos.east, gps.utm_pos.north, gps.course, gps.hmsl, gps.gspeed, -gps.ned_vel.z, vsupply, autopilot_flight_time, rssi CTRLZ
43 
44 Receiving:
45  In: +CMTI: ...,<number>
46  Out: AT+CMGR=<number>
47  In: +CMGR ...
48  In: B42 (or S42 3.14)
49  Out: AT+CMGD=<number>
50  In: OK
51 */
52 
53 #include <stdbool.h>
54 #include <string.h>
55 #include <stdio.h>
56 #include <stdlib.h>
57 
58 #include "gsm.h"
59 #include "mcu_periph/uart.h"
60 #include "std.h"
61 #ifdef USE_USB_SERIAL
62 #include "mcu_periph/usb_serial.h"
63 #endif
64 #include "mcu_periph/uart.h"
66 #include "ap_subsystems/datalink/downlink.h"
67 #include "subsystems/gps.h"
68 #include "autopilot.h"
69 //#include "subsystems/navigation/common_nav.h" //why is should this be needed?
70 #include "generated/settings.h"
71 
72 #ifndef GSM_LINK
73 #define GSM_LINK UART3100
74 #endif
75 
76 #define GSM_MAX_PAYLOAD 160
77 
78 #define __GSMLink(dev, _x) dev##_x
79 #define _GSMLink(dev, _x) __GSMLink(dev, _x)
80 #define GSMLink(_x) _GSMLink(GSM_LINK, _x)
81 
82 #define GSMBuffer() GSMLink(ChAvailable())
83 #define ReadGSMBuffer() { while (GSMLink(ChAvailable())&&!gsm_line_received) gsm_parse(GSMLink(Getch())); }
84 
85 #define GSMTransmit(_c) GSMLink(Transmit(_c))
86 
87 #define CTRLZ 0x1A
88 #define GSM_ORIGIN_MAXLEN 32
89 #define DATA_MAXLEN 128
90 
91 #define CMTI "+CMTI:"
92 #define MAXLEN_CMTI_ANSWER 32
93 #define MAXLEN_SMS_CONTENT DATA_MAXLEN
94 
95 static bool gsm_line_received;
96 static bool prompt_received;
97 static bool waiting_for_reply; /* An AT command has been sent and an answer is expected */
98 
99 // static char msg_status[16];
100 // static char msg_date[32];
101 
102 static char expected_ack[10];
103 static char gsm_buf[GSM_MAX_PAYLOAD] __attribute__ ((aligned));
107 
108 #define STATUS_NONE 0
109 #define STATUS_CSQ 1
110 #define STATUS_REQUESTING_MESSAGE 2
111 #define STATUS_SEND_AT 3
112 #define STATUS_SEND_CMGF 4
113 #define STATUS_SEND_CNMI 5
114 #define STATUS_SEND_CPMS 6
115 #define STATUS_RECEPTION_SMS2 7
116 #define STATUS_WAITING_DATA 8
117 #define STATUS_IDLE 9
118 #define STATUS_WAITING_PROMPT 10
119 #define STATUS_DELETE_SMS 11
120 #define STATUS_POWERON 12
121 
123 
125 
126 static void Send_AT(void);
127 static void Send_CMGF(void);
128 static void Send_CNMI(void);
129 static void Send_CPMS(void);
130 static void Suppr_SMS(int);
131 static void gsm_send_report_continue(void);
132 static void gsm_parse(uint8_t c);
133 static void gsm_got_line(void);
134 static void gsm_got_prompt(void);
135 static void gsm_receive_content(void);
136 static void request_for_msg(void);
137 static void Send_CSQ(void);
138 static void Send(const char string[]);
139 static void parse_msg_header(void);
140 static char* indexn(char*, char, uint8_t);
141 
142 
145 
146 
147 /*****************************************************************************/
148 void gsm_init(void) {
149  if (gsm_status == STATUS_NONE) { /* First call */
150  LED_ON(GSM_ONOFF_LED);
151  gsm_status = STATUS_POWERON;
152  //} else { /* Second call */
153  // gsm_buf_idx = 0;
154  // gsm_line_received = false;
155  //
156  // Send_AT();
157  // gsm_status = STATUS_SEND_AT;
158  // gsm_gsm_init_status = FALSE;
159  }
160  gcs_index = 0;
161  gcs_index_max = 0;
162 #ifdef GCS_NUMBER_1
163  gcs_index_max++;
164 #endif
165 #ifdef GCS_NUMBER_2
166  gcs_index_max++;
167 #endif
168 }
169 
170 void gsm_init_report(void) { /* Second call */
171  if (gsm_status != STATUS_NONE) {
172  gsm_buf_idx = 0;
173  gsm_line_received = false;
174 
175  Send_AT();
176  gsm_status = STATUS_SEND_AT;
177  gsm_gsm_init_report_status = FALSE;
178  }
179 }
180 
181 void gsm_event(void) {
182  if (GSMBuffer()) {
183  ReadGSMBuffer();
184  }
185 
186  if (gsm_line_received) {
187  if (gsm_buf_len > 0) DOWNLINK_SEND_DEBUG_GSM_RECEIVE(DefaultChannel, DefaultDevice, gsm_buf_len, gsm_buf);
188  gsm_got_line();
189  gsm_line_received = false;
190  } else if (prompt_received) {
191  DOWNLINK_SEND_DEBUG_GSM_RECEIVE(DefaultChannel, DefaultDevice, 1, ">");
192  gsm_got_prompt();
193  prompt_received = false;
194  }
195 }
196 
197 
198 // A line of length gsm_buf_len is available in the gsm_buf buffer
199 static void gsm_got_line(void)
200 {
201  if (gsm_status == STATUS_WAITING_DATA) { // Currently receiving a SMS
203  Suppr_SMS(index_msg);
204  gsm_status = STATUS_DELETE_SMS;
205  } else if (gsm_status == STATUS_IDLE
206  && strncmp(CMTI, gsm_buf, strlen(CMTI)) == 0) {
207  /* A SMS is available */
208  /* Extracting the index of the message */
209  char * first_comma = indexn(gsm_buf, ',',MAXLEN_CMTI_ANSWER);
210  if (first_comma) {
211  index_msg = atoi(first_comma+1);
212  request_for_msg();
213  gsm_status = STATUS_REQUESTING_MESSAGE;
214  }
215  } else if (waiting_for_reply) { // Other cases
216  // Do we get what we were expecting
217 
218  bool gsm_answer = strncmp(expected_ack, gsm_buf, strlen(expected_ack)) == 0;
219  if (gsm_answer) {
220  waiting_for_reply = false;
221 
222  switch(gsm_status) {
223  case STATUS_CSQ :
225  gsm_status = STATUS_WAITING_PROMPT;
226  break;
227 
230  gsm_status = STATUS_WAITING_DATA;
231  break;
232 
233  case STATUS_SEND_AT :
234  gsm_answer = false;
235  Send_CMGF();
236  gsm_status = STATUS_SEND_CMGF;
237  break;
238 
239  case STATUS_SEND_CMGF :
240  gsm_answer = false;
241  Send_CNMI();
242  gsm_status = STATUS_SEND_CNMI;
243  break;
244 
245  case STATUS_SEND_CNMI :
246  gsm_answer = false;
247  Send_CPMS();
248  gsm_status = STATUS_SEND_CPMS;
249  break;
250 
251  case STATUS_SEND_CPMS :
252  gsm_answer = false;
253  gsm_status = STATUS_IDLE;
254  gsm_gsm_send_report_status = MODULES_START;
255  break;
256 
257  case STATUS_DELETE_SMS :
258  gsm_status = STATUS_IDLE;
259  break;
260 
261  default:
262  break;
263  }
264  } else {
265  /* Let's wait for the next line */
266  }
267  }
268 }
269 
270 
271 
272 // Receiving a SMS, first step: asking for a given message
273 static void request_for_msg(void)
274 {
275  char demande_lecture_SMS[16];
276 
277  strcpy(expected_ack, "+CMGR");
278  sprintf(demande_lecture_SMS, "AT+CMGR=%d", index_msg);
279  waiting_for_reply = true;
280  Send(demande_lecture_SMS);
281 }
282 
283 
289 static void gsm_receive_content(void)
290 {
291  // ?????? sprintf(data_to_send, "%d %s %s %s %s", index_msg, flag, expediteur, dateheure, data_recue);
292  // ?????? Send(data_to_send);
293 
294  // Checking the number of the sender
295  if (
296 //#if ! (defined GCS_NUMBER_1 || defined GCS_NUMBER_2 || defined SAFETY_NUMBER_1 || defined SAFETY_NUMBER_2)
297  true
298 //#else
299 // false
300 //#endif
301 #ifdef GCS_NUMBER_1
302  || strncmp((char*)GCS_NUMBER_1, origin, strlen(GCS_NUMBER_1)) == 0
303 #endif
304 #ifdef GCS_NUMBER_2
305  || strncmp((char*)GCS_NUMBER_2, origin, strlen(GCS_NUMBER_2)) == 0
306 #endif
307 #ifdef SAFETY_NUMBER_1
308  || strncmp((char*)SAFETY_NUMBER_1, origin, strlen(SAFETY_NUMBER_1)) == 0
309 #endif
310 #ifdef SAFETY_NUMBER_2
311  || strncmp((char*)SAFETY_NUMBER_2, origin, strlen(SAFETY_NUMBER_2)) == 0
312 #endif
313  ) {
314  // Decoding the message ...
315 
316  // Search for the instruction
317  switch (gsm_buf[0]) {
318  case 'B' :
319  {
320  uint8_t block_index = atoi(gsm_buf+1);
321  if (block_index > 0) /* Warning: no way to go to the first block */
322  nav_goto_block(block_index);
323  break;
324  }
325  case 'S' :
326  {
327  uint8_t var_index = atoi(gsm_buf+1);
328  if (var_index > 0) {
329  float value = atof(indexn(gsm_buf, ' ',MAXLEN_SMS_CONTENT)+1);
330  DlSetting(var_index, value);
331  }
332  }
333 
334  default:
335  // Report an error ???
336  break;
337  }
338  }
339 }
340 
341 
342 // Deleting a SMS
343 void Suppr_SMS(int index_)
344 {
345  char demande_suppression[20];
346 
347  sprintf(demande_suppression, "AT+CMGD=%d", index_);
348  strcpy(expected_ack, "OK");
349  waiting_for_reply = true;
350  Send(demande_suppression);
351 }
352 
353 
354 // We just have received a prompt ">" (we are sending a SMS)
355 static void gsm_got_prompt(void)
356 {
357  if (gsm_status == STATUS_WAITING_PROMPT) { // We were waiting for a prompt
358  char string[strlen(data_to_send) +3];
359 
360  sprintf(string, "%s%c", data_to_send, CTRLZ);
361  Send(string);
362  }
363 
364  gsm_status = STATUS_IDLE;
365 }
366 
369 static void parse_msg_header(void)
370 {
371  /* Extraction du flag*/
374  /* Extraction de l'expediteur*/
375  // Extraction(buffer2, '"', 2, 1, '"', 1, 0, origin);
376 
377  /* Extraction de date heure*/
378  // Extraction(buffer2, '"', 4, 1, '"', 1, 0, msg_date);
379 
380  //pb d'ecriture du flag => solution de fortune (pb si flag != rec unread)
381  //??????? strncpy(flag, flag, 10);
382 }
383 
384 
385 
386 // Periodic message, first step (called every 60s)
388 {
389  gsm_status = STATUS_IDLE;
390  if(gsm_status == STATUS_IDLE) {
391  // Checking the network coverage
392  Send_CSQ();
393  gsm_status = STATUS_CSQ;
394  }
395 }
396 
397 
398 // Sending a message, second step; we have asked for network quality
400 {
401  //We got "+CSQ: <rssi>,<ber>" <rssi> and <ber> on 2 digits (cf 3.5.4.4.4)
402  // and we expect "OK" on the second line
403  uint8_t rssi = atoi(gsm_buf + strlen("+CSQ: "));
404 
405  // Donnee GPS :ne sont pas envoyes gps_mode, gps.tow, gps.utm_pos.zone, gps_nb_ovrn
406  // Donnees batterie (seuls vsupply et autopilot_flight_time sont envoyes)
407  // concatenation de toutes les infos en un seul message à transmettre
408  sprintf(data_to_send, "%ld %ld %d %ld %d %d %d %d %d", gps.utm_pos.east, gps.utm_pos.north, gps_course, gps.hmsl, gps.gspeed, -gps.ned_vel.z, vsupply, autopilot_flight_time, rssi);
409 
410  // send the number and wait for the prompt
411  char buf[32];
412  switch (gcs_index) {
413 #ifdef GCS_NUMBER_1
414  case 0 :
415  sprintf(buf, "AT+CMGS=\"%s\"", GCS_NUMBER_1);
416  Send(buf);
417  break;
418 #endif
419 #ifdef GCS_NUMBER_2
420  case 1 :
421  sprintf(buf, "AT+CMGS=\"%s\"", GCS_NUMBER_2);
422  Send(buf);
423  break;
424 #endif
425  default :
426  gcs_index = 0;
427  break;
428  }
429  gcs_index++;
430  if (gcs_index == gcs_index_max) gcs_index = 0;
431 }
432 
433 
434 
435 
436 static void Send_AT(void)
437 {
438  strcpy(expected_ack, "OK");
439  waiting_for_reply = true;
440 
441  Send("ATE0");
442 }
443 
444 static void Send_CMGF(void)
445 {
446  strcpy(expected_ack, "OK");
447  waiting_for_reply = true;
448  Send("AT+CMGF=1");
449 }
450 
451 static void Send_CSQ(void)
452 {
453  /***** FIXME ****** strcpy(expected_ack, "+CSQ:"); ****/
454  strcpy(expected_ack, "OK");
455  waiting_for_reply = true;
456  Send("AT+CSQ");
457 }
458 
459 static void Send_CNMI(void)
460 {
461  strcpy(expected_ack, "OK");
462  waiting_for_reply = true;
463  Send("AT+CNMI=1,1,0,0,0");
464 }
465 
466 static void Send_CPMS(void)
467 {
468  strcpy(expected_ack, "+CPMS:");
469  waiting_for_reply = true;
470  Send("AT+CPMS=\"SM\"");
471 }
472 
473 
474 static void gsm_parse(uint8_t c) {
475  switch(c) {
476  case GSM_CMD_LINE_TERMINATION:
477  break;
478  case '>':
479  prompt_received = true;
480  break;
481  case GSM_RESPONSE_FORMATING:
482  gsm_buf[gsm_buf_idx] = '\0';
483  gsm_line_received = true;
484  gsm_buf_len = gsm_buf_idx;
485  gsm_buf_idx=0;
486  break;
487  default:
488  if (gsm_buf_idx < GSM_MAX_PAYLOAD) {
489  gsm_buf[gsm_buf_idx] = c;
490  gsm_buf_idx++;
491  } /* else extra characters are ignored */
492  break;
493  }
494 }
495 
496 
497 // Sending a string to the GSM module (through the UART)
498 static void Send(const char string[])
499 {
500  int i = 0;
501 
502  while(string[i])
503  GSMTransmit(string[i++]);
504  GSMTransmit(GSM_CMD_LINE_TERMINATION);
505 
506  DOWNLINK_SEND_DEBUG_GSM_SEND(DefaultChannel, DefaultDevice, i, string);
507 }
508 
509 /* Returns a pointer to the first occurrence of the character c in the firtn
510  n chars of string s. Return NULL if not found */
511 static char* indexn(char* s, char c, uint8_t n) {
512  while(n && (*s != c)) {
513  n--;
514  s++;
515  }
516  return (n ? s : NULL);
517 }
#define GSM_MAX_PAYLOAD
Definition: gsm.c:76
static bool gsm_line_received
Definition: gsm.c:95
static uint8_t gsm_buf_idx
Definition: gsm.c:104
struct NedCoor_i ned_vel
speed NED in cm/s
Definition: gps.h:69
uint16_t vsupply
Supply voltage in deciVolt.
Definition: autopilot.c:51
arch independent UART (Universal Asynchronous Receiver/Transmitter) API
static char data_to_send[DATA_MAXLEN]
Definition: gsm.c:106
uint16_t value
Definition: adc_arch.c:585
uint16_t autopilot_flight_time
flight time in seconds.
Definition: autopilot.c:47
static bool waiting_for_reply
Definition: gsm.c:97
#define STATUS_REQUESTING_MESSAGE
Definition: gsm.c:110
static void Suppr_SMS(int)
Definition: gsm.c:343
static uint8_t gcs_index
Definition: gsm.c:143
#define GSM_ORIGIN_MAXLEN
Definition: gsm.c:88
static void parse_msg_header(void)
Message header in gsm_bug.
Definition: gsm.c:369
#define STATUS_SEND_AT
Definition: gsm.c:111
#define LED_ON(i)
Definition: led_hw.h:28
#define ReadGSMBuffer()
Definition: gsm.c:83
int32_t hmsl
height above mean sea level in mm
Definition: gps.h:67
static char * indexn(char *, char, uint8_t)
Definition: gsm.c:511
void gsm_init_report(void)
Definition: gsm.c:170
static void gsm_receive_content(void)
Receiving a SMS, third step, content in gsm_buf Message can be Bdd where dd is a block index on two d...
Definition: gsm.c:289
static void gsm_got_prompt(void)
Definition: gsm.c:355
static char origin[GSM_ORIGIN_MAXLEN]
Definition: gsm.c:105
#define STATUS_CSQ
Definition: gsm.c:109
#define MAXLEN_SMS_CONTENT
Definition: gsm.c:93
#define DATA_MAXLEN
Definition: gsm.c:89
static void Send_CSQ(void)
Definition: gsm.c:451
void gsm_send_report()
Definition: gsm.c:387
#define FALSE
Definition: imu_chimu.h:141
#define MAXLEN_CMTI_ANSWER
Definition: gsm.c:92
static uint8_t gsm_buf_len
Definition: gsm.c:104
static void Send(const char string[])
Definition: gsm.c:498
#define STATUS_WAITING_PROMPT
Definition: gsm.c:118
int32_t z
Down.
void gsm_event(void)
Definition: gsm.c:181
static uint8_t gcs_index_max
Definition: gsm.c:144
static uint8_t index_msg
Definition: gsm.c:124
Communications through GSM.
static void gsm_parse(uint8_t c)
Definition: gsm.c:474
int16_t gspeed
norm of 2d ground speed in cm/s
Definition: gps.h:70
#define STATUS_IDLE
Definition: gsm.c:117
Device independent GPS code (interface)
#define STATUS_SEND_CPMS
Definition: gsm.c:114
static uint8_t gsm_status
Definition: gsm.c:122
static bool prompt_received
Definition: gsm.c:96
#define STATUS_WAITING_DATA
Definition: gsm.c:116
int32_t north
in centimeters
#define STATUS_SEND_CMGF
Definition: gsm.c:112
#define STATUS_NONE
Definition: gsm.c:108
#define CMTI
Definition: gsm.c:91
struct adc_buf * buf
Definition: adc_arch.c:586
int32_t east
in centimeters
#define STATUS_POWERON
Definition: gsm.c:120
unsigned char uint8_t
Definition: types.h:14
static void Send_CPMS(void)
Definition: gsm.c:466
static void gsm_got_line(void)
Definition: gsm.c:199
#define GSMBuffer()
Definition: gsm.c:82
#define CTRLZ
Definition: gsm.c:87
static char gsm_buf[GSM_MAX_PAYLOAD]
Definition: gsm.c:103
#define GSMTransmit(_c)
Definition: gsm.c:85
static void gsm_send_report_continue(void)
Definition: gsm.c:399
static void request_for_msg(void)
Definition: gsm.c:273
#define STATUS_SEND_CNMI
Definition: gsm.c:113
struct UtmCoor_i utm_pos
position in UTM (north,east: cm; alt: mm over ellipsoid)
Definition: gps.h:66
static char expected_ack[10]
Definition: gsm.c:102
static void Send_AT(void)
Definition: gsm.c:436
static void Send_CNMI(void)
Definition: gsm.c:459
#define STATUS_DELETE_SMS
Definition: gsm.c:119
void gsm_init(void)
Definition: gsm.c:148
void nav_goto_block(uint8_t b)
struct GpsState gps
global GPS state
Definition: gps.c:41
arch independent USB API
static void Send_CMGF(void)
Definition: gsm.c:444