Commit e3b80911 authored by Jeroen Vreeken's avatar Jeroen Vreeken
Browse files

Move servo state and safety blocks to the command protocol

Various small fixes
Add command protocol to websocket
Add cross compiling with 'TARGET='
Fix some issues with ARM
parent cbe16b01
......@@ -145,7 +145,7 @@ int main(int argc, char **argv)
struct command_server *cmd_srv;
struct status_server *stat_srv;
struct weather *weather;
double az, el, prev_az;
double az, el, prev_az = 0;
time_t lastt = 0;
......@@ -244,6 +244,8 @@ int main(int argc, char **argv)
entry.t.tv_nsec = 0;
entry.value.f = az * 2 * M_PI / 360.0;
command_send(sp_command_az, &entry);
if (el < 0.0)
el = 0.0;
entry.value.f = el * 2 * M_PI / 360.0;
command_send(sp_command_el, &entry);
}
......
......@@ -143,7 +143,7 @@ int main(int argc, char **argv)
struct weather *weather;
struct command_server *cmd_srv;
struct status_server *stat_srv;
double az, el, prev_az;
double az, el, prev_az = 0;;
time_t lastt = 0;
......@@ -239,6 +239,8 @@ int main(int argc, char **argv)
entry.t.tv_nsec = 0;
entry.value.f = az * 2 * M_PI / 360.0;
command_send(sp_command_az, &entry);
if (el < 0.0)
el = 0.0;
entry.value.f = el * 2 * M_PI / 360.0;
command_send(sp_command_el, &entry);
}
......
all:
@$(MAKE) --no-print-directory -C ../../.. targets_console/console/mod_websocket_dt
......@@ -4,10 +4,11 @@ MOD_WEBSOCKET_DT_SRCS=$(DIR)/mod_websocket_dt.c
MOD_WEBSOCKET_DT_OBJS=$(MOD_WEBSOCKET_DT_SRCS:.c=.lo)
$(MOD_WEBSOCKET_DT_OBJS): CFLAGS += -Wall -g
$(DIR)/mod_websocket_dt.so_LDFLAGS += -module -rpath /usr/lib/apache2/modules -ltrace -lutils -Xcompiler -shared
$(DIR)/mod_websocket_dt.so: libtrace.la libutils.la
$(DIR)/mod_websocket_dt.so_LDFLAGS += -module -rpath /usr/lib/apache2/modules -ltrace -lutils -lcommand -Xcompiler -shared
$(DIR)/mod_websocket_dt.so: libtrace.la libutils.la libcommand.la
$(DIR)/mod_websocket_dt.so: $(MOD_WEBSOCKET_DT_OBJS)
SRCS += $(MOD_WEBSOCKET_DT_SRCS)
TARGETS += $(MOD_WEBSOCKET_DT_TARGETS)
CLEAN += $(MOD_WEBSOCKET_DT_TARGETS) $(MOD_WEBSOCKET_DT_OBJS)
CLEAN += $(DIR)/.libs
/*
Copyright Jeroen Vreeken (pe1rxq@amsat.org), 2013
Copyright Jeroen Vreeken (jeroen@vreeken.net), 2013, 2014
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
......@@ -26,6 +26,7 @@
#include <errno.h>
#include <trace/trace.h>
#include <command/command.h>
#include <websocket_plugin.h>
#include <utils/tcp_connect.h>
......@@ -33,12 +34,18 @@
#include <dt_port_numbers.h>
#include <utils/dt_host.h>
static char *command_host = "localhost";
static int command_port = 11000;
struct plugin_private {
const WebSocketServer *server;
pthread_t *threads;
int nr_threads;
struct command **commands;
int nr_commands;
bool connected;
};
......@@ -54,6 +61,52 @@ static void *on_connect(const WebSocketServer *server)
return priv;
}
static struct command *get_command(struct plugin_private *priv,
char *name, char *id, enum command_value_type vtype)
{
struct command *command = NULL;
int i;
for (i = 0; i < priv->nr_commands; i++) {
if (!strcmp(priv->commands[i]->name, name)) {
command = priv->commands[i];
break;
}
}
if (!command) {
struct command **cl;
cl = realloc(priv->commands,
sizeof(struct command *) * (priv->nr_commands + 1));
if (!cl)
goto err;
priv->commands = cl;
command = command_open_simple(command_host, command_port,
name, "override", vtype);
if (!command)
goto err;
cl[priv->nr_commands] = command;
priv->nr_commands++;
}
err:
return command;
}
static void cleanup_command(struct plugin_private *priv)
{
int i;
for (i = 0; i < priv->nr_commands; i++) {
command_free(priv->commands[i]);
}
free(priv->commands);
priv->commands = NULL;
priv->nr_commands = 0;
}
static void handler_trace_value(struct trace *trace,
struct trace_value *value)
{
......@@ -405,6 +458,29 @@ static size_t on_message(void *plugin_private,
do_command(ident, command);
free(ident);
} else if (!strcmp(cmd, "controller_command")) {
char *name;
char *type;
struct command_entry entry;
struct command *command;
enum command_value_type vtype;
sscanf(text, "%*s %as %as", &name, &type);
if (!strcmp(type, "bool")) {
int v;
sscanf(text, "%*s %*s %*s %d", &v);
entry.value.b = v;
entry.type = COMMAND_PTYPE_SETPOINT;
vtype = COMMAND_VALUE_TYPE_BOOL;
}
free(type);
command = get_command(priv, name, "override", vtype);
if (command) {
command_send(command, &entry);
}
free(name);
} else if (!strcmp(cmd, "shell")) {
char *command;
......@@ -434,6 +510,7 @@ static void on_disconnect(void *plugin_private, const WebSocketServer *server)
for (i = 0; i < priv->nr_threads; i++) {
pthread_join(priv->threads[i], NULL);
}
cleanup_command(priv);
free(priv);
}
......
......@@ -34,7 +34,10 @@ $(DIR)/test-003: libpredict.la
$(DIR)/test-003: $(DIR)/test-003.o
PREDICTLIB_SRCS += $(DIR)/test-003.c
PREDICTLIB_OBJS := $(PREDICTLIB_SRCS:.c=.lo)
PREDICTLIB_OBJS := $(PREDICTLIB_SRCS:.c=.lo) \
$(DIR)/test-001.o \
$(DIR)/test-002.o \
$(DIR)/test-003.o
SRCS += $(PREDICTLIB_SRCS)
TARGETS += $(PREDICTLIB_TARGETS)
......
......@@ -61,33 +61,25 @@ struct spg {
char *name;
};
struct spg *spgs = NULL;
static struct spg *spgs = NULL;
static int spgs_nr = 0;
struct spg_client *clients = NULL;
static struct spg_client *clients = NULL;
typedef union {
float f;
uint32_t u;
} float32_t;
static char *command_host = "localhost";
static int future_hold = 3;
static char *command_id = "console/spg_auth";
static char *logfile = "spg_auth.log";
char *command_host = "localhost";
int future_hold = 3;
char *command_id = "console/spg_auth";
static float az_offset = 0.0;
static float el_offset = 0.0;
char *logfile = "spg_auth.log";
static char current_auth[100] = { "none" };
float az_offset = 0.0;
float el_offset = 0.0;
char current_auth[100] = { "none" };
int fd_listen;
int fd_console;
int fd_offset;
static int fd_listen;
static struct command_pkt *list_pkt;
......@@ -106,7 +98,7 @@ static void handler_name(struct command *command, char *name)
}
int handle_offsets(char *command)
static int handle_offsets(char *command)
{
sscanf(command, "%f %f", &az_offset, &el_offset);
log_send(LOG_T_DEBUG, "New offset: %e %e\n", az_offset, el_offset);
......@@ -114,12 +106,13 @@ int handle_offsets(char *command)
return 0;
}
void try_command(struct command *command)
static void try_command(struct command *command)
{
struct spg_client *client = command->private;
struct command_entry *entry = &client->entry;
if (!client->command->id || !client->spg || strcmp(client->command->id, current_auth)) {
if (!client->command->id || !client->spg || (
strcmp(client->command->id, current_auth) && strcmp(client->command->id, "override"))) {
client->pending = 0;
return;
}
......@@ -141,10 +134,20 @@ void try_command(struct command *command)
}
}
if (!strcmp(client->spg->name, "Elevation_Setpoint")) {
float value;
switch(entry->type) {
case COMMAND_PTYPE_SETPOINT:
case COMMAND_PTYPE_SETPOINT_TIME:
entry->value.f += el_offset;
value = entry->value.f + el_offset;
/* Only apply offset if we stay above zero.
otherwise leave the original value.
*/
if (value >= 0.0) {
entry->value.f = value;
} else if (entry->value.f > 0.0) {
entry->value.f = 0.0;
}
default:
break;
}
......@@ -156,7 +159,7 @@ void try_command(struct command *command)
log_send(LOG_T_DEBUG, "Done command");
}
void handler_entry(struct command *command, struct command_entry *entry)
static void handler_entry(struct command *command, struct command_entry *entry)
{
struct spg_client *client = command->private;
......@@ -166,7 +169,7 @@ void handler_entry(struct command *command, struct command_entry *entry)
try_command(command);
}
void handler_close(struct command *command)
static void handler_close(struct command *command)
{
struct spg_client *client = command->private;
......@@ -175,7 +178,7 @@ void handler_close(struct command *command)
client->cleanup = true;
}
void new_connection(void)
static void new_connection(void)
{
int fd;
struct spg_client *new_client;
......@@ -216,7 +219,7 @@ err_client:
int handle_con_client(char *command)
static int handle_con_client(char *command)
{
if (strcmp(current_auth, command)) {
int i;
......@@ -229,9 +232,12 @@ int handle_con_client(char *command)
for (i = 0; i < spgs_nr; i++) {
struct command_entry entry;
entry.type = COMMAND_PTYPE_SPEED;
entry.value.f = 0.0;
command_send(spgs[i].spg_cmd, &entry);
if (!strcmp(spgs[i].name, "Azimuth_Setpoint") ||
!strcmp(spgs[i].name, "Elevation_Setpoint")) {
entry.type = COMMAND_PTYPE_SPEED;
entry.value.f = 0.0;
command_send(spgs[i].spg_cmd, &entry);
}
}
log_send(LOG_T_INFO, "Changed setpoint source to: %s",
......@@ -240,7 +246,7 @@ int handle_con_client(char *command)
return 0;
}
void update_status(struct status_server *stat_srv)
static void update_status(struct status_server *stat_srv)
{
static time_t last = 0;
time_t now;
......
/*
Javascript sending controller commands
Copyright Jeroen Vreeken (pe1rxq@amsat.org), 2014
Copyright Stichting C.A. Muller Radioastronomiestation, 2014
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
var controller_command_loaded;
if (!controller_command_loaded) {
controller_command_loaded = true;
function controller_command (name, vtype)
{
this.send = function send (value)
{
dt_websocket_send("controller_command " + name + " " + vtype + " " + value);
}
}
}
......@@ -238,6 +238,10 @@ dt_ui_element.prototype.text_set = function (text)
if (this.parent)
this.parent.room(this);
}
dt_ui_element.prototype.text_get = function ()
{
return this.element.innerHTML;
}
dt_ui_element.prototype.wrap_set = function (wrap, pre)
{
if (!wrap) {
......@@ -334,24 +338,32 @@ function dt_ui_window_hide(elementid)
this.hide_ui.top_set(0);
this.hide_ui.left_set(0);
this.hide_ui.text_set("hide");
this.hide_ui.text_set("^");
this.hide_ui.padding_height = 0;
var dt_ui_window_hide_this = this;
var dt_ui_window_hide_visible = true;
var dt_ui_window_hide_height;
var dt_ui_window_hide_width;
this.hide_ui.onclick = function(elem) {
if (dt_ui_window_hide_visible) {
dt_ui_window_hide_height =
dt_ui_window_hide_this.height_get();
dt_ui_window_hide_width =
dt_ui_window_hide_this.width_get();
dt_ui_window_hide_this.height_set(
dt_ui_window_hide_this.title.height_get());
dt_ui_window_hide_this.hide_ui.text_set("show");
dt_ui_window_hide_this.width_set(
dt_ui_window_hide_this.title.width_get());
dt_ui_window_hide_this.hide_ui.text_set("+");
} else {
dt_ui_window_hide_this.height_set(
dt_ui_window_hide_height);
dt_ui_window_hide_this.hide_ui.text_set("hide");
dt_ui_window_hide_this.width_set(
dt_ui_window_hide_width);
dt_ui_window_hide_this.hide_ui.text_set("^");
}
dt_ui_window_hide_visible = !dt_ui_window_hide_visible;
......@@ -364,6 +376,7 @@ dt_ui_window_hide.prototype.title_set = function (titletext)
{
dt_ui_window.prototype.title_set.call(this, titletext);
this.hide_ui.left_set(this.title.width_get());
this.hide_ui.height_set(this.title.height_get());
}
dt_ui_window_hide.prototype.hide = function()
{
......
......@@ -178,98 +178,8 @@
<td>
<div style="background: lightgrey; border:thin solid black" width="50%"
id="Offset">
<i>
Offset
</i>
<div id="Offset_show" align="right" style="float:right"></div>
<table border="0" id="Offset_table">
<tr>
<td></td>
<th>Azimuth</th>
<th>Elevation</th>
</tr>
<tr>
<th>
Current Offset:
</th>
<td>
<div id="Azimuth_Offset"></div>
</td>
<td>
<div id="Elevation_Offset"></div>
</td>
</tr>
<tr>
<th colspan="3">
New Offset:
</th>
</tr>
<tr>
<th colspan="3">
<span id="Offset_Reset"></span>
</th>
</tr>
<tr>
<th>
<span id="Offset_Set1"></span>
</th>
<td>
<input type="text" width="4" id="az_offset1"
onchange="check_floatval('az_offset1');">
</td>
<td>
<input type="text" width="4" id="el_offset1"
onchange="check_floatval('el_offset1');">
</td>
</tr>
<tr>
<th>
<span id="Offset_Set2"></span>
</th>
<td>
<input type="text" width="4" id="az_offset2"
onchange="check_floatval('az_offset2');">
</td>
<td>
<input type="text" width="4" id="el_offset2"
onchange="check_floatval('el_offset2');">
</td>
</tr>
<tr>
<th>
<span id="Offset_Set3"></span>
</th>
<td>
<input type="text" width="4" id="az_offset3"
onchange="check_floatval('az_offset3');">
</td>
<td>
<input type="text" width="4" id="el_offset3"
onchange="check_floatval('el_offset3');">
</td>
</tr>
<tr>
<th>
<span id="Offset_Set4"></span>
</th>
<td>
<input type="text" width="4" id="az_offset4"
onchange="check_floatval('az_offset4');">
</td>
<td>
<input type="text" width="4" id="el_offset4"
onchange="check_floatval('el_offset4');">
</td>
</tr>
</table>
</p>
</div>
<div id="offset"></div>
</td>
<!--
......@@ -293,25 +203,7 @@
</tr>
</table>
<div style="background: lightgrey; border:thin solid black"
id="Log_box">
<div style="height: 30px">
<div id="Log_show" align="right" style="float:right">show</div>
<i>
Controller log<br>
</i>
</div>
<div id="log"
style='background: white; border:thin solid black; height:150px;
font-family: monospace; font-size:100%; white-space: pre ;
overflow:scroll'>
</div>
</div>
<div id="log"></div>
<p>
......@@ -374,11 +266,11 @@
/* 'includes' */
eval(load("dt_ui.js"));
eval(load("trace.js"));
eval(load("shell.js"));
eval(load("azel.js"));
eval(load("j2000.js"));
eval(load("status.js"));
eval(load("command.js"));
eval(load("controller_command.js"));
eval(load("manual.js"));
eval(load("sun.js"));
eval(load("moon.js"));
......@@ -389,6 +281,7 @@ eval(load("utils.js"));
eval(load("offset.js"));
eval(load("model.js"));
eval(load("dt_websocket.js"));
eval(load("log.js"));
new dt_websocket("ws://"+ window.location.host +"/dt");
......@@ -397,8 +290,6 @@ new dt_websocket("ws://"+ window.location.host +"/dt");
*/
var trace_url = "trace.cgi";
var shell_url = "shell.cgi";
var offset_url = "command.cgi_offset";
......@@ -418,15 +309,17 @@ var sat_spg = new sat("spg_sat");
var auth_win = new authorization("authorization");
var model_win = new model("model");
var offset_win = new offset("offset");
function offset_cb(azimuth_off, elevation_off)
{
Azimuth_Offset_value(azimuth_off);
Elevation_Offset_value(elevation_off);
offset_win.set_offset(azimuth_off, elevation_off);
}
auth_win.offset_cb = offset_cb;
var log_win = new log("log");
auth_win.tracker_window_set("console/azel", azel_spg);
auth_win.tracker_window_set("console/j2000tracker", j2000_spg);
auth_win.tracker_window_set("console/moontracker", moon_spg);
......@@ -501,18 +394,25 @@ function check_floatval(element)
Azimuth
*/
var azimuth_enable_param = 'controller \'params { { "azimuth_servo_state", "enabled", (int)1 } } \' ';
var azimuth_elevation_disable_param = 'controller \'params { { "azimuth_servo_state", "enabled", (int)0 } { "elevation_servo_state", "enabled", (int)0 } { "elevation_safety", "recover", (int)0 } } \' ';
var azimuth_enable_command = new controller_command("azimuth_servo_state", "bool");
var elevation_enable_command = new controller_command("elevation_servo_state", "bool");
var elevation_recover_command = new controller_command("elevation_safety", "bool");
var azimuth_disable = new dt_button("azimuth_elevation_disable");
azimuth_disable.background("red");
azimuth_disable.value("Disable");
azimuth_disable.