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