aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.gitignore1
-rw-r--r--mqtt-client/Dockerfile2
-rw-r--r--mqtt-client/mqtt-client.py45
-rw-r--r--mqtt-client/requirements.txt1
-rw-r--r--switch-snmp/mikrotik.py28
-rw-r--r--switch-snmp/requirements.txt3
-rw-r--r--switch-snmp/switches.py57
7 files changed, 107 insertions, 30 deletions
diff --git a/.gitignore b/.gitignore
index 4059ff0..69b3cef 100644
--- a/.gitignore
+++ b/.gitignore
@@ -8,6 +8,7 @@ influxdb-config/
influxdb-data/
node-red-data/
prometheus/web.yml
+prometheus/web.yml
# Byte-compiled / optimized / DLL files
__pycache__/
diff --git a/mqtt-client/Dockerfile b/mqtt-client/Dockerfile
index ad59f9b..80350cf 100644
--- a/mqtt-client/Dockerfile
+++ b/mqtt-client/Dockerfile
@@ -6,5 +6,7 @@ RUN apt-get install -y python3-pip iputils-ping
COPY . /app
WORKDIR /app
RUN pip3 install -r requirements.txt
+RUN pip3 install -r TasmotaCLI/requirements.txt
+RUN pip3 install docker
ENTRYPOINT ["python3"]
CMD ["mqtt-client.py"]
diff --git a/mqtt-client/mqtt-client.py b/mqtt-client/mqtt-client.py
index 18dcd82..f81d1d6 100644
--- a/mqtt-client/mqtt-client.py
+++ b/mqtt-client/mqtt-client.py
@@ -1,6 +1,7 @@
import paho.mqtt.client as paho
from influxdb_client import InfluxDBClient, Point, WritePrecision
from influxdb_client.client.write_api import SYNCHRONOUS
+import prometheus_client
import threading
import time
import json
@@ -18,6 +19,32 @@ class MQTTClient:
org = os.environ["DOCKER_INFLUXDB_INIT_ORG"]
)
self.influxc.ping()
+ self.tasmota_power_prom = prometheus_client.Gauge(
+ "tasmota_power",
+ "Power metrics as reported by Tasmota-flashed plugs",
+ labelnames = ["plug", "field"]
+ )
+ self.humidity_prom = prometheus_client.Gauge(
+ "humidity",
+ "Humidity as reported by a zigbee device over MQTT",
+ labelnames = ["location"]
+ )
+ self.temperature_prom = prometheus_client.Gauge(
+ "temperature",
+ "Temperature as reported by a zigbee device over MQTT",
+ labelnames = ["location"]
+ )
+ self.doorsensor_prom = prometheus_client.Enum(
+ "door_sensor",
+ "Door sensor state change as reported by zigbee door sensor over MQTT",
+ states = ["opened", "closed"],
+ labelnames = ["location"]
+ )
+ self.door_opened_counter = prometheus_client.Counter(
+ "door_opened",
+ "Door sensor opened as reported by zigbee door sensor over MQTT",
+ labelnames = ["location"]
+ )
self.mqttc = paho.Client(mqtt_client_name, clean_session = True)
if loop_forever:
@@ -49,11 +76,15 @@ class MQTTClient:
elif type_ == "TasmotaZigbee":
self.handle_zigbee(msg_j)
+
def handle_plug(self, msg_j, location):
print("'%s' is using %.1fw @ %s. %.1fkWh so far today, %.1fkWh yesterday" % (location, msg_j["ENERGY"]["Power"], msg_j["Time"], msg_j["ENERGY"]["Today"], msg_j["ENERGY"]["Yesterday"]))
fields = {k: v for k, v in msg_j["ENERGY"].items() if k not in {"TotalStartTime"}}
self.append_influxdb(fields, "tasmota_power", {"plug": location})
+ for k, v in fields.items():
+ self.tasmota_power_prom.labels(plug = location, field = k).set(v)
+
def handle_zigbee(self, msg_j):
def toggle_geoffery():
print("Starting thread...")
@@ -81,6 +112,17 @@ class MQTTClient:
print("Harvey's button pressed, toggling TasmotaHarveyPC Plug")
self.toggle_plug("TasmotaHarveyPC")
+ if "Humidity" in fields.keys():
+ self.humidity_prom.labels(location = friendlyname).set(fields["Humidity"])
+ elif "Temperature" in fields.keys():
+ self.temperature_prom.labels(location = friendlyname).set(fields["Temperature"])
+ elif "ZoneStatus" in fields.keys() and "Contact" in fields.keys():
+ if fields["ZoneStatus"] == 1 and fields["Contact"] == 1:
+ self.doorsensor_prom.labels(location = friendlyname).state("opened")
+ self.door_opened_counter.labels(location = friendlyname).inc()
+ elif fields["ZoneStatus"] == 0 and fields["Contact"] == 0:
+ self.doorsensor_prom.labels(location = friendlyname).state("closed")
+
def set_plug(self, friendlyname, payload):
t = "cmnd/TasmotaPlug/%s/Power" % friendlyname
self.mqttc.publish(t, payload = payload)
@@ -106,8 +148,11 @@ if __name__ == "__main__":
dotenv.load_dotenv(dotenv_path = env_path)
INFLUXDB_HOST = "dns.athome"
MQTT_HOST = "dns.athome"
+ PROM_HOST = "dns.athome"
else:
INFLUXDB_HOST = "influxdb"
MQTT_HOST = "mqtt"
+ PROM_HOST = "prometheus"
+ prometheus_client.start_http_server(8000)
mqtt_client = MQTTClient()
diff --git a/mqtt-client/requirements.txt b/mqtt-client/requirements.txt
index ac151c7..3e6f8db 100644
--- a/mqtt-client/requirements.txt
+++ b/mqtt-client/requirements.txt
@@ -1,3 +1,4 @@
paho-mqtt==1.6.1
python-dotenv
influxdb-client
+prometheus-client
diff --git a/switch-snmp/mikrotik.py b/switch-snmp/mikrotik.py
index 29bc797..8493675 100644
--- a/switch-snmp/mikrotik.py
+++ b/switch-snmp/mikrotik.py
@@ -8,9 +8,6 @@ import time
import os
import re
-from influxdb_client import InfluxDBClient, Point, WritePrecision
-from influxdb_client.client.write_api import SYNCHRONOUS
-
logging.basicConfig(
format = "%(levelname)s\t[%(asctime)s]\t%(message)s",
level = logging.INFO,
@@ -121,30 +118,6 @@ def print_points(points):
measurement["fields"]["tpPoeVoltage"],
))
-def append(points):
- env_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), "..", "config.env")
- if os.path.exists(env_path):
- import dotenv
- dotenv.load_dotenv(dotenv_path = env_path)
- INFLUXDB_HOST = "dns.athome"
- else:
- INFLUXDB_HOST = "influxdb"
-
- influxc = InfluxDBClient(
- url = "http://%s:8086" % INFLUXDB_HOST,
- token = os.environ["DOCKER_INFLUXDB_INIT_ADMIN_TOKEN"],
- org = os.environ["DOCKER_INFLUXDB_INIT_ORG"]
- )
- influxc.ping()
-
- write_api = influxc.write_api(write_options = SYNCHRONOUS)
- write_api.write(
- os.environ["DOCKER_INFLUXDB_INIT_BUCKET"],
- os.environ["DOCKER_INFLUXDB_INIT_ORG"],
- points,
- write_precision = WritePrecision.S
- )
-
if __name__ == "__main__":
if not os.path.exists(os.path.join(os.path.dirname(__file__), "mikrotik-switches.conf")):
raise FileNotFoundError("Couldn't find mikrotik config file")
@@ -154,5 +127,4 @@ if __name__ == "__main__":
import json
points = get_points()
print(json.dumps(points, indent = 4))
- append(points)
diff --git a/switch-snmp/requirements.txt b/switch-snmp/requirements.txt
index aaf744d..aeb5843 100644
--- a/switch-snmp/requirements.txt
+++ b/switch-snmp/requirements.txt
@@ -1,4 +1,5 @@
python-dotenv
influxdb-client
pandas
-fabric \ No newline at end of file
+fabric
+prometheus-client \ No newline at end of file
diff --git a/switch-snmp/switches.py b/switch-snmp/switches.py
index aee56d2..bede120 100644
--- a/switch-snmp/switches.py
+++ b/switch-snmp/switches.py
@@ -1,7 +1,62 @@
+import prometheus_client
import snmpOmada
import mikrotik
+import os
+
+from influxdb_client import InfluxDBClient, Point, WritePrecision
+from influxdb_client.client.write_api import SYNCHRONOUS
+
+def append(points):
+ influxc = InfluxDBClient(
+ url = "http://%s:8086" % INFLUXDB_HOST,
+ token = os.environ["DOCKER_INFLUXDB_INIT_ADMIN_TOKEN"],
+ org = os.environ["DOCKER_INFLUXDB_INIT_ORG"]
+ )
+ influxc.ping()
+
+ for measurement in points:
+ for field in measurement["fields"].keys():
+ try:
+ float(measurement["fields"][field])
+ except ValueError:
+ continue
+ else:
+ switch_power.labels(
+ field = field,
+ type = measurement["tags"]["type"],
+ port = str(measurement["tags"]["port"]),
+ port_name = measurement["tags"]["port_name"],
+ host = measurement["tags"]["switch_host"]
+ ).set(float(measurement["fields"][field]))
+
+ write_api = influxc.write_api(write_options = SYNCHRONOUS)
+ write_api.write(
+ os.environ["DOCKER_INFLUXDB_INIT_BUCKET"],
+ os.environ["DOCKER_INFLUXDB_INIT_ORG"],
+ points,
+ write_precision = WritePrecision.S
+ )
if __name__ == "__main__":
+ env_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), "..", "config.env")
+ if os.path.exists(env_path):
+ import dotenv
+ dotenv.load_dotenv(dotenv_path = env_path)
+ INFLUXDB_HOST = "dns.athome"
+ PUSHGATEWAY_HOST = "dns.athome"
+ else:
+ INFLUXDB_HOST = "influxdb"
+ PUSHGATEWAY_HOST = "pushgateway"
+
+ registry = prometheus_client.CollectorRegistry()
+ switch_power = prometheus_client.Gauge(
+ "switch_power",
+ "POE switch power usage metrics from Omada and Mikrotik switches, using Omada SNMP names",
+ labelnames = ["field", "type", "port", "port_name", "host"]
+ )
+
points = snmpOmada.get_points() + mikrotik.get_points()
mikrotik.print_points(points)
- mikrotik.append(points) \ No newline at end of file
+ append(points)
+
+ prometheus_client.push_to_gateway("%s:9091" % PUSHGATEWAY_HOST, job = "switchSNMP", registry = registry) \ No newline at end of file