При работе IoT устройств важно, чтобы время было синхронизировано с NTP серверами или сервером времени оператора сотовой связи. Если после загрузки SIM800 выполнить команду, она вернет дату и время по-умолчанию, вместо текущего.
AT+CCLK? +CCLK: "04/01/01,00:00:40+12" OK Проверим автоматическую синхронизацию времени AT+CLTS? +CLTS: 0 OK
Активируем автоматическую синхронизацию времени командой AT+CLTS:
AT+CLTS=1 OK Сохраним настройку в памяти для синхронизации времени при перезагрузке. AT&W Можно использовать короткую команду AT+CLTS=1;&W OK AT+CLTS? +CLTS: 1 OK
Перезагружаем модем командой AT+CFUN=1,1 (не всегда корректно отрабатывает) или AT+CFUN:
AT+CFUN=0 +SAPBR 1: DEACT +PDP: DEACT +CPIN: NOT READY OK AT+CFUN=1 +CPIN: READY OK SMS Ready Call Ready *PSUTTZ: 2019,5,25,18,46,18,"+12",0 DST: 0
Проверяем повторно время
AT+CCLK? +CCLK: "19/05/25,21:50:06+12" OK
Теперь время возвращается правильное. Оно возвращается в формате: «yy/mm/dd,hh:mm:ss+/-zz».
Синхронизация SIM800 с NTP Server-ом
Синхронизация SIM800 с NTP сервером у меня работает через раз. Причину не выяснил. Нередко получаю такую ошибку после запуска.
AT+CNTPCID=1 OK AT+CNTP="pool.ntp.org",3 OK AT+CNTP OK +CNTP: 62 - если команда с ошибкой +CNTP: 1 - если команда отработала без ошибки
Команда AT+CNTP для синхронизации с NTP сервером возвращает 62 ошибку.
1 - Network time synchronization is successful 61 - Network error 62 - DNS resolution error 63 - Connection error 64 - Service response error 65 - Service response timeout
Код для библиотеки TinyGSM для синхронизации времени на SIM800 с NTP сервером. Мой GitHub pull request.
boolean isValidNumber(String str) { boolean isNum = false; if(!(str.charAt(0) == '+' || str.charAt(0) == '-' || isDigit(str.charAt(0)))) return false; for(byte i=1;i < str.length(); i++) { if(!(isDigit(str.charAt(i)) || str.charAt(i) == '.')) return false; } return true; } String ShowNTPError(byte error) { switch (error) { case 1: return "Network time synchronization is successful"; case 61: return "Network error"; case 62: return "DNS resolution error"; case 63: return "Connection error"; case 64: return "Service response error"; case 65: return "Service response timeout"; default: return "Unknown error"; } } byte NTPServerSync(String server = "pool.ntp.org", byte TimeZone = 3) { Serial.println("Sync time with NTP server."); sendAT(GF("+CNTPCID=1")); if (waitResponse(10000L) != 1) { Serial.println("AT command \"AT+CNTPCID=1\" executing fault."); } String CNTP = "+CNTP=" + server + "," + String(TimeZone); sendAT(GF(CNTP)); if (waitResponse(10000L) != 1) { Serial.println("AT command \"" + CNTP + "\" executing fault."); } sendAT(GF("+CNTP")); if (waitResponse(10000L, GF(GSM_NL "+CNTP:"))) { String result = stream.readStringUntil('\n'); result.trim(); if (isValidNumber(result)) { return result.toInt(); } } else { Serial.println("AT command \"+CNTP\" executing fault."); } return -1; }
Cделаем разрешение (resolve) доменного имени:
AT+CDNSGIP="ya.ru" OK +CDNSGIP: 0,8 - parsing error +CDNSGIP: 1,"ya.ru","87.250.250.242" - корректный результат
Как и в случае с AT+CNTP периодически функция возвращает ошибку. Мне не удалось найти способа обеспечить 100% стабильную работу. Настройки DNS серверов принятых SIM800 корректные, даже когда AT команда AT+CDNSGIP возвращает неверный результат:
AT+CDNSCFG? PrimaryDns: 8.8.8.8 SecondaryDns: 8.8.4.4 OK
C DNS серверами все в порядке, однако, возникает проблема при синхронизации времени с NTP сервером, либо разрешения символического имени.
Код для TinyGSM для активации автоматической синхронизации времени
При выполнении команды перезагрузки (restart()) в TinyGSM выполняется команда AT+CLTS=1:
bool restart() { if (!testAT()) { return false; } //Enable Local Time Stamp for getting network time // TODO: Find a better place for this sendAT(GF("+CLTS=1")); if (waitResponse(10000L) != 1) { return false; } sendAT(GF("&W")); waitResponse(); sendAT(GF("+CFUN=0")); if (waitResponse(10000L) != 1) { return false; } sendAT(GF("+CFUN=1,1")); if (waitResponse(10000L) != 1) { return false; } delay(3000); return init(); }
Однако код отрабатывает некорректно. Если после restart() выполнить команду AT+CCLK?, то она вернет время по умолчанию. Для тестирования команд GSM модема SIM800 я написал скетч.
После тестирования различных вариантов получил нормально работающий код:
void SetAutoTimeSync() { Serial.println("Enable GSM RTC network time sync."); sendAT(GF("+CLTS=1")); if (waitResponse(10000L) != 1) { Serial.println("AT command \"AT+CLTS=1\" executing fault.");; } sendAT(GF("&W")); waitResponse(); sendAT(GF("+CFUN=0")); if (waitResponse(10000L) != 1) { Serial.println("AT command \"AT+CFUN=0\" executing fault.");; } //delay(3000); sendAT(GF("+CFUN=1")); //if (modemGSM.waitResponse(10000L) != 1) if (waitResponse(10000L, GF(GSM_NL "DST:")) != 1) { Serial.println("AT command \"AT+CFUN=1\" executing fault.");; } Serial.println("DateTime: "+ GetDateTime()); } String GetDateTime() { sendAT(GF("+CCLK?")); if (waitResponse(10000L, GF(GSM_NL "+CCLK:"))) { String body = stream.readStringUntil('\n'); return body; } else { Serial.println("AT command \"+CCLK?\" executing fault."); } return ""; }
Отправил в github.
Для парсинга строки DateTime возвращаемой GSM модемом SIM800 я написал следующую функцию:
//Parse GSM modem DateTime string "yy/mm/dd,hh:mm:ss+/-zz" bool ParseDateTimeString(String datetime, byte &year, byte &month, byte &day, byte &hours, byte &minutes, byte &seconds, byte &timezone) { return sscanf(datetime.c_str(), "%d/%d/%d,%d:%d:%d+%d", &year, &month, &day, &hours, &minutes, &seconds, &timezone) == 7; }
Вызов функции:
byte year = 0; byte month = 0; byte day = 0; byte hours = 0; byte minutes = 0; byte seconds = 0; byte timezone = 0; ParseDateTimeString("19/05/25,21:50:06+12", year, month, day, hours, minutes, seconds, timezone); char str[25]; sprintf(str, "%d/%d/%d,%d:%d:%d+%d", year, month, day, hours, minutes, seconds, timezone); Serial.println(str);
Полезные ссылки
- https://github.com/Warlib1975/GSM-modem-AT-commands-tester — небольшой скетч для отладки AT команд SIM800.
- https://elementztechblog.wordpress.com/2016/12/28/getting-time-and-date-from-gsm-modem/
- NTP на SIM800 (eng).
- Работа с DNS на SIM800.