Paparazzi UAS  v5.0.5_stable-7-g4b8bbb7
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 #ifndef DOWNLINK_DEVICE
65 #define DOWNLINK_DEVICE DOWNLINK_AP_DEVICE
66 #endif
67 #include "mcu_periph/uart.h"
69 #include "ap_subsystems/datalink/downlink.h"
70 #include "subsystems/gps.h"
71 #include "autopilot.h"
72 //#include "subsystems/navigation/common_nav.h" //why is should this be needed?
73 #include "generated/settings.h"
74 
75 #ifndef GSM_LINK
76 #define GSM_LINK UART3100
77 #endif
78 
79 #define GSM_MAX_PAYLOAD 160
80 
81 #define __GSMLink(dev, _x) dev##_x
82 #define _GSMLink(dev, _x) __GSMLink(dev, _x)
83 #define GSMLink(_x) _GSMLink(GSM_LINK, _x)
84 
85 #define GSMBuffer() GSMLink(ChAvailable())
86 #define ReadGSMBuffer() { while (GSMLink(ChAvailable())&&!gsm_line_received) gsm_parse(GSMLink(Getch())); }
87 
88 #define GSMTransmit(_c) GSMLink(Transmit(_c))
89 
90 #define CTRLZ 0x1A
91 #define GSM_ORIGIN_MAXLEN 32
92 #define DATA_MAXLEN 128
93 
94 #define CMTI "+CMTI:"
95 #define MAXLEN_CMTI_ANSWER 32
96 #define MAXLEN_SMS_CONTENT DATA_MAXLEN
97 
98 static bool gsm_line_received;
99 static bool prompt_received;
100 static bool waiting_for_reply; /* An AT command has been sent and an answer is expected */
101 
102 // static char msg_status[16];
103 // static char msg_date[32];
104 
105 static char expected_ack[10];
106 static char gsm_buf[GSM_MAX_PAYLOAD] __attribute__ ((aligned));
110 
111 #define STATUS_NONE 0
112 #define STATUS_CSQ 1
113 #define STATUS_REQUESTING_MESSAGE 2
114 #define STATUS_SEND_AT 3
115 #define STATUS_SEND_CMGF 4
116 #define STATUS_SEND_CNMI 5
117 #define STATUS_SEND_CPMS 6
118 #define STATUS_RECEPTION_SMS2 7
119 #define STATUS_WAITING_DATA 8
120 #define STATUS_IDLE 9
121 #define STATUS_WAITING_PROMPT 10
122 #define STATUS_DELETE_SMS 11
123 #define STATUS_POWERON 12
124 
126 
128 
129 static void Send_AT(void);
130 static void Send_CMGF(void);
131 static void Send_CNMI(void);
132 static void Send_CPMS(void);
133 static void Suppr_SMS(int);
134 static void gsm_send_report_continue(void);
135 static void gsm_parse(uint8_t c);
136 static void gsm_got_line(void);
137 static void gsm_got_prompt(void);
138 static void gsm_receive_content(void);
139 static void request_for_msg(void);
140 static void Send_CSQ(void);
141 static void Send(const char string[]);
142 static void parse_msg_header(void);
143 static char* indexn(char*, char, uint8_t);
144 
145 
148 
149 
150 /*****************************************************************************/
151 void gsm_init(void) {
152  if (gsm_status == STATUS_NONE) { /* First call */
153  LED_ON(GSM_ONOFF_LED);
154  gsm_status = STATUS_POWERON;
155  //} else { /* Second call */
156  // gsm_buf_idx = 0;
157  // gsm_line_received = false;
158  //
159  // Send_AT();
160  // gsm_status = STATUS_SEND_AT;
161  // gsm_gsm_init_status = FALSE;
162  }
163  gcs_index = 0;
164  gcs_index_max = 0;
165 #ifdef GCS_NUMBER_1
166  gcs_index_max++;
167 #endif
168 #ifdef GCS_NUMBER_2
169  gcs_index_max++;
170 #endif
171 }
172 
173 void gsm_init_report(void) { /* Second call */
174  if (gsm_status != STATUS_NONE) {
175  gsm_buf_idx = 0;
176  gsm_line_received = false;
177 
178  Send_AT();
179  gsm_status = STATUS_SEND_AT;
180  gsm_gsm_init_report_status = FALSE;
181  }
182 }
183 
184 void gsm_event(void) {
185  if (GSMBuffer()) {
186  ReadGSMBuffer();
187  }
188 
189  if (gsm_line_received) {
190  if (gsm_buf_len > 0) DOWNLINK_SEND_DEBUG_GSM_RECEIVE(DefaultChannel, DefaultDevice, gsm_buf_len, gsm_buf);
191  gsm_got_line();
192  gsm_line_received = false;
193  } else if (prompt_received) {
194  DOWNLINK_SEND_DEBUG_GSM_RECEIVE(DefaultChannel, DefaultDevice, 1, ">");
195  gsm_got_prompt();
196  prompt_received = false;
197  }
198 }
199 
200 
201 // A line of length gsm_buf_len is available in the gsm_buf buffer
202 static void gsm_got_line(void)
203 {
204  if (gsm_status == STATUS_WAITING_DATA) { // Currently receiving a SMS
206  Suppr_SMS(index_msg);
207  gsm_status = STATUS_DELETE_SMS;
208  } else if (gsm_status == STATUS_IDLE
209  && strncmp(CMTI, gsm_buf, strlen(CMTI)) == 0) {
210  /* A SMS is available */
211  /* Extracting the index of the message */
212  char * first_comma = indexn(gsm_buf, ',',MAXLEN_CMTI_ANSWER);
213  if (first_comma) {
214  index_msg = atoi(first_comma+1);
215  request_for_msg();
216  gsm_status = STATUS_REQUESTING_MESSAGE;
217  }
218  } else if (waiting_for_reply) { // Other cases
219  // Do we get what we were expecting
220 
221  bool gsm_answer = strncmp(expected_ack, gsm_buf, strlen(expected_ack)) == 0;
222  if (gsm_answer) {
223  waiting_for_reply = false;
224 
225  switch(gsm_status) {
226  case STATUS_CSQ :
228  gsm_status = STATUS_WAITING_PROMPT;
229  break;
230 
233  gsm_status = STATUS_WAITING_DATA;
234  break;
235 
236  case STATUS_SEND_AT :
237  gsm_answer = false;
238  Send_CMGF();
239  gsm_status = STATUS_SEND_CMGF;
240  break;
241 
242  case STATUS_SEND_CMGF :
243  gsm_answer = false;
244  Send_CNMI();
245  gsm_status = STATUS_SEND_CNMI;
246  break;
247 
248  case STATUS_SEND_CNMI :
249  gsm_answer = false;
250  Send_CPMS();
251  gsm_status = STATUS_SEND_CPMS;
252  break;
253 
254  case STATUS_SEND_CPMS :
255  gsm_answer = false;
256  gsm_status = STATUS_IDLE;
257  gsm_gsm_send_report_status = MODULES_START;
258  break;
259 
260  case STATUS_DELETE_SMS :
261  gsm_status = STATUS_IDLE;
262  break;
263 
264  default:
265  break;
266  }
267  } else {
268  /* Let's wait for the next line */
269  }
270  }
271 }
272 
273 
274 
275 // Receiving a SMS, first step: asking for a given message
276 static void request_for_msg(void)
277 {
278  char demande_lecture_SMS[16];
279 
280  strcpy(expected_ack, "+CMGR");
281  sprintf(demande_lecture_SMS, "AT+CMGR=%d", index_msg);
282  waiting_for_reply = true;
283  Send(demande_lecture_SMS);
284 }
285 
286 
292 static void gsm_receive_content(void)
293 {
294  // ?????? sprintf(data_to_send, "%d %s %s %s %s", index_msg, flag, expediteur, dateheure, data_recue);
295  // ?????? Send(data_to_send);
296 
297  // Checking the number of the sender
298  if (
299 //#if ! (defined GCS_NUMBER_1 || defined GCS_NUMBER_2 || defined SAFETY_NUMBER_1 || defined SAFETY_NUMBER_2)
300  true
301 //#else
302 // false
303 //#endif
304 #ifdef GCS_NUMBER_1
305  || strncmp((char*)GCS_NUMBER_1, origin, strlen(GCS_NUMBER_1)) == 0
306 #endif
307 #ifdef GCS_NUMBER_2
308  || strncmp((char*)GCS_NUMBER_2, origin, strlen(GCS_NUMBER_2)) == 0
309 #endif
310 #ifdef SAFETY_NUMBER_1
311  || strncmp((char*)SAFETY_NUMBER_1, origin, strlen(SAFETY_NUMBER_1)) == 0
312 #endif
313 #ifdef SAFETY_NUMBER_2
314  || strncmp((char*)SAFETY_NUMBER_2, origin, strlen(SAFETY_NUMBER_2)) == 0
315 #endif
316  ) {
317  // Decoding the message ...
318 
319  // Search for the instruction
320  switch (gsm_buf[0]) {
321  case 'B' :
322  {
323  uint8_t block_index = atoi(gsm_buf+1);
324  if (block_index > 0) /* Warning: no way to go to the first block */
325  nav_goto_block(block_index);
326  break;
327  }
328  case 'S' :
329  {
330  uint8_t var_index = atoi(gsm_buf+1);
331  if (var_index > 0) {
332  float value = atof(indexn(gsm_buf, ' ',MAXLEN_SMS_CONTENT)+1);
333  DlSetting(var_index, value);
334  }
335  }
336 
337  default:
338  // Report an error ???
339  break;
340  }
341  }
342 }
343 
344 
345 // Deleting a SMS
346 void Suppr_SMS(int index_)
347 {
348  char demande_suppression[20];
349 
350  sprintf(demande_suppression, "AT+CMGD=%d", index_);
351  strcpy(expected_ack, "OK");
352  waiting_for_reply = true;
353  Send(demande_suppression);
354 }
355 
356 
357 // We just have received a prompt ">" (we are sending a SMS)
358 static void gsm_got_prompt(void)
359 {
360  if (gsm_status == STATUS_WAITING_PROMPT) { // We were waiting for a prompt
361  char string[strlen(data_to_send) +3];
362 
363  sprintf(string, "%s%c", data_to_send, CTRLZ);
364  Send(string);
365  }
366 
367  gsm_status = STATUS_IDLE;
368 }
369 
372 static void parse_msg_header(void)
373 {
374  /* Extraction du flag*/
377  /* Extraction de l'expediteur*/
378  // Extraction(buffer2, '"', 2, 1, '"', 1, 0, origin);
379 
380  /* Extraction de date heure*/
381  // Extraction(buffer2, '"', 4, 1, '"', 1, 0, msg_date);
382 
383  //pb d'ecriture du flag => solution de fortune (pb si flag != rec unread)
384  //??????? strncpy(flag, flag, 10);
385 }
386 
387 
388 
389 // Periodic message, first step (called every 60s)
391 {
392  gsm_status = STATUS_IDLE;
393  if(gsm_status == STATUS_IDLE) {
394  // Checking the network coverage
395  Send_CSQ();
396  gsm_status = STATUS_CSQ;
397  }
398 }
399 
400 
401 // Sending a message, second step; we have asked for network quality
403 {
404  //We got "+CSQ: <rssi>,<ber>" <rssi> and <ber> on 2 digits (cf 3.5.4.4.4)
405  // and we expect "OK" on the second line
406  uint8_t rssi = atoi(gsm_buf + strlen("+CSQ: "));
407 
408  // Donnee GPS :ne sont pas envoyes gps_mode, gps.tow, gps.utm_pos.zone, gps_nb_ovrn
409  // Donnees batterie (seuls vsupply et autopilot_flight_time sont envoyes)
410  // concatenation de toutes les infos en un seul message à transmettre
411  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);
412 
413  // send the number and wait for the prompt
414  char buf[32];
415  switch (gcs_index) {
416 #ifdef GCS_NUMBER_1
417  case 0 :
418  sprintf(buf, "AT+CMGS=\"%s\"", GCS_NUMBER_1);
419  Send(buf);
420  break;
421 #endif
422 #ifdef GCS_NUMBER_2
423  case 1 :
424  sprintf(buf, "AT+CMGS=\"%s\"", GCS_NUMBER_2);
425  Send(buf);
426  break;
427 #endif
428  default :
429  gcs_index = 0;
430  break;
431  }
432  gcs_index++;
433  if (gcs_index == gcs_index_max) gcs_index = 0;
434 }
435 
436 
437 
438 
439 static void Send_AT(void)
440 {
441  strcpy(expected_ack, "OK");
442  waiting_for_reply = true;
443 
444  Send("ATE0");
445 }
446 
447 static void Send_CMGF(void)
448 {
449  strcpy(expected_ack, "OK");
450  waiting_for_reply = true;
451  Send("AT+CMGF=1");
452 }
453 
454 static void Send_CSQ(void)
455 {
456  /***** FIXME ****** strcpy(expected_ack, "+CSQ:"); ****/
457  strcpy(expected_ack, "OK");
458  waiting_for_reply = true;
459  Send("AT+CSQ");
460 }
461 
462 static void Send_CNMI(void)
463 {
464  strcpy(expected_ack, "OK");
465  waiting_for_reply = true;
466  Send("AT+CNMI=1,1,0,0,0");
467 }
468 
469 static void Send_CPMS(void)
470 {
471  strcpy(expected_ack, "+CPMS:");
472  waiting_for_reply = true;
473  Send("AT+CPMS=\"SM\"");
474 }
475 
476 
477 static void gsm_parse(uint8_t c) {
478  switch(c) {
479  case GSM_CMD_LINE_TERMINATION:
480  break;
481  case '>':
482  prompt_received = true;
483  break;
484  case GSM_RESPONSE_FORMATING:
485  gsm_buf[gsm_buf_idx] = '\0';
486  gsm_line_received = true;
487  gsm_buf_len = gsm_buf_idx;
488  gsm_buf_idx=0;
489  break;
490  default:
491  if (gsm_buf_idx < GSM_MAX_PAYLOAD) {
492  gsm_buf[gsm_buf_idx] = c;
493  gsm_buf_idx++;
494  } /* else extra characters are ignored */
495  break;
496  }
497 }
498 
499 
500 // Sending a string to the GSM module (through the UART)
501 static void Send(const char string[])
502 {
503  int i = 0;
504 
505  while(string[i])
506  GSMTransmit(string[i++]);
507  GSMTransmit(GSM_CMD_LINE_TERMINATION);
508 
509  DOWNLINK_SEND_DEBUG_GSM_SEND(DefaultChannel, DefaultDevice, i, string);
510 }
511 
512 /* Returns a pointer to the first occurrence of the character c in the firtn
513  n chars of string s. Return NULL if not found */
514 static char* indexn(char* s, char c, uint8_t n) {
515  while(n && (*s != c)) {
516  n--;
517  s++;
518  }
519  return (n ? s : NULL);
520 }
#define GSM_MAX_PAYLOAD
Definition: gsm.c:79
static bool gsm_line_received
Definition: gsm.c:98
static uint8_t gsm_buf_idx
Definition: gsm.c:107
struct NedCoor_i ned_vel
speed NED in cm/s
Definition: gps.h:69
uint16_t vsupply
Supply voltage in deciVolt.
Definition: autopilot.c:41
arch independent UART (Universal Asynchronous Receiver/Transmitter) API
static char data_to_send[DATA_MAXLEN]
Definition: gsm.c:109
uint16_t value
ADC1+2 interrupt hander.
Definition: adc_arch.c:577
uint16_t autopilot_flight_time
flight time in seconds.
Definition: autopilot.c:37
static bool waiting_for_reply
Definition: gsm.c:100
#define STATUS_REQUESTING_MESSAGE
Definition: gsm.c:113
static void Suppr_SMS(int)
Definition: gsm.c:346
static uint8_t gcs_index
Definition: gsm.c:146
#define GSM_ORIGIN_MAXLEN
Definition: gsm.c:91
static void parse_msg_header(void)
Message header in gsm_bug.
Definition: gsm.c:372
#define STATUS_SEND_AT
Definition: gsm.c:114
#define LED_ON(i)
Definition: led_hw.h:28
#define ReadGSMBuffer()
Definition: gsm.c:86
int32_t hmsl
height above mean sea level in mm
Definition: gps.h:67
static char * indexn(char *, char, uint8_t)
Definition: gsm.c:514
void gsm_init_report(void)
Definition: gsm.c:173
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:292
static void gsm_got_prompt(void)
Definition: gsm.c:358
static char origin[GSM_ORIGIN_MAXLEN]
Definition: gsm.c:108
#define STATUS_CSQ
Definition: gsm.c:112
#define MAXLEN_SMS_CONTENT
Definition: gsm.c:96
#define DATA_MAXLEN
Definition: gsm.c:92
static void Send_CSQ(void)
Definition: gsm.c:454
void gsm_send_report()
Definition: gsm.c:390
#define FALSE
Definition: imu_chimu.h:141
#define MAXLEN_CMTI_ANSWER
Definition: gsm.c:95
static uint8_t gsm_buf_len
Definition: gsm.c:107
static void Send(const char string[])
Definition: gsm.c:501
#define STATUS_WAITING_PROMPT
Definition: gsm.c:121
int32_t z
Down.
void gsm_event(void)
Definition: gsm.c:184
static uint8_t gcs_index_max
Definition: gsm.c:147
static uint8_t index_msg
Definition: gsm.c:127
Communications through GSM.
static void gsm_parse(uint8_t c)
Definition: gsm.c:477
int16_t gspeed
norm of 2d ground speed in cm/s
Definition: gps.h:70
#define STATUS_IDLE
Definition: gsm.c:120
Device independent GPS code (interface)
#define STATUS_SEND_CPMS
Definition: gsm.c:117
static uint8_t gsm_status
Definition: gsm.c:125
static bool prompt_received
Definition: gsm.c:99
#define STATUS_WAITING_DATA
Definition: gsm.c:119
int32_t north
in centimeters
#define STATUS_SEND_CMGF
Definition: gsm.c:115
#define STATUS_NONE
Definition: gsm.c:111
#define CMTI
Definition: gsm.c:94
struct adc_buf * buf
Definition: adc_arch.c:578
int32_t east
in centimeters
#define STATUS_POWERON
Definition: gsm.c:123
unsigned char uint8_t
Definition: types.h:14
static void Send_CPMS(void)
Definition: gsm.c:469
static void gsm_got_line(void)
Definition: gsm.c:202
#define GSMBuffer()
Definition: gsm.c:85
#define CTRLZ
Definition: gsm.c:90
static char gsm_buf[GSM_MAX_PAYLOAD]
Definition: gsm.c:106
#define GSMTransmit(_c)
Definition: gsm.c:88
static void gsm_send_report_continue(void)
Definition: gsm.c:402
static void request_for_msg(void)
Definition: gsm.c:276
#define STATUS_SEND_CNMI
Definition: gsm.c:116
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:105
static void Send_AT(void)
Definition: gsm.c:439
static void Send_CNMI(void)
Definition: gsm.c:462
#define STATUS_DELETE_SMS
Definition: gsm.c:122
static struct point c
Definition: discsurvey.c:39
void gsm_init(void)
Definition: gsm.c:151
void nav_goto_block(uint8_t b)
struct GpsState gps
global GPS state
Definition: gps.c:33
arch independent USB API
static void Send_CMGF(void)
Definition: gsm.c:447