diff --git a/Cpp-Implementation/Infrastructure/DataType.h b/Cpp-Implementation/Infrastructure/DataType.h new file mode 100644 index 0000000..02d237d --- /dev/null +++ b/Cpp-Implementation/Infrastructure/DataType.h @@ -0,0 +1,18 @@ +#ifndef DATATYPE_H +#define DATATYPE_H + +#include + +enum DataType : uint8_t +{ + Float32 = 0, + Int32 = 1, + Int16 = 2, + Int8 = 3, + Uint32 = 4, + Uint16 = 5, + Uint8 = 6, + Boolean = 7, +} + +#endif \ No newline at end of file diff --git a/Cpp-Implementation/Infrastructure/MessageType.h b/Cpp-Implementation/Infrastructure/MessageType.h new file mode 100644 index 0000000..5a8c2d8 --- /dev/null +++ b/Cpp-Implementation/Infrastructure/MessageType.h @@ -0,0 +1,29 @@ +#ifndef MESSAGETYPE_H +#define MESSAGETYPE_H + +#include + +enum MessageType : uint8_t +{ + NodeInfoReq = 0, + NodeInfoAnnouncement = 1, + InfoStatus = 10, + WarningStatus = 11, + ErrorStatus = 12, + TelemetryValueRegistration = 20, + ParameterRegistration = 21, + TelemetryGroupDefinition = 30, + TelemetryGroupUpdate = 31, + HeartbeatReq = 40, + HeartbeatRes = 41, + ParameterSetReq = 50, + ParameterSetConfirmation = 51, + ParameterSetLock = 52, + ParameterSetLockConfirmation = 53, + FieldGetReq = 60, + FieldGetRes = 61, + FieldIdLookupReq = 62, + FieldIdLookupRes = 63, +} + +#endif \ No newline at end of file diff --git a/Cpp-Implementation/Infrastructure/ParameterSetStatus.h b/Cpp-Implementation/Infrastructure/ParameterSetStatus.h new file mode 100644 index 0000000..0e2eb71 --- /dev/null +++ b/Cpp-Implementation/Infrastructure/ParameterSetStatus.h @@ -0,0 +1,14 @@ +#ifndef PARAMETERSETSTATUS_H +#define PARAMETERSETSTATUS_H + +#include + +enum ParameterSetStatus : uint8_t +{ + Success = 0, + InvalidParameterId = 1, + ParameterLocked = 2, + NodeToNodeModification = 3, +} + +#endif \ No newline at end of file diff --git a/Cpp-Implementation/LiquidCan.h b/Cpp-Implementation/LiquidCan.h index e69de29..75cf4bf 100644 --- a/Cpp-Implementation/LiquidCan.h +++ b/Cpp-Implementation/LiquidCan.h @@ -0,0 +1,5 @@ + +#ifndef LIQUIDCAN_H +#define LIQUIDCAN_H + +#endif //LIQUIDCAN_H \ No newline at end of file diff --git a/Cpp-Implementation/Model/FieldGetReq.h b/Cpp-Implementation/Model/FieldGetReq.h new file mode 100644 index 0000000..23d1552 --- /dev/null +++ b/Cpp-Implementation/Model/FieldGetReq.h @@ -0,0 +1,11 @@ +#ifndef FIELDGETREQ_H +#define FIELDGETREQ_H + +#include + +struct FieldGetReq +{ + uint8_t fieldId; +} + +#endif \ No newline at end of file diff --git a/Cpp-Implementation/Model/FieldGetRes.h b/Cpp-Implementation/Model/FieldGetRes.h new file mode 100644 index 0000000..437dd90 --- /dev/null +++ b/Cpp-Implementation/Model/FieldGetRes.h @@ -0,0 +1,12 @@ +#ifndef FIELDGETRES_H +#define FIELDGETRES_H + +#include + +struct FieldGetRes +{ + uint8_t fieldId; + uint8_t value[62]; +} + +#endif \ No newline at end of file diff --git a/Cpp-Implementation/Model/FieldIdLookupReq.h b/Cpp-Implementation/Model/FieldIdLookupReq.h new file mode 100644 index 0000000..53a5a30 --- /dev/null +++ b/Cpp-Implementation/Model/FieldIdLookupReq.h @@ -0,0 +1,11 @@ +#ifndef FIELDIDLOOKUPREQ_H +#define FIELDIDLOOKUPREQ_H + +#include + +struct FieldIdLookupReq +{ + uint8_t fieldName[61]; +} + +#endif \ No newline at end of file diff --git a/Cpp-Implementation/Model/FieldIdLookupRes.h b/Cpp-Implementation/Model/FieldIdLookupRes.h new file mode 100644 index 0000000..2bb555b --- /dev/null +++ b/Cpp-Implementation/Model/FieldIdLookupRes.h @@ -0,0 +1,12 @@ +#ifndef FIELDIDLOOKUPRES_H +#define FIELDIDLOOKUPRES_H + +#include + +struct FieldIdLookupRes +{ + uint8_t fieldId; + DataType fieldType; +} + +#endif \ No newline at end of file diff --git a/Cpp-Implementation/Model/FieldRegistration.h b/Cpp-Implementation/Model/FieldRegistration.h new file mode 100644 index 0000000..b3e4c0f --- /dev/null +++ b/Cpp-Implementation/Model/FieldRegistration.h @@ -0,0 +1,13 @@ +#ifndef FIELDREGISTRATION_H +#define FIELDREGISTRATION_H + +#include + +struct FieldRegistration +{ + uint8_t fieldId; + uint8_t fieldType; + int8_t fieldName[61]; +} + +#endif \ No newline at end of file diff --git a/Cpp-Implementation/Model/HeartBeat.h b/Cpp-Implementation/Model/HeartBeat.h new file mode 100644 index 0000000..337ba6d --- /dev/null +++ b/Cpp-Implementation/Model/HeartBeat.h @@ -0,0 +1,11 @@ +#ifndef HEARTBEAT_H +#define HEARTBEAT_H + +#include + +struct HeartBeat +{ + uint32_t counter; +} + +#endif \ No newline at end of file diff --git a/Cpp-Implementation/Model/NodeInfoRes.h b/Cpp-Implementation/Model/NodeInfoRes.h new file mode 100644 index 0000000..c37c75d --- /dev/null +++ b/Cpp-Implementation/Model/NodeInfoRes.h @@ -0,0 +1,15 @@ +#ifndef NODEINFORES_H +#define NODEINFORES_H + +#include + +struct NodeInfoRes +{ + uint8_t telCnt; + uint8_t parCnt; + uint32_t firmwareHash; + uint32_t liquidHash; + int8_t deviceName[53]; +} + +#endif \ No newline at end of file diff --git a/Cpp-Implementation/Model/ParameterSetConfirmation.h b/Cpp-Implementation/Model/ParameterSetConfirmation.h new file mode 100644 index 0000000..e94aa52 --- /dev/null +++ b/Cpp-Implementation/Model/ParameterSetConfirmation.h @@ -0,0 +1,13 @@ +#ifndef PARAMETERSETCONFIRMATION_H +#define PARAMETERSETCONFIRMATION_H + +#include + +struct ParameterSetConfirmation +{ + uint8_t parameterId; + ParameterSetStatus status; + uint8_t value[61]; +} + +#endif \ No newline at end of file diff --git a/Cpp-Implementation/Model/ParameterSetLock.h b/Cpp-Implementation/Model/ParameterSetLock.h new file mode 100644 index 0000000..01738f3 --- /dev/null +++ b/Cpp-Implementation/Model/ParameterSetLock.h @@ -0,0 +1,12 @@ +#ifndef PARAMETERSETLOCK_H +#define PARAMETERSETLOCK_H + +#include + +struct ParameterSetLock +{ + uint8_t parameterId; + uint8_t lockStatus; +} + +#endif \ No newline at end of file diff --git a/Cpp-Implementation/Model/ParameterSetReq.h b/Cpp-Implementation/Model/ParameterSetReq.h new file mode 100644 index 0000000..a78f19e --- /dev/null +++ b/Cpp-Implementation/Model/ParameterSetReq.h @@ -0,0 +1,12 @@ +#ifndef PARAMETERSETREQ_H +#define PARAMETERSETREQ_H + +#include + +struct ParameterSetReq +{ + uint8_t parameterId; + uint8_t value[61]; +} + +#endif \ No newline at end of file diff --git a/Cpp-Implementation/Model/Status.h b/Cpp-Implementation/Model/Status.h new file mode 100644 index 0000000..3f06360 --- /dev/null +++ b/Cpp-Implementation/Model/Status.h @@ -0,0 +1,11 @@ +#ifndef STATUS_H +#define STATUS_H + +#include + +struct Status +{ + int8_t msg[63]; +} + +#endif \ No newline at end of file diff --git a/Cpp-Implementation/Model/TelemetryGroupDefinition.h b/Cpp-Implementation/Model/TelemetryGroupDefinition.h new file mode 100644 index 0000000..229589d --- /dev/null +++ b/Cpp-Implementation/Model/TelemetryGroupDefinition.h @@ -0,0 +1,12 @@ +#ifndef TELEMETRYGROUPDEFINITION_H +#define TELEMETRYGROUPDEFINITION_H + +#include + +struct TelemetryGroupDefinition +{ + uint8_t groupId; + uint8_t fieldIds[62]; +} + +#endif \ No newline at end of file diff --git a/Cpp-Implementation/Model/TelemetryGroupUpdate.h b/Cpp-Implementation/Model/TelemetryGroupUpdate.h new file mode 100644 index 0000000..b469256 --- /dev/null +++ b/Cpp-Implementation/Model/TelemetryGroupUpdate.h @@ -0,0 +1,12 @@ +#ifndef TELEMETRYGROUPUPDATE_H +#define TELEMETRYGROUPUPDATE_H + +#include + +struct TelemetryGroupUpdate +{ + uint8_t groupId; + uint8_t values[62]; +} + +#endif \ No newline at end of file diff --git a/LiquidCAN.yaml b/LiquidCAN.yaml new file mode 100644 index 0000000..8a9d3c9 --- /dev/null +++ b/LiquidCAN.yaml @@ -0,0 +1,163 @@ +enum: + - name: "parameter_set_status" + type: "uint8_t" + values: + - name: "success" + value: 0 + - name: "invalid_parameter_id" + value: 1 + - name: "parameter_locked" + value: 2 + - name: "node_to_node_modification" + value: 3 + - name: "data_type" + type: "uint8_t" + values: + - name: "float32" + value: 0 + - name: "int32" + value: 1 + - name: "int16" + value: 2 + - name: "int8" + value: 3 + - name: "uint32" + value: 4 + - name: "uint16" + value: 5 + - name: "uint8" + value: 6 + - name: "boolean" + value: 7 + - name: "message_type" + type: "uint8_t" + values: + - name: "node_info_req" + value: 0 + - name: "node_info_announcement" + value: 1 + - name: "info_status" + value: 10 + - name: "warning_status" + value: 11 + - name: "error_status" + value: 12 + - name: "telemetry_value_registration" + value: 20 + - name: "parameter_registration" + value: 21 + - name: "telemetry_group_definition" + value: 30 + - name: "telemetry_group_update" + value: 31 + - name: "heartbeat_req" + value: 40 + - name: "heartbeat_res" + value: 41 + - name: "parameter_set_req" + value: 50 + - name: "parameter_set_confirmation" + value: 51 + - name: "parameter_set_lock" + value: 52 + - name: "parameter_set_lock_confirmation" + value: 53 + - name: "field_get_req" + value: 60 + - name: "field_get_res" + value: 61 + - name: "field_id_lookup_req" + value: 62 + - name: "field_id_lookup_res" + value: 63 + +struct: + - name: "node_info_res" + fields: + - name: "tel_cnt" + type: "uint8_t" + - name: "par_cnt" + type: "uint8_t" + - name: "firmware_hash" + type: "uint32_t" + - name: "liquid_hash" + type: "uint32_t" + - name: "device_name" + type: "int8_t" + length: 53 + - name: "status" + fields: + - name: "msg" + type: "int8_t" + length: 63 + - name: "field_registration" + fields: + - name: "field_id" + type: "uint8_t" + - name: "field_type" + type: "uint8_t" + - name: "field_name" + type: "int8_t" + length: 61 + - name: "telemetry_group_definition" + fields: + - name: "group_id" + type: "uint8_t" + - name: "field_ids" + type: "uint8_t" + length: 62 + - name: "telemetry_group_update" + fields: + - name: "group_id" + type: "uint8_t" + - name: "values" + type: "uint8_t" + length: 62 + - name: "heart_beat" + fields: + - name: "counter" + type: "uint32_t" + - name: "parameter_set_req" + fields: + - name: "parameter_id" + type: "uint8_t" + - name: "value" + type: "uint8_t" + length: 61 + - name: "parameter_set_confirmation" + fields: + - name: "parameter_id" + type: "uint8_t" + - name: "status" + type: "parameter_set_status" + - name: "value" + type: "uint8_t" + length: 61 + - name: "field_get_req" + fields: + - name: "field_id" + type: "uint8_t" + - name: "field_get_res" + fields: + - name: "field_id" + type: "uint8_t" + - name: "value" + type: "uint8_t" + length: 62 + - name: "field_id_lookup_req" + fields: + - name: "field_name" + type: "uint8_t" + length: 61 + - name: "field_id_lookup_res" + fields: + - name: "field_id" + type: "uint8_t" + - name: "field_type" + type: "data_type" + - name: "parameter_set_lock" + fields: + - name: "parameter_id" + type: "uint8_t" + - name: "lock_status" + type: "uint8_t" \ No newline at end of file diff --git a/LiquidCAN_generator.py b/LiquidCAN_generator.py new file mode 100644 index 0000000..ae4c6b1 --- /dev/null +++ b/LiquidCAN_generator.py @@ -0,0 +1,146 @@ +import yaml +import os + +cpp_path = "./Cpp-Implementation" +enum_path = "/Infrastructure" +model_path = "/Model" + + +def convert_to_camel_case(value, upper=True): + components = value.split("_") + + if not components: + return "" + + if upper: + return "".join(x.title() for x in components) + + res = components[0].lower() + for part in components[1:]: + if part: + res += part.title() + return res + + +def change_case(value, value_type): + if value_type == "type": + return convert_to_camel_case(value) + elif value_type == "struct_member": + return convert_to_camel_case(value, False) + elif value_type == "enum_member": + return convert_to_camel_case(value) + return value + + +def add_cpp_preprocessor_directives(code_string, name): + new_code_string = f"#ifndef {name.upper()}_H\n" + new_code_string += f"#define {name.upper()}_H\n\n" + new_code_string += "#include \n\n" + new_code_string += code_string + "\n" + new_code_string += "#endif" + return new_code_string + + +def create_enum(name, fields, data_type=None): + name = change_case(name, "type") + code = f"enum {name}" + + if data_type is not None: + if not data_type.endswith("_t"): + raise Exception(f"Invalid data type: {data_type}") + code += f" : {data_type}\n" + else: + code += "\n" + code += "{\n" + + has_value = False + for element in fields: + code += f"\t{change_case(element["name"], "enum_member")}" + + if "value" in element: + has_value = True + code += f" = {element["value"]}" + elif has_value: + raise Exception(f"not every value in {name} has a value!") + + code += ",\n" + code += "}\n" + return add_cpp_preprocessor_directives(code, name) + + +def create_struct(name, fields): + name = change_case(name, "type") + code = f"struct {name}\n" + code += "{\n" + required_types = [] + for element in fields: + code += "\t" + + type_name = element["type"] + if type_name.endswith("_t"): + code += type_name + else: + code += f"{change_case(type_name, "type")}" + required_types.append(type_name) + + code += f" {change_case(element["name"], "struct_member")}" + if "length" in element: + code += f"[{element["length"]}]" + code += ";\n" + code += "}\n" + return add_cpp_preprocessor_directives(code, name), required_types + + +def prepare_write(path): + if os.path.exists(path): + for dir_file in os.listdir(path): + os.remove(f"{path}/{dir_file}") + else: + os.makedirs(path) + + +with open("./LiquidCAN.yaml", 'r') as file: + data = yaml.safe_load(file) + +type_set = set() + +# enum +cpp_enum_code = [] +if "enum" in data.keys(): + for enum in data["enum"]: + name = enum["name"] + if "type" in enum.keys(): + cpp_enum = create_enum(name, enum["values"], enum["type"]) + else: + cpp_enum = data = create_enum(name, enum["values"]) + + type_set.add(name) + cpp_enum_code.append((name, cpp_enum)) + +# struct +cpp_struct_code = [] +if "struct" in data.keys(): + for struct in data["struct"]: + name = struct["name"] + cpp_code, requires = create_struct(name, struct["fields"]) + cpp_struct_code.append((name, cpp_code, requires)) + type_set.add(name) + +# Type validation +for name, cpp_struct, required_types in cpp_struct_code: + for required_type in required_types: + if required_type not in type_set: + raise Exception(f"{required_type} is not defined!\n\r This type is required for {name}") + +# Create cpp enums +prepare_write(f"{cpp_path}{enum_path}") +for name, code in cpp_enum_code: + with open(f"{cpp_path}{enum_path}/{convert_to_camel_case(name)}.h", "w") as file: + file.write(code) + +# Create cpp structs +prepare_write(f"{cpp_path}{model_path}") +for name, code, _ in cpp_struct_code: + with open(f"{cpp_path}{model_path}/{convert_to_camel_case(name)}.h", "w") as file: + file.write(code) +