56 int main(
int argc,
char *argv[]) {
61 "Usage: %1$s [-h host] [-p port] [-k sysid] topic [topic ...]\n"
62 "\t-h\tMQTT Broker Host name\n"
63 "\t-p\tMQTT Broker port\n"
64 "\t-k sysid\tEnable Victron compatible keepalive messages/requests for given system ID\n"
65 "\t-v\tDump all messages\n"
66 "\nDefaults equivalent to %1$s -h localhost -p 1883\n"
72 bool keepalive =
false;
78 while ((go = getopt(argc, argv,
"h:k:p:v")) != -1) {
82 log_error(&state,
"Only a single hostname is supported");
85 host = strdup(optarg);
90 port = strtol(optarg, NULL, 0);
91 if (port <= 0 || errno) {
92 log_error(&state,
"Invalid port number (%s)", optarg);
101 "Cannot specify keepalive option multiple times");
104 sysid = strdup(optarg);
111 log_error(&state,
"Unknown option `-%c'", optopt);
116 int remaining = argc - optind;
117 if (remaining == 0) {
123 log_error(&state,
"Invalid options provided");
124 fprintf(stderr, usage, argv[0]);
125 if (host) { free(host); }
126 if (sysid) { free(sysid); }
130 if (host == NULL) { host = strdup(
"localhost"); }
132 if (port == 0) { port = 1883; }
136 for (
int t = 0; t < remaining; t++) {
139 qm.
tc[t].
topic = strdup(argv[optind + t]);
140 qm.
tc[t].
name = strdup(argv[optind + t]);
146 log_info(&state, 1,
"Connecting to %s:%d...", host, port);
149 log_error(&state,
"Unable to subscribe to topics");
150 if (host) { free(host); }
151 if (sysid) { free(sysid); }
155 sigset_t *hMask = calloc(1,
sizeof(sigset_t));
159 sigaddset(hMask, SIGINT);
160 sigaddset(hMask, SIGQUIT);
161 sigdelset(hMask, SIGINT);
162 sigdelset(hMask, SIGQUIT);
164 const struct sigaction saShutdown = {
165 .sa_handler =
signalShutdown, .sa_mask = *hMask, .sa_flags = SA_RESTART};
166 sigaction(SIGINT, &saShutdown, NULL);
167 sigaction(SIGQUIT, &saShutdown, NULL);
168 sigaction(SIGRTMIN + 1, &saShutdown, NULL);
170 log_info(&state, 1,
"Starting message loop...");
175 if (keepalive && (count % 100) == 0) {
176 time_t now = time(NULL);
177 if ((now - lastKA) >= 60) {
195 log_info(&state, 1,
"Closing connections");
bool mqtt_victron_keepalive(mqtt_conn *conn, mqtt_queue_map *qm, char *sysid)
Send MQTT keepalive commands required by Victron systems.
bool mqtt_subscribe_batch(mqtt_conn *conn, mqtt_queue_map *qm)
Subscribe to all topics configured in a mqtt_queue_map.
mqtt_conn * mqtt_openConnection(const char *host, const int port, mqtt_queue_map *qm)
Open and configure a connection to an MQTT server.
void mqtt_closeConnection(mqtt_conn *conn)
Close MQTT server connection.
int main(int argc, char *argv[])
bool shutdown
Set true to start clean shutdown.
void msg_destroy(msg_t *msg)
Destroy a message.
bool mqtt_init_queue_map(mqtt_queue_map *qm)
Initialise mqtt_queue_map to sensible defaults.
struct mosquitto mqtt_conn
Convenient alias for library structure.
void mqtt_destroy_queue_map(mqtt_queue_map *qm)
Release resources used by mqtt_queue_map instance.
void signalShutdown(int signnum)
Set safe shutdown flag.
void log_info(const program_state *s, const int level, const char *format,...)
Output formatted information message at a given level.
void log_error(const program_state *s, const char *format,...)
Output formatted error message.
msg_t * queue_pop(msgqueue *queue)
Remove topmost item from the queue and return it, if queue is not empty.
bool dumpall
Dump any message, not just matches in .tc.
int numtopics
Number of topics registered.
mqtt_topic_config tc[120]
Individual topic configuration.
msgqueue q
Internal message queue.
uint8_t type
Channel number to use.
char * topic
MQTT topic to subscribe/match against.
bool text
Treat received data as text.
msg_data_t data
Embedded data.
uint8_t type
Message type. Common types to be documented.
Program state and logging information.
int verbose
Current log verbosity (console output)
char * data
Character array, should be null terminated.
string string
Single character array with length.
#define GIT_VERSION_STRING
Git version description.