kopia lustrzana https://github.com/Hamlib/Hamlib
Refactor multicast publisher and rig poll routine. Create skeleton for multicast command server.
rodzic
fb03d095df
commit
c8c8869a3c
|
@ -2758,7 +2758,13 @@ struct rig_state {
|
|||
volatile int morse_data_handler_thread_run;
|
||||
void *morse_data_handler_priv_data;
|
||||
FIFO_RIG *fifo_morse;
|
||||
int port_multicast; /*!< May be different so this is initially a copy of rigctl'd port selection */
|
||||
char *multicast_data_addr; /*!< Multicast data UDP address for publishing rig data and state */
|
||||
int multicast_data_port; /*!< Multicast data UDP port for publishing rig data and state */
|
||||
char *multicast_cmd_addr; /*!< Multicast command server UDP address for sending commands to rig */
|
||||
int multicast_cmd_port; /*!< Multicast command server UDP port for sending commands to rig */
|
||||
|
||||
volatile int multicast_receiver_run;
|
||||
void *multicast_receiver_priv_data;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
54
src/conf.c
54
src/conf.c
|
@ -92,8 +92,8 @@ static const struct confparams frontend_cfg_params[] =
|
|||
},
|
||||
{
|
||||
TOK_POLL_INTERVAL, "poll_interval", "Rig state poll interval in milliseconds",
|
||||
"Polling interval in milliseconds for transceive emulation, value of 0 disables polling",
|
||||
"0", RIG_CONF_NUMERIC, { .n = { 0, 1000000, 1 } }
|
||||
"Polling interval in milliseconds for transceive emulation, defaults to 1000, value of 0 disables polling",
|
||||
"1000", RIG_CONF_NUMERIC, { .n = { 0, 1000000, 1 } }
|
||||
},
|
||||
{
|
||||
TOK_PTT_TYPE, "ptt_type", "PTT type",
|
||||
|
@ -190,6 +190,26 @@ static const struct confparams frontend_cfg_params[] =
|
|||
"Add Hz to VFOB/Sub frequency set",
|
||||
"0", RIG_CONF_NUMERIC, { .n = {0, 1e12, 1}}
|
||||
},
|
||||
{
|
||||
TOK_MULTICAST_DATA_ADDR, "multicast_data_addr", "Multicast data UDP address",
|
||||
"Multicast data UDP address for publishing rig data and state, value of 0.0.0.0 disables multicast data publishing",
|
||||
"224.0.0.1", RIG_CONF_STRING,
|
||||
},
|
||||
{
|
||||
TOK_MULTICAST_DATA_PORT, "multicast_data_port", "Multicast data UDP port",
|
||||
"Multicast data UDP port for publishing rig data and state",
|
||||
"4532", RIG_CONF_NUMERIC, { .n = { 0, 1000000, 1 } }
|
||||
},
|
||||
{
|
||||
TOK_MULTICAST_CMD_ADDR, "multicast_cmd_addr", "Multicast command server UDP address",
|
||||
"Multicast command UDP address for sending commands to rig, value of 0.0.0.0 disables multicast command server",
|
||||
"224.0.0.2", RIG_CONF_STRING,
|
||||
},
|
||||
{
|
||||
TOK_MULTICAST_CMD_PORT, "multicast_cmd_port", "Multicast command server UDP port",
|
||||
"Multicast data UDP port for sending commands to rig",
|
||||
"4532", RIG_CONF_NUMERIC, { .n = { 0, 1000000, 1 } }
|
||||
},
|
||||
|
||||
{ RIG_CONF_END, NULL, }
|
||||
};
|
||||
|
@ -608,7 +628,11 @@ static int frontend_set_conf(RIG *rig, token_t token, const char *val)
|
|||
break;
|
||||
|
||||
case TOK_POLL_INTERVAL:
|
||||
rs->poll_interval = atof(val);
|
||||
if (1 != sscanf(val, "%ld", &val_i))
|
||||
{
|
||||
return -RIG_EINVAL;
|
||||
}
|
||||
rs->poll_interval = val_i;
|
||||
// Make sure cache times out before next poll cycle
|
||||
rig_set_cache_timeout_ms(rig, HAMLIB_CACHE_ALL, atol(val));
|
||||
break;
|
||||
|
@ -735,7 +759,31 @@ static int frontend_set_conf(RIG *rig, token_t token, const char *val)
|
|||
rig_debug(RIG_DEBUG_VERBOSE, "%s: offset_vfob=%ld\n", __func__, val_i);
|
||||
break;
|
||||
|
||||
case TOK_MULTICAST_DATA_ADDR:
|
||||
rs->multicast_data_addr = strdup(val);
|
||||
break;
|
||||
|
||||
case TOK_MULTICAST_DATA_PORT:
|
||||
if (1 != sscanf(val, "%ld", &val_i))
|
||||
{
|
||||
return -RIG_EINVAL;
|
||||
}
|
||||
|
||||
rs->multicast_data_port = val_i;
|
||||
break;
|
||||
|
||||
case TOK_MULTICAST_CMD_ADDR:
|
||||
rs->multicast_cmd_addr = strdup(val);
|
||||
break;
|
||||
|
||||
case TOK_MULTICAST_CMD_PORT:
|
||||
if (1 != sscanf(val, "%ld", &val_i))
|
||||
{
|
||||
return -RIG_EINVAL;
|
||||
}
|
||||
|
||||
rs->multicast_cmd_port = val_i;
|
||||
break;
|
||||
|
||||
default:
|
||||
return -RIG_EINVAL;
|
||||
|
|
116
src/event.c
116
src/event.c
|
@ -75,12 +75,11 @@ void *rig_poll_routine(void *arg)
|
|||
int update_occurred;
|
||||
|
||||
vfo_t vfo = RIG_VFO_NONE, vfo_prev = RIG_VFO_NONE;
|
||||
freq_t freq_main = 0, freq_sub = 0, freq_main_prev = 0, freq_sub_prev = 0;
|
||||
rmode_t mode_main = RIG_MODE_NONE, mode_sub = RIG_MODE_NONE,
|
||||
mode_main_prev = RIG_MODE_NONE, mode_sub_prev = RIG_MODE_NONE;
|
||||
pbwidth_t width_main = 0, width_sub = 0, width_main_prev = 0,
|
||||
width_sub_prev = 0;
|
||||
split_t split, split_prev = -1;
|
||||
freq_t freq_main_a = 0, freq_main_b = 0, freq_main_c = 0, freq_sub_a = 0, freq_sub_b = 0, freq_sub_c = 0;
|
||||
rmode_t mode_main_a = 0, mode_main_b = 0, mode_main_c = 0, mode_sub_a = 0, mode_sub_b = 0, mode_sub_c = 0;
|
||||
pbwidth_t width_main_a = 0, width_main_b = 0, width_main_c = 0, width_sub_a = 0, width_sub_b = 0, width_sub_c = 0;
|
||||
ptt_t ptt = RIG_PTT_OFF;
|
||||
split_t split = RIG_SPLIT_OFF;
|
||||
|
||||
rig_debug(RIG_DEBUG_VERBOSE, "%s(%d): Starting rig poll routine thread\n",
|
||||
__FILE__, __LINE__);
|
||||
|
@ -92,6 +91,109 @@ void *rig_poll_routine(void *arg)
|
|||
|
||||
while (rs->poll_routine_thread_run)
|
||||
{
|
||||
if (rig->state.cache.freqMainA != freq_main_a)
|
||||
{
|
||||
freq_main_a = rig->state.cache.freqMainA;
|
||||
update_occurred = 1;
|
||||
}
|
||||
else if (rig->state.cache.freqMainB != freq_main_b)
|
||||
{
|
||||
freq_main_b = rig->state.cache.freqMainB;
|
||||
update_occurred = 1;
|
||||
}
|
||||
else if (rig->state.cache.freqMainC != freq_main_c)
|
||||
{
|
||||
freq_main_b = rig->state.cache.freqMainC;
|
||||
update_occurred = 1;
|
||||
}
|
||||
else if (rig->state.cache.freqSubA != freq_sub_a)
|
||||
{
|
||||
freq_sub_a = rig->state.cache.freqSubA;
|
||||
update_occurred = 1;
|
||||
}
|
||||
else if (rig->state.cache.freqSubB != freq_sub_b)
|
||||
{
|
||||
freq_sub_b = rig->state.cache.freqSubB;
|
||||
update_occurred = 1;
|
||||
}
|
||||
else if (rig->state.cache.freqSubC != freq_sub_c)
|
||||
{
|
||||
freq_sub_c = rig->state.cache.freqSubC;
|
||||
update_occurred = 1;
|
||||
}
|
||||
else if (rig->state.cache.ptt != ptt)
|
||||
{
|
||||
ptt = rig->state.cache.ptt;
|
||||
update_occurred = 1;
|
||||
}
|
||||
else if (rig->state.cache.split != split)
|
||||
{
|
||||
split = rig->state.cache.split;
|
||||
update_occurred = 1;
|
||||
}
|
||||
else if (rig->state.cache.modeMainA != mode_main_a)
|
||||
{
|
||||
mode_main_a = rig->state.cache.modeMainA;
|
||||
update_occurred = 1;
|
||||
}
|
||||
else if (rig->state.cache.modeMainB != mode_main_b)
|
||||
{
|
||||
mode_main_b = rig->state.cache.modeMainB;
|
||||
update_occurred = 1;
|
||||
}
|
||||
else if (rig->state.cache.modeMainC != mode_main_c)
|
||||
{
|
||||
mode_main_c = rig->state.cache.modeMainC;
|
||||
update_occurred = 1;
|
||||
}
|
||||
else if (rig->state.cache.modeSubA != mode_sub_a)
|
||||
{
|
||||
mode_sub_a = rig->state.cache.modeSubA;
|
||||
update_occurred = 1;
|
||||
}
|
||||
else if (rig->state.cache.modeSubB != mode_sub_b)
|
||||
{
|
||||
mode_sub_b = rig->state.cache.modeSubB;
|
||||
update_occurred = 1;
|
||||
}
|
||||
else if (rig->state.cache.modeSubC != mode_sub_c)
|
||||
{
|
||||
mode_sub_c = rig->state.cache.modeSubC;
|
||||
update_occurred = 1;
|
||||
}
|
||||
else if (rig->state.cache.widthMainA != width_main_a)
|
||||
{
|
||||
width_main_a = rig->state.cache.widthMainA;
|
||||
update_occurred = 1;
|
||||
}
|
||||
else if (rig->state.cache.widthMainB != width_main_b)
|
||||
{
|
||||
width_main_b = rig->state.cache.widthMainB;
|
||||
update_occurred = 1;
|
||||
}
|
||||
else if (rig->state.cache.widthMainC != width_main_c)
|
||||
{
|
||||
width_main_c = rig->state.cache.widthMainC;
|
||||
update_occurred = 1;
|
||||
}
|
||||
else if (rig->state.cache.widthSubA != width_sub_a)
|
||||
{
|
||||
width_sub_a = rig->state.cache.widthSubA;
|
||||
update_occurred = 1;
|
||||
}
|
||||
else if (rig->state.cache.widthSubB != width_sub_b)
|
||||
{
|
||||
width_sub_b = rig->state.cache.widthSubB;
|
||||
update_occurred = 1;
|
||||
}
|
||||
else if (rig->state.cache.widthSubC != width_sub_c)
|
||||
{
|
||||
width_sub_c = rig->state.cache.widthSubC;
|
||||
update_occurred = 1;
|
||||
}
|
||||
|
||||
// The original code here actively reads rig state, which can be too intensive and intrusive
|
||||
#if 0
|
||||
if (rig->caps->get_vfo)
|
||||
{
|
||||
result = rig_get_vfo(rig, &vfo);
|
||||
|
@ -225,10 +327,12 @@ void *rig_poll_routine(void *arg)
|
|||
split_prev = split;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (update_occurred)
|
||||
{
|
||||
network_publish_rig_poll_data(rig);
|
||||
update_occurred = 0;
|
||||
}
|
||||
|
||||
hl_usleep(rs->poll_interval * 1000);
|
||||
|
|
319
src/network.c
319
src/network.c
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* Hamlib Interface - network communication low-level support
|
||||
* Copyright (c) 2021 by Mikael Nousiainen
|
||||
* Copyright (c) 2021-2023 by Mikael Nousiainen
|
||||
* Copyright (c) 2000-2012 by Stephane Fillod
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
|
@ -126,6 +126,20 @@ typedef struct multicast_publisher_priv_data_s
|
|||
multicast_publisher_args args;
|
||||
} multicast_publisher_priv_data;
|
||||
|
||||
typedef struct multicast_receiver_args_s
|
||||
{
|
||||
RIG *rig;
|
||||
int socket_fd;
|
||||
const char *multicast_addr;
|
||||
int multicast_port;
|
||||
} multicast_receiver_args;
|
||||
|
||||
typedef struct multicast_receiver_priv_data_s
|
||||
{
|
||||
pthread_t thread_id;
|
||||
multicast_receiver_args args;
|
||||
} multicast_receiver_priv_data;
|
||||
|
||||
static void handle_error(enum rig_debug_level_e lvl, const char *msg)
|
||||
{
|
||||
int e;
|
||||
|
@ -515,7 +529,6 @@ static int multicast_publisher_write_data(multicast_publisher_args
|
|||
return (RIG_OK);
|
||||
}
|
||||
|
||||
#if 0 // disable until we figure out what to do about Windows poor performance
|
||||
static int multicast_publisher_read_data(multicast_publisher_args
|
||||
const *mcast_publisher_args, size_t length, unsigned char *data)
|
||||
{
|
||||
|
@ -558,7 +571,6 @@ static int multicast_publisher_read_data(multicast_publisher_args
|
|||
|
||||
return (RIG_OK);
|
||||
}
|
||||
#endif
|
||||
|
||||
#else
|
||||
|
||||
|
@ -638,7 +650,6 @@ static int multicast_publisher_write_data(const multicast_publisher_args
|
|||
return (RIG_OK);
|
||||
}
|
||||
|
||||
#if 0
|
||||
static int multicast_publisher_read_data(const multicast_publisher_args
|
||||
*mcast_publisher_args, size_t length, unsigned char *data)
|
||||
{
|
||||
|
@ -703,7 +714,6 @@ static int multicast_publisher_read_data(const multicast_publisher_args
|
|||
|
||||
return (RIG_OK);
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -777,7 +787,6 @@ int network_publish_rig_transceive_data(RIG *rig)
|
|||
return multicast_publisher_write_packet_header(rig, &packet);
|
||||
}
|
||||
|
||||
// cppcheck-suppress unusedFunction
|
||||
int network_publish_rig_spectrum_data(RIG *rig, struct rig_spectrum_line *line)
|
||||
{
|
||||
int result;
|
||||
|
@ -827,7 +836,6 @@ int network_publish_rig_spectrum_data(RIG *rig, struct rig_spectrum_line *line)
|
|||
RETURNFUNC2(RIG_OK);
|
||||
}
|
||||
|
||||
#if 0
|
||||
static int multicast_publisher_read_packet(multicast_publisher_args
|
||||
const *mcast_publisher_args,
|
||||
uint8_t *type, struct rig_spectrum_line *spectrum_line,
|
||||
|
@ -893,11 +901,10 @@ static int multicast_publisher_read_packet(multicast_publisher_args
|
|||
|
||||
return (RIG_OK);
|
||||
}
|
||||
#endif
|
||||
|
||||
void *multicast_publisher(void *arg)
|
||||
{
|
||||
//unsigned char spectrum_data[HAMLIB_MAX_SPECTRUM_DATA];
|
||||
unsigned char spectrum_data[HAMLIB_MAX_SPECTRUM_DATA];
|
||||
char snapshot_buffer[HAMLIB_MAX_SNAPSHOT_PACKET_SIZE];
|
||||
|
||||
struct multicast_publisher_args_s *args = (struct multicast_publisher_args_s *)
|
||||
|
@ -923,29 +930,20 @@ void *multicast_publisher(void *arg)
|
|||
|
||||
while (rs->multicast_publisher_run == 1)
|
||||
{
|
||||
int i;
|
||||
int result;
|
||||
static freq_t freqA, freqB, freqC;
|
||||
static mode_t modeA, modeB, modeC;
|
||||
static pbwidth_t widthA, widthB, widthC;
|
||||
static ptt_t ptt;
|
||||
static split_t split;
|
||||
|
||||
#if 0
|
||||
result = multicast_publisher_read_packet(args, &packet_type, &spectrum_line,
|
||||
spectrum_data);
|
||||
#endif
|
||||
if (result != RIG_OK)
|
||||
{
|
||||
if (result == -RIG_ETIMEOUT)
|
||||
{
|
||||
// continue;
|
||||
continue;
|
||||
}
|
||||
|
||||
// TODO: how to detect closing of pipe, indicate with error code
|
||||
// TODO: error handling, flush pipe in case of error?
|
||||
//hl_usleep(500 * 1000);
|
||||
// continue;
|
||||
continue;
|
||||
}
|
||||
|
||||
result = snapshot_serialize(sizeof(snapshot_buffer), snapshot_buffer, rig,
|
||||
|
@ -959,10 +957,8 @@ void *multicast_publisher(void *arg)
|
|||
continue;
|
||||
}
|
||||
|
||||
#if 0
|
||||
rig_debug(RIG_DEBUG_CACHE, "%s: sending rig snapshot data: %s\n", __func__,
|
||||
snapshot_buffer);
|
||||
#endif
|
||||
|
||||
send_result = sendto(
|
||||
socket_fd,
|
||||
|
@ -978,84 +974,73 @@ void *multicast_publisher(void *arg)
|
|||
rig_debug(RIG_DEBUG_ERR, "%s: error sending UDP packet: %s\n", __func__,
|
||||
strerror(errno));
|
||||
}
|
||||
|
||||
struct sockaddr_in client_addr;
|
||||
char buf[4096];
|
||||
socklen_t client_len = sizeof(client_addr);
|
||||
int n = recvfrom(socket_fd, buf, sizeof(buf), 0, (struct sockaddr*)&client_addr, &client_len);
|
||||
if (n > 0)
|
||||
{
|
||||
// To-do handle commands from multicast clients
|
||||
rig_debug(RIG_DEBUG_ERR, "%s: received %d bytes=%s\n", __func__, n, buf);
|
||||
}
|
||||
for(i=0;i<5;++i)
|
||||
{
|
||||
hl_usleep(200*1000);
|
||||
if (rig->state.cache.freqMainA != freqA)
|
||||
{
|
||||
freqA = rig->state.cache.freqMainA;
|
||||
break;
|
||||
}
|
||||
if (rig->state.cache.freqMainB != freqB)
|
||||
{
|
||||
freqB = rig->state.cache.freqMainB;
|
||||
break;
|
||||
}
|
||||
if (rig->state.cache.freqMainC != freqC)
|
||||
{
|
||||
freqC = rig->state.cache.freqMainC;
|
||||
break;
|
||||
}
|
||||
if (rig->state.cache.ptt != ptt)
|
||||
{
|
||||
ptt = rig->state.cache.ptt;
|
||||
break;
|
||||
}
|
||||
if (rig->state.cache.split != split)
|
||||
{
|
||||
split = rig->state.cache.split;
|
||||
break;
|
||||
}
|
||||
if (rig->state.cache.modeMainA != modeA)
|
||||
{
|
||||
modeA = rig->state.cache.modeMainA;
|
||||
break;
|
||||
}
|
||||
if (rig->state.cache.modeMainB != modeB)
|
||||
{
|
||||
modeB = rig->state.cache.modeMainB;
|
||||
break;
|
||||
}
|
||||
if (rig->state.cache.modeMainC != modeC)
|
||||
{
|
||||
modeC = rig->state.cache.modeMainC;
|
||||
break;
|
||||
}
|
||||
if (rig->state.cache.widthMainA != widthA)
|
||||
{
|
||||
widthA = rig->state.cache.widthMainA;
|
||||
break;
|
||||
}
|
||||
if (rig->state.cache.widthMainB != widthB)
|
||||
{
|
||||
widthB = rig->state.cache.widthMainB;
|
||||
break;
|
||||
}
|
||||
if (rig->state.cache.widthMainC != widthC)
|
||||
{
|
||||
widthC = rig->state.cache.widthMainC;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
rs->multicast_publisher_run = 2; // stop value
|
||||
|
||||
rig_debug(RIG_DEBUG_VERBOSE, "%s(%d): Stopping multicast publisher\n", __FILE__,
|
||||
__LINE__);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void *multicast_receiver(void *arg)
|
||||
{
|
||||
char data[4096];
|
||||
|
||||
struct multicast_receiver_args_s *args = (struct multicast_receiver_args_s *)
|
||||
arg;
|
||||
RIG *rig = args->rig;
|
||||
struct rig_state *rs = &rig->state;
|
||||
|
||||
struct sockaddr_in dest_addr;
|
||||
int socket_fd = args->socket_fd;
|
||||
|
||||
rig_debug(RIG_DEBUG_VERBOSE, "%s(%d): Starting multicast receiver\n", __FILE__,
|
||||
__LINE__);
|
||||
|
||||
memset(&dest_addr, 0, sizeof(dest_addr));
|
||||
dest_addr.sin_family = AF_INET;
|
||||
dest_addr.sin_addr.s_addr = inet_addr(args->multicast_addr);
|
||||
dest_addr.sin_port = htons(args->multicast_port);
|
||||
|
||||
if ((bind(socket_fd, (struct sockaddr *) &dest_addr, sizeof(dest_addr))) < 0) {
|
||||
rig_debug(RIG_DEBUG_ERR, "%s: error binding UDP socket to %s:%d: %s\n", __func__,
|
||||
args->multicast_addr, args->multicast_port, strerror(errno));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
rs->multicast_receiver_run = 1;
|
||||
|
||||
while (rs->multicast_receiver_run == 1)
|
||||
{
|
||||
ssize_t result;
|
||||
struct sockaddr_in client_addr;
|
||||
socklen_t client_len = sizeof(client_addr);
|
||||
|
||||
result = recvfrom(socket_fd, data, sizeof(data), 0, (struct sockaddr *) &client_addr, &client_len);
|
||||
|
||||
rig_debug(RIG_DEBUG_ERR, "%s: received multicast packet with result %ld\n", __func__, result);
|
||||
|
||||
if (result <= 0)
|
||||
{
|
||||
if (result < 0)
|
||||
{
|
||||
rig_debug(RIG_DEBUG_ERR, "%s: error receiving from UDP socket %s:%d: %s\n", __func__,
|
||||
args->multicast_addr, args->multicast_port, strerror(errno));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// TODO: handle commands from multicast clients
|
||||
rig_debug(RIG_DEBUG_ERR, "%s: received %ld bytes=%s\n", __func__, result, data);
|
||||
|
||||
// TODO: if a new snapshot needs to be sent, call network_publish_rig_poll_data() and the publisher routine will send out a snapshot
|
||||
// TODO: new logic in publisher needs to be written for other types of responses
|
||||
}
|
||||
|
||||
rig_debug(RIG_DEBUG_VERBOSE, "%s(%d): Stopping multicast receiver\n", __FILE__,
|
||||
__LINE__);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//! @endcond
|
||||
|
||||
/**
|
||||
|
@ -1077,11 +1062,11 @@ int network_multicast_publisher_start(RIG *rig, const char *multicast_addr,
|
|||
|
||||
ENTERFUNC;
|
||||
|
||||
rig_debug(RIG_DEBUG_VERBOSE, "%s(%d):multicast address=%s, port=%d\n", __FILE__,
|
||||
rig_debug(RIG_DEBUG_VERBOSE, "%s(%d): multicast publisher address=%s, port=%d\n", __FILE__,
|
||||
__LINE__,
|
||||
multicast_addr, multicast_port);
|
||||
|
||||
if (strcmp(multicast_addr, "0.0.0.0") == 0)
|
||||
if (multicast_addr == NULL || strcmp(multicast_addr, "0.0.0.0") == 0)
|
||||
{
|
||||
rig_debug(RIG_DEBUG_TRACE, "%s(%d): not starting multicast publisher\n",
|
||||
__FILE__, __LINE__);
|
||||
|
@ -1231,5 +1216,149 @@ int network_multicast_publisher_stop(RIG *rig)
|
|||
|
||||
RETURNFUNC(RIG_OK);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* \brief Start multicast receiver
|
||||
*
|
||||
* Start multicast receiver.
|
||||
*
|
||||
* \param multicast_addr UDP address
|
||||
* \param multicast_port UDP socket port
|
||||
* \return RIG_OK or < 0 if error
|
||||
*/
|
||||
int network_multicast_receiver_start(RIG *rig, const char *multicast_addr, int multicast_port)
|
||||
{
|
||||
struct rig_state *rs = &rig->state;
|
||||
multicast_receiver_priv_data *mcast_receiver_priv;
|
||||
int socket_fd;
|
||||
int status;
|
||||
|
||||
ENTERFUNC;
|
||||
|
||||
rig_debug(RIG_DEBUG_VERBOSE, "%s(%d): multicast receiver address=%s, port=%d\n", __FILE__,
|
||||
__LINE__,
|
||||
multicast_addr, multicast_port);
|
||||
|
||||
if (multicast_addr == NULL || strcmp(multicast_addr, "0.0.0.0") == 0)
|
||||
{
|
||||
rig_debug(RIG_DEBUG_TRACE, "%s(%d): not starting multicast receiver\n",
|
||||
__FILE__, __LINE__);
|
||||
return RIG_OK;
|
||||
}
|
||||
|
||||
if (rs->multicast_receiver_priv_data != NULL)
|
||||
{
|
||||
rig_debug(RIG_DEBUG_ERR, "%s(%d): multicast receiver already running\n",
|
||||
__FILE__,
|
||||
__LINE__);
|
||||
RETURNFUNC(-RIG_EINVAL);
|
||||
}
|
||||
|
||||
status = network_init();
|
||||
|
||||
if (status != RIG_OK)
|
||||
{
|
||||
RETURNFUNC(status);
|
||||
}
|
||||
|
||||
socket_fd = socket(AF_INET, SOCK_DGRAM, 0);
|
||||
|
||||
if (socket_fd < 0)
|
||||
{
|
||||
rig_debug(RIG_DEBUG_ERR, "%s: error opening new UDP socket: %s", __func__,
|
||||
strerror(errno));
|
||||
RETURNFUNC(-RIG_EIO);
|
||||
}
|
||||
|
||||
rs->multicast_receiver_run = 1;
|
||||
rs->multicast_receiver_priv_data = calloc(1,
|
||||
sizeof(multicast_receiver_priv_data));
|
||||
|
||||
if (rs->multicast_receiver_priv_data == NULL)
|
||||
{
|
||||
close(socket_fd);
|
||||
RETURNFUNC(-RIG_ENOMEM);
|
||||
}
|
||||
|
||||
mcast_receiver_priv = (multicast_receiver_priv_data *)
|
||||
rs->multicast_receiver_priv_data;
|
||||
mcast_receiver_priv->args.socket_fd = socket_fd;
|
||||
mcast_receiver_priv->args.multicast_addr = multicast_addr;
|
||||
mcast_receiver_priv->args.multicast_port = multicast_port;
|
||||
mcast_receiver_priv->args.rig = rig;
|
||||
|
||||
int err = pthread_create(&mcast_receiver_priv->thread_id, NULL,
|
||||
multicast_receiver,
|
||||
&mcast_receiver_priv->args);
|
||||
|
||||
if (err)
|
||||
{
|
||||
rig_debug(RIG_DEBUG_ERR, "%s(%d) pthread_create error %s\n", __FILE__, __LINE__,
|
||||
strerror(errno));
|
||||
free(mcast_receiver_priv);
|
||||
rs->multicast_receiver_priv_data = NULL;
|
||||
close(socket_fd);
|
||||
RETURNFUNC(-RIG_EINTERNAL);
|
||||
}
|
||||
|
||||
RETURNFUNC(RIG_OK);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Stop multicast receiver
|
||||
*
|
||||
* Stop multicast receiver
|
||||
*
|
||||
* \return RIG_OK or < 0 if error
|
||||
*/
|
||||
int network_multicast_receiver_stop(RIG *rig)
|
||||
{
|
||||
struct rig_state *rs = &rig->state;
|
||||
multicast_receiver_priv_data *mcast_receiver_priv;
|
||||
|
||||
ENTERFUNC;
|
||||
|
||||
rs->multicast_receiver_run = 0;
|
||||
|
||||
mcast_receiver_priv = (multicast_receiver_priv_data *)
|
||||
rs->multicast_receiver_priv_data;
|
||||
|
||||
if (mcast_receiver_priv == NULL)
|
||||
{
|
||||
RETURNFUNC(RIG_OK);
|
||||
}
|
||||
|
||||
// Close the socket first to stop the routine
|
||||
if (mcast_receiver_priv->args.socket_fd >= 0)
|
||||
{
|
||||
close(mcast_receiver_priv->args.socket_fd);
|
||||
}
|
||||
|
||||
if (mcast_receiver_priv->thread_id != 0)
|
||||
{
|
||||
int err = pthread_join(mcast_receiver_priv->thread_id, NULL);
|
||||
|
||||
if (err)
|
||||
{
|
||||
rig_debug(RIG_DEBUG_ERR, "%s(%d): pthread_join error %s\n", __FILE__, __LINE__,
|
||||
strerror(errno));
|
||||
// just ignore it
|
||||
}
|
||||
|
||||
mcast_receiver_priv->thread_id = 0;
|
||||
}
|
||||
|
||||
if (mcast_receiver_priv->args.socket_fd >= 0)
|
||||
{
|
||||
mcast_receiver_priv->args.socket_fd = -1;
|
||||
}
|
||||
|
||||
free(rs->multicast_receiver_priv_data);
|
||||
rs->multicast_receiver_priv_data = NULL;
|
||||
|
||||
RETURNFUNC(RIG_OK);
|
||||
}
|
||||
|
||||
#endif
|
||||
/** @} */
|
||||
|
|
|
@ -36,6 +36,8 @@ int network_publish_rig_transceive_data(RIG *rig);
|
|||
int network_publish_rig_spectrum_data(RIG *rig, struct rig_spectrum_line *line);
|
||||
HAMLIB_EXPORT(int) network_multicast_publisher_start(RIG *rig, const char *multicast_addr, int multicast_port, enum multicast_item_e items);
|
||||
HAMLIB_EXPORT(int) network_multicast_publisher_stop(RIG *rig);
|
||||
HAMLIB_EXPORT(int) network_multicast_receiver_start(RIG *rig, const char *multicast_addr, int multicast_port);
|
||||
HAMLIB_EXPORT(int) network_multicast_receiver_stop(RIG *rig);
|
||||
|
||||
__END_DECLS
|
||||
|
||||
|
|
42
src/rig.c
42
src/rig.c
|
@ -670,7 +670,11 @@ RIG *HAMLIB_API rig_init(rig_model_t rig_model)
|
|||
rs->vfo_comp = 0.0; /* override it with preferences */
|
||||
rs->current_vfo = RIG_VFO_CURR; /* we don't know yet! */
|
||||
rs->tx_vfo = RIG_VFO_CURR; /* we don't know yet! */
|
||||
rs->poll_interval = 0; // disable polling by default
|
||||
rs->poll_interval = 1000; // enable polling by default
|
||||
rs->multicast_data_addr = "224.0.0.1"; // enable multicast data publishing by default
|
||||
rs->multicast_data_port = 4532;
|
||||
rs->multicast_cmd_addr = "224.0.0.2"; // enable multicast command server by default
|
||||
rs->multicast_cmd_port = 4532;
|
||||
rs->lo_freq = 0;
|
||||
rs->cache.timeout_ms = 500; // 500ms cache timeout by default
|
||||
rs->cache.ptt = 0;
|
||||
|
@ -1484,18 +1488,32 @@ int HAMLIB_API rig_open(RIG *rig)
|
|||
memcpy(&rs->pttport_deprecated, &rs->pttport, sizeof(hamlib_port_t_deprecated));
|
||||
memcpy(&rs->dcdport_deprecated, &rs->dcdport, sizeof(hamlib_port_t_deprecated));
|
||||
rig_flush_force(&rs->rigport, 1);
|
||||
// if (rig->caps->rig_model != RIG_MODEL_NETRIGCTL) multicast_init(rig, "224.0.0.1", 4532);
|
||||
// multicast_init(rig, "224.0.0.1", 4532);
|
||||
char *multicast_addr = "224.0.0.1";
|
||||
int multicast_port = 4532;
|
||||
enum multicast_item_e items = RIG_MULTICAST_POLL | RIG_MULTICAST_TRANSCEIVE;
|
||||
// | RIG_MULTICAST_SPECTRUM;
|
||||
retval = network_multicast_publisher_start(rig, multicast_addr,
|
||||
multicast_port, items);
|
||||
|
||||
enum multicast_item_e items = RIG_MULTICAST_POLL | RIG_MULTICAST_TRANSCEIVE
|
||||
| RIG_MULTICAST_SPECTRUM;
|
||||
retval = network_multicast_publisher_start(rig, rs->multicast_data_addr,
|
||||
rs->multicast_data_port, items);
|
||||
|
||||
if (retval != RIG_OK)
|
||||
{
|
||||
rig_debug(RIG_DEBUG_ERR, "%s: network_multicast_server failed: %s\n", __FILE__,
|
||||
rig_debug(RIG_DEBUG_ERR, "%s: network_multicast_publisher_start failed: %s\n", __FILE__,
|
||||
rigerror(retval));
|
||||
// we will consider this non-fatal for now
|
||||
}
|
||||
|
||||
retval = network_multicast_receiver_start(rig, rs->multicast_cmd_addr, rs->multicast_cmd_port);
|
||||
|
||||
if (retval != RIG_OK)
|
||||
{
|
||||
rig_debug(RIG_DEBUG_ERR, "%s: network_multicast_receiver_start failed: %s\n", __FILE__,
|
||||
rigerror(retval));
|
||||
// we will consider this non-fatal for now
|
||||
}
|
||||
|
||||
retval = rig_poll_routine_start(rig);
|
||||
if (retval != RIG_OK)
|
||||
{
|
||||
rig_debug(RIG_DEBUG_ERR, "%s: rig_poll_routine_start failed: %s\n", __FILE__,
|
||||
rigerror(retval));
|
||||
// we will consider this non-fatal for now
|
||||
}
|
||||
|
@ -1541,9 +1559,9 @@ int HAMLIB_API rig_close(RIG *rig)
|
|||
|
||||
morse_data_handler_stop(rig);
|
||||
async_data_handler_stop(rig);
|
||||
rig_poll_routine_stop(rig);
|
||||
network_multicast_receiver_stop(rig);
|
||||
network_multicast_publisher_stop(rig);
|
||||
//while(rs->multicast_publisher_run != 2) hl_usleep(10*1000);
|
||||
//multicast_stop(rig);
|
||||
|
||||
/*
|
||||
* Let the backend say 73s to the rig.
|
||||
|
|
|
@ -131,6 +131,15 @@
|
|||
#define TOK_OFFSET_VFOA TOKEN_FRONTEND(130)
|
||||
/** \brief rig: Add Hz to VFOB/Sub frequency set */
|
||||
#define TOK_OFFSET_VFOB TOKEN_FRONTEND(131)
|
||||
/** \brief rig: Multicast data UDP address for publishing rig data and state, default 224.0.0.1, value of 0.0.0.0 disables multicast data publishing */
|
||||
#define TOK_MULTICAST_DATA_ADDR TOKEN_FRONTEND(132)
|
||||
/** \brief rig: Multicast data UDP port, default 4532 */
|
||||
#define TOK_MULTICAST_DATA_PORT TOKEN_FRONTEND(133)
|
||||
/** \brief rig: Multicast command server UDP address for sending commands to rig, default 224.0.0.2, value of 0.0.0.0 disables multicast command server */
|
||||
#define TOK_MULTICAST_CMD_ADDR TOKEN_FRONTEND(134)
|
||||
/** \brief rig: Multicast command server UDP port, default 4532 */
|
||||
#define TOK_MULTICAST_CMD_PORT TOKEN_FRONTEND(135)
|
||||
|
||||
/*
|
||||
* rotator specific tokens
|
||||
* (strictly, should be documented as rotator_internal)
|
||||
|
|
|
@ -105,8 +105,6 @@ static struct option long_options[] =
|
|||
{"twiddle_rit", 1, 0, 'w'},
|
||||
{"uplink", 1, 0, 'x'},
|
||||
{"debug-time-stamps", 0, 0, 'Z'},
|
||||
{"multicast-addr", 1, 0, 'M'},
|
||||
{"multicast-port", 1, 0, 'n'},
|
||||
{"password", 1, 0, 'A'},
|
||||
{"rigctld-idle", 0, 0, 'R'},
|
||||
{"bind-all", 0, 0, 'b'},
|
||||
|
@ -145,8 +143,6 @@ static int volatile ctrl_c;
|
|||
|
||||
const char *portno = "4532";
|
||||
const char *src_addr = NULL; /* INADDR_ANY */
|
||||
const char *multicast_addr = "0.0.0.0";
|
||||
int multicast_port = 4532;
|
||||
extern char rigctld_password[65];
|
||||
char resp_sep = '\n';
|
||||
extern int lock_mode;
|
||||
|
@ -618,33 +614,6 @@ int main(int argc, char *argv[])
|
|||
rig_set_debug_time_stamp(1);
|
||||
break;
|
||||
|
||||
case 'M':
|
||||
if (!optarg)
|
||||
{
|
||||
usage(); /* wrong arg count */
|
||||
exit(1);
|
||||
}
|
||||
|
||||
multicast_addr = optarg;
|
||||
break;
|
||||
|
||||
case 'n':
|
||||
if (!optarg)
|
||||
{
|
||||
usage(); /* wrong arg count */
|
||||
exit(1);
|
||||
}
|
||||
|
||||
multicast_port = atoi(optarg);
|
||||
|
||||
if (multicast_port == 0)
|
||||
{
|
||||
fprintf(stderr, "Invalid multicast port: %s\n", optarg);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
usage(); /* unknown option? */
|
||||
exit(1);
|
||||
|
@ -867,18 +836,6 @@ int main(int argc, char *argv[])
|
|||
|
||||
saved_result = result;
|
||||
|
||||
enum multicast_item_e items = RIG_MULTICAST_POLL | RIG_MULTICAST_TRANSCEIVE |
|
||||
RIG_MULTICAST_SPECTRUM;
|
||||
retcode = network_multicast_publisher_start(my_rig, multicast_addr,
|
||||
multicast_port, items);
|
||||
|
||||
if (retcode != RIG_OK)
|
||||
{
|
||||
rig_debug(RIG_DEBUG_ERR, "%s: network_multicast_server failed: %s\n", __FILE__,
|
||||
rigerror(retcode));
|
||||
// we will consider this non-fatal for now
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
sock_listen = socket(result->ai_family,
|
||||
|
@ -1148,8 +1105,6 @@ int main(int argc, char *argv[])
|
|||
rig_close(my_rig); /* close port */
|
||||
#endif
|
||||
|
||||
network_multicast_publisher_stop(my_rig);
|
||||
|
||||
rig_cleanup(my_rig); /* if you care about memory */
|
||||
|
||||
#ifdef __MINGW32__
|
||||
|
@ -1464,8 +1419,6 @@ void usage(void)
|
|||
" -w, --twiddle_rit suppress VFOB getfreq so RIT can be twiddled\n"
|
||||
" -x, --uplink set uplink get_freq ignore, 1=Sub, 2=Main\n"
|
||||
" -Z, --debug-time-stamps enable time stamps for debug messages\n"
|
||||
" -M, --multicast-addr=addr set multicast UDP address, default 0.0.0.0 (off), recommend 224.0.1.1\n"
|
||||
" -n, --multicast-port=port set multicast UDP port, default 4532\n"
|
||||
" -A, --password set password for rigctld access\n"
|
||||
" -R, --rigctld-idle make rigctld close the rig when no clients are connected\n"
|
||||
" -h, --help display this help and exit\n"
|
||||
|
|
Ładowanie…
Reference in New Issue