Instrument Neutral Distributed Interface INDI  1.9.5
InMemoryDatabase.cpp
Go to the documentation of this file.
1 
9 #include "InMemoryDatabase.h"
10 
11 #include "basedevice.h"
12 #include "indicom.h"
13 
14 #include <cerrno>
15 #include <cstdlib>
16 #include <cstring>
17 #include <sys/stat.h>
18 
19 namespace INDI
20 {
21 namespace AlignmentSubsystem
22 {
23 InMemoryDatabase::InMemoryDatabase() : DatabaseReferencePositionIsValid(false),
24  LoadDatabaseCallback(nullptr), LoadDatabaseCallbackThisPointer(nullptr)
25 {
26 }
27 
29  double Tolerance) const
30 {
31  for (AlignmentDatabaseType::const_iterator iTr = MySyncPoints.begin(); iTr != MySyncPoints.end(); iTr++)
32  {
33  if (((std::abs((*iTr).RightAscension - CandidateEntry.RightAscension) < 24.0 * Tolerance / 100.0) &&
34  (std::abs((*iTr).Declination - CandidateEntry.Declination) < 180.0 * Tolerance / 100.0)) ||
35  ((std::abs((*iTr).TelescopeDirection.x - CandidateEntry.TelescopeDirection.x) < Tolerance / 100.0) &&
36  (std::abs((*iTr).TelescopeDirection.y - CandidateEntry.TelescopeDirection.y) < Tolerance / 100.0) &&
37  (std::abs((*iTr).TelescopeDirection.z - CandidateEntry.TelescopeDirection.z) < Tolerance / 100.0)))
38  return true;
39  }
40  return false;
41 }
42 
44 {
45  if (DatabaseReferencePositionIsValid)
46  {
47  Position = DatabaseReferencePosition;
48  return true;
49  }
50  else
51  return false;
52 }
53 
54 bool InMemoryDatabase::LoadDatabase(const char *DeviceName)
55 {
56  char DatabaseFileName[MAXRBUF];
57  char Errmsg[MAXRBUF];
58  XMLEle *FileRoot = nullptr;
59  XMLEle *EntriesRoot = nullptr;
60  XMLEle *EntryRoot = nullptr;
61  XMLEle *Element = nullptr;
62  XMLAtt *Attribute = nullptr;
63  LilXML *Parser = newLilXML();
64 
65  FILE *fp = nullptr;
66 
67  snprintf(DatabaseFileName, MAXRBUF, "%s/.indi/%s_alignment_database.xml", getenv("HOME"), DeviceName);
68 
69  fp = fopen(DatabaseFileName, "r");
70  if (fp == nullptr)
71  {
72  snprintf(Errmsg, MAXRBUF, "Unable to read alignment database file. Error loading file %s: %s\n",
73  DatabaseFileName, strerror(errno));
74  return false;
75  }
76 
77  char whynot[MAXRBUF];
78  if (nullptr == (FileRoot = readXMLFile(fp, Parser, whynot)))
79  {
80  snprintf(Errmsg, MAXRBUF, "Unable to parse database XML: %s", whynot);
81  return false;
82  }
83 
84  if (strcmp(tagXMLEle(FileRoot), "INDIAlignmentDatabase") != 0)
85  {
86  return false;
87  }
88 
89  if (nullptr == (EntriesRoot = findXMLEle(FileRoot, "DatabaseEntries")))
90  {
91  snprintf(Errmsg, MAXRBUF, "Cannot find DatabaseEntries element");
92  return false;
93  }
94 
95  if (nullptr != (Element = findXMLEle(FileRoot, "DatabaseReferenceLocation")))
96  {
97  if (nullptr == (Attribute = findXMLAtt(Element, "latitude")))
98  {
99  snprintf(Errmsg, MAXRBUF, "Cannot find latitude attribute");
100  return false;
101  }
102  sscanf(valuXMLAtt(Attribute), "%lf", &DatabaseReferencePosition.latitude);
103  if (nullptr == (Attribute = findXMLAtt(Element, "longitude")))
104  {
105  snprintf(Errmsg, MAXRBUF, "Cannot find longitude attribute");
106  return false;
107  }
108  sscanf(valuXMLAtt(Attribute), "%lf", &DatabaseReferencePosition.longitude);
109  DatabaseReferencePositionIsValid = true;
110  }
111 
112  MySyncPoints.clear();
113 
114  for (EntryRoot = nextXMLEle(EntriesRoot, 1); EntryRoot != nullptr; EntryRoot = nextXMLEle(EntriesRoot, 0))
115  {
116  AlignmentDatabaseEntry CurrentValues;
117  if (strcmp(tagXMLEle(EntryRoot), "DatabaseEntry") != 0)
118  {
119  return false;
120  }
121  for (Element = nextXMLEle(EntryRoot, 1); Element != nullptr; Element = nextXMLEle(EntryRoot, 0))
122  {
123  if (strcmp(tagXMLEle(Element), "ObservationJulianDate") == 0)
124  {
125  sscanf(pcdataXMLEle(Element), "%lf", &CurrentValues.ObservationJulianDate);
126  }
127  else if (strcmp(tagXMLEle(Element), "RightAscension") == 0)
128  {
129  f_scansexa(pcdataXMLEle(Element), &CurrentValues.RightAscension);
130  }
131  else if (strcmp(tagXMLEle(Element), "Declination") == 0)
132  {
133  f_scansexa(pcdataXMLEle(Element), &CurrentValues.Declination);
134  }
135  else if (strcmp(tagXMLEle(Element), "TelescopeDirectionVectorX") == 0)
136  {
137  sscanf(pcdataXMLEle(Element), "%lf", &CurrentValues.TelescopeDirection.x);
138  }
139  else if (strcmp(tagXMLEle(Element), "TelescopeDirectionVectorY") == 0)
140  {
141  sscanf(pcdataXMLEle(Element), "%lf", &CurrentValues.TelescopeDirection.y);
142  }
143  else if (strcmp(tagXMLEle(Element), "TelescopeDirectionVectorZ") == 0)
144  {
145  sscanf(pcdataXMLEle(Element), "%lf", &CurrentValues.TelescopeDirection.z);
146  }
147  else
148  return false;
149  }
150  MySyncPoints.push_back(CurrentValues);
151  }
152 
153  fclose(fp);
154  delXMLEle(FileRoot);
155  delLilXML(Parser);
156 
157  if (nullptr != LoadDatabaseCallback)
158  (*LoadDatabaseCallback)(LoadDatabaseCallbackThisPointer);
159 
160  return true;
161 }
162 
163 bool InMemoryDatabase::SaveDatabase(const char *DeviceName)
164 {
165  char ConfigDir[MAXRBUF];
166  char DatabaseFileName[MAXRBUF];
167  char Errmsg[MAXRBUF];
168  struct stat Status;
169  FILE *fp;
170 
171  snprintf(ConfigDir, MAXRBUF, "%s/.indi/", getenv("HOME"));
172  snprintf(DatabaseFileName, MAXRBUF, "%s%s_alignment_database.xml", ConfigDir, DeviceName);
173 
174  if (stat(ConfigDir, &Status) != 0)
175  {
176  if (mkdir(ConfigDir, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH) < 0)
177  {
178  snprintf(Errmsg, MAXRBUF, "Unable to create config directory. Error %s: %s\n", ConfigDir, strerror(errno));
179  return false;
180  }
181  }
182 
183  fp = fopen(DatabaseFileName, "w");
184  if (fp == nullptr)
185  {
186  snprintf(Errmsg, MAXRBUF, "Unable to open database file. Error opening file %s: %s\n", DatabaseFileName,
187  strerror(errno));
188  return false;
189  }
190 
191  fprintf(fp, "<INDIAlignmentDatabase>\n");
192 
193  if (DatabaseReferencePositionIsValid)
194  fprintf(fp, " <DatabaseReferenceLocation latitude='%lf' longitude='%lf'/>\n", DatabaseReferencePosition.latitude,
195  DatabaseReferencePosition.longitude);
196 
197  fprintf(fp, " <DatabaseEntries>\n");
198  for (AlignmentDatabaseType::const_iterator Itr = MySyncPoints.begin(); Itr != MySyncPoints.end(); Itr++)
199  {
200  char SexaString[12]; // Long enough to hold xx:xx:xx.xx
201  fprintf(fp, " <DatabaseEntry>\n");
202 
203  fprintf(fp, " <ObservationJulianDate>%lf</ObservationJulianDate>\n", (*Itr).ObservationJulianDate);
204  fs_sexa(SexaString, (*Itr).RightAscension, 2, 3600);
205  fprintf(fp, " <RightAscension>%s</RightAscension>\n", SexaString);
206  fs_sexa(SexaString, (*Itr).Declination, 2, 3600);
207  fprintf(fp, " <Declination>%s</Declination>\n", SexaString);
208  fprintf(fp, " <TelescopeDirectionVectorX>%lf</TelescopeDirectionVectorX>\n",
209  (*Itr).TelescopeDirection.x);
210  fprintf(fp, " <TelescopeDirectionVectorY>%lf</TelescopeDirectionVectorY>\n",
211  (*Itr).TelescopeDirection.y);
212  fprintf(fp, " <TelescopeDirectionVectorZ>%lf</TelescopeDirectionVectorZ>\n",
213  (*Itr).TelescopeDirection.z);
214 
215  fprintf(fp, " </DatabaseEntry>\n");
216  }
217  fprintf(fp, " </DatabaseEntries>\n");
218 
219  fprintf(fp, "</INDIAlignmentDatabase>\n");
220 
221  fclose(fp);
222 
223  return true;
224 }
225 
226 void InMemoryDatabase::SetDatabaseReferencePosition(double Latitude, double Longitude)
227 {
228  DatabaseReferencePosition.latitude = Latitude;
229  DatabaseReferencePosition.longitude = Longitude;
230  DatabaseReferencePositionIsValid = true;
231 }
232 
233 void InMemoryDatabase::SetLoadDatabaseCallback(LoadDatabaseCallbackPointer_t CallbackPointer, void *ThisPointer)
234 {
235  LoadDatabaseCallback = CallbackPointer;
236  LoadDatabaseCallbackThisPointer = ThisPointer;
237 }
238 
239 } // namespace AlignmentSubsystem
240 } // namespace INDI
INDI::AlignmentSubsystem::InMemoryDatabase::LoadDatabase
bool LoadDatabase(const char *DeviceName)
Load the database from persistent storage.
Definition: InMemoryDatabase.cpp:54
INDI::AlignmentSubsystem::AlignmentDatabaseEntry::TelescopeDirection
TelescopeDirectionVector TelescopeDirection
Normalised vector giving telescope pointing direction. This is referred to elsewhere as the "apparent...
Definition: Common.h:191
newLilXML
LilXML * newLilXML()
Create a new lilxml parser.
Definition: lilxml.c:148
INDI::AlignmentSubsystem::InMemoryDatabase::GetDatabaseReferencePosition
bool GetDatabaseReferencePosition(IGeographicCoordinates &Position)
Get the database reference position.
Definition: InMemoryDatabase.cpp:43
basedevice.h
InMemoryDatabase.h
INDI::AlignmentSubsystem::AlignmentDatabaseEntry
Entry in the in memory alignment database.
Definition: Common.h:145
pcdataXMLEle
char * pcdataXMLEle(XMLEle *ep)
Return the pcdata of an XML element.
Definition: lilxml.c:575
indicom.h
Implementations for common driver routines.
nextXMLEle
XMLEle * nextXMLEle(XMLEle *ep, int init)
Iterate an XML element for a list of nesetd XML elements.
Definition: lilxml.c:524
INDI::AlignmentSubsystem::InMemoryDatabase::CheckForDuplicateSyncPoint
bool CheckForDuplicateSyncPoint(const AlignmentDatabaseEntry &CandidateEntry, double Tolerance=0.1) const
Check if a entry already exists in the database.
Definition: InMemoryDatabase.cpp:28
f_scansexa
int f_scansexa(const char *str0, double *dp)
convert sexagesimal string str AxBxC to double.
Definition: indicom.c:201
INDI::AlignmentSubsystem::InMemoryDatabase::SaveDatabase
bool SaveDatabase(const char *DeviceName)
Save the database to persistent storage.
Definition: InMemoryDatabase.cpp:163
INDI::AlignmentSubsystem::InMemoryDatabase::SetLoadDatabaseCallback
void SetLoadDatabaseCallback(LoadDatabaseCallbackPointer_t CallbackPointer, void *ThisPointer)
Set the function to be called when the database is loaded or reloaded.
Definition: InMemoryDatabase.cpp:233
MAXRBUF
#define MAXRBUF
Definition: indidriver.c:52
delLilXML
void delLilXML(LilXML *lp)
Delete a lilxml parser.
Definition: lilxml.c:157
INDI::IGeographicCoordinates::longitude
double longitude
Definition: libastro.h:66
INDI::IGeographicCoordinates::latitude
double latitude
Definition: libastro.h:67
xml_att_
Definition: lilxml.c:120
INDI::AlignmentSubsystem::TelescopeDirectionVector::z
double z
Definition: Common.h:78
readXMLFile
XMLEle * readXMLFile(FILE *fp, LilXML *lp, char ynot[])
Handy wrapper to read one xml file.
Definition: lilxml.c:622
tagXMLEle
char * tagXMLEle(XMLEle *ep)
Return the tag of an XML element.
Definition: lilxml.c:569
xml_ele_
Definition: lilxml.c:105
INDI::IGeographicCoordinates
Definition: libastro.h:64
INDI::AlignmentSubsystem::TelescopeDirectionVector::y
double y
Definition: Common.h:77
valuXMLAtt
char * valuXMLAtt(XMLAtt *ap)
Return the value of an XML attribute.
Definition: lilxml.c:593
findXMLEle
XMLEle * findXMLEle(XMLEle *ep, const char *tag)
Find an XML element within an XML element.
Definition: lilxml.c:506
INDI
Namespace to encapsulate INDI client, drivers, and mediator classes.
Definition: AlignmentSubsystemForClients.cpp:11
INDI::AlignmentSubsystem::AlignmentDatabaseEntry::Declination
double Declination
Declination in decimal degrees.
Definition: Common.h:187
fs_sexa
int fs_sexa(char *out, double a, int w, int fracbase)
Converts a sexagesimal number to a string.
Definition: indicom.c:137
LilXML_
Definition: lilxml.c:91
INDI::AlignmentSubsystem::AlignmentDatabaseEntry::RightAscension
double RightAscension
Right ascension in decimal hours. N.B. libnova works in decimal degrees so conversion is always neede...
Definition: Common.h:184
INDI::AlignmentSubsystem::InMemoryDatabase::InMemoryDatabase
InMemoryDatabase()
Default constructor.
Definition: InMemoryDatabase.cpp:23
delXMLEle
void delXMLEle(XMLEle *ep)
delXMLEle Delete XML element.
Definition: lilxml.c:165
INDI::AlignmentSubsystem::AlignmentDatabaseEntry::ObservationJulianDate
double ObservationJulianDate
Definition: Common.h:180
errno
int errno
INDI::AlignmentSubsystem::TelescopeDirectionVector::x
double x
Definition: Common.h:76
INDI::AlignmentSubsystem::InMemoryDatabase::SetDatabaseReferencePosition
void SetDatabaseReferencePosition(double Latitude, double Longitude)
Set the database reference position.
Definition: InMemoryDatabase.cpp:226
findXMLAtt
XMLAtt * findXMLAtt(XMLEle *ep, const char *name)
Find an XML attribute within an XML element.
Definition: lilxml.c:493