Skip to content

Commit

Permalink
Add a separate INDI::GPSInterface so that any driver may opt to provi…
Browse files Browse the repository at this point in the history
…de GPS functionality without needing to be a dedicated GPS transceiver
  • Loading branch information
knro committed Sep 25, 2023
1 parent c229761 commit 28c431b
Show file tree
Hide file tree
Showing 5 changed files with 26 additions and 277 deletions.
4 changes: 2 additions & 2 deletions drivers/weather/uranusmeteo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -304,7 +304,7 @@ bool UranusMeteo::ISNewSwitch(const char * dev, const char * name, ISState * sta
{
if (dev && !strcmp(dev, getDeviceName()))
{
if (processSwitch(dev, name, states, names, n))
if (WI::processSwitch(dev, name, states, names, n))
return true;
}

Expand Down Expand Up @@ -337,7 +337,7 @@ bool UranusMeteo::ISNewNumber(const char * dev, const char * name, double values
return true;
}

if (processNumber(dev, name, values, names, n))
if (WI::processNumber(dev, name, values, names, n))
return true;
}

Expand Down
2 changes: 2 additions & 0 deletions libs/indibase/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,7 @@ list(APPEND ${PROJECT_NAME}_SOURCES
inditelescope.cpp
indifilterwheel.cpp
indifocuserinterface.cpp
indigpsinterface.cpp
indiweatherinterface.cpp
indifocuser.cpp
indirotator.cpp
Expand Down Expand Up @@ -186,6 +187,7 @@ list(APPEND ${PROJECT_NAME}_HEADERS
indireceiver.h
indifilterwheel.h
indifocuserinterface.h
indigpsinterface.h
indiweatherinterface.h
indifocuser.h
indirotator.h
Expand Down
230 changes: 15 additions & 215 deletions libs/indibase/indigps.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,191 +32,35 @@ namespace INDI
//////////////////////////////////////////////////////////////////////
///
//////////////////////////////////////////////////////////////////////
bool GPS::initProperties()
GPS::GPS() : GI(this)
{
DefaultDevice::initProperties();

time(&m_GPSTime);

PeriodNP[0].fill("PERIOD", "Period (s)", "%.f", 0, 3600, 60.0, 0);
PeriodNP.fill(getDeviceName(), "GPS_REFRESH_PERIOD", "Refresh", MAIN_CONTROL_TAB, IP_RW, 0, IPS_IDLE);

RefreshSP[0].fill("REFRESH", "GPS", ISS_OFF);
RefreshSP.fill(getDeviceName(), "GPS_REFRESH", "Refresh", MAIN_CONTROL_TAB, IP_RW, ISR_ATMOST1, 0, IPS_IDLE);

LocationNP[LOCATION_LATITUDE].fill("LAT", "Lat (dd:mm:ss)", "%010.6m", -90, 90, 0, 0.0);
LocationNP[LOCATION_LONGITUDE].fill("LONG", "Lon (dd:mm:ss)", "%010.6m", 0, 360, 0, 0.0);
LocationNP[LOCATION_ELEVATION].fill("ELEV", "Elevation (m)", "%g", -200, 10000, 0, 0);
LocationNP.fill(getDeviceName(), "GEOGRAPHIC_COORD", "Location", MAIN_CONTROL_TAB, IP_RO, 60, IPS_IDLE);

// System Time Settings
SystemTimeUpdateSP[UPDATE_NEVER].fill("UPDATE_NEVER", "Never", ISS_OFF);
SystemTimeUpdateSP[UPDATE_ON_STARTUP].fill("UPDATE_ON_STARTUP", "On Startup", ISS_ON);
SystemTimeUpdateSP[UPDATE_ON_REFRESH].fill("UPDATE_ON_REFRESH", "On Refresh", ISS_OFF);
SystemTimeUpdateSP.fill(getDeviceName(), "SYSTEM_TIME_UPDATE", "System Time", MAIN_CONTROL_TAB, IP_RW, ISR_1OFMANY, 60, IPS_IDLE);
SystemTimeUpdateSP.load();

TimeTP[0].fill("UTC", "UTC Time", nullptr);
TimeTP[1].fill("OFFSET", "UTC Offset", nullptr);
TimeTP.fill(getDeviceName(), "TIME_UTC", "UTC", MAIN_CONTROL_TAB, IP_RO, 60, IPS_IDLE);

setDefaultPollingPeriod(2000);

// Default interface, can be overridden by child
setDriverInterface(GPS_INTERFACE);

return true;
}

//////////////////////////////////////////////////////////////////////
///
//////////////////////////////////////////////////////////////////////
bool GPS::Disconnect()
{
m_SystemTimeUpdated = false;
return INDI::DefaultDevice::Disconnect();
}

//////////////////////////////////////////////////////////////////////
///
//////////////////////////////////////////////////////////////////////
bool GPS::updateProperties()
bool GPS::initProperties()
{
DefaultDevice::updateProperties();

if (isConnected())
{
// Update GPS and send values to client
IPState state = updateGPS();

LocationNP.setState(state);
defineProperty(LocationNP);
TimeTP.setState(state);
defineProperty(TimeTP);
RefreshSP.setState(state);
defineProperty(RefreshSP);
defineProperty(PeriodNP);
defineProperty(SystemTimeUpdateSP);
DefaultDevice::initProperties();

if (state != IPS_OK)
{
if (state == IPS_BUSY)
LOG_INFO("GPS fix is in progress...");
GI::initProperties("Main Control");

timerID = SetTimer(getCurrentPollingPeriod());
}
else if (PeriodNP[0].getValue() > 0)
timerID = SetTimer(PeriodNP[0].getValue());
}
else
{
deleteProperty(LocationNP);
deleteProperty(TimeTP);
deleteProperty(RefreshSP);
deleteProperty(PeriodNP);
deleteProperty(SystemTimeUpdateSP);
setDefaultPollingPeriod(2000);

if (timerID > 0)
{
RemoveTimer(timerID);
timerID = -1;
}
}
// Default interface, can be overridden by child
setDriverInterface(GPS_INTERFACE);

return true;
}

//////////////////////////////////////////////////////////////////////
///
//////////////////////////////////////////////////////////////////////
void GPS::TimerHit()
{
if (!isConnected())
{
timerID = SetTimer(getCurrentPollingPeriod());
return;
}

IPState state = updateGPS();

LocationNP.setState(state);
TimeTP.setState(state);
RefreshSP.setState(state);

switch (state)
{
// Ok
case IPS_OK:
LocationNP.apply();
TimeTP.apply();
// We got data OK, but if we are required to update once in a while, we'll call it.
if (PeriodNP[0].getValue() > 0)
timerID = SetTimer(PeriodNP[0].getValue() * 1000);

// Update system time
// This ideally should be done only ONCE
switch (SystemTimeUpdateSP.findOnSwitchIndex())
{
case UPDATE_ON_STARTUP:
if (m_SystemTimeUpdated == false)
{
setSystemTime(m_GPSTime);
m_SystemTimeUpdated = true;
}
break;

case UPDATE_ON_REFRESH:
setSystemTime(m_GPSTime);
break;

default:
break;
}

return;
break;

// GPS fix is in progress or alert
case IPS_ALERT:
LocationNP.apply();
TimeTP.apply();
break;

default:
break;
}

timerID = SetTimer(getCurrentPollingPeriod());
}

IPState GPS::updateGPS()
{
LOG_ERROR("updateGPS() must be implemented in GPS device child class to update TIME_UTC and GEOGRAPHIC_COORD properties.");
return IPS_ALERT;
}

//////////////////////////////////////////////////////////////////////
///
//////////////////////////////////////////////////////////////////////
bool GPS::setSystemTime(time_t &raw_time)
bool GPS::updateProperties()
{
#ifdef __linux__
#if defined(__GNU_LIBRARY__)
#if (__GLIBC__ >= 2) && (__GLIBC_MINOR__ > 30)
timespec sTime = {};
sTime.tv_sec = raw_time;
auto rc = clock_settime(CLOCK_REALTIME, &sTime);
if (rc)
LOGF_WARN("Failed to update system time: %s", strerror(rc));
#else
stime(&raw_time);
#endif
#else
stime(&raw_time);
#endif
#else
INDI_UNUSED(raw_time);
#endif
DefaultDevice::updateProperties();
GI::updateProperties();
return true;
}

Expand All @@ -227,26 +71,10 @@ bool GPS::ISNewSwitch(const char *dev, const char *name, ISState *states, char *
{
if (dev != nullptr && strcmp(dev, getDeviceName()) == 0)
{
// Refresh
if (RefreshSP.isNameMatch(name))
{
RefreshSP[0].s = ISS_OFF;
RefreshSP.setState(IPS_OK);
RefreshSP.apply();

// Manual trigger
GPS::TimerHit();
return true;
}
// System Time Update
else if (SystemTimeUpdateSP.isNameMatch(name))
if (GI::processSwitch(dev, name, states, names, n))
{
SystemTimeUpdateSP.update(states, names, n);
SystemTimeUpdateSP.setState(IPS_OK);
SystemTimeUpdateSP.apply();
if (SystemTimeUpdateSP.findOnSwitchIndex() == UPDATE_ON_REFRESH)
LOG_WARN("Updating system time on refresh may lead to undesirable effects on system time accuracy.");
saveConfig(true, SystemTimeUpdateSP.getName());
if (SystemTimeUpdateSP.isNameMatch(name))
saveConfig(true, SystemTimeUpdateSP.getName());
return true;
}
}
Expand All @@ -261,34 +89,8 @@ bool GPS::ISNewNumber(const char *dev, const char *name, double values[], char *
{
if (dev != nullptr && strcmp(dev, getDeviceName()) == 0)
{
if (PeriodNP.isNameMatch(name))
{
double prevPeriod = PeriodNP[0].getValue();
PeriodNP.update(values, names, n);
// Do not remove timer if GPS update is still in progress
if (timerID > 0 && RefreshSP.getState() != IPS_BUSY)
{
RemoveTimer(timerID);
timerID = -1;
}

if (PeriodNP[0].getValue() == 0)
{
LOG_INFO("GPS Update Timer disabled.");
}
else
{
timerID = SetTimer(PeriodNP[0].value * 1000);
// Need to warn user this is not recommended. Startup values should be enough
if (prevPeriod == 0)
LOG_INFO("GPS Update Timer enabled. Warning: Updating system-wide time repeatedly may lead to undesirable side-effects.");
}

PeriodNP.setState(IPS_OK);
PeriodNP.apply();

if (GI::processNumber(dev, name, values, names, n))
return true;
}
}

return DefaultDevice::ISNewNumber(dev, name, values, names, n);
Expand All @@ -300,9 +102,7 @@ bool GPS::ISNewNumber(const char *dev, const char *name, double values[], char *
bool GPS::saveConfigItems(FILE *fp)
{
DefaultDevice::saveConfigItems(fp);

PeriodNP.save(fp);
SystemTimeUpdateSP.save(fp);
GI::saveConfigItems(fp);
return true;
}
}
Loading

0 comments on commit 28c431b

Please sign in to comment.