MQTT WIP: intermediate state, added perfect hash to map topic to variables
authorEdouard Tisserant <edouard@beremiz.fr>
Wed, 03 Jul 2024 11:44:01 +0200
changeset 3981 74035ea6792c
parent 3980 96acfee19caf
child 3982 69d161fc2e08
MQTT WIP: intermediate state, added perfect hash to map topic to variables
mqtt/mqtt_client_gen.py
--- a/mqtt/mqtt_client_gen.py	Fri Jun 14 15:56:12 2024 +0200
+++ b/mqtt/mqtt_client_gen.py	Wed Jul 03 11:44:01 2024 +0200
@@ -8,6 +8,7 @@
 import wx
 import wx.dataview as dv
 
+from perfect_hash import generate_code, IntSaltHash
 
 MQTT_IEC_types = dict(
 # IEC61131|  C  type   | sz
@@ -286,6 +287,39 @@
                 for row in data:
                     writer.writerow([direction] + row)
 
+    def _TopicsPerfectHash(self, topics):
+        template = """
+#define NK  $NK       /* number of keys */
+#define NG  $NG       /* number of vertices */
+#define NS  $NS       /* length of array T1 and T2 */
+
+int S1[] = {$S1};
+int S2[] = {$S2};
+int G[] = {$G};
+char *K[] = {$K};
+"""
+		code = generate_code(topics, Hash=IntSaltHash, template=template)
+        code += """
+/* return index of key in K if key is found, -1 otherwise */
+int MQTT_Topic_index(const char *key)
+{
+    int i, f1 = 0, f2 = 0;
+
+    for (i = 0; key[i] != '\\0' && i < NS; i++) {
+        f1 += S1[i] * key[i];
+        f2 += S2[i] * key[i];
+        f1 %= NG;
+        f2 %= NG;
+    }
+    i = (G[f1] + G[f2]) % NG;
+    if (i < NK && strcmp(key, K[i]) == 0)
+        return i;
+
+    return -1;
+}
+""" 
+		return code
+
     def GenerateC(self, path, locstr, config):
         template = """/* code generated by beremiz MQTT extension */
 
@@ -338,13 +372,23 @@
 	LogWarning("Paho MQTT Trace : %d, %s\n", level, message);
 }
 
-#define DECL_VAR(ua_type, C_type, c_loc_name)                                                       \\
-static MQTT_Variant c_loc_name##_variant;                                                             \\
+#define DECL_VAR(iec_type, C_type, c_loc_name)                                                       \\
 static C_type c_loc_name##_buf = 0;                                                                 \\
 C_type *c_loc_name = &c_loc_name##_buf;
 
 {decl}
 
+#define INIT_TOPIC(topic, iec_type, c_loc_name)                                                  \\
+{topic, &c_loc_name##_buf, iec_type##_ENUM},
+
+ststic struct {
+	const char *topic; //null terminated topic string
+	void *pdata; //pointer to data
+	__IEC_types_enum vartype;
+} topics [] = {
+{topics}
+}
+
 void __cleanup_{locstr}(void)
 {{
     MQTT_Client_disconnect(client);
@@ -466,6 +510,7 @@
             uri      = config["URI"],
             clientID = config["clientID"],
             decl     = "",
+            topics   = "",
             cleanup  = "",
             init     = "",
             retrieve = "",
@@ -483,17 +528,19 @@
             formatdict["init"] += """
     INIT_NoAuth()"""
 
+		topics = OrderedDict()
         for direction, data in self.items():
             iec_direction_prefix = {"input": "__I", "output": "__Q"}[direction]
-#            for row in data:
-#                name, ua_nsidx, ua_nodeid_type, _ua_node_id, ua_type, iec_number = row
-#                iec_type, C_type, iec_size_prefix, ua_type_enum, ua_type = MQTT_IEC_types[ua_type]
-#                c_loc_name = iec_direction_prefix + iec_size_prefix + locstr + "_" + str(iec_number)
-#                ua_nodeid_type, id_formating = MQTT_NODE_ID_types[ua_nodeid_type]
-#                ua_node_id = id_formating.format(_ua_node_id)
-#
-#                formatdict["decl"] += """
-#DECL_VAR({ua_type}, {C_type}, {c_loc_name})""".format(**locals())
+            for row in data:
+				Topic, QoS, Retain, iec_type, iec_number = row
+                C_type, iec_size_prefix = MQTT_IEC_types[iec_type]
+                c_loc_name = iec_direction_prefix + iec_size_prefix + locstr + "_" + str(iec_number)
+
+                formatdict["decl"] += """
+DECL_VAR({iec_type}, {C_type}, {c_loc_name})""".format(**locals())
+
+                formatdict["topics"] += """
+INIT_TOPIC({Topic}, {iec_type}, {c_loc_name})""".format(**locals())
 #
 #                if direction == "input":
 #                    formatdict["init"] += """