Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
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
3 changes: 2 additions & 1 deletion camerad/astrocam.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,9 @@ namespace AstroCam {
nlohmann::json jmessage_out;

// build JSON message with my telemetry
jmessage_out[Key::SOURCE] = "camerad";
jmessage_out[Key::SOURCE] = Topic::CAMERAD;
jmessage_out[Key::Camerad::READY] = this->can_expose.load();
jmessage_out[Key::Camerad::SHUTTERTIME] = this->camera.shutter.get_duration();

// publish JSON message
try {
Expand Down
2 changes: 1 addition & 1 deletion camerad/camerad.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -339,7 +339,7 @@ void async_main(Network::UdpSocket sock) {
}

while (1) {
std::string message = server.camera.async.dequeue(); // get the latest message from the queue (blocks)
std::string_view message = server.camera.async.dequeue(); // get the latest message from the queue (blocks)
retval = sock.Send(message); // transmit the message
if (retval < 0) {
std::stringstream errstm;
Expand Down
10 changes: 5 additions & 5 deletions common/common.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ namespace Common {
* @param[in] message string to write
*
*/
void Queue::enqueue_and_log(std::string function, std::string message) {
void Queue::enqueue_and_log(std::string_view function, std::string_view message) {
std::lock_guard<std::mutex> lock(queue_mutex);
message_queue.push(message);
notifier.notify_one();
Expand All @@ -77,9 +77,9 @@ namespace Common {
* @param[in] message string to write
*
*/
void Queue::enqueue_and_log( std::string tag, std::string function, std::string message ) {
void Queue::enqueue_and_log( std::string_view tag, std::string_view function, std::string_view message ) {
std::lock_guard<std::mutex> lock(queue_mutex);
std::stringstream qmessage;
std::ostringstream qmessage;
qmessage << tag << ":" << message;
message_queue.push(qmessage.str());
notifier.notify_one();
Expand All @@ -98,12 +98,12 @@ namespace Common {
* If the queue is empty, wait untill an element is avaiable.
*
*/
std::string Queue::dequeue(void) {
std::string_view Queue::dequeue(void) {
std::unique_lock<std::mutex> lock(queue_mutex);
while(message_queue.empty()) {
notifier.wait(lock); // release lock as long as the wait and reaquire it afterwards.
}
std::string message = message_queue.front();
std::string_view message = message_queue.front();
message_queue.pop();
return message;
}
Expand Down
10 changes: 5 additions & 5 deletions common/common.h
Original file line number Diff line number Diff line change
Expand Up @@ -1112,7 +1112,7 @@ namespace Common {
*/
class Queue {
private:
std::queue<std::string> message_queue;
std::queue<std::string_view> message_queue;
mutable std::mutex queue_mutex;
std::condition_variable notifier;
bool is_running;
Expand All @@ -1123,10 +1123,10 @@ namespace Common {
void service_running(bool state) { this->is_running = state; }; ///< set service running
bool service_running() { return this->is_running; }; ///< is the service running?

void enqueue_and_log(std::string function, std::string message);
void enqueue_and_log(std::string tag, std::string function, std::string message);
void enqueue(std::string message); ///< push an element into the queue.
std::string dequeue(void); ///< pop an element from the queue
void enqueue_and_log(std::string_view function, std::string_view message);
void enqueue_and_log(std::string_view tag, std::string_view function, std::string_view message);
void enqueue(std::string message_view); ///< push an element into the queue.
std::string_view dequeue(void); ///< pop an element from the queue
};
/**************** Common::Queue *********************************************/

Expand Down
22 changes: 21 additions & 1 deletion common/message_keys.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@ namespace Key {
}

namespace Camerad {
inline const std::string READY = "ready";
inline const std::string READY = "ready";
inline const std::string SHUTTERTIME = "shuttime_sec";
}

namespace Acamd {
Expand All @@ -50,4 +51,23 @@ namespace Key {
inline const std::string FINEACQUIRE_LOCKED = "fineacquire_locked";
inline const std::string FINEACQUIRE_RUNNING = "fineacquire_running";
}

namespace Slitd {
inline const std::string SLITPOSA = "slitposa";
inline const std::string SLITPOSB = "slitposb";
inline const std::string SLITW = "slitw";
inline const std::string SLITO = "slito";
inline const std::string ISOPEN = "isopen";
inline const std::string ISHOME = "ishome";
}

namespace Tcsd {
inline const std::string TELRA = "telra";
inline const std::string TELDEC = "teldec";
inline const std::string ALT = "alt";
inline const std::string AZ = "az";
inline const std::string AIRMASS = "airmass";
inline const std::string CASANGLE = "casangle";
}

}
4 changes: 4 additions & 0 deletions common/sequencerd_commands.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,11 @@ const std::string SEQUENCERD_GUIDE = "guide";
const std::string SEQUENCERD_MODEXPTIME = "modexptime";
const std::string SEQUENCERD_ONTARGET = "ontarget";
const std::string SEQUENCERD_USERCONTINUE = "usercontinue";
const std::string SEQUENCERD_OP = "op";
const std::string SEQUENCERD_PAUSE = "pause";
const std::string SEQUENCERD_REPEAT = "repeat";
const std::string SEQUENCERD_RESUME = "resume";
const std::string SEQUENCERD_SCRIPT = "script";
const std::string SEQUENCERD_SHUTDOWN = "shutdown";
const std::string SEQUENCERD_START = "start";
const std::string SEQUENCERD_STARTONE = "startone";
Expand Down Expand Up @@ -54,11 +56,13 @@ const std::vector<std::string> SEQUENCERD_SYNTAX = {
SEQUENCERD_GUIDE,
SEQUENCERD_MODEXPTIME+" <exptime>",
SEQUENCERD_ONTARGET,
SEQUENCERD_OP,
SEQUENCERD_PAUSE,
SEQUENCERD_REPEAT,
SEQUENCERD_RESUME,
TELEMREQUEST+" [?]",
SEQUENCERD_USERCONTINUE,
SEQUENCERD_SCRIPT,
SEQUENCERD_SHUTDOWN,
SEQUENCERD_START,
SEQUENCERD_STARTONE,
Expand Down
2 changes: 2 additions & 0 deletions sequencerd/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ add_executable(sequencerd
${SEQUENCER_DIR}/sequencer_server.cpp
${SEQUENCER_DIR}/sequencer_interface.cpp
${SEQUENCER_DIR}/sequence_acquisition.cpp
${SEQUENCER_DIR}/sequence_wait.cpp
${SEQUENCER_DIR}/sequence_builder.cpp
${SEQUENCER_DIR}/sequence.cpp
${MYSQL_INCLUDES}
${PYTHON_DEV}
Expand Down
134 changes: 134 additions & 0 deletions sequencerd/command.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
/**
* @file command.h
* @brief header-only library for handling commands to daemons
* @details This provides a wrapper to form command and arg list strings.
* Also a wrapper that stores transition states, and validates that
* a command is allowed to be sent while in the current state.
* @author David Hale <dhale@astro.caltech.edu>
*
*/

#pragma once

#include <string>
#include <vector>
#include <unordered_map>
#include <stdexcept>

/***** Sequencer **************************************************************/
/**
* @brief namespace for the observation sequencer
*
*/
namespace Sequencer {

/**
* @brief wrapper to form string from command and arglist
*/
struct Command {
std::string name;
std::vector<std::string> arglist;

std::string str() const {
std::string strung = name;
for (const auto &arg : arglist) {
strung += " " + arg;
}
return strung;
}
};


/**
* @brief command specs right now just holds min/max number of allowed args
*/
struct CommandSpec {
int min_args;
int max_args;
};

using CommandSpecMap = std::unordered_map<std::string, CommandSpec>;


/**
* @brief structure contains command and states it can transition from->to
*/
template <typename State>
struct Transition {
State from;
std::string command;
State to;
};


/**
* @brief contains the functionality of the library
* @details This pairs specs and transitions with a command and holds
* the client object used to communiate with the daemon.
*/
template <typename State>
class CommandClient {
private:
Common::DaemonClient &client;
const CommandSpecMap &specs;
State state;
const std::vector<Transition<State>> &transitions;

void validate_args( const Command &cmd ) const {
auto it = specs.find( cmd.name );
if (it == specs.end()) throw std::runtime_error("unknown command: "+cmd.name);
int nargs = cmd.arglist.size();
if (nargs < it->second.min_args || nargs > it->second.max_args) {
throw std::runtime_error("invalid arg count for "+cmd.name);
}
}

void validate_order( const Command &cmd ) const {
for (const auto &transition : transitions) {
if (transition.from == state && transition.command == cmd.name) {
return;
}
}
throw std::runtime_error("invalid command order: "+cmd.name);
}

void advance_state( const Command &cmd ) {
for (const auto &transition : transitions) {
if (transition.from == state && transition.command == cmd.name) {
state = transition.to;
return;
}
}
}

public:
CommandClient( Common::DaemonClient &client,
const CommandSpecMap &specs,
State initial_state,
const std::vector<Transition<State>> &transitions )
: client(client),
specs(specs),
state(initial_state),
transitions(transitions) { }

/**
* @brief primary interface to sending commands
* @details This validates the number of args, validates the
* transition state, that this command is allowed to be used
* in the current state, and sends the command.
* @param[in] cmd Command struct contains command and arglist
* @return return value from the client
*
*/
long send( const Command &cmd ) {
validate_args( cmd );
validate_order( cmd );
long ret = client.command( cmd.str() );
advance_state( cmd );
return ret;
}

State get_state() const { return state; }
};
}
/***** Sequencer **************************************************************/
37 changes: 37 additions & 0 deletions sequencerd/command_rules.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@

#pragma once

#include "command.h"

#include <vector>

namespace Sequencer {

enum class CameraState {
IDLE,
READY,
EXPOSING,
READING
};

const CommandSpecMap camerad_specs = {
{ CAMERAD_ACTIVATE, {0, 4} },
{ CAMERAD_DEACTIVATE, {1, 4} },
{ CAMERAD_OPEN, {0, 1} },
{ CAMERAD_CLOSE, {0, 0} },
{ CAMERAD_EXPTIME, {0, 1} },
{ CAMERAD_EXPOSE, {0, 0} },
{ CAMERAD_READOUT, {0, 2} }
};

const std::vector<Transition<CameraState>> camerad_transitions = {
{ CameraState::IDLE, CAMERAD_OPEN, CameraState::READY },
{ CameraState::READY, CAMERAD_ACTIVATE, CameraState::READY },
{ CameraState::READY, CAMERAD_DEACTIVATE, CameraState::READY },
{ CameraState::READY, CAMERAD_EXPTIME, CameraState::READY },
{ CameraState::READY, CAMERAD_EXPOSE, CameraState::EXPOSING },
{ CameraState::EXPOSING, CAMERAD_READOUT, CameraState::READING },
{ CameraState::READING, CAMERAD_READOUT, CameraState::READY }
};

}
Loading