.
675 |
676 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # mqtt2cloud
2 |
3 | MQTT2Cloud is a set of python daemons that will subscribe to an MQTT broker and push values to different providers whenever a message is recevied from certain topics.
4 |
5 | You can read more about this in my post about [Storing and publishing sensor data]( http://tinkerman.eldiariblau.net/storing-and-publishing-sensor-data/ "Storing and publishing sensor data").
6 |
7 | ## Requirements
8 |
9 | * python-yaml
10 | sudo apt-get install python-yaml
11 |
12 | * python-mosquitto
13 | sudo apt-get install python-mosquitto
14 |
15 | * tempodb [if using TempoDB daemon]
16 | pip install tempodb
17 |
18 | * requests [tempodb installs this]
19 | pip install requests
20 |
21 | ## Install
22 |
23 | Just clone or extract the code in some folder. I'm not providing an setup.py file yet.
24 |
25 | ## Configuration
26 |
27 | Rename or copy the config/mqtt2???.yaml.sample files to config/mqtt2???.yaml and edit them. The configuration is pretty straight forward:
28 |
29 | ### daemon
30 |
31 | Just define the log file paths.
32 |
33 | ### mqtt
34 |
35 | These are standard Mosquitto parameters. The status topic is the topic to post messages when the daemon starts or stops.
36 |
37 | ### cosm, xively, sen.se
38 |
39 | The API key and timeout value.
40 |
41 | ### tempodb
42 |
43 | A set of databases, each with its api key and secret.
44 |
45 | ### thethings.io
46 |
47 | A set of things, each with its token.
48 |
49 | ### topics
50 |
51 | For every topic you want to push you have to specify a destination string. This destination string has two parameters, using '/' as separator.
52 | Depending on the cloud service you are using these parameters could be: feed/datastream for xively.com, feed/(empty) for sen.se or database/series from tempo-db.com.
53 | The tempo-db.com 'database' must have been defined in the tempodb/databases section of the configuration.
54 |
55 |
56 | topics:
57 | /raw/sensor/battery: 45243/battery
58 |
59 |
60 | ## Running it
61 |
62 | The utils stay resident as a daemons. You can start them, stop them or restart them (to reload the configuration) by using:
63 |
64 | python mqtt2cosm.py start|stop|restart
65 | python mqtt2tempodb.py start|stop|restart
66 |
67 |
68 |
69 |
--------------------------------------------------------------------------------
/config/mqtt2cosm.yaml.sample:
--------------------------------------------------------------------------------
1 | daemon:
2 | pidfile: /tmp/mqtt2cosm.pid
3 | stderr: /tmp/mqtt2cosm.err
4 | stdout: /tmp/mqtt2cosm.log
5 | debug: True
6 |
7 | mqtt:
8 | client_id: mqtt2cosm
9 | host: localhost
10 | port: 1883
11 | keepalive: 60
12 | clean_session: True
13 | qos: 0
14 | status_topic: /service/mqtt2cosm/status
15 |
16 | cosm:
17 | api_key: AABBCC
18 | timeout: 10
19 |
20 | topics:
21 | /home/general/power: 98259/test
22 |
23 |
--------------------------------------------------------------------------------
/config/mqtt2sense.yaml.sample:
--------------------------------------------------------------------------------
1 | daemon:
2 | pidfile: /tmp/mqtt2sense.pid
3 | stderr: /tmp/mqtt2sense.err
4 | stdout: /tmp/mqtt2sense.log
5 | debug: True
6 |
7 | mqtt:
8 | client_id: mqtt2sense
9 | host: localhost
10 | port: 1883
11 | keepalive: 60
12 | clean_session: True
13 | qos: 0
14 | status_topic: /service/mqtt2sense/status
15 |
16 | sense:
17 | api_key: AABBCC
18 | timeout: 10
19 |
20 | topics:
21 | /home/general/power: 98259/test
22 |
23 |
--------------------------------------------------------------------------------
/config/mqtt2tempodb.yaml.sample:
--------------------------------------------------------------------------------
1 | daemon:
2 | pidfile: /tmp/mqtt2tempodb.pid
3 | stderr: /tmp/mqtt2tempodb.err
4 | stdout: /tmp/mqtt2tempodb.log
5 | debug: True
6 |
7 | mqtt:
8 | client_id: mqtt2tempodb
9 | host: localhost
10 | port: 1883
11 | keepalive: 60
12 | clean_session: True
13 | qos: 0
14 | status_topic: /service/mqtt2tempodb/status
15 |
16 | tempodb:
17 | databases:
18 | home:
19 | api_key: AAA
20 | api_secret: BBB
21 | timeout: 5
22 |
23 | topics:
24 | /home/general/power: home/power
25 |
26 |
--------------------------------------------------------------------------------
/config/mqtt2thethingsio.yaml.sample:
--------------------------------------------------------------------------------
1 | daemon:
2 | pidfile: /tmp/mqtt2thethingsio.pid
3 | stderr: /tmp/mqtt2thethingsio.err
4 | stdout: /tmp/mqtt2thethingsio.log
5 | debug: True
6 |
7 | mqtt:
8 | client_id: mqtt2thethingsio
9 | host: localhost
10 | port: 1883
11 | keepalive: 60
12 | clean_session: True
13 | qos: 0
14 | status_topic: /service/mqtt2thethingsio/status
15 |
16 | thethingsio:
17 | things:
18 | home:
19 | token: AABBCC
20 |
21 | topics:
22 | /home/general/power: home/power
23 |
--------------------------------------------------------------------------------
/config/mqtt2thingspeak.yaml.sample:
--------------------------------------------------------------------------------
1 | daemon:
2 | pidfile: /tmp/mqtt2thingspeak.pid
3 | stderr: /tmp/mqtt2thingspeak.err
4 | stdout: /tmp/mqtt2thingspeak.log
5 | debug: True
6 |
7 | mqtt:
8 | client_id: mqtt2thingspeak
9 | host: localhost
10 | port: 1883
11 | keepalive: 60
12 | clean_session: True
13 | qos: 0
14 | status_topic: /service/mqtt2thingspeak/status
15 |
16 | thingspeak:
17 | channels:
18 | 2323: AAABBBCCC
19 |
20 | topics:
21 | /home/general/power: 2323/energy
22 |
23 |
--------------------------------------------------------------------------------
/config/mqtt2xively.yaml.sample:
--------------------------------------------------------------------------------
1 | daemon:
2 | pidfile: /tmp/mqtt2xively.pid
3 | stderr: /tmp/mqtt2xively.err
4 | stdout: /tmp/mqtt2xively.log
5 | debug: True
6 |
7 | mqtt:
8 | client_id: mqtt2xively
9 | host: localhost
10 | port: 1883
11 | keepalive: 60
12 | clean_session: True
13 | qos: 0
14 | status_topic: /service/mqtt2xively/status
15 |
16 | xively:
17 | api_key: AABBCC
18 | timeout: 10
19 |
20 | topics:
21 | /home/general/power: 98259/test
22 |
23 |
--------------------------------------------------------------------------------
/cosm2csv.py:
--------------------------------------------------------------------------------
1 | #! /usr/bin/python
2 | # -*- coding: utf-8 -*-
3 | # vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4
4 |
5 | # Cosm.com to CSV
6 | # Copyright (C) 2013 by Xose Pérez
7 | #
8 | # This program is free software: you can redistribute it and/or modify
9 | # it under the terms of the GNU General Public License as published by
10 | # the Free Software Foundation, either version 3 of the License, or
11 | # (at your option) any later version.
12 | #
13 | # This program is distributed in the hope that it will be useful,
14 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
15 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 | # GNU General Public License for more details.
17 | #
18 | # You should have received a copy of the GNU General Public License
19 | # along with this program. If not, see .
20 |
21 | __app__ = "Cosm.com to CSV"
22 | __version__ = "0.1"
23 | __author__ = "Xose Pérez"
24 | __contact__ = "xose.perez@gmail.com"
25 | __copyright__ = "Copyright (C) 2013 Xose Pérez"
26 | __license__ = 'GPL v3'
27 |
28 | import re
29 | import datetime
30 |
31 | from libs.services.Cosm import Cosm
32 | import argparse
33 |
34 | if __name__ == "__main__":
35 |
36 | parser = argparse.ArgumentParser(description='Cosm.com to CSV')
37 | parser.add_argument("-k", dest="api_key", help="cosm.com API key", required=True)
38 | parser.add_argument("-f", dest="feed", help="coms.com feed", required=True, type=int)
39 | parser.add_argument("-d", dest="datastream", help="datastream in the feed", required=True)
40 | parser.add_argument("-s", dest="start", help="start datetime (YYYY-MM-DD [HH:MM:SS])", required=True)
41 | parser.add_argument("-e", dest="end", help="end datetime (YYYY-MM-DD [HH:MM:SS])", required=True)
42 | parser.add_argument("--format", dest="format", help="output timestamp format")
43 | options = parser.parse_args()
44 |
45 | cosm = Cosm(options.api_key)
46 |
47 | start = datetime.datetime(*[int(x) for x in re.findall(r'\d+', options.start)])
48 | end = datetime.datetime(*[int(x) for x in re.findall(r'\d+', options.end)])
49 |
50 | print "timestamp,value"
51 | for ts, value in cosm.get(options.feed, options.datastream, start, end):
52 | if options.format:
53 | ts = datetime.datetime(*[int(x) for x in re.findall(r'\d+', ts)])
54 | ts = ts.strftime(options.format)
55 | print "%s,%s" % (ts, value)
56 |
57 |
--------------------------------------------------------------------------------
/do:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | FOLDER=.venv
4 |
5 | if [ $# -eq 0 ]; then
6 | ACTION='activate'
7 | else
8 | ACTION=$1
9 | fi
10 |
11 | case "$ACTION" in
12 |
13 | "activate")
14 | . venv/bin/activate
15 | ;;
16 |
17 | "deactivate")
18 | deactivate
19 | ;;
20 |
21 | "setup")
22 | if [ ! -d $FOLDER ]; then
23 | virtualenv $FOLDER
24 | fi
25 |
26 | deactivate
27 | source $FOLDER/bin/activate
28 |
29 | pip install ConfigParser
30 | pip install pyaml
31 | pip install mosquitto
32 | pip install requests
33 |
34 | wget https://bitbucket.org/oojah/mosquitto/raw/v1.3/lib/python/mosquitto.py
35 | mv mosquitto.py $FOLDER/lib/python2.7/site-packages/
36 |
37 | ;;
38 |
39 | "start" | "stop" | "restart")
40 | source $FOLDER/bin/activate
41 | python mqtt2xively.py $ACTION
42 | #python mqtt2tempodb.py $ACTION
43 | python mqtt2thingspeak.py $ACTION
44 | #python mqtt2sense.py $ACTION
45 | python mqtt2thethingsio.py $ACTION
46 | deactivate
47 | ;;
48 |
49 | *)
50 | echo "Unknown action $ACTION."
51 | ;;
52 | esac
53 |
--------------------------------------------------------------------------------
/libs/Config.py:
--------------------------------------------------------------------------------
1 | #! /usr/bin/python
2 | # -*- coding: utf-8 -*-
3 | # vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4
4 |
5 | # Copyright (C) 2012 by Xose Pérez
6 | #
7 | # This program is free software: you can redistribute it and/or modify
8 | # it under the terms of the GNU General Public License as published by
9 | # the Free Software Foundation, either version 3 of the License, or
10 | # (at your option) any later version.
11 | #
12 | # This program is distributed in the hope that it will be useful,
13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | # GNU General Public License for more details.
16 | #
17 | # You should have received a copy of the GNU General Public License
18 | # along with this program. If not, see .
19 |
20 | __author__ = "Xose Pérez"
21 | __contact__ = "xose.perez@gmail.com"
22 | __copyright__ = "Copyright (C) 2012 Xose Pérez"
23 | __license__ = 'GPL v3'
24 |
25 | import yaml
26 |
27 | class Config(object):
28 | """
29 | Simple YAML configuration parser
30 | """
31 |
32 | config = None
33 |
34 | def __init__(self, filename):
35 | """
36 | Constructor, parses and stores the configuration
37 | """
38 | handler = file(filename, 'r')
39 | self.config = yaml.load(handler)
40 | handler.close()
41 |
42 | def get(self, section, key=None, default=None):
43 | """
44 | Retrieves a given section/key combination,
45 | if not existent it return a default value
46 | """
47 | try:
48 | if key is None:
49 | return self.config[section]
50 | else:
51 | return self.config[section][key]
52 | except:
53 | return default
54 |
55 |
--------------------------------------------------------------------------------
/libs/Daemon.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | # This code was originally poster by Sander Merechal in this post:
4 | # http://www.jejik.com/articles/2007/02/a_simple_unix_linux_daemon_in_python/
5 | # The original license is unknown but the code was released free to use.
6 | # The code here might be slightly different from Sander's original one.
7 |
8 | import sys, os, time, atexit
9 | from signal import SIGTERM
10 |
11 | class Daemon:
12 | """
13 | A generic daemon class.
14 |
15 | Usage: subclass the Daemon class and override the run() method
16 | """
17 | def __init__(self, pidfile, stdin='/dev/null', stdout='/dev/null', stderr='/dev/null'):
18 | self.stdin = stdin
19 | self.stdout = stdout
20 | self.stderr = stderr
21 | self.pidfile = pidfile
22 |
23 | def daemonize(self):
24 | """
25 | do the UNIX double-fork magic, see Stevens' "Advanced
26 | Programming in the UNIX Environment" for details (ISBN 0201563177)
27 | http://www.erlenstar.demon.co.uk/unix/faq_2.html#SEC16
28 | """
29 | try:
30 | pid = os.fork()
31 | if pid > 0:
32 | # exit first parent
33 | sys.exit(0)
34 | except OSError, e:
35 | sys.stderr.write("fork #1 failed: %d (%s)\n" % (e.errno, e.strerror))
36 | sys.exit(1)
37 |
38 | # decouple from parent environment
39 | os.chdir("/")
40 | os.setsid()
41 | os.umask(0)
42 |
43 | # do second fork
44 | try:
45 | pid = os.fork()
46 | if pid > 0:
47 | # exit from second parent
48 | sys.exit(0)
49 | except OSError, e:
50 | sys.stderr.write("fork #2 failed: %d (%s)\n" % (e.errno, e.strerror))
51 | sys.exit(1)
52 |
53 | # redirect standard file descriptors
54 | sys.stdout.flush()
55 | sys.stderr.flush()
56 | si = file(self.stdin, 'r')
57 | so = file(self.stdout, 'a+')
58 | se = file(self.stderr, 'a+', 0)
59 | os.dup2(si.fileno(), sys.stdin.fileno())
60 | os.dup2(so.fileno(), sys.stdout.fileno())
61 | os.dup2(se.fileno(), sys.stderr.fileno())
62 |
63 | # write pidfile
64 | atexit.register(self.cleanup)
65 | pid = str(os.getpid())
66 | file(self.pidfile,'w+').write("%s\n" % pid)
67 |
68 | def cleanup(self):
69 | os.remove(self.pidfile)
70 |
71 | def start(self):
72 | """
73 | Start the daemon
74 | """
75 | # Check for a pidfile to see if the daemon already runs
76 | try:
77 | pf = file(self.pidfile,'r')
78 | pid = int(pf.read().strip())
79 | pf.close()
80 | except IOError:
81 | pid = None
82 |
83 | if pid:
84 | message = "pidfile %s already exist. Daemon already running?\n"
85 | sys.stderr.write(message % self.pidfile)
86 | sys.exit(1)
87 |
88 | # Start the daemon
89 | self.daemonize()
90 | self.run()
91 |
92 | def stop(self):
93 | """
94 | Stop the daemon
95 | """
96 | # Get the pid from the pidfile
97 | try:
98 | pf = file(self.pidfile,'r')
99 | pid = int(pf.read().strip())
100 | pf.close()
101 | except IOError:
102 | pid = None
103 |
104 | if not pid:
105 | message = "pidfile %s does not exist. Daemon not running?\n"
106 | sys.stderr.write(message % self.pidfile)
107 | return # not an error in a restart
108 |
109 | # Try killing the daemon process
110 | try:
111 | while 1:
112 | os.kill(pid, SIGTERM)
113 | time.sleep(0.1)
114 | except OSError, err:
115 | err = str(err)
116 | if err.find("No such process") > 0:
117 | if os.path.exists(self.pidfile):
118 | os.remove(self.pidfile)
119 | else:
120 | print str(err)
121 | sys.exit(1)
122 |
123 | def restart(self):
124 | """
125 | Restart the daemon
126 | """
127 | self.stop()
128 | self.start()
129 |
130 | def run(self):
131 | """
132 | You should override this method when you subclass Daemon. It will be called after the process has been
133 | daemonized by start() or restart().
134 | """
135 |
--------------------------------------------------------------------------------
/libs/Manager.py:
--------------------------------------------------------------------------------
1 | #! /usr/bin/python
2 | # -*- coding: utf-8 -*-
3 | # vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4
4 |
5 | # MQTT to Cloud
6 | # Copyright (C) 2013 by Xose Pérez
7 | #
8 | # This program is free software: you can redistribute it and/or modify
9 | # it under the terms of the GNU General Public License as published by
10 | # the Free Software Foundation, either version 3 of the License, or
11 | # (at your option) any later version.
12 | #
13 | # This program is distributed in the hope that it will be useful,
14 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
15 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 | # GNU General Public License for more details.
17 | #
18 | # You should have received a copy of the GNU General Public License
19 | # along with this program. If not, see .
20 |
21 | __app__ = "MQTT to Cloud"
22 | __version__ = "0.3.1"
23 | __author__ = "Xose Pérez"
24 | __contact__ = "xose.perez@gmail.com"
25 | __copyright__ = "Copyright (C) 2013 Xose Pérez"
26 | __license__ = 'GPL v3'
27 |
28 | import sys
29 | import time
30 | from datetime import datetime
31 | import ctypes
32 |
33 | from Daemon import Daemon
34 |
35 | class Manager(Daemon):
36 | """
37 | MQTT2Cloud manager.
38 | Glues the different components together
39 | """
40 |
41 | debug = True
42 | mqtt = None
43 | service = None
44 |
45 | topics = {}
46 |
47 | def log(self, message):
48 | """
49 | Log method.
50 | TODO: replace with standard python logging facility
51 | """
52 | if self.debug:
53 | timestamp = datetime.now().strftime('%Y-%m-%dT%H:%M:%S.%f')
54 | sys.stdout.write("[%s] %s\n" % (timestamp, message))
55 | sys.stdout.flush()
56 |
57 | def load_topics(self, topics):
58 | """
59 | Loads the mappings from MQTT topics
60 | """
61 | self.topics = {}
62 | for topic, data in topics.iteritems():
63 | feed, stream = data.split('/', 2)
64 | self.topics[topic] = {'feed': feed, 'stream': stream}
65 |
66 | def cleanup(self):
67 | """
68 | Clean up connections and unbind ports
69 | """
70 | self.mqtt.disconnect()
71 | self.log("[INFO] Exiting")
72 | sys.exit()
73 |
74 | def mqtt_connect(self):
75 | """
76 | Initiate connection to MQTT broker and bind callback methods
77 | """
78 | self.mqtt.on_connect = self.mqtt_on_connect
79 | self.mqtt.on_disconnect = self.mqtt_on_disconnect
80 | self.mqtt.on_message = self.mqtt_on_message
81 | self.mqtt.on_subscribe = self.mqtt_on_subscribe
82 | self.mqtt.connect()
83 |
84 | def mqtt_on_connect(self, obj, userdata, result_code):
85 | """
86 | Callback when connection to the MQTT broker has succedeed or failed
87 | """
88 | if result_code == 0:
89 | self.log("[INFO] Connected to MQTT broker")
90 | self.mqtt.send_connected()
91 | for topic, data in self.topics.iteritems():
92 | rc, mid = self.mqtt.subscribe(topic, 0)
93 | self.log("[INFO] Subscription to %s sent with MID %d" % (topic, mid))
94 | else:
95 | self.stop()
96 |
97 | def mqtt_on_disconnect(self, obj, userdata, result_code):
98 | """
99 | Callback when disconnecting from the MQTT broker
100 | """
101 | if result_code != 0:
102 | time.sleep(3)
103 | self.mqtt_connect()
104 |
105 | def mqtt_on_subscribe(self, obj, userdata, mid, qos_list):
106 | """
107 | Callback when succeeded subscription
108 | """
109 | self.log("[INFO] Subscription for MID %s confirmed." % mid)
110 |
111 | def mqtt_on_message(self, obj, userdata, msg):
112 | """
113 | Incoming message, publish to the defined service if there is a mapping match
114 | """
115 | data = self.topics.get(msg.topic, None)
116 | if data:
117 | try:
118 | message = ctypes.string_at(msg.payload, msg.payloadlen)
119 | except:
120 | message = msg.payload
121 | try:
122 | status = 'DEBUG' if self.service.push(data['feed'], data['stream'], message) else 'ERROR'
123 | response = self.service.last_response
124 | except Exception as e:
125 | response = e
126 | status = 'ERROR'
127 | self.log("[%s] Message routed from %s to %s:%s = %s (%s)" % (status, msg.topic, data['feed'], data['stream'], message, response))
128 |
129 | def run(self):
130 | """
131 | Entry point, initiates components and loops forever...
132 | """
133 | self.log("[INFO] Starting " + __app__ + " v" + __version__)
134 | if not self.mqtt:
135 | self.log("[ERROR] MQTT broker not defined")
136 | sys.exit(2)
137 | if not self.service:
138 | self.log("[ERROR] Cloud service not defined")
139 | sys.exit(2)
140 |
141 | self.mqtt_connect()
142 |
143 | while True:
144 | self.mqtt.loop()
145 | self.service.loop()
146 |
--------------------------------------------------------------------------------
/libs/Mosquitto.py:
--------------------------------------------------------------------------------
1 | #! /usr/bin/python
2 | # -*- coding: utf-8 -*-
3 | # vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4
4 |
5 | # Copyright (C) 2012 by Xose Pérez
6 | #
7 | # This program is free software: you can redistribute it and/or modify
8 | # it under the terms of the GNU General Public License as published by
9 | # the Free Software Foundation, either version 3 of the License, or
10 | # (at your option) any later version.
11 | #
12 | # This program is distributed in the hope that it will be useful,
13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | # GNU General Public License for more details.
16 | #
17 | # You should have received a copy of the GNU General Public License
18 | # along with this program. If not, see .
19 |
20 | __author__ = "Xose Pérez"
21 | __contact__ = "xose.perez@gmail.com"
22 | __copyright__ = "Copyright (C) 2012 Xose Pérez"
23 | __license__ = 'GPL v3'
24 |
25 | import sys
26 | from mosquitto import Mosquitto as _Mosquitto
27 |
28 | class Mosquitto(_Mosquitto):
29 | """
30 | Wrapper for the official Mosquitto client that allows injection and easy mocking
31 | """
32 |
33 | client_id = 'xbee2mqtt'
34 | host = 'localhost'
35 | port = 1883
36 | keepalive = 60
37 | clean_session = False
38 | qos = 0
39 | retain = False
40 | status_topic = '/service/xbee2mqtt/status'
41 | set_will = False
42 |
43 | def connect(self):
44 | """
45 | Connects to the Mosquitto broker with the pre-configured parameters
46 | """
47 | if self.set_will:
48 | self.will_set(self.status_topic, "0", self.qos, self.retain)
49 | _Mosquitto.connect(self, self.host, self.port, self.keepalive)
50 |
51 | def publish(self, topic, value):
52 | """
53 | Publishes a value to a given topic, uses pre-loaded values for QoS and retain
54 | """
55 | _Mosquitto.publish(self, topic, str(value), self.qos, self.retain)
56 |
57 | def send_connected(self):
58 | """
59 | Send connection notification
60 | """
61 | self.publish(self.status_topic, "1")
62 |
63 |
64 |
--------------------------------------------------------------------------------
/libs/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xoseperez/mqtt2cloud/ec39e64151c6d221597001bd6cbeb00a8499d496/libs/__init__.py
--------------------------------------------------------------------------------
/libs/services/CloudService.py:
--------------------------------------------------------------------------------
1 | #! /usr/bin/python
2 | # -*- coding: utf-8 -*-
3 | # vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4
4 |
5 | # MQTT to Cloud
6 | # Copyright (C) 2013 by Xose Pérez
7 | #
8 | # This program is free software: you can redistribute it and/or modify
9 | # it under the terms of the GNU General Public License as published by
10 | # the Free Software Foundation, either version 3 of the License, or
11 | # (at your option) any later version.
12 | #
13 | # This program is distributed in the hope that it will be useful,
14 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
15 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 | # GNU General Public License for more details.
17 | #
18 | # You should have received a copy of the GNU General Public License
19 | # along with this program. If not, see .
20 |
21 | __app__ = "MQTT to Cloud"
22 | __author__ = "Xose Pérez"
23 | __contact__ = "xose.perez@gmail.com"
24 | __copyright__ = "Copyright (C) 2013 Xose Pérez"
25 | __license__ = 'GPL v3'
26 |
27 | class CloudService(object):
28 |
29 | last_response = None
30 |
31 | def push(self, feed, stream, value):
32 | pass
33 |
34 | def loop(self):
35 | pass
36 |
--------------------------------------------------------------------------------
/libs/services/Cosm.py:
--------------------------------------------------------------------------------
1 | #! /usr/bin/python
2 | # -*- coding: utf-8 -*-
3 | # vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4
4 |
5 | # Copyright (C) 2013 by Xose Pérez
6 | #
7 | # This program is free software: you can redistribute it and/or modify
8 | # it under the terms of the GNU General Public License as published by
9 | # the Free Software Foundation, either version 3 of the License, or
10 | # (at your option) any later version.
11 | #
12 | # This program is distributed in the hope that it will be useful,
13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | # GNU General Public License for more details.
16 | #
17 | # You should have received a copy of the GNU General Public License
18 | # along with this program. If not, see .
19 |
20 | __author__ = "Xose Pérez"
21 | __contact__ = "xose.perez@gmail.com"
22 | __copyright__ = "Copyright (C) 2013 Xose Pérez"
23 | __license__ = 'GPL v3'
24 |
25 | import requests
26 | import json
27 | import datetime
28 | from CloudService import CloudService
29 |
30 | class Cosm(CloudService):
31 | """
32 | Cosm.com client
33 | """
34 |
35 | api_key = ''
36 | timeout = 5
37 |
38 | datapoints = []
39 | base_url = "http://api.cosm.com/v2/feeds/%s/datastreams/%s"
40 |
41 | def __init__(self, api_key, timeout = None):
42 | """
43 | Constructor, provide API Key
44 | """
45 | self.api_key = api_key
46 | if timeout:
47 | self.timeout = timeout
48 |
49 | def headers(self):
50 | return {'X-ApiKey': self.api_key}
51 |
52 | def clear(self):
53 | """
54 | Reset the stored datapoints
55 | """
56 | self.datapoints = []
57 |
58 | def add(self, at, value):
59 | """
60 | Add a datapoint with a given timestamp and value
61 | """
62 | self.datapoints.append({'at': at, 'value': value})
63 |
64 | def send(self, feed, datastream):
65 | """
66 | Send all stored datapoints.
67 | Usage example:
68 | cosm = Cosm('APIKEY')
69 | cosm.add('2012-12-27T12:00:00+01:00', 190)
70 | cosm.add('2012-12-27T13:00:00+01:00', 150)
71 | cosm.add('2012-12-27T14:00:00+01:00', 270)
72 | cosm.send(94234, 1)
73 | """
74 | try:
75 | url = self.base_url % (feed, datastream) + "/datapoints.json"
76 | data = json.dumps({'datapoints' : self.datapoints})
77 | response = requests.post(url, data=data, headers=self.headers(), timeout=self.timeout)
78 | return response.status_code == 200
79 | except:
80 | return False
81 |
82 | def get(self, feed, datastream, start, end, step=360):
83 | """
84 | Gets all datapoints (interval 0) from a feed between two dates
85 | """
86 |
87 | ts_start = start
88 | step = datetime.timedelta(minutes=step)
89 | url = self.base_url % (feed, datastream)
90 | counter = 1
91 |
92 | while ts_start < end:
93 | ts_end = min(ts_start + step, end)
94 | data = {'limit': 1000, 'interval': 0, 'start': ts_start.isoformat(), 'end': ts_end.isoformat(), 'c': counter}
95 | response = requests.get(url, params=data, headers=self.headers(), timeout=self.timeout)
96 | response = json.loads(response.text)
97 | if 'datapoints' in response:
98 | for datapoint in response['datapoints']:
99 | yield [datapoint['at'], datapoint['value']]
100 | ts_start = ts_end
101 | counter = counter + 1
102 |
103 |
104 | def push(self, feed, datastream, value):
105 | """
106 | Pushes a single value with current timestamp to the given feed/datastream
107 | """
108 | try:
109 | url = self.base_url % (feed, datastream) + ".json"
110 | data = json.dumps({'current_value' : value})
111 | response = requests.put(url, data=data, headers=self.headers(), timeout=self.timeout)
112 | self.last_response = response.status_code
113 | return self.last_response == 200
114 | except Exception as e:
115 | self.last_response = e
116 | return False
117 |
--------------------------------------------------------------------------------
/libs/services/Sense.py:
--------------------------------------------------------------------------------
1 | #! /usr/bin/python
2 | # -*- coding: utf-8 -*-
3 | # vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4
4 |
5 | # Copyright (C) 2013 by Xose Pérez
6 | #
7 | # This program is free software: you can redistribute it and/or modify
8 | # it under the terms of the GNU General Public License as published by
9 | # the Free Software Foundation, either version 3 of the License, or
10 | # (at your option) any later version.
11 | #
12 | # This program is distributed in the hope that it will be useful,
13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | # GNU General Public License for more details.
16 | #
17 | # You should have received a copy of the GNU General Public License
18 | # along with this program. If not, see .
19 |
20 | __author__ = "Xose Pérez"
21 | __contact__ = "xose.perez@gmail.com"
22 | __copyright__ = "Copyright (C) 2013 Xose Pérez"
23 | __license__ = 'GPL v3'
24 |
25 | import requests
26 | import json
27 | from CloudService import CloudService
28 |
29 | class Sense(CloudService):
30 | """
31 | Sense.com client
32 | """
33 |
34 | api_key = ''
35 | timeout = 5
36 |
37 | datapoints = []
38 | base_url = "http://api.sen.se/events/"
39 |
40 | def __init__(self, api_key, timeout = None):
41 | """
42 | Constructor, provide API Key
43 | """
44 | self.api_key = api_key
45 | if timeout:
46 | self.timeout = timeout
47 |
48 | def headers(self):
49 | return {
50 | 'sense_key': self.api_key,
51 | 'Content-type': 'application/json'
52 |
53 | }
54 |
55 | def push(self, feed, datastream, value):
56 | """
57 | Pushes a single value with current timestamp to the given feed
58 | """
59 | try:
60 | data = { 'feed_id': feed, 'value': value }
61 | response = requests.post(self.base_url, data=json.dumps(data), headers=self.headers(), timeout=self.timeout)
62 | self.last_response = response.status_code
63 | return self.last_response == 200
64 | except Exception as e:
65 | self.last_response = e
66 | return False
67 |
--------------------------------------------------------------------------------
/libs/services/TempoDB.py:
--------------------------------------------------------------------------------
1 | #! /usr/bin/python
2 | # -*- coding: utf-8 -*-
3 | # vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4
4 |
5 | # Copyright (C) 2013 by Xose Pérez
6 | #
7 | # This program is free software: you can redistribute it and/or modify
8 | # it under the terms of the GNU General Public License as published by
9 | # the Free Software Foundation, either version 3 of the License, or
10 | # (at your option) any later version.
11 | #
12 | # This program is distributed in the hope that it will be useful,
13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | # GNU General Public License for more details.
16 | #
17 | # You should have received a copy of the GNU General Public License
18 | # along with this program. If not, see .
19 |
20 | __author__ = "Xose Pérez"
21 | __contact__ = "xose.perez@gmail.com"
22 | __copyright__ = "Copyright (C) 2013 Xose Pérez"
23 | __license__ = 'GPL v3'
24 |
25 | from tempodb import Client, DataPoint
26 | from datetime import datetime
27 | from CloudService import CloudService
28 |
29 | class TempoDB(CloudService):
30 | """
31 | Tempo-db.com client
32 | """
33 |
34 | _databases = None
35 | _timeout = 5
36 |
37 | def __init__(self, databases, timeout = None):
38 | """
39 | Constructor, provide API Key and secrets for multiple databases
40 | """
41 | self._databases = databases
42 | if timeout:
43 | self._timeout = timeout
44 |
45 | def push(self, database, series, value):
46 | """
47 | Pushes a single value with current timestamp to the given database/series
48 | """
49 | try:
50 | db = self._databases[database]
51 | client = Client(db['api_key'], db['api_secret'])
52 | data = [DataPoint(datetime.now(), float(value))]
53 | client.write_key(series, data)
54 | self.last_response = 'OK'
55 | return True
56 | except Exception as e:
57 | self.last_response = e
58 | return False
59 |
--------------------------------------------------------------------------------
/libs/services/TheThingsIO.py:
--------------------------------------------------------------------------------
1 | #! /usr/bin/python
2 | # -*- coding: utf-8 -*-
3 | # vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4
4 |
5 | # Copyright (C) 2013 by Xose Pérez
6 | #
7 | # This program is free software: you can redistribute it and/or modify
8 | # it under the terms of the GNU General Public License as published by
9 | # the Free Software Foundation, either version 3 of the License, or
10 | # (at your option) any later version.
11 | #
12 | # This program is distributed in the hope that it will be useful,
13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | # GNU General Public License for more details.
16 | #
17 | # You should have received a copy of the GNU General Public License
18 | # along with this program. If not, see .
19 |
20 | __author__ = "Xose Pérez"
21 | __contact__ = "xose.perez@gmail.com"
22 | __copyright__ = "Copyright (C) 2016 Xose Pérez"
23 | __license__ = 'GPL v3'
24 |
25 | from CloudService import CloudService
26 | from thethingsio.thethingsAPI import thethingsiO
27 |
28 | class TheThingsIO(CloudService):
29 | """
30 | theThings.io client
31 | """
32 |
33 | things = None
34 |
35 | def __init__(self, things):
36 | """
37 | Constructor, provide API Key
38 | """
39 | self.things = things
40 |
41 | def push(self, thing, variable, value):
42 | """
43 | Pushes a single value with current timestamp to the given thing/variable
44 | """
45 | try:
46 | t = self.things.get(thing)
47 | api = thethingsiO(t['token'])
48 | api.clear()
49 | api.addVar(variable, value)
50 | self.last_response = api.write()
51 | return self.last_response == 201
52 | except Exception as e:
53 | self.last_response = e
54 | return False
55 |
--------------------------------------------------------------------------------
/libs/services/Thingspeak.py:
--------------------------------------------------------------------------------
1 | #! /usr/bin/python
2 | # -*- coding: utf-8 -*-
3 | # vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4
4 |
5 | # Copyright (C) 2013 by Xose Pérez
6 | #
7 | # This program is free software: you can redistribute it and/or modify
8 | # it under the terms of the GNU General Public License as published by
9 | # the Free Software Foundation, either version 3 of the License, or
10 | # (at your option) any later version.
11 | #
12 | # This program is distributed in the hope that it will be useful,
13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | # GNU General Public License for more details.
16 | #
17 | # You should have received a copy of the GNU General Public License
18 | # along with this program. If not, see .
19 |
20 | __author__ = "Xose Pérez"
21 | __contact__ = "xose.perez@gmail.com"
22 | __copyright__ = "Copyright (C) 2013 Xose Pérez"
23 | __license__ = 'GPL v3'
24 |
25 | import requests
26 | import time
27 | from CloudService import CloudService
28 |
29 | class Thingspeak(CloudService):
30 | """
31 | Thingspeak.com client
32 | """
33 |
34 | channels = {}
35 | api_url = "http://api.thingspeak.com/update"
36 | time_between_updates = 15
37 |
38 | def __init__(self, channels, group_fields=True, group_timeout=2, request_timeout=5):
39 | """
40 | Constructor, Api Key mandatory
41 | """
42 | for id, key in channels.iteritems():
43 | self.channels[id] = {
44 | 'key': key,
45 | 'timeout': None,
46 | 'data': dict()
47 | }
48 |
49 | self.group_fields = group_fields
50 | self.group_timeout = group_timeout
51 | self.request_timeout = request_timeout
52 |
53 | def push(self, channel_id, field, value):
54 | """
55 | Pushes a single value with current timestamp to the given feed/datastream
56 | """
57 | channel = self.channels.get(int(channel_id))
58 | if channel == None:
59 | return False
60 |
61 | channel['data'][field] = value
62 | if self.group_fields:
63 | channel['timeout'] = max(channel['timeout'], time.time() + self.group_timeout)
64 | else:
65 | channel['timeout'] = max(channel['timeout'], time.time())
66 |
67 | return True
68 |
69 | def loop(self):
70 | """
71 | Continuously check for pending sendings
72 | """
73 | for id, channel in self.channels.iteritems():
74 | if channel['timeout'] is not None and channel['timeout'] < time.time():
75 | if len(channel['data']) > 0:
76 | self.send(channel['key'], channel['data'])
77 | channel['timeout'] = time.time() + self.time_between_updates
78 | channel['data'] = {}
79 |
80 | def send(self, key, data):
81 | """
82 | Actually sends the data
83 | """
84 | data['key'] = key
85 | try:
86 | response = requests.post(self.api_url, data=data, timeout=self.request_timeout)
87 | self.last_response = response.status_code
88 | return self.last_response == 200
89 | except Exception as e:
90 | self.last_response = e
91 | return False
92 |
--------------------------------------------------------------------------------
/libs/services/Xively.py:
--------------------------------------------------------------------------------
1 | #! /usr/bin/python
2 | # -*- coding: utf-8 -*-
3 | # vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4
4 |
5 | # Copyright (C) 2013 by Xose Pérez
6 | #
7 | # This program is free software: you can redistribute it and/or modify
8 | # it under the terms of the GNU General Public License as published by
9 | # the Free Software Foundation, either version 3 of the License, or
10 | # (at your option) any later version.
11 | #
12 | # This program is distributed in the hope that it will be useful,
13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | # GNU General Public License for more details.
16 | #
17 | # You should have received a copy of the GNU General Public License
18 | # along with this program. If not, see .
19 |
20 | __author__ = "Xose Pérez"
21 | __contact__ = "xose.perez@gmail.com"
22 | __copyright__ = "Copyright (C) 2013 Xose Pérez"
23 | __license__ = 'GPL v3'
24 |
25 | import requests
26 | import json
27 | import datetime
28 | from CloudService import CloudService
29 |
30 | class Xively(CloudService):
31 | """
32 | Xively.com client
33 | """
34 |
35 | api_key = ''
36 | timeout = 5
37 |
38 | datapoints = []
39 | base_url = "https://api.xively.com/v2/feeds/%s/datastreams/%s.json"
40 |
41 | def __init__(self, api_key, timeout = None):
42 | """
43 | Constructor, provide API Key
44 | """
45 | self.api_key = api_key
46 | if timeout:
47 | self.timeout = timeout
48 |
49 | def headers(self):
50 | return {
51 | 'X-ApiKey': self.api_key,
52 | 'Content-type': 'application/json'
53 | }
54 |
55 | def push(self, feed, datastream, value):
56 | """
57 | Pushes a single value with current timestamp to the given feed/datastream
58 | """
59 | try:
60 | url = self.base_url % (feed, datastream)
61 | data = json.dumps({'current_value' : value})
62 | response = requests.put(url, data=data, headers=self.headers(), timeout=self.timeout)
63 | self.last_response = response.status_code
64 | return self.last_response == 200
65 | except Exception as e:
66 | self.last_response = e
67 | return False
68 |
--------------------------------------------------------------------------------
/libs/services/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xoseperez/mqtt2cloud/ec39e64151c6d221597001bd6cbeb00a8499d496/libs/services/__init__.py
--------------------------------------------------------------------------------
/mqtt2cosm.py:
--------------------------------------------------------------------------------
1 | #! /usr/bin/python
2 | # -*- coding: utf-8 -*-
3 | # vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4
4 |
5 | # MQTT to Cloud
6 | # Copyright (C) 2013 by Xose Pérez
7 | #
8 | # This program is free software: you can redistribute it and/or modify
9 | # it under the terms of the GNU General Public License as published by
10 | # the Free Software Foundation, either version 3 of the License, or
11 | # (at your option) any later version.
12 | #
13 | # This program is distributed in the hope that it will be useful,
14 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
15 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 | # GNU General Public License for more details.
17 | #
18 | # You should have received a copy of the GNU General Public License
19 | # along with this program. If not, see .
20 |
21 | __app__ = "MQTT to Cloud"
22 | __author__ = "Xose Pérez"
23 | __contact__ = "xose.perez@gmail.com"
24 | __copyright__ = "Copyright (C) 2013 Xose Pérez"
25 | __license__ = 'GPL v3'
26 |
27 | import sys
28 |
29 | from libs.Config import Config
30 | from libs.Mosquitto import Mosquitto
31 | from libs.Manager import Manager
32 |
33 | from libs.services.Cosm import Cosm
34 |
35 | if __name__ == "__main__":
36 |
37 | config = Config('config/mqtt2cosm.yaml')
38 |
39 | manager = Manager(config.get('daemon', 'pidfile', '/tmp/mqtt2cloud.pid'))
40 | manager.stdout = config.get('daemon', 'stdout', '/dev/null')
41 | manager.stderr = config.get('daemon', 'stderr', '/dev/null')
42 | manager.debug = config.get('daemon', 'debug', False)
43 |
44 | mqtt = Mosquitto(config.get('mqtt', 'client_id'))
45 | mqtt.host = config.get('mqtt', 'host')
46 | mqtt.port = config.get('mqtt', 'port')
47 | mqtt.keepalive = config.get('mqtt', 'keepalive')
48 | mqtt.clean_session = config.get('mqtt', 'clean_session')
49 | mqtt.qos = config.get('mqtt', 'qos', 0)
50 | mqtt.retain = config.get('mqtt', 'retain', True)
51 | mqtt.status_topic = config.get('mqtt', 'status_topic')
52 | mqtt.set_will = config.get('mqtt', 'set_will')
53 | manager.mqtt = mqtt
54 |
55 | cosm = Cosm(
56 | config.get('cosm', 'api_key'),
57 | config.get('cosm', 'timeout')
58 | )
59 | manager.service = cosm
60 |
61 | manager.load_topics(config.get('topics', default=[]))
62 |
63 | if len(sys.argv) == 2:
64 | if 'start' == sys.argv[1]:
65 | manager.start()
66 | elif 'stop' == sys.argv[1]:
67 | manager.stop()
68 | elif 'restart' == sys.argv[1]:
69 | manager.restart()
70 | else:
71 | print "Unknown command"
72 | sys.exit(2)
73 | sys.exit(0)
74 | else:
75 | print "usage: %s start|stop|restart" % sys.argv[0]
76 | sys.exit(2)
77 |
78 |
--------------------------------------------------------------------------------
/mqtt2sense.py:
--------------------------------------------------------------------------------
1 | #! /usr/bin/python
2 | # -*- coding: utf-8 -*-
3 | # vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4
4 |
5 | # MQTT to Cloud
6 | # Copyright (C) 2013 by Xose Pérez
7 | #
8 | # This program is free software: you can redistribute it and/or modify
9 | # it under the terms of the GNU General Public License as published by
10 | # the Free Software Foundation, either version 3 of the License, or
11 | # (at your option) any later version.
12 | #
13 | # This program is distributed in the hope that it will be useful,
14 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
15 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 | # GNU General Public License for more details.
17 | #
18 | # You should have received a copy of the GNU General Public License
19 | # along with this program. If not, see .
20 |
21 | __app__ = "MQTT to Cloud"
22 | __author__ = "Xose Pérez"
23 | __contact__ = "xose.perez@gmail.com"
24 | __copyright__ = "Copyright (C) 2013 Xose Pérez"
25 | __license__ = 'GPL v3'
26 |
27 | import sys
28 |
29 | from libs.Config import Config
30 | from libs.Mosquitto import Mosquitto
31 | from libs.Manager import Manager
32 |
33 | from libs.services.Sense import Sense
34 |
35 | if __name__ == "__main__":
36 |
37 | config = Config('config/mqtt2sense.yaml')
38 |
39 | manager = Manager(config.get('daemon', 'pidfile', '/tmp/mqtt2sense.pid'))
40 | manager.stdout = config.get('daemon', 'stdout', '/dev/null')
41 | manager.stderr = config.get('daemon', 'stderr', '/dev/null')
42 | manager.debug = config.get('daemon', 'debug', False)
43 |
44 | mqtt = Mosquitto(config.get('mqtt', 'client_id'))
45 | mqtt.host = config.get('mqtt', 'host')
46 | mqtt.port = config.get('mqtt', 'port')
47 | mqtt.keepalive = config.get('mqtt', 'keepalive')
48 | mqtt.clean_session = config.get('mqtt', 'clean_session')
49 | mqtt.qos = config.get('mqtt', 'qos', 0)
50 | mqtt.retain = config.get('mqtt', 'retain', True)
51 | mqtt.status_topic = config.get('mqtt', 'status_topic')
52 | mqtt.set_will = config.get('mqtt', 'set_will')
53 | manager.mqtt = mqtt
54 |
55 | sense = Sense(
56 | config.get('sense', 'api_key'),
57 | config.get('sense', 'timeout')
58 | )
59 | manager.service = sense
60 |
61 | manager.load_topics(config.get('topics', default=[]))
62 |
63 | if len(sys.argv) == 2:
64 | if 'start' == sys.argv[1]:
65 | manager.start()
66 | elif 'stop' == sys.argv[1]:
67 | manager.stop()
68 | elif 'restart' == sys.argv[1]:
69 | manager.restart()
70 | else:
71 | print "Unknown command"
72 | sys.exit(2)
73 | sys.exit(0)
74 | else:
75 | print "usage: %s start|stop|restart" % sys.argv[0]
76 | sys.exit(2)
77 |
78 |
--------------------------------------------------------------------------------
/mqtt2tempodb.py:
--------------------------------------------------------------------------------
1 | #! /usr/bin/python
2 | # -*- coding: utf-8 -*-
3 | # vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4
4 |
5 | # MQTT to Cloud
6 | # Copyright (C) 2013 by Xose Pérez
7 | #
8 | # This program is free software: you can redistribute it and/or modify
9 | # it under the terms of the GNU General Public License as published by
10 | # the Free Software Foundation, either version 3 of the License, or
11 | # (at your option) any later version.
12 | #
13 | # This program is distributed in the hope that it will be useful,
14 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
15 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 | # GNU General Public License for more details.
17 | #
18 | # You should have received a copy of the GNU General Public License
19 | # along with this program. If not, see .
20 |
21 | __app__ = "MQTT to Cloud"
22 | __author__ = "Xose Pérez"
23 | __contact__ = "xose.perez@gmail.com"
24 | __copyright__ = "Copyright (C) 2013 Xose Pérez"
25 | __license__ = 'GPL v3'
26 |
27 | import sys
28 |
29 | from libs.Config import Config
30 | from libs.Mosquitto import Mosquitto
31 | from libs.Manager import Manager
32 |
33 | from libs.services.TempoDB import TempoDB
34 |
35 | if __name__ == "__main__":
36 |
37 | config = Config('config/mqtt2tempodb.yaml')
38 |
39 | manager = Manager(config.get('daemon', 'pidfile', '/tmp/mqtt2cloud.pid'))
40 | manager.stdout = config.get('daemon', 'stdout', '/dev/null')
41 | manager.stderr = config.get('daemon', 'stderr', '/dev/null')
42 | manager.debug = config.get('daemon', 'debug', False)
43 |
44 | mqtt = Mosquitto(config.get('mqtt', 'client_id'))
45 | mqtt.host = config.get('mqtt', 'host')
46 | mqtt.port = config.get('mqtt', 'port')
47 | mqtt.keepalive = config.get('mqtt', 'keepalive')
48 | mqtt.clean_session = config.get('mqtt', 'clean_session')
49 | mqtt.qos = config.get('mqtt', 'qos', 0)
50 | mqtt.retain = config.get('mqtt', 'retain', True)
51 | mqtt.status_topic = config.get('mqtt', 'status_topic')
52 | mqtt.set_will = config.get('mqtt', 'set_will')
53 | manager.mqtt = mqtt
54 |
55 | tempodb = TempoDB(
56 | config.get('tempodb', 'databases'),
57 | config.get('tempodb', 'timeout')
58 | )
59 | manager.service = tempodb
60 |
61 | manager.load_topics(config.get('topics', default=[]))
62 |
63 | if len(sys.argv) == 2:
64 | if 'start' == sys.argv[1]:
65 | manager.start()
66 | elif 'stop' == sys.argv[1]:
67 | manager.stop()
68 | elif 'restart' == sys.argv[1]:
69 | manager.restart()
70 | else:
71 | print "Unknown command"
72 | sys.exit(2)
73 | sys.exit(0)
74 | else:
75 | print "usage: %s start|stop|restart" % sys.argv[0]
76 | sys.exit(2)
77 |
78 |
--------------------------------------------------------------------------------
/mqtt2thethingsio.py:
--------------------------------------------------------------------------------
1 | #! /usr/bin/python
2 | # -*- coding: utf-8 -*-
3 | # vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4
4 |
5 | # MQTT to Cloud
6 | # Copyright (C) 2016 by Xose Pérez
7 | #
8 | # This program is free software: you can redistribute it and/or modify
9 | # it under the terms of the GNU General Public License as published by
10 | # the Free Software Foundation, either version 3 of the License, or
11 | # (at your option) any later version.
12 | #
13 | # This program is distributed in the hope that it will be useful,
14 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
15 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 | # GNU General Public License for more details.
17 | #
18 | # You should have received a copy of the GNU General Public License
19 | # along with this program. If not, see .
20 |
21 | __app__ = "MQTT to Cloud"
22 | __author__ = "Xose Pérez"
23 | __contact__ = "xose.perez@gmail.com"
24 | __copyright__ = "Copyright (C) 2016 Xose Pérez"
25 | __license__ = 'GPL v3'
26 |
27 | import sys
28 |
29 | from libs.Config import Config
30 | from libs.Mosquitto import Mosquitto
31 | from libs.Manager import Manager
32 |
33 | from libs.services.TheThingsIO import TheThingsIO
34 |
35 | if __name__ == "__main__":
36 |
37 | config = Config('config/mqtt2thethingsio.yaml')
38 |
39 | manager = Manager(config.get('daemon', 'pidfile', '/tmp/mqtt2cloud.pid'))
40 | manager.stdout = config.get('daemon', 'stdout', '/dev/null')
41 | manager.stderr = config.get('daemon', 'stderr', '/dev/null')
42 | manager.debug = config.get('daemon', 'debug', False)
43 |
44 | mqtt = Mosquitto(config.get('mqtt', 'client_id'))
45 | mqtt.host = config.get('mqtt', 'host')
46 | mqtt.port = config.get('mqtt', 'port')
47 | mqtt.keepalive = config.get('mqtt', 'keepalive')
48 | mqtt.clean_session = config.get('mqtt', 'clean_session')
49 | mqtt.qos = config.get('mqtt', 'qos', 0)
50 | mqtt.retain = config.get('mqtt', 'retain', True)
51 | mqtt.status_topic = config.get('mqtt', 'status_topic')
52 | mqtt.set_will = config.get('mqtt', 'set_will')
53 | manager.mqtt = mqtt
54 |
55 | thethingsio = TheThingsIO(
56 | config.get('thethingsio', 'things')
57 | )
58 | manager.service = thethingsio
59 |
60 | manager.load_topics(config.get('topics', default=[]))
61 |
62 | if len(sys.argv) == 2:
63 | if 'start' == sys.argv[1]:
64 | manager.start()
65 | elif 'stop' == sys.argv[1]:
66 | manager.stop()
67 | elif 'restart' == sys.argv[1]:
68 | manager.restart()
69 | else:
70 | print "Unknown command"
71 | sys.exit(2)
72 | sys.exit(0)
73 | else:
74 | print "usage: %s start|stop|restart" % sys.argv[0]
75 | sys.exit(2)
76 |
--------------------------------------------------------------------------------
/mqtt2thingspeak.py:
--------------------------------------------------------------------------------
1 | #! /usr/bin/python
2 | # -*- coding: utf-8 -*-
3 | # vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4
4 |
5 | # MQTT to Cloud
6 | # Copyright (C) 2013 by Xose Pérez
7 | #
8 | # This program is free software: you can redistribute it and/or modify
9 | # it under the terms of the GNU General Public License as published by
10 | # the Free Software Foundation, either version 3 of the License, or
11 | # (at your option) any later version.
12 | #
13 | # This program is distributed in the hope that it will be useful,
14 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
15 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 | # GNU General Public License for more details.
17 | #
18 | # You should have received a copy of the GNU General Public License
19 | # along with this program. If not, see .
20 |
21 | __app__ = "MQTT to Cloud"
22 | __author__ = "Xose Pérez"
23 | __contact__ = "xose.perez@gmail.com"
24 | __copyright__ = "Copyright (C) 2013 Xose Pérez"
25 | __license__ = 'GPL v3'
26 |
27 | import sys
28 |
29 | from libs.Config import Config
30 | from libs.Mosquitto import Mosquitto
31 | from libs.Manager import Manager
32 |
33 | from libs.services.Thingspeak import Thingspeak
34 |
35 | if __name__ == "__main__":
36 |
37 | config = Config('config/mqtt2thingspeak.yaml')
38 |
39 | manager = Manager(config.get('daemon', 'pidfile', '/tmp/mqtt2thingspeak.pid'))
40 | manager.stdout = config.get('daemon', 'stdout', '/dev/null')
41 | manager.stderr = config.get('daemon', 'stderr', '/dev/null')
42 | manager.debug = config.get('daemon', 'debug', False)
43 |
44 | mqtt = Mosquitto(config.get('mqtt', 'client_id'))
45 | mqtt.host = config.get('mqtt', 'host')
46 | mqtt.port = config.get('mqtt', 'port')
47 | mqtt.keepalive = config.get('mqtt', 'keepalive')
48 | mqtt.clean_session = config.get('mqtt', 'clean_session')
49 | mqtt.qos = config.get('mqtt', 'qos', 0)
50 | mqtt.retain = config.get('mqtt', 'retain', True)
51 | mqtt.status_topic = config.get('mqtt', 'status_topic')
52 | mqtt.set_will = config.get('mqtt', 'set_will')
53 | manager.mqtt = mqtt
54 |
55 | thingspeak = Thingspeak(
56 | config.get('thingspeak', 'channels'),
57 | )
58 | manager.service = thingspeak
59 |
60 | manager.load_topics(config.get('topics', default=[]))
61 |
62 | if len(sys.argv) == 2:
63 | if 'start' == sys.argv[1]:
64 | manager.start()
65 | elif 'stop' == sys.argv[1]:
66 | manager.stop()
67 | elif 'restart' == sys.argv[1]:
68 | manager.restart()
69 | else:
70 | print "Unknown command"
71 | sys.exit(2)
72 | sys.exit(0)
73 | else:
74 | print "usage: %s start|stop|restart" % sys.argv[0]
75 | sys.exit(2)
76 |
77 |
--------------------------------------------------------------------------------
/mqtt2xively.py:
--------------------------------------------------------------------------------
1 | #! /usr/bin/python
2 | # -*- coding: utf-8 -*-
3 | # vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4
4 |
5 | # MQTT to Cloud
6 | # Copyright (C) 2013 by Xose Pérez
7 | #
8 | # This program is free software: you can redistribute it and/or modify
9 | # it under the terms of the GNU General Public License as published by
10 | # the Free Software Foundation, either version 3 of the License, or
11 | # (at your option) any later version.
12 | #
13 | # This program is distributed in the hope that it will be useful,
14 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
15 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 | # GNU General Public License for more details.
17 | #
18 | # You should have received a copy of the GNU General Public License
19 | # along with this program. If not, see .
20 |
21 | __app__ = "MQTT to Cloud"
22 | __author__ = "Xose Pérez"
23 | __contact__ = "xose.perez@gmail.com"
24 | __copyright__ = "Copyright (C) 2013 Xose Pérez"
25 | __license__ = 'GPL v3'
26 |
27 | import sys
28 |
29 | from libs.Config import Config
30 | from libs.Mosquitto import Mosquitto
31 | from libs.Manager import Manager
32 |
33 | from libs.services.Xively import Xively
34 |
35 | if __name__ == "__main__":
36 |
37 | config = Config('config/mqtt2xively.yaml')
38 |
39 | manager = Manager(config.get('daemon', 'pidfile', '/tmp/mqtt2xively.pid'))
40 | manager.stdout = config.get('daemon', 'stdout', '/dev/null')
41 | manager.stderr = config.get('daemon', 'stderr', '/dev/null')
42 | manager.debug = config.get('daemon', 'debug', False)
43 |
44 | mqtt = Mosquitto(config.get('mqtt', 'client_id'))
45 | mqtt.host = config.get('mqtt', 'host')
46 | mqtt.port = config.get('mqtt', 'port')
47 | mqtt.keepalive = config.get('mqtt', 'keepalive')
48 | mqtt.clean_session = config.get('mqtt', 'clean_session')
49 | mqtt.qos = config.get('mqtt', 'qos', 0)
50 | mqtt.retain = config.get('mqtt', 'retain', True)
51 | mqtt.status_topic = config.get('mqtt', 'status_topic')
52 | mqtt.set_will = config.get('mqtt', 'set_will')
53 | manager.mqtt = mqtt
54 |
55 | xively = Xively(
56 | config.get('xively', 'api_key'),
57 | config.get('xively', 'timeout')
58 | )
59 | manager.service = xively
60 |
61 | manager.load_topics(config.get('topics', default=[]))
62 |
63 | if len(sys.argv) == 2:
64 | if 'start' == sys.argv[1]:
65 | manager.start()
66 | elif 'stop' == sys.argv[1]:
67 | manager.stop()
68 | elif 'restart' == sys.argv[1]:
69 | manager.restart()
70 | else:
71 | print "Unknown command"
72 | sys.exit(2)
73 | sys.exit(0)
74 | else:
75 | print "usage: %s start|stop|restart" % sys.argv[0]
76 | sys.exit(2)
77 |
78 |
--------------------------------------------------------------------------------
/var/log/.empty:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xoseperez/mqtt2cloud/ec39e64151c6d221597001bd6cbeb00a8499d496/var/log/.empty
--------------------------------------------------------------------------------
/var/run/.empty:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xoseperez/mqtt2cloud/ec39e64151c6d221597001bd6cbeb00a8499d496/var/run/.empty
--------------------------------------------------------------------------------