# HG changeset patch # User Edouard Tisserant # Date 1719999841 -7200 # Node ID 74035ea6792ca2c6b2e713d63ef75c16df84d62a # Parent 96acfee19caf4d4fed2be675fbaa472cb50be3c7 MQTT WIP: intermediate state, added perfect hash to map topic to variables diff -r 96acfee19caf -r 74035ea6792c 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"] += """