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