Merge branch 'development' into pre-release-12.3

This commit is contained in:
Theo Arends 2022-12-11 12:23:24 +01:00
commit ac8a886988
8 changed files with 116 additions and 110 deletions

View File

@ -19,6 +19,7 @@ All notable changes to this project will be documented in this file.
### Fixed
- TasmotaSerial ``read(buffer, size)`` regression from v9.3.0
- RCSwitch exception 0/6 on some protocols (#17285)
- ESP32 exception 28 when RtcNtpServer is enabled on restart (#17338)
## [12.2.0.5] 20221129
### Added

View File

@ -166,6 +166,7 @@ The latter links can be used for OTA upgrades too like ``OtaUrl http://ota.tasmo
- ModbusBridge baudrates over 76500 baud [#17106](https://github.com/arendst/Tasmota/issues/17106)
- SenseAir S8 module detection [#17033](https://github.com/arendst/Tasmota/issues/17033)
- RCSwitch exception 0/6 on some protocols [#17285](https://github.com/arendst/Tasmota/issues/17285)
- ESP32 exception 28 when RtcNtpServer is enabled on restart [#17338](https://github.com/arendst/Tasmota/issues/17338)
### Removed
- Define ``USE_PN532_DATA_RAW`` from NFC reader [#16939](https://github.com/arendst/Tasmota/issues/16939)

View File

@ -0,0 +1,23 @@
:H,ST7789,135,240,16,SPI,3,*,*,*,*,*,*,*,40
:S,2,1,3,0,80,30
:I
01,A0
11,A0
3A,81,55
36,81,00
21,80
13,80
29,A0
:o,28
:O,29
:A,2A,2B,2C
:R,36
:0,C0,35,28,00
:1,A0,28,34,01
:2,00,34,28,02
:3,60,28,35,03
:i,21,20
:TI2,38,32,23
:r,1
:B,30,5
#

View File

@ -1024,18 +1024,20 @@ bool DecodeCommand(const char* haystack, void (* const MyCommand[])(void), const
return false;
}
const char kOptions[] PROGMEM = "OFF|" D_OFF "|FALSE|" D_FALSE "|STOP|" D_STOP "|" D_CELSIUS "|" // 0
const char kOptions[] PROGMEM = "OFF|" D_OFF "|FALSE|" D_FALSE "|STOP|" D_STOP "|" D_CELSIUS "|DOWN|" D_CLOSE "|" // 0
"ON|" D_ON "|TRUE|" D_TRUE "|START|" D_START "|" D_FAHRENHEIT "|" D_USER "|" // 1
"TOGGLE|" D_TOGGLE "|" D_ADMIN "|" // 2
"BLINK|" D_BLINK "|" // 3
"BLINKOFF|" D_BLINKOFF "|" // 4
"UP|" D_OPEN "|" // 100
"ALL" ; // 255
const uint8_t sNumbers[] PROGMEM = { 0,0,0,0,0,0,0,
const uint8_t sNumbers[] PROGMEM = { 0,0,0,0,0,0,0,0,0,
1,1,1,1,1,1,1,1,
2,2,2,
3,3,
4,4,
100,100,
255 };
int GetStateNumber(const char *state_text)

View File

@ -254,7 +254,7 @@ uint8_t ShutterRealToPercentPosition(int32_t realpos, uint32_t index)
//uint16_t addon = ( realpercent*10 - Settings->shuttercoeff[j-1][index] ) * Shutter[index].open_max * (calibrate_pos[j+1] - calibrate_pos[j]) / (Settings->shuttercoeff[j][index] -Settings->shuttercoeff[j-1][index]) / 100;
//AddLog(LOG_LEVEL_ERROR, PSTR("SHT: Realpercent TEMP2: %d %%, delta %d, %d, coeff %d"), addon,( realpos - (Shutter[index].open_max * calibrate_pos[j] / 100) ) , (calibrate_pos[j+1] - calibrate_pos[j])* Shutter[index].open_max/100, (Settings->shuttercoeff[j][index] -Settings->shuttercoeff[j-1][index]));
realpercent += SHT_DIV_ROUND(((int64_t)realpos - SHT_DIV_ROUND(Shutter[index].open_max * calibrate_pos[j], 100)) * (Settings->shuttercoeff[j][index] - Settings->shuttercoeff[j-1][index]), (calibrate_pos[j+1] - calibrate_pos[j])/10*Shutter[index].open_max) ;
}
}
break;
}
}
@ -690,7 +690,7 @@ void ShutterStartInit(uint32_t i, int32_t direction, int32_t target_pos)
ShutterGlobal.start_reported = 0;
Shutter[i].tilt_real_pos = tmax(tmin(Shutter[i].tilt_real_pos,Shutter[i].tilt_config[1]),Shutter[i].tilt_config[0]);
Shutter[i].tilt_start_pos = Shutter[i].tilt_real_pos;
if (Shutter[i].tilt_config[1]-Shutter[i].tilt_config[0] != 0) {
if (Shutter[i].tilt_config[1]-Shutter[i].tilt_config[0] != 0) {
Shutter[i].venetian_delay = SHT_DIV_ROUND((direction > 0 ? Shutter[i].tilt_config[1]-Shutter[i].tilt_real_pos : Shutter[i].tilt_real_pos-Shutter[i].tilt_config[0]) * Shutter[i].tilt_config[2], Shutter[i].tilt_config[1]-Shutter[i].tilt_config[0]);
//AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: real %d, start %d, counter %d,freq_max %d, dir %d, freq %d"),Shutter[i].real_position, Shutter[i].start_position ,RtcSettings.pulse_counter[i],ShutterGlobal.open_velocity_max , direction ,ShutterGlobal.open_velocity_max );
AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: VenetianDelay: %d, Pos: %d, Dir: %d, Delta: %d, Dur: %d, StartP: %d, TgtP: %d"),
@ -864,6 +864,7 @@ void ShutterButtonHandler(void)
}
if (NOT_PRESSED == button) {
//AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: Shtr%d, Button %d, hold %d, dir %d, index %d, payload %d"), shutter_index+1, button_index+1, Button.hold_timer[button_index],Shutter[shutter_index].direction,XdrvMailbox.index,XdrvMailbox.payload);
if (Shutter[shutter_index].direction && (Button.hold_timer[button_index] > 0 && (!Settings->flag.button_single || Button.hold_timer[button_index] > 20))) {
XdrvMailbox.index = shutter_index +1;
XdrvMailbox.payload = XdrvMailbox.index;
@ -1062,7 +1063,7 @@ void ShutterToggle(bool dir)
void CmndShutterOpen(void)
{
//AddLog(LOG_LEVEL_DEBUG, PSTR("SHT: Payload open: %d, i %d"), XdrvMailbox.payload, XdrvMailbox.index);
if ((1 == XdrvMailbox.index) && (XdrvMailbox.payload != -99)) {
if ((!XdrvMailbox.usridx) && (XdrvMailbox.payload != -99)) {
XdrvMailbox.index = XdrvMailbox.payload;
}
XdrvMailbox.payload = 100;
@ -1085,11 +1086,10 @@ void CmndShutterStopOpen(void)
void CmndShutterClose(void)
{
//AddLog(LOG_LEVEL_DEBUG, PSTR("SHT: Payload close: %d, i %d"), XdrvMailbox.payload, XdrvMailbox.index);
if ((1 == XdrvMailbox.index) && (XdrvMailbox.payload != -99)) {
if ((!XdrvMailbox.usridx) && (XdrvMailbox.payload != -99)) {
XdrvMailbox.index = XdrvMailbox.payload;
}
XdrvMailbox.payload = 0;
XdrvMailbox.data_len = 0;
TasmotaGlobal.last_source = SRC_WEBGUI;
CmndShutterPosition();
}
@ -1143,14 +1143,15 @@ void CmndShutterStopToggleDir(void)
void CmndShutterStop(void)
{
if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= TasmotaGlobal.shutters_present)) {
//AddLog(LOG_LEVEL_DEBUG, PSTR("SHT: Try Stop %d: dir: %d"), XdrvMailbox.index, Shutter[XdrvMailbox.index -1].direction);
if (!(Settings->shutter_options[XdrvMailbox.index-1] & 2)) {
if ((1 == XdrvMailbox.index) && (XdrvMailbox.payload != -99)) {
if ((!XdrvMailbox.usridx) && (XdrvMailbox.payload != -99)) {
XdrvMailbox.index = XdrvMailbox.payload;
}
uint32_t i = XdrvMailbox.index -1;
if (Shutter[i].direction != 0) {
AddLog(LOG_LEVEL_DEBUG, PSTR("SHT: Stop moving %d: dir: %d"), XdrvMailbox.index, Shutter[i].direction);
AddLog(LOG_LEVEL_DEBUG, PSTR("SHT: Stop %d: dir: %d"), XdrvMailbox.index, Shutter[i].direction);
Shutter[i].target_position = Shutter[i].real_position;
}
if (XdrvMailbox.command)
@ -1182,17 +1183,17 @@ void CmndShutterPosition(void)
if (!(Settings->shutter_options[XdrvMailbox.index-1] & 2)) {
uint32_t index = XdrvMailbox.index-1;
//limit the payload
AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: Pos. in: payload %s (%d), payload %d, idx %d, src %d"), XdrvMailbox.data , XdrvMailbox.data_len, XdrvMailbox.payload , XdrvMailbox.index, TasmotaGlobal.last_source );
AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: Pos. payload <%s> (%d), payload %d, idx %d (%d), src %d"), XdrvMailbox.data , XdrvMailbox.data_len, XdrvMailbox.payload , XdrvMailbox.index, XdrvMailbox.usridx, TasmotaGlobal.last_source );
// value 0 with data_len > 0 can mean Open
// special handling fo UP,DOWN,TOGGLE,STOP command comming with payload -99
if ((XdrvMailbox.data_len > 1) && (XdrvMailbox.payload <= 0)) {
//UpperCase(XdrvMailbox.data, XdrvMailbox.data);
if (!strcasecmp(XdrvMailbox.data,D_CMND_SHUTTER_UP) || !strcasecmp(XdrvMailbox.data,D_CMND_SHUTTER_OPEN) || ((Shutter[index].direction==0) && !strcasecmp(XdrvMailbox.data,D_CMND_SHUTTER_STOPOPEN))) {
// STOP will come with payload 0 because predefined value in TASMOTA
if ((XdrvMailbox.data_len > 3) && (XdrvMailbox.payload <= 0)) {
if ( ((Shutter[index].direction==0) && !strcasecmp(XdrvMailbox.data,D_CMND_SHUTTER_STOPOPEN))) {
CmndShutterOpen();
return;
}
if (!strcasecmp(XdrvMailbox.data,D_CMND_SHUTTER_DOWN) || !strcasecmp(XdrvMailbox.data,D_CMND_SHUTTER_CLOSE) || ((Shutter[index].direction==0) && !strcasecmp(XdrvMailbox.data,D_CMND_SHUTTER_STOPCLOSE))) {
if ( ((Shutter[index].direction==0) && !strcasecmp(XdrvMailbox.data,D_CMND_SHUTTER_STOPCLOSE))) {
CmndShutterClose();
return;
}
@ -1205,6 +1206,7 @@ void CmndShutterPosition(void)
return;
}
if (!strcasecmp(XdrvMailbox.data,D_CMND_SHUTTER_STOP) || ((Shutter[index].direction) && (!strcasecmp(XdrvMailbox.data,D_CMND_SHUTTER_STOPOPEN) || !strcasecmp(XdrvMailbox.data,D_CMND_SHUTTER_STOPCLOSE)))) {
// Back to normal: all -99 if not a clear position
XdrvMailbox.payload = -99;
CmndShutterStop();
return;
@ -1293,16 +1295,11 @@ void CmndShutterPosition(void)
} // if (Shutter[i].direction[index] != new_shutterdirection)
} else {
target_pos_percent = ShutterRealToPercentPosition(Shutter[index].real_position, index);
ShutterReportPosition(true, index);
}
index = (!XdrvMailbox.usridx && !XdrvMailbox.data_len)?MAX_SHUTTERS:index;
ShutterReportPosition(true, index);
ShutterGlobal.start_reported = 1;
XdrvMailbox.index = index +1; // Fix random index for ShutterClose
// As this function is called three times from outside the command handler
// XdrvMailbox.command may not point to a char string resulting in exception 29 on strcpy
char command[CMDSZ] = { 0 };
XdrvMailbox.command = command;
strcpy(XdrvMailbox.command, D_CMND_SHUTTER_POSITION);
ResponseCmndIdxNumber((Settings->shutter_options[index] & 1) ? 100 - target_pos_percent : target_pos_percent);
} else {
ShutterReportPosition(true, MAX_SHUTTERS);
if (XdrvMailbox.command)
@ -1366,30 +1363,37 @@ void CmndShutterMotorDelay(void)
void CmndShutterMode(void)
{
if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= MAX_MODES)) {
ShutterGlobal.position_mode = XdrvMailbox.payload;
Settings->shutter_mode = XdrvMailbox.payload;
ShutterInit();
if (!XdrvMailbox.usridx && !XdrvMailbox.data_len) {
if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= MAX_MODES)) {
ShutterGlobal.position_mode = XdrvMailbox.payload;
Settings->shutter_mode = XdrvMailbox.payload;
ShutterInit();
}
ResponseCmndNumber(ShutterGlobal.position_mode);
}
ResponseCmndNumber(ShutterGlobal.position_mode);
}
void CmndShutterRelay(void)
{
if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= MAX_SHUTTERS)) {
if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 64)) {
Settings->shutter_startrelay[XdrvMailbox.index -1] = XdrvMailbox.payload;
if (XdrvMailbox.payload > 0) {
ShutterGlobal.RelayShutterMask |= 3 << (XdrvMailbox.payload - 1);
} else {
ShutterGlobal.RelayShutterMask ^= 3 << (Settings->shutter_startrelay[XdrvMailbox.index -1] - 1);
}
Settings->shutter_startrelay[XdrvMailbox.index -1] = XdrvMailbox.payload;
ShutterInit();
// if payload is 0 to disable the relay there must be a reboot. Otherwhise does not work
if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 64) && (XdrvMailbox.index <= MAX_SHUTTERS)) {
Settings->shutter_startrelay[XdrvMailbox.index -1] = XdrvMailbox.payload;
if (XdrvMailbox.payload > 0) {
ShutterGlobal.RelayShutterMask |= 3 << (XdrvMailbox.payload - 1);
} else {
ShutterGlobal.RelayShutterMask ^= 3 << (Settings->shutter_startrelay[XdrvMailbox.index -1] - 1);
}
ResponseCmndIdxNumber(Settings->shutter_startrelay[XdrvMailbox.index -1]);
Settings->shutter_startrelay[XdrvMailbox.index -1] = XdrvMailbox.payload;
ShutterInit();
// if payload is 0 to disable the relay there must be a reboot. Otherwhise does not work
}
uint32_t start = (!XdrvMailbox.usridx && !XdrvMailbox.data_len)?0:XdrvMailbox.index -1;
uint32_t end = (!XdrvMailbox.usridx && !XdrvMailbox.data_len)?TasmotaGlobal.shutters_present:XdrvMailbox.index;
// {"ShutterRelay1":"1","ShutterRelay2":"3","ShutterRelay3":"5"}
Response_P(PSTR("{"));
for (uint32_t i = start; i < end; i++) {
ResponseAppend_P(PSTR("%s\"" D_PRFX_SHUTTER D_CMND_SHUTTER_RELAY "%d\":\"%d\""), (i)?",":"", i+1,Settings->shutter_startrelay[i]);
}
ResponseAppend_P(PSTR("}"));
}
void CmndShutterButton(void)
@ -1676,22 +1680,18 @@ void CmndShutterSetTilt(void)
if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= TasmotaGlobal.shutters_present)) {
if (XdrvMailbox.payload != -99 ) {
Shutter[XdrvMailbox.index -1].tilt_target_pos = tmin(tmax(XdrvMailbox.payload, Shutter[XdrvMailbox.index -1].tilt_config[0]), Shutter[XdrvMailbox.index -1].tilt_config[1]);
XdrvMailbox.payload = -99;
}
if ((XdrvMailbox.data_len > 1) && (XdrvMailbox.payload <= 0)) {
if (!strcasecmp(XdrvMailbox.data,D_CMND_SHUTTER_OPEN) ) {
Shutter[XdrvMailbox.index -1].tilt_target_pos = Shutter[XdrvMailbox.index -1].tilt_config[3]; // open position
XdrvMailbox.payload = -99;
}
if (!strcasecmp(XdrvMailbox.data,D_CMND_SHUTTER_CLOSE) ) {
Shutter[XdrvMailbox.index -1].tilt_target_pos = Shutter[XdrvMailbox.index -1].tilt_config[4]; // close position
XdrvMailbox.payload = -99;
}
// assuming OPEN=100=tilt_config[3]/CLOSE=0=tilt_config[4]
if (XdrvMailbox.data_len > 3 && XdrvMailbox.payload >= 0 ) {
Shutter[XdrvMailbox.index -1].tilt_target_pos = Shutter[XdrvMailbox.index -1].tilt_config[XdrvMailbox.payload?3:4];
}
}
XdrvMailbox.data[0] = '\0';
AddLog(LOG_LEVEL_INFO, PSTR("SHT: TiltTarget %d, payload %d"), Shutter[XdrvMailbox.index -1].tilt_target_pos,XdrvMailbox.payload);
Shutter[XdrvMailbox.index -1].tiltmoving = 1;
// Avoid shutterposition try to interpret "open/close or payload"
XdrvMailbox.data_len = 0;
XdrvMailbox.payload = -99;
CmndShutterPosition();
}

View File

@ -405,9 +405,15 @@ extern "C" {
be_return(vm); /* return code */
}
// wc.POST(string | bytes) -> httpCode:int
int32_t wc_POST(struct bvm *vm);
int32_t wc_POST(struct bvm *vm) {
// Combined function for POST/PUT/PATCH/DELETE
enum {
wc_POST_op,
wc_PUT_op,
wc_PATCH_op,
wc_DELETE_op
};
int32_t wc_PostPutPatchDelete(struct bvm *vm, int32_t op);
int32_t wc_PostPutPatchDelete(struct bvm *vm, int32_t op) {
int32_t argc = be_top(vm);
if (argc >= 2 && (be_isstring(vm, 2) || be_isbytes(vm, 2))) {
HTTPClientLight * cl = wc_getclient(vm);
@ -420,7 +426,22 @@ extern "C" {
buf = (const char*) be_tobytes(vm, 2, &buf_len);
}
uint32_t http_connect_time = millis();
int32_t httpCode = cl->POST((uint8_t*)buf, buf_len);
int32_t httpCode;
switch (op) {
case wc_PUT_op:
httpCode = cl->PUT((uint8_t*)buf, buf_len);
break;
case wc_PATCH_op:
httpCode = cl->PATCH((uint8_t*)buf, buf_len);
break;
case wc_DELETE_op:
httpCode = cl->DELETE((uint8_t*)buf, buf_len);
break;
case wc_POST_op:
default:
httpCode = cl->POST((uint8_t*)buf, buf_len);
break;
}
wc_errorCodeMessage(httpCode, http_connect_time);
be_pushint(vm, httpCode);
be_return(vm); /* return code */
@ -428,73 +449,29 @@ extern "C" {
be_raise(vm, kTypeError, nullptr);
}
// wc.POST(string | bytes) -> httpCode:int
int32_t wc_POST(struct bvm *vm);
int32_t wc_POST(struct bvm *vm) {
return wc_PostPutPatchDelete(vm, wc_POST_op);
}
// wc.PUT(string | bytes) -> httpCode:int
int32_t wc_PUT(struct bvm *vm);
int32_t wc_PUT(struct bvm *vm) {
int32_t argc = be_top(vm);
if (argc >= 2 && (be_isstring(vm, 2) || be_isbytes(vm, 2))) {
HTTPClientLight * cl = wc_getclient(vm);
const char * buf = nullptr;
size_t buf_len = 0;
if (be_isstring(vm, 2)) { // string
buf = be_tostring(vm, 2);
buf_len = strlen(buf);
} else { // bytes
buf = (const char*) be_tobytes(vm, 2, &buf_len);
}
uint32_t http_connect_time = millis();
int32_t httpCode = cl->PUT((uint8_t*)buf, buf_len);
wc_errorCodeMessage(httpCode, http_connect_time);
be_pushint(vm, httpCode);
be_return(vm); /* return code */
}
be_raise(vm, kTypeError, nullptr);
return wc_PostPutPatchDelete(vm, wc_PUT_op);
}
// wc.PATCH(string | bytes) -> httpCode:int
int32_t wc_PATCH(struct bvm *vm);
int32_t wc_PATCH(struct bvm *vm) {
int32_t argc = be_top(vm);
if (argc >= 2 && (be_isstring(vm, 2) || be_isbytes(vm, 2))) {
HTTPClientLight * cl = wc_getclient(vm);
const char * buf = nullptr;
size_t buf_len = 0;
if (be_isstring(vm, 2)) { // string
buf = be_tostring(vm, 2);
buf_len = strlen(buf);
} else { // bytes
buf = (const char*) be_tobytes(vm, 2, &buf_len);
}
uint32_t http_connect_time = millis();
int32_t httpCode = cl->PATCH((uint8_t*)buf, buf_len);
wc_errorCodeMessage(httpCode, http_connect_time);
be_pushint(vm, httpCode);
be_return(vm); /* return code */
}
be_raise(vm, kTypeError, nullptr);
return wc_PostPutPatchDelete(vm, wc_PATCH_op);
}
// wc.DELETE(string | bytes) -> httpCode:int
int32_t wc_DELETE(struct bvm *vm);
int32_t wc_DELETE(struct bvm *vm) {
int32_t argc = be_top(vm);
if (argc >= 2 && (be_isstring(vm, 2) || be_isbytes(vm, 2))) {
HTTPClientLight * cl = wc_getclient(vm);
const char * buf = nullptr;
size_t buf_len = 0;
if (be_isstring(vm, 2)) { // string
buf = be_tostring(vm, 2);
buf_len = strlen(buf);
} else { // bytes
buf = (const char*) be_tobytes(vm, 2, &buf_len);
}
uint32_t http_connect_time = millis();
int32_t httpCode = cl->DELETE((uint8_t*)buf, buf_len);
wc_errorCodeMessage(httpCode, http_connect_time);
be_pushint(vm, httpCode);
be_return(vm); /* return code */
}
be_raise(vm, kTypeError, nullptr);
return wc_PostPutPatchDelete(vm, wc_DELETE_op);
}
int32_t wc_getstring(struct bvm *vm);

View File

@ -404,6 +404,8 @@ NtpServer RtcChipTimeServer(PortUdp);
void RtcChipEverySecond(void) {
static bool ntp_server_started = false;
if (TasmotaGlobal.global_state.network_down) { return; } // Exception on ESP32 if network is down (#17338)
if (Settings->sbflag1.local_ntp_server && (Rtc.utc_time > START_VALID_TIME)) {
if (!ntp_server_started) {
if (RtcChipTimeServer.beginListening()) {
@ -418,7 +420,7 @@ void RtcChipEverySecond(void) {
void CmndRtcNtpServer(void) {
// RtcChipNtpServer 0 or 1
if (XdrvMailbox.payload >= 0) {
if ((XdrvMailbox.payload >= 0) && !TasmotaGlobal.global_state.network_down) {
Settings->sbflag1.local_ntp_server = 0;
if ((XdrvMailbox.payload &1) && RtcChipTimeServer.beginListening()) {
Settings->sbflag1.local_ntp_server = 1;

View File

@ -584,7 +584,7 @@ void UBXSelectMode(uint16_t mode)
UBX.mode.send_when_new = 0; // only TELE
break;
case 9:
if (timeServer.beginListening()) {
if (!TasmotaGlobal.global_state.network_down && timeServer.beginListening()) {
UBX.mode.runningNTP = true;
}
break;
@ -722,7 +722,7 @@ void UBXLoop50msec(void)
}
}
// handle NTP-server
if(UBX.mode.runningNTP){
if(!TasmotaGlobal.global_state.network_down && UBX.mode.runningNTP){
timeServer.processOneRequest(UBX.rec_buffer.values.time, UBX.state.timeOffset - NTP_MILLIS_OFFSET);
}
}