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