Instructions how-to use Zabbix as your Controller with MQTT, part 2 (Auto-Discovery of Sensors)



  • Part 2. First have a look at part 1.

    Here's an additional script created in Python to implement Auto-Discovery and automatic creation of sensors and nodes in Zabbix. It's using the Zabbix-API to check and create hostgroup, hosts and items automatically, if they're new and presented to the Controller (after power-on of the node sensors). The script runs on my RPI, where my Mosquitto and Zabbix is installed too.

    Script description.
    The script connects to the mosquitto broker and listens to the MQTT traffic from the MySensors network.

    1. First it checks if the Zabbix-hostgroup exists, named "MySensors". If not it's created automatically.
    2. When a new sensor-node is presented via MQTT a Zabbix-host is created automatically, added to the hostgroup, and the host is named with the Topics prefix + Node-ID.
    3. When a new Child sensor is presented a Zabbix-Item is created, added to the host, and given the name of the Presentation Topic. The key of the Zabbix-Item is set to the value of Child-Id. The Item-name can later be modified to anything of your preference.

    Run the script in the background together with the script described in part 1. The first script passes the data to Zabbix. And this script handles the automatic creation of the sensors.

    Script:

    import paho.mqtt.client as mqtt
    import time
    from  pyzabbix import ZabbixMetric, ZabbixSender
    from zabbix.api import ZabbixAPI
    
    
    # Create ZabbixAPI class instance
    zapi = ZabbixAPI(url='http://localhost/zabbix/', user='Admin', password='zabbix')
    
    # Moquitto Topic Prefix
    topic_sub = "domoticz/in/MyMQTT/"
    
    # Name of Zabbix hostgroup
    hostGroup = 'MySensors'
    
    # Create hostgroup, if missing
    result = zapi.do_request('hostgroup.get', {'filter': {'name': [hostGroup]}})
    if [name['name'] for name in result['result']] == []:
         zapi.hostgroup.create(name=hostGroup)
         result = zapi.do_request('hostgroup.get', {'filter': {'name': [hostGroup]}})
         print(time.strftime("%c")+" Hostgroup created: "+hostGroup+" : "+str(result))      # log hostgroup creation
    
    # Get hostgroup-id
    groupId = [name['groupid'] for name in result['result']]
    
    
    # Mosquitto: the callback for when the client receives a CONNACK response from the server.
    def on_connect(client, userdata, flags, rc):
        print("Connected with result code "+str(rc))
    
        # Mosquitto: subscribing in on_connect() means that if we lose the connection and
        # reconnect then subscriptions will be renewed.
        client.subscribe(topic_sub+"+/+/+/+/+")
    
    # Mosquitto: the callback for when a PUBLISH message is received from the server.
    def on_message(client, userdata, msg):
        msg.topic = msg.topic.replace("/", ".")
    
        myNode  = msg.topic[:msg.topic.find(".", len(topic_sub)+1)]
        myItem  = msg.topic[len(myNode)+1:]
        mySplit = myItem.split('.')
    
    
        # Check if host (node) exist, or create new host.
        # 255 = child, 0 = presentation, 17 = S_ARDUINO_NODE
        if myItem == '255.0.0.17':
            result = zapi.do_request('host.get', {'filter':{'host':[myNode]}})
            if [host['host'] for host in result['result']] == []:                           # new node sensor, create host
                result = zapi.do_request('host.create', {'host': myNode, 'interfaces': [{'type': 1, 'main': 1, 'useip': 1, 'ip': '127.0.0
    .1', 'dns': '', 'port': '10050'}], 'groups': [{'groupid': groupId[0]}]})
                print(time.strftime("%c")+" Host created: "+myNode+" : "+str(result))       # log host creation
    
                # create item I_BATTERY_LEVEL
                result = zapi.do_request('host.get', {'filter':{'host':[myNode]}})
                hostId = [item['hostid'] for item in result['result']]
                result = zapi.do_request('item.create', {'hostid': hostId[0], 'value_type': '0','type': '2', 'name': 'I_BATTERY_LEVEL', '
    key_': '255.3.0.0'})
                print(time.strftime("%c")+" Item created: I_BATTERY_LEVEL : "+str(result))  # log item creation
    
        if mySplit[1] == '0':        # command = presentation
            if mySplit[0] != '255':  # child = 255, don't create item
                result = zapi.do_request('item.get', {'host': myNode, 'filter': {'key_':[mySplit[0]]}})
                if [host['key_'] for host in result['result']] == []:                       # new child, create item
                    result = zapi.do_request('host.get', {'filter':{'host':[myNode]}})
                    hostId = [item['hostid'] for item in result['result']]
                    result = zapi.do_request('item.create', {'hostid': hostId[0], 'value_type': '0','type': '2', 'name': myItem, 'key_':
    mySplit[0]})
                    print(time.strftime("%c")+" Item created: "+myItem+" : "+str(result))   # log item creation
    
    
    
    
    # Mosquitto: client start-up.
    client = mqtt.Client()
    client.on_connect = on_connect
    client.on_message = on_message
    
    client.connect("localhost", 1883, 60)
    
    
    # Mosquitto: blocking call that processes network traffic, dispatches callbacks and
    # handles reconnecting.
    client.loop_forever()
    
    

    Run the script e.g. in the background as a daemon and printouts sent to a log file "zabbix_cnfg.log

    python -u mqtt_zabbix_api.py > zabbix_cnfg.log 2>&1 &
    

    I'm quite new with Python scripting, so it's possible the code isn't that elegant. But it works fine for me. :simple_smile:
    And it's fun! 😄


Log in to reply
 

399
Online

6.7k
Users

7.6k
Topics

80.3k
Posts

Looks like your connection to MySensors Forum was lost, please wait while we try to reconnect.