| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358 |
- #!/usr/bin/env python3
- import itertools
- import json
- from cmk.agent_based.v2 import (
- AgentSection,
- CheckPlugin,
- Metric,
- Result,
- Service,
- State,
- check_levels,
- render,
- )
- # JSON parsing
- def parse_p1(string_table):
- flat = list(itertools.chain.from_iterable(string_table))
- raw = "".join(flat)
- try:
- data = json.loads(raw)
- except json.JSONDecodeError:
- return None
- if not isinstance(data, dict):
- return None
- return data
- agent_section_p1 = AgentSection(
- name="p1",
- parse_function=parse_p1,
- )
- # P1 tariff
- def discover_p1_tariff(section):
- if section is not None and "active_tariff" in section:
- yield Service()
- def check_p1_tariff(section):
- tariff = section.get("active_tariff")
- if tariff is None:
- yield Result(
- state=State.UNKNOWN,
- summary="Active tariff is not available",
- )
- return
- yield Result(
- state=State.OK,
- summary=f"Tariff: {tariff}",
- )
- check_plugin_p1_tariff = CheckPlugin(
- name="p1_tariff",
- sections=["p1"],
- service_name="P1 Tariff",
- discovery_function=discover_p1_tariff,
- check_function=check_p1_tariff,
- )
- # Power
- POWER_ITEMS = {
- "Total": "active_power_w",
- "L1": "active_power_l1_w",
- "L2": "active_power_l2_w",
- "L3": "active_power_l3_w",
- }
- def discover_p1_power(section):
- for item, key in POWER_ITEMS.items():
- if key in section:
- yield Service(item=item)
- def check_p1_power(item, section):
- key = POWER_ITEMS.get(item)
- if key is None or key not in section:
- yield Result(
- state=State.UNKNOWN,
- summary="Power value is not available",
- )
- return
- value = float(section[key])
- yield Result(
- state=State.OK,
- summary=f"{value:.0f} W",
- )
- yield Metric(
- name="p1_power_w",
- value=value,
- boundaries=(0, None),
- )
- check_plugin_p1_power = CheckPlugin(
- name="p1_power",
- sections=["p1"],
- service_name="P1 Power %s",
- discovery_function=discover_p1_power,
- check_function=check_p1_power,
- )
- # Voltage
- VOLTAGE_ITEMS = {
- "L1": "active_voltage_l1_v",
- "L2": "active_voltage_l2_v",
- "L3": "active_voltage_l3_v",
- }
- def discover_p1_voltage(section):
- for item, key in VOLTAGE_ITEMS.items():
- if key in section:
- yield Service(item=item)
- def check_p1_voltage(item, params, section):
- key = VOLTAGE_ITEMS.get(item)
- if key is None or key not in section:
- yield Result(
- state=State.UNKNOWN,
- summary="Voltage value is not available",
- )
- return
- value = float(section[key])
- yield from check_levels(
- value,
- levels_upper=params["levels"],
- metric_name="p1_voltage_v",
- label="Voltage",
- render_func=lambda v: f"{v:.1f} V",
- boundaries=(0, 300),
- )
- check_plugin_p1_voltage = CheckPlugin(
- name="p1_voltage",
- sections=["p1"],
- service_name="P1 Voltage %s",
- discovery_function=discover_p1_voltage,
- check_function=check_p1_voltage,
- check_default_parameters={
- "levels": ("fixed", (252.0, 253.0)),
- },
- check_ruleset_name="p1_voltage",
- )
- # Current
- CURRENT_ITEMS = {
- "Total": "active_current_a",
- "L1": "active_current_l1_a",
- "L2": "active_current_l2_a",
- "L3": "active_current_l3_a",
- }
- def discover_p1_current(section):
- for item, key in CURRENT_ITEMS.items():
- if key in section:
- yield Service(item=item)
- def check_p1_current(item, section):
- key = CURRENT_ITEMS.get(item)
- if key is None or key not in section:
- yield Result(
- state=State.UNKNOWN,
- summary="Current value is not available",
- )
- return
- value = float(section[key])
- yield Result(
- state=State.OK,
- summary=f"{value:.3f} A",
- )
- yield Metric(
- name="p1_current_a",
- value=value,
- boundaries=(0, None),
- )
- check_plugin_p1_current = CheckPlugin(
- name="p1_current",
- sections=["p1"],
- service_name="P1 Current %s",
- discovery_function=discover_p1_current,
- check_function=check_p1_current,
- )
- # Energy import / export
- ENERGY_ITEMS = {
- "Import": {
- "total": "total_power_import_kwh",
- "t1": "total_power_import_t1_kwh",
- "t2": "total_power_import_t2_kwh",
- },
- "Export": {
- "total": "total_power_export_kwh",
- "t1": "total_power_export_t1_kwh",
- "t2": "total_power_export_t2_kwh",
- },
- }
- def discover_p1_energy(section):
- for item, keys in ENERGY_ITEMS.items():
- if any(key in section for key in keys.values()):
- yield Service(item=item)
- def check_p1_energy(item, section):
- keys = ENERGY_ITEMS.get(item)
- if keys is None:
- yield Result(
- state=State.UNKNOWN,
- summary="Unknown energy type",
- )
- return
- found = False
- for metric_name, key in (
- ("p1_energy_total_kwh", keys["total"]),
- ("p1_energy_t1_kwh", keys["t1"]),
- ("p1_energy_t2_kwh", keys["t2"]),
- ):
- if key not in section:
- continue
- found = True
- yield Metric(
- name=metric_name,
- value=float(section[key]),
- boundaries=(0, None),
- )
- if not found:
- yield Result(
- state=State.UNKNOWN,
- summary=f"{item} energy values are not available",
- )
- return
- yield Result(
- state=State.OK,
- summary=f"{item} energy data available",
- )
- check_plugin_p1_energy = CheckPlugin(
- name="p1_energy",
- sections=["p1"],
- service_name="P1 Energy %s",
- discovery_function=discover_p1_energy,
- check_function=check_p1_energy,
- )
- # Gas
- def discover_p1_gas(section):
- if "total_gas_m3" in section:
- yield Service()
- def check_p1_gas(section):
- value = float(section["total_gas_m3"])
- yield Result(
- state=State.OK,
- summary=f"{value:.2f} m³",
- )
- yield Metric(
- name="p1_gas_m3",
- value=value,
- boundaries=(0, None),
- )
- check_plugin_p1_gas = CheckPlugin(
- name="p1_gas",
- sections=["p1"],
- service_name="P1 Gas",
- discovery_function=discover_p1_gas,
- check_function=check_p1_gas,
- )
- # Power quality
- POWER_QUALITY_KEYS = {
- "Voltage sag L1": "voltage_sag_l1_count",
- "Voltage sag L2": "voltage_sag_l2_count",
- "Voltage sag L3": "voltage_sag_l3_count",
- "Voltage swell L1": "voltage_swell_l1_count",
- "Voltage swell L2": "voltage_swell_l2_count",
- "Voltage swell L3": "voltage_swell_l3_count",
- "Any power failure": "any_power_fail_count",
- "Long power failure": "long_power_fail_count",
- }
- def discover_p1_power_quality(section):
- if any(key in section for key in POWER_QUALITY_KEYS.values()):
- yield Service()
- def check_p1_power_quality(section):
- found = 0
- for metric_name, key in POWER_QUALITY_KEYS.items():
- if key not in section:
- continue
- found += 1
- metric_id = (
- metric_name.lower()
- .replace(" ", "_")
- )
- yield Metric(
- name=f"p1_{metric_id}",
- value=float(section[key]),
- boundaries=(0, None),
- )
- if found:
- yield Result(
- state=State.OK,
- summary=f"{found} power-quality counters available",
- )
- else:
- yield Result(
- state=State.UNKNOWN,
- summary="No power-quality counters available",
- )
- check_plugin_p1_power_quality = CheckPlugin(
- name="p1_power_quality",
- sections=["p1"],
- service_name="P1 Power Quality",
- discovery_function=discover_p1_power_quality,
- check_function=check_p1_power_quality,
- )
|