Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
10b552b
adds the missing subscribers to camerad for header data collection
astronomerdave May 20, 2026
32f0bb9
fix: update missed home state in slitd
astronomerdave May 20, 2026
b0834ab
fix: lamp modulator naming was off by 1
astronomerdave May 20, 2026
fe32076
powerd publishes status
astronomerdave May 20, 2026
0cdabe1
sequencer writes IMGTYPE keyword
astronomerdave May 20, 2026
a574ead
updates default slit width
astronomerdave May 20, 2026
5859cf4
fix: drain DaemonClient send buffer from DONTWAIT or timed-out sends
astronomerdave May 20, 2026
1d7dd20
calibd publishes status
astronomerdave May 20, 2026
925b063
sequencer skips targets if nexp==0
astronomerdave May 20, 2026
6ff50a9
fix: focusd publishes on status change
astronomerdave May 20, 2026
4bb6f45
fix: sequencerd publishes targetinfo
astronomerdave May 20, 2026
6b4e927
finish migrating telemetry from TELEMREQUEST pull to ZMQ pub/sub
astronomerdave May 24, 2026
428a544
adds Config file updates that should have been part of commit ca90f1
astronomerdave May 25, 2026
c4db130
removes legacy test code
astronomerdave May 25, 2026
1eb2a87
fix: restores fix made in PR 433 which PR 439 inadvertently removed
astronomerdave May 25, 2026
dfe3c61
adds remaining needed publish mutex locks (see PR 433)
astronomerdave May 25, 2026
0ee3e82
fix uninitialized var and split acam thermal from status topics
astronomerdave May 28, 2026
1760717
fixes mostly pertaining to pub-sub issues --
astronomerdave May 28, 2026
f971db1
fix: prevents reporting status if device is closed
astronomerdave May 28, 2026
615412d
fix: pretty serious oversight, was passing sockets by value which
astronomerdave May 29, 2026
7c6059d
removes debug logging that made for high-volume tcsd logs
astronomerdave May 29, 2026
00b8471
removes more tcs verbose logging
astronomerdave May 29, 2026
b6c8420
fix: replaces motor count as mechanism of completion with vector of
astronomerdave May 29, 2026
0cb78b0
fix: inter-daemon communication hasn't been robust, lacking proper
astronomerdave May 29, 2026
907dace
bugfix: acquire flag wasn't cleared on stop, resulting in offsets
astronomerdave May 30, 2026
9c7e359
cleanup: disable LOGLEVEL_DEBUG, tidy some log writes
astronomerdave Jun 1, 2026
53fe435
fix: guard close_log() with loglock and clear stream state to fix noon
astronomerdave Jun 1, 2026
304d679
fix: retries init_log on failure
astronomerdave Jun 1, 2026
145a2c3
fix: adds capped exponential backoff to thermald telemetry reconnect
astronomerdave Jun 1, 2026
29cf6f7
fix: make TcpSocket fd atomic and Close() single-shot
astronomerdave Jun 1, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions Andor/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ set( ANDOR_DIR ${PROJECT_BASE_DIR}/Andor )

set( CMAKE_CXX_STANDARD 17 )

add_definitions( -Wall -ansi -O0 -Wno-variadic-macros -ggdb )
add_definitions( -Wall -O0 -Wno-variadic-macros -ggdb )
add_definitions(-D_LP64)

include_directories( ${PROJECT_BASE_DIR}/utils )
Expand All @@ -30,12 +30,14 @@ find_library( CFITS_LIB cfitsio NAMES libcfitsio PATHS /usr/local/lib )
find_path( PYTHON_DEV "Python.h" PATHS /usr/include/python3.9 )
find_library( PYTHON_LIB python3.9 NAMES libpython3.9 PATHS /usr/lib64 )
include_directories( ${PYTHON_DEV} )

add_link_options( -L/usr/lib64 -lpython3.9 -lcrypt -lpthread -ldl -lutil -lm -lm )

include_directories( ${PYTHON_DEV} )

add_library( andor STATIC
${ANDOR_DIR}/andor.cpp
${ANDOR_DIR}/andor_emulator.cpp
${PYTHON_DEV}
)

target_link_libraries( andor
Expand Down
2 changes: 1 addition & 1 deletion Andor/andor_emulator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1218,7 +1218,7 @@ namespace Andor {
}

#ifdef LOGLEVEL_DEBUG
// log_python_arguments(pFunction, pArgs, pKwArgs);
log_python_arguments(pFunction, pArgs, pKwArgs);
#endif

// Call the Python function here
Expand Down
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
# @author David Hale <dhale@caltech.edu>
# ----------------------------------------------------------------------------

add_definitions(-DLOGLEVEL_DEBUG)
#add_definitions(-DLOGLEVEL_DEBUG)

cmake_minimum_required( VERSION 3.12 )

Expand Down
9 changes: 3 additions & 6 deletions Config/acamd.cfg.in
Original file line number Diff line number Diff line change
Expand Up @@ -169,14 +169,11 @@ ACQUIRE_TCS_MAX_OFFSET=60 # the maximum allowable offset sent to the TCS, in
SKYSIM_IMAGE_SIZE=1024

# -----------------------------------------------------------------------------
# TELEM_PROVIDER=( <name> <port> )
# SUBSCRIBE_TO=( <name> <endpoint> )
#
# This is a list of telemetry providers where <name> is the daemon name,
# and <port> is the port on which to send the telemetry request.
# This is a list of pub/sub sources to subscribe to, where <name> is the daemon
# name and <endpoint> is its ZeroMQ publish endpoint.
# Provide one per line.
#
TELEM_PROVIDER=(tcsd @TCSD_NB_PORT@)
TELEM_PROVIDER=(sequencerd @SEQUENCERD_NB_PORT@)
#
SUBSCRIBE_TO=(tcsd "tcp://127.0.0.1:@TCSD_PUB_PORT@")
SUBSCRIBE_TO=(sequencerd "tcp://127.0.0.1:@SEQUENCERD_PUB_PORT@")
19 changes: 5 additions & 14 deletions Config/camerad.cfg.in
Original file line number Diff line number Diff line change
Expand Up @@ -155,20 +155,11 @@ ACTIVATE_COMMANDS=(G PON, ERS 1000 1000, EPG 500, CLR)
ACTIVATE_COMMANDS=(U PON, CLR)

# -----------------------------------------------------------------------------
# TELEM_PROVIDER=( <name> <port> )
#
# This is a list of telemetry providers where <name> is the daemon name,
# and <port> is the port on which to send the telemetry request. These are the
# sources for telemetry information for FITS headers. Provide one per line.
#
TELEM_PROVIDER=(calibd @CALIBD_NB_PORT@)
TELEM_PROVIDER=(flexured @FLEXURED_NB_PORT@)
TELEM_PROVIDER=(focusd @FOCUSD_NB_PORT@)
TELEM_PROVIDER=(powerd @POWERD_NB_PORT@)
TELEM_PROVIDER=(sequencerd @SEQUENCERD_NB_PORT@)
TELEM_PROVIDER=(slitd @SLITD_NB_PORT@)
TELEM_PROVIDER=(tcsd @TCSD_NB_PORT@)
TELEM_PROVIDER=(thermald @THERMALD_NB_PORT@)
# SUBSCRIBE_TO=( <name> <endpoint> )
#
# This is a list of pub/sub sources to subscribe to, where <name> is the daemon
# name and <endpoint> is its ZeroMQ publish endpoint. These are the sources for
# telemetry information for FITS headers. Provide one per line.
#
SUBSCRIBE_TO=(calibd "tcp://127.0.0.1:@CALIBD_PUB_PORT@")
SUBSCRIBE_TO=(flexured "tcp://127.0.0.1:@FLEXURED_PUB_PORT@")
Expand Down
17 changes: 10 additions & 7 deletions Config/flexured.cfg.in
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,13 @@ NBPORT=@FLEXURED_NB_PORT@ # slitd server non-blocking port
DAEMON=no # run as daemon?
ASYNCPORT=@MESSAGEPORT@ # asynchronous message port
ASYNCGROUP=239.1.1.234 # asynchronous message broadcast group
PUBLISHER_PORT="tcp://127.0.0.1:@FLEXURED_PUB_PORT@" # my zeromq pub port

# Message pub/sub
# PUB_ENDPOINT=tcp://127.0.0.1:<PORT>
# SUB_ENDPOINT=tcp://127.0.0.1:<PORT>
#
PUB_ENDPOINT="tcp://127.0.0.1:@MESSAGE_BROKER_SUB_PORT@"
SUB_ENDPOINT="tcp://127.0.0.1:@MESSAGE_BROKER_PUB_PORT@"

# this is the port number that the emulator listens to
#
Expand Down Expand Up @@ -61,14 +67,11 @@ MOTOR_AXIS="I 3 -1000 1000 0 na 300.0"
#

# -----------------------------------------------------------------------------
# TELEM_PROVIDER=( <name> <port> )
# SUBSCRIBE_TO=( <name> <endpoint> )
#
# This is a list of telemetry providers where <name> is the daemon name,
# and <port> is the port on which to send the telemetry request.
# This is a list of pub/sub sources to subscribe to, where <name> is the daemon
# name and <endpoint> is its ZeroMQ publish endpoint.
# Provide one per line.
#
TELEM_PROVIDER=(tcsd @TCSD_NB_PORT@)
TELEM_PROVIDER=(thermald @THERMALD_NB_PORT@)
#
SUBSCRIBE_TO=(tcsd "tcp://127.0.0.1:@TCSD_PUB_PORT@")
SUBSCRIBE_TO=(thermald "tcp://127.0.0.1:@THERMALD_PUB_PORT@")
33 changes: 17 additions & 16 deletions Config/sequencerd.cfg.in
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ CAMERA_EPILOGUE=(close)
# slit init and shutdown states
# formatted as (width offset)
#
SLIT__INIT=(0.5 3.0)
SLIT__INIT=(0.4 3.0)
SLIT__SHUTDOWN=

# ACAM init and shutdown states
Expand All @@ -107,7 +107,7 @@ CALIB_DOOR__SHUTDOWN=close
# Virtual Slit Mode slit offset positions
# units are arcseconds
#
VIRTUAL_SLITW_ACQUIRE=0.5 # slit width during acquire
VIRTUAL_SLITW_ACQUIRE=0.4 # slit width during acquire
VIRTUAL_SLITO_ACQUIRE=-3.0 # slit offset for acquiring target
VIRTUAL_SLITO_EXPOSE=3.0 # slit offset for science exposure

Expand Down Expand Up @@ -162,29 +162,30 @@ ACQUIRE_MIN_REPEAT=2 # minimum number of sequential successful a
ACQUIRE_TCS_MAX_OFFSET=60 # the maximum allowable offset sent to the TCS, in arcsec

# Calibration Settings
# CAL_TARGET=(name caldoor calcover U G R I lampthar lampfear lampbluc lampredc lolamp hilamp mod1 mod2 ... mod6)
# CAL_TARGET=(name caldoor calcover U G R I lampthar lampfear lampbluc lampredc lolamp hilamp mod1 mod2 ... mod6 imgtype)
#
# where name must be "DEFAULT" or start with "CAL_"
# caldoor = open | close
# calcover = open | close
# U,G,R,I = on | off # indicates which channels to enable/disable
# lamp* = on | off # lamp power
# mod* = on | off # lamp modulator
# for a total of 19 required parameters
# imgtype = <imgtype> # FITS IMGTYPE keyword
# for a total of 20 required parameters
# name=SCIENCE defines science target operation
#
# name door cover U G R I thar fear bluc redc llmp hlmp mod1 mod2 mod3 mod4 mod5 mod6
CAL_TARGET=(CAL_THAR open close on on on on on on on on off off off off off off off on )
CAL_TARGET=(CAL_FEAR open close on on on on on on on on off off on off off off off off)
CAL_TARGET=(CAL_THAR_UG open close on on off off on on on on off off off off off off off on )
CAL_TARGET=(CAL_FEAR_UG open close on on off off on on on on off off on off off off off off)
CAL_TARGET=(CAL_CONTR open close on on on on on on on on off off off off off on off off)
CAL_TARGET=(CAL_CONTB open close on on on on on on on on off off off off off off on off)
CAL_TARGET=(CAL_DOME close open on on on on off off off off off on off off off off off off)
CAL_TARGET=(CAL_DOME_UG close open on on off off off off off off off on off off off off off off)
CAL_TARGET=(CAL_BIAS close close on on on on off off off off off off off off off off off off)
CAL_TARGET=(CAL_DARK close close on on on on off off off off off off off off off off off off)
CAL_TARGET=(SCIENCE close open on on on on off off off off off off off off off off off off)
# name door cover U G R I thar fear bluc redc llmp hlmp mod1 mod2 mod3 mod4 mod5 mod6 imgtype
CAL_TARGET=(CAL_THAR open close on on on on on on on on off off off off off off off on THAR )
CAL_TARGET=(CAL_FEAR open close on on on on on on on on off off on off off off off off FEAR )
CAL_TARGET=(CAL_THAR_UG open close on on off off on on on on off off off off off off off on THAR )
CAL_TARGET=(CAL_FEAR_UG open close on on off off on on on on off off on off off off off off FEAR )
CAL_TARGET=(CAL_CONTR open close on on on on on on on on off off off off off on off off CONT )
CAL_TARGET=(CAL_CONTB open close on on on on on on on on off off off off off off on off CONT )
CAL_TARGET=(CAL_DOME close open on on on on off off off off off on off off off off off off DOMEFLAT)
CAL_TARGET=(CAL_DOME_UG close open on on off off off off off off off on off off off off off off DOMEFLAT)
CAL_TARGET=(CAL_BIAS close close on on on on off off off off off off off off off off off off BIAS )
CAL_TARGET=(CAL_DARK close close on on on on off off off off off off off off off off off off DARK )
CAL_TARGET=(SCIENCE close open on on on on off off off off off off off off off off off off SCI )

# miscellaneous
#
Expand Down
17 changes: 10 additions & 7 deletions Config/thermald.cfg.in
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,13 @@ NBPORT=@THERMALD_NB_PORT@ # thermald server non-blocking port
DAEMON=yes # run as daemon?
ASYNCPORT=@MESSAGEPORT@ # asynchronous message port
ASYNCGROUP=239.1.1.234 # asynchronous message broadcast group
PUBLISHER_PORT="tcp://127.0.0.1:@THERMALD_PUB_PORT@" # my zeromq pub port

# Message pub/sub
# PUB_ENDPOINT=tcp://127.0.0.1:<PORT>
# SUB_ENDPOINT=tcp://127.0.0.1:<PORT>
#
PUB_ENDPOINT="tcp://127.0.0.1:@MESSAGE_BROKER_SUB_PORT@"
SUB_ENDPOINT="tcp://127.0.0.1:@MESSAGE_BROKER_PUB_PORT@"

# database configuration
#
Expand Down Expand Up @@ -102,15 +108,12 @@ CAMP_CHAN="22 TFLEXCON_UR"
CAMP_CHAN="23 TACAM"

# -----------------------------------------------------------------------------
# TELEM_PROVIDER=( <name> <port> )
# SUBSCRIBE_TO=( <name> <endpoint> )
#
# This is a list of telemetry providers where <name> is the daemon name,
# and <port> is the port on which to send the telemetry request.
# This is a list of pub/sub sources to subscribe to, where <name> is the daemon
# name and <endpoint> is its ZeroMQ publish endpoint.
# Provide one per line.
#
TELEM_PROVIDER=(acamd @ACAMD_NB_PORT@)
TELEM_PROVIDER=(slicecamd @SLICECAMD_NB_PORT@)
#
SUBSCRIBE_TO=(acamd "tcp://127.0.0.1:@ACAMD_PUB_PORT@")
SUBSCRIBE_TO=(slicecamd "tcp://127.0.0.1:@SLICECAMD_PUB_PORT@")

10 changes: 3 additions & 7 deletions LKS/lks.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -172,9 +172,9 @@ namespace LKS {
long retval=0;

#ifdef LOGLEVEL_DEBUG
// message << "[DEBUG] send to LKS " << this->model << " (" << this->name << ") on socket "
// << this->sock.gethost() << "/" << this->sock.getport() << ": " << cmd;
// logwrite( function, message.str() );
message << "[DEBUG] send to LKS " << this->model << " (" << this->name << ") on socket "
<< this->sock.gethost() << "/" << this->sock.getport() << ": " << cmd;
logwrite( function, message.str() );
#endif

std::lock_guard<std::mutex> lock( this->mtx );
Expand Down Expand Up @@ -228,10 +228,6 @@ namespace LKS {

retstring = reply;

#ifdef LOGLEVEL_DEBUG
// message << " reply=" << reply; logwrite( function, message.str() );
#endif

return( error );
}
/***** LKS::Interface::send_command *****************************************/
Expand Down
2 changes: 1 addition & 1 deletion PI/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ set( PI_DIR ${PROJECT_BASE_DIR}/PI )

set( CMAKE_CXX_STANDARD 17 )

add_definitions( -Wall -ansi -O1 -Wno-variadic-macros -ggdb )
add_definitions( -Wall -O1 -Wno-variadic-macros -ggdb )

include_directories( ${PROJECT_BASE_DIR}/utils )
include_directories( ${PROJECT_BASE_DIR}/common )
Expand Down
39 changes: 21 additions & 18 deletions PI/pi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -424,6 +424,11 @@ namespace Physik_Instrumente {

this->thread_error.store( NO_ERROR ); // initialize the thread_error state.

// vector of threads to perform the operation for each motor
//
std::vector<std::thread> workers;
workers.reserve(motornames.size());

for ( size_t n=0; n < motornames.size(); n++ ) {

auto name = motornames[n];
Expand All @@ -434,16 +439,15 @@ namespace Physik_Instrumente {
// Spawn a thread to performm the move.
// If there is more than one then they can be done in parallel.
//
std::thread( _dothread_moveto, std::ref( *this ), name, addr, axis, position ).detach();
this->motors_running++;
try {
workers.emplace_back( _dothread_moveto, std::ref( *this ), name, addr, axis, position );
}
catch(...) { for ( auto &t : workers ) t.join(); throw; }
}

// wait for the threads to finish
// TODO add a way to abort this
//
while ( this->motors_running != 0 ) {
std::this_thread::sleep_for( std::chrono::milliseconds( 1 ) );
}
for ( auto &t : workers ) t.join();

logwrite( function, "move(s) complete" );

Expand Down Expand Up @@ -685,8 +689,6 @@ namespace Physik_Instrumente {

iface.thread_error.fetch_or( error ); // preserve any error returned

--iface.motors_running; // atomically decrement the number of motors waiting

message.str(""); message << "completed move " << name << ( error!=NO_ERROR ? " with error" : "" );
logwrite( function, message.str() );

Expand Down Expand Up @@ -811,6 +813,11 @@ namespace Physik_Instrumente {
//
this->thread_error.store( NO_ERROR );

// vector of threads to perform the operation for each motor
//
std::vector<std::thread> workers;
workers.reserve(name_list.size());

// Now loop through the built up list of motor names
//
for ( const auto &name : name_list ) {
Expand All @@ -823,22 +830,22 @@ namespace Physik_Instrumente {
message << " }";
logwrite( function, message.str() );
retstring="unknown_motor";
for ( auto &t : workers ) t.join(); // join any workers spawned before returning
return ERROR;
}

// Spawn a thread to performm the home move.
// If there is more than one then they can be done in parallel.
//
std::thread( _dothread_home, std::ref( *this ), name ).detach();
this->motors_running++;
try {
workers.emplace_back( _dothread_home, std::ref( *this ), name );
}
catch(...) { for ( auto &t : workers ) t.join(); throw; }
}

// wait for the threads to finish
// TODO add a way to abort this
//
while ( this->motors_running != 0 ) {
std::this_thread::sleep_for( std::chrono::milliseconds( 1 ) );
}
for ( auto &t : workers ) t.join();

logwrite( function, "home complete" );

Expand Down Expand Up @@ -878,14 +885,12 @@ namespace Physik_Instrumente {
message.str(""); message << "ERROR: name \"" << name << "\" not in motormap: " << e.what();
logwrite( function, message.str() );
iface.thread_error.fetch_or( ERROR ); // preserve this error
--iface.motors_running; // atomically decrement the number of motors waiting
return;
}

if ( reftype.empty() ) {
message.str(""); message << "NOTICE referencing not available for " << name;
logwrite( function, message.str() );
--iface.motors_running; // atomically decrement the number of motors waiting
return;
}

Expand Down Expand Up @@ -937,8 +942,6 @@ namespace Physik_Instrumente {

iface.thread_error.fetch_or( error ); // preserve any error returned

--iface.motors_running; // atomically decrement the number of motors waiting

message.str(""); message << "completed home " << name << ( error!=NO_ERROR ? " with error" : "" );
logwrite( function, message.str() );

Expand Down
Loading
Loading