edouard@4081: # mqtt/client.py edouard@4081: edouard@4081: from __future__ import absolute_import edouard@4081: edouard@4081: import os edouard@4081: edouard@4081: from POULibrary import POULibrary edouard@4081: import util.paths as paths edouard@4081: edouard@4081: mqtt_python_lib_code = """ edouard@4081: def MQTT_publish(clientname, topic, payload, QoS = 1, Retained = False): edouard@4081: c_function_name = "__mqtt_python_publish_" + clientname edouard@4081: c_function = getattr(PLCBinary, c_function_name) edouard@4081: c_function.restype = ctypes.c_int # error or 0 edouard@4081: c_function.argtypes = [ edouard@4081: ctypes.c_char_p, # topic edouard@4081: ctypes.c_char_p, # data edouard@4081: ctypes.c_uint32, # datalen edouard@4081: ctypes.c_uint8, # QoS edouard@4081: ctypes.c_uint8, # Retained edouard@4081: ] edouard@4081: res = c_function(topic, payload, len(payload), QoS, Retained) edouard@4081: return res edouard@4081: edouard@4081: # C per client CallBack type for __mqtt_python_subscribe_{name} edouard@4081: c_cb_type = ctypes.CFUNCTYPE(ctypes.c_int, # return edouard@4081: ctypes.c_char_p, # topic edouard@4081: ctypes.POINTER(ctypes.c_char), # data edouard@4081: ctypes.c_uint32) # data length edouard@4081: edouard@4081: # CallBacks management edouard@4081: # - each call to MQTT_subscribe registers a callback edouard@4081: MQTT_subscribers_cbs = {} edouard@4081: edouard@4081: # - one callback registered to C side per client edouard@4081: MQTT_client_cbs = {} edouard@4081: edouard@4081: def per_client_cb_factory(client): edouard@4081: def per_client_cb(topic, dataptr, datalen): edouard@4081: payload = ctypes.string_at(dataptr, datalen) edouard@4081: subscriber = MQTT_subscribers_cbs[client].get(topic, None) edouard@4081: if subscriber: edouard@4081: subscriber(topic, payload) edouard@4081: return 0 edouard@4081: return 1 edouard@4081: return per_client_cb edouard@4081: edouard@4081: def MQTT_subscribe(clientname, topic, cb, QoS = 1): edouard@4081: global MQTT_client_cbs, MQTT_subscribers_cbs edouard@4081: c_function_name = "__mqtt_python_subscribe_" + clientname edouard@4081: c_function = getattr(PLCBinary, c_function_name) edouard@4081: c_function.restype = ctypes.c_int # error or 0 edouard@4081: c_function.argtypes = [ edouard@4081: ctypes.c_char_p, # topic edouard@4081: ctypes.c_uint8] # QoS edouard@4081: edouard@4081: MQTT_subscribers_cbs.setdefault(clientname, {})[topic] = cb edouard@4081: edouard@4081: c_cb = MQTT_client_cbs.get(clientname, None) edouard@4081: if c_cb is None: edouard@4081: c_cb = c_cb_type(per_client_cb_factory(clientname)) edouard@4081: MQTT_client_cbs[clientname] = c_cb edouard@4081: register_c_function = getattr(PLCBinary, "__mqtt_python_callback_setter_"+clientname ) edouard@4081: register_c_function.argtypes = [c_cb_type] edouard@4081: register_c_function(c_cb) edouard@4081: edouard@4081: res = c_function(topic, QoS) edouard@4081: return res edouard@4081: edouard@4081: """ edouard@4081: edouard@4081: class MQTTLibrary(POULibrary): edouard@4081: edouard@4081: def GetLibraryPath(self): edouard@4081: return paths.AbsNeighbourFile(__file__, "pous.xml") edouard@4081: edouard@4081: def Generate_C(self, buildpath, varlist, IECCFLAGS): edouard@4081: edouard@4081: runtimefile_path = os.path.join(buildpath, "runtime_00_mqtt.py") edouard@4081: runtimefile = open(runtimefile_path, 'w') edouard@4081: runtimefile.write(mqtt_python_lib_code) edouard@4081: runtimefile.close() edouard@4081: return ((["mqtt"], [], False), "", edouard@4081: ("runtime_00_mqtt.py", open(runtimefile_path, "rb")))