Pracuję nad aplikacją, która używa modemu GSM do jednej z dwóch rzeczy; sprawdź jego status za pomocą wbudowanego stosu HTTP, wysyłając żądanie GET do serwera lub wysyłając dane do serwera (przy użyciu protokołu UDP). Wypróbowałem kilka różnych metod, aby było to tak wiarygodne, jak to tylko możliwe, a na koniec jestem gotów poprosić o pomoc.Zapisywanie sterownika modemu GSM?
Moja aplikacja napisana jest dla modułu SIMCOM908 i platformy PIC18 (do projektowania używam Eksploratora PIC18).
Problem polega więc na tym, że modem jest zajęty robieniem czegoś i pomija polecenie. Jako człowiek, zobaczyłbym to i po prostu ponownie wysłałem polecenie. Dodanie obiektu do MCU do limitu czasu i ponowne wysłanie nie jest problemem.
Problem polega na tym, że modem wysyła niezamawiane odpowiedzi po różnych zdarzeniach. Gdy modem zmieni status rejestracji (z wieżą komórki), odpowie: +CGREG: 1, ...
lub gdy GPS będzie gotowy GPS Ready
. Odpowiedzi te mogą się zdarzyć w dowolnym czasie, w tym w środku polecenia (np. Tworzenie połączenia IP).
To jest problem, ponieważ nie wymyśliłem sposobu, aby sobie z tym poradzić. Moja aplikacja musi wysłać polecenie (aby połączyć się z serwerem, na przykład, AT+CIPSTART="UDP","example.com",5000
) To polecenie odpowie "OK", a następnie po zakończeniu polecenia "CONNECT OK". Jednak muszę być w stanie reagować na wiele innych możliwych reakcji i nie znalazłem sposobu na zrobienie tego. Co muszę zrobić z moim kodem; czekać na odpowiedź z modemu, sprawdzić odpowiedź, wykonać akcję na podstawie tej odpowiedzi?
Mam ograniczony kod (jako 8-bitowy mikrokontroler!) I chciałbym, aby powtarzanie było minimalne. Jak mogę napisać funkcję odpowiedzi, która przyjmie odpowiedź z modułu GSM (zamówiona lub teraz), a następnie niech reszta mojego programu wie, co się dzieje?
Idealnie, chciałbym zrobić coś z tymi odpowiedziami. Jak zachować wewnętrzny stan (kiedy słyszę GPS Ready
, wiem, że mogę zasilać GPS itp
Być może istnieją pewne rzeczy, mam o tym myśleć, czy może jest projektem open source, które już rozwiązuje ten problem?
Oto co mam do tej pory..
/* Command responses */
enum {
// Common
OK = 0,
ERROR,
TIMEOUT,
OTHER,
// CGREG
NOT_REGISTERED,
// CGATT
NOT_ATTACHED,
// Network Status
NO_NETWORK,
// GPRS status
NO_ADDRESS,
// HTTP ACTION
NETWORK_ERROR,
// IP Stack State
IP_INITIAL,
IP_STATUS,
IP_CONFIG,
UDP_CLOSING,
UDP_CLOSED,
UDP_CONNECTING
} gsmResponse;
int gsm_sendCommand(const char * cmd) {
unsigned long timeout = timer_getCurrentTime() + 5000;
uart_clearb(GSM_UART); // Clear the input buffer
uart_puts(GSM_UART, cmd); // Send the command to the module
while (strstr(bf2, "\r") == NULL) { // Keep waiting for a response from the module
if (timeout < timer_getCurrentTime()) { // Check we haven't timed out yet
printf("Command timed out: %s\r\n", cmd);
return TIMEOUT;
}
}
timer_delay(100); // Let the rest of the response be received.
return OK;
}
int gsm_simpleCommand(const char * cmd) {
if (gsm_sendCommand(cmd) == TIMEOUT)
return TIMEOUT;
// Getting an ERROR response is quick, so if there is a response, this will be there
if (strstr(bf2, "ERROR") != NULL)
return ERROR;
// Sometimes the OK (meaning the command ran) can take a while
// As long as there wasn't an error, we can wait for the OK
while (strstr(bf2, "OK") == NULL);
return OK;
}
prosta komenda ma żadnych komend AT, która jest specjalnie szuka OK
lub ERROR
w odpowiedzi Coś AT
jednak ja również użyć go do bardziej zaawansowanych poleceń jak AT+CPIN?
ponieważ to m eScale złapię całą odpowiedź i mogę dalej szukać +CPIN: READY
. Jednak żadna z tych faktycznych odpowiedzi na niechciane odpowiedzi. W rzeczywistości funkcja gsm_sendCommand()
powróci wcześniej, gdy otrzyma niezamawianą odpowiedź.
Co to jest dobry sposób na zarządzanie złożonymi, czasami niezamawianymi wiadomościami o statusie? Proszę zauważyć, że ta aplikacja jest napisana w języku C i działa na mikrokontroleru 8-bitowym!
Prawdopodobnie musisz zaimplementować automat stanów (FSM): 'newstate = oldstate [message]', i może uznać drugi koniec za stanowy. – wildplasser
To będzie część tego, jak myślę. Jednak pełny FSM w tym przypadku nie wydaje się najlepszą opcją. Muszę śledzić stan binarny kilku różnych niezamówionych kodów, a nie wielu stanów pojedynczego systemu. Po prostu będę mieć kilka globalnych typów boolowskich do śledzenia. – dantheman