Commits

Roger Light committed 42e4395

Rename all pachube->cosm.

  • Participants
  • Parent commits 4dcf24a

Comments (0)

Files changed (10)

File CMakeLists.txt

 set(CMAKE_LEGACY_CYGWIN_WIN32 0)
 
-project(mqtt2pachube)
+project(mqtt2cosm)
 
 cmake_minimum_required(VERSION 2.6)
 
 	set (INCLUDEDIR include)
 	set (DATAROOTDIR share)
 	set (MANDIR ${DATAROOTDIR}/man)
-	set (SHAREDIR ${DATAROOTDIR}/mqtt2pachube)
+	set (SHAREDIR ${DATAROOTDIR}/mqtt2cosm)
 endif (WIN32)
 
 # ========================================

File mqtt2cosm.conf

+# Config file for mqtt2pachube
+# Send data from mqtt subscriptions to pachube.com feeds
+#
+# Lines with a # as the very first character are comments.
+
+# =================================================================
+# Pachube options
+# =================================================================
+
+# You must define your Pachube API key here to have permission to update feeds.
+#pachube_apikey
+
+# The Pachube MQTT server host and port.
+#pachube_host api.pachube.com
+#pachube_port 1883
+
+# =================================================================
+# MQTT Broker options
+# =================================================================
+
+# The host that the MQTT broker is running on. Defaults to localhost.
+#mqtt_host localhost
+
+# The port to connect to the broker on. Defaults to 1883.
+#mqtt_port 1883
+
+# The client id to connect to the broker with. If not given, a random ID will
+# be used.
+#mqtt_id
+
+# =================================================================
+# MQTT Subscriptions
+# =================================================================
+
+# An unlimited number of MQTT subscriptions can be defined here. This is where
+# you choose what data comes from MQTT to mqtt2pachube.
+
+# The subscription option has the format:
+#subscription <topic>
+#
+# Examples:
+#
+# subscription energy/#
+# subscription twitter/+/status
+# subscription foo/bar
+# subscription pachube/#
+#
+# By default the subscription is made using Quality of Service 0. To change
+# this, use the qos keyword immediately after defining the subscription.
+#
+#qos <qos value, 0-2>
+
+# =================================================================
+# Topic/Feed Maps
+# =================================================================
+
+# This section allows you to create mappings from the incoming MQTT topics to
+# Pachube feeds and IDs.
+#
+# A complete map consists of the keywords topic, feed and datastream. The topic
+# keyword corresponds to the incoming MQTT topic and must match exactly. It
+# must be the first keyword in a map configuration. The feed keyword is a
+# Pachube feed number and must already exist. The datastream keyword
+# corresponds to the datastream number within the given feed.  Datastream is an
+# optional keyword and will be treated as 0 if not provided.
+#
+# Maps with identical topics feeding different feed/datastreams are valid.
+#
+# Fictional example that matches a real Pachube feed:
+#
+# # Pachube Office environment
+# topic pachube/office/humidity
+# feed 504
+# datastream 0
+
+# topic pachube/office/light_level
+# feed 504
+# datastream 1
+
+# topic pachube/office/temperature
+# feed 504
+# datastream 2
+

File mqtt2pachube.conf

-# Config file for mqtt2pachube
-# Send data from mqtt subscriptions to pachube.com feeds
-#
-# Lines with a # as the very first character are comments.
-
-# =================================================================
-# Pachube options
-# =================================================================
-
-# You must define your Pachube API key here to have permission to update feeds.
-#pachube_apikey
-
-# The Pachube MQTT server host and port.
-#pachube_host api.pachube.com
-#pachube_port 1883
-
-# =================================================================
-# MQTT Broker options
-# =================================================================
-
-# The host that the MQTT broker is running on. Defaults to localhost.
-#mqtt_host localhost
-
-# The port to connect to the broker on. Defaults to 1883.
-#mqtt_port 1883
-
-# The client id to connect to the broker with. If not given, a random ID will
-# be used.
-#mqtt_id
-
-# =================================================================
-# MQTT Subscriptions
-# =================================================================
-
-# An unlimited number of MQTT subscriptions can be defined here. This is where
-# you choose what data comes from MQTT to mqtt2pachube.
-
-# The subscription option has the format:
-#subscription <topic>
-#
-# Examples:
-#
-# subscription energy/#
-# subscription twitter/+/status
-# subscription foo/bar
-# subscription pachube/#
-#
-# By default the subscription is made using Quality of Service 0. To change
-# this, use the qos keyword immediately after defining the subscription.
-#
-#qos <qos value, 0-2>
-
-# =================================================================
-# Topic/Feed Maps
-# =================================================================
-
-# This section allows you to create mappings from the incoming MQTT topics to
-# Pachube feeds and IDs.
-#
-# A complete map consists of the keywords topic, feed and datastream. The topic
-# keyword corresponds to the incoming MQTT topic and must match exactly. It
-# must be the first keyword in a map configuration. The feed keyword is a
-# Pachube feed number and must already exist. The datastream keyword
-# corresponds to the datastream number within the given feed.  Datastream is an
-# optional keyword and will be treated as 0 if not provided.
-#
-# Maps with identical topics feeding different feed/datastreams are valid.
-#
-# Fictional example that matches a real Pachube feed:
-#
-# # Pachube Office environment
-# topic pachube/office/humidity
-# feed 504
-# datastream 0
-
-# topic pachube/office/light_level
-# feed 504
-# datastream 1
-
-# topic pachube/office/temperature
-# feed 504
-# datastream 2
-
-mqtt2pachube
+mqtt2cosm
 ============
 
-This is mqtt2pachube, a tool to provide a gateway between an MQTT broker and
-pachube.com. It is currently experimental, but seems to work. It isn't
+This is mqtt2cosm, a tool to provide a gateway between an MQTT broker and
+cosm.com. It is currently experimental, but seems to work. It isn't
 supported on Windows.
 
 Using this tool, it is possible to subscribe to topics on an MQTT broker and
-map them to pachube feeds and datastreams.
+map them to cosm feeds and datastreams.
 
 Example
 =======
 particular sensor such as "office" or "garage" and <measurement> is the type of
 measurement such as "temperature" or "humidity".
 
-With mqtt2pachube you could subscribe to sensors/+/+ to get data from all
-sensors. You can then create topic mappings to pachube feeds such as below:
+With mqtt2cosm you could subscribe to sensors/+/+ to get data from all
+sensors. You can then create topic mappings to cosm feeds such as below:
 
 sensors/office/temperature -> feed 47080 datastream 0
 sensors/garage/temperature -> feed 47080 datastream 1
 sensors/office/humidity -> feed 47081 datastream 0
 sensors/garage/humidity -> feed 47081 datastream 1
 
-Each time a message appears on one of those topics, it will be published to pachube.
+Each time a message appears on one of those topics, it will be published to cosm.

File src/CMakeLists.txt

-add_executable(mqtt2pachube
-	mqtt2pachube.c mqtt2pachube.h
+add_executable(mqtt2cosm
+	mqtt2cosm.c mqtt2cosm.h
 	conf.c
 	)
 
-target_link_libraries(mqtt2pachube mosquitto)
+target_link_libraries(mqtt2cosm mosquitto)
 
-install(TARGETS mqtt2pachube RUNTIME DESTINATION ${BINDIR} LIBRARY DESTINATION ${LIBDIR})
+install(TARGETS mqtt2cosm RUNTIME DESTINATION ${BINDIR} LIBRARY DESTINATION ${LIBDIR})
 #include <stdlib.h>
 #include <string.h>
 
-#include "mqtt2pachube.h"
+#include "mqtt2cosm.h"
 
 static int _conf_parse_int(char *token, const char *name, int *value);
 static int _conf_parse_string(char *token, const char *name, char **value);
 
-int config_parse(const char *config_file, struct mqtt2pachube_config *config)
+int config_parse(const char *config_file, struct mqtt2cosm_config *config)
 {
 	FILE *fptr;
 	char buf[1024];
-	struct mqtt2pachube_subscription *current_sub = NULL;
-	struct mqtt2pachube_map *current_map = NULL;
+	struct mqtt2cosm_subscription *current_sub = NULL;
+	struct mqtt2cosm_map *current_map = NULL;
 
 	fptr = fopen(config_file, "rt");
 	if(!fptr){
 	}
 
 	config->mqtt_port = 1883;
-	config->pachube_port = 1883;
+	config->cosm_port = 1883;
 
 	while(fgets(buf, 1024, fptr)){
 		if(buf[0] != '#' && buf[0] != 10 && buf[0] != 13){
 					fclose(fptr);
 					return 1;
 				}
-			}else if(!strncmp(buf, "pachube_apikey ", 15)){
-				if(_conf_parse_string(&(buf[15]), "pachube_apikey", &config->pachube_apikey)){
+			}else if(!strncmp(buf, "cosm_apikey ", 15)){
+				if(_conf_parse_string(&(buf[15]), "cosm_apikey", &config->cosm_apikey)){
 					fclose(fptr);
 					return 1;
 				}
-			}else if(!strncmp(buf, "pachube_host ", 13)){
-				if(_conf_parse_string(&(buf[13]), "pachube_host", &config->pachube_host)){
+			}else if(!strncmp(buf, "cosm_host ", 13)){
+				if(_conf_parse_string(&(buf[13]), "cosm_host", &config->cosm_host)){
 					fclose(fptr);
 					return 1;
 				}
-			}else if(!strncmp(buf, "pachube_port ", 13)){
-				if(_conf_parse_int(&(buf[13]), "pachube_port", &config->pachube_port)){
+			}else if(!strncmp(buf, "cosm_port ", 13)){
+				if(_conf_parse_int(&(buf[13]), "cosm_port", &config->cosm_port)){
 					fclose(fptr);
 					return 1;
 				}
 			}else if(!strncmp(buf, "subscription ", 13)){
 				config->sub_count++;
-				config->subs = realloc(config->subs, sizeof(struct mqtt2pachube_subscription)*config->sub_count);
+				config->subs = realloc(config->subs, sizeof(struct mqtt2cosm_subscription)*config->sub_count);
 				if(!config->subs){
 					fprintf(stderr, "Error: Out of memory.\n");
 					fclose(fptr);
 				}
 			}else if(!strncmp(buf, "topic ", 6)){
 				config->map_count++;
-				config->maps = realloc(config->maps, sizeof(struct mqtt2pachube_map)*config->map_count);
+				config->maps = realloc(config->maps, sizeof(struct mqtt2cosm_map)*config->map_count);
 				if(!config->maps){
 					fprintf(stderr, "Error: Out of memory.\n");
 					fclose(fptr);
 	}
 	fclose(fptr);
 
-	if(!config->pachube_apikey){
+	if(!config->cosm_apikey){
 		fprintf(stderr, "Error: You must provide a Pachube API key in the config file.\n");
 		return 1;
 	}
 	if(!config->mqtt_host){
 		config->mqtt_host = strdup("localhost");
 	}
-	if(!config->pachube_host){
-		config->pachube_host = strdup("api.pachube.com");
+	if(!config->cosm_host){
+		config->cosm_host = strdup("api.cosm.com");
 	}
 
 	return 0;
 }
 
 
-void config_cleanup(struct mqtt2pachube_config *config)
+void config_cleanup(struct mqtt2cosm_config *config)
 {
 }
 

File src/mqtt2cosm.c

+/*
+Copyright (c) 2012 Roger Light <roger@atchoo.org>
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice,
+   this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+3. Neither the name of the project nor the names of its
+   contributors may be used to endorse or promote products derived from
+   this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+*/
+#include <stdio.h>
+#include <string.h>
+#include <sys/select.h>
+#include <mosquitto.h>
+
+#include "mqtt2cosm.h"
+
+struct mqtt2cosm_config config;
+
+/* Callback for the non-Pachube end. */
+void on_mqtt_message(struct mosquitto *mosq, void *obj, const struct mosquitto_message *msg)
+{
+	int i;
+	struct mosquitto *mosq_cosm = (struct mosquitto *)obj;
+	char topic[100];
+
+	for(i=0; i<config.map_count; i++){
+		if(!strcmp(msg->topic, config.maps[i].topic)){
+			snprintf(topic, 100, "/v2/feeds/%d/datastreams/%d.csv", config.maps[i].feed, config.maps[i].datastream);
+
+			mosquitto_publish(mosq_cosm, NULL, topic, msg->payloadlen, msg->payload, 0, false);
+		}
+	}
+}
+
+/* Callback for the non-Pachube end. */
+void on_mqtt_connect(struct mosquitto *mosq, void *obj, int rc)
+{
+	int i;
+
+	for(i=0; i<config.sub_count; i++){
+		mosquitto_subscribe(mosq, NULL, config.subs[i].topic, config.subs[i].qos);
+	}
+}
+
+int main(int argc, char *argv[])
+{
+	struct mosquitto *mosq;
+	struct mosquitto *mosq_cosm;
+	int max_socket, mosq_socket, cosm_socket;
+	struct timespec timeout;
+	fd_set readfds, writefds;
+	int fdcount;
+	int rc;
+
+	if(argc != 2){
+		fprintf(stderr, "Usage: mqtt2cosm <config file>\n");
+		return 1;
+	}
+
+	memset(&config, 0, sizeof(struct mqtt2cosm_config));
+	if(config_parse(argv[1], &config)) return 1;
+
+	mosquitto_lib_init();
+
+	/* Init non-Pachube side */
+	mosq = mosquitto_new(config.mqtt_id, true, NULL);
+	if(!mosq){
+		fprintf(stderr, "Error creating mqtt instance.\n");
+		return 1;
+	}
+	
+	mosquitto_connect_callback_set(mosq, on_mqtt_connect);
+	mosquitto_message_callback_set(mosq, on_mqtt_message);
+
+	/* Init Pachube side */
+	mosq_cosm = mosquitto_new(NULL, true, NULL);
+	if(!mosq_cosm){
+		fprintf(stderr, "Error creating cosm instance.\n");
+		return 1;
+	}
+	mosquitto_username_pw_set(mosq_cosm, config.cosm_apikey, NULL);
+
+	/* Set user data */
+	mosquitto_user_data_set(mosq, mosq_cosm);
+	mosquitto_user_data_set(mosq_cosm, mosq);
+
+	/* Connect */
+	mosquitto_connect(mosq, config.mqtt_host, config.mqtt_port, 60);
+	mosq_socket = mosquitto_socket(mosq);
+
+	mosquitto_connect(mosq_cosm, config.cosm_host, config.cosm_port, 60);
+	cosm_socket = mosquitto_socket(mosq_cosm);
+
+	while(1){
+		if(mosq_socket > cosm_socket){
+			max_socket = mosq_socket;
+		}else{
+			max_socket = cosm_socket;
+		}
+		FD_ZERO(&readfds);
+		FD_SET(mosq_socket, &readfds);
+		FD_SET(cosm_socket, &readfds);
+
+		FD_ZERO(&writefds);
+		if(mosquitto_want_write(mosq)){
+			FD_SET(mosq_socket, &writefds);
+		}
+		if(mosquitto_want_write(mosq_cosm)){
+			FD_SET(cosm_socket, &writefds);
+		}
+
+		timeout.tv_sec = 1;
+		timeout.tv_nsec = 0;
+
+		fdcount = pselect(max_socket+1, &readfds, &writefds, NULL, &timeout, NULL);
+		if(fdcount == -1){
+			close(mosq_socket);
+			mosquitto_reconnect(mosq);
+			mosq_socket = mosquitto_socket(mosq);
+
+			close(cosm_socket);
+			mosquitto_reconnect(mosq_cosm);
+			cosm_socket = mosquitto_socket(mosq_cosm);
+		}else{
+			if(FD_ISSET(mosq_socket, &readfds)){
+				if(mosquitto_loop_read(mosq)){
+					close(mosq_socket);
+					mosquitto_reconnect(mosq);
+					mosq_socket = mosquitto_socket(mosq);
+				}
+			}
+			if(FD_ISSET(mosq_socket, &writefds)){
+				if(mosquitto_loop_write(mosq)){
+					close(mosq_socket);
+					mosquitto_reconnect(mosq);
+					mosq_socket = mosquitto_socket(mosq);
+				}
+			}
+
+			if(FD_ISSET(cosm_socket, &readfds)){
+				if(mosquitto_loop_read(mosq_cosm)){
+					close(cosm_socket);
+					mosquitto_reconnect(mosq_cosm);
+					cosm_socket = mosquitto_socket(mosq_cosm);
+				}
+			}
+			if(FD_ISSET(cosm_socket, &writefds)){
+				if(mosquitto_loop_write(mosq_cosm)){
+					close(cosm_socket);
+					mosquitto_reconnect(mosq_cosm);
+					cosm_socket = mosquitto_socket(mosq_cosm);
+				}
+			}
+		}
+		if(mosquitto_loop_misc(mosq)){
+			mosquitto_reconnect(mosq);
+			mosq_socket = mosquitto_socket(mosq);
+		}
+		if(mosquitto_loop_misc(mosq_cosm)){
+			mosquitto_reconnect(mosq_cosm);
+			cosm_socket = mosquitto_socket(mosq_cosm);
+		}
+	}
+
+	mosquitto_lib_cleanup();
+	config_cleanup(&config);
+
+	return 0;
+}
+

File src/mqtt2cosm.h

+/*
+Copyright (c) 2012 Roger Light <roger@atchoo.org>
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice,
+   this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+3. Neither the name of the project nor the names of its
+   contributors may be used to endorse or promote products derived from
+   this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+*/
+#ifndef MQTT2PACHUBE_H
+#define MQTT2PACHUBE_H
+
+struct mqtt2cosm_map{
+	char *topic;
+	int feed;
+	int datastream;
+};
+
+struct mqtt2cosm_subscription{
+	char *topic;
+	int qos;
+};
+
+struct mqtt2cosm_config{
+	char *mqtt_id;
+	char *mqtt_host;
+	int mqtt_port;
+	char *cosm_host;
+	int cosm_port;
+	char *cosm_apikey;
+	struct mqtt2cosm_subscription *subs;
+	int sub_count;
+	struct mqtt2cosm_map *maps;
+	int map_count;
+};
+
+int config_parse(const char *conffile, struct mqtt2cosm_config *config);
+void config_cleanup(struct mqtt2cosm_config *config);
+
+#endif

File src/mqtt2pachube.c

-/*
-Copyright (c) 2012 Roger Light <roger@atchoo.org>
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
-1. Redistributions of source code must retain the above copyright notice,
-   this list of conditions and the following disclaimer.
-2. Redistributions in binary form must reproduce the above copyright
-   notice, this list of conditions and the following disclaimer in the
-   documentation and/or other materials provided with the distribution.
-3. Neither the name of the project nor the names of its
-   contributors may be used to endorse or promote products derived from
-   this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
-LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGE.
-*/
-#include <stdio.h>
-#include <string.h>
-#include <sys/select.h>
-#include <mosquitto.h>
-
-#include "mqtt2pachube.h"
-
-struct mqtt2pachube_config config;
-
-/* Callback for the non-Pachube end. */
-void on_mqtt_message(struct mosquitto *mosq, void *obj, const struct mosquitto_message *msg)
-{
-	int i;
-	struct mosquitto *mosq_pachube = (struct mosquitto *)obj;
-	char topic[100];
-
-	for(i=0; i<config.map_count; i++){
-		if(!strcmp(msg->topic, config.maps[i].topic)){
-			snprintf(topic, 100, "/v2/feeds/%d/datastreams/%d.csv", config.maps[i].feed, config.maps[i].datastream);
-
-			mosquitto_publish(mosq_pachube, NULL, topic, msg->payloadlen, msg->payload, 0, false);
-		}
-	}
-}
-
-/* Callback for the non-Pachube end. */
-void on_mqtt_connect(struct mosquitto *mosq, void *obj, int rc)
-{
-	int i;
-
-	for(i=0; i<config.sub_count; i++){
-		mosquitto_subscribe(mosq, NULL, config.subs[i].topic, config.subs[i].qos);
-	}
-}
-
-int main(int argc, char *argv[])
-{
-	struct mosquitto *mosq;
-	struct mosquitto *mosq_pachube;
-	int max_socket, mosq_socket, pachube_socket;
-	struct timespec timeout;
-	fd_set readfds, writefds;
-	int fdcount;
-	int rc;
-
-	if(argc != 2){
-		fprintf(stderr, "Usage: mqtt2pachube <config file>\n");
-		return 1;
-	}
-
-	memset(&config, 0, sizeof(struct mqtt2pachube_config));
-	if(config_parse(argv[1], &config)) return 1;
-
-	mosquitto_lib_init();
-
-	/* Init non-Pachube side */
-	mosq = mosquitto_new(config.mqtt_id, true, NULL);
-	if(!mosq){
-		fprintf(stderr, "Error creating mqtt instance.\n");
-		return 1;
-	}
-	
-	mosquitto_connect_callback_set(mosq, on_mqtt_connect);
-	mosquitto_message_callback_set(mosq, on_mqtt_message);
-
-	/* Init Pachube side */
-	mosq_pachube = mosquitto_new(NULL, true, NULL);
-	if(!mosq_pachube){
-		fprintf(stderr, "Error creating pachube instance.\n");
-		return 1;
-	}
-	mosquitto_username_pw_set(mosq_pachube, config.pachube_apikey, NULL);
-
-	/* Set user data */
-	mosquitto_user_data_set(mosq, mosq_pachube);
-	mosquitto_user_data_set(mosq_pachube, mosq);
-
-	/* Connect */
-	mosquitto_connect(mosq, config.mqtt_host, config.mqtt_port, 60);
-	mosq_socket = mosquitto_socket(mosq);
-
-	mosquitto_connect(mosq_pachube, config.pachube_host, config.pachube_port, 60);
-	pachube_socket = mosquitto_socket(mosq_pachube);
-
-	while(1){
-		if(mosq_socket > pachube_socket){
-			max_socket = mosq_socket;
-		}else{
-			max_socket = pachube_socket;
-		}
-		FD_ZERO(&readfds);
-		FD_SET(mosq_socket, &readfds);
-		FD_SET(pachube_socket, &readfds);
-
-		FD_ZERO(&writefds);
-		if(mosquitto_want_write(mosq)){
-			FD_SET(mosq_socket, &writefds);
-		}
-		if(mosquitto_want_write(mosq_pachube)){
-			FD_SET(pachube_socket, &writefds);
-		}
-
-		timeout.tv_sec = 1;
-		timeout.tv_nsec = 0;
-
-		fdcount = pselect(max_socket+1, &readfds, &writefds, NULL, &timeout, NULL);
-		if(fdcount == -1){
-			close(mosq_socket);
-			mosquitto_reconnect(mosq);
-			mosq_socket = mosquitto_socket(mosq);
-
-			close(pachube_socket);
-			mosquitto_reconnect(mosq_pachube);
-			pachube_socket = mosquitto_socket(mosq_pachube);
-		}else{
-			if(FD_ISSET(mosq_socket, &readfds)){
-				if(mosquitto_loop_read(mosq)){
-					close(mosq_socket);
-					mosquitto_reconnect(mosq);
-					mosq_socket = mosquitto_socket(mosq);
-				}
-			}
-			if(FD_ISSET(mosq_socket, &writefds)){
-				if(mosquitto_loop_write(mosq)){
-					close(mosq_socket);
-					mosquitto_reconnect(mosq);
-					mosq_socket = mosquitto_socket(mosq);
-				}
-			}
-
-			if(FD_ISSET(pachube_socket, &readfds)){
-				if(mosquitto_loop_read(mosq_pachube)){
-					close(pachube_socket);
-					mosquitto_reconnect(mosq_pachube);
-					pachube_socket = mosquitto_socket(mosq_pachube);
-				}
-			}
-			if(FD_ISSET(pachube_socket, &writefds)){
-				if(mosquitto_loop_write(mosq_pachube)){
-					close(pachube_socket);
-					mosquitto_reconnect(mosq_pachube);
-					pachube_socket = mosquitto_socket(mosq_pachube);
-				}
-			}
-		}
-		if(mosquitto_loop_misc(mosq)){
-			mosquitto_reconnect(mosq);
-			mosq_socket = mosquitto_socket(mosq);
-		}
-		if(mosquitto_loop_misc(mosq_pachube)){
-			mosquitto_reconnect(mosq_pachube);
-			pachube_socket = mosquitto_socket(mosq_pachube);
-		}
-	}
-
-	mosquitto_lib_cleanup();
-	config_cleanup(&config);
-
-	return 0;
-}
-

File src/mqtt2pachube.h

-/*
-Copyright (c) 2012 Roger Light <roger@atchoo.org>
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
-1. Redistributions of source code must retain the above copyright notice,
-   this list of conditions and the following disclaimer.
-2. Redistributions in binary form must reproduce the above copyright
-   notice, this list of conditions and the following disclaimer in the
-   documentation and/or other materials provided with the distribution.
-3. Neither the name of the project nor the names of its
-   contributors may be used to endorse or promote products derived from
-   this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
-LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGE.
-*/
-#ifndef MQTT2PACHUBE_H
-#define MQTT2PACHUBE_H
-
-struct mqtt2pachube_map{
-	char *topic;
-	int feed;
-	int datastream;
-};
-
-struct mqtt2pachube_subscription{
-	char *topic;
-	int qos;
-};
-
-struct mqtt2pachube_config{
-	char *mqtt_id;
-	char *mqtt_host;
-	int mqtt_port;
-	char *pachube_host;
-	int pachube_port;
-	char *pachube_apikey;
-	struct mqtt2pachube_subscription *subs;
-	int sub_count;
-	struct mqtt2pachube_map *maps;
-	int map_count;
-};
-
-int config_parse(const char *conffile, struct mqtt2pachube_config *config);
-void config_cleanup(struct mqtt2pachube_config *config);
-
-#endif