1 | # -*- coding: utf-8 -*- |
||
2 | # |
||
3 | # This file is part of Glances. |
||
4 | # |
||
5 | # Copyright (C) 2019 Nicolargo <[email protected]> |
||
6 | # |
||
7 | # Glances is free software; you can redistribute it and/or modify |
||
8 | # it under the terms of the GNU Lesser 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 | # Glances 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 Lesser General Public License for more details. |
||
16 | # |
||
17 | # You should have received a copy of the GNU Lesser General Public License |
||
18 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
||
19 | |||
20 | """MQTT interface class.""" |
||
21 | |||
22 | import socket |
||
23 | import string |
||
24 | |||
25 | from glances.logger import logger |
||
26 | from glances.exports.glances_export import GlancesExport |
||
27 | |||
28 | # Import paho for MQTT |
||
29 | from requests import certs |
||
30 | import paho.mqtt.client as paho |
||
31 | |||
32 | |||
33 | class Export(GlancesExport): |
||
34 | |||
35 | """This class manages the MQTT export module.""" |
||
36 | |||
37 | def __init__(self, config=None, args=None): |
||
38 | """Init the MQTT export IF.""" |
||
39 | super(Export, self).__init__(config=config, args=args) |
||
40 | |||
41 | # Mandatories configuration keys (additional to host and port) |
||
42 | self.user = None |
||
43 | self.password = None |
||
44 | self.topic = None |
||
45 | self.tls = 'true' |
||
46 | |||
47 | # Load the MQTT configuration file |
||
48 | self.export_enable = self.load_conf('mqtt', |
||
49 | mandatories=['host', 'password'], |
||
50 | options=['port', 'user', 'topic', 'tls']) |
||
51 | if not self.export_enable: |
||
52 | exit('Missing MQTT config') |
||
53 | |||
54 | # Get the current hostname |
||
55 | self.hostname = socket.gethostname() |
||
56 | |||
57 | self.port = int(self.port) or 8883 |
||
58 | self.topic = self.topic or 'glances' |
||
59 | self.user = self.user or 'glances' |
||
60 | self.tls = (self.tls and self.tls.lower() == 'true') |
||
61 | |||
62 | # Init the MQTT client |
||
63 | self.client = self.init() |
||
64 | |||
65 | def init(self): |
||
66 | """Init the connection to the MQTT server.""" |
||
67 | if not self.export_enable: |
||
68 | return None |
||
69 | try: |
||
70 | client = paho.Client(client_id='glances_' + self.hostname, |
||
71 | clean_session=False) |
||
72 | client.username_pw_set(username=self.user, |
||
73 | password=self.password) |
||
74 | if self.tls: |
||
75 | client.tls_set(certs.where()) |
||
76 | client.connect(host=self.host, |
||
77 | port=self.port) |
||
78 | client.loop_start() |
||
79 | return client |
||
80 | except Exception as e: |
||
0 ignored issues
–
show
|
|||
81 | logger.critical("Connection to MQTT server failed : %s " % e) |
||
0 ignored issues
–
show
|
|||
82 | return None |
||
83 | |||
84 | def export(self, name, columns, points): |
||
85 | """Write the points in MQTT.""" |
||
86 | |||
87 | WHITELIST = '_-' + string.ascii_letters + string.digits |
||
88 | SUBSTITUTE = '_' |
||
89 | |||
90 | def whitelisted(s, |
||
91 | whitelist=WHITELIST, |
||
92 | substitute=SUBSTITUTE): |
||
93 | return ''.join(c if c in whitelist else substitute for c in s) |
||
94 | |||
95 | for sensor, value in zip(columns, points): |
||
96 | try: |
||
97 | sensor = [whitelisted(name) for name in sensor.split('.')] |
||
98 | tobeexport = [self.topic, self.hostname, name] |
||
99 | tobeexport.extend(sensor) |
||
100 | topic = '/'.join(tobeexport) |
||
101 | |||
102 | self.client.publish(topic, value) |
||
103 | except Exception as e: |
||
0 ignored issues
–
show
Catching very general exceptions such as
Exception is usually not recommended.
Generally, you would want to handle very specific errors in the exception handler. This ensure that you do not hide other types of errors which should be fixed. So, unless you specifically plan to handle any error, consider adding a more specific exception. ![]() |
|||
104 | logger.error("Can not export stats to MQTT server (%s)" % e) |
||
0 ignored issues
–
show
|
|||
105 |
Generally, you would want to handle very specific errors in the exception handler. This ensure that you do not hide other types of errors which should be fixed.
So, unless you specifically plan to handle any error, consider adding a more specific exception.