Add support for GPS as NTP server

Add support for GPS as NTP server by Christian Baars and Adrian Scillato
This commit is contained in:
Theo Arends 2019-12-23 15:39:07 +01:00
parent d5dcf462d0
commit fb8bb1223a
6 changed files with 216 additions and 194 deletions

View File

@ -54,5 +54,6 @@ The following binary downloads have been compiled with ESP8266/Arduino library c
- Change Smoother ``Fade`` using 100Hz instead of 20Hz animation (#7179) - Change Smoother ``Fade`` using 100Hz instead of 20Hz animation (#7179)
- Change number of rule ``Var``s and ``Mem``s from 5 to 16 (#4933) - Change number of rule ``Var``s and ``Mem``s from 5 to 16 (#4933)
- Add support for max 150 characters in most command parameter strings (#3686, #4754) - Add support for max 150 characters in most command parameter strings (#3686, #4754)
- Add support for GPS as NTP server by Christian Baars and Adrian Scillato
- Add Zigbee coalesce sensor attributes into a single message - Add Zigbee coalesce sensor attributes into a single message
- Add Deepsleep start delay based on Teleperiod if ``Teleperiod`` differs from 10 or 300 - Add Deepsleep start delay based on Teleperiod if ``Teleperiod`` differs from 10 or 300

View File

@ -6,6 +6,7 @@
- Change Smoother ``Fade`` using 100Hz instead of 20Hz animation (#7179) - Change Smoother ``Fade`` using 100Hz instead of 20Hz animation (#7179)
- Change number of rule ``Var``s and ``Mem``s from 5 to 16 (#4933) - Change number of rule ``Var``s and ``Mem``s from 5 to 16 (#4933)
- Add support for max 150 characters in most command parameter strings (#3686, #4754) - Add support for max 150 characters in most command parameter strings (#3686, #4754)
- Add support for GPS as NTP server by Christian Baars and Adrian Scillato
- Add Zigbee coalesce sensor attributes into a single message - Add Zigbee coalesce sensor attributes into a single message
- Add Deepsleep start delay based on Teleperiod if ``Teleperiod`` differs from 10 or 300 - Add Deepsleep start delay based on Teleperiod if ``Teleperiod`` differs from 10 or 300

View File

@ -493,7 +493,9 @@ void GetFeatures(void)
feature5 |= 0x00100000; feature5 |= 0x00100000;
#endif #endif
// feature5 |= 0x00200000; // feature5 |= 0x00200000;
// feature5 |= 0x00400000; #ifdef USE_GPS
feature5 |= 0x00400000;
#endif
// feature5 |= 0x00800000; // feature5 |= 0x00800000;
// feature5 |= 0x01000000; // feature5 |= 0x01000000;

View File

@ -295,7 +295,8 @@ const char kSensorNames[] PROGMEM =
D_SENSOR_SM2135_CLK "|" D_SENSOR_SM2135_DAT "|" D_SENSOR_SM2135_CLK "|" D_SENSOR_SM2135_DAT "|"
D_SENSOR_DEEPSLEEP "|" D_SENSOR_EXS_ENABLE "|" D_SENSOR_DEEPSLEEP "|" D_SENSOR_EXS_ENABLE "|"
D_SENSOR_SLAVE_TX "|" D_SENSOR_SLAVE_RX "|" D_SENSOR_SLAVE_RESET "|" D_SENSOR_SLAVE_RESET "i|" D_SENSOR_SLAVE_TX "|" D_SENSOR_SLAVE_RX "|" D_SENSOR_SLAVE_RESET "|" D_SENSOR_SLAVE_RESET "i|"
D_SENSOR_HPMA_RX "|" D_SENSOR_HPMA_TX "|" D_SENSOR_GPS_RX "|" D_SENSOR_GPS_TX D_SENSOR_HPMA_RX "|" D_SENSOR_HPMA_TX "|"
D_SENSOR_GPS_RX "|" D_SENSOR_GPS_TX
; ;
const char kSensorNamesFixed[] PROGMEM = const char kSensorNamesFixed[] PROGMEM =
@ -673,6 +674,7 @@ const uint8_t kGpioNiceList[] PROGMEM = {
#endif // USE_SOLAX_X1 #endif // USE_SOLAX_X1
#endif // USE_ENERGY_SENSOR #endif // USE_ENERGY_SENSOR
// Serial
#ifdef USE_SERIAL_BRIDGE #ifdef USE_SERIAL_BRIDGE
GPIO_SBR_TX, // Serial Bridge Serial interface GPIO_SBR_TX, // Serial Bridge Serial interface
GPIO_SBR_RX, // Serial Bridge Serial interface GPIO_SBR_RX, // Serial Bridge Serial interface
@ -727,6 +729,11 @@ const uint8_t kGpioNiceList[] PROGMEM = {
GPIO_IBEACON_RX, GPIO_IBEACON_RX,
GPIO_IBEACON_TX, GPIO_IBEACON_TX,
#endif #endif
#ifdef USE_GPS
GPIO_GPS_RX, // GPS serial interface
GPIO_GPS_TX, // GPS serial interface
#endif
#ifdef USE_MGC3130 #ifdef USE_MGC3130
GPIO_MGC3130_XFER, GPIO_MGC3130_XFER,
GPIO_MGC3130_RESET, GPIO_MGC3130_RESET,
@ -756,11 +763,7 @@ const uint8_t kGpioNiceList[] PROGMEM = {
GPIO_A4988_MS3, // A4988 microstep pin3 GPIO_A4988_MS3, // A4988 microstep pin3
#endif #endif
#ifdef USE_DEEPSLEEP #ifdef USE_DEEPSLEEP
GPIO_DEEPSLEEP GPIO_DEEPSLEEP,
#endif
#ifdef USE_GPS
GPIO_GPS_RX, // GPS serial interface
GPIO_GPS_TX // GPS serial interface
#endif #endif
}; };

View File

@ -1,5 +1,5 @@
/* /*
xsns_60_GPS.ino - GPS UBLOX support for Sonoff-Tasmota xsns_60_GPS.ino - GPS UBLOX support for Tasmota
Copyright (C) 2019 Theo Arends, Christian Baars and Adrian Scillato Copyright (C) 2019 Theo Arends, Christian Baars and Adrian Scillato
@ -15,7 +15,10 @@
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifdef USE_GPS
/*********************************************************************************************\
-------------------------------------------------------------------------------------------- --------------------------------------------------------------------------------------------
Version Date Action Description Version Date Action Description
-------------------------------------------------------------------------------------------- --------------------------------------------------------------------------------------------
@ -97,14 +100,13 @@ rule2 on tele-GPS#int>9 do DisplayText [f0c9l4]I%value% endon on tele-GPS#int
rule3 on tele-FLOG#sec do DisplayText [f0c1l4]SAV:%value% endon on tele-FLOG#rec==1 do DisplayText [f0c1l4]REC: endon on tele-FLOG#mode do DisplayText [f0c14l4]M%value% endon rule3 on tele-FLOG#sec do DisplayText [f0c1l4]SAV:%value% endon on tele-FLOG#rec==1 do DisplayText [f0c1l4]REC: endon on tele-FLOG#mode do DisplayText [f0c14l4]M%value% endon
*/ \*********************************************************************************************/
#ifdef USE_GPS #define XSNS_60 60
#include "NTPServer.h" #include "NTPServer.h"
#include "NTPPacket.h" #include "NTPPacket.h"
/*********************************************************************************************\ /*********************************************************************************************\
* constants * constants
\*********************************************************************************************/ \*********************************************************************************************/
@ -117,7 +119,6 @@ const char kUBXTypes[] PROGMEM = "UBX";
#define UBX_LAT_LON_THRESHOLD 1000 // filter out some noise of local drift #define UBX_LAT_LON_THRESHOLD 1000 // filter out some noise of local drift
/********************************************************************************************\ /********************************************************************************************\
| *globals | *globals
\*********************************************************************************************/ \*********************************************************************************************/
@ -152,13 +153,13 @@ const char UBLOX_INIT[] PROGMEM = {
char UBX_name[4]; char UBX_name[4];
struct UBX_t{ struct UBX_t {
const char UBX_HEADER[2] = { 0xB5, 0x62 }; // TODO: Check if we really save space here inside the struct const char UBX_HEADER[2] = { 0xB5, 0x62 }; // TODO: Check if we really save space here inside the struct
const char NAV_POSLLH_HEADER[2] = { 0x01, 0x02 }; const char NAV_POSLLH_HEADER[2] = { 0x01, 0x02 };
const char NAV_STATUS_HEADER[2] = { 0x01, 0x03 }; const char NAV_STATUS_HEADER[2] = { 0x01, 0x03 };
const char NAV_TIME_HEADER[2] = { 0x01, 0x21 }; const char NAV_TIME_HEADER[2] = { 0x01, 0x21 };
struct entry_t{ struct entry_t {
int32_t lat; //raw sensor value int32_t lat; //raw sensor value
int32_t lon; //raw sensor value int32_t lon; //raw sensor value
uint32_t time; //local time from system (maybe provided by the sensor) uint32_t time; //local time from system (maybe provided by the sensor)
@ -281,7 +282,9 @@ NtpServer timeServer(PortUdp);
/*********************************************************************************************\ /*********************************************************************************************\
* helper function * helper function
\*********************************************************************************************/ \*********************************************************************************************/
void UBXcalcChecksum(char* CK, size_t msgSize) {
void UBXcalcChecksum(char* CK, size_t msgSize)
{
memset(CK, 0, 2); memset(CK, 0, 2);
for (int i = 0; i < msgSize; i++) { for (int i = 0; i < msgSize; i++) {
CK[0] += ((char*)(&UBX.Message))[i]; CK[0] += ((char*)(&UBX.Message))[i];
@ -289,19 +292,22 @@ void UBXcalcChecksum(char* CK, size_t msgSize) {
} }
} }
boolean UBXcompareMsgHeader(const char* msgHeader) { bool UBXcompareMsgHeader(const char* msgHeader)
{
char* ptr = (char*)(&UBX.Message); char* ptr = (char*)(&UBX.Message);
return ptr[0] == msgHeader[0] && ptr[1] == msgHeader[1]; return ptr[0] == msgHeader[0] && ptr[1] == msgHeader[1];
} }
void UBXinitCFG(void){ void UBXinitCFG(void)
for(uint32_t i = 0; i < sizeof(UBLOX_INIT); i++) { {
for (uint32_t i = 0; i < sizeof(UBLOX_INIT); i++) {
UBXSerial->write( pgm_read_byte(UBLOX_INIT+i) ); UBXSerial->write( pgm_read_byte(UBLOX_INIT+i) );
} }
DEBUG_SENSOR_LOG(PSTR("UBX: turn off NMEA")); DEBUG_SENSOR_LOG(PSTR("UBX: turn off NMEA"));
} }
void UBXTriggerTele(void){ void UBXTriggerTele(void)
{
mqtt_data[0] = '\0'; mqtt_data[0] = '\0';
if (MqttShowSensor()) { if (MqttShowSensor()) {
MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_SENSOR), Settings.flag.mqtt_sensor_retain); MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_SENSOR), Settings.flag.mqtt_sensor_retain);
@ -313,7 +319,6 @@ void UBXTriggerTele(void){
/********************************************************************************************/ /********************************************************************************************/
void UBXDetect(void) void UBXDetect(void)
{ {
if ((pin[GPIO_GPS_RX] < 99) && (pin[GPIO_GPS_TX] < 99)) { if ((pin[GPIO_GPS_RX] < 99) && (pin[GPIO_GPS_TX] < 99)) {
@ -329,7 +334,7 @@ void UBXDetect(void)
UBXinitCFG(); // turn of NMEA, only use "our" UBX-messages UBXinitCFG(); // turn of NMEA, only use "our" UBX-messages
#ifdef USE_FLOG #ifdef USE_FLOG
if(!Flog){ if (!Flog) {
Flog = new FLOG; // init Flash Log Flog = new FLOG; // init Flash Log
Flog->init(); Flog->init();
} }
@ -340,7 +345,8 @@ void UBXDetect(void)
UBXTriggerTele(); // ... once at after start UBXTriggerTele(); // ... once at after start
} }
uint32_t UBXprocessGPS() { uint32_t UBXprocessGPS()
{
static uint32_t fpos = 0; static uint32_t fpos = 0;
static char checksum[2]; static char checksum[2];
static uint8_t currentMsgType = MT_NONE; static uint8_t currentMsgType = MT_NONE;
@ -353,20 +359,20 @@ uint32_t UBXprocessGPS() {
byte c = UBXSerial->read(); byte c = UBXSerial->read();
if ( fpos < 2 ) { if ( fpos < 2 ) {
// For the first two bytes we are simply looking for a match with the UBX header bytes (0xB5,0x62) // For the first two bytes we are simply looking for a match with the UBX header bytes (0xB5,0x62)
if ( c == UBX.UBX_HEADER[fpos] ) if ( c == UBX.UBX_HEADER[fpos] ) {
fpos++; fpos++;
else } else {
fpos = 0; // Reset to beginning state. fpos = 0; // Reset to beginning state.
} }
else { } else {
// If we come here then fpos >= 2, which means we have found a match with the UBX_HEADER // If we come here then fpos >= 2, which means we have found a match with the UBX_HEADER
// and we are now reading in the bytes that make up the payload. // and we are now reading in the bytes that make up the payload.
// Place the incoming byte into the ubxMessage struct. The position is fpos-2 because // Place the incoming byte into the ubxMessage struct. The position is fpos-2 because
// the struct does not include the initial two-byte header (UBX_HEADER). // the struct does not include the initial two-byte header (UBX_HEADER).
if ( (fpos-2) < payloadSize ) if ( (fpos-2) < payloadSize ) {
((char*)(&UBX.Message))[fpos-2] = c; ((char*)(&UBX.Message))[fpos-2] = c;
}
fpos++; fpos++;
if ( fpos == 4 ) { if ( fpos == 4 ) {
@ -424,7 +430,7 @@ uint32_t UBXprocessGPS() {
} }
} }
// DEBUG_SENSOR_LOG(PSTR("UBX: got none or unknown Message")); // DEBUG_SENSOR_LOG(PSTR("UBX: got none or unknown Message"));
if(data_bytes!=0) { if (data_bytes!=0) {
UBX.state.non_empty_loops++; UBX.state.non_empty_loops++;
DEBUG_SENSOR_LOG(PSTR("UBX: got %u bytes, non-empty-loop: %u"), data_bytes, UBX.state.non_empty_loops); DEBUG_SENSOR_LOG(PSTR("UBX: got %u bytes, non-empty-loop: %u"), data_bytes, UBX.state.non_empty_loops);
} else { } else {
@ -436,8 +442,10 @@ uint32_t UBXprocessGPS() {
/********************************************************************************************\ /********************************************************************************************\
| * callback functions for the download | * callback functions for the download
\*********************************************************************************************/ \*********************************************************************************************/
#ifdef USE_FLOG #ifdef USE_FLOG
void UBXsendHeader(void) { void UBXsendHeader(void)
{
WebServer->setContentLength(CONTENT_LENGTH_UNKNOWN); WebServer->setContentLength(CONTENT_LENGTH_UNKNOWN);
WebServer->sendHeader(F("Content-Disposition"), F("attachment; filename=TASMOTA.gpx")); WebServer->sendHeader(F("Content-Disposition"), F("attachment; filename=TASMOTA.gpx"));
WSSend(200, CT_STREAM, F( WSSend(200, CT_STREAM, F(
@ -448,7 +456,8 @@ void UBXsendHeader(void) {
"<trk>\r\n<trkseg>\r\n")); "<trk>\r\n<trkseg>\r\n"));
} }
void UBXsendRecord(uint8_t *buf){ void UBXsendRecord(uint8_t *buf)
{
char record[100]; char record[100];
char stime[32]; char stime[32];
UBX_t::entry_t *entry = (UBX_t::entry_t*)buf; UBX_t::entry_t *entry = (UBX_t::entry_t*)buf;
@ -462,21 +471,26 @@ void UBXsendRecord(uint8_t *buf){
WebServer->sendContent_P(record); WebServer->sendContent_P(record);
} }
void UBXsendFooter(void){ void UBXsendFooter(void)
{
WebServer->sendContent(F("</trkseg>\n</trk>\n</gpx>")); WebServer->sendContent(F("</trkseg>\n</trk>\n</gpx>"));
WebServer->sendContent(""); WebServer->sendContent("");
Rtc.user_time_entry = false; // we have blocked the main loop and want a new valid time Rtc.user_time_entry = false; // we have blocked the main loop and want a new valid time
} }
/********************************************************************************************/ /********************************************************************************************/
void UBXsendFile(void){
void UBXsendFile(void)
{
if (!HttpCheckPriviledgedAccess()) { return; } if (!HttpCheckPriviledgedAccess()) { return; }
Flog->startDownload(sizeof(UBX.rec_buffer),UBXsendHeader,UBXsendRecord,UBXsendFooter); Flog->startDownload(sizeof(UBX.rec_buffer),UBXsendHeader,UBXsendRecord,UBXsendFooter);
} }
#endif //USE_FLOG #endif //USE_FLOG
/********************************************************************************************/ /********************************************************************************************/
void UBXSetRate(uint16_t interval){ void UBXSetRate(uint16_t interval)
{
UBX.Message.cfgRate.cls = 0x06; UBX.Message.cfgRate.cls = 0x06;
UBX.Message.cfgRate.id = 0x08; UBX.Message.cfgRate.id = 0x08;
UBX.Message.cfgRate.len = 6; UBX.Message.cfgRate.len = 6;
@ -491,15 +505,15 @@ void UBXSetRate(uint16_t interval){
DEBUG_SENSOR_LOG(PSTR("UBX: requested interval: %u seconds measRate: %u ms"), interval, UBX.Message.cfgRate.measRate); DEBUG_SENSOR_LOG(PSTR("UBX: requested interval: %u seconds measRate: %u ms"), interval, UBX.Message.cfgRate.measRate);
UBXSerial->write(UBX.UBX_HEADER[0]); UBXSerial->write(UBX.UBX_HEADER[0]);
UBXSerial->write(UBX.UBX_HEADER[1]); UBXSerial->write(UBX.UBX_HEADER[1]);
for(uint32_t i =0; i<sizeof(UBX.Message.cfgRate); i++){ for (uint32_t i =0; i<sizeof(UBX.Message.cfgRate); i++) {
UBXSerial->write(((uint8_t*)(&UBX.Message.cfgRate))[i]); UBXSerial->write(((uint8_t*)(&UBX.Message.cfgRate))[i]);
DEBUG_SENSOR_LOG(PSTR("UBX: cfgRate byte %u: %x"), i, ((uint8_t*)(&UBX.Message.cfgRate))[i]); DEBUG_SENSOR_LOG(PSTR("UBX: cfgRate byte %u: %x"), i, ((uint8_t*)(&UBX.Message.cfgRate))[i]);
} }
UBX.state.log_interval = 10*interval; UBX.state.log_interval = 10*interval;
} }
void UBXSelectMode(uint16_t mode)
void UBXSelectMode(uint16_t mode){ {
DEBUG_SENSOR_LOG(PSTR("UBX: set mode to %u"),mode); DEBUG_SENSOR_LOG(PSTR("UBX: set mode to %u"),mode);
switch(mode){ switch(mode){
#ifdef USE_FLOG #ifdef USE_FLOG
@ -537,7 +551,7 @@ void UBXSelectMode(uint16_t mode){
UBX.mode.send_when_new = 0; // only TELE UBX.mode.send_when_new = 0; // only TELE
break; break;
case 9: case 9:
if (timeServer.beginListening()){ if (timeServer.beginListening()) {
UBX.mode.runningNTP = true; UBX.mode.runningNTP = true;
} }
break; break;
@ -555,7 +569,7 @@ void UBXSelectMode(uint16_t mode){
Settings.longitude = UBX.state.last_lon; Settings.longitude = UBX.state.last_lon;
break; break;
default: default:
if(mode>1000 && mode <1066) { if (mode>1000 && mode <1066) {
// UBXSetRate(mode-1000); // min. 1001 = 0.001 Hz, but will be converted to 1/65535 anyway ~0.015 Hz, max. 2000 = 1.000 Hz // UBXSetRate(mode-1000); // min. 1001 = 0.001 Hz, but will be converted to 1/65535 anyway ~0.015 Hz, max. 2000 = 1.000 Hz
UBXSetRate(mode-1000); // set interval between measurements in seconds from 1 to 65 UBXSetRate(mode-1000); // set interval between measurements in seconds from 1 to 65
} }
@ -564,26 +578,28 @@ void UBXSelectMode(uint16_t mode){
UBX.mode.send_UI_only = true; UBX.mode.send_UI_only = true;
UBXTriggerTele(); UBXTriggerTele();
} }
/********************************************************************************************/ /********************************************************************************************/
bool UBXHandlePOSLLH(){ bool UBXHandlePOSLLH()
{
DEBUG_SENSOR_LOG(PSTR("UBX: iTOW: %u"),UBX.Message.navPosllh.iTOW); DEBUG_SENSOR_LOG(PSTR("UBX: iTOW: %u"),UBX.Message.navPosllh.iTOW);
if(UBX.state.gpsFix>1){ if (UBX.state.gpsFix>1) {
if(UBX.mode.filter_noise){ if (UBX.mode.filter_noise) {
if((UBX.Message.navPosllh.lat-UBX.rec_buffer.values.lat<abs(UBX_LAT_LON_THRESHOLD))||(UBX.Message.navPosllh.lon-UBX.rec_buffer.values.lon<abs(UBX_LAT_LON_THRESHOLD))){ if ((UBX.Message.navPosllh.lat-UBX.rec_buffer.values.lat<abs(UBX_LAT_LON_THRESHOLD))||(UBX.Message.navPosllh.lon-UBX.rec_buffer.values.lon<abs(UBX_LAT_LON_THRESHOLD))) {
DEBUG_SENSOR_LOG(PSTR("UBX: Diff lat: %u lon: %u "),UBX.Message.navPosllh.lat-UBX.rec_buffer.values.lat, UBX.Message.navPosllh.lon-UBX.rec_buffer.values.lon); DEBUG_SENSOR_LOG(PSTR("UBX: Diff lat: %u lon: %u "),UBX.Message.navPosllh.lat-UBX.rec_buffer.values.lat, UBX.Message.navPosllh.lon-UBX.rec_buffer.values.lon);
return false; //no new position return false; //no new position
} }
} }
UBX.rec_buffer.values.lat = UBX.Message.navPosllh.lat; UBX.rec_buffer.values.lat = UBX.Message.navPosllh.lat;
UBX.rec_buffer.values.lon = UBX.Message.navPosllh.lon; UBX.rec_buffer.values.lon = UBX.Message.navPosllh.lon;
DEBUG_SENSOR_LOG(PSTR("UBX: lat/lon: %i / %i"),UBX.rec_buffer.values.lat, UBX.rec_buffer.values.lon); DEBUG_SENSOR_LOG(PSTR("UBX: lat/lon: %i / %i"), UBX.rec_buffer.values.lat, UBX.rec_buffer.values.lon);
DEBUG_SENSOR_LOG(PSTR("UBX: hAcc: %d"),UBX.Message.navPosllh.hAcc); DEBUG_SENSOR_LOG(PSTR("UBX: hAcc: %d"), UBX.Message.navPosllh.hAcc);
UBX.state.last_iTOW = UBX.Message.navPosllh.iTOW; UBX.state.last_iTOW = UBX.Message.navPosllh.iTOW;
UBX.state.last_height = UBX.Message.navPosllh.height; UBX.state.last_height = UBX.Message.navPosllh.height;
UBX.state.last_vAcc = UBX.Message.navPosllh.vAcc; UBX.state.last_vAcc = UBX.Message.navPosllh.vAcc;
UBX.state.last_hAcc = UBX.Message.navPosllh.hAcc; UBX.state.last_hAcc = UBX.Message.navPosllh.hAcc;
if(UBX.mode.send_when_new){ if (UBX.mode.send_when_new) {
UBXTriggerTele(); UBXTriggerTele();
} }
return true; // new position return true; // new position
@ -593,21 +609,22 @@ bool UBXHandlePOSLLH(){
return false; // no GPS-fix return false; // no GPS-fix
} }
void UBXHandleSTATUS(){ void UBXHandleSTATUS()
DEBUG_SENSOR_LOG(PSTR("UBX: gpsFix: %u, valid: %u"),UBX.Message.navStatus.gpsFix, (UBX.Message.navStatus.flags)&1); {
if((UBX.Message.navStatus.flags)&1){ DEBUG_SENSOR_LOG(PSTR("UBX: gpsFix: %u, valid: %u"), UBX.Message.navStatus.gpsFix, (UBX.Message.navStatus.flags)&1);
if ((UBX.Message.navStatus.flags)&1) {
UBX.state.gpsFix = UBX.Message.navStatus.gpsFix; //only store fixed status if flag is valid UBX.state.gpsFix = UBX.Message.navStatus.gpsFix; //only store fixed status if flag is valid
} } else {
else{
UBX.state.gpsFix = 0; // without valid flag, everything is "no fix" UBX.state.gpsFix = 0; // without valid flag, everything is "no fix"
} }
} }
void UBXHandleTIME(){ void UBXHandleTIME()
DEBUG_SENSOR_LOG(PSTR("UBX: UTC-Time: %u-%u-%u %u:%u:%u"),UBX.Message.navTime.year, UBX.Message.navTime.month ,UBX.Message.navTime.day,UBX.Message.navTime.hour,UBX.Message.navTime.min,UBX.Message.navTime.sec); {
if(UBX.Message.navTime.valid.UTC){ DEBUG_SENSOR_LOG(PSTR("UBX: UTC-Time: %u-%u-%u %u:%u:%u"), UBX.Message.navTime.year, UBX.Message.navTime.month ,UBX.Message.navTime.day,UBX.Message.navTime.hour,UBX.Message.navTime.min,UBX.Message.navTime.sec);
if (UBX.Message.navTime.valid.UTC) {
DEBUG_SENSOR_LOG(PSTR("UBX: UTC-Time is valid")); DEBUG_SENSOR_LOG(PSTR("UBX: UTC-Time is valid"));
if(Rtc.user_time_entry == false || UBX.mode.forceUTCupdate){ if (Rtc.user_time_entry == false || UBX.mode.forceUTCupdate) {
AddLog_P(LOG_LEVEL_INFO, PSTR("UBX: UTC-Time is valid, set system time")); AddLog_P(LOG_LEVEL_INFO, PSTR("UBX: UTC-Time is valid, set system time"));
TIME_T gpsTime; TIME_T gpsTime;
gpsTime.year = UBX.Message.navTime.year - 1970; gpsTime.year = UBX.Message.navTime.year - 1970;
@ -624,7 +641,7 @@ void UBXHandleTIME(){
void UBXHandleOther(void) void UBXHandleOther(void)
{ {
if(UBX.state.non_empty_loops>6){ // we expect only 4-5 non-empty loops in a row, could change with other sensor speed (Hz) if (UBX.state.non_empty_loops>6) { // we expect only 4-5 non-empty loops in a row, could change with other sensor speed (Hz)
UBXinitCFG(); // this should only happen with lots of NMEA-messages, but it is only a guess!! UBXinitCFG(); // this should only happen with lots of NMEA-messages, but it is only a guess!!
AddLog_P(LOG_LEVEL_ERROR, PSTR("UBX: possible device-reset, will re-init")); AddLog_P(LOG_LEVEL_ERROR, PSTR("UBX: possible device-reset, will re-init"));
UBXSerial->flush(); UBXSerial->flush();
@ -664,8 +681,8 @@ void UBXLoop(void)
} }
#ifdef USE_FLOG #ifdef USE_FLOG
if(counter>UBX.state.log_interval){ if (counter>UBX.state.log_interval) {
if(Flog->recording && new_position){ if (Flog->recording && new_position) {
UBX.rec_buffer.values.time = Rtc.local_time; UBX.rec_buffer.values.time = Rtc.local_time;
Flog->addToBuffer(UBX.rec_buffer.bytes, sizeof(UBX.rec_buffer.bytes)); Flog->addToBuffer(UBX.rec_buffer.bytes, sizeof(UBX.rec_buffer.bytes));
counter = 0; counter = 0;
@ -673,7 +690,7 @@ void UBXLoop(void)
} }
#endif // USE_FLOG #endif // USE_FLOG
counter++; counter++;
} }
/********************************************************************************************/ /********************************************************************************************/
@ -735,12 +752,11 @@ void UBXShow(bool json)
dtostrfd((double)UBX.state.last_vAcc/1000.0f,3,hAcc); dtostrfd((double)UBX.state.last_vAcc/1000.0f,3,hAcc);
dtostrfd((double)UBX.state.last_hAcc/1000.0f,3,vAcc); dtostrfd((double)UBX.state.last_hAcc/1000.0f,3,vAcc);
if (json) if (json) {
{
ResponseAppend_P(PSTR(",\"GPS\":{")); ResponseAppend_P(PSTR(",\"GPS\":{"));
if(UBX.mode.send_UI_only){ if (UBX.mode.send_UI_only) {
uint32_t i = UBX.state.log_interval / 10; uint32_t i = UBX.state.log_interval / 10;
ResponseAppend_P(PSTR("\"fil\":%u,\"int\":%u}"),UBX.mode.filter_noise, i); ResponseAppend_P(PSTR("\"fil\":%u,\"int\":%u}"), UBX.mode.filter_noise, i);
} else { } else {
ResponseAppend_P(PSTR("\"lat\":%s,\"lon\":%s,\"height\":%s,\"hAcc\":%s,\"vAcc\":%s}"), lat, lon, height, hAcc, vAcc); ResponseAppend_P(PSTR("\"lat\":%s,\"lon\":%s,\"height\":%s,\"hAcc\":%s,\"vAcc\":%s}"), lat, lon, height, hAcc, vAcc);
} }
@ -755,32 +771,32 @@ void UBXShow(bool json)
#ifdef DEBUG_TASMOTA_SENSOR #ifdef DEBUG_TASMOTA_SENSOR
#ifdef USE_FLOG #ifdef USE_FLOG
WSContentSend_PD(HTTP_SNS_FLOGVER, Flog->num_sectors, Flog->size, Flog->current_sector, Flog->sectors_left, Flog->sector.header.physical_start_sector); WSContentSend_PD(HTTP_SNS_FLOGVER, Flog->num_sectors, Flog->size, Flog->current_sector, Flog->sectors_left, Flog->sector.header.physical_start_sector);
if(Flog->recording){ if (Flog->recording) {
WSContentSend_PD(HTTP_SNS_FLOGREC, Flog->sector.header.buf_pointer - 8); WSContentSend_PD(HTTP_SNS_FLOGREC, Flog->sector.header.buf_pointer - 8);
} }
#endif //USE_FLOG #endif //USE_FLOG
#endif // DEBUG_TASMOTA_SENSOR #endif // DEBUG_TASMOTA_SENSOR
#ifdef USE_FLOG #ifdef USE_FLOG
if(Flog->ready){ if (Flog->ready) {
WSContentSend_P(HTTP_SNS_FLOG,kFLOG_STATE[Flog->recording]); WSContentSend_P(HTTP_SNS_FLOG,kFLOG_STATE[Flog->recording]);
} }
if(!Flog->recording && Flog->found_saved_data){ if (!Flog->recording && Flog->found_saved_data) {
WSContentSend_P(HTTP_BTN_FLOG_DL); WSContentSend_P(HTTP_BTN_FLOG_DL);
} }
#endif //USE_FLOG #endif //USE_FLOG
if(UBX.mode.runningNTP){ if (UBX.mode.runningNTP) {
WSContentSend_P(HTTP_SNS_NTPSERVER); WSContentSend_P(HTTP_SNS_NTPSERVER);
} }
#endif // USE_WEBSERVER #endif // USE_WEBSERVER
} }
} }
/*********************************************************************************************\ /*********************************************************************************************\
* check the UBX commands * check the UBX commands
\*********************************************************************************************/ \*********************************************************************************************/
bool UBXCmd(void) { bool UBXCmd(void)
{
bool serviced = true; bool serviced = true;
if (XdrvMailbox.data_len > 0) { if (XdrvMailbox.data_len > 0) {
UBXSelectMode(XdrvMailbox.payload); UBXSelectMode(XdrvMailbox.payload);
@ -793,8 +809,6 @@ bool UBXCmd(void) {
* Interface * Interface
\*********************************************************************************************/ \*********************************************************************************************/
#define XSNS_60 60
bool Xsns60(uint8_t function) bool Xsns60(uint8_t function)
{ {
bool result = false; bool result = false;
@ -805,7 +819,7 @@ bool Xsns60(uint8_t function)
UBXDetect(); UBXDetect();
break; break;
case FUNC_COMMAND_SENSOR: case FUNC_COMMAND_SENSOR:
if (XSNS_60 == XdrvMailbox.index){ if (XSNS_60 == XdrvMailbox.index) {
result = UBXCmd(); result = UBXCmd();
} }
break; break;
@ -814,7 +828,7 @@ bool Xsns60(uint8_t function)
break; break;
case FUNC_EVERY_100_MSECOND: case FUNC_EVERY_100_MSECOND:
#ifdef USE_FLOG #ifdef USE_FLOG
if(!Flog->running_download) if (!Flog->running_download)
#endif //USE_FLOG #endif //USE_FLOG
{ {
UBXLoop(); UBXLoop();
@ -831,7 +845,7 @@ bool Xsns60(uint8_t function)
#ifdef USE_WEBSERVER #ifdef USE_WEBSERVER
case FUNC_WEB_SENSOR: case FUNC_WEB_SENSOR:
#ifdef USE_FLOG #ifdef USE_FLOG
if(!Flog->running_download) if (!Flog->running_download)
#endif //USE_FLOG #endif //USE_FLOG
{ {
UBXShow(0); UBXShow(0);

View File

@ -131,7 +131,8 @@ a_setoption = [[
"GroupTopic replaces %topic% (0) or fixed topic cmnd/grouptopic (1)", "GroupTopic replaces %topic% (0) or fixed topic cmnd/grouptopic (1)",
"Enable incrementing bootcount when deepsleep is enabled", "Enable incrementing bootcount when deepsleep is enabled",
"Do not power off if slider moved to far left", "Do not power off if slider moved to far left",
"","", "Bypass Compatibility check",
"",
"Enable shutter support", "Enable shutter support",
"Invert PCF8574 ports" "Invert PCF8574 ports"
],[ ],[
@ -187,7 +188,7 @@ a_features = [[
"USE_SHUTTER","USE_PCF8574","USE_DDSU666","USE_DEEPSLEEP", "USE_SHUTTER","USE_PCF8574","USE_DDSU666","USE_DEEPSLEEP",
"USE_SONOFF_SC","USE_SONOFF_RF","USE_SONOFF_L1","USE_EXS_DIMMER", "USE_SONOFF_SC","USE_SONOFF_RF","USE_SONOFF_L1","USE_EXS_DIMMER",
"USE_ARDUINO_SLAVE","USE_HIH6","USE_HPMA","USE_TSL2591", "USE_ARDUINO_SLAVE","USE_HIH6","USE_HPMA","USE_TSL2591",
"USE_DHT12","","","", "USE_DHT12","","USE_GPS","",
"","","","", "","","","",
"","","","" "","","",""
]] ]]