初始化工程

This commit is contained in:
何 泽隆
2024-11-03 16:58:00 +08:00
commit 239fd2ca11
9 changed files with 1555 additions and 0 deletions

2
.gitignore vendored Normal file
View File

@@ -0,0 +1,2 @@
# 生成文件
**/__pycache__

35
.vscode/launch.json vendored Normal file
View File

@@ -0,0 +1,35 @@
{
// 使用 IntelliSense 了解相关属性。
// 悬停以查看现有属性的描述。
// 欲了解更多信息,请访问: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "CBB-Param 代码生成",
"type": "debugpy",
"request": "launch",
"program": "source/main.py",
"console": "integratedTerminal",
"args": [
"test/param_input.xlsx",
"-t=CBB_Param",
"-d=PV_INV30",
]
},
{
"name": "COMM-ARM 代码生成",
"type": "debugpy",
"request": "launch",
"program": "source/main.py",
"console": "integratedTerminal",
"args": [
// "${command:pickArgs}",
"test/光伏逆变器2.1_通信地址表_V01.xlsx",
"-t=COMM_ARM",
"-d=PV_INV30"
],
// "preLaunchTask": "deEncrpyt",
// "postDebugTask": "delFile",
}
]
}

54
.vscode/tasks.json vendored Normal file
View File

@@ -0,0 +1,54 @@
{
// See https://go.microsoft.com/fwlink/?LinkId=733558
// for the documentation about the tasks.json format
"version": "2.0.0",
"tasks": [
{
"label": "echo",
"type": "shell",
"command": "echo Hello"
},
{
"label": "deEncrpyt",
"type": "shell",
"command": "de_encrypt",
"args": [
"test/光伏逆变器2.1_通信地址表_V01.xlsx",
],
"problemMatcher": [],
"presentation":{
"echo": true,
"reveal": "always",
"focus": false,
"panel": "shared",
"showReuseMessage": true,
"clear": false
},
"group": {
"kind": "none"
}
},
{
"label": "delFile",
"type": "shell",
"command": "rm",
"args": [
"test/光伏逆变器2.1_通信地址表_V01_dec.dec",
],
"problemMatcher": [],
"presentation":{
"echo": true,
"reveal": "always",
"focus": false,
"panel": "shared",
"showReuseMessage": true,
"clear": false
},
"group": {
"kind": "none"
}
}
]
}

BIN
requirements.txt Normal file

Binary file not shown.

View File

@@ -0,0 +1,931 @@
#!/usr/bin/python3
# -*- coding: utf-8 -*-
import openpyxl
import os
import time
import re
import sys
import getopt
STORAGE_DICS = [
["PARAM_STORE_ADDR", "C1", "存储区域基地址", "D1",],
["PARAM_STORE_NAME", "C2", "存储区域命名", "D2",],
["PARAM_STORE_UNIT", "C3", "存储区域擦写单元", "D3",],
["PARAM_DATA_UNIT", "C4", "存储区域单分区大小", "D4",],
["PARAM_NUM", "C5", "参数个数", "D5",],
["PARAM_RAM", "C6", "是否需要RAM参数对象", "D6",],
["PARAM_STORAGE_TYPE","C7", "存储器类型", "D7",],
["PARAM_FILE_PATH", "C8", "参数文件路径", "D8",],
]
class ParamItem(object):
'''
从excel表格中读取到的参数信息体
index参数索引
DI参数唯一编码
str_name参数名称汉字
name参数标识符
store_type参数存储类型
size参数数据域大小
default_val参数默认值
local_type参数本地使用类型
ratio缩放倍率
min参数范围-最小值
max参数范围-最大值
flag参数标记
check_func参数修改前的有效性检查函数
updata_func参数更新后的回调函数
infomation当前参数注释
offset当前参数的内存对象偏移
offset_str当前参数的存储偏移
size_string参数的数据域大小宏定义
'''
def __init__(self, row):
'''
将excel中的一行数据转换为参数信息体
'''
self.index = row[0].value
self.DI = row[1].value
self.str_name = row[2].value
self.name = row[3].value
self.store_type = row[4].value
self.size = row[5].value
self.default_value = row[6].value
self.local_type = row[7].value
self.ratio = row[8].value
self.min = row[9].value
self.max = row[10].value
self.flag = row[11].value
self.check_func = row[12].value
self.updata_func = row[13].value
self.infomation = row[14].value
self.offset = ""
self.offset_str = ""
self.size_string = ""
def __str__(self):
return "%s,\t%s,\t%s,\t%s,\t%s,\t%s,\t%s,\t%s,\t%s,\t%s,\t%s,\t%s,\t%s,\t%s,\t%s"%(
self.index, self.DI, self.str_name, self.name, self.store_type, self.size, self.default_value,
self.local_type, self.ratio, self.min, self.max, self.flag, self.check_func, self.updata_func, self.infomation)
class StorageConfig(object):
'''
读取excel中的所有sheet将sheet中的数据转换为参数信息结构体
'''
def __init__(self):
self.workbook = openpyxl.load_workbook("tools/param_input.xlsx", data_only=True)
self.config_set = {}
self.param_index = ""
for sheet_name in self.workbook.sheetnames:
self.config_set[sheet_name] = {}
self.config_set[sheet_name]["name"] = sheet_name
sheet = self.workbook[sheet_name]
self.config_set[sheet_name]["param_storage_addr"] = {sheet["C1"].value:sheet["D1"].value}
self.config_set[sheet_name]["param_storage_name"] = {sheet["C2"].value:sheet["D2"].value}
self.config_set[sheet_name]["param_storage_unit"] = {sheet["C3"].value:sheet["D3"].value}
self.config_set[sheet_name]["param_data_unit"] = {sheet["C4"].value:sheet["D4"].value}
self.config_set[sheet_name]["param_num"] = {sheet["C5"].value:sheet["D5"].value}
self.config_set[sheet_name]["param_ram"] = {sheet["C6"].value:sheet["D6"].value}
self.config_set[sheet_name]["storage_type"] = {sheet["C7"].value:sheet["D7"].value}
self.config_set[sheet_name]["file_path_prefix"] = {sheet["C8"].value:sheet["D8"].value}
cell_table = sheet["A11":"O%d"%(11+self.config_set[sheet_name]['param_num']["参数个数"])]
self.config_set[sheet_name]["param_info_list"] = []
offset = 0
for row_cel in cell_table[1:]:
param = ParamItem(row_cel)
offset = offset + int(param.size) + 7 #PARAM_INFO_SIZE
param.offset = "%s_PARAM_%s_OFFSET"%(sheet_name.upper(), param.name.upper())
param.size_string = "%s_PARAM_%s_SIZE"%(sheet_name.upper(), param.name.upper())
self.config_set[sheet_name]["param_info_list"].append([param,offset])
def data_check(self):
for sheet in self.workbook:
for item in STORAGE_DICS:
if sheet[item[1]].value != item[2]:
print(item,sheet[item[1]].value, item[2], "bad file")
def __generate_definations(self):
'''生成defination.h'''
file_name_formate = "param_%s_defination.h"
file_title_formate = '''/*
* =====================================================================================
*
* Filename: param_%s_defination.h
*
* Description:
*
* Version: 1.0
* Created: %s
* Revision: none
* Compiler: gcc
*
* Author: Autogenerated
* Organization: Topscomm
*
* =====================================================================================
*/
#ifndef __PARAM_%s_DEFINATION_H__
#define __PARAM_%s_DEFINATION_H__
#include <stdint.h>
#include <stddef.h>
#define %s_PARAM_NUM (%s)
'''
file_end_formate = '''
#endif /* ----- #ifndef __PARAM_%s_DEFINATION_H__ ----- */
'''
for key, value in self.config_set.items():
file_name = file_name_formate % key.lower();
ret_str = ""
ret_str = ret_str + file_title_formate%(key.lower(), time.strftime("%d/%m/%Y %H:%M:%S"), key.upper(),key.upper(),key.upper(),value["param_num"]["参数个数"])
format_str = "#define {:<50} {}\n"
max_line_len = 0
for size_item in value["param_info_list"]:
curr_line = key.upper()+"_PARAM_"+size_item[0].name.upper()+"_SIZE"
if len(curr_line) > max_line_len :
max_line_len = len(curr_line)
if size_item[0].store_type == "PARAM_ARRAY":
ret_str = ret_str + format_str.format(curr_line, '('+str(size_item[0].size)+')')
if size_item[0].store_type == "PARAM_FLOAT":
ret_str = ret_str + format_str.format(curr_line, '(sizeof(float))')
if size_item[0].store_type == "PARAM_UINT8":
ret_str = ret_str + format_str.format(curr_line, '(sizeof(uint8_t))')
if size_item[0].store_type == "PARAM_INT8":
ret_str = ret_str + format_str.format(curr_line, '(sizeof(int8_t))')
if size_item[0].store_type == "PARAM_UINT16":
ret_str = ret_str + format_str.format(curr_line, '(sizeof(uint16_t))')
if size_item[0].store_type == "PARAM_INT16":
ret_str = ret_str + format_str.format(curr_line, '(sizeof(int16_t))')
if size_item[0].store_type == "PARAM_UINT32":
ret_str = ret_str + format_str.format(curr_line, '(sizeof(uint32_t))')
if size_item[0].store_type == "PARAM_INT32":
ret_str = ret_str + format_str.format(curr_line, '(sizeof(int32_t))')
if size_item[0].store_type == "PARAM_UINT64":
ret_str = ret_str + format_str.format(curr_line, '(sizeof(uint64_t))')
if size_item[0].store_type == "PARAM_INT64":
ret_str = ret_str + format_str.format(curr_line, '(sizeof(int64_t))')
if size_item[0].store_type == "PARAM_DOUBLE":
ret_str = ret_str + format_str.format(curr_line, '(sizeof(double))')
size_item[0].size_string = "%s_PARAM_%s_SIZE"%(key.upper(), size_item[0].name.upper())
ret_str = ret_str + "\n\n"
format_str = " {:<%s}/* {} */\n"%(2*max_line_len)
ret_str = ret_str + """typedef struct\n{\n"""
for size_item in value["param_info_list"]:
if size_item[0].store_type == "PARAM_ARRAY":
ret_str = ret_str + format_str.format ("uint8_t "+size_item[0].name+"["+size_item[0].size_string+"];", size_item[0].str_name)
if size_item[0].store_type == "PARAM_FLOAT":
ret_str = ret_str + format_str.format ("float "+size_item[0].name+";", size_item[0].str_name)
if size_item[0].store_type == "PARAM_UINT8":
ret_str = ret_str + format_str.format ("uint8_t "+size_item[0].name+";", size_item[0].str_name)
if size_item[0].store_type == "PARAM_INT8":
ret_str = ret_str + format_str.format ("int8_t "+size_item[0].name+";", size_item[0].str_name)
if size_item[0].store_type == "PARAM_UINT16":
ret_str = ret_str + format_str.format ("uint16_t "+size_item[0].name+";", size_item[0].str_name)
if size_item[0].store_type == "PARAM_INT16":
ret_str = ret_str + format_str.format ("int16_t "+size_item[0].name+";", size_item[0].str_name)
if size_item[0].store_type == "PARAM_UINT32":
ret_str = ret_str + format_str.format ("uint32_t "+size_item[0].name+";", size_item[0].str_name)
if size_item[0].store_type == "PARAM_INT32":
ret_str = ret_str + format_str.format ("int32_t "+size_item[0].name+";", size_item[0].str_name)
if size_item[0].store_type == "PARAM_UINT64":
ret_str = ret_str + format_str.format ("uint64_t "+size_item[0].name+";", size_item[0].str_name)
if size_item[0].store_type == "PARAM_INT64":
ret_str = ret_str + format_str.format ("int64_t "+size_item[0].name+";", size_item[0].str_name)
if size_item[0].store_type == "PARAM_DOUBLE":
ret_str = ret_str + format_str.format ("double "+size_item[0].name+";", size_item[0].str_name)
ret_str = ret_str + "} %s_param_t;\n\n"%key.lower()
ret_str = ret_str + file_end_formate%(key.upper())
with open("%s/"%self.file_path+file_name, 'w', encoding="utf-8") as f:
f.write(ret_str)
def __generate_internal_definations(self):
'''生成.h'''
file_name_formate = "param_%s.h"
file_title_formate = '''/*
* =====================================================================================
*
* Filename: param_%s.h
*
* Description:
*
* Version: 1.0
* Created: %s
* Revision: none
* Compiler: gcc
*
* Author: Autogenerated
* Organization: Topscomm
*
* =====================================================================================
*/
#ifndef __PARAM_%s_H__
#define __PARAM_%s_H__
#include <stdint.h>
#include "./param_config.h"
#include "../param_functional/param_block.h"
#include "./param_%s_defination.h"
#define %s_PARAM_STORE_ADDR (%s)
'''
file_end_formate = '''
#if ENABLE_PARAM_IN_RAM
#if ENABLE_PARAM_PRESET
typedef struct
{
%s_param_t preset_table;
} update_%s_param_t;
#endif
#endif
extern param_info_table_t %s_PARAM_INFO;
#endif /* ----- #ifndef __PARAM_%s_H__ ----- */
'''
for key, value in self.config_set.items():
file_name = file_name_formate%key.lower()
ret_str = ""
ret_str = ret_str + file_title_formate%(key.lower(), time.strftime("%d/%m/%Y %H:%M:%S"), key.upper(),key.upper(),key.lower(),key.upper(), value["param_storage_addr"]["存储区域基地址"])
format_str = "#define {:<%s} {}\n"
index = 0
last_str = ""
max_line_len = 0
for size_item in value["param_info_list"]:
if max_line_len <= len("%s_PARAM_%s_SIZE"%(key.upper(), size_item[0].name.upper())):
max_len_len = len("%s_PARAM_%s_SIZE"%(key.upper(), size_item[0].name.upper()))
format_str = format_str%(max_len_len + 5)
for size_item in value["param_info_list"]:
size_item[0].size_string = "%s_PARAM_%s_SIZE"%(key.upper(), size_item[0].name.upper())
if index == 0:
ret_str = ret_str + format_str.format(key.upper()+"_PARAM_"+size_item[0].name.upper()+"_OFFSET", '0')
else:
ret_str = ret_str + format_str.format(key.upper()+"_PARAM_"+size_item[0].name.upper()+"_OFFSET", last_str)
index = index + 1
last_str = ('({:<%s} + {:<%s} + PARAM_INFO_SIZE)' %(2*max_line_len, 3*max_line_len)).format(key.upper()+"_PARAM_"+size_item[0].name.upper()+"_OFFSET",
key.upper()+"_PARAM_"+size_item[0].name.upper()+"_SIZE")
ret_str = ret_str + "\n"
ret_str = ret_str + '''#define %s_PARAM_STORAGE_SIZE\t\t%s\n\n''' % (key.upper(), last_str)
ret_str = ret_str + file_end_formate%(key.lower(), key.lower(), key.upper(),key.upper())
with open("%s/"%self.file_path+file_name, 'w', encoding="utf-8") as f:
f.write(ret_str)
def __generate_infomatin(self):
'''生成.c'''
file_name_formate = "param_%s.c"
file_title_formate = '''/*
* =====================================================================================
*
* Filename: param_%s.c
*
* Description:
*
* Version: 1.0
* Created: %s
* Revision: none
* Compiler: gcc
*
* Author: Autogenerated
* Organization: Topscomm
*
* =====================================================================================
*/
#include <stddef.h>
#include "plm_type_def.h"
#include "../param_export.h"
#include "./param_%s.h"
#if ENABLE_PARAM_IN_RAM
#if ENABLE_PARAM_PRESET
update_%s_param_t g_update_%s_param_info; /*预存参数数据缓冲区 */
#endif
%s_param_t g_%s_param_in_ram; /*参数ram缓冲区*/
uint16_t g_check_%s_param_crc[%s_PARAM_NUM]; /*用于记录参数的校验crc结果*/
#endif
PARAM_CHANGE_FLAG_E g_%s_param_change_flag[%s_PARAM_NUM]; /*用于记录参数的修改标记*/
const %s_param_t %s_PARAM_DEFAULT_VALUE_TABLE =
{
'''
file_end_formate = '''
param_info_table_t %s_PARAM_INFO =
{
#if ENABLE_PARAM_MUTEX
.ptr_mutex = &g_param_resouce.param_mutex,
#endif
.ptr_category_name = %s_REGION_NAME,
.ptr_default_value_table = (void*)&%s_PARAM_DEFAULT_VALUE_TABLE, //默认参数值
.ptr_index_table = (void*)%s_PARAM_INDEX_TABLE, //参数索引表
.param_num = %s_PARAM_NUM, //参数个数
.param_data_size = %s_PARAM_STORAGE_SIZE, //数据长度
.param_base_addr = %s_PARAM_STORE_ADDR, //参数存储页地址
#if ENABLE_PARAM_IN_RAM
#if ENABLE_PARAM_PRESET
.ptr_preset_dataset = (void*)&g_update_%s_param_info.preset_table,//预设参数表
#endif
.ptr_param_in_ram = (void*)&g_%s_param_in_ram, //参数ram缓冲区
.ptr_crc_in_ram = g_check_%s_param_crc, //参数crc校验值
#endif
.ptr_change_flag = g_%s_param_change_flag, //参数变更标记
.backup_offset = %s, //备份之间的偏移
.idx_min = %s, //参数索引最小值
.idx_max = %s, //参数索引最大值
.ptr_exchange_unit = &g_param_resouce.ptr_param_unit_buff, //参数写入缓冲区
.exchange_size = %s, //按页写入的缓冲区的大小
};
'''
for key, value in self.config_set.items():
file_name = file_name_formate%key.lower()
ret_str = ""
ret_str = ret_str + file_title_formate%(key.lower(), time.strftime("%d/%m/%Y %H:%M:%S"), key.lower(), key.lower(), key.lower(), key.lower(), key.lower(), key.lower(), key.upper(), key.lower(), key.upper(), key.lower(), key.upper())
format_str = " .{:<20} = {:<40} //{}\n"
for size_item in value["param_info_list"]:
if size_item[0].store_type == "PARAM_ARRAY":
ret_str = ret_str + format_str.format(size_item[0].name, "{"+str(size_item[0].default_value)+"},", size_item[0].str_name)
else:
ret_str = ret_str + format_str.format(size_item[0].name, str(size_item[0].default_value)+",", size_item[0].str_name)
ret_str = ret_str + "};\n\n\n"
ret_str = ret_str + "const param_info_t %s_PARAM_INDEX_TABLE[%s_PARAM_NUM] =\n{\n"%(key.upper(),key.upper())
format_str = "{:<40} {:<30} {:<30} {:<30} {:<40} {:<50} {:<20} {:<20} {:<20} {:<30} {:<30} {:<40}\n"
for size_item in value["param_info_list"]:
ret_str = ret_str + format_str.format(" {.idx=PARA_IDX_%s"%size_item[0].name.upper()+",", ".identity="+str(size_item[0].DI)+",",
".store_type="+size_item[0].store_type+",", ".local_type="+str(size_item[0].local_type)+",",
".size="+size_item[0].size_string+",", ".offset="+"offsetof(%s_param_t, %s)"%(key.lower(),size_item[0].name)+",",
".ratio="+str(size_item[0].ratio)+",", ".min="+str(size_item[0].min)+",", ".max="+str(size_item[0].max)+",",
".check_func="+size_item[0].check_func+",", ".update_func="+size_item[0].updata_func+",},", "//"+size_item[0].str_name)
ret_str = ret_str + "};\n\n\n"
file_end = file_end_formate % (key.upper(), key.upper(),key.upper(),key.upper(),key.upper(),key.upper(),key.upper(),key.lower(),key.lower(),key.lower(),key.lower(),
value["param_data_unit"]["存储区域单分区大小"],
"PARA_IDX_%s"%value["param_info_list"][0][0].name.upper(),
"PARA_IDX_%s"%value["param_info_list"][value['param_num']["参数个数"]-1][0].name.upper(),
value["param_storage_unit"]["存储区域擦写单元"])
ret_str = ret_str + file_end
with open("%s/"%self.file_path+file_name, 'w', encoding="utf-8") as f:
f.write(ret_str)
def __generate_export(self):
'''生成interface.h的部分内容'''
file_title_formate = '''/*
* =====================================================================================
*
* Filename: param_defination.h
*
* Description:
*
* Version: 1.0
* Created: %s
* Revision: none
* Compiler: gcc
*
* Author: Autogenerated
* Organization: Topscomm
*
* =====================================================================================
*/
#ifndef __PARAM_DEFINATION_H__
#define __PARAM_DEFINATION_H__
#include <stdint.h>
/* ##### LOCAL INCLUDES #################################################### */
'''
file_title_formate = file_title_formate%(time.strftime("%d/%m/%Y %H:%M:%S"))
for t_item in self.config_set.items():
file_title_formate = file_title_formate + '#include {:<55} {}\n'.format('"param_defination/param_%s_defination.h"'%t_item[0].lower(), "/* %s参数个数及参数数据域大小 */" % t_item[0])
file_title_formate = file_title_formate + "\n/* ##### EXPORTED MACROS ######################################################## */\n"
ret_str = file_title_formate
for key, value in self.config_set.items():
ret_str = ret_str + "#define {:<25} {:<30} /* {}存储区域名 */\n".format(key.upper()+"_REGION_NAME", value['param_storage_name']['存储区域命名'], key.upper())
category_format = '''
/* ##### EXPORTED DATA TYPES #################################################### */
typedef enum
{
%s
PARAM_CATEGORY_MAX, /*参数表个数*/
}PARAM_CATEGORY_E; /* ---------- end of enum PARAM_CATEGORY_E ---------- */
'''
cat_str = ""
for key, value in self.config_set.items():
cat_str = cat_str + "{:<25} /*{}*/\n ".format(key.upper() + "_PARAM,",key)
ret_str = ret_str + category_format%cat_str
index_format = '''
typedef enum
{
%s
PARA_IDX_MAX, /*参数索引总个数*/
}PARAM_IDX_E; /* ---------- end of enum PARAM_IDX_E ---------- */
'''
index_str = ""
for key, value in self.config_set.items():
index_str = index_str + "\n /* %s */\n "%key
for size_item in value["param_info_list"]:
index_str = index_str + "{:<45} //{}\n ".format("PARA_IDX_"+size_item[0].name.upper()+",", size_item[0].str_name)
file_end = '''
#endif /* ----- #ifndef __PARAM_DEFINATION_H__ ----- */
'''
ret_str = ret_str + index_format%index_str + file_end
with open("%s/param_defination.h"%self.file_path, 'w', encoding="utf-8") as f:
f.write(ret_str)
def __generate_storage(self):
'''生成param_storage_config.c的部分内容'''
file_title_formate = '''/*
* =====================================================================================
*
* Filename: param_storage_config.c
*
* Description:
*
* Version: 1.0
* Created: %s
* Revision: none
* Compiler: gcc
*
* Author: Autogenerated
* Organization: Topscomm
*
* =====================================================================================
*/
#include "../param_storage/norflash_operation.h"
#include "../param_storage/eeprom_operation.h"
#include "../param_storage/file_system_operation.h"
#include "../param_storage/param_storage.h"
#if FILE_SYSTEM_EXIST
const char g_param_file_path_prefix[FILE_NAME_MAX_LEN]="%s"; /*存放参数文件的路径前缀*/
#define FILE_MAX_LEN (%s) /*文件最大长度*/
#endif
/* ##### VARIABLES - LOCAL TO THIS SOURCE FILE ################################ */
static const storage_info_t all_storage_info_table[PARAM_CATEGORY_MAX] =
{
'''
item_format=''' /* %s */
{
.ptr_name = %s_REGION_NAME,
.region = %s_PARAM,
#if FILE_SYSTEM_EXIST
.max_addr = 0+FILE_MAX_LEN - 1,
.min_addr = 0,
#else
.max_addr = %s,
.min_addr = %s,
#endif
.storage_read = %s_read,
.storage_write = %s_write,
.storage_clean = %s_clean,
},
'''
for t_item in self.config_set.items():
file_title_formate = file_title_formate%(time.strftime("%d/%m/%Y %H:%M:%S"),t_item[1]['file_path_prefix']['参数文件路径'],str(t_item[1]['param_data_unit']['存储区域单分区大小'])+ "*3")
break
for t_item in self.config_set.items():
file_title_formate = file_title_formate + item_format % (t_item[0].upper(),t_item[0].upper(), t_item[0].upper(),
str(t_item[1]['param_storage_addr']['存储区域基地址']) + "+" + str(t_item[1]['param_data_unit']['存储区域单分区大小'])+ "*3 - 1",
t_item[1]['param_storage_addr']['存储区域基地址'],
t_item[1]['storage_type']['存储器类型'],
t_item[1]['storage_type']['存储器类型'],
t_item[1]['storage_type']['存储器类型'])
file_end = '''
};
/* ##### FUNCTION DEFINITIONS - EXPORTED FUNCTIONS ############################ */
/*
* === FUNCTION ======================================================================
* Name: param_storage_get_info_table
* Description: 获取所有存储区域的汇总表,用于对存储区域进行检索
* =====================================================================================
*/
const storage_info_t* param_storage_get_info_table()
{
return &all_storage_info_table[0];
} /* ----- end of function param_storage_get_info_table ----- */
'''
ret_str = ""
ret_str = file_title_formate + file_end
with open("%s/param_storage_config.c"%self.file_path, 'w', encoding="utf-8") as f:
f.write(ret_str)
def generate_code_files(self, path):
'''
实际执行excel转代码生成.c、.h、defination.h、param_export.h、
'''
self.file_path = path
self.__generate_definations()
self.__generate_internal_definations()
self.__generate_infomatin()
self.__generate_export()
self.__generate_storage()
def gen_param_info(content):
items = {}
match = re.search(r"offset=offsetof\(.*\)", content)
if match != None:
group_list = match.group().split("=")
items[group_list[0]] = group_list[1].split(", ")[1].strip(')')
else:
items["offset"] = ""
content = content.replace(".offset=offsetof(", "")
for item in content.split(","):
match = re.search(r"\..*=.*", item)
if match != None:
key_value = match.group().strip("}").strip(".").split('=')
items[key_value[0]] = key_value[1]
return items
class ParamCategory(object):
'''
用于存储从代码文件中读出的信息
cat_name业务参数类型名称
base_addr参数存储的基地址
data_size参数数据存储的总大小暂未使用
param_num当前类型中参数的个数
backup_offset备份之间的偏移
param_name_list标识符列表
param_name_str_list参数名称列表汉字
default_value默认参数字典
index_table默认索引表
exchange_size:存储区域擦写单元
'''
def __init__(self, cat_name):
'''
初始化代码文件信息,仅传入参数类型名,构造空的参数信息体
'''
self.cat_name = cat_name.upper()
self.base_addr = ""
self.data_size = 0
self.param_num = 0
self.backup_offset = ""
self.param_name_list=[]
self.param_name_str_list=[]
self.default_value={}
self.index_table=[]
self.storage_name=''
self.exchange_size = ""
def __str__(self):
'''
将对象转换为可打印的字符串
'''
ret = ""
ret = ret + "cat_name:\t" + self.cat_name + "\n"
ret = ret + "storage_name:\t" + self.storage_name + "\n"
ret = ret + "base_addr:\t"+ self.base_addr + "\n"
ret = ret + "data_size:\t"+ str(self.data_size) + "\n"
ret = ret + "param_num:\t"+ str(self.param_num) + "\n"
ret = ret + "backup_offset:\t"+ self.backup_offset + "\n"
ret = ret + "param_name_list"+ str(self.param_name_list) + "\n"
ret = ret + "param_name_str_list"+ str(self.param_name_str_list) + "\n"
ret = ret + "default_value"+ str(self.default_value) + "\n"
ret = ret + "index_table"+ str(self.index_table) + "\n"
ret = ret + "exchange_size:\t"+ self.exchange_size + "\n"
return ret
class CodeGeneration(object):
'''
将代码文件还原为excel文件
'''
categary_pattern = r'param_[a-z]*\.c'
def __find_param_category(self, path):
'''
找到path目录下可被逆向解析的文件将可解析的文件构造成参数类型
'''
file_list = os.listdir(path)
cat_list = []
cat_temp_list = []
for file_item in os.listdir(path):
categary_pattern = r'param_[a-z]*\.c'
matches = re.search(categary_pattern, file_item)
if matches != None :
cat_temp_list.append(matches.group()[6:-2])
for cat_idx in cat_temp_list:
if "param_"+cat_idx+"_defination.h" in os.listdir(path) and "param_"+cat_idx+".h" in os.listdir(path):
cat_list.append(cat_idx)
return cat_list
def __build_local_info(self, path, cat_name):
'''
读取.h文件通过.h文件构建存储基地址
'''
with open("%s/param_%s.h"%(path,cat_name.lower()), 'r', encoding="utf-8") as f:
param_h = f.read()
state = 0
for line in param_h.split('\n'):
line.strip()
if line.find("_PARAM_STORE_ADDR") != -1:
self.categorys[cat_name].base_addr = line.split("(")[1].split(')')[0].strip()
def __build_extern_info(self, path, cat_name):
'''
读取_defination.h文件通过_defination.h文件构建各个参数的数据域大小
'''
with open("%s/param_%s_defination.h"%(path, cat_name.lower()), 'r', encoding="utf-8") as f:
param_h = f.read()
item_index = 0
state = 0
for line in param_h.split('\n'):
line.strip()
if line.find("_PARAM_NUM") != -1:
self.categorys[cat_name].param_num = int(line.split("(")[1].split(')')[0].strip())
categary_pattern = r'#define.*_SIZE.*\('
matches = re.search(categary_pattern, line)
if matches != None :
if self.categorys[cat_name].index_table[item_index]['size'] == line.split(' ')[1].split('(')[0].strip() :
if line.find("(sizeof(uint8_t))") != -1:
self.categorys[cat_name].index_table[item_index]['size'] = 1
elif line.find("(sizeof(int8_t))") != -1:
self.categorys[cat_name].index_table[item_index]['size'] = 1
elif line.find("(sizeof(uint16_t))") != -1:
self.categorys[cat_name].index_table[item_index]['size'] = 2
elif line.find("(sizeof(int16_t))") != -1:
self.categorys[cat_name].index_table[item_index]['size'] = 2
elif line.find("(sizeof(uint32_t))") != -1:
self.categorys[cat_name].index_table[item_index]['size'] = 4
elif line.find("(sizeof(int32_t))") != -1:
self.categorys[cat_name].index_table[item_index]['size'] = 4
elif line.find("(sizeof(uint64_t))") != -1:
self.categorys[cat_name].index_table[item_index]['size'] = 8
elif line.find("(sizeof(int64_t))") != -1:
self.categorys[cat_name].index_table[item_index]['size'] = 8
elif line.find("(sizeof(float))") != -1:
self.categorys[cat_name].index_table[item_index]['size'] = 4
elif line.find("(sizeof(double))") != -1:
self.categorys[cat_name].index_table[item_index]['size'] = 8
else:
self.categorys[cat_name].index_table[item_index]['size'] = int(line.split('(')[1].split(')')[0])
item_index = item_index + 1
def __build_list(self, path, cat_name):
'''
读取.c文件通过.c文件构建各个参数的数据域的名称、名字、各索引项、默认值等
'''
with open("%s/param_%s.c"%(path, cat_name.lower()), 'r', encoding="utf-8") as f:
param_h = f.read()
state = 0
for line in param_h.split('\n'):
line.strip()
if line.find(".backup_offset") != -1:
self.categorys[cat_name].backup_offset = int(line.split(",")[0].split('=')[1].strip())
if line.find(".exchange_size") != -1:
self.categorys[cat_name].exchange_size = int(line.split(",")[0].split('=')[1].strip())
if state == 1 :
if line.startswith("};") != True :
if line.startswith("{") != True:
if line.find("}") == -1:
self.categorys[cat_name].default_value[line.split('=')[0].strip().strip(".")] = line.split("=")[1].split(",")[0].strip()
self.categorys[cat_name].param_name_str_list.append(line.split(',')[1].strip().strip("/"))
else:
self.categorys[cat_name].default_value[line.split('=')[0].strip().strip(".")] = line.split("{")[1].split("}")[0]
self.categorys[cat_name].param_name_str_list.append(line.split('},')[1].strip().strip("/"))
self.categorys[cat_name].param_name_list.append(line.split('=')[0].strip().strip("."))
else:
state = 0
if state == 2 :
if line.startswith("};") != True :
if line.startswith("{") != True:
self.categorys[cat_name].index_table.append(gen_param_info(line))
else:
state = 0
if line.startswith("const") and line.find("PARAM_DEFAULT_VALUE_TABLE") != -1:
state = 1
if line.startswith("const") and line.find("PARAM_INDEX_TABLE") != -1:
state = 2
def __build_export(self, path):
with open("%s/param_defination.h"%(path), 'r', encoding="utf-8") as f:
param_h = f.read()
state = 0
for line in param_h.split('\n'):
line.strip()
if line.find("_REGION_NAME") != -1:
self.storage_name_list[line.split("_REGION_NAME")[0].strip().split(' ')[1].lower()] = line.split("_REGION_NAME")[1].strip().split(' ')[0]
if line.find("_PARAM,") != -1:
self.cat_list.append(line.strip().split(',')[0].split('_')[0].upper())
def __build_storage(self, path):
with open("%s/param_storage_config.c"%(path), 'r', encoding="utf-8") as f:
param_c = f.read()
state = 0
self.storage_type = param_c.split("};")[0].split("all_storage_info_table")[1].split("},")[0].split(".storage_read")[1].split(".storage_write")[0].strip('= ').split("_read")[0]
self.file_path_prefix = param_c.split("]=\"")[1].split("\";")[0]
def __init__(self, path):
'''
传入路径path解析路径下的代码文件找到能够解析成参数类型的三种文件param_*.h、param_*_defination.h、param_*.c
将找到的可被解析的文件构造成参数类型信息体并写入到excel文件中。
'''
cat_list = self.__find_param_category(path)
self.cat_list = []
self.storage_name_list = {}
self.categorys = {}
self.storage_type = {}
self.__build_export(path)
self.__build_storage(path)
for cat_name in cat_list:
self.categorys[cat_name] = ParamCategory(cat_name)
self.__build_list(path, cat_name)
self.__build_extern_info(path, cat_name)
self.__build_local_info(path, cat_name)
def gen_data_file(self):
'''
实际执行将读取到的参数信息写入到xlsx文件中文件名为"param_output.xlsx"
'''
wb = openpyxl.Workbook()
wb.remove(wb[wb.sheetnames[0]])
''' 单元格填充黄色 '''
fill = openpyxl.styles.PatternFill("solid", fgColor="FFFF00")
cell_name_list = ["序号", "唯一码DI、点号等", "参数名", "参数标识符", "参数存储类型", "参数数据大小(字节数)", "默认值", "对象解析类型", "缩放倍数", "参数最小值", "参数最大值", "参数标记", "参数有效性检查", "参数配置后回调", "注释"]
for sheet in codes.cat_list:
if sheet not in wb.sheetnames:
wb.create_sheet(sheet)
wb[sheet]["C1"].value = '存储区域基地址'
wb[sheet]["D1"].value = self.categorys[sheet.lower()].base_addr
wb[sheet]["C2"].value = '存储区域命名'
wb[sheet]["D2"].value = self.storage_name_list[sheet.lower()]
wb[sheet]["C3"].value = '存储区域擦写单元'
wb[sheet]["D3"].value = self.categorys[sheet.lower()].exchange_size
wb[sheet]["C4"].value = '存储区域单分区大小'
wb[sheet]["D4"].value = self.categorys[sheet.lower()].backup_offset
wb[sheet]["C5"].value = '参数个数'
wb[sheet]["D5"].value = self.categorys[sheet.lower()].param_num
wb[sheet]["C6"].value = '是否需要RAM参数对象'
wb[sheet]["D6"].value = 'true/false'
wb[sheet]["C7"].value = '存储器类型'
wb[sheet]["D7"].value = self.storage_type
wb[sheet]["C8"].value = '参数文件路径'
wb[sheet]["D8"].value = self.file_path_prefix
wb[sheet]["E8"].value = '注释:当存储器类型为fs时需要填写参数文件路径'
''' 单元格填充黄色 '''
wb[sheet]["C1"].fill = fill
wb[sheet]["C2"].fill = fill
wb[sheet]["C3"].fill = fill
wb[sheet]["C4"].fill = fill
wb[sheet]["C5"].fill = fill
wb[sheet]["C6"].fill = fill
wb[sheet]["C7"].fill = fill
wb[sheet]["C8"].fill = fill
for i in range(1, 16):
wb[sheet].cell(row = 11, column = i, value = cell_name_list[i-1])
wb[sheet].cell(row = 11, column = i).fill = fill
for i in range(0, int(self.categorys[sheet.lower()].param_num)):
wb[sheet].cell(row = 12+i, column = 1, value = i+1)
wb[sheet].cell(row = 12+i, column = 2, value = self.categorys[sheet.lower()].index_table[i]['identity'])
wb[sheet].cell(row = 12+i, column = 3, value = self.categorys[sheet.lower()].param_name_str_list[i])
wb[sheet].cell(row = 12+i, column = 4, value = self.categorys[sheet.lower()].param_name_list[i])
wb[sheet].cell(row = 12+i, column = 5, value = self.categorys[sheet.lower()].index_table[i]['store_type'])
wb[sheet].cell(row = 12+i, column = 6, value = self.categorys[sheet.lower()].index_table[i]['size'])
wb[sheet].cell(row = 12+i, column = 7, value = self.categorys[sheet.lower()].default_value[self.categorys[sheet.lower()].index_table[i]['offset']])
wb[sheet].cell(row = 12+i, column = 8, value = self.categorys[sheet.lower()].index_table[i]['local_type'])
wb[sheet].cell(row = 12+i, column = 9, value = self.categorys[sheet.lower()].index_table[i]['ratio'])
wb[sheet].cell(row = 12+i, column = 10, value = self.categorys[sheet.lower()].index_table[i]['min'])
wb[sheet].cell(row = 12+i, column = 11, value = self.categorys[sheet.lower()].index_table[i]['max'])
wb[sheet].cell(row = 12+i, column = 12, value = "0")
wb[sheet].cell(row = 12+i, column = 13, value = self.categorys[sheet.lower()].index_table[i]['check_func'])
wb[sheet].cell(row = 12+i, column = 14, value = self.categorys[sheet.lower()].index_table[i]['update_func'])
wb[sheet].cell(row = 12+i, column = 15, value = "")
wb.save("tools/param_output.xlsx")
if __name__ == '__main__':
try:
opts, args = getopt.getopt(sys.argv[1:],"hgr")
except getopt.GetoptError:
print('param_code_automation.py -h -g -r')
sys.exit(2)
for opt, arg in opts:
if opt == '-h':
print('param_code_automation.py -h -g -r')
print(' -h for help')
print(' -g for generate param code, need param_input.xlsx')
print(' -r for generate excel, output file name is param_output.xlsx\n')
sys.exit()
elif opt in ("-g"):
#执行以下代码从param_input.xlsx生成代码
storage_cofnig = StorageConfig()
storage_cofnig.generate_code_files("tools/param_code_generation/param/param_defination")
sys.exit()
elif opt in ("-r"):
##执行一下代码从讲代码目录逆向为param_output.xlsx
codes = CodeGeneration("param/param_defination")
codes.gen_data_file()
sys.exit()

405
sample/task.json Normal file
View File

@@ -0,0 +1,405 @@
interface TaskConfiguration extends BaseTaskConfiguration {
/**
* The configuration's version number
*/
version: '2.0.0';
/**
* Windows specific task configuration
*/
windows?: BaseTaskConfiguration;
/**
* macOS specific task configuration
*/
osx?: BaseTaskConfiguration;
/**
* Linux specific task configuration
*/
linux?: BaseTaskConfiguration;
}
interface BaseTaskConfiguration {
/**
* The type of a custom task. Tasks of type "shell" are executed
* inside a shell (e.g. bash, cmd, powershell, ...)
*/
type: 'shell' | 'process';
/**
* The command to be executed. Can be an external program or a shell
* command.
*/
command: string;
/**
* Specifies whether a global command is a background task.
*/
isBackground?: boolean;
/**
* The command options used when the command is executed. Can be omitted.
*/
options?: CommandOptions;
/**
* The arguments passed to the command. Can be omitted.
*/
args?: string[];
/**
* The presentation options.
*/
presentation?: PresentationOptions;
/**
* The problem matcher to be used if a global command is executed (e.g. no tasks
* are defined). A tasks.json file can either contain a global problemMatcher
* property or a tasks property but not both.
*/
problemMatcher?: string | ProblemMatcher | (string | ProblemMatcher)[];
/**
* The configuration of the available tasks. A tasks.json file can either
* contain a global problemMatcher property or a tasks property but not both.
*/
tasks?: TaskDescription[];
}
/**
* Options to be passed to the external program or shell
*/
export interface CommandOptions {
/**
* The current working directory of the executed program or shell.
* If omitted the current workspace's root is used.
*/
cwd?: string;
/**
* The environment of the executed program or shell. If omitted
* the parent process' environment is used.
*/
env?: { [key: string]: string };
/**
* Configuration of the shell when task type is `shell`
*/
shell: {
/**
* The shell to use.
*/
executable: string;
/**
* The arguments to be passed to the shell executable to run in command mode
* (e.g ['-c'] for bash or ['/S', '/C'] for cmd.exe).
*/
args?: string[];
};
}
/**
* The description of a task.
*/
interface TaskDescription {
/**
* The task's name
*/
label: string;
/**
* The type of a custom task. Tasks of type "shell" are executed
* inside a shell (e.g. bash, cmd, powershell, ...)
*/
type: 'shell' | 'process';
/**
* The command to execute. If the type is "shell" it should be the full
* command line including any additional arguments passed to the command.
*/
command: string;
/**
* Whether the executed command is kept alive and runs in the background.
*/
isBackground?: boolean;
/**
* Additional arguments passed to the command. Should be used if type
* is "process".
*/
args?: string[];
/**
* Defines the group to which this task belongs. Also supports to mark
* a task as the default task in a group.
*/
group?: 'build' | 'test' | { kind: 'build' | 'test'; isDefault: boolean };
/**
* The presentation options.
*/
presentation?: PresentationOptions;
/**
* The problem matcher(s) to use to capture problems in the tasks
* output.
*/
problemMatcher?: string | ProblemMatcher | (string | ProblemMatcher)[];
/**
* Defines when and how a task is run.
*/
runOptions?: RunOptions;
}
interface PresentationOptions {
/**
* Controls whether the task output is reveal in the user interface.
* Defaults to `always`.
*/
reveal?: 'never' | 'silent' | 'always';
/**
* Controls whether the command associated with the task is echoed
* in the user interface. Defaults to `true`.
*/
echo?: boolean;
/**
* Controls whether the panel showing the task output is taking focus.
* Defaults to `false`.
*/
focus?: boolean;
/**
* Controls if the task panel is used for this task only (dedicated),
* shared between tasks (shared) or if a new panel is created on
* every task execution (new). Defaults to `shared`.
*/
panel?: 'shared' | 'dedicated' | 'new';
/**
* Controls whether to show the `Terminal will be reused by tasks,
* press any key to close it` message.
*/
showReuseMessage?: boolean;
/**
* Controls whether the terminal is cleared before this task is run.
* Defaults to `false`.
*/
clear?: boolean;
/**
* Controls whether the task is executed in a specific terminal
* group using split panes. Tasks in the same group (specified by a string value)
* will use split terminals to present instead of a new terminal panel.
*/
group?: string;
}
/**
* A description of a problem matcher that detects problems
* in build output.
*/
interface ProblemMatcher {
/**
* The name of a base problem matcher to use. If specified the
* base problem matcher will be used as a template and properties
* specified here will replace properties of the base problem
* matcher
*/
base?: string;
/**
* The owner of the produced VS Code problem. This is typically
* the identifier of a VS Code language service if the problems are
* to be merged with the one produced by the language service
* or 'external'. Defaults to 'external' if omitted.
*/
owner?: string;
/**
* A human-readable string describing the source of this problem.
* E.g. 'typescript' or 'super lint'.
*/
source?: string;
/**
* The severity of the VS Code problem produced by this problem matcher.
*
* Valid values are:
* "error": to produce errors.
* "warning": to produce warnings.
* "info": to produce infos.
*
* The value is used if a pattern doesn't specify a severity match group.
* Defaults to "error" if omitted.
*/
severity?: string;
/**
* Defines how filename reported in a problem pattern
* should be read. Valid values are:
* - "absolute": the filename is always treated absolute.
* - "relative": the filename is always treated relative to
* the current working directory. This is the default.
* - ["relative", "path value"]: the filename is always
* treated relative to the given path value.
* - "autodetect": the filename is treated relative to
* the current workspace directory, and if the file
* does not exist, it is treated as absolute.
* - ["autodetect", "path value"]: the filename is treated
* relative to the given path value, and if it does not
* exist, it is treated as absolute.
* - "search": performs a deep (and, possibly, heavy) file system
* search within the directories.
* - ["search", {include: ["${workspaceFolder}"]}]: performs
* a deep search among the directories given in the "include" array.
* - ["search", {include: ["${workspaceFolder}"], exclude: []}]:
* performs a deep search among the directories given in the "include"
* array, excluding those named in the "exclude" array.
*/
fileLocation?: string | string[] | ['search', { include?: string[]; exclude?: string[] }];
/**
* The name of a predefined problem pattern, the inline definition
* of a problem pattern or an array of problem patterns to match
* problems spread over multiple lines.
*/
pattern?: string | ProblemPattern | ProblemPattern[];
/**
* Additional information used to detect when a background task (like a watching task in Gulp)
* is active.
*/
background?: BackgroundMatcher;
}
/**
* A description to track the start and end of a background task.
*/
interface BackgroundMatcher {
/**
* If set to true the watcher is in active mode when the task
* starts. This is equals of issuing a line that matches the
* beginPattern.
*/
activeOnStart?: boolean;
/**
* If matched in the output the start of a background task is signaled.
*/
beginsPattern?: string;
/**
* If matched in the output the end of a background task is signaled.
*/
endsPattern?: string;
}
interface ProblemPattern {
/**
* The regular expression to find a problem in the console output of an
* executed task.
*/
regexp: string;
/**
* Whether the pattern matches a problem for the whole file or for a location
* inside a file.
*
* Defaults to "location".
*/
kind?: 'file' | 'location';
/**
* The match group index of the filename.
*/
file: number;
/**
* The match group index of the problem's location. Valid location
* patterns are: (line), (line,column) and (startLine,startColumn,endLine,endColumn).
* If omitted the line and column properties are used.
*/
location?: number;
/**
* The match group index of the problem's line in the source file.
* Can only be omitted if location is specified.
*/
line?: number;
/**
* The match group index of the problem's column in the source file.
*/
column?: number;
/**
* The match group index of the problem's end line in the source file.
*
* Defaults to undefined. No end line is captured.
*/
endLine?: number;
/**
* The match group index of the problem's end column in the source file.
*
* Defaults to undefined. No end column is captured.
*/
endColumn?: number;
/**
* The match group index of the problem's severity.
*
* Defaults to undefined. In this case the problem matcher's severity
* is used.
*/
severity?: number;
/**
* The match group index of the problem's code.
*
* Defaults to undefined. No code is captured.
*/
code?: number;
/**
* The match group index of the message. Defaults to 0.
*/
message: number;
/**
* Specifies if the last pattern in a multi line problem matcher should
* loop as long as it does match a line consequently. Only valid on the
* last problem pattern in a multi line problem matcher.
*/
loop?: boolean;
}
/**
* A description to when and how run a task.
*/
interface RunOptions {
/**
* Controls how variables are evaluated when a task is executed through
* the Rerun Last Task command.
* The default is `true`, meaning that variables will be re-evaluated when
* a task is rerun. When set to `false`, the resolved variable values from
* the previous run of the task will be used.
*/
reevaluateOnRerun?: boolean;
/**
* Specifies when a task is run.
*
* Valid values are:
* "default": The task will only be run when executed through the Run Task command.
* "folderOpen": The task will be run when the containing folder is opened.
*/
runOn?: string;
}

21
source/CBB/Param.py Normal file
View File

@@ -0,0 +1,21 @@
# -*- coding: utf-8 -*-
'''
参数管理模块代码生成
此脚本提供参数管理模块代码生成相关类与功能函数。
'''
import numpy as np
from pandas import DataFrame
def code_cbb_param(sheet: DataFrame) -> str|None:
""" 参数页代码生成 """
pass
def code_cbb_params(sheets: dict[str, DataFrame]) -> str|None:
""" 完整参数模块配置代码生成 """
pass

View File

@@ -0,0 +1,44 @@
import numpy as np
from pandas import DataFrame
def code_param_arm(sheet: DataFrame) -> str|None:
""" 生成所需代码内容 """
result = ""
result += "#include <stdint.h>\n"
result += "#include <stdbool.h>\n"
result += "\n"
object_list = []
serises_variable = sheet['变量名'].dropna()
serises_name = sheet['协议结构名称'].dropna()
serises_name[serises_variable.index[-1]+1] = 'endline'
for index in range(serises_name.shape[0]-1):
meta_object = {}
meta_object['name'] = serises_name.iloc[index]
meta_object['range'] = (serises_name.index[index], serises_name.index[index+1]-1)
meta_object['member'] = sheet.loc[serises_name.index[index]: serises_name.index[index+1]-1]
code_object = f"typedef struct tag_{meta_object['name']}" + "\n"
code_object += "{" + "\n"
list_codes = []
for id, item in meta_object['member'].iterrows():
if item['变量名'] is np.nan:
continue
code_veriable = f" uint16_t "
code_veriable += f"a" if item['数据长度'] > 1 else ""
code_veriable += f"{item['变量名']}"
code_veriable += f"[{item['数据长度']}];" if item['数据长度'] > 1 else ";"
code_comment = f"/*{item['地址']} {item['数据项名称']}*/"
list_codes.append((index, code_veriable, code_comment))
code_len_max = max((len(line[1]) for line in list_codes)) + 2
code_len_max = code_len_max if code_len_max > 65 else 65
for id, line_prefix, line_suffix in list_codes:
code_object += line_prefix + " " * (code_len_max - len(line_prefix)) + line_suffix + "\n"
code_object += "}" + f"{meta_object['name']};" + "\n"
result += code_object + "\n"
return result

63
source/main.py Normal file
View File

@@ -0,0 +1,63 @@
import re
import argparse
import subprocess
import pandas as pd
from pathlib import Path
from PV_Inverter.CodeGenerator import code_param_arm
from CBB.Param import code_cbb_params
def save_file(content: str, path_file: Path):
if not path_file.parent.exists():
path_file.parent.mkdir(parents=True)
return path_file.write_text(content)
def main(args: argparse.Namespace) -> bool:
""" 核心执行函数 """
global type_list, dev_list
file_excel = Path(args.path)
code_folder = Path(args.output) if args.output else (file_excel.parent / "result")
# 读取Excel文件
if file_excel.exists():
if file_excel.suffix in ['.dec', '.xlsx']:
dataframes = pd.read_excel(file_excel, sheet_name=None)
elif file_excel.suffix == '.xls':
dataframes = pd.read_excel(file_excel, sheet_name=None, engine='xlrd')
else:
raise ValueError("File format Unsupported.")
else:
raise ValueError("File does not exist.")
if args.type == 'COMM_ARM':
# 光伏逆变器-ARM数据结构体生成
content_code = code_param_arm(dataframes['ARM地址表'])
elif args.type == 'CBB_Param':
content_code = code_cbb_params(dataframes)
save_file(content_code, code_folder / 'param_arm_struct.h')
if __name__ == "__main__":
type_list = ['COMM_DSP', 'COMM_ARM', 'CBB_Param']
dev_list = ['PV_INV30', 'PV_INV40', 'PV_INV50']
parser = argparse.ArgumentParser()
parser.add_argument("path")
parser.add_argument(
"-t", "--type",
choices=type_list,
help=f"Specify the Code Generate type [{', '.join(type_list)}]",
required=True
)
parser.add_argument(
"-d", "--device",
choices=dev_list,
help=f"Specify the device type [{', '.join(dev_list)}]",
required=True
)
parser.add_argument("-i", "--ignore")
parser.add_argument("-o", "--output")
args = parser.parse_args()
main(args)