Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

INDI build on Windows #1921

Closed
AstroAir opened this issue Aug 12, 2023 · 13 comments
Closed

INDI build on Windows #1921

AstroAir opened this issue Aug 12, 2023 · 13 comments

Comments

@AstroAir
Copy link
Contributor

Recently, due to writing an astronomical software, I have already written the client for INDI, but when I tried to write it on Windows, the construction of INDI was completely unsuccessful. Because at the time of design, it seems that INDI did not consider its use on Windows at all. I compiled using Mingw64 (Msys2), but still cannot pass. Most of the problems are focused on using network communication libraries unique to Linux, such as sys/socket. h. Currently, I have started migrating under Windows, but under Mingw64, there is a method of building

Install Msys2

Download https://github.com/msys2/msys2-installer/releases/download/2023-07-18/msys2-x86_64-20230718.exe

pacman -Syu # Update all of the packages
pacman -S mingw-w64-x86_64-toolchain # Install g++ toolchain
pacman -S mingw-w64-x86_64-cmake # Install Cmake

Install dependencies

If there is anything missing, you can use a search engine to search for the name of the Msys2+package (usually between lib and - dev)

pacman -S mingw-w64-x86_64-zlib
pacman -S mingw-w64-x86_64-cfitsio
pacman -S mingw-w64-x86_64-libnova
pacman -S mingw-w64-x86_64-libusb
pacman -S mingw-w64-x86_64-fftw
pacman -S mingw-w64-x86_64-libxisf
pacman -S mingw-w64-x86_64-rtl-sdr

Install libev-dev

This is what Indiserver relies on, and other components do not seem to need it

Download sources from http://dist.schmorp.de/libev/Attic/

pacman -S autoconf
pacman -S automake
pacman -S libtool
pacman -S make
sh autogen.sh
./configure
make
make -j4
make install

Build the project

After installing all of the dependencies , we can try to build the sources manually

cmake ..
cmake --build . -jn # or make -jn

But by default, only INDIClient will be built, so we need to modify CMakeLists.txt first

if(INDI_BUILD_DRIVERS)
    if(WIN32 OR ANDROID) # Remove WIN32 then allow the cmake to build the whole project
        message(WARNING "INDI drivers are only supported under Linux, BSD, MacOS, and Cygwin while current system is " ${CMAKE_SYSTEM_NAME})
    else(WIN32 OR ANDROID)
    ...
endif()

then retry building commands.

like tools/setINDIProperty.cpp can be written as following

/* connect to an INDI server and set one or more device.property.element.
 */

#define _GNU_SOURCE // needed for fdopen

#include "indiapi.h"
#include "indidevapi.h"
#include "lilxml.h"

#include <errno.h>
#include <math.h>
#ifdef _WIN32
#include <winsock2.h>
#include <ws2tcpip.h>
#else
#include <netdb.h>
#include <netinet/in.h>
#include <sys/socket.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <time.h>
#include <unistd.h>
#include <sys/types.h>

/* table of INDI definition elements we can set
 * N.B. do not change defs[] order, they are indexed via -x/-n/-s args
 */
typedef struct
{
    char *defType; /* defXXXVector name */
    char *defOne;  /* defXXX name */
    char *newType; /* newXXXVector name */
    char *oneType; /* oneXXX name */
} INDIDef;
static INDIDef defs[] = {
    { "defTextVector", "defText", "newTextVector", "oneText" },
    { "defNumberVector", "defNumber", "newNumberVector", "oneNumber" },
    { "defSwitchVector", "defSwitch", "newSwitchVector", "oneSwitch" },
};
#define NDEFS (sizeof(defs) / sizeof(defs[0]))

#define INDIPORT 7624                 /* default port */
static char host_def[] = "localhost"; /* default host name */

static char *me;              /* our name for usage message */
static char *host = host_def; /* working host name */
static int port   = INDIPORT; /* working port number */
static int verbose;           /* report extra info */
static int directfd = -1;     /* direct filedes to server, if >= 0 */
#define TIMEOUT 2             /* default timeout, secs */
static int timeout = TIMEOUT; /* working timeout, secs */
static LilXML *lillp;         /* XML parser context */

typedef struct
{
    char *e, *v; /* element name and value */
    int ok;      /* set when found */
} SetEV;

typedef struct
{
    char *d;     /* device */
    char *p;     /* property */
    SetEV *ev;   /* elements */
    int nev;     /* n elements */
    INDIDef *dp; /* one of defs if known, else NULL */
} SetSpec;

static SetSpec *sets; /* set of properties to set */
static int nsets;

static void usage(void);
static int crackSpec(int *acp, char **avp[]);
static void openINDIServer(FILE **rfpp, FILE **wfpp);
static void listenINDI(FILE *rfp, FILE *wfp);
static int finished(void);
static void onAlarm(int dummy);
static int readServerChar(FILE *fp);
static void findSet(XMLEle *root, FILE *fp);
static void scanEV(SetSpec *specp, char ev[]);
static void scanEEVV(SetSpec *specp, char *ep, char ev[]);
static void scanEVEV(SetSpec *specp, char ev[]);
static void sendNew(FILE *fp, INDIDef *dp, SetSpec *sp);
static void sendSpecs(FILE *wfp);

int main(int ac, char *av[])
{
    FILE *rfp, *wfp;
    int stop = 0;
    int allspeced;

    /* save our name */
    me = av[0];

    /* crack args */
    while (!stop && --ac && **++av == '-')
    {
        char *s = *av;
        while (*++s)
        {
            switch (*s)
            {
                case 'd':
                    if (ac < 2)
                    {
                        fprintf(stderr, "-d requires open fileno\n");
                        usage();
                    }
                    directfd = atoi(*++av);
                    ac--;
                    break;

                case 'h':
                    if (directfd >= 0)
                    {
                        fprintf(stderr, "Can not combine -d and -h\n");
                        usage();
                    }
                    if (ac < 2)
                    {
                        fprintf(stderr, "-h requires host name\n");
                        usage();
                    }
                    host = *++av;
                    ac--;
                    break;

                case 'p':
                    if (directfd >= 0)
                    {
                        fprintf(stderr, "Can not combine -d and -p\n");
                        usage();
                    }
                    if (ac < 2)
                    {
                        fprintf(stderr, "-p requires tcp port number\n");
                        usage();
                    }
                    port = atoi(*++av);
                    ac--;
                    break;

                case 't':
                    if (ac < 2)
                    {
                        fprintf(stderr, "-t requires timeout\n");
                        usage();
                    }
                    timeout = atoi(*++av);
                    ac--;
                    break;

                case 'v': /* verbose */
                    verbose++;
                    break;

                case 'x': /* FALLTHRU */
                case 'n': /* FALLTHRU */
                case 's':
                    /* stop if see one of the property types */
                    stop = 1;
                    break;

                default:
                    fprintf(stderr, "Unknown flag: %c\n", *s);
                    usage();
            }
        }
    }

    /* now ac args starting at av[0] */
    if (ac < 1)
        usage();

    /* crack each property, add to sets[]  */
    allspeced = 1;
    do
    {
        if (!crackSpec(&ac, &av))
            allspeced = 0;
    } while (ac > 0);

    /* open connection */
    if (directfd >= 0)
    {
        wfp = fdopen(directfd, "w");
        rfp = fdopen(directfd, "r");
        setbuf(rfp, NULL); /* don't absorb next guy's stuff */
        if (!rfp || !wfp)
        {
            fprintf(stderr, "Direct fd %d: %s\n", directfd, strerror(errno));
            exit(1);
        }
        if (verbose)
            fprintf(stderr, "Using direct fd %d\n", directfd);
    }
    else
    {
        openINDIServer(&rfp, &wfp);
        if (verbose)
            fprintf(stderr, "Connected to %s on port %d\n", host, port);
    }

    /* build a parser context for cracking XML responses */
    lillp = newLilXML();

    /* just send it all speced, else check with server */
    if (allspeced)
    {
        sendSpecs(wfp);
    }
    else
    {
        /* issue getProperties */
        if (verbose)
            fprintf(stderr, "Querying for properties\n");
        fprintf(wfp, "<getProperties version='%g'/>\n", INDIV);
        fflush(wfp);

        /* listen for properties, set when see any we recognize */
        listenINDI(rfp, wfp);
    }

    return (0);
}

static void usage()
{
    fprintf(stderr, "Purpose: set one or more writable INDI properties\n");
    fprintf(stderr, "%s\n", GIT_TAG_STRING);
    fprintf(stderr, "Usage: %s [options] {[type] spec} ...\n", me);
    fprintf(stderr, "Options:\n");
    fprintf(stderr, "  -d f  : use file descriptor f already open to server\n");
    fprintf(stderr, "  -h h  : alternate host, default is %s\n", host_def);
    fprintf(stderr, "  -p p  : alternate port, default is %d\n", INDIPORT);
    fprintf(stderr, "  -t t  : max time to wait, default is %d secs\n", TIMEOUT);
    fprintf(stderr, "  -v    : verbose (more are cumulative)\n");
    fprintf(stderr, "Each spec optionally preceded by its type is sent without first confirming\n");
    fprintf(stderr, "its structure. This is much more efficient but there is no error checking.\n");
    fprintf(stderr, "Types are indicated with the following flags:\n");
    fprintf(stderr, "  -x    : Text\n");
    fprintf(stderr, "  -n    : Number\n");
    fprintf(stderr, "  -s    : Switch\n");
    fprintf(stderr, "Spec may be either:\n");
    fprintf(stderr, "    device.property.e1[;e2...]=v1[;v2...]\n");
    fprintf(stderr, "  or\n");
    fprintf(stderr, "    device.property.e1=v1[;e2=v2...]\n");
    fprintf(stderr, "Exit status:\n");
    fprintf(stderr, "  0: all settings successful\n");
    fprintf(stderr, "  1: at least one setting was invalid\n");
    fprintf(stderr, "  2: real trouble, try repeating with -v\n");

    exit(2);
}

/* crack property set spec, add to sets [], move to next spec.
 * return 1 if see a type
 */
static int crackSpec(int *acp, char **avp[])
{
    char d[128], p[128], ev[2048];
    char *spec  = *avp[0];
    INDIDef *dp = NULL;

    /* check if first arg is type indicator */
    if ((*acp > 0) && (spec[0] == '-'))
    {
        switch (spec[1])
        {
            case 'x':
                dp = &defs[0];
                break;
            case 'n':
                dp = &defs[1];
                break;
            case 's':
                dp = &defs[2];
                break;
            default:
                fprintf(stderr, "Bad property type: %s\n", spec);
                usage();
        }
        (*acp)--;
        (*avp)++;
        spec = *avp[0];
    }
    if (*acp <= 0)
    {
        fprintf(stderr, "Missing spec\n");
        usage();
    }

    /* then scan arg for property spec */
    //if (sscanf(spec, "%[^.].%[^.].%s", d, p, ev) != 3)
    if (sscanf(spec, "%[^.].%[^.].%[^\n]", d, p, ev) != 3)
    {
        fprintf(stderr, "Malformed property spec: %s\n", spec);
        usage();
    }

    /* add to list */
    sets            = (SetSpec *)realloc(sets, (nsets + 1) * sizeof(SetSpec));
    sets[nsets].d   = strdup(d);
    sets[nsets].p   = strdup(p);
    sets[nsets].dp  = dp;
    sets[nsets].ev  = NULL;
    sets[nsets].nev = 0;
    scanEV(&sets[nsets++], ev);

    /* update caller's pointers */
    (*acp)--;
    (*avp)++;

    /* return 1 if saw a spec */
    return (dp ? 1 : 0);
}

/* open a read and write connection to host and port or die.
 * exit if trouble.
 */
static void openINDIServer(FILE **rfpp, FILE **wfpp)
{
    struct sockaddr_in serv_addr;
    struct hostent *hp;
    int sockfd;

    /* lookup host address */
    hp = gethostbyname(host);
    if (!hp)
    {
        perror("gethostbyname");
        exit(2);
    }

    /* create a socket to the INDI server */
    (void)memset((char *)&serv_addr, 0, sizeof(serv_addr));
    serv_addr.sin_family      = AF_INET;
    serv_addr.sin_addr.s_addr = ((struct in_addr *)(hp->h_addr_list[0]))->s_addr;
    serv_addr.sin_port        = htons(port);
    if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
    {
        perror("socket");
        exit(2);
    }

    /* connect */
    if (connect(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0)
    {
        perror("connect");
        exit(2);
    }

    /* prepare for line-oriented i/o to client */
    *rfpp = fdopen(sockfd, "r");
    *wfpp = fdopen(sockfd, "w");
}

#define TIMEOUT_MS 5000

static void CALLBACK onTimer(HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime)
{
    printf("Timer expired!\n");
    exit(0);
}

/* listen for property reports, send new sets if match */
static void listenINDI(FILE *rfp, FILE *wfp)
{
    char msg[1024];

#ifdef _WIN32
    SetTimer(NULL, 0, TIMEOUT_MS, onTimer);
#else
    signal(SIGALRM, onAlarm);
    alarm(TIMEOUT_MS / 1000);
#endif

    /* read from server, exit if find all properties */
    while (1)
    {
        XMLEle *root = readXMLEle(lillp, readServerChar(rfp), msg);
        if (root)
        {
            /* found a complete XML element */
            if (verbose > 1)
                prXMLEle(stderr, root, 0);
            findSet(root, wfp);
            if (finished() == 0)
            {
#ifdef _WIN32
                shutdown(fileno(wfp), SD_SEND);
#else
                shutdown(fileno(wfp), SHUT_WR);
#endif
                exit(0); // found all we want
            }
            delXMLEle(root); // not yet, delete and continue
        }
        else if (msg[0])
        {
            fprintf(stderr, "Bad XML: %s\n", msg);
            exit(2);
        }
    }
}

/* return 0 if we are sure we set everything we wanted to, else -1 */
static int finished()
{
    int i, j;

    for (i = 0; i < nsets; i++)
        for (j = 0; j < sets[i].nev; j++)
            if (!sets[i].ev[j].ok)
                return (-1);
    return (0);
}

/* called after timeout seconds because we did not find something we trying
 * to set.
 */
static void onAlarm(int dummy)
{
    INDI_UNUSED(dummy);
    int i, j;

    for (i = 0; i < nsets; i++)
        for (j = 0; j < sets[i].nev; j++)
            if (!sets[i].ev[j].ok)
                fprintf(stderr, "No %s.%s.%s from %s:%d\n", sets[i].d, sets[i].p, sets[i].ev[j].e, host, port);

    exit(1);
}

static int readServerChar(FILE *fp)
{
    int c = fgetc(fp);

    if (c == EOF)
    {
        if (ferror(fp))
            perror("read");
        else
            fprintf(stderr, "INDI server %s:%d disconnected\n", host, port);
        exit(2);
    }

    if (verbose > 2)
        fprintf(stderr, "Read %c\n", c);

    return (c);
}

/* issue a set command if it matches the given property */
static void findSet(XMLEle *root, FILE *fp)
{
    char *rtype, *rdev, *rprop;
    XMLEle *ep;
    int t, s, i;

    /* check type */
    rtype = tagXMLEle(root);
    for (t = 0; t < (int)NDEFS; t++)
    {
        if (strcmp(rtype, defs[t].defType) == 0)
            break;
    }
    if (t == NDEFS)
        return;

    alarm(timeout); /* reset timeout */

    /* check each set for matching device and property name, send if ok */
    rdev  = (char *)findXMLAttValu(root, "device");
    rprop = (char *)findXMLAttValu(root, "name");
    if (verbose > 1)
        fprintf(stderr, "Read definition for %s.%s\n", rdev, rprop);

    for (s = 0; s < nsets; s++)
    {
        if (!strcmp(rdev, sets[s].d) && !strcmp(rprop, sets[s].p))
        {
            /* found device and name,  check perm */
            if (!strchr(findXMLAttValu(root, "perm"), 'w'))
            {
                if (verbose)
                    fprintf(stderr, "%s.%s is read-only\n", rdev, rprop);
                exit(1);
            }
            /* check matching elements */
            for (i = 0; i < sets[s].nev; i++)
            {
                for (ep = nextXMLEle(root, 1); ep; ep = nextXMLEle(root, 0))
                {
                    if (!strcmp(findXMLAttValu(ep, "name"), sets[s].ev[i].e) && !strcmp(tagXMLEle(ep), defs[t].defOne))
                    {
                        sets[s].ev[i].ok = 1;
                        break;
                    }
                }
                if (!ep)
                    return; /* not in this msg, maybe later */
            }
            /* all element names found, send new values */
            sendNew(fp, &defs[t], &sets[s]);
        }
    }
}

/* send the given set specification of the given INDI type to channel on fp */
static void sendNew(FILE *fp, INDIDef *dp, SetSpec *sp)
{
    int i;

    fprintf(fp, "<%s device='%s' name='%s'>\n", dp->newType, sp->d, sp->p);
    for (i = 0; i < sp->nev; i++)
    {
        if (verbose)
            fprintf(stderr, "  %s.%s.%s <- %s\n", sp->d, sp->p, sp->ev[i].e, sp->ev[i].v);
        fprintf(fp, "  <%s name='%s'>%s</%s>\n", dp->oneType, sp->ev[i].e, sp->ev[i].v, dp->oneType);
    }
    fprintf(fp, "</%s>\n", dp->newType);
    fflush(fp);
    if (feof(fp) || ferror(fp))
    {
        fprintf(stderr, "Send error\n");
        exit(2);
    }
}

/* scan ev for element definitions in either of two forms and add to sp:
 *    e1[;e2...]=v1[;v2...]
 *  or
 *    e1=v1[;e2=v2...]
 * exit if nothing sensible found.
 */
static void scanEV(SetSpec *specp, char ev[])
{
    char *ep, *sp; /* pointers to = and ; */

    if (verbose > 1)
        fprintf(stderr, "Scanning assignments %s\n", ev);

    ep = strchr(ev, '=');
    sp = strchr(ev, ';');

    if (!ep)
    {
        fprintf(stderr, "Malformed assignment: %s\n", ev);
        usage();
    }

    if (sp < ep)
        scanEEVV(specp, ep, ev); /* including just one E=V */
    else
        scanEVEV(specp, ev);
}

/* add specs of the form e1[;e2...]=v1[;v2...] to sp.
 * v is pointer to equal sign.
 * exit if trouble.
 * N.B. e[] and v[] are modified in place.
 */
static void scanEEVV(SetSpec *sp, char *v, char *e)
{
    static char sep[] = ";";
    char *ec, *vc;

    *v++ = '\0';

    while (1)
    {
        char *e0 = strtok_r(e, sep, &ec);
        char *v0 = strtok_r(v, sep, &vc);

        if (!e0 && !v0)
            break;
        if (!e0)
        {
            fprintf(stderr, "More values than elements for %s.%s\n", sp->d, sp->p);
            exit(2);
        }
        if (!v0)
        {
            fprintf(stderr, "More elements than values for %s.%s\n", sp->d, sp->p);
            exit(2);
        }

        sp->ev            = (SetEV *)realloc(sp->ev, (sp->nev + 1) * sizeof(SetEV));
        sp->ev[sp->nev].e = strdup(e0);
        sp->ev[sp->nev].v = strdup(v0);
        if (verbose > 1)
            fprintf(stderr, "Found assignment %s=%s\n", sp->ev[sp->nev].e, sp->ev[sp->nev].v);
        sp->nev++;

        e = NULL;
        v = NULL;
    }
}

/* add specs of the form e1=v1[;e2=v2...] to sp.
 * exit if trouble.
 * N.B. ev[] is modified in place.
 */
static void scanEVEV(SetSpec *sp, char ev[])
{
    char *s, *e;
    int last = 0;

    do
    {
        s = strchr(ev, ';');
        if (s)
            *s++ = '\0';
        else
        {
            s    = ev + strlen(ev);
            last = 1;
        }
        e = strchr(ev, '=');
        if (e)
            *e++ = '\0';
        else
        {
            fprintf(stderr, "Malformed assignment: %s\n", ev);
            usage();
        }

        sp->ev            = (SetEV *)realloc(sp->ev, (sp->nev + 1) * sizeof(SetEV));
        sp->ev[sp->nev].e = strdup(ev);
        sp->ev[sp->nev].v = strdup(e);
        if (verbose > 1)
            fprintf(stderr, "Found assignment %s=%s\n", sp->ev[sp->nev].e, sp->ev[sp->nev].v);
        sp->nev++;

        ev = s;

    } while (!last);
}

/* send each SetSpec, all of which have a known type, to wfp
 */
static void sendSpecs(FILE *wfp)
{
    int i;

    for (i = 0; i < nsets; i++)
        sendNew(wfp, sets[i].dp, &sets[i]);
}
@knro
Copy link
Contributor

knro commented Aug 12, 2023

It would be great if INDI can be built on Windows (not just INDI Client like it is now). Just to be clear, INDI Client compiles and runs on Windows just fine without any additional libraries. It is that INDI server + drivers that do not compile natively on Windows. I presume you are trying to tackle the INDI server + drivers part.

@AstroAir
Copy link
Contributor Author

@knro Yes, there are no issues with the construction of INDIClient. At present, I am working on other parts of the indiserver, but due to some confusion in the code, it has not been resolved yet. The current main issue is still focused on indidriver, and the previous ones can already be built normally

@knro
Copy link
Contributor

knro commented Aug 12, 2023

Alright, please let us know if you can make INDI runs natively on Windows, this would be quite a breakthrough. We still have the issues of dependencies but once INDI runs natively, the rest of the issues can be streamlined in the build process.

@AstroAir AstroAir closed this as not planned Won't fix, can't repro, duplicate, stale Aug 15, 2023
@laheller
Copy link
Contributor

laheller commented Oct 5, 2023

@knro @AstroAir

With only minimal chages in the sources I successfully built INDI on Windows/Cygwin. More info and PR later after testing.

image

BR,

Ladislav

@knro
Copy link
Contributor

knro commented Oct 5, 2023

Very excited to see this @laheller ! Were you able to test any drivers with any clients?

@laheller
Copy link
Contributor

laheller commented Oct 5, 2023

@knro

Not yet, because I am fighting with the indiweb installation in python/cygwin environment and it has a troubles with psutil dependency.
Once I have test results, will let you know.
First probably here in this issue thread.

BR,

Ladislav

@knro
Copy link
Contributor

knro commented Oct 6, 2023

You can still test everything without indiweb.

@laheller
Copy link
Contributor

laheller commented Oct 6, 2023

@knro

Finally I managed to work also indiweb on Cygwin beside one issue (see the screenshot).
Tested with

  • KSTARS/EKOS client on Windows
  • INDI server running on Windows/Cygwin
  • Simulators added to the profile

Everything seems to be working.

Screenshot - indiweb started server and simulator devices:
image

Additional screenshots from EKOS:
image

image

What do you think, do I need to perform any further tests?

BR,

Ladislav

@knro
Copy link
Contributor

knro commented Oct 6, 2023

Wow that's very nice! Have you tried connecting to any physical devices via Serial connection or USB??

@laheller
Copy link
Contributor

laheller commented Oct 6, 2023

Wow that's very nice! Have you tried connecting to any physical devices via Serial connection or USB??

@knro

Not yet but I definitely will try with my:

  • SkyWatcher HEQ5 mount
  • Canon DSLR camera
  • ZWO ASI camera

Probably not under night sky but just "blindly" instead. Once done, will let you know.

@knro
Copy link
Contributor

knro commented Oct 6, 2023

I think this might work just for the skywatcher. The Canon needs libgphoto2 and ZWO driver does not include any Windows DLLs so it can't work on Windows. Perhaps you can try to add Windows support to this driver.

@laheller
Copy link
Contributor

laheller commented Oct 7, 2023

@knro

While I am checking the devices and their drivers, here is the PR. I just did it, because it is only for this repo and also independent from the 3rd party drivers.

Update:
I just built the gphoto2 (for test from command line) and libgphoto2 from sources, because those are not prebuilt for Cygwin.
I also built the indi-gphoto 3rd party driver and started to test it using Kstars and everything else on Windows/Cygwin with my Canon EOS 1300D camera. But unfortunately no matter what I did in EKOS, it ended up with force/close of the whole Kstars...
I don't think the problem is with gphoto2 and Cygwin, because via gphoto2 cli the camera works perfectly. It's something in EKOS and/or the indi_gphoto driver.

BR,

Ladislav

@laheller
Copy link
Contributor

laheller commented Oct 9, 2023

Hi @knro

I was able to build also indi-asi drivers on Cygwin.
I have a ZWO ASI 120 MC-S camera without cooling.
When I start EKOS and open Indi Control Panel, I see an error message there which says:

Failed to get perc power information (ASI_ERROR_INVALID_CONTROL_TYPE).

Also in the Indi Control Panel / Image Info tab I see that main camera parameters are incorrectly detected, because the maximum width is definitely not 2. See the screenshot below.
The correct values should be:

Maximum width: 1280
Maximum height: 960
Pixel size X/Y: 3.75 μm

image

Please if you have time, check & answer also my previous comment above regarding the Kstars/Windows crash.
If you are not familiar with Windows, please redirect me to the developer, who is maintaining the Kstars/Windows builds, because I have an issue with Kstars and DSLR camera which I cannot workaround.

Best Regards,

Ladislav

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants