diff --git a/ccdcapture.c b/ccdcapture.c index da59ea6..8110930 100644 --- a/ccdcapture.c +++ b/ccdcapture.c @@ -525,8 +525,11 @@ int cc_read2buf(int fd, cc_strbuff *buf){ do{ rd = read(fd, buf->buf + buf->buflen, maxlen); if(rd <= 0){ - if(errno == EAGAIN || errno == EWOULDBLOCK) continue; - goto ret; + if(errno == EINTR){ + DBG("errno=%d, '%s'", errno, strerror(errno)); + continue; + } + goto ret; // EAGAIN or other error -> client disconnected }else break; }while(1); DBG("got %zd bytes", rd); @@ -736,6 +739,7 @@ char *cc_nextkw(char *buf, char record[FLEN_CARD], int newlines){ } }else nextline = buf + (FLEN_CARD - 1); strncpy(record, buf, l); + if(l < FLEN_CARD) record[l] = 0; return nextline; } diff --git a/ccdcapture.h b/ccdcapture.h index f4211fd..d5c44ad 100644 --- a/ccdcapture.h +++ b/ccdcapture.h @@ -201,9 +201,11 @@ typedef struct{ // wait for mutex locking #define CC_BUSY_TIMEOUT (1.0) // wait for exposition ends (between subsequent check calls) -#define CC_WAIT_TIMEOUT (2.0) +#define CC_WAIT_TIMEOUT (15.0) // client will disconnect after this time from last server message -#define CC_CLIENT_TIMEOUT (3.0) +#define CC_CLIENT_TIMEOUT (30.0) +// minimal sleep (us) time when client waits for exp end +#define CC_IMWAIT_SLEEP (1000) // fd - socket fd to send private messages, key, val - key and its value typedef cc_hresult (*cc_mesghandler)(int fd, const char *key, const char *val); @@ -234,6 +236,7 @@ typedef enum{ #define CC_CMD_SHMEMKEY "shmemkey" // CCD/CMOS +#define CC_CMD_IMNUMBER "imnumber" #define CC_CMD_PLUGINCMD "plugincmd" #define CC_CMD_CAMLIST "camlist" #define CC_CMD_CAMDEVNO "camdevno" diff --git a/client.c b/client.c index 3c6d6e6..aa928fb 100644 --- a/client.c +++ b/client.c @@ -39,11 +39,11 @@ extern double answer_timeout; static char sendbuf[BUFSIZ]; static char *lastfilename = NULL; // send message and wait any answer -#define SENDMSG(...) do{DBG("SENDMSG"); snprintf(sendbuf, BUFSIZ-1, __VA_ARGS__); verbose(2, "\t> %s", sendbuf); cc_sendstrmessage(sock, sendbuf); while(getans(sock, NULL));} while(0) +#define SENDMSG(...) do{DBG("SENDMSG"); snprintf(sendbuf, BUFSIZ-1, __VA_ARGS__); verbose(2, "\t> %s", sendbuf); if(!cc_sendstrmessage(sock, sendbuf)) ERRX("Server disconnected"); while(getans(sock, NULL));} while(0) // send message and wait answer starting with 'cmd' -#define SENDMSGW(cmd, ...) do{DBG("SENDMSGW"); snprintf(sendbuf, BUFSIZ-1, cmd __VA_ARGS__); verbose(2, "\t> %s", sendbuf); cc_sendstrmessage(sock, sendbuf);}while(!getans(sock, cmd)) +#define SENDMSGW(cmd, ...) do{DBG("SENDMSGW"); snprintf(sendbuf, BUFSIZ-1, cmd __VA_ARGS__); verbose(2, "\t> %s", sendbuf); if(!cc_sendstrmessage(sock, sendbuf)) ERRX("Server disconnected");}while(!getans(sock, cmd)) // send command and wait for answer on it -#define SENDCMDW(cmd) do{DBG("SENDCMDW"); strncpy(sendbuf, cmd, BUFSIZ-1); verbose(2, "\t> %s", sendbuf); cc_sendstrmessage(sock, sendbuf);}while(!getans(sock, cmd)) +#define SENDCMDW(cmd) do{DBG("SENDCMDW"); strncpy(sendbuf, cmd, BUFSIZ-1); verbose(2, "\t> %s", sendbuf); if(!cc_sendstrmessage(sock, sendbuf)) ERRX("Server disconnected");}while(!getans(sock, cmd)) static volatile atomic_int expstate = CAMERA_CAPTURE; static int xm0,ym0,xm1,ym1; // max format static int xc0,yc0,xc1,yc1; // current format @@ -54,8 +54,9 @@ static int oldgrabno = 0; static cc_IMG ima = {0}, *shmima = NULL; // ima - local storage, shmima - shm (if available) static size_t imbufsz = 0; // image buffer for allocated `ima` static uint8_t *imbuf = NULL; // we can't use shmima->data as it belongs to server, so we use `imbuf` and set ima.data = imbuf +static int current_image_number = -1; // for net-parser - last number of exposed image - +#if 0 // read message from queue or file descriptor static char *readmsg(int fd){ static cc_strbuff *buf = NULL; @@ -78,6 +79,7 @@ static char *readmsg(int fd){ } return NULL; } +#endif #define CMP_ANS(cmd, ans) strncmp(cmd, ans, sizeof(cmd)-1) // parser of CCD server messages; return TRUE to exit from polling cycle of `getans` (if receive 'FAIL', 'OK' or 'BUSY') @@ -89,7 +91,7 @@ static cc_hresult parseans(char *ans){ for(cc_hresult res = CC_RESULT_BUSY; res < CC_RESULT_NUM; ++res){ const char *resmsg = cc_hresult2str(res); if(0 == strcmp(resmsg, ans)){ - WARNX("Server answered: %s", resmsg); + verbose(1, "Server answered: %s", resmsg); return res; } } @@ -97,16 +99,18 @@ static cc_hresult parseans(char *ans){ if(0 == CMP_ANS(CC_CMD_EXPSTATE, ans)){ int st = atoi(val); atomic_store(&expstate, st); - DBG("Exposition state: %d", st); - return CC_RESULT_OK; + DBG("Current state: %d", atomic_load(&expstate)); + return CC_RESULT_SILENCE; }else if(0 == CMP_ANS(CC_CMD_FRAMEMAX, ans)){ sscanf(val, "%d,%d,%d,%d", &xm0, &ym0, &xm1, &ym1); DBG("Got maxformat: %d,%d,%d,%d", xm0, ym0, xm1, ym1); - return CC_RESULT_OK; + return CC_RESULT_SILENCE; }else if(0 == CMP_ANS(CC_CMD_FRAMEFORMAT, ans)){ sscanf(val, "%d,%d,%d,%d", &xc0, &yc0, &xc1, &yc1); DBG("Got current format: %d,%d,%d,%d", xc0, yc0, xc1, yc1); - return CC_RESULT_OK; + return CC_RESULT_SILENCE; + }else if(0 == CMP_ANS(CC_CMD_IMNUMBER, ans)){ + current_image_number = atoi(val); } //TIMESTAMP("parseans() end"); return CC_RESULT_SILENCE; // echo of sent command or something else @@ -116,13 +120,28 @@ static cc_hresult parseans(char *ans){ // if msg != NULL - wait for it in answer static int getans(int sock, const char *msg){ double t0 = sl_dtime(); + char buf[BUFSIZ+1]; + int idx = 0; char *ans = NULL; - double tmout = answer_timeout; + TIMESTAMP("GetAns(%s)", msg); + double tmout = answer_timeout + 5.; // make first timeout larger for slow networks // TODO: increase first timeout up to 15-30s (add key?) - if(msg) tmout *= 5.; // make first timeout larger for slow networks cc_hresult res = CC_RESULT_FAIL; while(sl_dtime() - t0 < tmout){ - ans = readmsg(sock); + ans = NULL; + if(1 == sl_canread(sock)){ + ssize_t got = read(sock, buf+idx, BUFSIZ-idx); + if(got > 0){ + idx += got; + buf[idx] = 0; + char *nl = strchr(buf, '\n'); + if(nl){ + *nl = 0; + ans = buf; + DBG("got '%s'", ans); + } + } + } if(!ans) continue; // got answer -> make timeout less tmout = answer_timeout; @@ -132,14 +151,15 @@ static int getans(int sock, const char *msg){ DBG("1 msg-> %s, ans -> %s", msg, ans); res = parseans(ans); DBG("2 msg-> %s, ans -> %s; result: %d", msg, ans, res); - if(res == CC_RESULT_SILENCE && msg){ - if(strncmp(ans, msg, strlen(msg))) continue; + if(msg){ + if(res != CC_RESULT_SILENCE || strncmp(ans, msg, strlen(msg))) continue; else res = CC_RESULT_OK; } DBG("Got answer -> break"); break; } - if(!ans) DBG("Got no answer from server"); + TIMESTAMP("GetAns(%s), ans: '%s', result: %d", msg, ans, res); + if(!ans) DBG("Got no answer from server; result=%d", res); if(res == CC_RESULT_OK) return TRUE; return FALSE; } @@ -289,8 +309,10 @@ static int getimage(int askheader){ } memcpy(&ima, shmima, sizeof(cc_IMG)); }else{ // get image by socket - DBG("Open socket @ %s", GP->imageport); - imsock = cc_open_socket(FALSE, GP->imageport, TRUE); + if(imsock < 0){ + DBG("Open socket @ %s", GP->imageport); + imsock = cc_open_socket(FALSE, GP->imageport, TRUE); + } if(imsock < 0) ERRX("getimage(): can't open image transport socket"); // get image size if(!readNbytes(imsock, sizeof(cc_IMG), (uint8_t*)&ima)){ @@ -298,6 +320,10 @@ static int getimage(int askheader){ goto eofg; } } + if(ima.MAGICK != CC_SHM_MAGIC){ + WARNX("Wrong image: bad magick"); + goto eofg; + } if(ima.bytelen < 1){ WARNX("Wrong image size"); goto eofg; @@ -358,11 +384,24 @@ static int getimage(int askheader){ }else ima.headerstrings = 0; }else WARNX("Still got old image"); eofg: - if(imsock != -1) close(imsock); + if(imsock != -1) close(imsock); // reopen in next time in case of error if(shmlocked) cc_unlock_shm(); return ret; } +// get number of current image; return number or -1 if got error/timeout +static int curImNo(int sock){ + if(shmima){ + if(!cc_lock_shm(FALSE)) return -1; + int CurNo = shmima->imnumber; + cc_unlock_shm(); + return CurNo; + } + // no shared memory: try to get number over TCP + SENDCMDW(CC_CMD_IMNUMBER); + return current_image_number; +} + void client(int sock){ if(sock < 0) ERRX("Can't run without command socket"); if(!GP->forceimsock && !shmima){ // init shm buffer if user don't ask to force workign through image socket @@ -388,9 +427,11 @@ void client(int sock){ double timeout = CC_CLIENT_TIMEOUT; verbose(1, "Exposing frame 1..."); atomic_store(&expstate, CAMERA_CAPTURE); // could be changed earlier + DBG("Current state: %d", atomic_load(&expstate)); verbose(2, "Wait for exposition end"); t0 = sl_dtime(); tw = tstart = t0; + int lastImNo = curImNo(sock); while(sl_dtime() - t0 < timeout){ if(sl_dtime() - tw > CC_WAIT_TIMEOUT){ SENDCMDW(CC_CMD_TREMAIN); // get remained time @@ -398,13 +439,12 @@ void client(int sock){ } if(sl_dtime() - tstart < GP->exptime){ t0 = sl_dtime(); // refresh timeout until exp not ends + continue; }else{ SENDCMDW(CC_CMD_EXPSTATE); -#ifdef EBUG - usleep(300000); -#endif } int curst = atomic_load(&expstate); + DBG("Current state: %d", curst); if(curst == CAMERA_ERROR){ WARNX(_("Can't make exposition")); if(Nremain > 1){ @@ -414,25 +454,29 @@ void client(int sock){ } continue; } - //if(expstate != CAMERA_CAPTURE){ if(curst == CAMERA_FRAMERDY){ atomic_store(&expstate, CAMERA_IDLE); - if(Nremain > 1){ - verbose(1, "Exposing frame %d...", nframe+1); + int cur = curImNo(sock); + DBG("Current state: %d, imno: %d", atomic_load(&expstate), cur); + if(Nremain > 1){ // start next capture + verbose(1, "Exposing frame %d...", nframe); SENDMSGW(CC_CMD_EXPSTATE, "=%d", CAMERA_CAPTURE); tstart = sl_dtime(); } - verbose(2, "Frame ready, try to grab"); int failed = TRUE; - if(!getimage(TRUE)){ - WARNX("Can't get next image"); - }else{ - if(saveFITS(&ima, &lastfilename)){ - --Nremain; - ++nframe; - failed = FALSE; + if(lastImNo < cur){ + lastImNo = cur; + verbose(2, "Frame ready, try to grab"); + if(!getimage(TRUE)){ + WARNX("Can't get next image"); + }else{ + if(saveFITS(&ima, &lastfilename)){ + --Nremain; + ++nframe; + failed = FALSE; + } } - } + }else verbose(2, "Got already saved image, wait next"); if(failed && Nremain == 1){ // last image -> should re-expose verbose(1, "Exposing frame %d...", nframe); SENDMSGW(CC_CMD_EXPSTATE, "=%d", CAMERA_CAPTURE); @@ -476,32 +520,40 @@ static void *grabnext(void _U_ *arg){ FNAME(); if(controlfd < 0) return NULL; int sock = controlfd; + int lastImNo = curImNo(sock); while(1){ if(!getWin()) exit(1); TIMESTAMP("End of cycle, start new"); atomic_store(&expstate, CAMERA_CAPTURE); + DBG("Current state: %d", atomic_load(&expstate)); TIMEINIT(); SENDMSGW(CC_CMD_EXPSTATE, "=%d", CAMERA_CAPTURE); // start capture double timeout = GP->exptime + CC_CLIENT_TIMEOUT, t0 = sl_dtime(); useconds_t sleept = 500000; // 0.5s if(GP->exptime < 0.5){ - sleept = (useconds_t)(GP->exptime * 500000.); - if(sleept < 1000) sleept = 1000; + sleept = (useconds_t)(GP->exptime * 250000.); // a quater of exposition time + if(sleept < CC_IMWAIT_SLEEP) sleept = CC_IMWAIT_SLEEP; } -// double exptime = GP->exptime; - TIMESTAMP("Wait for exposition ends (%g s)", timeout); + TIMESTAMP("Wait for exposition ends (%g s), sleep for %dus", timeout, sleept); + int curst = CAMERA_CAPTURE; while(sl_dtime() - t0 < timeout){ + DBG("start sleep for %dus", sleept); usleep(sleept); - // getans(sock, NULL); - //TIMESTAMP("EXPSTATE ===> %d", expstate); - if(atomic_load(&expstate) != CAMERA_CAPTURE) break; - if(sl_dtime() - t0 < GP->exptime + 0.5) sleept = 1000; + SENDCMDW(CC_CMD_EXPSTATE); + curst = atomic_load(&expstate); + if(curst != CAMERA_CAPTURE) break; + if(sl_dtime() - t0 > GP->exptime && sleept != CC_IMWAIT_SLEEP){ + DBG("Set sleeping time to %dus", sleept); + sleept = CC_IMWAIT_SLEEP; + } } - if(sl_dtime() - t0 >= timeout || atomic_load(&expstate) != CAMERA_FRAMERDY){ - WARNX("Image wasn't received"); + int cur = curImNo(sock); + if(sl_dtime() - t0 >= timeout || curst != CAMERA_FRAMERDY || cur <= lastImNo){ + WARNX("Image wasn't received, state: %d, waiting: %g, lastNo: %d, curNo: %d (timeout: %g)", curst, sl_dtime() - t0, lastImNo, cur, timeout); continue; } - TIMESTAMP("Frame ready"); + lastImNo = cur; + TIMESTAMP("Frame ready (%d from server's start)", cur); getimage(FALSE); } return NULL; @@ -512,17 +564,26 @@ static void *waitimage(void _U_ *arg){ FNAME(); if(controlfd < 0) return NULL; int sock = controlfd; + int lastImNo = curImNo(sock); + double t0 = sl_dtime(); while(1){ if(!getWin()) exit(1); - getans(sock, NULL); - if(atomic_load(&expstate) != CAMERA_FRAMERDY){ - usleep(1000); + double tcur = sl_dtime(); + if(tcur - t0 >= CC_WAIT_TIMEOUT){ + SENDCMDW(CC_CMD_EXPSTATE); // `ping` server to know if it disconnected + t0 = tcur; + } + int cur = curImNo(sock); + if(cur <= lastImNo){ + usleep(CC_IMWAIT_SLEEP); continue; } - TIMESTAMP("End of cycle, start new"); + lastImNo = cur; + TIMESTAMP("End of cycle #%d, start new", cur); TIMEINIT(); getimage(FALSE); atomic_store(&expstate, CAMERA_IDLE); + DBG("Current state: %d", atomic_load(&expstate)); } return NULL; } diff --git a/locale/ru/messages.po b/locale/ru/messages.po index e13cfd5..c8da9e7 100644 --- a/locale/ru/messages.po +++ b/locale/ru/messages.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2026-06-04 18:22+0300\n" +"POT-Creation-Date: 2026-06-08 17:06+0300\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -494,12 +494,12 @@ msgstr "" msgid "Can't set brightness to %g" msgstr "" -#: ccdfunc.c:690 server.c:323 +#: ccdfunc.c:690 server.c:330 #, c-format msgid "Can't set binning %dx%d" msgstr "" -#: ccdfunc.c:702 server.c:324 +#: ccdfunc.c:702 server.c:331 msgid "Can't set given geometry" msgstr "" @@ -547,11 +547,11 @@ msgstr "" msgid "Capture frame %d" msgstr "" -#: ccdfunc.c:750 ccdfunc.c:827 server.c:184 server.c:185 +#: ccdfunc.c:750 ccdfunc.c:827 server.c:194 server.c:195 msgid "Camera plugin have no function `start exposition`" msgstr "" -#: ccdfunc.c:752 ccdfunc.c:829 server.c:190 server.c:191 +#: ccdfunc.c:752 ccdfunc.c:829 server.c:200 server.c:201 msgid "Can't start exposition" msgstr "" @@ -563,7 +563,7 @@ msgstr "" msgid "Read grabbed image" msgstr "" -#: ccdfunc.c:762 ccdfunc.c:842 server.c:208 server.c:209 +#: ccdfunc.c:762 ccdfunc.c:842 server.c:218 server.c:219 msgid "Camera plugin have no function `capture`" msgstr "" @@ -571,7 +571,7 @@ msgstr "" msgid "Can't grab image" msgstr "" -#: ccdfunc.c:778 client.c:447 +#: ccdfunc.c:778 client.c:491 #, c-format msgid "%d seconds till pause ends\n" msgstr "" @@ -580,15 +580,15 @@ msgstr "" msgid "Some error when capture" msgstr "" -#: server.c:235 +#: server.c:247 msgid "No camera device" msgstr "" -#: client.c:409 +#: client.c:449 msgid "Can't make exposition" msgstr "" -#: client.c:459 +#: client.c:503 msgid "Server timeout" msgstr "" diff --git a/locale/ru/ru.po b/locale/ru/ru.po index e20c037..2f47263 100644 --- a/locale/ru/ru.po +++ b/locale/ru/ru.po @@ -7,7 +7,7 @@ msgid "" msgstr "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" - "POT-Creation-Date: 2026-06-04 18:16+0300\n" + "POT-Creation-Date: 2026-06-08 16:46+0300\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -21,7 +21,7 @@ msgstr "Project-Id-Version: PACKAGE VERSION\n" msgid "%.1f seconds till exposition ends" msgstr "%.1f секунд до окончания экспозиции" -#: ccdfunc.c:778 client.c:447 +#: ccdfunc.c:778 client.c:491 #, c-format msgid "%d seconds till pause ends\n" msgstr "%d секунд до окончания паузы\n" @@ -66,12 +66,12 @@ msgstr " msgid "Camera plugin have no fun speed setter" msgstr "У плагина камеры нет особых команд" -#: ccdfunc.c:762 ccdfunc.c:842 server.c:208 server.c:209 +#: ccdfunc.c:762 ccdfunc.c:842 server.c:218 server.c:219 #, fuzzy msgid "Camera plugin have no function `capture`" msgstr "У плагина камеры нет особых команд" -#: ccdfunc.c:750 ccdfunc.c:827 server.c:184 server.c:185 +#: ccdfunc.c:750 ccdfunc.c:827 server.c:194 server.c:195 #, fuzzy msgid "Camera plugin have no function `start exposition`" msgstr "У плагина камеры нет особых команд" @@ -130,7 +130,7 @@ msgstr " msgid "Can't init mutex!" msgstr "Не могу инициализировать мьютекс!" -#: client.c:409 +#: client.c:449 msgid "Can't make exposition" msgstr "Не могу выполнить экспозицию" @@ -174,7 +174,7 @@ msgstr " msgid "Can't set active wheel number" msgstr "Не могу установить номер активного колеса" -#: ccdfunc.c:690 server.c:323 +#: ccdfunc.c:690 server.c:330 #, c-format msgid "Can't set binning %dx%d" msgstr "Не могу установить биннинг %dx%d" @@ -202,7 +202,7 @@ msgstr " msgid "Can't set gain to %g" msgstr "Не могу установить Gain в %g" -#: ccdfunc.c:702 server.c:324 +#: ccdfunc.c:702 server.c:331 msgid "Can't set given geometry" msgstr "Не могу установить геометрию" @@ -225,7 +225,7 @@ msgstr " msgid "Can't set wheel position %d" msgstr "Не могу установить положение колеса %d" -#: ccdfunc.c:752 ccdfunc.c:829 server.c:190 server.c:191 +#: ccdfunc.c:752 ccdfunc.c:829 server.c:200 server.c:201 msgid "Can't start exposition" msgstr "Не могу начать экспозицию" @@ -304,7 +304,7 @@ msgstr " msgid "N flushes before exposing (default: 1)" msgstr "N засвечиваний перед экспозицией (по умолчанию: 1)" -#: server.c:235 +#: server.c:247 msgid "No camera device" msgstr "Не указано устройство камеры" @@ -338,7 +338,7 @@ msgstr " msgid "Readout mode: %s" msgstr "Режим считывания: %s" -#: client.c:459 +#: client.c:503 msgid "Server timeout" msgstr "Таймаут сервера" diff --git a/server.c b/server.c index 08ca857..c02ec63 100644 --- a/server.c +++ b/server.c @@ -82,6 +82,7 @@ strpair allcommands[] = { { CC_CMD_HBIN, "horizontal binning" }, { CC_CMD_HELP, "show this help" }, { CC_CMD_IMHEIGHT, "last image height" }, + { CC_CMD_IMNUMBER, "grabbed image number from server start"}, { CC_CMD_IMWIDTH, "last image width" }, { CC_CMD_INFTY, "an infinity loop taking images until there's connected clients" }, { CC_CMD_INSTRUMENT, "FITS 'INSTRUME' field" }, @@ -116,6 +117,7 @@ static int lock(){ //DBG("\n\nAlready locked"); return FALSE; } + //DBG("LOCK()"); return TRUE; } static void unlock(){ @@ -123,6 +125,7 @@ static void unlock(){ LOGERR("Can't unlock socket mutex"); ERR("Can't unlock socket mutex"); } + //DBG("UNLOCK()"); } static cc_IMG *ima = NULL; @@ -145,10 +148,15 @@ static void fixima(){ if(!camera) return; double t0 = sl_dtime(); int locked = FALSE; + TIMESTAMP("Lock socket"); // lock socket operations - while(!(locked = lock()) && sl_dtime() - t0 < 0.5); - if(!locked) while(!lock()) unlock(); // force unlocking if can't do this gracefully + while(!(locked = lock()) && sl_dtime() - t0 < 0.5) usleep(1000); + if(!locked){ + DBG("Still locked from outside -> unlock/lock"); + while(!lock()) unlock(); // force unlocking if can't do this gracefully + }else DBG("LOCK takes %gs", sl_dtime()-t0); int raw_width = curformat.w / GP->hbin, raw_height = curformat.h / GP->vbin; + TIMESTAMP("Check SHM image"); // allocate memory for largest possible image if(!ima){ ima = cc_getshm(GP->shmkey, camera->array.h * camera->array.w * 2); @@ -156,6 +164,7 @@ static void fixima(){ // init shared semaphore cc_init_sem(TRUE); } + TIMESTAMP("Lock SHM image"); cc_lock_shm(TRUE); shmkey = GP->shmkey; //if(raw_width == ima->w && raw_height == ima->h) return; // all OK @@ -171,6 +180,7 @@ static void fixima(){ DBG("new image: %dx%d", raw_width, raw_height); cc_unlock_shm(); unlock(); + TIMESTAMP("All OK"); } // functions for processCAM finite state machine @@ -216,12 +226,14 @@ static inline void cameracapturestate(){ // capturing - wait for exposition ends camstate = CAMERA_ERROR; return; }else{ + TIMESTAMP("Fill FITS header"); ima->gotstat = 0; // fresh image without statistics - recalculate when save ima->timestamp = sl_dtime(); // set timestamp fillFITSheader(ima); ++ima->imnumber; // increment counter } cc_unlock_shm(); + TIMESTAMP("Captured and unlocked"); } camstate = CAMERA_FRAMERDY; } @@ -249,7 +261,7 @@ static void* processCAM(_U_ void *d){ printf("\t\t\tprocessCAM(), 5 seconds\n"); } #endif - usleep(100); + usleep(1000); if(tremain < 0.5 && tremain > 0.) usleep(tremain*1e6); if(lock()){ // log @@ -276,22 +288,17 @@ static void* processCAM(_U_ void *d){ unlock(); continue; } + unlock(); cc_camera_state curstate = camstate; switch(curstate){ - case CAMERA_IDLE: - cameraidlestate(); - break; case CAMERA_CAPTURE: cameracapturestate(); break; - case CAMERA_FRAMERDY: - // do nothing: when `server` got this state it sends "expstate=2" to all clients and changes state to IDLE - break; - case CAMERA_ERROR: - // do nothing: when `server` got this state it sends "expstate=3" to all clients and changes state to IDLE + default: + cameraidlestate(); break; } - unlock(); + } } return NULL; @@ -363,9 +370,7 @@ static cc_hresult restarthandler(_U_ int fd, _U_ const char *key, _U_ const char static cc_hresult imsizehandler(int fd, const char *key, _U_ const char *val){ char buf[64]; if(!ima) return CC_RESULT_FAIL; - // send image width/height in pixels - if(0 == strcmp(key, CC_CMD_IMHEIGHT)) snprintf(buf, 63, CC_CMD_IMHEIGHT "=%d", ima->h); - else snprintf(buf, 63, CC_CMD_IMWIDTH "=%d", ima->w); + snprintf(buf, 63, "%s=%d", key, (0 == strcmp(key, CC_CMD_IMHEIGHT)) ? ima->h : ima->w); if(!cc_sendstrmessage(fd, buf)) return CC_RESULT_DISCONNECTED; return CC_RESULT_SILENCE; } @@ -488,19 +493,21 @@ static cc_hresult camfanhandler(int fd, _U_ const char *key, _U_ const char *val } const char *shutterstr[] = {"open", "close", "expose @high", "expose @low"}; static cc_hresult shutterhandler(_U_ int fd, _U_ const char *key, const char *val){ + char buf[64]; if(!camera->shuttercmd) return CC_RESULT_FAIL; - if(val){ - int x = atoi(val); - if(x < 0 || x >= SHUTTER_AMOUNT) return CC_RESULT_BADVAL; - int r = camera->shuttercmd((cc_shutter_op)x); - if(r){ - LOGMSG("Shutter command '%s'", shutterstr[x]); - }else{ - LOGWARN("Can't run shutter command '%s'", shutterstr[x]); - return CC_RESULT_FAIL; - } + if(!val) return CC_RESULT_BADVAL; + int x = atoi(val); + if(x < 0 || x >= SHUTTER_AMOUNT) return CC_RESULT_BADVAL; + int r = camera->shuttercmd((cc_shutter_op)x); + if(r){ + LOGMSG("Shutter command '%s'", shutterstr[x]); + }else{ + LOGWARN("Can't run shutter command '%s'", shutterstr[x]); + return CC_RESULT_FAIL; } - return CC_RESULT_OK; + snprintf(buf, 63, "%s=%d", key, x); + if(!cc_sendstrmessage(fd, buf)) return CC_RESULT_DISCONNECTED; + return CC_RESULT_SILENCE; } static cc_hresult confiohandler(_U_ int fd, _U_ const char *key, _U_ const char *val){ char buf[64]; @@ -613,17 +620,18 @@ static cc_hresult expstatehandler(int fd, _U_ const char *key, const char *val){ int n = atoi(val); if(n == CAMERA_IDLE){ // cancel expositions camflags |= FLAG_CANCEL; - return CC_RESULT_OK; } else if(n == CAMERA_CAPTURE){ // start exposition if(GP->exptime < 1e-9){ // need exposition time to be set return CC_RESULT_FAIL; } - if(camstate == CAMERA_CAPTURE) return CC_RESULT_BUSY; // in progress + if(camstate == CAMERA_CAPTURE){ + DBG("Capture in process when user ask '%s=%s'", key, val); + return CC_RESULT_BUSY; // in progress + } TIMESTAMP("Get FLAG_STARTCAPTURE"); TIMEINIT(); camflags |= FLAG_STARTCAPTURE; - return CC_RESULT_OK; } else return CC_RESULT_BADVAL; } @@ -657,6 +665,16 @@ static cc_hresult _8bithandler(int fd, _U_ const char *key, const char *val){ if(!cc_sendstrmessage(fd, buf)) return CC_RESULT_DISCONNECTED; return CC_RESULT_SILENCE; } +static cc_hresult imnohandler(int fd, const char *key, const char _U_ *val){ + if(!ima) return CC_RESULT_FAIL; + char buf[64]; + cc_lock_shm(TRUE); + int No = ima->imnumber; + cc_unlock_shm(); + snprintf(buf, 63, "%s=%d", key, No); + if(!cc_sendstrmessage(fd, buf)) return CC_RESULT_DISCONNECTED; + return CC_RESULT_SILENCE; +} static cc_hresult fastspdhandler(int fd, _U_ const char *key, const char *val){ char buf[64]; if(!camera->setfastspeed) return CC_RESULT_FAIL; @@ -955,6 +973,7 @@ static cc_handleritem items[] = { {chkcc, camsetNhandler, CC_CMD_CAMDEVNO}, {chkcc, camfanhandler, CC_CMD_CAMFANSPD}, {chkcc, exphandler, CC_CMD_EXPOSITION}, + {chkcc, imnohandler, CC_CMD_IMNUMBER}, {chkcc, binhandler, CC_CMD_HBIN}, {chkcc, binhandler, CC_CMD_VBIN}, {chkcc, temphandler, CC_CMD_CAMTEMPER}, @@ -1078,9 +1097,7 @@ void server(int sock, int imsock){ printf("\t\t\tserver(), 5 seconds\n"); } #endif - DBG("poll"); poll(poll_set, nfd, 1); // max timeout - 1ms - DBG("chk imsock"); //if(imsock > -1 && sl_canread(imsock) > 0){ if(imsock > -1 && (poll_set[1].revents & POLLIN)){ //uint8_t buf[32]; @@ -1113,7 +1130,6 @@ void server(int sock, int imsock){ } }else{WARN("accept()"); DBG("disconnected");} } - DBG("chk cmd sock"); if(poll_set[0].revents & POLLIN){ // check main for accept() struct sockaddr_in addr; socklen_t len = sizeof(addr); @@ -1147,11 +1163,11 @@ void server(int sock, int imsock){ camstate = CAMERA_IDLE; } #endif - DBG("scan connections"); // scan connections for(int fdidx = 2; fdidx < nfd; ++fdidx){ if((poll_set[fdidx].revents & POLLIN) == 0) continue; int fd = poll_set[fdidx].fd; + DBG("Got active fd=%d", fd); cc_strbuff *curbuff = buffers[fdidx-1]; int disconnected = 0; if(cc_read2buf(fd, curbuff)){ @@ -1173,7 +1189,6 @@ void server(int sock, int imsock){ --nfd; } } - DBG("Check infty"); // check `infty` if(camstate != CAMERA_CAPTURE && infty){ // start new exposition // mark to start new capture in infinity loop when at least one client connected @@ -1183,7 +1198,6 @@ void server(int sock, int imsock){ TIMEINIT(); } } - DBG("OK ->"); } WARNX("SERVER STOPPED!"); camstop();