mqtt/library.py
author Edouard Tisserant <edouard.tisserant@gmail.com>
Sun, 26 Jan 2025 14:58:13 +0100 (8 weeks ago)
changeset 4103 63c002e87c57
parent 4100 c6c80c088497
permissions -rw-r--r--
Merge remote-tracking branch 'hggit/python3' into python3
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
4099
97e93962be0c MQTT: fix non reconnecting python topics. WIP
Edouard Tisserant <edouard@beremiz.fr>
parents: 4081
diff changeset
    25
# C per client CallBack type for __mqtt_python_onmsg_{name}
97e93962be0c MQTT: fix non reconnecting python topics. WIP
Edouard Tisserant <edouard@beremiz.fr>
parents: 4081
diff changeset
    26
mqtt_c_cb_onmsg_type = ctypes.CFUNCTYPE(ctypes.c_int,                   # return
97e93962be0c MQTT: fix non reconnecting python topics. WIP
Edouard Tisserant <edouard@beremiz.fr>
parents: 4081
diff changeset
    27
                                        ctypes.c_char_p,                # topic
97e93962be0c MQTT: fix non reconnecting python topics. WIP
Edouard Tisserant <edouard@beremiz.fr>
parents: 4081
diff changeset
    28
                                        ctypes.POINTER(ctypes.c_char),  # data
97e93962be0c MQTT: fix non reconnecting python topics. WIP
Edouard Tisserant <edouard@beremiz.fr>
parents: 4081
diff changeset
    29
                                        ctypes.c_uint32)                # data length
97e93962be0c MQTT: fix non reconnecting python topics. WIP
Edouard Tisserant <edouard@beremiz.fr>
parents: 4081
diff changeset
    30
97e93962be0c MQTT: fix non reconnecting python topics. WIP
Edouard Tisserant <edouard@beremiz.fr>
parents: 4081
diff changeset
    31
# C per client CallBack type for __mqtt_python_resub_{name}
97e93962be0c MQTT: fix non reconnecting python topics. WIP
Edouard Tisserant <edouard@beremiz.fr>
parents: 4081
diff changeset
    32
mqtt_c_cb_resub_type = ctypes.CFUNCTYPE(ctypes.c_int)                  # return
4081
86fbb3991af6 MQTT: allow publish and subscribe from user python code.
Edouard Tisserant <edouard@beremiz.fr>
parents:
diff changeset
    33
86fbb3991af6 MQTT: allow publish and subscribe from user python code.
Edouard Tisserant <edouard@beremiz.fr>
parents:
diff changeset
    34
# CallBacks management
86fbb3991af6 MQTT: allow publish and subscribe from user python code.
Edouard Tisserant <edouard@beremiz.fr>
parents:
diff changeset
    35
# - 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
    36
MQTT_subscribers_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
# - 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
    39
MQTT_client_cbs = {}
86fbb3991af6 MQTT: allow publish and subscribe from user python code.
Edouard Tisserant <edouard@beremiz.fr>
parents:
diff changeset
    40
4100
c6c80c088497 MQTT: fix typo in resub python callback.
Edouard Tisserant <edouard@beremiz.fr>
parents: 4099
diff changeset
    41
def mqtt_per_client_cb_factory(clientname):
4099
97e93962be0c MQTT: fix non reconnecting python topics. WIP
Edouard Tisserant <edouard@beremiz.fr>
parents: 4081
diff changeset
    42
    def per_client_onmsg_cb(topic, dataptr, datalen):
4081
86fbb3991af6 MQTT: allow publish and subscribe from user python code.
Edouard Tisserant <edouard@beremiz.fr>
parents:
diff changeset
    43
        payload = ctypes.string_at(dataptr, datalen)
4100
c6c80c088497 MQTT: fix typo in resub python callback.
Edouard Tisserant <edouard@beremiz.fr>
parents: 4099
diff changeset
    44
        subscriber,_Qos = MQTT_subscribers_cbs[clientname].get(topic, None)
4081
86fbb3991af6 MQTT: allow publish and subscribe from user python code.
Edouard Tisserant <edouard@beremiz.fr>
parents:
diff changeset
    45
        if subscriber:
86fbb3991af6 MQTT: allow publish and subscribe from user python code.
Edouard Tisserant <edouard@beremiz.fr>
parents:
diff changeset
    46
            subscriber(topic, payload)
86fbb3991af6 MQTT: allow publish and subscribe from user python code.
Edouard Tisserant <edouard@beremiz.fr>
parents:
diff changeset
    47
            return 0
86fbb3991af6 MQTT: allow publish and subscribe from user python code.
Edouard Tisserant <edouard@beremiz.fr>
parents:
diff changeset
    48
        return 1
4099
97e93962be0c MQTT: fix non reconnecting python topics. WIP
Edouard Tisserant <edouard@beremiz.fr>
parents: 4081
diff changeset
    49
    def per_client_resub_cb():
4100
c6c80c088497 MQTT: fix typo in resub python callback.
Edouard Tisserant <edouard@beremiz.fr>
parents: 4099
diff changeset
    50
        for topic,(_cb,QoS) in MQTT_subscribers_cbs[clientname].items():
4099
97e93962be0c MQTT: fix non reconnecting python topics. WIP
Edouard Tisserant <edouard@beremiz.fr>
parents: 4081
diff changeset
    51
            _MQTT_subscribe(clientname, topic, QoS)
97e93962be0c MQTT: fix non reconnecting python topics. WIP
Edouard Tisserant <edouard@beremiz.fr>
parents: 4081
diff changeset
    52
        return 1
97e93962be0c MQTT: fix non reconnecting python topics. WIP
Edouard Tisserant <edouard@beremiz.fr>
parents: 4081
diff changeset
    53
    return per_client_onmsg_cb,per_client_resub_cb
4081
86fbb3991af6 MQTT: allow publish and subscribe from user python code.
Edouard Tisserant <edouard@beremiz.fr>
parents:
diff changeset
    54
    
4099
97e93962be0c MQTT: fix non reconnecting python topics. WIP
Edouard Tisserant <edouard@beremiz.fr>
parents: 4081
diff changeset
    55
def _MQTT_subscribe(clientname, topic, QoS):
4081
86fbb3991af6 MQTT: allow publish and subscribe from user python code.
Edouard Tisserant <edouard@beremiz.fr>
parents:
diff changeset
    56
    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
    57
    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
    58
    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
    59
    c_function.argtypes = [
86fbb3991af6 MQTT: allow publish and subscribe from user python code.
Edouard Tisserant <edouard@beremiz.fr>
parents:
diff changeset
    60
        ctypes.c_char_p,  # topic
86fbb3991af6 MQTT: allow publish and subscribe from user python code.
Edouard Tisserant <edouard@beremiz.fr>
parents:
diff changeset
    61
        ctypes.c_uint8]   # QoS
86fbb3991af6 MQTT: allow publish and subscribe from user python code.
Edouard Tisserant <edouard@beremiz.fr>
parents:
diff changeset
    62
4099
97e93962be0c MQTT: fix non reconnecting python topics. WIP
Edouard Tisserant <edouard@beremiz.fr>
parents: 4081
diff changeset
    63
    return c_function(topic, QoS)
4081
86fbb3991af6 MQTT: allow publish and subscribe from user python code.
Edouard Tisserant <edouard@beremiz.fr>
parents:
diff changeset
    64
4099
97e93962be0c MQTT: fix non reconnecting python topics. WIP
Edouard Tisserant <edouard@beremiz.fr>
parents: 4081
diff changeset
    65
def MQTT_subscribe(clientname, topic, cb, QoS = 1):
97e93962be0c MQTT: fix non reconnecting python topics. WIP
Edouard Tisserant <edouard@beremiz.fr>
parents: 4081
diff changeset
    66
    global MQTT_client_cbs, MQTT_subscribers_cbs
97e93962be0c MQTT: fix non reconnecting python topics. WIP
Edouard Tisserant <edouard@beremiz.fr>
parents: 4081
diff changeset
    67
97e93962be0c MQTT: fix non reconnecting python topics. WIP
Edouard Tisserant <edouard@beremiz.fr>
parents: 4081
diff changeset
    68
    MQTT_subscribers_cbs.setdefault(clientname, {})[topic] = (cb, QoS)
97e93962be0c MQTT: fix non reconnecting python topics. WIP
Edouard Tisserant <edouard@beremiz.fr>
parents: 4081
diff changeset
    69
    res = _MQTT_subscribe(clientname, topic, QoS)
97e93962be0c MQTT: fix non reconnecting python topics. WIP
Edouard Tisserant <edouard@beremiz.fr>
parents: 4081
diff changeset
    70
97e93962be0c MQTT: fix non reconnecting python topics. WIP
Edouard Tisserant <edouard@beremiz.fr>
parents: 4081
diff changeset
    71
    c_cbs = MQTT_client_cbs.get(clientname, None)
97e93962be0c MQTT: fix non reconnecting python topics. WIP
Edouard Tisserant <edouard@beremiz.fr>
parents: 4081
diff changeset
    72
    if c_cbs is None:
97e93962be0c MQTT: fix non reconnecting python topics. WIP
Edouard Tisserant <edouard@beremiz.fr>
parents: 4081
diff changeset
    73
        cb_onmsg, cb_resub = mqtt_per_client_cb_factory(clientname)
97e93962be0c MQTT: fix non reconnecting python topics. WIP
Edouard Tisserant <edouard@beremiz.fr>
parents: 4081
diff changeset
    74
        c_cbs = (mqtt_c_cb_onmsg_type(cb_onmsg),
97e93962be0c MQTT: fix non reconnecting python topics. WIP
Edouard Tisserant <edouard@beremiz.fr>
parents: 4081
diff changeset
    75
                 mqtt_c_cb_resub_type(cb_resub))
97e93962be0c MQTT: fix non reconnecting python topics. WIP
Edouard Tisserant <edouard@beremiz.fr>
parents: 4081
diff changeset
    76
        MQTT_client_cbs[clientname] = c_cbs
4081
86fbb3991af6 MQTT: allow publish and subscribe from user python code.
Edouard Tisserant <edouard@beremiz.fr>
parents:
diff changeset
    77
        register_c_function = getattr(PLCBinary, "__mqtt_python_callback_setter_"+clientname )
4099
97e93962be0c MQTT: fix non reconnecting python topics. WIP
Edouard Tisserant <edouard@beremiz.fr>
parents: 4081
diff changeset
    78
        register_c_function.argtypes = [mqtt_c_cb_onmsg_type, mqtt_c_cb_resub_type]
97e93962be0c MQTT: fix non reconnecting python topics. WIP
Edouard Tisserant <edouard@beremiz.fr>
parents: 4081
diff changeset
    79
        register_c_function(*c_cbs)
4081
86fbb3991af6 MQTT: allow publish and subscribe from user python code.
Edouard Tisserant <edouard@beremiz.fr>
parents:
diff changeset
    80
86fbb3991af6 MQTT: allow publish and subscribe from user python code.
Edouard Tisserant <edouard@beremiz.fr>
parents:
diff changeset
    81
    return res
86fbb3991af6 MQTT: allow publish and subscribe from user python code.
Edouard Tisserant <edouard@beremiz.fr>
parents:
diff changeset
    82
86fbb3991af6 MQTT: allow publish and subscribe from user python code.
Edouard Tisserant <edouard@beremiz.fr>
parents:
diff changeset
    83
"""
86fbb3991af6 MQTT: allow publish and subscribe from user python code.
Edouard Tisserant <edouard@beremiz.fr>
parents:
diff changeset
    84
86fbb3991af6 MQTT: allow publish and subscribe from user python code.
Edouard Tisserant <edouard@beremiz.fr>
parents:
diff changeset
    85
class MQTTLibrary(POULibrary):
86fbb3991af6 MQTT: allow publish and subscribe from user python code.
Edouard Tisserant <edouard@beremiz.fr>
parents:
diff changeset
    86
    
86fbb3991af6 MQTT: allow publish and subscribe from user python code.
Edouard Tisserant <edouard@beremiz.fr>
parents:
diff changeset
    87
    def GetLibraryPath(self):
86fbb3991af6 MQTT: allow publish and subscribe from user python code.
Edouard Tisserant <edouard@beremiz.fr>
parents:
diff changeset
    88
        return paths.AbsNeighbourFile(__file__, "pous.xml")
86fbb3991af6 MQTT: allow publish and subscribe from user python code.
Edouard Tisserant <edouard@beremiz.fr>
parents:
diff changeset
    89
86fbb3991af6 MQTT: allow publish and subscribe from user python code.
Edouard Tisserant <edouard@beremiz.fr>
parents:
diff changeset
    90
    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
    91
86fbb3991af6 MQTT: allow publish and subscribe from user python code.
Edouard Tisserant <edouard@beremiz.fr>
parents:
diff changeset
    92
        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
    93
        runtimefile = open(runtimefile_path, 'w')
86fbb3991af6 MQTT: allow publish and subscribe from user python code.
Edouard Tisserant <edouard@beremiz.fr>
parents:
diff changeset
    94
        runtimefile.write(mqtt_python_lib_code)
86fbb3991af6 MQTT: allow publish and subscribe from user python code.
Edouard Tisserant <edouard@beremiz.fr>
parents:
diff changeset
    95
        runtimefile.close()
86fbb3991af6 MQTT: allow publish and subscribe from user python code.
Edouard Tisserant <edouard@beremiz.fr>
parents:
diff changeset
    96
        return ((["mqtt"], [], False), "",
86fbb3991af6 MQTT: allow publish and subscribe from user python code.
Edouard Tisserant <edouard@beremiz.fr>
parents:
diff changeset
    97
                ("runtime_00_mqtt.py", open(runtimefile_path, "rb")))