I’m working to add snoop function on EQMOD driver to update local position and local time from another drivers whose get these information from a GPS via an Arduino module. Like the Astroberry project done on indi_rpi driver Thanks to rkaczorek for the idea.
Today it build to work with my own specific driver.
I think it could nice if this function is going to be integrated in the original EQMod driver. For that and to do a clean job, I think create a kind of “generic” function and publish the definition of the XML items required to send data to EQMod driver.
Sure I’ve to ask if the EQMod maintainer if he would include in the driver itself.
I would like to open the discussion for vector name, elements name, format of value/text and other idea about this topic.
Till now I use these information in my draft:
- Longitude In sexagesimal
- Longitude in sexagesimal
- Elevation in meter
- Date as yyyy-mm-dd
- Time as hh:mm
- IPState to know if the GPS is valid
First think I will change is to use two vectors for GPS Data. One for position data, and second one for Date/Time.
It looks that I program it correctly to have change done in the EQMod driver, but I’m not so familiar with the relations between LST, Julian date, EQ. Coordinates, UTC Time and scope location yet to be sure all changes are implemented.
Any help and support would be welcome.
As I’m not experimented programmers, I hope writing a correct and good usable code..
Here you are my code proposal:
bool EQMod::ISSnoopDevice (XMLEle *root)
/* This function expect that all datas from the GPS are in the same Text Vector
* We expect that the setting of time or position could be selected separatly by the user
* In usual the time is provide quite faster by the GPS than the localisation
* Philippe Besson
* V0.1 - 20th of August 2015
*/
{
time_t t0;
struct tm st={0}, lt={0};
int rc;
double dGpsLon, dGpsLat, dGpsElev;
char year[5], month[3], day [3], hour[3], min[3], sec[3];
// Wich device send the message
//TODO Could be used to do a self registration as subsrider to sent acknwoledgement back!
const char *propDevice = findXMLAttValu(root, "device");
DEBUGF(INDI::Logger::DBG_WARNING, "Received a snoop message from device : %s", propDevice);
/* XML Tag received by the GPS driver
2015-08-17T18:01:02: Date
2015-08-17T18:01:02: Heure GMT
2015-08-17T18:01:02: Altitude (m)
2015-08-17T18:01:02: Latitude
2015-08-17T18:01:02: Longitude
2015-08-17T18:01:02: Satellites
2015-08-17T18:01:02: Antenne
*/
const char *propState = findXMLAttValu(root, "state");
// GPS Value OK? Defined IPS_OK state of vector as GPSFix
if (!strcmp(propState, "Idle")) gpsdata.state = IPS_IDLE;
else if (!strcmp(propState, "Ok")) gpsdata.state = IPS_OK;
else if (!strcmp(propState, "Busy")) gpsdata.state = IPS_BUSY;
else if (!strcmp(propState, "Alert")) gpsdata.state = IPS_ALERT;
DEBUGF(INDI::Logger::DBG_DEBUG, "GPS State received : %s", propState);
DEBUGF(INDI::Logger::DBG_DEBUG, "GPS State received value : %d", gpsdata.state);
const char *propName = findXMLAttValu(root, "name");
if (!strcmp(propName, "GPS-SYNC"))
{
DEBUGF(INDI::Logger::DBG_DEBUG, "%s", "GPS-SYNC Message received !");
// Identified the GPS data as valid
if (gpsdata.state == IPS_OK)
{
XMLEle *ep=NULL;
for (ep = nextXMLEle(root, 1) ; ep != NULL ; ep = nextXMLEle(root, 0))
{
const char *elemName = findXMLAttValu(ep, "name");
DEBUGF(INDI::Logger::DBG_DEBUG, "Snooping property received %s", (char *)elemName);
if ((!strcmp(elemName, "GPSPOS")) && (!strcmp(pcdataXMLEle(ep), "On")))
// Mannage Local position value
// Convert Gps data coord to double value
{
if (f_scansexa(gpsdata.Lon, &dGpsLon) != 0)
{
DEBUGF(INDI::Logger::DBG_DEBUG, "Convertion error from sexagesimal to double for longitude from GPS %s", gpsdata.Lon);
return 0;
}
if (f_scansexa(gpsdata.Lat, &dGpsLat) != 0)
{
DEBUGF(INDI::Logger::DBG_DEBUG, "Convertion error from sexagesimal to double for latitude from GPS %s", gpsdata.Lat);
return 0;
}
dGpsElev = atof(gpsdata.Elev);
DEBUGF(INDI::Logger::DBG_DEBUG, "LONG %f", dGpsLon);
DEBUGF(INDI::Logger::DBG_DEBUG, "LAT %f", dGpsLat);
//strncpy(gpsdata.Lat, pcdataXMLEle(ep), sizeof(gpsdata.Lat));
// Here we set the new site postion from the GPS
if (updateLocation(dGpsLat, dGpsLon, dGpsElev))
{
LocationN[LOCATION_LATITUDE].value = dGpsLat;
LocationN[LOCATION_LONGITUDE].value = dGpsLon;
LocationN[LOCATION_ELEVATION].value = dGpsElev;
LocationNP.s=IPS_OK;
// Update client display
IDSetNumber(&LocationNP,NULL);
}
else
{
LocationNP.s=IPS_ALERT;
// Update client display
IDSetNumber(&LocationNP,NULL);
}
}
else if ((!strcmp(elemName, "GPSTIME")) && (!strcmp(pcdataXMLEle(ep), "On")))
// Mannage Time snoop value
{
// Here we set the new time from the GPS
//We are looking for time offset and time zone; GPS provide UTC time
t0 = time(NULL);
localtime_r(&t0, <);
DEBUGF(INDI::Logger::DBG_DEBUG, "Offset to GMT is %d", lt.tm_gmtoff);
DEBUGF(INDI::Logger::DBG_DEBUG, "The time zone is %s", lt.tm_zone);
/* initialize time from snopped device*/
DEBUGF(INDI::Logger::DBG_SESSION, "TIME = %s, DATE = %s", gpsdata.Time, gpsdata.Date);
rc = sscanf(gpsdata.Date, "%[^-]-%[^-]-%[^\n]", year, month, day);
DEBUGF(INDI::Logger::DBG_DEBUG, "rc DATE : %d", rc);
if (rc == 3)
{
rc = sscanf(gpsdata.Time, "%[^:]:%[^:]:%[^\n]", hour, min, sec);
DEBUGF(INDI::Logger::DBG_DEBUG, "rc TIME : %d", rc);
if (rc == 3)
{
// all extration data has been successfull (rc result OK)
// Reuse partially the init code for time initialisation
st.tm_year = atoi(year) - 1900;
st.tm_mon = atoi(month) -1;
st.tm_mday = atoi(day);
st.tm_hour = atoi(hour);
st.tm_min = atoi(min);
st.tm_sec = atoi(sec);
st.tm_isdst = 1; // Is DST on? 1 = yes, 0 = no, -1 = unknown
lasttimeupdate.tv_sec = mktime(&st) + lt.tm_gmtoff; // compensate with local time offset to UTC time
lasttimeupdate.tv_usec = lasttimeupdate.tv_sec * 1000;
// now gmtime give the UTC time from the GPS
gmtime_r(&lasttimeupdate.tv_sec, &utc);
lndate.seconds = utc.tm_sec; + ((double)lasttimeupdate.tv_usec / 1000000);
lndate.minutes = utc.tm_min;
lndate.hours = utc.tm_hour;
lndate.days = utc.tm_mday;
lndate.months = utc.tm_mon + 1;
lndate.years = utc.tm_year + 1900;
// Set the new value of the lastclockupdate value
clock_gettime(CLOCK_MONOTONIC, &lastclockupdate);
} //if (rc == 3)
} //if (rc == 3)
} //else if ((!strcmp(elemName, "GPSTIME")) && (!strcmp(pcdataXMLEle(ep), "On")))
} //for (ep = nextXMLEle(root, 1) ; ep != NULL ; ep = nextXMLEle(root, 0))
} //if (gpsdata.state == IPS_OK)
} //if (!strcmp(propName, "GPS-SYNC"))
if (!strcmp(propName, "GPS-INFO"))
// Getting GPS data throughtthe snoop of the text vector who's contain these
{
if (gpsdata.state == IPS_OK)
{
XMLEle *ep=NULL;
// Store values received by the GPS module on BoxControler
for (ep = nextXMLEle(root, 1) ; ep != NULL ; ep = nextXMLEle(root, 0))
{
const char *elemName = findXMLAttValu(ep, "name");
DEBUGF(INDI::Logger::DBG_DEBUG, "Snooping property received %s", (char *)elemName);
if (!strcmp(elemName, "Latitude"))
{
strncpy(gpsdata.Lat, pcdataXMLEle(ep), sizeof(gpsdata.Lat));
DEBUGF(INDI::Logger::DBG_DEBUG, "Latitude OK %s", gpsdata.Lat);
}
else if (!strcmp(elemName, "Longitude"))
{
strncpy(gpsdata.Lon, pcdataXMLEle(ep), sizeof(gpsdata.Lon));
DEBUGF(INDI::Logger::DBG_DEBUG, "Longitude OK %s", gpsdata.Lon);
}
else if (!strcmp(elemName, "Altitude (m)"))
{
strncpy(gpsdata.Elev, pcdataXMLEle(ep), sizeof(gpsdata.Elev));
DEBUGF(INDI::Logger::DBG_DEBUG, "Altitude OK %s", gpsdata.Elev);
}
else if (!strcmp(elemName, "Heure GMT"))
{
strncpy(gpsdata.Time, pcdataXMLEle(ep), sizeof(gpsdata.Time));
DEBUGF(INDI::Logger::DBG_DEBUG, "Heure GMT OK %s", gpsdata.Time);
}
else if (!strcmp(elemName, "Date"))
{
strncpy(gpsdata.Date, pcdataXMLEle(ep), sizeof(gpsdata.Date));
DEBUGF(INDI::Logger::DBG_DEBUG, "Date OK %s", gpsdata.Date);
}
} //for (ep = nextXMLEle(root, 1) ; ep != NULL ; ep = nextXMLEle(root, 0))
} //if (gpsdata.state == IPS_OK)
} //if (!strcmp(propName, "GPS-INFO"))
return true;
} //EQMod::ISSnoopDevice