При работе 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.