void mqtt_send(struct mosquitto* mosq, const char* mqtt_payload, const char* mqtt_topic) { // send MQTT message if there is payload if (mqtt_payload[0] && mosq) { int ret; int mid; ret = mosquitto_publish( mosq, &mid, mqtt_topic, strlen(mqtt_payload), mqtt_payload, 2, /* qos */ true /* retain */ ); if (ret != MOSQ_ERR_SUCCESS) syslog(LOG_ERR, "MQTT error on message \"%s\": %d (%s)", mqtt_payload, ret, mosquitto_strerror(ret)); else syslog(LOG_INFO, "MQTT message \"%s\" sent with id %d.", mqtt_payload, mid); } }
static void mqtt_misc(void* userdata) { mqtt_t inst = (mqtt_t) userdata; int rval; int fd; if (inst->connected == 0) { inst->reconnect_timer++; inst->reconnect_timer %= 20; if (inst->reconnect_timer == 0) { rval = mosquitto_reconnect(inst->mosq); if (rval != MOSQ_ERR_SUCCESS) { error("Cannot reconnect mosquitto: %s", mosquitto_strerror(rval)); } else { fd = mosquitto_socket(inst->mosq); assert(fd != 0); rval = dispatch_register(inst->dispatch, fd, mqtt_read, mqtt_write, NULL, mqtt_close, inst); assert(rval == 0); } } } rval = mosquitto_loop_misc(inst->mosq); switch (rval) { case MOSQ_ERR_SUCCESS: break; case MOSQ_ERR_NO_CONN: //debug("mosquitto_loop_misc: No connection"); break; case MOSQ_ERR_INVAL: default: error("mosquitto_loop_misc: %s", mosquitto_strerror(rval)); break; } }
/* handle mosquitto lib return codes */ static int mosq__pstatus(lua_State *L, int mosq_errno) { switch (mosq_errno) { case MOSQ_ERR_SUCCESS: lua_pushboolean(L, true); return 1; break; case MOSQ_ERR_INVAL: case MOSQ_ERR_NOMEM: case MOSQ_ERR_PROTOCOL: case MOSQ_ERR_NOT_SUPPORTED: return luaL_error(L, mosquitto_strerror(mosq_errno)); break; case MOSQ_ERR_NO_CONN: case MOSQ_ERR_CONN_LOST: case MOSQ_ERR_PAYLOAD_SIZE: lua_pushnil(L); lua_pushinteger(L, mosq_errno); lua_pushstring(L, mosquitto_strerror(mosq_errno)); return 3; break; case MOSQ_ERR_ERRNO: lua_pushnil(L); lua_pushinteger(L, errno); lua_pushstring(L, strerror(errno)); return 3; break; } return 0; }
void on_mqtt_connect(struct mosquitto *mosq, void *obj, int result) { struct device *dev; int rc; if (!result) { connected = true; if(config.debug) printf("MQTT Connected.\n"); rc = mosquitto_subscribe(mosq, NULL, bridge.bridge_dev->config_topic, config.mqtt_qos); if (rc) { fprintf(stderr, "MQTT - Subscribe ERROR: %s\n", mosquitto_strerror(rc)); run = 0; return; } if (config.debug > 1) printf("Subscribe topic: %s\n", bridge.bridge_dev->config_topic); for (dev = bridge.dev_list; dev != NULL; dev = dev->next) { rc = mosquitto_subscribe(mosq, NULL, dev->config_topic, config.mqtt_qos); if (rc) { fprintf(stderr, "MQTT - Subscribe ERROR: %s\n", mosquitto_strerror(rc)); run = 0; return; } if (config.debug > 1) printf("Subscribe topic: %s\n", bridge.bridge_dev->config_topic); } send_alive(mosq); } else { fprintf(stderr, "MQTT - Failed to connect: %s\n", mosquitto_connack_string(result)); } }
void pub(char *prefix ,char *zone, char *topic, char *str, int retain) { char *fulltopic; int rc; int qos = 2; int mid; fulltopic = malloc(strlen(prefix) + ((zone) ? strlen(zone) : 0) + strlen(topic) + 12); if (fulltopic == NULL) { fprintf(stderr, "ENOMEM\n"); return; } if (zone) { sprintf(fulltopic, "%s/%s/%s", prefix, zone, topic); } else { sprintf(fulltopic, "%s/%s", prefix, topic); } // printf("%s %s\n", fulltopic, str); fflush(stdout); rc = mosquitto_publish(m, &mid, fulltopic, strlen(str), str, qos, retain); if (rc != MOSQ_ERR_SUCCESS) { fprintf(stderr, "Cannot publish: %s\n", mosquitto_strerror(rc)); fatal(); } // printf("PUB mid %d\n", mid); free(fulltopic); }
void mqtt_exit(mqtt_t inst) { int rval; mosquitto_destroy(inst->mosq); rval = mosquitto_lib_cleanup(); if (rval != MOSQ_ERR_SUCCESS) { error("Cannot cleanup library: '%s'", mosquitto_strerror(rval)); } }
int mqtt_publish(struct mosquitto *mosq, char *topic, char *payload) { int rc; rc = mosquitto_publish(mosq, NULL, topic, strlen(payload), payload, config.mqtt_qos, false); if (rc) { fprintf(stderr, "Error: MQTT publish returned: %s\n", mosquitto_strerror(rc)); return 0; } return 1; }
static int mqtt_close(void* userdata) { mqtt_t inst = (mqtt_t) userdata; int rval; info("Stopping MQTT service"); rval = mosquitto_disconnect(inst->mosq); if (rval != MOSQ_ERR_SUCCESS) { error("Cannot disconnect mosquitto: %s", mosquitto_strerror(rval)); } return rval; }
int mqtt_publish(mqtt_t inst, char* topic, char* payload) { int rval = 0; int qos = 0; bool retain = false; int mid = 0; if (inst->connected != 0) { rval = mosquitto_publish(inst->mosq, &mid, topic, (int)strlen(payload), payload, qos, retain); if (rval != MOSQ_ERR_SUCCESS) { error("Cannot publish: %s", mosquitto_strerror(rval)); } } return rval; }
static bool runForever(MqttMount *mount) { const int timeoutMs = 10; while(1){ const int status = mosquitto_loop(mount->connection, timeoutMs, 1); if (status == MOSQ_ERR_CONN_LOST) { mount->connect(); } else if (status == MOSQ_ERR_SUCCESS) { // Run MicroFlo network for (int i=0; i<20; i++) { mount->network->runTick(); } } else { LOG("mosquitto loop error: %s\n", mosquitto_strerror(status)); return false; } } return true; }
void pub(char *prefix ,char *zone, char *topic, char *str, int retain) { char *fulltopic; int rc; fulltopic = malloc(strlen(prefix) + ((zone) ? strlen(zone) : 0) + strlen(topic) + 12); if (zone) { sprintf(fulltopic, "%s/%s/%s", prefix, zone, topic); } else { sprintf(fulltopic, "%s/%s", prefix, topic); } // printf("%s %s\n", fulltopic, str); fflush(stdout); rc = mosquitto_publish(m, NULL, fulltopic, strlen(str), str, 0, retain); if (rc != MOSQ_ERR_SUCCESS) { fprintf(stderr, "Cannot publish: %s\n", mosquitto_strerror(rc)); } free(fulltopic); }
void on_mqtt_connect(struct mosquitto *mosq, void *obj, int result) { int rc; if (!result) { connected = true; if(config.debug != 0) printf("MQTT Connected.\n"); rc = mosquitto_subscribe(mosq, NULL, bridge.config_topic, config.mqtt_qos); if (rc) { fprintf(stderr, "MQTT - Subscribe ERROR: %s\n", mosquitto_strerror(rc)); run = 0; return; } snprintf(gbuf, GBUF_SIZE, "%d,%d", PROTO_ST_ALIVE, bridge.modules_len); mqtt_publish(mosq, bridge.status_topic, gbuf); return; } else { fprintf(stderr, "MQTT - Failed to connect: %s\n", mosquitto_connack_string(result)); } }
mqtt_t mqtt_init() { mqtt_t inst = NULL; int rval; int major = 0; int minor = 0; int revision = 0; (void) mosquitto_lib_version(&major, &minor, &revision); info("Use mosquitto v%d.%d r%d", major, minor, revision); rval = mosquitto_lib_init(); if (rval != MOSQ_ERR_SUCCESS) { error("Cannot initialize library: '%s'", mosquitto_strerror(rval)); } else { inst = (mqtt_t) calloc(sizeof(struct mqtt_struct_t), 1); if (inst == NULL) { error("Cannot allocate mqtt"); } } return inst; }
static int mqtt_write(void* userdata) { mqtt_t inst = (mqtt_t) userdata; int rval; rval = mosquitto_loop_write(inst->mosq, 1); switch (rval) { case MOSQ_ERR_SUCCESS: break; case MOSQ_ERR_NO_CONN: case MOSQ_ERR_CONN_LOST: break; case MOSQ_ERR_INVAL: case MOSQ_ERR_NOMEM: case MOSQ_ERR_PROTOCOL: case MOSQ_ERR_ERRNO: default: error("mosquitto_loop_write: %s", mosquitto_strerror(rval)); break; } return 0; }
int mqtt_publish_message(struct mqtt *mqtt, const char *topic, const char *fmt, ...) { char *message; va_list ap; int ret; int err = 0; if (!mqtt || !topic || !fmt) return EINVAL; va_start(ap, fmt); err = re_vsdprintf(&message, fmt, ap); va_end(ap); if (err) return err; ret = mosquitto_publish(mqtt->mosq, NULL, topic, (int)str_len(message), message, 0, false); if (ret != MOSQ_ERR_SUCCESS) { warning("mqtt: failed to publish (%s)\n", mosquitto_strerror(ret)); err = EINVAL; goto out; } out: mem_deref(message); return err; }
int serial_in(int sd, struct mosquitto *mosq, char *md_id) { static char serial_buf[SERIAL_MAX_BUF]; static int buf_len = 0; char *buf_p; char id[DEVICE_ID_SIZE + 1]; struct device *dev; int rc, sread; if (buf_len) buf_p = &serial_buf[buf_len - 1]; else buf_p = &serial_buf[0]; sread = serialport_read_until(sd, buf_p, eolchar, SERIAL_MAX_BUF - buf_len, config.serial.timeout); if (sread == -1) { fprintf(stderr, "Serial - Read Error.\n"); return -1; } if (sread == 0) return 0; buf_len += sread; if (serial_buf[buf_len - 1] == eolchar) { serial_buf[buf_len - 1] = 0; //replace eolchar buf_len--; // eolchar was counted, decreasing 1 if (config.debug > 3) printf("Serial - size:%d, serial_buf:%s\n", buf_len, serial_buf); if (buf_len < SERIAL_INIT_LEN) { // We need at least SERIAL_INIT_LEN to count as a valid command if (config.debug > 1) printf("Invalid serial input.\n"); buf_len = 0; return 0; } sread = buf_len; // for return buf_len = 0; // reseting for the next input buf_p = &serial_buf[SERIAL_INIT_LEN]; // Serial debug if (!strncmp(serial_buf, SERIAL_INIT_DEBUG, SERIAL_INIT_LEN)) { if (config.debug) { printf("Device Debug: %s\n", buf_p); snprintf(gbuf, GBUF_SIZE, "%d,%s,%d,%s", PROTOCOL_MD_OPTIONS, MODULES_BRIDGE_ID, MODULES_BRIDGE_DEBUG, buf_p); mqtt_publish(mosq, bridge.bridge_dev->status_topic, gbuf); } return sread; } else if ((!strncmp(serial_buf, SERIAL_INIT_STATUS, SERIAL_INIT_LEN)) || (!strncmp(serial_buf, SERIAL_INIT_CONFIG, SERIAL_INIT_LEN))) { if (config.debug > 2) printf("Serial IN - Message: %s\n", serial_buf); // Get device id from buf if (utils_getString(&buf_p, id, DEVICE_ID_SIZE, ',') != DEVICE_ID_SIZE) { if (config.debug > 1) printf("Serial - Error: %d\n", ERROR_MIS_DEVICE_ID); return 0; } if (!bridge_isValid_device_id(id)) { if (config.debug > 1) printf("Serial - Error: %d\n", ERROR_DEV_INV_ID); return 0; } dev = bridge_get_device(&bridge, id); if (!dev) { dev = bridge_add_device(&bridge, id, md_id); if (!dev) { if (config.debug > 1) printf("Serial - Failed to add device.\n"); return sread; } rc = mosquitto_subscribe(mosq, NULL, dev->config_topic, config.mqtt_qos); if (rc) { fprintf(stderr, "MQTT - Subscribe ERROR: %s\n", mosquitto_strerror(rc)); run = 0; return sread; } if (config.debug > 2) printf("Subscribe topic: %s\n", bridge.bridge_dev->config_topic); if (config.debug > 2) { printf("New device:\n"); bridge_print_device(dev); } } if (!strncmp(serial_buf, SERIAL_INIT_CONFIG, SERIAL_INIT_LEN)) { // Get device id from buf if (utils_getString(&buf_p, id, DEVICE_ID_SIZE, ',') != DEVICE_ID_SIZE) { if (config.debug > 1) printf("Serial - Error: %d\n", ERROR_MIS_DEVICE_ID); return 0; } if (!bridge_isValid_device_id(id)) { if (config.debug > 1) printf("Serial - Error: %d\n", ERROR_DEV_INV_ID); return 0; } device_config_to_mqtt(mosq, sd, dev, id, buf_p); } else { device_status_to_mqtt(mosq, sd, dev, buf_p); } } else { if (config.debug > 1) printf("Unknown serial data.\n"); } return sread; } else if (buf_len == SERIAL_MAX_BUF) { if (config.debug > 1) printf("Serial buffer full.\n"); buf_len = 0; } else { if (config.debug > 1) printf("Serial chunked.\n"); } return 0; }
const char* strerror(int mosq_errno) { return mosquitto_strerror(mosq_errno); }
int main(int argc, char *argv[]) { struct mosq_config cfg; char buf[1024]; struct mosquitto *mosq = NULL; int rc; int rc2; rc = client_config_load(&cfg, CLIENT_PUB, argc, argv); if(rc){ client_config_cleanup(&cfg); if(rc == 2){ /* --help */ print_usage(); }else{ fprintf(stderr, "\nUse 'mosquitto_pub --help' to see usage.\n"); } return 1; } topic = cfg.topic; message = cfg.message; msglen = cfg.msglen; qos = cfg.qos; retain = cfg.retain; mode = cfg.pub_mode; username = cfg.username; password = cfg.password; quiet = cfg.quiet; if(cfg.pub_mode == MSGMODE_STDIN_FILE){ if(load_stdin()){ fprintf(stderr, "Error loading input from stdin.\n"); return 1; } }else if(cfg.file_input){ if(load_file(cfg.file_input)){ fprintf(stderr, "Error loading input file \"%s\".\n", cfg.file_input); return 1; } } if(!topic || mode == MSGMODE_NONE){ fprintf(stderr, "Error: Both topic and message must be supplied.\n"); print_usage(); return 1; } mosquitto_lib_init(); if(client_id_generate(&cfg, "mosqpub")){ return 1; } mosq = mosquitto_new(cfg.id, true, NULL); if(!mosq){ switch(errno){ case ENOMEM: if(!quiet) fprintf(stderr, "Error: Out of memory.\n"); break; case EINVAL: if(!quiet) fprintf(stderr, "Error: Invalid id.\n"); break; } mosquitto_lib_cleanup(); return 1; } if(cfg.debug){ mosquitto_log_callback_set(mosq, my_log_callback); } mosquitto_connect_callback_set(mosq, my_connect_callback); mosquitto_disconnect_callback_set(mosq, my_disconnect_callback); mosquitto_publish_callback_set(mosq, my_publish_callback); if(client_opts_set(mosq, &cfg)){ return 1; } rc = client_connect(mosq, &cfg); if(rc) return rc; if(mode == MSGMODE_STDIN_LINE){ mosquitto_loop_start(mosq); } do{ if(mode == MSGMODE_STDIN_LINE){ if(status == STATUS_CONNACK_RECVD){ if(fgets(buf, 1024, stdin)){ buf[strlen(buf)-1] = '\0'; rc2 = mosquitto_publish(mosq, &mid_sent, topic, strlen(buf), buf, qos, retain); if(rc2){ if(!quiet) fprintf(stderr, "Error: Publish returned %d, disconnecting.\n", rc2); mosquitto_disconnect(mosq); } }else if(feof(stdin)){ last_mid = mid_sent; status = STATUS_WAITING; } }else if(status == STATUS_WAITING){ if(last_mid_sent == last_mid && disconnect_sent == false){ mosquitto_disconnect(mosq); disconnect_sent = true; } #ifdef WIN32 Sleep(100); #else usleep(100000); #endif } rc = MOSQ_ERR_SUCCESS; }else{ rc = mosquitto_loop(mosq, -1, 1); } }while(rc == MOSQ_ERR_SUCCESS && connected); if(mode == MSGMODE_STDIN_LINE){ mosquitto_loop_stop(mosq, false); } if(message && mode == MSGMODE_FILE){ free(message); } mosquitto_destroy(mosq); mosquitto_lib_cleanup(); if(rc){ fprintf(stderr, "Error: %s\n", mosquitto_strerror(rc)); } return rc; }
int main(int argc, char *argv[]) { char *id = NULL; char *id_prefix = NULL; int i; char *host = "localhost"; int port = 1883; int keepalive = 60; char buf[1024]; bool debug = false; struct mosquitto *mosq = NULL; int rc; int rc2; char hostname[256]; char err[1024]; int len; char *will_payload = NULL; long will_payloadlen = 0; int will_qos = 0; bool will_retain = false; char *will_topic = NULL; char *cafile = NULL; char *capath = NULL; char *certfile = NULL; char *keyfile = NULL; char *psk = NULL; char *psk_identity = NULL; for(i=1; i<argc; i++){ if(!strcmp(argv[i], "-p") || !strcmp(argv[i], "--port")){ if(i==argc-1){ fprintf(stderr, "Error: -p argument given but no port specified.\n\n"); print_usage(); return 1; }else{ port = atoi(argv[i+1]); if(port<1 || port>65535){ fprintf(stderr, "Error: Invalid port given: %d\n", port); print_usage(); return 1; } } i++; }else if(!strcmp(argv[i], "--cafile")){ if(i==argc-1){ fprintf(stderr, "Error: --cafile argument given but no file specified.\n\n"); print_usage(); return 1; }else{ cafile = argv[i+1]; } i++; }else if(!strcmp(argv[i], "--capath")){ if(i==argc-1){ fprintf(stderr, "Error: --capath argument given but no directory specified.\n\n"); print_usage(); return 1; }else{ capath = argv[i+1]; } i++; }else if(!strcmp(argv[i], "--cert")){ if(i==argc-1){ fprintf(stderr, "Error: --cert argument given but no file specified.\n\n"); print_usage(); return 1; }else{ certfile = argv[i+1]; } i++; }else if(!strcmp(argv[i], "-d") || !strcmp(argv[i], "--debug")){ debug = true; }else if(!strcmp(argv[i], "-f") || !strcmp(argv[i], "--file")){ if(mode != MSGMODE_NONE){ fprintf(stderr, "Error: Only one type of message can be sent at once.\n\n"); print_usage(); return 1; }else if(i==argc-1){ fprintf(stderr, "Error: -f argument given but no file specified.\n\n"); print_usage(); return 1; }else{ if(load_file(argv[i+1])) return 1; } i++; }else if(!strcmp(argv[i], "--help")){ print_usage(); return 0; }else if(!strcmp(argv[i], "-h") || !strcmp(argv[i], "--host")){ if(i==argc-1){ fprintf(stderr, "Error: -h argument given but no host specified.\n\n"); print_usage(); return 1; }else{ host = argv[i+1]; } i++; }else if(!strcmp(argv[i], "-i") || !strcmp(argv[i], "--id")){ if(id_prefix){ fprintf(stderr, "Error: -i and -I argument cannot be used together.\n\n"); print_usage(); return 1; } if(i==argc-1){ fprintf(stderr, "Error: -i argument given but no id specified.\n\n"); print_usage(); return 1; }else{ id = argv[i+1]; } i++; }else if(!strcmp(argv[i], "-I") || !strcmp(argv[i], "--id-prefix")){ if(id){ fprintf(stderr, "Error: -i and -I argument cannot be used together.\n\n"); print_usage(); return 1; } if(i==argc-1){ fprintf(stderr, "Error: -I argument given but no id prefix specified.\n\n"); print_usage(); return 1; }else{ id_prefix = argv[i+1]; } i++; }else if(!strcmp(argv[i], "--key")){ if(i==argc-1){ fprintf(stderr, "Error: --key argument given but no file specified.\n\n"); print_usage(); return 1; }else{ keyfile = argv[i+1]; } i++; }else if(!strcmp(argv[i], "-l") || !strcmp(argv[i], "--stdin-line")){ if(mode != MSGMODE_NONE){ fprintf(stderr, "Error: Only one type of message can be sent at once.\n\n"); print_usage(); return 1; }else{ mode = MSGMODE_STDIN_LINE; } }else if(!strcmp(argv[i], "-m") || !strcmp(argv[i], "--message")){ if(mode != MSGMODE_NONE){ fprintf(stderr, "Error: Only one type of message can be sent at once.\n\n"); print_usage(); return 1; }else if(i==argc-1){ fprintf(stderr, "Error: -m argument given but no message specified.\n\n"); print_usage(); return 1; }else{ message = argv[i+1]; msglen = strlen(message); mode = MSGMODE_CMD; } i++; }else if(!strcmp(argv[i], "-n") || !strcmp(argv[i], "--null-message")){ if(mode != MSGMODE_NONE){ fprintf(stderr, "Error: Only one type of message can be sent at once.\n\n"); print_usage(); return 1; }else{ mode = MSGMODE_NULL; } }else if(!strcmp(argv[i], "--psk")){ if(i==argc-1){ fprintf(stderr, "Error: --psk argument given but no key specified.\n\n"); print_usage(); return 1; }else{ psk = argv[i+1]; } i++; }else if(!strcmp(argv[i], "--psk-identity")){ if(i==argc-1){ fprintf(stderr, "Error: --psk-identity argument given but no identity specified.\n\n"); print_usage(); return 1; }else{ psk_identity = argv[i+1]; } i++; }else if(!strcmp(argv[i], "-q") || !strcmp(argv[i], "--qos")){ if(i==argc-1){ fprintf(stderr, "Error: -q argument given but no QoS specified.\n\n"); print_usage(); return 1; }else{ qos = atoi(argv[i+1]); if(qos<0 || qos>2){ fprintf(stderr, "Error: Invalid QoS given: %d\n", qos); print_usage(); return 1; } } i++; }else if(!strcmp(argv[i], "--quiet")){ quiet = true; }else if(!strcmp(argv[i], "-r") || !strcmp(argv[i], "--retain")){ retain = 1; }else if(!strcmp(argv[i], "-s") || !strcmp(argv[i], "--stdin-file")){ if(mode != MSGMODE_NONE){ fprintf(stderr, "Error: Only one type of message can be sent at once.\n\n"); print_usage(); return 1; }else{ if(load_stdin()) return 1; } }else if(!strcmp(argv[i], "-t") || !strcmp(argv[i], "--topic")){ if(i==argc-1){ fprintf(stderr, "Error: -t argument given but no topic specified.\n\n"); print_usage(); return 1; }else{ topic = argv[i+1]; } i++; }else if(!strcmp(argv[i], "-u") || !strcmp(argv[i], "--username")){ if(i==argc-1){ fprintf(stderr, "Error: -u argument given but no username specified.\n\n"); print_usage(); return 1; }else{ username = argv[i+1]; } i++; }else if(!strcmp(argv[i], "-P") || !strcmp(argv[i], "--pw")){ if(i==argc-1){ fprintf(stderr, "Error: -P argument given but no password specified.\n\n"); print_usage(); return 1; }else{ password = argv[i+1]; } i++; }else if(!strcmp(argv[i], "--will-payload")){ if(i==argc-1){ fprintf(stderr, "Error: --will-payload argument given but no will payload specified.\n\n"); print_usage(); return 1; }else{ will_payload = argv[i+1]; will_payloadlen = strlen(will_payload); } i++; }else if(!strcmp(argv[i], "--will-qos")){ if(i==argc-1){ fprintf(stderr, "Error: --will-qos argument given but no will QoS specified.\n\n"); print_usage(); return 1; }else{ will_qos = atoi(argv[i+1]); if(will_qos < 0 || will_qos > 2){ fprintf(stderr, "Error: Invalid will QoS %d.\n\n", will_qos); return 1; } } i++; }else if(!strcmp(argv[i], "--will-retain")){ will_retain = true; }else if(!strcmp(argv[i], "--will-topic")){ if(i==argc-1){ fprintf(stderr, "Error: --will-topic argument given but no will topic specified.\n\n"); print_usage(); return 1; }else{ will_topic = argv[i+1]; } i++; }else{ fprintf(stderr, "Error: Unknown option '%s'.\n",argv[i]); print_usage(); return 1; } } if(!topic || mode == MSGMODE_NONE){ fprintf(stderr, "Error: Both topic and message must be supplied.\n"); print_usage(); return 1; } if(will_payload && !will_topic){ fprintf(stderr, "Error: Will payload given, but no will topic given.\n"); print_usage(); return 1; } if(will_retain && !will_topic){ fprintf(stderr, "Error: Will retain given, but no will topic given.\n"); print_usage(); return 1; } if(password && !username){ if(!quiet) fprintf(stderr, "Warning: Not using password since username not set.\n"); } if((certfile && !keyfile) || (keyfile && !certfile)){ fprintf(stderr, "Error: Both certfile and keyfile must be provided if one of them is.\n"); print_usage(); return 1; } if((cafile || capath) && psk){ if(!quiet) fprintf(stderr, "Error: Only one of --psk or --cafile/--capath may be used at once.\n"); return 1; } if(psk && !psk_identity){ if(!quiet) fprintf(stderr, "Error: --psk-identity required if --psk used.\n"); return 1; } mosquitto_lib_init(); if(id_prefix){ id = malloc(strlen(id_prefix)+10); if(!id){ if(!quiet) fprintf(stderr, "Error: Out of memory.\n"); mosquitto_lib_cleanup(); return 1; } snprintf(id, strlen(id_prefix)+10, "%s%d", id_prefix, getpid()); }else if(!id){ hostname[0] = '\0'; gethostname(hostname, 256); hostname[255] = '\0'; len = strlen("mosqpub/-") + 6 + strlen(hostname); id = malloc(len); if(!id){ if(!quiet) fprintf(stderr, "Error: Out of memory.\n"); mosquitto_lib_cleanup(); return 1; } snprintf(id, len, "mosqpub/%d-%s", getpid(), hostname); if(strlen(id) > MOSQ_MQTT_ID_MAX_LENGTH){ /* Enforce maximum client id length of 23 characters */ id[MOSQ_MQTT_ID_MAX_LENGTH] = '\0'; } } mosq = mosquitto_new(id, true, NULL); if(!mosq){ switch(errno){ case ENOMEM: if(!quiet) fprintf(stderr, "Error: Out of memory.\n"); break; case EINVAL: if(!quiet) fprintf(stderr, "Error: Invalid id.\n"); break; } mosquitto_lib_cleanup(); return 1; } if(debug){ mosquitto_log_callback_set(mosq, my_log_callback); } if(will_topic && mosquitto_will_set(mosq, will_topic, will_payloadlen, will_payload, will_qos, will_retain)){ if(!quiet) fprintf(stderr, "Error: Problem setting will.\n"); mosquitto_lib_cleanup(); return 1; } if(username && mosquitto_username_pw_set(mosq, username, password)){ if(!quiet) fprintf(stderr, "Error: Problem setting username and password.\n"); mosquitto_lib_cleanup(); return 1; } if((cafile || capath) && mosquitto_tls_set(mosq, cafile, capath, certfile, keyfile, NULL)){ if(!quiet) fprintf(stderr, "Error: Problem setting TLS options.\n"); mosquitto_lib_cleanup(); return 1; } if(psk && mosquitto_tls_psk_set(mosq, psk, psk_identity, NULL)){ if(!quiet) fprintf(stderr, "Error: Problem setting TLS-PSK options.\n"); mosquitto_lib_cleanup(); return 1; } mosquitto_connect_callback_set(mosq, my_connect_callback); mosquitto_disconnect_callback_set(mosq, my_disconnect_callback); mosquitto_publish_callback_set(mosq, my_publish_callback); rc = mosquitto_connect(mosq, host, port, keepalive); if(rc){ if(!quiet){ if(rc == MOSQ_ERR_ERRNO){ #ifndef WIN32 strerror_r(errno, err, 1024); #else FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, errno, 0, (LPTSTR)&err, 1024, NULL); #endif fprintf(stderr, "Error: %s\n", err); }else{ fprintf(stderr, "Unable to connect (%d).\n", rc); } } mosquitto_lib_cleanup(); return rc; } if(mode == MSGMODE_STDIN_LINE){ mosquitto_loop_start(mosq); } do{ if(mode == MSGMODE_STDIN_LINE){ if(status == STATUS_CONNACK_RECVD){ if(fgets(buf, 1024, stdin)){ buf[strlen(buf)-1] = '\0'; rc2 = mosquitto_publish(mosq, &mid_sent, topic, strlen(buf), buf, qos, retain); if(rc2){ if(!quiet) fprintf(stderr, "Error: Publish returned %d, disconnecting.\n", rc2); mosquitto_disconnect(mosq); } }else if(feof(stdin)){ last_mid = mid_sent; status = STATUS_WAITING; } }else if(status == STATUS_WAITING){ #ifdef WIN32 Sleep(1000); #else usleep(1000000); #endif } rc = MOSQ_ERR_SUCCESS; }else{ rc = mosquitto_loop(mosq, -1, 1); } }while(rc == MOSQ_ERR_SUCCESS && connected); if(mode == MSGMODE_STDIN_LINE){ mosquitto_loop_stop(mosq, false); } if(message && mode == MSGMODE_FILE){ free(message); } mosquitto_destroy(mosq); mosquitto_lib_cleanup(); if(rc){ if(rc == MOSQ_ERR_ERRNO){ fprintf(stderr, "Error: %s\n", strerror(errno)); }else{ fprintf(stderr, "Error: %s\n", mosquitto_strerror(rc)); } } return rc; }
int main(int argc, char *argv[]) { struct mosquitto *mosq = NULL; int rc; mosquitto_lib_init(); if(pub_shared_init()) return 1; memset(&cfg, 0, sizeof(struct mosq_config)); rc = client_config_load(&cfg, CLIENT_PUB, argc, argv); if(rc){ if(rc == 2){ /* --help */ print_usage(); }else{ fprintf(stderr, "\nUse 'mosquitto_pub --help' to see usage.\n"); } goto cleanup; } #ifndef WITH_THREADING if(cfg.pub_mode == MSGMODE_STDIN_LINE){ fprintf(stderr, "Error: '-l' mode not available, threading support has not been compiled in.\n"); goto cleanup; } #endif if(cfg.pub_mode == MSGMODE_STDIN_FILE){ if(load_stdin()){ fprintf(stderr, "Error loading input from stdin.\n"); goto cleanup; } }else if(cfg.file_input){ if(load_file(cfg.file_input)){ fprintf(stderr, "Error loading input file \"%s\".\n", cfg.file_input); goto cleanup; } } if(!cfg.topic || cfg.pub_mode == MSGMODE_NONE){ fprintf(stderr, "Error: Both topic and message must be supplied.\n"); print_usage(); goto cleanup; } if(client_id_generate(&cfg)){ goto cleanup; } mosq = mosquitto_new(cfg.id, true, NULL); if(!mosq){ switch(errno){ case ENOMEM: if(!cfg.quiet) fprintf(stderr, "Error: Out of memory.\n"); break; case EINVAL: if(!cfg.quiet) fprintf(stderr, "Error: Invalid id.\n"); break; } goto cleanup; } if(cfg.debug){ mosquitto_log_callback_set(mosq, my_log_callback); } mosquitto_connect_v5_callback_set(mosq, my_connect_callback); mosquitto_disconnect_v5_callback_set(mosq, my_disconnect_callback); mosquitto_publish_v5_callback_set(mosq, my_publish_callback); if(client_opts_set(mosq, &cfg)){ goto cleanup; } rc = client_connect(mosq, &cfg); if(rc){ goto cleanup; } rc = pub_shared_loop(mosq); if(cfg.message && cfg.pub_mode == MSGMODE_FILE){ free(cfg.message); } mosquitto_destroy(mosq); mosquitto_lib_cleanup(); client_config_cleanup(&cfg); pub_shared_cleanup(); if(rc){ fprintf(stderr, "Error: %s\n", mosquitto_strerror(rc)); } return rc; cleanup: mosquitto_lib_cleanup(); client_config_cleanup(&cfg); pub_shared_cleanup(); return 1; }
//int subscribeFromMaster(char* _host, int _port, char* _topic) void subscribeFromMaster(struct client_config *s_cfg) { struct mosq_config cfg; struct mosquitto *mosq = NULL; char *temp[] = {"mosquitto_sub","-h","163.180.117.97","-t","test","-p","10011",}; int rc; rc = client_config_load(&cfg, CLIENT_SUB, 7, temp); if(rc){ client_config_cleanup(&cfg); if(rc == 2){ /* --help */ print_usage(); }else{ fprintf(stderr, "\nUse 'mosquitto_sub --help' to see usage.\n"); } return ; } cfg.port = s_cfg->port; cfg.host = (char*)malloc(strlen(s_cfg->host)); strcpy(cfg.host, s_cfg->host); cfg.topic = (char*)malloc(strlen(s_cfg->topic)); strcpy(cfg.topic, s_cfg->topic); cfg.topic_count = 1; printf("===================================================\n"); printf("---------------------------------------------------\n"); printf(" SUBSCRIBE FROM CLIENT!\n"); printf("#HOST : %s\n", cfg.host); printf("PORT : %d\n", cfg.port); printf("TOPIC : %s\n", cfg.topic); printf("---------------------------------------------------\n"); printf("===================================================\n"); //mosquitto_lib_init(); if(client_id_generate(&cfg, "mosqsub")){ return ; } mosq = mosquitto_new("monitor", cfg.clean_session, &cfg); if(!mosq){ switch(errno){ case ENOMEM: if(!cfg.quiet) fprintf(stderr, "Error: Out of memory.\n"); break; case EINVAL: if(!cfg.quiet) fprintf(stderr, "Error: Invalid id and/or clean_session.\n"); break; } mosquitto_lib_cleanup(); return ; } if(client_opts_set(mosq, &cfg)){ return ; } if(cfg.debug){ mosquitto_log_callback_set(mosq, my_log_callback); mosquitto_subscribe_callback_set(mosq, my_subscribe_callback); } mosquitto_connect_callback_set(mosq, my_connect_callback); mosquitto_message_callback_set(mosq, my_message_callback); rc = client_connect(mosq, &cfg); if(rc) return ; masterMosq = mosq; rc = mosquitto_loop_forever(mosq, -1, 1); mosquitto_destroy(mosq); mosquitto_lib_cleanup(); if(cfg.msg_count>0 && rc == MOSQ_ERR_NO_CONN){ rc = 0; } if(rc){ fprintf(stderr, "Error: %s\n", mosquitto_strerror(rc)); } return ; }
int main(int argc, char *argv[]) { int sd = -1; char *conf_file = NULL; struct mosquitto *mosq; struct module *md; struct device *dev; int rc; int i; gbuf[0] = 0; if (!quiet) printf("Version: %s\n", version); signal(SIGINT, handle_signal); signal(SIGTERM, handle_signal); signal(SIGUSR1, handle_signal); signal(SIGUSR2, handle_signal); signal(SIGALRM, each_sec); for (i=1; i<argc; i++) { if(!strcmp(argv[i], "-c") || !strcmp(argv[i], "--config")){ if(i==argc-1){ fprintf(stderr, "Error: -c argument given but no file specified.\n\n"); print_usage(argv[0]); return 1; }else{ conf_file = argv[i+1]; } i++; }else if(!strcmp(argv[i], "--quiet")){ quiet = true; }else{ fprintf(stderr, "Error: Unknown option '%s'.\n",argv[i]); print_usage(argv[0]); return 1; } } if (!conf_file) { fprintf(stderr, "Error: No config file given.\n"); return 1; } memset(&config, 0, sizeof(struct bridge_config)); if (config_parse(conf_file, &config)) return 1; if (quiet) config.debug = 0; if (config.debug != 0) printf("Debug: %d\n", config.debug); rc = bridge_init(&bridge, config.id, MODULES_BRIDGE_ID); if (rc) { if (config.debug) printf("Error: Failed to initialize bridge: %d\n", rc); return 1; } mosquitto_lib_init(); mosq = mosquitto_new(config.id, true, NULL); if(!mosq){ fprintf(stderr, "Error creating mqtt instance.\n"); switch(errno){ case ENOMEM: fprintf(stderr, " out of memory.\n"); break; case EINVAL: fprintf(stderr, " invalid id.\n"); break; } return 1; } snprintf(gbuf, GBUF_SIZE, "%d", PROTOCOL_TIMEOUT); mosquitto_will_set(mosq, bridge.bridge_dev->status_topic, strlen(gbuf), gbuf, config.mqtt_qos, MQTT_RETAIN); mosquitto_connect_callback_set(mosq, on_mqtt_connect); mosquitto_disconnect_callback_set(mosq, on_mqtt_disconnect); mosquitto_message_callback_set(mosq, on_mqtt_message); mosquitto_user_data_set(mosq, &sd); md = bridge_add_module(bridge.bridge_dev, MODULES_MQTT_ID, true); if (!md) { fprintf(stderr, "Failed to add MQTT module.\n"); return 1; } if (config.scripts_folder) { if (access(config.scripts_folder, R_OK )) { fprintf(stderr, "Couldn't open scripts folder: %s\n", config.scripts_folder); return 1; } md = bridge_add_module(bridge.bridge_dev, MODULES_SCRIPT_ID, true); if (!md) { fprintf(stderr, "Failed to add script module.\n"); return 1; } } if (config.interface) { //TODO: check if interface exists if (access("/proc/net/dev", R_OK )) { fprintf(stderr, "Couldn't open /proc/net/dev\n"); return 1; } md = bridge_add_module(bridge.bridge_dev, MODULES_BANDWIDTH_ID, true); if (!md) { fprintf(stderr, "Failed to add bandwidth module.\n"); return 1; } bandwidth = true; } if (config.serial.port) { sd = serialport_init(config.serial.port, config.serial.baudrate); if( sd == -1 ) { fprintf(stderr, "Couldn't open serial port.\n"); return 1; } else { md = bridge_add_module(bridge.bridge_dev, MODULES_SERIAL_ID, true); if (!md) { fprintf(stderr, "Failed to add serial module.\n"); return 1; } serialport_flush(sd); bridge.serial_ready = true; if (config.debug) printf("Serial ready.\n"); } } if (config.debug > 2) bridge_print_modules(bridge.bridge_dev); rc = mosquitto_connect(mosq, config.mqtt_host, config.mqtt_port, 60); if (rc) { fprintf(stderr, "ERROR: %s\n", mosquitto_strerror(rc)); return -1; } alarm(1); while (run) { if (bridge.serial_ready) { rc = serial_in(sd, mosq, MODULES_SERIAL_ID); if (rc == -1) { serial_hang(mosq); } else if (rc > 0) { bridge.serial_alive = DEVICE_ALIVE_MAX; } } if (user_signal) { if (config.debug > 2) printf("Signal - SIGUSR: %d\n", user_signal); signal_usr(sd, mosq); } rc = mosquitto_loop(mosq, 100, 1); if (run && rc) { if (config.debug > 2) printf("MQTT loop: %s\n", mosquitto_strerror(rc)); usleep(100000); // wait 100 msec mosquitto_reconnect(mosq); } usleep(20); if (every1s) { every1s = false; for (dev = bridge.dev_list; dev != NULL; dev = dev->next) { if (dev->alive) { dev->alive--; if (!dev->alive) { if (connected) { snprintf(gbuf, GBUF_SIZE, "%d", PROTOCOL_TIMEOUT); mqtt_publish(mosq, dev->status_topic, gbuf); rc = mosquitto_unsubscribe(mosq, NULL, dev->config_topic); if (rc) fprintf(stderr, "Error: MQTT unsubscribe returned: %s\n", mosquitto_strerror(rc)); } if (config.debug) printf("Device: %s - Timeout.\n", dev->id); bridge_remove_device(&bridge, dev->id); } } } } if (every30s) { every30s = false; if (connected) { send_alive(mosq); if (bandwidth) { md = bridge_get_module(bridge.bridge_dev, MODULES_BANDWIDTH_ID); if (md) { snprintf(gbuf, GBUF_SIZE, "%.0f,%.0f", upspeed, downspeed); mqtt_publish(mosq, md->topic, gbuf); if (config.debug > 2) printf("down: %f - up: %f\n", downspeed, upspeed); } } } else { if (config.debug) printf("MQTT Offline.\n"); } if (bridge.serial_alive) { bridge.serial_alive--; if (!bridge.serial_alive) { if (config.debug > 1) printf("Serial timeout.\n"); serial_hang(mosq); } } else { if (config.serial.port && !bridge.serial_ready) { if (config.debug > 1) printf("Trying to reconnect serial port.\n"); serialport_close(sd); sd = serialport_init(config.serial.port, config.serial.baudrate); if( sd == -1 ) { fprintf(stderr, "Couldn't open serial port.\n"); } else { serialport_flush(sd); bridge.serial_ready = true; snprintf(gbuf, GBUF_SIZE, "%d", MODULES_SERIAL_OPEN); mqtt_publish(mosq, md->topic, gbuf); if (config.debug) printf("Serial reopened.\n"); } } } } } if (bridge.serial_ready) { serialport_close(sd); } mosquitto_destroy(mosq); mosquitto_lib_cleanup(); config_cleanup(&config); printf("Exiting..\n\n"); return 0; }
int pub_shared_loop(struct mosquitto *mosq) { int read_len; int pos; int rc, rc2; char *buf2; int buf_len_actual; int mode; int loop_delay = 1000; if(cfg.repeat_count > 1 && (cfg.repeat_delay.tv_sec == 0 || cfg.repeat_delay.tv_usec != 0)){ loop_delay = cfg.repeat_delay.tv_usec / 2000; } mode = cfg.pub_mode; if(mode == MSGMODE_STDIN_LINE){ mosquitto_loop_start(mosq); } do{ if(mode == MSGMODE_STDIN_LINE){ if(status == STATUS_CONNACK_RECVD){ pos = 0; read_len = line_buf_len; while(connected && fgets(&line_buf[pos], read_len, stdin)){ buf_len_actual = strlen(line_buf); if(line_buf[buf_len_actual-1] == '\n'){ line_buf[buf_len_actual-1] = '\0'; rc2 = my_publish(mosq, &mid_sent, cfg.topic, buf_len_actual-1, line_buf, cfg.qos, cfg.retain); if(rc2){ if(!cfg.quiet) fprintf(stderr, "Error: Publish returned %d, disconnecting.\n", rc2); mosquitto_disconnect_v5(mosq, MQTT_RC_DISCONNECT_WITH_WILL_MSG, cfg.disconnect_props); } break; }else{ line_buf_len += 1024; pos += 1023; read_len = 1024; buf2 = realloc(line_buf, line_buf_len); if(!buf2){ fprintf(stderr, "Error: Out of memory.\n"); return MOSQ_ERR_NOMEM; } line_buf = buf2; } } if(feof(stdin)){ if(mid_sent == -1){ /* Empty file */ mosquitto_disconnect_v5(mosq, 0, cfg.disconnect_props); disconnect_sent = true; status = STATUS_DISCONNECTING; }else{ last_mid = mid_sent; status = STATUS_WAITING; } } }else if(status == STATUS_WAITING){ if(last_mid_sent == last_mid && disconnect_sent == false){ mosquitto_disconnect_v5(mosq, 0, cfg.disconnect_props); disconnect_sent = true; } #ifdef WIN32 Sleep(100); #else struct timespec ts; ts.tv_sec = 0; ts.tv_nsec = 100000000; nanosleep(&ts, NULL); #endif } rc = MOSQ_ERR_SUCCESS; }else{ rc = mosquitto_loop(mosq, loop_delay, 1); if(ready_for_repeat && check_repeat_time()){ rc = 0; switch(cfg.pub_mode){ case MSGMODE_CMD: case MSGMODE_FILE: case MSGMODE_STDIN_FILE: rc = my_publish(mosq, &mid_sent, cfg.topic, cfg.msglen, cfg.message, cfg.qos, cfg.retain); break; case MSGMODE_NULL: rc = my_publish(mosq, &mid_sent, cfg.topic, 0, NULL, cfg.qos, cfg.retain); break; case MSGMODE_STDIN_LINE: break; } if(rc){ fprintf(stderr, "Error sending repeat publish: %s", mosquitto_strerror(rc)); } } } }while(rc == MOSQ_ERR_SUCCESS && connected); if(mode == MSGMODE_STDIN_LINE){ mosquitto_loop_stop(mosq, false); } return 0; }
int main(int argc, char *argv[]) { struct mosq_config cfg; int rc; #ifndef WIN32 struct sigaction sigact; #endif memset(&cfg, 0, sizeof(struct mosq_config)); rc = client_config_load(&cfg, CLIENT_SUB, argc, argv); if(rc){ client_config_cleanup(&cfg); if(rc == 2){ /* --help */ print_usage(); }else{ fprintf(stderr, "\nUse 'mosquitto_sub --help' to see usage.\n"); } return 1; } if(cfg.no_retain && cfg.retained_only){ fprintf(stderr, "\nError: Combining '-R' and '--retained-only' makes no sense.\n"); return 1; } mosquitto_lib_init(); if(client_id_generate(&cfg, "mosqsub")){ return 1; } mosq = mosquitto_new(cfg.id, cfg.clean_session, &cfg); cfg.idtext = cfg.id; if(!mosq){ switch(errno){ case ENOMEM: if(!cfg.quiet) fprintf(stderr, "Error: Out of memory.\n"); break; case EINVAL: if(!cfg.quiet) fprintf(stderr, "Error: Invalid id and/or clean_session.\n"); break; } mosquitto_lib_cleanup(); return 1; } if(client_opts_set(mosq, &cfg)){ return 1; } if(cfg.debug){ mosquitto_log_callback_set(mosq, my_log_callback); mosquitto_subscribe_callback_set(mosq, my_subscribe_callback); } mosquitto_connect_with_flags_callback_set(mosq, my_connect_callback); if(cfg.isfmask) { mosquitto_message_callback_set(mosq, my_message_file_callback); } else { mosquitto_message_callback_set(mosq, my_message_callback); } rc = client_connect(mosq, &cfg); if(rc) return rc; #ifndef WIN32 sigact.sa_handler = my_signal_handler; sigemptyset(&sigact.sa_mask); sigact.sa_flags = 0; if(sigaction(SIGALRM, &sigact, NULL) == -1){ perror("sigaction"); return 1; } if(cfg.timeout){ alarm(cfg.timeout); } #endif rc = mosquitto_loop_forever(mosq, -1, 1); mosquitto_destroy(mosq); mosquitto_lib_cleanup(); if(cfg.msg_count>0 && rc == MOSQ_ERR_NO_CONN){ rc = 0; } if(rc){ fprintf(stderr, "Error: %s\n", mosquitto_strerror(rc)); } return rc; }
static void raw_event(const char *data, int controllerId, int callbackId, void *context) { struct context *ctx = context; struct relay_rule *relay_rules = ctx->relay_rules; if(ctx->debug>1) printf("raw_event: %s\n", data); struct telldus_data d; telldus_data_init(&d,data); int f = 0; for(f=0; f<ctx->num_relay_rules; f++) { int i = 0; int accepted = 1; // ensure all filters match in this relay_rule specification while(relay_rules[f].filters[i].key && relay_rules[f].filters[i].value && accepted) { char expected[256]; telldus_data_get_value(expected, sizeof(expected)-1, relay_rules[f].filters[i].key, &d); accepted &= !strcmp(expected, relay_rules[f].filters[i].value); i++; } int j = 0; if(accepted) { // matched, now format and deliver messages on all associated mqtt_templates while(relay_rules[f].mqtt_template[j].topicformat && relay_rules[f].mqtt_template[j].messageformat && ! ctx->failures) { char topic[1024]; char publish_topic[1024]; char message[256]; format_message(topic, sizeof(topic)-1, relay_rules[f].mqtt_template[j].topicformat, &d); format_message(message, sizeof(topic)-1, relay_rules[f].mqtt_template[j].messageformat, &d); snprintf(publish_topic,sizeof(publish_topic), "%s%s",ctx->pub_prefix,topic); int rc2; static int mid_sent = 0; rc2 = mosquitto_publish(ctx->mosq, &mid_sent, publish_topic, strlen(message), (uint8_t *)message, relay_rules[f].mqtt_template[j].qos, relay_rules[f].mqtt_template[j].retain); if(rc2) { fprintf(stderr, "Error: mosquitto_publish() returned %d: %s.\n", rc2, mosquitto_strerror(rc2)); // ignore failures for now, telldus callbacks can appear before MQTT connection is established // ctx->failures++; } if(ctx->debug>3) fprintf(stderr, "Done with template %d.\n", j); j++; } } } telldus_data_release(&d); }
void mqtt_cb_disconnect(struct mosquitto *mosq, void *userdat, int rc) { printf("MQTT disconnect, error: %d: %s\n", rc, mosquitto_strerror(rc)); }
/* * ########################## * Main Function * ########################## */ int main(int argc, char *argv[]) { /* program setup variable */ struct mosquitto *mosq = NULL; struct mqtt_userdata *ud = NULL; unsigned int max_inflight = 20; bool debug = false; char buf[MQTT_BUFSIZE]; char err[MQTT_ERR_BUFSIZE]; /* client id */ char id[MQTT_ID_LEN]; char id_prefix[MQTT_ID_LEN]; char hostname[MQTT_HOSTNAME_BUFSIZE]; /* broker variable */ char host[MQTT_IP_LEN] = "127.0.0.1"; int port = 1883; int keepalive = 60; /* will information */ char *will_topic = NULL; long will_payloadlen = 0; char *will_payload = NULL; int will_qos = 0; bool will_retain = false; /* temp variable */ int i; int rc; int rc2; /* initialized program and user data structure */ ud = malloc(sizeof(struct mqtt_userdata)); memset(ud, 0, sizeof(struct mqtt_userdata)); ud->last_mid = -1; ud->connected = true; memset(id, '\0', sizeof(id)); memset(id_prefix, '\0', sizeof(id_prefix)); ud->qos = 2; /* get option */ for(i=1; i<argc; i++){ if(!strcmp(argv[i], "-p") || !strcmp(argv[i], "--port")){ if(i==argc-1){ fprintf(stderr, "Error: -p argument given but no port specified.\n\n"); mqtt_print_usage(); return 1; }else{ port = atoi(argv[i+1]); if(port<1 || port>65535){ fprintf(stderr, "Error: Invalid port given: %d\n", port); mqtt_print_usage(); return 1; } } i++; }else if(!strcmp(argv[i], "-d") || !strcmp(argv[i], "--debug")){ debug = true; }else if(!strcmp(argv[i], "-f") || !strcmp(argv[i], "--file")){ if(ud->mode != MQTT_MSGMODE_NONE){ fprintf(stderr, "Error: Only one type of message can be sent at once.\n\n"); mqtt_print_usage(); return 1; }else if(i==argc-1){ fprintf(stderr, "Error: -f argument given but no file specified.\n\n"); mqtt_print_usage(); return 1; }else{ if(mqtt_load_file(argv[i+1], ud)) return 1; } i++; }else if(!strcmp(argv[i], "--help")){ mqtt_print_usage(); return 0; }else if(!strcmp(argv[i], "-h") || !strcmp(argv[i], "--host")){ if(i==argc-1){ fprintf(stderr, "Error: -h argument given but no host specified.\n\n"); mqtt_print_usage(); return 1; }else{ if (strlen(argv[i+1]) >= MQTT_IP_LEN) { fprintf(stderr, "Error: max length of ip is %d.\n\n", MQTT_IP_LEN); mqtt_print_usage(); } else { memset(host, '\0', sizeof(host)); strcpy(host, argv[i+1]); } } i++; }else if(!strcmp(argv[i], "-i") || !strcmp(argv[i], "--id")){ if(strlen(id_prefix) != 0){ fprintf(stderr, "Error: -i and -I argument cannot be used together.\n\n"); mqtt_print_usage(); return 1; } if(i==argc-1){ fprintf(stderr, "Error: -i argument given but no id specified.\n\n"); mqtt_print_usage(); return 1; }else{ if (strlen(argv[i+1]) >= MOSQ_MQTT_ID_MAX_LENGTH) { fprintf(stderr, "Error: max length of client id is %d.\n\n", MOSQ_MQTT_ID_MAX_LENGTH); mqtt_print_usage(); } else { strcpy(id, argv[i+1]); } } i++; }else if(!strcmp(argv[i], "-I") || !strcmp(argv[i], "--id-prefix")){ if(strlen(id) != 0){ fprintf(stderr, "Error: -i and -I argument cannot be used together.\n\n"); mqtt_print_usage(); return 1; } if(i==argc-1){ fprintf(stderr, "Error: -I argument given but no id prefix specified.\n\n"); mqtt_print_usage(); return 1; }else{ if (strlen(argv[i+1]) >= MOSQ_MQTT_ID_MAX_LENGTH) { fprintf(stderr, "Error: max length of client id is %d.\n\n", MOSQ_MQTT_ID_MAX_LENGTH); mqtt_print_usage(); } else { strcpy(id_prefix, argv[i+1]); } } i++; }else if(!strcmp(argv[i], "-l") || !strcmp(argv[i], "--stdin-line")){ if(ud->mode != MQTT_MSGMODE_NONE){ fprintf(stderr, "Error: Only one type of message can be sent at once.\n\n"); mqtt_print_usage(); return 1; }else{ ud->mode = MQTT_MSGMODE_STDIN_LINE; } }else if(!strcmp(argv[i], "-m") || !strcmp(argv[i], "--message")){ if(ud->mode != MQTT_MSGMODE_NONE){ fprintf(stderr, "Error: Only one type of message can be sent at once.\n\n"); mqtt_print_usage(); return 1; }else if(i==argc-1){ fprintf(stderr, "Error: -m argument given but no message specified.\n\n"); mqtt_print_usage(); return 1; }else{ ud->message = argv[i+1]; ud->msglen = strlen(ud->message); ud->mode = MQTT_MSGMODE_CMD; } i++; }else if(!strcmp(argv[i], "-M")){ if(i==argc-1){ fprintf(stderr, "Error: -M argument given but max_inflight not specified.\n\n"); mqtt_print_usage(); return 1; }else{ max_inflight = atoi(argv[i+1]); } i++; }else if(!strcmp(argv[i], "-n") || !strcmp(argv[i], "--null-message")){ if(ud->mode != MQTT_MSGMODE_NONE){ fprintf(stderr, "Error: Only one type of message can be sent at once.\n\n"); mqtt_print_usage(); return 1; }else{ ud->mode = MQTT_MSGMODE_NULL; } }else if(!strcmp(argv[i], "-q") || !strcmp(argv[i], "--qos")){ if(i==argc-1){ fprintf(stderr, "Error: -q argument given but no QoS specified.\n\n"); mqtt_print_usage(); return 1; }else{ ud->qos = atoi(argv[i+1]); if(ud->qos<0 || ud->qos>2){ fprintf(stderr, "Error: Invalid QoS given: %d\n", ud->qos); mqtt_print_usage(); return 1; } } i++; }else if(!strcmp(argv[i], "--quiet")){ ud->quiet = true; }else if(!strcmp(argv[i], "-r") || !strcmp(argv[i], "--retain")){ ud->retain = 1; }else if(!strcmp(argv[i], "-s") || !strcmp(argv[i], "--stdin-file")){ if(ud->mode != MQTT_MSGMODE_NONE){ fprintf(stderr, "Error: Only one type of message can be sent at once.\n\n"); mqtt_print_usage(); return 1; }else{ if(mqtt_load_stdin(ud)) return 1; } }else if(!strcmp(argv[i], "-t") || !strcmp(argv[i], "--topic")){ if(i==argc-1){ fprintf(stderr, "Error: -t argument given but no topic specified.\n\n"); mqtt_print_usage(); return 1; }else{ ud->topic = argv[i+1]; } i++; }else if(!strcmp(argv[i], "-u") || !strcmp(argv[i], "--username")){ if(i==argc-1){ fprintf(stderr, "Error: -u argument given but no username specified.\n\n"); mqtt_print_usage(); return 1; }else{ ud->username = argv[i+1]; } i++; }else if(!strcmp(argv[i], "-P") || !strcmp(argv[i], "--pw")){ if(i==argc-1){ fprintf(stderr, "Error: -P argument given but no password specified.\n\n"); mqtt_print_usage(); return 1; }else{ ud->password = argv[i+1]; } i++; }else if(!strcmp(argv[i], "--will-payload")){ if(i==argc-1){ fprintf(stderr, "Error: --will-payload argument given but no will payload specified.\n\n"); mqtt_print_usage(); return 1; }else{ will_payload = argv[i+1]; will_payloadlen = strlen(will_payload); } i++; }else if(!strcmp(argv[i], "--will-qos")){ if(i==argc-1){ fprintf(stderr, "Error: --will-qos argument given but no will QoS specified.\n\n"); mqtt_print_usage(); return 1; }else{ will_qos = atoi(argv[i+1]); if(will_qos < 0 || will_qos > 2){ fprintf(stderr, "Error: Invalid will QoS %d.\n\n", will_qos); return 1; } } i++; }else if(!strcmp(argv[i], "--will-retain")){ will_retain = true; }else if(!strcmp(argv[i], "--will-topic")){ if(i==argc-1){ fprintf(stderr, "Error: --will-topic argument given but no will topic specified.\n\n"); mqtt_print_usage(); return 1; }else{ will_topic = argv[i+1]; } i++; }else{ fprintf(stderr, "Error: Unknown option '%s'.\n",argv[i]); mqtt_print_usage(); return 1; } } /* verify necessary variable */ if(!ud->topic || ud->mode == MQTT_MSGMODE_NONE){ fprintf(stderr, "Error: Both topic and message must be supplied.\n"); mqtt_print_usage(); return 1; } if(will_payload && !will_topic){ fprintf(stderr, "Error: Will payload given, but no will topic given.\n"); mqtt_print_usage(); return 1; } if(will_retain && !will_topic){ fprintf(stderr, "Error: Will retain given, but no will topic given.\n"); mqtt_print_usage(); return 1; } if(ud->password && !ud->username){ if(!ud->quiet) fprintf(stderr, "Warning: Not using password since username not set.\n"); } /* init mosquitto library */ mosquitto_lib_init(); /* setup client id */ if(strlen(id_prefix) != 0){ snprintf(id, sizeof(id), "%s%d", id_prefix, getpid()); }else if(strlen(id) == 0){ memset(hostname, '\0', sizeof(hostname)); gethostname(hostname, sizeof(hostname)); snprintf(id, sizeof(id), "mosqub/%d-%s", getpid(), hostname); } if(strlen(id) > MOSQ_MQTT_ID_MAX_LENGTH){ /* Enforce maximum client id length of 23 characters */ id[MOSQ_MQTT_ID_MAX_LENGTH] = '\0'; } /* start mosquitto */ mosq = mosquitto_new(id, true, ud); if(!mosq){ if(!ud->quiet) fprintf(stderr, "Error: %s\n", strerror(errno)); mosquitto_lib_cleanup(); return 1; } /* setup mosquitto */ if(debug){ mosquitto_log_callback_set(mosq, mqtt_log_callback); } if(will_topic && mosquitto_will_set(mosq, will_topic, will_payloadlen, will_payload, will_qos, will_retain)){ if(!ud->quiet) fprintf(stderr, "Error: Problem setting will.\n"); mosquitto_lib_cleanup(); return 1; } if(ud->username && mosquitto_username_pw_set(mosq, ud->username, ud->password)){ if(!ud->quiet) fprintf(stderr, "Error: Problem setting username and password.\n"); mosquitto_lib_cleanup(); return 1; } mosquitto_max_inflight_messages_set(mosq, max_inflight); mosquitto_connect_callback_set(mosq, mqtt_connect_callback); mosquitto_disconnect_callback_set(mosq, mqtt_disconnect_callback); mosquitto_publish_callback_set(mosq, mqtt_publish_callback); /* connect mosquitto */ rc = mosquitto_connect(mosq, host, port, keepalive); if(rc){ if(!ud->quiet){ if(rc == MOSQ_ERR_ERRNO){ #ifndef WIN32 strerror_r(errno, err, sizeof(err)); #else FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, errno, 0, (LPTSTR)&err, sizeof(err), NULL); #endif fprintf(stderr, "Error: %s\n", err); }else{ fprintf(stderr, "Unable to connect (%d: %s).\n", rc, mosquitto_strerror(rc)); } } mosquitto_lib_cleanup(); return rc; } /* publish mosquitto mqtt message BASED ON DIFFERENT message mode */ if(ud->mode == MQTT_MSGMODE_STDIN_LINE){ mosquitto_loop_start(mosq); } do{ if(ud->mode == MQTT_MSGMODE_STDIN_LINE){ if(ud->status == MQTT_STATUS_CONNACK_RECVD){ if(fgets(buf, sizeof(buf), stdin)){ buf[strlen(buf)-1] = '\0'; rc2 = mosquitto_publish(mosq, &ud->mid_sent, ud->topic, strlen(buf), buf, ud->qos, ud->retain); if(rc2){ if(!ud->quiet) fprintf(stderr, "Error: Publish returned %d, disconnecting.\n", rc2); mosquitto_disconnect(mosq); } }else if(feof(stdin)){ ud->last_mid = ud->mid_sent; ud->status = MQTT_STATUS_WAITING; } }else if(ud->status == MQTT_STATUS_WAITING){ #ifdef WIN32 Sleep(1000); #else usleep(1000000); #endif } rc = MOSQ_ERR_SUCCESS; }else{ rc = mosquitto_loop(mosq, -1, 1); } }while(rc == MOSQ_ERR_SUCCESS && ud->connected); if(ud->mode == MQTT_MSGMODE_STDIN_LINE){ mosquitto_loop_stop(mosq, false); } /* free mosquitto */ mosquitto_destroy(mosq); mosquitto_lib_cleanup(); mqtt_userdata_free(ud); return rc; }
int main(int argc, char *argv[]) { char *id = NULL; char *id_prefix = NULL; int i; char *host = "localhost"; int port = 1883; int keepalive = 60; bool clean_session = true; bool debug = false; struct mosquitto *mosq = NULL; int rc; char hostname[256]; char err[1024]; struct userdata ud; int len; char *will_payload = NULL; long will_payloadlen = 0; int will_qos = 0; bool will_retain = false; char *will_topic = NULL; char *cafile = NULL; char *capath = NULL; char *certfile = NULL; char *keyfile = NULL; char *psk = NULL; char *psk_identity = NULL; memset(&ud, 0, sizeof(struct userdata)); for(i=1; i<argc; i++){ if(!strcmp(argv[i], "-p") || !strcmp(argv[i], "--port")){ if(i==argc-1){ fprintf(stderr, "Error: -p argument given but no port specified.\n\n"); print_usage(); return 1; }else{ port = atoi(argv[i+1]); if(port<1 || port>65535){ fprintf(stderr, "Error: Invalid port given: %d\n", port); print_usage(); return 1; } } i++; }else if(!strcmp(argv[i], "-c") || !strcmp(argv[i], "--disable-clean-session")){ clean_session = false; }else if(!strcmp(argv[i], "--cafile")){ if(i==argc-1){ fprintf(stderr, "Error: --cafile argument given but no file specified.\n\n"); print_usage(); return 1; }else{ cafile = argv[i+1]; } i++; }else if(!strcmp(argv[i], "--capath")){ if(i==argc-1){ fprintf(stderr, "Error: --capath argument given but no directory specified.\n\n"); print_usage(); return 1; }else{ capath = argv[i+1]; } i++; }else if(!strcmp(argv[i], "--cert")){ if(i==argc-1){ fprintf(stderr, "Error: --cert argument given but no file specified.\n\n"); print_usage(); return 1; }else{ certfile = argv[i+1]; } i++; }else if(!strcmp(argv[i], "-d") || !strcmp(argv[i], "--debug")){ debug = true; }else if(!strcmp(argv[i], "--help")){ print_usage(); return 0; }else if(!strcmp(argv[i], "-h") || !strcmp(argv[i], "--host")){ if(i==argc-1){ fprintf(stderr, "Error: -h argument given but no host specified.\n\n"); print_usage(); return 1; }else{ host = argv[i+1]; } i++; }else if(!strcmp(argv[i], "-i") || !strcmp(argv[i], "--id")){ if(id_prefix){ fprintf(stderr, "Error: -i and -I argument cannot be used together.\n\n"); print_usage(); return 1; } if(i==argc-1){ fprintf(stderr, "Error: -i argument given but no id specified.\n\n"); print_usage(); return 1; }else{ id = argv[i+1]; } i++; }else if(!strcmp(argv[i], "-I") || !strcmp(argv[i], "--id-prefix")){ if(id){ fprintf(stderr, "Error: -i and -I argument cannot be used together.\n\n"); print_usage(); return 1; } if(i==argc-1){ fprintf(stderr, "Error: -I argument given but no id prefix specified.\n\n"); print_usage(); return 1; }else{ id_prefix = argv[i+1]; } i++; }else if(!strcmp(argv[i], "-k") || !strcmp(argv[i], "--keepalive")){ if(i==argc-1){ fprintf(stderr, "Error: -k argument given but no keepalive specified.\n\n"); print_usage(); return 1; }else{ keepalive = atoi(argv[i+1]); if(keepalive>65535){ fprintf(stderr, "Error: Invalid keepalive given: %d\n", keepalive); print_usage(); return 1; } } i++; }else if(!strcmp(argv[i], "--key")){ if(i==argc-1){ fprintf(stderr, "Error: --key argument given but no file specified.\n\n"); print_usage(); return 1; }else{ keyfile = argv[i+1]; } i++; }else if(!strcmp(argv[i], "--psk")){ if(i==argc-1){ fprintf(stderr, "Error: --psk argument given but no key specified.\n\n"); print_usage(); return 1; }else{ psk = argv[i+1]; } i++; }else if(!strcmp(argv[i], "--psk-identity")){ if(i==argc-1){ fprintf(stderr, "Error: --psk-identity argument given but no identity specified.\n\n"); print_usage(); return 1; }else{ psk_identity = argv[i+1]; } i++; }else if(!strcmp(argv[i], "-q") || !strcmp(argv[i], "--qos")){ if(i==argc-1){ fprintf(stderr, "Error: -q argument given but no QoS specified.\n\n"); print_usage(); return 1; }else{ ud.topic_qos = atoi(argv[i+1]); if(ud.topic_qos<0 || ud.topic_qos>2){ fprintf(stderr, "Error: Invalid QoS given: %d\n", ud.topic_qos); print_usage(); return 1; } } i++; }else if(!strcmp(argv[i], "--quiet")){ ud.quiet = true; }else if(!strcmp(argv[i], "-t") || !strcmp(argv[i], "--topic")){ if(i==argc-1){ fprintf(stderr, "Error: -t argument given but no topic specified.\n\n"); print_usage(); return 1; }else{ ud.topic_count++; ud.topics = realloc(ud.topics, ud.topic_count*sizeof(char *)); ud.topics[ud.topic_count-1] = argv[i+1]; } i++; }else if(!strcmp(argv[i], "-u") || !strcmp(argv[i], "--username")){ if(i==argc-1){ fprintf(stderr, "Error: -u argument given but no username specified.\n\n"); print_usage(); return 1; }else{ ud.username = argv[i+1]; } i++; }else if(!strcmp(argv[i], "-v") || !strcmp(argv[i], "--verbose")){ ud.verbose = 1; }else if(!strcmp(argv[i], "-P") || !strcmp(argv[i], "--pw")){ if(i==argc-1){ fprintf(stderr, "Error: -P argument given but no password specified.\n\n"); print_usage(); return 1; }else{ ud.password = argv[i+1]; } i++; }else if(!strcmp(argv[i], "--will-payload")){ if(i==argc-1){ fprintf(stderr, "Error: --will-payload argument given but no will payload specified.\n\n"); print_usage(); return 1; }else{ will_payload = argv[i+1]; will_payloadlen = strlen(will_payload); } i++; }else if(!strcmp(argv[i], "--will-qos")){ if(i==argc-1){ fprintf(stderr, "Error: --will-qos argument given but no will QoS specified.\n\n"); print_usage(); return 1; }else{ will_qos = atoi(argv[i+1]); if(will_qos < 0 || will_qos > 2){ fprintf(stderr, "Error: Invalid will QoS %d.\n\n", will_qos); return 1; } } i++; }else if(!strcmp(argv[i], "--will-retain")){ will_retain = true; }else if(!strcmp(argv[i], "--will-topic")){ if(i==argc-1){ fprintf(stderr, "Error: --will-topic argument given but no will topic specified.\n\n"); print_usage(); return 1; }else{ will_topic = argv[i+1]; } i++; }else{ fprintf(stderr, "Error: Unknown option '%s'.\n",argv[i]); print_usage(); return 1; } } if(clean_session == false && (id_prefix || !id)){ if(!ud.quiet) fprintf(stderr, "Error: You must provide a client id if you are using the -c option.\n"); return 1; } if(ud.topic_count == 0){ fprintf(stderr, "Error: You must specify a topic to subscribe to.\n"); print_usage(); return 1; } if(will_payload && !will_topic){ fprintf(stderr, "Error: Will payload given, but no will topic given.\n"); print_usage(); return 1; } if(will_retain && !will_topic){ fprintf(stderr, "Error: Will retain given, but no will topic given.\n"); print_usage(); return 1; } if(ud.password && !ud.username){ if(!ud.quiet) fprintf(stderr, "Warning: Not using password since username not set.\n"); } if((certfile && !keyfile) || (keyfile && !certfile)){ fprintf(stderr, "Error: Both certfile and keyfile must be provided if one of them is.\n"); print_usage(); return 1; } if((cafile || capath) && psk){ if(!ud.quiet) fprintf(stderr, "Error: Only one of --psk or --cafile/--capath may be used at once.\n"); return 1; } if(psk && !psk_identity){ if(!ud.quiet) fprintf(stderr, "Error: --psk-identity required if --psk used.\n"); return 1; } mosquitto_lib_init(); if(id_prefix){ id = malloc(strlen(id_prefix)+10); if(!id){ if(!ud.quiet) fprintf(stderr, "Error: Out of memory.\n"); mosquitto_lib_cleanup(); return 1; } snprintf(id, strlen(id_prefix)+10, "%s%d", id_prefix, getpid()); }else if(!id){ hostname[0] = '\0'; gethostname(hostname, 256); hostname[255] = '\0'; len = strlen("mosqsub/-") + 6 + strlen(hostname); id = malloc(len); if(!id){ if(!ud.quiet) fprintf(stderr, "Error: Out of memory.\n"); mosquitto_lib_cleanup(); return 1; } snprintf(id, len, "mosqsub/%d-%s", getpid(), hostname); if(strlen(id) > MOSQ_MQTT_ID_MAX_LENGTH){ /* Enforce maximum client id length of 23 characters */ id[MOSQ_MQTT_ID_MAX_LENGTH] = '\0'; } } mosq = mosquitto_new(id, clean_session, &ud); if(!mosq){ switch(errno){ case ENOMEM: if(!ud.quiet) fprintf(stderr, "Error: Out of memory.\n"); break; case EINVAL: if(!ud.quiet) fprintf(stderr, "Error: Invalid id and/or clean_session.\n"); break; } mosquitto_lib_cleanup(); return 1; } if(debug){ mosquitto_log_callback_set(mosq, my_log_callback); } if(will_topic && mosquitto_will_set(mosq, will_topic, will_payloadlen, will_payload, will_qos, will_retain)){ if(!ud.quiet) fprintf(stderr, "Error: Problem setting will.\n"); mosquitto_lib_cleanup(); return 1; } if(ud.username && mosquitto_username_pw_set(mosq, ud.username, ud.password)){ if(!ud.quiet) fprintf(stderr, "Error: Problem setting username and password.\n"); mosquitto_lib_cleanup(); return 1; } if((cafile || capath) && mosquitto_tls_set(mosq, cafile, capath, certfile, keyfile, NULL)){ if(!ud.quiet) fprintf(stderr, "Error: Problem setting TLS options.\n"); mosquitto_lib_cleanup(); return 1; } if(psk && mosquitto_tls_psk_set(mosq, psk, psk_identity, NULL)){ if(!ud.quiet) fprintf(stderr, "Error: Problem setting TLS-PSK options.\n"); mosquitto_lib_cleanup(); return 1; } mosquitto_connect_callback_set(mosq, my_connect_callback); mosquitto_message_callback_set(mosq, my_message_callback); if(debug){ mosquitto_subscribe_callback_set(mosq, my_subscribe_callback); } rc = mosquitto_connect(mosq, host, port, keepalive); if(rc){ if(!ud.quiet){ if(rc == MOSQ_ERR_ERRNO){ #ifndef WIN32 strerror_r(errno, err, 1024); #else FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, errno, 0, (LPTSTR)&err, 1024, NULL); #endif fprintf(stderr, "Error: %s\n", err); }else{ fprintf(stderr, "Unable to connect (%d).\n", rc); } } return rc; mosquitto_lib_cleanup(); } rc = mosquitto_loop_forever(mosq, -1, 1); mosquitto_destroy(mosq); mosquitto_lib_cleanup(); if(rc){ if(rc == MOSQ_ERR_ERRNO){ fprintf(stderr, "Error: %s\n", strerror(errno)); }else{ fprintf(stderr, "Error: %s\n", mosquitto_strerror(rc)); } } return rc; }
int main(int argc, char *argv[]) { // initialize the system logging openlog("ampel", LOG_CONS | LOG_PID, LOG_USER); syslog(LOG_INFO, "Starting Ampel controller."); // initialize I2C I2C_init(); // initialize MQTT mosquitto_lib_init(); void *mqtt_obj; struct mosquitto *mosq; mosq = mosquitto_new("ampel", true, mqtt_obj); if (((int)mosq == ENOMEM) || ((int)mosq == EINVAL)) { syslog(LOG_ERR, "MQTT error %d (%s)!", (int)mosq, mosquitto_strerror((int)mosq)); mosq = NULL; } if (mosq) { int ret; ret = mosquitto_connect(mosq, MQTT_HOST, MQTT_PORT, 30); if (ret == MOSQ_ERR_SUCCESS) syslog(LOG_INFO, "MQTT connection to %s established.", MQTT_HOST); else { syslog(LOG_ERR, "MQTT error %d (%s)!", ret, mosquitto_strerror(ret)); //TODO cleanup return -1; } } // subscribe to door topic if (mosq) { mosquitto_message_callback_set(mosq, mqtt_message_callback); mosquitto_subscribe(mosq, NULL, MQTT_DOOR_TOPIC, 0); } struct ampel_state_t before = { .red = false, .green = false, .blink = false }; int countdown; char mqtt_payload[MQTT_MSG_MAXLEN]; char run=1; int i=0; while(run) { struct ampel_state_t color = before; // check space status bool is_open = get_space_status(SPACEAPI_PATH); // manage the countdown if (!is_open && door_is_locked) { if (countdown) --countdown; } else { countdown = 30; } // set ampel according to space status color.red = !is_open && countdown; color.green = is_open; color.blink = door_is_locked; printf("****** %u\n", i++); printf("Ampel State:\n"); char* on = color.blink ? "Blink" : "On"; printf("Red:\t\t%s\n", color.red ? on : "Off"); printf("Green:\t\t%s\n", color.green ? on : "Off"); printf("Door:\t\t%s\n", door_is_closed ? (door_is_locked ? "Locked" : "Closed") : "Open"); printf("Countdown:\t%d s\n", countdown); printf("\n"); // set the LEDs ampel_set_color(color); // emit MQTT messages mqtt_payload[0] = 0; // render MQTT-message based on ampel state if ((before.red != color.red) || (before.green != color.green) || (before.blink != color.blink)) { strcpy(mqtt_payload, MQTT_MSG_AMPEL); char b = color.blink ? 'b' : '1'; mqtt_payload[13] = color.red ? b : '0'; mqtt_payload[14] = color.green ? b : '0'; } before = color; // send MQTT message if there is payload if (mqtt_payload[0] && mosq) { int ret; int mid; ret = mosquitto_publish( mosq, &mid, MQTT_AMPEL_TOPIC, strlen(mqtt_payload), mqtt_payload, 2, /* qos */ true /* retain */ ); if (ret != MOSQ_ERR_SUCCESS) syslog(LOG_ERR, "MQTT error on message \"%s\": %d (%s)", mqtt_payload, ret, mosquitto_strerror(ret)); else syslog(LOG_INFO, "MQTT message \"%s\" sent with id %d.", mqtt_payload, mid); } // call the mosquitto loop to process messages if (mosq) { int ret; ret = mosquitto_loop(mosq, 100, 1); // if failed, try to reconnect if (ret) { syslog(LOG_ERR, "MQTT reconnect."); mosquitto_reconnect(mosq); } } if (sleep(1)) break; } // clean-up MQTT if (mosq) { mosquitto_disconnect(mosq); mosquitto_destroy(mosq); } mosquitto_lib_cleanup(); syslog(LOG_INFO, "Doorstate observer finished."); closelog(); return 0; }
int main(int argc, char **argv) { struct tm gmt_init, local_init; char ch, *progname = *argv, *nodename, *topic, *prefix = DEFAULT_PREFIX;; int usage = 0, interval = 10, rc; struct utsname uts; char clientid[30]; char *host = "localhost", *ca_file; int port = 1883, keepalive = 60; int do_tls = FALSE, tls_insecure = FALSE; int do_psk = FALSE; char *psk_key = NULL, *psk_identity = NULL; struct udata udata; udata.mid = 17; while ((ch = getopt(argc, argv, "i:t:h:p:C:LUK:I:")) != EOF) { switch (ch) { case 'C': ca_file = optarg; do_tls = TRUE; break; case 'h': host = optarg; break; case 'i': interval = atoi(optarg); interval = (interval < 1) ? 1 : interval; break; case 's': tls_insecure = TRUE; break; case 'p': port = atoi(optarg); break; case 't': prefix = optarg; break; case 'L': do_local = !do_local; break; case 'U': do_utc = !do_utc; break; case 'I': psk_identity = optarg; do_psk = TRUE; break; case 'K': psk_key = optarg; do_psk = TRUE; break; default: usage = 1; break; } } if (do_tls && do_psk) usage = 1; if (do_psk && (psk_key == NULL || psk_identity == NULL)) usage = 1; if (usage) { fprintf(stderr, "Usage: %s [-h host] [-i interval] [-p port] [-t prefix] [-C CA-cert] [-L] [-U] [-K psk-key] [-I psk-identity] [-s]\n", progname); exit(1); } /* Find nodename; chop at first '.' */ if (uname(&uts) == 0) { char *p; nodename = strdup(uts.nodename); if ((p = strchr(nodename, '.')) != NULL) *p = 0; } else { nodename = strdup("unknown"); } mosquitto_lib_init(); sprintf(clientid, "mqtt-tics-%d", getpid()); m = mosquitto_new(clientid, TRUE, (void *)&udata); if (!m) { fprintf(stderr, "Out of memory.\n"); exit(1); } if (do_psk) { rc = mosquitto_tls_psk_set(m, psk_key, psk_identity,NULL); if (rc != MOSQ_ERR_SUCCESS) { fprintf(stderr, "Cannot set TLS PSK: %s\n", mosquitto_strerror(rc)); exit(3); } } else if (do_tls) { rc = mosquitto_tls_set(m, ca_file, NULL, NULL, NULL, NULL); if (rc != MOSQ_ERR_SUCCESS) { fprintf(stderr, "Cannot set TLS PSK: %s\n", mosquitto_strerror(rc)); exit(3); } /* FIXME */ // mosquitto_tls_opts_set(m, SSL_VERIFY_PEER, "tlsv1", NULL); if (tls_insecure) { #if LIBMOSQUITTO_VERSION_NUMBER >= 1002000 /* mosquitto_tls_insecure_set() requires libmosquitto 1.2. */ mosquitto_tls_insecure_set(m, TRUE); #endif } } mosquitto_publish_callback_set(m, cb_pub); mosquitto_disconnect_callback_set(m, cb_disconnect); if ((rc = mosquitto_connect(m, host, port, keepalive)) != MOSQ_ERR_SUCCESS) { fprintf(stderr, "Unable to connect to %s:%d: %s\n", host, port, mosquitto_strerror(rc)); perror(""); exit(2); } signal(SIGINT, catcher); mosquitto_loop_start(m); if ((topic = malloc(strlen(prefix) + (3 * strlen(nodename)) + 12)) == NULL) { fprintf(stderr, "ENOMEM\n"); goto abort; } sprintf(topic, prefix, nodename, nodename, nodename); memset(&gmt_init, 0, sizeof(struct tm)); memset(&local_init, 0, sizeof(struct tm)); time(&start_tics); while (1) { pubtime(topic, &gmt_init, &local_init); sleep(interval); } free(topic); abort: free(nodename); mosquitto_disconnect(m); mosquitto_loop_stop(m, false); mosquitto_lib_cleanup(); return 0; }