MuninPlugin ‐ EN - gajdipajti/fan-control GitHub Wiki
Munin Plugin
The documentation, drawings, and circuit diagrams are available under the CC BY-SA-4.0 license.
Munin plugins have their own mental world. There are no language restrictions. A plugin can be written in bash, perl, python, c, or whatever runs on the operating system. munin-monitoring. It is worth looking around in the github page.
To write this plugin, I chose the python3 language and restricting it to python3.10 or above. I really like the switch/case' structure, or match/case' in python lingo.
But what is in the code:
- From the file name, we can read which tty device we will connect to. We will join.
- We write the reading of individual values in a function.
- In the case of a serial port, we like a byte streams, so I can send the carriage return character.
- The .readline()function waits until the newline character in the response or until the timeout expires.
- The answer is interpreted according to ASCII.
- We return the cleaned value.
 
- If the plugin was called with an argument, then we know that the configuration is requested by the Munin master.
- If the plugin was called without arguments, only the value should be returned.
#!/usr/bin/python
# A basic munin-node plugin to monitor the Fan Control Nano.
"""
USAGE
    rename the file to contain the tty device: fan-control-nano_ttyUSB0
    add dialout permissions
DESCRIPTION
    A Munin plugin to graph the temperatures and fan speeds of a rack. It requires
    the Fan Control Nano.
AUTHOR
    Tamás Gajdos [https://github.com/gajdipajti]
    Founded by the Free Software Foundation Hungary.
LICENSE
    This munin plugin script is GPLv3 licensed.
"""
import re
import serial
import sys
# Extract tty device from filename
ttyDevice = re.search('_tty(.*)', __file__)
# print(ttyDevice.group()[1:])
# Create the connection
ser = serial.Serial("/dev/" + ttyDevice.group()[1:], baudrate=115200, timeout=3.0)
# Implemented functions, to extract data
def getTemperature():
  ser.write(b't?\r')
  answer = ser.readline()
  temperature = bytes(answer).decode('ASCII')
  return temperature.strip()
def getTemperatureSource():
  ser.write(b'ts?\r')
  answer = ser.readline()
  tempSource = bytes(answer).decode('ASCII')
  match tempSource[0]:
    case 'N':
      return 'NTC'
    case 'L':
      return 'LM35'
    case 'D':
      return 'DS18B20'
    case 'A':
      return 'AD22100KTZ'
    case _:
      return 'Unknown'
def getRPM():
  ser.write(b'rpm?\r')
  answer = ser.readline()
  rpmValues = bytes(answer).decode('ASCII')
  return rpmValues.strip()
def getPWM():
  ser.write(b'pwmA?\r')
  answer = ser.readline()
  pwmValues = bytes(answer).decode('ASCII')
  return pwmValues.strip()
if len(sys.argv) == 2:
  # Something was passed
  match sys.argv[1]:
    case 'autoconf':
      print('yes')
    case 'config':
      # We configure the plugin here
      # print('multigraph fan_control_temp')
      print('graph_title Fan Control Nano Temperature: ' + getTemperatureSource())
      print('graph_vlabel Temperature in Celsius')
      print('graph_category Sensors')
      print('temp.label Measured Temperature')
      print('graph_args --base 1000  --lower-limit 0 --upper-limit 85')
else:
   print('temp.value ' + getTemperature())
ser.close()