mqtt/library.py
author Edouard Tisserant <edouard.tisserant@gmail.com>
Wed, 22 Jan 2025 22:05:08 +0100 (2 months ago)
changeset 4102 32e0ffdf2f44
parent 4081 86fbb3991af6
child 4099 97e93962be0c
permissions -rw-r--r--
SVGHMI: update generated xslt
4081
86fbb3991af6 MQTT: allow publish and subscribe from user python code.
Edouard Tisserant <edouard@beremiz.fr>
parents:
diff changeset
     1
# mqtt/client.py
86fbb3991af6 MQTT: allow publish and subscribe from user python code.
Edouard Tisserant <edouard@beremiz.fr>
parents:
diff changeset
     2
86fbb3991af6 MQTT: allow publish and subscribe from user python code.
Edouard Tisserant <edouard@beremiz.fr>
parents:
diff changeset
     3
from __future__ import absolute_import
86fbb3991af6 MQTT: allow publish and subscribe from user python code.
Edouard Tisserant <edouard@beremiz.fr>
parents:
diff changeset
     4
86fbb3991af6 MQTT: allow publish and subscribe from user python code.
Edouard Tisserant <edouard@beremiz.fr>
parents:
diff changeset
     5
import os
86fbb3991af6 MQTT: allow publish and subscribe from user python code.
Edouard Tisserant <edouard@beremiz.fr>
parents:
diff changeset
     6
86fbb3991af6 MQTT: allow publish and subscribe from user python code.
Edouard Tisserant <edouard@beremiz.fr>
parents:
diff changeset
     7
from POULibrary import POULibrary
86fbb3991af6 MQTT: allow publish and subscribe from user python code.
Edouard Tisserant <edouard@beremiz.fr>
parents:
diff changeset
     8
import util.paths as paths
86fbb3991af6 MQTT: allow publish and subscribe from user python code.
Edouard Tisserant <edouard@beremiz.fr>
parents:
diff changeset
     9
86fbb3991af6 MQTT: allow publish and subscribe from user python code.
Edouard Tisserant <edouard@beremiz.fr>
parents:
diff changeset
    10
mqtt_python_lib_code = """
86fbb3991af6 MQTT: allow publish and subscribe from user python code.
Edouard Tisserant <edouard@beremiz.fr>
parents:
diff changeset
    11
def MQTT_publish(clientname, topic, payload, QoS = 1, Retained = False):
86fbb3991af6 MQTT: allow publish and subscribe from user python code.
Edouard Tisserant <edouard@beremiz.fr>
parents:
diff changeset
    12
    c_function_name = "__mqtt_python_publish_" + clientname
86fbb3991af6 MQTT: allow publish and subscribe from user python code.
Edouard Tisserant <edouard@beremiz.fr>
parents:
diff changeset
    13
    c_function = getattr(PLCBinary, c_function_name)
86fbb3991af6 MQTT: allow publish and subscribe from user python code.
Edouard Tisserant <edouard@beremiz.fr>
parents:
diff changeset
    14
    c_function.restype = ctypes.c_int # error or 0
86fbb3991af6 MQTT: allow publish and subscribe from user python code.
Edouard Tisserant <edouard@beremiz.fr>
parents:
diff changeset
    15
    c_function.argtypes = [
86fbb3991af6 MQTT: allow publish and subscribe from user python code.
Edouard Tisserant <edouard@beremiz.fr>
parents:
diff changeset
    16
        ctypes.c_char_p,  # topic
86fbb3991af6 MQTT: allow publish and subscribe from user python code.
Edouard Tisserant <edouard@beremiz.fr>
parents:
diff changeset
    17
        ctypes.c_char_p,  # data
86fbb3991af6 MQTT: allow publish and subscribe from user python code.
Edouard Tisserant <edouard@beremiz.fr>
parents:
diff changeset
    18
        ctypes.c_uint32,  # datalen
86fbb3991af6 MQTT: allow publish and subscribe from user python code.
Edouard Tisserant <edouard@beremiz.fr>
parents:
diff changeset
    19
        ctypes.c_uint8,   # QoS
86fbb3991af6 MQTT: allow publish and subscribe from user python code.
Edouard Tisserant <edouard@beremiz.fr>
parents:
diff changeset
    20
        ctypes.c_uint8,   # Retained
86fbb3991af6 MQTT: allow publish and subscribe from user python code.
Edouard Tisserant <edouard@beremiz.fr>
parents:
diff changeset
    21
    ]
86fbb3991af6 MQTT: allow publish and subscribe from user python code.
Edouard Tisserant <edouard@beremiz.fr>
parents:
diff changeset
    22
    res = c_function(topic, payload, len(payload), QoS, Retained)
86fbb3991af6 MQTT: allow publish and subscribe from user python code.
Edouard Tisserant <edouard@beremiz.fr>
parents:
diff changeset
    23
    return res
86fbb3991af6 MQTT: allow publish and subscribe from user python code.
Edouard Tisserant <edouard@beremiz.fr>
parents:
diff changeset
    24
86fbb3991af6 MQTT: allow publish and subscribe from user python code.
Edouard Tisserant <edouard@beremiz.fr>
parents:
diff changeset
    25
# C per client CallBack type for __mqtt_python_subscribe_{name}
86fbb3991af6 MQTT: allow publish and subscribe from user python code.
Edouard Tisserant <edouard@beremiz.fr>
parents:
diff changeset
    26
c_cb_type = ctypes.CFUNCTYPE(ctypes.c_int,                   # return
86fbb3991af6 MQTT: allow publish and subscribe from user python code.
Edouard Tisserant <edouard@beremiz.fr>
parents:
diff changeset
    27
                             ctypes.c_char_p,                # topic
86fbb3991af6 MQTT: allow publish and subscribe from user python code.
Edouard Tisserant <edouard@beremiz.fr>
parents:
diff changeset
    28
                             ctypes.POINTER(ctypes.c_char),  # data
86fbb3991af6 MQTT: allow publish and subscribe from user python code.
Edouard Tisserant <edouard@beremiz.fr>
parents:
diff changeset
    29
                             ctypes.c_uint32)                # data length
86fbb3991af6 MQTT: allow publish and subscribe from user python code.
Edouard Tisserant <edouard@beremiz.fr>
parents:
diff changeset
    30
86fbb3991af6 MQTT: allow publish and subscribe from user python code.
Edouard Tisserant <edouard@beremiz.fr>
parents:
diff changeset
    31
# CallBacks management
86fbb3991af6 MQTT: allow publish and subscribe from user python code.
Edouard Tisserant <edouard@beremiz.fr>
parents:
diff changeset
    32
# - each call to MQTT_subscribe registers a callback
86fbb3991af6 MQTT: allow publish and subscribe from user python code.
Edouard Tisserant <edouard@beremiz.fr>
parents:
diff changeset
    33
MQTT_subscribers_cbs = {}
86fbb3991af6 MQTT: allow publish and subscribe from user python code.
Edouard Tisserant <edouard@beremiz.fr>
parents:
diff changeset
    34
86fbb3991af6 MQTT: allow publish and subscribe from user python code.
Edouard Tisserant <edouard@beremiz.fr>
parents:
diff changeset
    35
# - one callback registered to C side per client
86fbb3991af6 MQTT: allow publish and subscribe from user python code.
Edouard Tisserant <edouard@beremiz.fr>
parents:
diff changeset
    36
MQTT_client_cbs = {}
86fbb3991af6 MQTT: allow publish and subscribe from user python code.
Edouard Tisserant <edouard@beremiz.fr>
parents:
diff changeset
    37
86fbb3991af6 MQTT: allow publish and subscribe from user python code.
Edouard Tisserant <edouard@beremiz.fr>
parents:
diff changeset
    38
def per_client_cb_factory(client):
86fbb3991af6 MQTT: allow publish and subscribe from user python code.
Edouard Tisserant <edouard@beremiz.fr>
parents:
diff changeset
    39
    def per_client_cb(topic, dataptr, datalen):
86fbb3991af6 MQTT: allow publish and subscribe from user python code.
Edouard Tisserant <edouard@beremiz.fr>
parents:
diff changeset
    40
        payload = ctypes.string_at(dataptr, datalen)
86fbb3991af6 MQTT: allow publish and subscribe from user python code.
Edouard Tisserant <edouard@beremiz.fr>
parents:
diff changeset
    41
        subscriber = MQTT_subscribers_cbs[client].get(topic, None)
86fbb3991af6 MQTT: allow publish and subscribe from user python code.
Edouard Tisserant <edouard@beremiz.fr>
parents:
diff changeset
    42
        if subscriber:
86fbb3991af6 MQTT: allow publish and subscribe from user python code.
Edouard Tisserant <edouard@beremiz.fr>
parents:
diff changeset
    43
            subscriber(topic, payload)
86fbb3991af6 MQTT: allow publish and subscribe from user python code.
Edouard Tisserant <edouard@beremiz.fr>
parents:
diff changeset
    44
            return 0
86fbb3991af6 MQTT: allow publish and subscribe from user python code.
Edouard Tisserant <edouard@beremiz.fr>
parents:
diff changeset
    45
        return 1
86fbb3991af6 MQTT: allow publish and subscribe from user python code.
Edouard Tisserant <edouard@beremiz.fr>
parents:
diff changeset
    46
    return per_client_cb
86fbb3991af6 MQTT: allow publish and subscribe from user python code.
Edouard Tisserant <edouard@beremiz.fr>
parents:
diff changeset
    47
    
86fbb3991af6 MQTT: allow publish and subscribe from user python code.
Edouard Tisserant <edouard@beremiz.fr>
parents:
diff changeset
    48
def MQTT_subscribe(clientname, topic, cb, QoS = 1):
86fbb3991af6 MQTT: allow publish and subscribe from user python code.
Edouard Tisserant <edouard@beremiz.fr>
parents:
diff changeset
    49
    global MQTT_client_cbs, MQTT_subscribers_cbs
86fbb3991af6 MQTT: allow publish and subscribe from user python code.
Edouard Tisserant <edouard@beremiz.fr>
parents:
diff changeset
    50
    c_function_name = "__mqtt_python_subscribe_" + clientname
86fbb3991af6 MQTT: allow publish and subscribe from user python code.
Edouard Tisserant <edouard@beremiz.fr>
parents:
diff changeset
    51
    c_function = getattr(PLCBinary, c_function_name)
86fbb3991af6 MQTT: allow publish and subscribe from user python code.
Edouard Tisserant <edouard@beremiz.fr>
parents:
diff changeset
    52
    c_function.restype = ctypes.c_int # error or 0
86fbb3991af6 MQTT: allow publish and subscribe from user python code.
Edouard Tisserant <edouard@beremiz.fr>
parents:
diff changeset
    53
    c_function.argtypes = [
86fbb3991af6 MQTT: allow publish and subscribe from user python code.
Edouard Tisserant <edouard@beremiz.fr>
parents:
diff changeset
    54
        ctypes.c_char_p,  # topic
86fbb3991af6 MQTT: allow publish and subscribe from user python code.
Edouard Tisserant <edouard@beremiz.fr>
parents:
diff changeset
    55
        ctypes.c_uint8]   # QoS
86fbb3991af6 MQTT: allow publish and subscribe from user python code.
Edouard Tisserant <edouard@beremiz.fr>
parents:
diff changeset
    56
86fbb3991af6 MQTT: allow publish and subscribe from user python code.
Edouard Tisserant <edouard@beremiz.fr>
parents:
diff changeset
    57
    MQTT_subscribers_cbs.setdefault(clientname, {})[topic] = cb
86fbb3991af6 MQTT: allow publish and subscribe from user python code.
Edouard Tisserant <edouard@beremiz.fr>
parents:
diff changeset
    58
86fbb3991af6 MQTT: allow publish and subscribe from user python code.
Edouard Tisserant <edouard@beremiz.fr>
parents:
diff changeset
    59
    c_cb = MQTT_client_cbs.get(clientname, None)
86fbb3991af6 MQTT: allow publish and subscribe from user python code.
Edouard Tisserant <edouard@beremiz.fr>
parents:
diff changeset
    60
    if c_cb is None:
86fbb3991af6 MQTT: allow publish and subscribe from user python code.
Edouard Tisserant <edouard@beremiz.fr>
parents:
diff changeset
    61
        c_cb = c_cb_type(per_client_cb_factory(clientname))
86fbb3991af6 MQTT: allow publish and subscribe from user python code.
Edouard Tisserant <edouard@beremiz.fr>
parents:
diff changeset
    62
        MQTT_client_cbs[clientname] = c_cb
86fbb3991af6 MQTT: allow publish and subscribe from user python code.
Edouard Tisserant <edouard@beremiz.fr>
parents:
diff changeset
    63
        register_c_function = getattr(PLCBinary, "__mqtt_python_callback_setter_"+clientname )
86fbb3991af6 MQTT: allow publish and subscribe from user python code.
Edouard Tisserant <edouard@beremiz.fr>
parents:
diff changeset
    64
        register_c_function.argtypes = [c_cb_type]
86fbb3991af6 MQTT: allow publish and subscribe from user python code.
Edouard Tisserant <edouard@beremiz.fr>
parents:
diff changeset
    65
        register_c_function(c_cb)
86fbb3991af6 MQTT: allow publish and subscribe from user python code.
Edouard Tisserant <edouard@beremiz.fr>
parents:
diff changeset
    66
86fbb3991af6 MQTT: allow publish and subscribe from user python code.
Edouard Tisserant <edouard@beremiz.fr>
parents:
diff changeset
    67
    res = c_function(topic, QoS)
86fbb3991af6 MQTT: allow publish and subscribe from user python code.
Edouard Tisserant <edouard@beremiz.fr>
parents:
diff changeset
    68
    return res
86fbb3991af6 MQTT: allow publish and subscribe from user python code.
Edouard Tisserant <edouard@beremiz.fr>
parents:
diff changeset
    69
86fbb3991af6 MQTT: allow publish and subscribe from user python code.
Edouard Tisserant <edouard@beremiz.fr>
parents:
diff changeset
    70
"""
86fbb3991af6 MQTT: allow publish and subscribe from user python code.
Edouard Tisserant <edouard@beremiz.fr>
parents:
diff changeset
    71
86fbb3991af6 MQTT: allow publish and subscribe from user python code.
Edouard Tisserant <edouard@beremiz.fr>
parents:
diff changeset
    72
class MQTTLibrary(POULibrary):
86fbb3991af6 MQTT: allow publish and subscribe from user python code.
Edouard Tisserant <edouard@beremiz.fr>
parents:
diff changeset
    73
    
86fbb3991af6 MQTT: allow publish and subscribe from user python code.
Edouard Tisserant <edouard@beremiz.fr>
parents:
diff changeset
    74
    def GetLibraryPath(self):
86fbb3991af6 MQTT: allow publish and subscribe from user python code.
Edouard Tisserant <edouard@beremiz.fr>
parents:
diff changeset
    75
        return paths.AbsNeighbourFile(__file__, "pous.xml")
86fbb3991af6 MQTT: allow publish and subscribe from user python code.
Edouard Tisserant <edouard@beremiz.fr>
parents:
diff changeset
    76
86fbb3991af6 MQTT: allow publish and subscribe from user python code.
Edouard Tisserant <edouard@beremiz.fr>
parents:
diff changeset
    77
    def Generate_C(self, buildpath, varlist, IECCFLAGS):
86fbb3991af6 MQTT: allow publish and subscribe from user python code.
Edouard Tisserant <edouard@beremiz.fr>
parents:
diff changeset
    78
86fbb3991af6 MQTT: allow publish and subscribe from user python code.
Edouard Tisserant <edouard@beremiz.fr>
parents:
diff changeset
    79
        runtimefile_path = os.path.join(buildpath, "runtime_00_mqtt.py")
86fbb3991af6 MQTT: allow publish and subscribe from user python code.
Edouard Tisserant <edouard@beremiz.fr>
parents:
diff changeset
    80
        runtimefile = open(runtimefile_path, 'w')
86fbb3991af6 MQTT: allow publish and subscribe from user python code.
Edouard Tisserant <edouard@beremiz.fr>
parents:
diff changeset
    81
        runtimefile.write(mqtt_python_lib_code)
86fbb3991af6 MQTT: allow publish and subscribe from user python code.
Edouard Tisserant <edouard@beremiz.fr>
parents:
diff changeset
    82
        runtimefile.close()
86fbb3991af6 MQTT: allow publish and subscribe from user python code.
Edouard Tisserant <edouard@beremiz.fr>
parents:
diff changeset
    83
        return ((["mqtt"], [], False), "",
86fbb3991af6 MQTT: allow publish and subscribe from user python code.
Edouard Tisserant <edouard@beremiz.fr>
parents:
diff changeset
    84
                ("runtime_00_mqtt.py", open(runtimefile_path, "rb")))