×

INDI Library v2.0.6 is Released (02 Feb 2024)

Bi-monthly release with minor bug fixes and improvements

Getting all the Telescopes and Cameras

  • Posts: 74
  • Thank you received: 5
This seems like a really basic question, but it has me stumped.

In my BaseClient subclass, I'm trying to get a list of all the Telescopes and Cameras registered with the server. If I have this code:
void IndiClient::newDevice(INDI::BaseDevice baseDevice)
{
    auto interface = baseDevice->getDriverInterface();
    if (interface == INDI::BaseDevice::TELESCOPE_INTERFACE)
    {
        IDLog("New Device: %s\n", baseDevice->getDeviceName());
    }
}


The interface always comes back as 0 (GENERAL_INTERFACE). I never get anything specific.

I've also tried using getDevices() after receiving the serverConnected() notification:
void IndiClient::serverConnected()
{
    IDLog("Server Connected\n\n");    
 
    IDLog("Listing mounts:\n");
    std::vector<INDI::BaseDevice> mounts;
    getDevices(mounts, INDI::BaseDevice::TELESCOPE_INTERFACE);
    for (INDI::BaseDevice *device : mounts)
        printf("Mount Name: %s\n", device->getDeviceName());
 
    IDLog("Listing cameras:\n");
    std::vector<INDI::BaseDevice> cameras;
    getDevices(cameras, INDI::BaseDevice::CCD_INTERFACE);
    for (INDI::BaseDevice *device : cameras)
        printf("Camera Name: %s\n", device->getDeviceName());
}

This doesn't return any mounts or cameras. However, if I wait a second of so after connecting and make the getDevices() calls, then it works. But it is unclear how long I need to wait for the info be be valid.

How am I supposed to accomplish what I need?
Last edit: 1 year 3 months ago by Bill Tschumy.
1 year 3 months ago #88911

Please Log in or Create an account to join the conversation.

  • Posts: 74
  • Thank you received: 5
I edited my text to fix a typo, and when I submitted it again it lost the <code></code> formatting. Seems like a bug in the message board system.

Ah, figured it out. Editing the message changed [code] to <code> which is not right. I fixed it.
Last edit: 1 year 3 months ago by Bill Tschumy.
1 year 3 months ago #88912

Please Log in or Create an account to join the conversation.

  • Posts: 74
  • Thank you received: 5
Still hoping to get a reply to this question. This seems really basic to writing an INDI client. The BaseDevices returned in newDevice() or getDevices()don't seem to be fully populated until some unspecified time later.

Is this supposed to work? Am I just using this wrong? Is there a bug in the INDI client library?

Another possible hint is when I call:
auto interface = baseDevice->getDriverInterface();
I get:
No IText 'DRIVER_INTERFACE' in .

Thanks,
Bill
Last edit: 1 year 3 months ago by Bill Tschumy.
1 year 3 months ago #88964

Please Log in or Create an account to join the conversation.

  • Posts: 74
  • Thank you received: 5
OK, I *think* I have figured this out. It looks like the driver information for a device, in particular device.getDriverInterface(), is not valid until you have received a newProperty() notification for the property "DRIVER_INFO".

If in the body of that notification you ask for getDriverInterface(), you get back valid information and can determine what class of device this is.

It seems to me that the documentation should note that the various queries about the driver are invalid until this newProperty notification has happened.
1 year 3 months ago #89042

Please Log in or Create an account to join the conversation.

  • Posts: 3
  • Thank you received: 0
Hello Bill, Could you mind giving me a valid demo about how to list all devices in indi client, I am also meeting these problems.
10 months 2 weeks ago #92798

Please Log in or Create an account to join the conversation.

  • Posts: 74
  • Thank you received: 5
Alan,

Unfortunately, I stopped work on that project before I got it fully fleshed out. I do have the code related to what you are asking (I think).

Here are the callbacks from INDI and what I did. Hope this helps even though it is not in a final form:
// ************************************************************************
// The following methods are called by the server as various states change.
// ************************************************************************
 
void IndiClient::newDevice(INDI::BaseDevice baseDevice)
{        
    //IDLog("New Device: %s\n", baseDevice.getDeviceName());
}
 
void IndiClient::removeDevice(INDI::BaseDevice baseDevice)
{
    IDLog("Remove Device: %s\n", baseDevice.getDeviceName());
 
    string removedDeviceName = baseDevice.getDeviceName();
    if (baseDevice.getDriverInterface() & BaseDevice::TELESCOPE_INTERFACE)
    {
        auto &mountNames = pNanoverse->_indiMountNames;
        for (int i = 0; i < mountNames.size(); i++)
        {
            if (removedDeviceName == mountNames[i])
            {
                mountNames.erase(mountNames.begin() + i);
            }
        }
        IDLog("\n");
    }
    else if (baseDevice.getDriverInterface() & BaseDevice::CCD_INTERFACE)
    {
        auto &cameraNames = pNanoverse->_indiCameraNames;
        for (int i = 0; i < cameraNames.size(); i++)
        {
            if (removedDeviceName == cameraNames[i])
            {
                cameraNames.erase(cameraNames.begin() + i);
            }
        }
    }
}
 
 
void IndiClient::newProperty(INDI::Property property)
{
    IDLog("New Property: %s\n", property.getName());
    auto baseDevice = property.getBaseDevice();
    auto deviceName = baseDevice.getDeviceName();
 
    if (property.isNameMatch("DRIVER_INFO"))
    {
        auto interface = baseDevice.getDriverInterface();
        if (interface & BaseDevice::TELESCOPE_INTERFACE)
        {
            IDLog("Found telescope: %s\n", deviceName);
            pNanoverse->_indiMountNames.push_back(deviceName);                
        }
        else if (interface & BaseDevice::CCD_INTERFACE)
        {
            IDLog("Found camera: %s\n", deviceName);
            pNanoverse->_indiCameraNames.push_back(deviceName);                
            setBLOBMode(B_ALSO, deviceName, nullptr);
            enableDirectBlobAccess(deviceName, nullptr);
        }
    }
 
    // Handle Telescope properties
    if (baseDevice.getDriverInterface() & BaseDevice::TELESCOPE_INTERFACE)
    {
        if (property.isNameMatch("SYSTEM_PORTS"))
        {
            IDLog("Found system ports for %s\n", deviceName);
            INDI::PropertyView<ISwitch> systemPorts = *(baseDevice.getSwitch("SYSTEM_PORTS"));
            vector<string> ports;
            for (auto &port : systemPorts)
            {
                ports.push_back(port.name);
            }
            pNanoverse->_indiSerialPortsMap.insert({deviceName, ports});
        }
 
        else if (property.isNameMatch("DEVICE_PORT"))
        {
            string portName = baseDevice.getText("DEVICE_PORT").at(0)->getText();
            pNanoverse->_indiCurrentSerialPortsMap.insert({deviceName, portName});
        }
    }
}
 
 
void IndiClient::updateProperty(INDI::Property property)
{
    if (property.isNameMatch("MOUNT_AXES"))
    {
        return;
    }
 
    //IDLog("Update Property: %s\n", property.getName());
    auto device = property.getBaseDevice();
    if (device.isDeviceNameMatch(pNanoverse->_indiCurrentMountName.c_str()) && property.isNameMatch("EQUATORIAL_EOD_COORD"))
    {
        double raInHours = IUFindNumber(property, "RA")->value;
        double decInDegrees = IUFindNumber(property, "DEC")->value;
        IDLog("Updated Coords.  ra = %f; dec = %f\n", raInHours, decInDegrees);
        setScopeRA(SSAngle::fromHours(raInHours));
        setScopeDec(SSAngle::fromDegrees(decInDegrees));
    }
}
 
 
void IndiClient::removeProperty(INDI::Property property)
{
    //IDLog("Remove Property: %s\n", property.getName());
}
 
 
void IndiClient::newMessage(INDI::BaseDevice baseDevice, int messageID)
{
    //IDLog("Receiving message from Server:\n    %s\n\n", baseDevice.messageQueue(messageID).c_str());
}
 
 
void IndiClient::serverConnected()
{
    IDLog("Server Connected\n\n");            
}
 
 
void IndiClient::serverDisconnected(int exit_code)
{
    IDLog("Server Disconnected with code: %d", exit_code);    
    resetMountNames();
}
 
The following user(s) said Thank You: Alan Lee
10 months 2 weeks ago #92801

Please Log in or Create an account to join the conversation.

Sorry I was traveling and just saw this. But you already figured it out. Basically DRIVER_INFO contains information about the driver interfaces. This is usually the most reliable way to identify the device types/subtypes are reported by INDI.
The following user(s) said Thank You: Alan Lee
10 months 2 weeks ago #92816

Please Log in or Create an account to join the conversation.

  • Posts: 3
  • Thank you received: 0
I wrote python and c++ demo to control my camera to exposure 1 second, and the python version worked but c++ verison didn't.
Here are my codes. And the C++ running error is in below.It means the error is in "indiclient.sendNewNumber(ccd_exposure);"
import PyIndi
import time
 
class IndiClient(PyIndi.BaseClient):
    def __init__(self):
        super(IndiClient, self).__init__()
    def newDevice(self, d):
        pass
    def newBLOB(self, bp):
        pass
    def newSwitch(self, svp):
        pass
    def newNumber(self, nvp):
        pass
    def newMessage(self, d, m):
        pass
    def serverConnected(self):
        pass
    def serverDisconnected(self, code):
        pass
    def newProperty(self,property):
        baseDevice = property.getBaseDevice()
        deviceName = baseDevice.getDeviceName()
        if(property.getName()=="DRIVER_INFO"):
            interface = baseDevice.getDriverInterface()
            if(interface & PyIndi.BaseDevice.CCD_INTERFACE):
                print("Found camera:" + deviceName)
 
# connect the server
indiclient=IndiClient()
indiclient.setServer("localhost",7624)
 
indiclient.connectServer()
 
# Let's take some pictures
ccd="Nikon DSLR DSC D5100 (PTP mode)"
device_ccd=indiclient.getDevice(ccd)
 
while not(device_ccd):
    time.sleep(0.5)
    device_ccd=indiclient.getDevice(ccd)
 
ccd_connect=device_ccd.getSwitch("CONNECTION")
while not(ccd_connect):
    time.sleep(0.5)
    ccd_connect=device_ccd.getSwitch("CONNECTION")
if not(device_ccd.isConnected()):
    ccd_connect[0].s=PyIndi.ISS_ON # the "CONNECT" switch
    ccd_connect[1].s=PyIndi.ISS_OFF # the "DISCONNECT" switch
    indiclient.sendNewSwitch(ccd_connect)
 
 
ccd_exposure=device_ccd.getNumber("CCD_EXPOSURE")
# while not(ccd_exposure):
#     time.sleep(0.5)
#     ccd_exposure=device_ccd.getNumber("CCD_EXPOSURE")
 
# we should inform the indi server that we want to receive the
# "CCD1" blob from this device
 
indiclient.setBLOBMode(PyIndi.B_ALSO, ccd, "CCD1")
 
ccd_ccd1=device_ccd.getBLOB("CCD1")
# while not(ccd_ccd1):
#     time.sleep(0.5)
#     ccd_ccd1=device_ccd.getBLOB("CCD1")
 
 
ccd_exposure[0].value=1.0
indiclient.sendNewNumber(ccd_exposure)
 
 
ccd_dis_connect=device_ccd.getSwitch("DISCONNECTION")
while not(ccd_dis_connect):
    time.sleep(0.5)
    ccd_dis_connect=device_ccd.getSwitch("DISCONNECTION")
    print("try disconnect")
 
print("disconnect!")

nikon_client.cpp
#include "nikon_client.h"
 
#include <basedevice.h>
 
#include <unistd.h> // sleep lib
 
#include <string>
#include <fstream>
#include <iostream>
#include <memory>
 
 
int main(int, char *[])
{
    IndiClient indiclient;
    indiclient.setServer("localhost", 7624);
 
    indiclient.connectServer();
 
    char ccd[]="Nikon DSLR DSC D5100 (PTP mode)";
 
    INDI::BaseDevice device_ccd = indiclient.getDevice(ccd);
    while(!device_ccd){
        sleep(0.5);
        device_ccd=indiclient.getDevice(ccd);
 
    }
 
    INDI::PropertySwitch ccd_connect=device_ccd.getSwitch("CONNECTION");
    while(!ccd_connect){
        sleep(0.5);
        ccd_connect=device_ccd.getSwitch("CONNECTION");
    }
    if(!device_ccd.isConnected()){
        ccd_connect[0].s=ISS_ON;
        ccd_connect[1].s=ISS_OFF;
        indiclient.sendNewSwitch(ccd_connect);
    }
    INDI::PropertyNumber ccd_exposure=device_ccd.getNumber("CCD_EXPOSURE");
    indiclient.setBLOBMode(B_ALSO,ccd,"CCD1");
    INDI::PropertyBlob ccd_ccd1=device_ccd.getBLOB("CCD1");
    while(!ccd_ccd1){
        sleep(0.5);
        ccd_ccd1=device_ccd.getBLOB("CCD1");
    }
 
    ccd_exposure[0].value=1.0;
    std::cout << "777.\n";
    indiclient.sendNewNumber(ccd_exposure);
    std::cout << "888.\n";
    INDI::PropertySwitch ccd_dis_connect=device_ccd.getSwitch("DISCONNECTION");
    while(!ccd_dis_connect){
        sleep(0.5);
        ccd_dis_connect=device_ccd.getSwitch("DISCONNECTION");
        std::cout << "Try disconnect.\n";
    }
 
    std::cout << "Press Enter key to terminate the client.\n";
    std::cin.ignore();
}
 
IndiClient::IndiClient():BaseClient()
{
 
}
 
void IndiClient::newDevice(INDI::BaseDevice baseDevice)
{
    return;
}
void IndiClient::newBLOB(IBLOB *bp)
{
    return;
}
void IndiClient::newSwitch(ISwitchVectorProperty *svp)
{
    return;
}
void IndiClient::newNumber(INumberVectorProperty *nvp)
{
    return;
}
void IndiClient::newMessage(INDI::BaseDevice *dp, int messageID)
{
    return;
}
void IndiClient::serverConnected()
{
    return;
}
void IndiClient::serverDisconnected(int exit_code)
{
    return;
}
 
void IndiClient::newProperty(INDI::Property property)
{   
    auto baseDevice = property.getBaseDevice();
    auto deviceName = baseDevice.getDeviceName();
 
    // With DRIVER_INFO defined, we have access to getDriverInterface()
    if (property.isNameMatch("DRIVER_INFO"))
    {
        auto interface = baseDevice.getDriverInterface();
 
        if(interface & INDI::BaseDevice::CCD_INTERFACE)
        {
            IDLog("Found camera: %s\n", deviceName);            
        }
    }
}

nikon_client.h
#include "baseclient.h"
#include <basedevice.h>
 
class IndiClient : public INDI::BaseClient
{
    public:
        IndiClient();
        ~IndiClient() = default;
    public:
        void newDevice(INDI::BaseDevice baseDevice);
        void newBLOB(IBLOB *bp);
        void newSwitch(ISwitchVectorProperty *svp);
        void newNumber(INumberVectorProperty *nvp); 
        void newMessage(INDI::BaseDevice *dp, int messageID); 
        void serverConnected();
        void serverDisconnected(int exit_code);
        void newProperty(INDI::Property property);
};
10 months 1 week ago #92946

Please Log in or Create an account to join the conversation.

  • Posts: 3
  • Thank you received: 0
There is the c++ demo running error:

INDI::BaseClient::connectServer: creating new connection...
Found camera: Nikon DSLR DSC D5100 (PTP mode)
777.
Segmentation fault
10 months 1 week ago #92947

Please Log in or Create an account to join the conversation.

Can you debug it and post the backtrace?
10 months 5 days ago #93000

Please Log in or Create an account to join the conversation.

Time to create page: 1.122 seconds