#include "utils.h" #include <assert.h> #include <libgen.h> #include <pthread.h> #include <signal.h> #include <stdio.h> #include <stdlib.h> #include <sys/stat.h> #include <unistd.h> #include <zmq.h> #include <fcntl.h> #ifndef LOG_DELAY #define LOG_DELAY 0 #endif /// @brief Set to non-zero to stop the processes unsigned char __stop = 0; unsigned char __stop_zmq_thread = 0; /// @brief Path of the break file (if found, publisher will stop publishing) char __break_file[STATIC_LEN]; /** * @brief Stop process properly on SIGINT * * @param signo */ void sighandler(int signo) { if (signo == SIGINT) { printf("Stopping...\n"); __stop = 1; } } void *publisher(void *zmq_publisher); void askforbreak(){ } typedef struct queue { int size; char issending; char msg[ZMQ_MSG_SIZE]; } queue; queue queues[MAX_QUEUES]; int main(int argc, char *argv[]) { if (argc != 6) { printf("Usage: %s <client> <loginterval> <ip> <port> <key>", argv[0]); exit(1); } //----- Init arguments char *client = argv[1]; int loginterval = atoi(argv[2]); char *ip = argv[3]; int port = atoi(argv[4]); char *key = argv[5]; // __regpower: char regpower[STATIC_LEN]=""; strcat(regpower, INA260_SYSFS); strcat(regpower, "/"); strcat(regpower, client); strcat(regpower, "/"); strcat(regpower, INA260_POWER_OUTPUT); // __break_file strcat(__break_file, "/publisher_"); strcat(__break_file, key); strcat(__break_file, "_break"); printf("%s\n",__break_file); //----- Sanity checks signal(SIGINT, sighandler); if (loginterval < MIN_INTERVAL) { printf("Log interval is too small (min=%ds)\n", MIN_INTERVAL); exit(2); } if (!FILE_EXISTS(regpower)) { printf("Logger cannot access to %s\n", regpower); exit(3); } //----- Prepare our context and publisher void *zmq_context = zmq_ctx_new(); void *zmq_publisher = zmq_socket(zmq_context, ZMQ_PUB); char bindto[STATIC_LEN]; sprintf(bindto, "tcp://%s:%d", ip, port); int rc = zmq_connect(zmq_publisher, bindto); if (rc != 0) { printf("Failed to connect to %s\n", bindto); exit(1); } //----- Init logging variables pthread_t zmq_thread; FILE *logptr; char logfilepath[STATIC_LEN] = ""; int regfd = open(regpower, O_RDONLY); char buffer[STATIC_LEN]; time_t interval; struct timespec power_ts; int queue_id = 0; // Init queues for (int i = 0; i < MAX_QUEUES; i++) { queues[queue_id].issending = 0; } pthread_create(&zmq_thread, NULL, publisher, zmq_publisher); //----- Start logging printf("Logger started [client=%s,interval=%ds]\n", client, loginterval); while (!__stop) { // Busy wait: while (queues[queue_id].issending) {} // Get current interval interval = INTERVAL(loginterval); // Write msg header: *queues[queue_id].msg = '\0'; sprintf(queues[queue_id].msg, "%s\n%s\n%s\n%ld\n", ZMQ_TOKEN, key, client, interval); queues[queue_id].size = strlen(queues[queue_id].msg); // Monitor: while ((TIMESTAMP() - interval) < loginterval) { // Check if should stop: if (__stop) break; // Read power: read(regfd, buffer, STATIC_LEN); // Get power measurement timestamp: clock_gettime(CLOCK_REALTIME, &power_ts); // Write measurement into msg buffer: char line[MAX_RECORD_LEN]; if ((queues[queue_id].size + MAX_RECORD_LEN) > ZMQ_MSG_SIZE) { printf( "Too many measurements to publish. Please increase ZMQ_MSG_SIZE\n"); } else { sprintf(queues[queue_id].msg + queues[queue_id].size, "%ld,%ld,%f\n", power_ts.tv_sec, power_ts.tv_nsec, atof(buffer)); queues[queue_id].size += strlen(queues[queue_id].msg + queues[queue_id].size); } // Reset power register file: lseek(regfd,0,SEEK_SET); #if LOG_DELAY > 0 usleep(LOG_DELAY * 1000); #endif } queues[queue_id].issending = 1; // Wait for next queue to be available: queue_id = (queue_id + 1) >= MAX_QUEUES ? 0 : (queue_id + 1); } //----- Cleaning close(regfd); __stop_zmq_thread=1; // Ignite clean stop pthread_join(zmq_thread, NULL); zmq_close(zmq_publisher); zmq_ctx_destroy(zmq_context); return 0; } void *publisher(void *zmq_publisher) { int queue_id = 0; while (1) { if(__stop_zmq_thread && !queues[queue_id].issending) break; if (queues[queue_id].issending) { long long startat=TIMESTAMP(); printf("Publishing..."); zmq_send(zmq_publisher, queues[queue_id].msg, queues[queue_id].size, 0); queues[queue_id].issending = 0; printf("done (duration %lld)\n",TIMESTAMP()-startat); } else { #if LOG_DELAY > 0 usleep(LOG_DELAY * 1000); #endif continue; // Queues are always filled in order by the logger (from 0 to n) } queue_id++; if (queue_id >= MAX_QUEUES) queue_id = 0; } pthread_exit(EXIT_SUCCESS); }