53 return "INDI Alpaca Server";
61 ServerSettingsTP[0].
fill(
"HOST",
"Host",
"0.0.0.0");
62 ServerSettingsTP[1].
fill(
"PORT",
"Port",
"11111");
66 INDIServerSettingsTP[0].
fill(
"HOST",
"Host",
"localhost");
67 INDIServerSettingsTP[1].
fill(
"PORT",
"Port",
"7624");
76 ConnectionSettingsNP[0].
fill(
"TIMEOUT",
"Timeout (sec)",
"%.0f", 1, 30, 1, 5);
77 ConnectionSettingsNP[1].
fill(
"RETRIES",
"Max Retries",
"%.0f", 1, 10, 1, 3);
78 ConnectionSettingsNP[2].
fill(
"RETRY_DELAY",
"Retry Delay (ms)",
"%.0f", 100, 5000, 100, 1000);
82 DiscoverySettingsNP[0].
fill(
"PORT",
"Discovery Port",
"%.0f", 1, 65535, 1, 32227);
86 StartupDelayNP[0].
fill(
"DELAY",
"Startup Delay (sec)",
"%.0f", 1, 60, 1, 3);
93 m_Client = std::make_shared<AlpacaClient>(m_DeviceManager);
138 ServerSettingsTP.
update(texts, names, n);
140 ServerSettingsTP.
apply();
148 INDIServerSettingsTP.
update(texts, names, n);
150 INDIServerSettingsTP.
apply();
166 ConnectionSettingsNP.
update(values, names, n);
168 ConnectionSettingsNP.
apply();
176 DiscoverySettingsNP.
update(values, names, n);
178 DiscoverySettingsNP.
apply();
181 if (m_Discovery && m_Discovery->isRunning())
183 m_Discovery->setDiscoveryPort(
static_cast<int>(DiscoverySettingsNP[0].getValue()));
184 LOGF_INFO(
"Discovery port updated to %d",
static_cast<int>(DiscoverySettingsNP[0].getValue()));
194 StartupDelayNP.
update(values, names, n);
196 StartupDelayNP.
apply();
197 LOGF_INFO(
"Startup delay updated to %d seconds",
static_cast<int>(StartupDelayNP[0].getValue()));
213 ServerControlSP.
update(states, names, n);
219 if (!m_ServerRunning)
221 if (startAlpacaServer())
233 LOG_ERROR(
"Failed to start Alpaca server");
238 LOG_INFO(
"Alpaca server is already running");
248 if (stopAlpacaServer())
260 LOG_ERROR(
"Failed to stop Alpaca server");
265 LOG_INFO(
"Alpaca server is not running");
273 ServerControlSP.
apply();
285 ServerSettingsTP.
save(fp);
286 INDIServerSettingsTP.
save(fp);
287 ConnectionSettingsNP.
save(fp);
288 DiscoverySettingsNP.
save(fp);
289 StartupDelayNP.
save(fp);
297 int startupDelay =
static_cast<int>(StartupDelayNP[0].getValue());
298 LOGF_INFO(
"Waiting %d seconds before connecting to INDI server...", startupDelay);
304 m_Client->setServer(INDIServerSettingsTP[0].
getText(), std::stoi(INDIServerSettingsTP[1].
getText()));
306 if (m_Client->connectServer())
308 LOG_INFO(
"Connected to INDI server");
311 if (!m_ServerRunning)
313 if (startAlpacaServer())
315 ServerControlSP[0].setState(ISS_ON);
316 ServerControlSP[1].setState(ISS_OFF);
317 ServerControlSP.setState(IPS_OK);
318 ServerControlSP.apply();
319 LOG_INFO(
"Alpaca server started automatically");
323 LOG_ERROR(
"Failed to start Alpaca server automatically");
333 LOG_ERROR(
"Failed to connect to INDI server");
349 if (m_Client->disconnectServer())
351 LOG_INFO(
"Disconnected from INDI server");
356 LOG_ERROR(
"Failed to disconnect from INDI server");
367bool INDIAlpacaServer::startAlpacaServer()
371 LOG_INFO(
"Alpaca server is already running");
376 m_Server = std::make_unique<httplib::Server>();
379 int discoveryPort =
static_cast<int>(DiscoverySettingsNP[0].getValue());
380 int alpacaPort = std::stoi(ServerSettingsTP[1].
getText());
381 m_Discovery = std::make_unique<AlpacaDiscovery>(discoveryPort, alpacaPort);
406 m_ServerThread = std::thread(&INDIAlpacaServer::serverThreadFunc,
this);
409 std::this_thread::sleep_for(std::chrono::milliseconds(100));
412 if (!m_Discovery->start())
414 LOG_ERROR(
"Failed to start Alpaca discovery server");
419 LOGF_INFO(
"Alpaca discovery server started on port %d", discoveryPort);
422 m_ServerRunning =
true;
426bool INDIAlpacaServer::stopAlpacaServer()
428 if (!m_ServerRunning)
430 LOG_INFO(
"Alpaca server is not running");
437 if (m_Discovery->isRunning())
439 if (!m_Discovery->stop())
441 LOG_ERROR(
"Failed to stop Alpaca discovery server");
446 LOG_INFO(
"Alpaca discovery server stopped");
458 if (m_ServerThread.joinable())
459 m_ServerThread.join();
464 m_ServerRunning =
false;
468void INDIAlpacaServer::serverThreadFunc()
470 LOG_INFO(
"Starting Alpaca server thread");
473 std::string host = ServerSettingsTP[0].
getText();
474 int port = std::stoi(ServerSettingsTP[1].
getText());
476 LOGF_INFO(
"Alpaca server listening on %s:%d", host.c_str(), port);
479 m_Server->listen(host.c_str(), port);
481 LOG_INFO(
"Alpaca server thread stopped");
void handleAlpacaRequest(const httplib::Request &req, httplib::Response &res)
void handleSetupRequest(const httplib::Request &req, httplib::Response &res)
static DeviceManager * getInstance()
void setAlpacaClient(const std::shared_ptr< AlpacaClient > &client)
virtual bool ISNewSwitch(const char *dev, const char *name, ISState *states, char *names[], int n) override
Process the client newSwitch command.
bool Connect() override
Connect to the device. INDI::DefaultDevice implementation connects to appropriate connection interfac...
bool Disconnect() override
Disconnect from device.
virtual bool initProperties() override
Initialize properties initial state and value. The child class must implement this function.
virtual bool ISNewNumber(const char *dev, const char *name, double values[], char *names[], int n) override
Process the client newNumber command.
virtual ~INDIAlpacaServer()
void TimerHit() override
Callback function to be called once SetTimer duration elapses.
bool updateProperties() override
updateProperties is called whenever there is a change in the CONNECTION status of the driver....
virtual bool saveConfigItems(FILE *fp) override
saveConfigItems Save specific properties in the provide config file handler. Child class usually over...
virtual bool ISNewText(const char *dev, const char *name, char *texts[], char *names[], int n) override
Process the client newSwitch command.
void ISGetProperties(const char *dev) override
define the driver's properties to the client. Usually, only a minimum set of properties are defined t...
const char * getDefaultName() override
const char * getDeviceName() const
INDI::PropertyText getText(const char *name) const
virtual bool updateProperties()
updateProperties is called whenever there is a change in the CONNECTION status of the driver....
virtual bool saveConfig(bool silent=false, const char *property=nullptr)
Save the current properties in a configuration file.
virtual bool ISNewSwitch(const char *dev, const char *name, ISState *states, char *names[], int n)
Process the client newSwitch command.
virtual void ISGetProperties(const char *dev)
define the driver's properties to the client. Usually, only a minimum set of properties are defined t...
virtual void setConnected(bool status, IPState state=IPS_OK, const char *msg=nullptr)
Set connection switch status in the client.
void setVersion(uint16_t vMajor, uint16_t vMinor)
Set driver version information to be defined in DRIVER_INFO property as vMajor.vMinor.
void defineProperty(INumberVectorProperty *property)
virtual bool saveConfigItems(FILE *fp)
saveConfigItems Save specific properties in the provide config file handler. Child class usually over...
uint32_t getCurrentPollingPeriod() const
getCurrentPollingPeriod Return the current polling period.
virtual bool initProperties()
Initialize properties initial state and value. The child class must implement this function.
void addAuxControls()
Add Debug, Simulation, and Configuration options to the driver.
virtual bool ISNewNumber(const char *dev, const char *name, double values[], char *names[], int n)
Process the client newNumber command.
int SetTimer(uint32_t ms)
Set a timer to call the function TimerHit after ms milliseconds.
virtual bool ISNewText(const char *dev, const char *name, char *texts[], char *names[], int n)
Process the client newSwitch command.
void setState(IPState state)
void apply(const char *format,...) const ATTRIBUTE_FORMAT_PRINTF(2
void save(FILE *f) const
save Save property to configuration file.
const char * getName() const
bool isNameMatch(const char *otherName) const
bool update(const double values[], const char *const names[], int n)
void fill(const char *device, const char *name, const char *label, const char *group, IPerm permission, double timeout, IPState state)
bool update(const ISState states[], const char *const names[], int n)
int findOnSwitchIndex() const
void fill(const char *device, const char *name, const char *label, const char *group, IPerm permission, ISRule rule, double timeout, IPState state)
bool update(const char *const texts[], const char *const names[], int n)
void fill(const char *device, const char *name, const char *label, const char *group, IPerm permission, double timeout, IPState state)
INDI::PropertyViewText * getText() const
static void singleShot(int msec, const std::function< void()> &callback)
This static function calls a the given function after a given time interval.
const char * CONNECTION_TAB
CONNECTION_TAB Where all device connection settings (serial, usb, ethernet) are defined and controlle...
const char * MAIN_CONTROL_TAB
MAIN_CONTROL_TAB Where all the primary controls for the device are located.
const char * OPTIONS_TAB
OPTIONS_TAB Where all the driver's options are located. Those may include auxiliary controls,...
std::unique_ptr< INDIAlpacaServer > indiAlpacaServer(new INDIAlpacaServer())
#define LOGF_INFO(fmt,...)
#define LOG_ERROR(txt)
Shorter logging macros. In order to use these macros, the function (or method) "getDeviceName()" must...